Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 246588f

Browse files
committed
Convert _ttconv.cpp to use raw Python/C API, rather than CXX.
svn path=/trunk/matplotlib/; revision=3662
1 parent e6c4277 commit 246588f

1 file changed

Lines changed: 156 additions & 133 deletions

File tree

src/_ttconv.cpp

Lines changed: 156 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,181 +1,204 @@
1-
#include "CXX/Extensions.hxx"
2-
#include "CXX/Objects.hxx"
3-
#include "ttconv/pprdrv.h"
4-
5-
class ttconv_module : public Py::ExtensionModule<ttconv_module>
6-
{
7-
public:
8-
ttconv_module()
9-
: Py::ExtensionModule<ttconv_module>( "ttconv" )
10-
{
11-
add_varargs_method("convert_ttf_to_ps",
12-
&ttconv_module::convert_ttf_to_ps,
13-
ttconv_module::convert_ttf_to_ps__doc__);
14-
add_varargs_method("get_pdf_charprocs",
15-
&ttconv_module::get_pdf_charprocs,
16-
ttconv_module::get_pdf_charprocs__doc__);
17-
18-
initialize( "The ttconv module" );
19-
}
20-
21-
Py::Object
22-
convert_ttf_to_ps(const Py::Tuple& args);
23-
static char convert_ttf_to_ps__doc__[];
1+
/*
2+
_ttconv.c
243
25-
Py::Object
26-
get_pdf_charprocs(const Py::Tuple& args);
27-
static char get_pdf_charprocs__doc__[];
28-
};
4+
Python wrapper for TrueType conversion library in ../ttconv.
5+
*/
296

30-
char ttconv_module::convert_ttf_to_ps__doc__[] =
31-
"convert_ttf_to_ps(filename, output, fonttype, glyph_ids)\n"
32-
"\n"
33-
"Converts the Truetype font into a Type 3 or Type 42 Postscript font, "
34-
"optionally subsetting the font to only the desired set of characters.\n"
35-
"\n"
36-
"filename is the path to a TTF font file.\n"
37-
"output is a Python file-like object with a write method that the Postscript "
38-
"font data will be written to.\n"
39-
"fonttype may be either 3 or 42. Type 3 is a \"raw Postscript\" font. "
40-
"Type 42 is an embedded Truetype font. Glyph subsetting is not supported "
41-
"for Type 42 fonts.\n"
42-
"glyph_ids (optional) is a list of glyph ids (integers) to keep when "
43-
"subsetting to a Type 3 font. If glyph_ids is not provided or is None, "
44-
"then all glyphs will be included. If any of the glyphs specified are "
45-
"composite glyphs, then the component glyphs will also be included."
46-
;
7+
#include <Python.h>
8+
#include "ttconv/pprdrv.h"
9+
#include <vector>
4710

4811
/**
4912
* An implementation of TTStreamWriter that writes to a Python
5013
* file-like object.
5114
*/
5215
class PythonFileWriter : public TTStreamWriter {
53-
Py::Callable _write_method;
16+
PyObject* _write_method;
5417

5518
public:
56-
PythonFileWriter(const Py::Object& file_like_object) {
57-
_write_method = file_like_object.getAttr( "write" );
19+
PythonFileWriter() {
20+
_write_method = NULL;
5821
}
5922

60-
virtual void write(const char* a) {
61-
Py::Tuple args(1);
62-
args[0] = Py::String(a);
63-
_write_method.apply(args);
23+
~PythonFileWriter() {
24+
if (_write_method)
25+
Py_DECREF(_write_method);
6426
}
65-
};
6627

67-
Py::Object
68-
ttconv_module::convert_ttf_to_ps(const Py::Tuple & args) {
69-
args.verify_length(3, 4);
28+
void set(PyObject* write_method) {
29+
if (_write_method)
30+
Py_DECREF(_write_method);
31+
_write_method = write_method;
32+
if (_write_method)
33+
Py_INCREF(_write_method);
34+
}
7035

71-
std::string fname = Py::String(args[0]).as_std_string();
36+
virtual void write(const char* a) {
37+
if (_write_method)
38+
PyObject_CallFunction(_write_method, "s", a);
39+
}
40+
};
7241

73-
PythonFileWriter python_file_writer(args[1]);
42+
int fileobject_to_PythonFileWriter(PyObject* object, void* address) {
43+
PythonFileWriter* file_writer = (PythonFileWriter*)address;
44+
PyObject* write_method = PyObject_GetAttrString(object, "write");
45+
if (write_method == NULL || ! PyCallable_Check(write_method)) {
46+
PyErr_SetString(PyExc_TypeError, "Expected a file-like object with a write method.");
47+
return 0;
48+
}
49+
file_writer->set(write_method);
50+
return 1;
51+
}
7452

75-
long font_type = (long)Py::Int(args[2]);
76-
if ( font_type != 3 && font_type != 42 ) {
77-
throw Py::ValueError("Font type must be either 3 (raw Postscript) or 42 (embedded Truetype)");
53+
int pyiterable_to_vector_int(PyObject* object, void* address) {
54+
std::vector<int>* result = (std::vector<int>*)address;
55+
PyObject* iterator = PyObject_GetIter(object);
56+
if (! iterator)
57+
return 0;
58+
PyObject* item;
59+
while (item = PyIter_Next(iterator)) {
60+
long value = PyInt_AsLong(item);
61+
if (value == -1 && PyErr_Occurred())
62+
return 0;
63+
result->push_back(value);
7864
}
65+
return 1;
66+
}
7967

80-
std::vector<int> glyph_ids;
81-
if ( args.size() == 4 ) {
82-
if ( args[3] != Py::None() ) {
83-
Py::SeqBase< Py::Int > py_glyph_ids = args[3];
84-
size_t num_glyphs = py_glyph_ids.size();
85-
// If there are no included glyphs, just return
86-
if (num_glyphs == 0) {
87-
return Py::Object();
88-
}
89-
glyph_ids.reserve(num_glyphs);
90-
for (size_t i = 0; i < num_glyphs; ++i) {
91-
glyph_ids.push_back( (long) py_glyph_ids.getItem(i) );
92-
}
93-
}
68+
static PyObject*
69+
convert_ttf_to_ps(PyObject* self, PyObject* args, PyObject* kwds) {
70+
const char* filename;
71+
PythonFileWriter output;
72+
int fonttype;
73+
std::vector<int> glyph_ids;
74+
75+
static char *kwlist[] = { "filename", "output", "fonttype", "glyph_ids", NULL };
76+
if (! PyArg_ParseTupleAndKeywords
77+
(args, kwds,
78+
"sO&i|O&:convert_ttf_to_ps", kwlist,
79+
&filename,
80+
fileobject_to_PythonFileWriter,
81+
&output,
82+
&fonttype,
83+
pyiterable_to_vector_int,
84+
&glyph_ids))
85+
return NULL;
86+
87+
if (fonttype != 3 && fonttype != 42) {
88+
PyErr_SetString(PyExc_ValueError,
89+
"fonttype must be either 3 (raw Postscript) or 42 "
90+
"(embedded Truetype)");
91+
return NULL;
9492
}
9593

9694
try {
97-
insert_ttfont( fname.c_str(), python_file_writer, (font_type_enum) font_type, glyph_ids );
95+
insert_ttfont( filename, output, (font_type_enum)fonttype, glyph_ids );
9896
} catch (TTException& e) {
99-
throw Py::RuntimeError(e.getMessage());
97+
PyErr_SetString(PyExc_RuntimeError, e.getMessage());
98+
return NULL;
99+
} catch (...) {
100+
PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
101+
return NULL;
100102
}
101103

102-
return Py::Object();
104+
Py_INCREF(Py_None);
105+
return Py_None;
103106
}
104107

105-
char ttconv_module::get_pdf_charprocs__doc__[] =
106-
"get_pdf_charprocs(filename, glyph_ids)\n"
107-
"\n"
108-
"Given a Truetype font file, returns a dictionary containing the PDF Type 3\n"
109-
"representation of its path. Useful for subsetting a Truetype font inside\n"
110-
"of a PDF file.\n"
111-
"\n"
112-
"filename is the path to a TTF font file.\n"
113-
"glyph_ids is a list of the numeric glyph ids to include.\n"
114-
"The return value is a dictionary where the keys are glyph names and \n"
115-
"the values are the stream content needed to render that glyph. This\n"
116-
"is useful to generate the CharProcs dictionary in a PDF Type 3 font.\n"
117-
;
118-
119-
/**
120-
* An implementation of TTStreamWriter that writes to a Python
121-
* file-like object.
122-
*/
123108
class PythonDictionaryCallback : public TTDictionaryCallback {
124-
Py::Dict _dict;
109+
PyObject* _dict;
125110

126111
public:
127-
PythonDictionaryCallback(const Py::Dict& dict) : _dict(dict) {
128-
112+
PythonDictionaryCallback(PyObject* dict) {
113+
_dict = dict;
129114
}
130115

131116
virtual void add_pair(const char* a, const char* b) {
132-
_dict.setItem(a, Py::String(b));
117+
PyObject* value = PyString_FromString(b);
118+
if (value)
119+
PyDict_SetItemString(_dict, a, value);
133120
}
134121
};
135122

136-
Py::Object
137-
ttconv_module::get_pdf_charprocs(const Py::Tuple & args) {
138-
args.verify_length(1, 2);
139-
140-
Py::Dict result;
141-
142-
std::string fname = Py::String(args[0]).as_std_string();
143-
144-
std::vector<int> glyph_ids;
145-
if ( args.size() == 2 ) {
146-
if ( args[1] != Py::None() ) {
147-
Py::SeqBase< Py::Int > py_glyph_ids = args[1];
148-
size_t num_glyphs = py_glyph_ids.size();
149-
// If there are no included glyphs, just return
150-
if (num_glyphs == 0) {
151-
return result;
152-
}
153-
glyph_ids.reserve(num_glyphs);
154-
for (size_t i = 0; i < num_glyphs; ++i) {
155-
glyph_ids.push_back( (long) py_glyph_ids.getItem(i) );
156-
}
157-
}
158-
}
123+
static PyObject*
124+
py_get_pdf_charprocs(PyObject* self, PyObject* args, PyObject* kwds) {
125+
const char* filename;
126+
std::vector<int> glyph_ids;
127+
PyObject* result;
128+
129+
static char *kwlist[] = { "filename", "glyph_ids", NULL };
130+
if (! PyArg_ParseTupleAndKeywords
131+
(args, kwds,
132+
"s|O&:convert_ttf_to_ps", kwlist,
133+
&filename,
134+
pyiterable_to_vector_int,
135+
&glyph_ids))
136+
return NULL;
159137

160-
PythonDictionaryCallback dictCallback(result);
138+
result = PyDict_New();
139+
if (!result)
140+
return NULL;
141+
142+
PythonDictionaryCallback dict(result);
161143

162144
try {
163-
::get_pdf_charprocs( fname.c_str(), glyph_ids, dictCallback );
145+
::get_pdf_charprocs( filename, glyph_ids, dict );
164146
} catch (TTException& e) {
165-
throw Py::RuntimeError(e.getMessage());
147+
PyErr_SetString(PyExc_RuntimeError, e.getMessage());
148+
return NULL;
149+
} catch (...) {
150+
PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
151+
return NULL;
166152
}
167153

168154
return result;
169155
}
170156

171-
#if defined(_MSC_VER)
172-
DL_EXPORT(void)
173-
#elif defined(__cplusplus)
174-
extern "C" void
175-
#else
176-
void
157+
static PyMethodDef ttconv_methods[] = {
158+
{"convert_ttf_to_ps", (PyCFunction)convert_ttf_to_ps, METH_KEYWORDS,
159+
"convert_ttf_to_ps(filename, output, fonttype, glyph_ids)\n"
160+
"\n"
161+
"Converts the Truetype font into a Type 3 or Type 42 Postscript font, "
162+
"optionally subsetting the font to only the desired set of characters.\n"
163+
"\n"
164+
"filename is the path to a TTF font file.\n"
165+
"output is a Python file-like object with a write method that the Postscript "
166+
"font data will be written to.\n"
167+
"fonttype may be either 3 or 42. Type 3 is a \"raw Postscript\" font. "
168+
"Type 42 is an embedded Truetype font. Glyph subsetting is not supported "
169+
"for Type 42 fonts.\n"
170+
"glyph_ids (optional) is a list of glyph ids (integers) to keep when "
171+
"subsetting to a Type 3 font. If glyph_ids is not provided or is None, "
172+
"then all glyphs will be included. If any of the glyphs specified are "
173+
"composite glyphs, then the component glyphs will also be included."
174+
},
175+
{"get_pdf_charprocs", (PyCFunction)py_get_pdf_charprocs, METH_KEYWORDS,
176+
"get_pdf_charprocs(filename, glyph_ids)\n"
177+
"\n"
178+
"Given a Truetype font file, returns a dictionary containing the PDF Type 3\n"
179+
"representation of its path. Useful for subsetting a Truetype font inside\n"
180+
"of a PDF file.\n"
181+
"\n"
182+
"filename is the path to a TTF font file.\n"
183+
"glyph_ids is a list of the numeric glyph ids to include.\n"
184+
"The return value is a dictionary where the keys are glyph names and \n"
185+
"the values are the stream content needed to render that glyph. This\n"
186+
"is useful to generate the CharProcs dictionary in a PDF Type 3 font.\n"
187+
},
188+
{NULL} /* Sentinel */
189+
};
190+
191+
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
192+
#define PyMODINIT_FUNC void
177193
#endif
178-
initttconv(void)
194+
PyMODINIT_FUNC
195+
initttconv(void)
179196
{
180-
static ttconv_module* ttconv = new ttconv_module;
197+
PyObject* m;
198+
199+
m = Py_InitModule3("ttconv", ttconv_methods,
200+
"Module to handle converting and subsetting TrueType "
201+
"fonts to Postscript Type 3, Postscript Type 42 and "
202+
"Pdf Type 3 fonts.");
181203
}
204+

0 commit comments

Comments
 (0)