diff --git a/CHANGELOG b/CHANGELOG index 0902e5e608b8..e2f39cebf738 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ New entries should be added at the top +2004-06-08 Rewrote ft2font using CXX as part of general memory leak + fixes - JDH + 2004-06-07 Fixed several problems with log ticks and scaling - JDH 2004-06-07 Fixed width/height issues for images - JDH @@ -16,7 +19,6 @@ New entries should be added at the top 2004-05-31 Added renderer markeredgewidth attribute of Line2D. - ADS - 2004-05-29 Fixed tick label clipping to work with navigation. 2004-05-28 Added renderer grouping commands to support groups in diff --git a/setupext.py b/setupext.py index db34f69f45ad..7e328974e530 100644 --- a/setupext.py +++ b/setupext.py @@ -94,7 +94,7 @@ def add_gd_flags(module): def add_ft2font_flags(module): 'Add the module flags to build extensions which use gd' - module.libraries.extend(['freetype', 'z']) + module.libraries.extend(['freetype', 'z' ]) add_base_flags(module) basedirs = module.include_dirs[:] # copy the list to avoid inf loop! @@ -114,7 +114,7 @@ def add_ft2font_flags(module): module.libraries.append('gw32c') # put this last for library link order - module.libraries.append('m') + module.libraries.extend(['stdc++', 'm']) @@ -245,10 +245,11 @@ def build_windowing(ext_modules, packages): def build_ft2font(ext_modules, packages): global BUILT_FT2FONT if BUILT_FT2FONT: return # only build it if you you haven't already - module = Extension('matplotlib.ft2font', - ['src/ft2font.c', - ], - ) + deps = ['src/ft2font.cpp'] + deps.extend(glob.glob('CXX/*.cxx')) + deps.extend(glob.glob('CXX/*.c')) + + module = Extension('matplotlib.ft2font', deps) add_ft2font_flags(module) ext_modules.append(module) BUILT_FT2FONT = True @@ -301,7 +302,7 @@ def build_agg(ext_modules, packages): global BUILT_AGG if BUILT_AGG: return # only build it if you you haven't already - deps = ['src/_backend_agg.cpp', 'src/ft2font.c'] + deps = ['src/_backend_agg.cpp', 'src/ft2font.cpp'] deps.extend(glob.glob('agg2/src/*.cpp')) deps.extend(glob.glob('CXX/*.cxx')) deps.extend(glob.glob('CXX/*.c')) diff --git a/src/_backend_agg.cpp b/src/_backend_agg.cpp index 704650cab04b..3709e11c3bb0 100644 --- a/src/_backend_agg.cpp +++ b/src/_backend_agg.cpp @@ -804,7 +804,7 @@ RendererAgg::draw_text(const Py::Tuple& args) { args.verify_length(4); - FT2FontObject *font = (FT2FontObject *)args[0].ptr(); + FT2Font *font = static_cast(args[0].ptr()); int x = Py::Int( args[1] ); int y = Py::Int( args[2] ); @@ -918,6 +918,7 @@ RendererAgg::write_rgba(const Py::Tuple& args) { Py::Object RendererAgg::write_png(const Py::Tuple& args) { + //small memory leak in this function - JDH 2004-06-08 if (debug) std::cout << "RendererAgg::write_png" << std::endl; diff --git a/src/_transforms.cpp b/src/_transforms.cpp index 52d68918b044..056813052bb1 100644 --- a/src/_transforms.cpp +++ b/src/_transforms.cpp @@ -8,6 +8,13 @@ #include "Numeric/arrayobject.h" #endif +#define DEBUG_MEM 0 + + +Value::~Value() { + //std::cout << "bye bye Value" << std::endl; +} + Py::Object Value::set(const Py::Tuple & args) { args.verify_length(1); @@ -46,7 +53,8 @@ LazyValue::number_add( const Py::Object &o ) { throw Py::TypeError("Can only add LazyValues with other LazyValues"); LazyValue* rhs = static_cast(o.ptr()); - return Py::Object(new BinOp(this, rhs, BinOp::ADD)); + + return Py::asObject(new BinOp(this, rhs, BinOp::ADD)); } Py::Object @@ -59,7 +67,7 @@ LazyValue::number_divide( const Py::Object &o ) { LazyValue* rhs = static_cast(o.ptr()); BinOp* op = new BinOp(this, rhs, BinOp::DIVIDE); //std::cout << "initing divide done" << std::endl; - return Py::Object(op); + return Py::asObject(op); } Py::Object @@ -70,7 +78,7 @@ LazyValue::number_multiply( const Py::Object &o ) { throw Py::TypeError("Can only multiply LazyValues with other LazyValues"); LazyValue* rhs = static_cast(o.ptr()); - return Py::Object(new BinOp(this, rhs, BinOp::MULTIPLY)); + return Py::asObject(new BinOp(this, rhs, BinOp::MULTIPLY)); } Py::Object @@ -81,9 +89,21 @@ LazyValue::number_subtract( const Py::Object &o ) { throw Py::TypeError("Can only subtract LazyValues with other LazyValues"); LazyValue* rhs = static_cast(o.ptr()); - return Py::Object(new BinOp(this, rhs, BinOp::SUBTRACT)); + return Py::asObject(new BinOp(this, rhs, BinOp::SUBTRACT)); } +BinOp::BinOp(LazyValue* lhs, LazyValue* rhs, int opcode) : + _lhs(lhs), _rhs(rhs), _opcode(opcode) { + Py_INCREF(lhs); + Py_INCREF(rhs); +} + +BinOp::~BinOp() { + Py_INCREF(_lhs); + Py_INCREF(_rhs); + if (DEBUG_MEM) std::cout << "bye bye BinOp" << std::endl; +} + Py::Object BinOp::get(const Py::Tuple & args) { args.verify_length(0); @@ -91,6 +111,31 @@ BinOp::get(const Py::Tuple & args) { return Py::Float( x ); } +Point::Point(LazyValue* x, LazyValue* y) : _x(x), _y(y) { + Py_INCREF(x); + Py_INCREF(y); +} + +Point::~Point() +{ + Py_DECREF(_x); + Py_DECREF(_y); + + if (DEBUG_MEM) std::cout << "bye bye Point" << std::endl; +} + +Interval::Interval(LazyValue* val1, LazyValue* val2) : + _val1(val1), _val2(val2) { + Py_INCREF(val1); + Py_INCREF(val2); +}; + +Interval::~Interval() { + Py_DECREF(_val1); + Py_DECREF(_val2); + + if (DEBUG_MEM) std::cout << "bye bye Interval" << std::endl; +} Py::Object Interval::update(const Py::Tuple &args) { @@ -125,6 +170,18 @@ Interval::update(const Py::Tuple &args) { return Py::Object(); } +Bbox::Bbox(Point* ll, Point* ur) : _ll(ll), _ur(ur) { + Py_INCREF(ll); + Py_INCREF(ur); +}; + + +Bbox::~Bbox() { + Py_DECREF(_ll); + Py_DECREF(_ur); + if (DEBUG_MEM) std::cout << "bye bye Bbox" << std::endl; +} + Py::Object Bbox::deepcopy(const Py::Tuple &args) { args.verify_length(0); @@ -135,8 +192,8 @@ Bbox::deepcopy(const Py::Tuple &args) { double maxx = _ur->xval(); double maxy = _ur->yval(); - return Py::Object( new Bbox( new Point(new Value(minx), new Value(miny) ), - new Point(new Value(maxx), new Value(maxy) ))); + return Py::asObject( new Bbox( new Point(new Value(minx), new Value(miny) ), + new Point(new Value(maxx), new Value(maxy) ))); } Py::Object @@ -306,6 +363,10 @@ Bbox::update(const Py::Tuple &args) { return Py::Object(); } +Func::~Func() { + if (DEBUG_MEM) std::cout << "bye bye Func" << std::endl; +} + Py::Object Func::map(const Py::Tuple &args) { @@ -328,6 +389,19 @@ Func::inverse(const Py::Tuple &args) { return Py::Float(xout); }; +FuncXY::FuncXY(Func* funcx, Func* funcy) : + _funcx(funcx), _funcy(funcy) { + Py_INCREF(funcx); + Py_INCREF(funcy); +} + +FuncXY::~FuncXY() { + Py_DECREF(_funcx); + Py_DECREF(_funcy); + + if (DEBUG_MEM) std::cout << "bye bye FuncXY" << std::endl; +} + Py::Object FuncXY::map(const Py::Tuple &args) { @@ -375,6 +449,7 @@ FuncXY::set_funcx(const Py::Tuple & args) { throw Py::TypeError("set_funcx(func) expected a Func instance"); _funcx = static_cast(args[0].ptr()); + Py_INCREF(_funcx); return Py::Object(); } @@ -386,6 +461,7 @@ FuncXY::set_funcy(const Py::Tuple & args) { throw Py::TypeError("set_funcy(func) expected a Func instance"); _funcy = static_cast(args[0].ptr()); + Py_INCREF(_funcy); return Py::Object(); } @@ -401,6 +477,14 @@ FuncXY::get_funcy(const Py::Tuple & args) { return Py::Object(_funcy); } +PolarXY::~PolarXY() { + if (DEBUG_MEM) std::cout << "bye bye PolarXY" << std::endl; +} + +Transformation::~Transformation() { + if (DEBUG_MEM) std::cout << "bye bye Transformation" << std::endl; +} + Py::Object Transformation::as_vec6(const Py::Tuple & args) { throw Py::RuntimeError("This transformation does not support as_vec6"); @@ -473,6 +557,7 @@ Transformation::set_offset(const Py::Tuple & args) { _xo = Py::Float(xy[0]); _yo = Py::Float(xy[1]); _transOffset = static_cast(args[1].ptr()); + Py_INCREF(_transOffset); return Py::Object(); } @@ -635,6 +720,24 @@ Transformation::seq_xy_tups(const Py::Tuple & args) { } +SeparableTransformation::SeparableTransformation(Bbox *b1, Bbox *b2, Func *funcx, Func *funcy) : + Transformation(), + _b1(b1), _b2(b2), _funcx(funcx), _funcy(funcy) { + Py_INCREF(b1); + Py_INCREF(b2); + Py_INCREF(funcx); + Py_INCREF(funcy); + +} + + +SeparableTransformation::~SeparableTransformation() { + Py_DECREF(_b1); + Py_DECREF(_b2); + Py_DECREF(_funcx); + Py_DECREF(_funcy); + if (DEBUG_MEM) std::cout << "bye bye SeparableTransformation" << std::endl; +} Py::Object SeparableTransformation::get_funcx(const Py::Tuple & args) { @@ -655,7 +758,7 @@ SeparableTransformation::set_funcx(const Py::Tuple & args) { if (!Func::check(args[0])) throw Py::TypeError("set_funcx(func) expected a func instance"); _funcx = static_cast(args[0].ptr()); - + Py_INCREF(_funcx); return Py::Object(); } @@ -665,7 +768,7 @@ SeparableTransformation::set_funcy(const Py::Tuple & args) { if (!Func::check(args[0])) throw Py::TypeError("set_funcy(func) expected a func instance"); _funcy = static_cast(args[0].ptr()); - + Py_INCREF(_funcy); return Py::Object(); } @@ -690,7 +793,7 @@ SeparableTransformation::set_bbox1(const Py::Tuple & args) { if (!Bbox::check(args[0])) throw Py::TypeError("set_bbox1(func) expected a func instance"); _b1 = static_cast(args[0].ptr()); - + Py_INCREF(_b1); return Py::Object(); } @@ -700,7 +803,7 @@ SeparableTransformation::set_bbox2(const Py::Tuple & args) { if (!Bbox::check(args[0])) throw Py::TypeError("set_bbox2(func) expected a func instance"); _b2 = static_cast(args[0].ptr()); - + Py_INCREF(_b2); return Py::Object(); } @@ -804,6 +907,28 @@ SeparableTransformation::eval_scalars(void) { } } +Affine::Affine(LazyValue *a, LazyValue *b, LazyValue *c, + LazyValue *d, LazyValue *tx, LazyValue *ty) : + _a(a), _b(b), _c(c), _d(d), _tx(tx), _ty(ty) { + Py_INCREF(a); + Py_INCREF(b); + Py_INCREF(c); + Py_INCREF(d); + Py_INCREF(tx); + Py_INCREF(ty); + +} + +Affine::~Affine() { + Py_DECREF(_a); + Py_DECREF(_b); + Py_DECREF(_c); + Py_DECREF(_d); + Py_DECREF(_tx); + Py_DECREF(_ty); + if (DEBUG_MEM) std::cout << "bye bye Affine" << std::endl; +} + Py::Object Affine::as_vec6(const Py::Tuple &args) { @@ -889,14 +1014,14 @@ Affine::eval_scalars(void) { } } - + /* ------------ module methods ------------- */ Py::Object _transforms_module::new_value (const Py::Tuple &args) { args.verify_length(1); double val = Py::Float(args[0]); - return Py::Object( new Value(val) ); + return Py::asObject( new Value(val) ); } @@ -919,7 +1044,8 @@ Py::Object _transforms_module::new_point (const Py::Tuple &args) y = static_cast(args[1].ptr()); else throw Py::TypeError("Can only create points from LazyValues"); - return Py::Object(new Point(x, y)); + + return Py::asObject(new Point(x, y)); } @@ -937,7 +1063,7 @@ Py::Object _transforms_module::new_interval (const Py::Tuple &args) LazyValue* v1 = static_cast(args[0].ptr()); LazyValue* v2 = static_cast(args[1].ptr()); - return Py::Object(new Interval(v1, v2) ); + return Py::asObject(new Interval(v1, v2) ); } Py::Object _transforms_module::new_bbox (const Py::Tuple &args) @@ -952,7 +1078,7 @@ Py::Object _transforms_module::new_bbox (const Py::Tuple &args) Point* ll = static_cast(args[0].ptr()); Point* ur = static_cast(args[1].ptr()); - return Py::Object(new Bbox(ll, ur) ); + return Py::asObject(new Bbox(ll, ur) ); } Py::Object _transforms_module::new_affine (const Py::Tuple &args) { @@ -972,7 +1098,7 @@ Py::Object _transforms_module::new_affine (const Py::Tuple &args) { LazyValue* d = static_cast(args[3].ptr()); LazyValue* tx = static_cast(args[4].ptr()); LazyValue* ty = static_cast(args[5].ptr()); - return Py::Object(new Affine(a, b, c, d, tx, ty)); + return Py::asObject(new Affine(a, b, c, d, tx, ty)); } @@ -982,7 +1108,7 @@ Py::Object _transforms_module::new_func (const Py::Tuple &args) { args.verify_length(1); int typecode = Py::Int(args[0]); - return Py::Object(new Func(typecode)); + return Py::asObject(new Func(typecode)); } Py::Object _transforms_module::new_funcxy (const Py::Tuple &args) @@ -995,14 +1121,14 @@ Py::Object _transforms_module::new_funcxy (const Py::Tuple &args) Func* funcx = static_cast(args[0].ptr()); Func* funcy = static_cast(args[1].ptr()); - return Py::Object(new FuncXY(funcx, funcy)); + return Py::asObject(new FuncXY(funcx, funcy)); } Py::Object _transforms_module::new_polarxy (const Py::Tuple &args) { args.verify_length(0); - return Py::Object( new PolarXY() ); + return Py::asObject( new PolarXY() ); } Py::Object _transforms_module::new_separable_transformation (const Py::Tuple &args) @@ -1023,8 +1149,8 @@ Py::Object _transforms_module::new_separable_transformation (const Py::Tuple &ar Func* funcx = static_cast(args[2].ptr()); Func* funcy = static_cast(args[3].ptr()); - return Py::Object( new SeparableTransformation(box1, box2, funcx, funcy) ); -} + return Py::asObject( new SeparableTransformation(box1, box2, funcx, funcy) ); +} void LazyValue::init_type() { @@ -1054,9 +1180,10 @@ void Point::init_type() { behaviors().name("Point"); behaviors().doc("A point x, y"); - + add_varargs_method("x", &Point::x, "x()\n"); add_varargs_method("y", &Point::y, "y()\n"); + add_varargs_method("reference_count", &Point::reference_count); } void Interval::init_type() @@ -1190,9 +1317,7 @@ extern "C" DL_EXPORT(void) init_transforms(void) { - //suppress unused warning by creating in two lines - static _transforms_module* _transforms = NULL; - _transforms = new _transforms_module; + static _transforms_module* _transforms = new _transforms_module; import_array(); diff --git a/src/_transforms.h b/src/_transforms.h index e59c7261fc3f..c16f4e3a8a1e 100644 --- a/src/_transforms.h +++ b/src/_transforms.h @@ -53,8 +53,7 @@ class LazyValue : public Py::PythonExtension { class Value: public LazyValue { public: Value(double val) : _val(val) {} - - + ~Value(); static void init_type(void); Py::Object set(const Py::Tuple &args); Py::Object get(const Py::Tuple &args); @@ -73,10 +72,8 @@ class Value: public LazyValue { // binary operations on lazy values class BinOp: public LazyValue { public: - BinOp(LazyValue* lhs, LazyValue* rhs, int opcode) : - _lhs(lhs), _rhs(rhs), _opcode(opcode) { - //std::cout << "called binop init " << lhs->val() << " " << rhs->val() << std::endl; - } + BinOp(LazyValue* lhs, LazyValue* rhs, int opcode); + ~BinOp(); static void init_type(void); Py::Object get(const Py::Tuple &args); @@ -111,8 +108,8 @@ class BinOp: public LazyValue { class Point: public Py::PythonExtension { public: - Point(LazyValue* x, LazyValue* y) : _x(x), _y(y) {} - ~Point() { } + Point(LazyValue* x, LazyValue* y); + ~Point(); static void init_type(void); // get the x Value instance @@ -128,6 +125,11 @@ class Point: public Py::PythonExtension { double xval() {return _x->val();} double yval() {return _y->val();} + Py::Object reference_count (const Py::Tuple& args) + { + return Py::Int(this->ob_refcnt); + } + private: LazyValue *_x; LazyValue *_y; @@ -137,10 +139,11 @@ class Point: public Py::PythonExtension { class Interval: public Py::PythonExtension { public: - Interval(LazyValue* val1, LazyValue* val2) : _val1(val1), _val2(val2) {}; - - static void init_type(void); + Interval(LazyValue* val1, LazyValue* val2); + ~Interval(); + static void init_type(void); + Py::Object contains( const Py::Tuple &args) { args.verify_length(1); double x = Py::Float(args[0]); @@ -227,9 +230,11 @@ class Interval: public Py::PythonExtension { class Bbox: public Py::PythonExtension { public: - Bbox(Point* ll, Point* ur) : _ll(ll), _ur(ur) {}; + Bbox(Point* ll, Point* ur); + ~Bbox(); static void init_type(void); + // return lower left point Py::Object ll(const Py::Tuple &args) { return Py::Object(_ll); } @@ -242,11 +247,11 @@ class Bbox: public Py::PythonExtension { Py::Object get_bounds(const Py::Tuple &args); Py::Object intervalx(const Py::Tuple &args) { - return Py::Object( new Interval( _ll->x_api(), _ur->x_api())); + return Py::asObject( new Interval( _ll->x_api(), _ur->x_api())); } Py::Object intervaly(const Py::Tuple &args) { - return Py::Object( new Interval( _ll->y_api(), _ur->y_api())); + return Py::asObject( new Interval( _ll->y_api(), _ur->y_api())); } @@ -292,7 +297,6 @@ class Bbox: public Py::PythonExtension { Py::Object overlapsy(const Py::Tuple &args); - ~Bbox() {} Point* ll_api() {return _ll;} Point* ur_api() {return _ur;} @@ -309,6 +313,8 @@ class Bbox: public Py::PythonExtension { class Func : public Py::PythonExtension { public: Func( unsigned int type=IDENTITY ) : _type(type) {}; + ~Func(); + static void init_type(void); Py::Object str() { return Py::String(as_string());} @@ -360,7 +366,9 @@ class Func : public Py::PythonExtension { class FuncXY : public Py::PythonExtension { public: - FuncXY(Func* funcx=NULL, Func* funcy=NULL) : _funcx(funcx), _funcy(funcy){} + FuncXY(Func* funcx=NULL, Func* funcy=NULL); + ~FuncXY(); + static void init_type(void); Py::Object map(const Py::Tuple &args); @@ -392,6 +400,8 @@ class FuncXY : public Py::PythonExtension { class PolarXY : public FuncXY { public: + ~PolarXY(); + static void init_type(void); // the api forward and inverse functions; theta in radians @@ -426,6 +436,8 @@ class Transformation: public Py::PythonExtension { Transformation() : _usingOffset(0), _transOffset(NULL), _xo(0), _yo(0), _invertible(true), _frozen(false) {} + ~Transformation(); + static void init_type(void); // for separable transforms @@ -487,9 +499,8 @@ class Transformation: public Py::PythonExtension { class SeparableTransformation: public Transformation { public: - SeparableTransformation(Bbox *b1, Bbox *b2, Func *funcx, Func *funcy) : - Transformation(), - _b1(b1), _b2(b2), _funcx(funcx), _funcy(funcy) {} + SeparableTransformation(Bbox *b1, Bbox *b2, Func *funcx, Func *funcy); + ~SeparableTransformation(); static void init_type(void); @@ -523,8 +534,9 @@ class SeparableTransformation: public Transformation { class Affine: public Transformation { public: Affine(LazyValue *a, LazyValue *b, LazyValue *c, - LazyValue *d, LazyValue *tx, LazyValue *ty) : - _a(a), _b(b), _c(c), _d(d), _tx(tx), _ty(ty) {} + LazyValue *d, LazyValue *tx, LazyValue *ty); + + ~Affine(); static void init_type(void); diff --git a/src/ft2font.h b/src/ft2font.h index d79faaeacdd8..986dbcdb5e93 100644 --- a/src/ft2font.h +++ b/src/ft2font.h @@ -1,48 +1,127 @@ /* A python interface to freetype2 */ #ifndef _FT2FONT_H #define _FT2FONT_H -#define MAXGLYPHS 1000 +#include +#include +#include +#include +#include -#include "Python.h" +extern "C" { #include #include FT_FREETYPE_H #include FT_GLYPH_H #include FT_SFNT_NAMES_H +} +#include "CXX/Extensions.hxx" + // the freetype string renderered into a width, height buffer -typedef struct { +class FT2Image { +public: + FT2Image(); + ~FT2Image(); unsigned char *buffer; unsigned long width; unsigned long height; int offsetx, offsety; -} FT2_Image; +}; -typedef struct { - PyObject_HEAD - PyObject *x_attr; /* Attributes dictionary */ - int glyph_num; -} GlyphObject; +class Glyph : public Py::PythonExtension { +public: + Glyph( FT_Face, FT_Glyph, unsigned int); + ~Glyph(); + int setattr( const char *_name, const Py::Object &value ); + Py::Object getattr( const char *_name ); + static void init_type(void); + int num; +private: + Py::Dict __dict__; +}; -typedef struct { - PyObject_HEAD - PyObject *x_attr; /* Attributes dictionary */ - FT_Face face; +class FT2Font : public Py::PythonExtension { +public: + FT2Font(std::string); + ~FT2Font(); + static void init_type(void); + Py::Object set_bitmap_size(const Py::Tuple & args); + Py::Object clear(const Py::Tuple & args); + Py::Object set_size(const Py::Tuple & args); + Py::Object set_text(const Py::Tuple & args); + Py::Object get_glyph(const Py::Tuple & args); + Py::Object get_num_glyphs(const Py::Tuple & args); + Py::Object load_char(const Py::Tuple & args); + Py::Object get_width_height(const Py::Tuple & args); + Py::Object write_bitmap(const Py::Tuple & args); + Py::Object draw_rect(const Py::Tuple & args); + Py::Object image_as_str(const Py::Tuple & args); + Py::Object draw_glyphs_to_bitmap(const Py::Tuple & args); + Py::Object draw_glyph_to_bitmap(const Py::Tuple & args); + Py::Object get_sfnt_name(const Py::Tuple & args); + int setattr( const char *_name, const Py::Object &value ); + Py::Object getattr( const char *_name ); + FT2Image image; + +private: + Py::Dict __dict__; + FT_Face face; FT_Matrix matrix; /* transformation matrix */ FT_Vector pen; /* untransformed origin */ FT_Error error; - FT_Glyph glyphs[MAXGLYPHS]; - FT_Vector pos [MAXGLYPHS]; - - GlyphObject *gms[MAXGLYPHS]; - char *text; + std::vector glyphs; + std::vector pos; + std::vector gms; + std::string text; double angle; - int num_chars; - int num_glyphs; - FT2_Image image; -} FT2FontObject; + + + FT_BBox compute_string_bbox(); + void load_glyphs(); + void draw_bitmap( FT_Bitmap* bitmap, FT_Int x, FT_Int y); + + static char set_bitmap_size__doc__ []; + static char clear__doc__ []; + static char set_size__doc__ []; + static char set_text__doc__ []; + static char get_glyph__doc__ []; + static char get_num_glyphs__doc__ []; + static char load_char__doc__ []; + static char get_width_height__doc__ []; + static char write_bitmap__doc__ []; + static char draw_rect__doc__ []; + static char image_as_str__doc__ []; + static char draw_glyphs_to_bitmap__doc__ []; + static char draw_glyph_to_bitmap__doc__ []; + static char get_sfnt_name__doc__ []; + +}; + +// the extension module +class ft2font_module : public Py::ExtensionModule + +{ +public: + ft2font_module() + : Py::ExtensionModule( "ft2font" ) + { + Glyph::init_type(); + FT2Font::init_type(); + + add_varargs_method("FT2Font", &ft2font_module::new_ft2font, + "FT2Font"); + initialize( "The ft2font module" ); + } + + ~ft2font_module(); + //static FT_Library ft2Library; + +private: + + Py::Object new_ft2font (const Py::Tuple &args); +};