Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

317 lines (275 sloc) 7.775 kB
/* -*- mode: c++; c-basic-offset: 4 -*- */
/*
_ttconv.c
Python wrapper for TrueType conversion library in ../ttconv.
*/
#include "mplutils.h"
#include <Python.h>
#include "ttconv/pprdrv.h"
#include <vector>
class PythonExceptionOccurred
{
};
/**
* An implementation of TTStreamWriter that writes to a Python
* file-like object.
*/
class PythonFileWriter : public TTStreamWriter
{
PyObject* _write_method;
public:
PythonFileWriter()
{
_write_method = NULL;
}
~PythonFileWriter()
{
Py_XDECREF(_write_method);
}
void set(PyObject* write_method)
{
Py_XDECREF(_write_method);
_write_method = write_method;
Py_XINCREF(_write_method);
}
virtual void write(const char* a)
{
PyObject* result = NULL;
if (_write_method)
{
#if PY3K
result = PyObject_CallFunction(_write_method, (char *)"y", a);
#else
result = PyObject_CallFunction(_write_method, (char *)"s", a);
#endif
if (! result)
{
throw PythonExceptionOccurred();
}
Py_DECREF(result);
}
}
};
int fileobject_to_PythonFileWriter(PyObject* object, void* address)
{
PythonFileWriter* file_writer = (PythonFileWriter*)address;
PyObject* write_method = PyObject_GetAttrString(object, "write");
if (write_method == NULL || ! PyCallable_Check(write_method))
{
PyErr_SetString(PyExc_TypeError, "Expected a file-like object with a write method.");
return 0;
}
file_writer->set(write_method);
Py_DECREF(write_method);
return 1;
}
int pyiterable_to_vector_int(PyObject* object, void* address)
{
std::vector<int>* result = (std::vector<int>*)address;
PyObject* iterator = PyObject_GetIter(object);
if (! iterator)
{
return 0;
}
PyObject* item;
while ((item = PyIter_Next(iterator)))
{
#if PY3K
long value = PyLong_AsLong(item);
#else
long value = PyInt_AsLong(item);
#endif
Py_DECREF(item);
if (value == -1 && PyErr_Occurred())
{
return 0;
}
result->push_back(value);
}
Py_DECREF(iterator);
return 1;
}
static PyObject*
convert_ttf_to_ps(PyObject* self, PyObject* args, PyObject* kwds)
{
const char* filename;
PythonFileWriter output;
int fonttype;
std::vector<int> glyph_ids;
static const char *kwlist[] =
{
"filename", "output", "fonttype", "glyph_ids", NULL
};
if (! PyArg_ParseTupleAndKeywords
(args, kwds,
"sO&i|O&:convert_ttf_to_ps",
(char**)kwlist,
&filename,
fileobject_to_PythonFileWriter,
&output,
&fonttype,
pyiterable_to_vector_int,
&glyph_ids))
{
return NULL;
}
if (fonttype != 3 && fonttype != 42)
{
PyErr_SetString(PyExc_ValueError,
"fonttype must be either 3 (raw Postscript) or 42 "
"(embedded Truetype)");
return NULL;
}
try
{
insert_ttfont(filename, output, (font_type_enum)fonttype, glyph_ids);
}
catch (TTException& e)
{
PyErr_SetString(PyExc_RuntimeError, e.getMessage());
return NULL;
}
catch (PythonExceptionOccurred&)
{
return NULL;
}
catch (...)
{
PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
class PythonDictionaryCallback : public TTDictionaryCallback
{
PyObject* _dict;
public:
PythonDictionaryCallback(PyObject* dict)
{
_dict = dict;
}
virtual void add_pair(const char* a, const char* b)
{
PyObject* value = PyBytes_FromString(b);
if (value)
{
if (PyDict_SetItemString(_dict, a, value))
{
Py_DECREF(value);
throw PythonExceptionOccurred();
}
}
Py_DECREF(value);
}
};
static PyObject*
py_get_pdf_charprocs(PyObject* self, PyObject* args, PyObject* kwds)
{
const char* filename;
std::vector<int> glyph_ids;
PyObject* result;
static const char *kwlist[] = { "filename", "glyph_ids", NULL };
if (! PyArg_ParseTupleAndKeywords
(args, kwds,
"s|O&:get_pdf_charprocs",
(char **)kwlist,
&filename,
pyiterable_to_vector_int,
&glyph_ids))
{
return NULL;
}
result = PyDict_New();
if (!result)
{
return NULL;
}
PythonDictionaryCallback dict(result);
try
{
::get_pdf_charprocs(filename, glyph_ids, dict);
}
catch (TTException& e)
{
Py_DECREF(result);
PyErr_SetString(PyExc_RuntimeError, e.getMessage());
return NULL;
}
catch (PythonExceptionOccurred&)
{
Py_DECREF(result);
return NULL;
}
catch (...)
{
Py_DECREF(result);
PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
return NULL;
}
return result;
}
static PyMethodDef ttconv_methods[] =
{
{
"convert_ttf_to_ps", (PyCFunction)convert_ttf_to_ps, METH_VARARGS | METH_KEYWORDS,
"convert_ttf_to_ps(filename, output, fonttype, glyph_ids)\n"
"\n"
"Converts the Truetype font into a Type 3 or Type 42 Postscript font, "
"optionally subsetting the font to only the desired set of characters.\n"
"\n"
"filename is the path to a TTF font file.\n"
"output is a Python file-like object with a write method that the Postscript "
"font data will be written to.\n"
"fonttype may be either 3 or 42. Type 3 is a \"raw Postscript\" font. "
"Type 42 is an embedded Truetype font. Glyph subsetting is not supported "
"for Type 42 fonts.\n"
"glyph_ids (optional) is a list of glyph ids (integers) to keep when "
"subsetting to a Type 3 font. If glyph_ids is not provided or is None, "
"then all glyphs will be included. If any of the glyphs specified are "
"composite glyphs, then the component glyphs will also be included."
},
{
"get_pdf_charprocs", (PyCFunction)py_get_pdf_charprocs, METH_VARARGS | METH_KEYWORDS,
"get_pdf_charprocs(filename, glyph_ids)\n"
"\n"
"Given a Truetype font file, returns a dictionary containing the PDF Type 3\n"
"representation of its paths. Useful for subsetting a Truetype font inside\n"
"of a PDF file.\n"
"\n"
"filename is the path to a TTF font file.\n"
"glyph_ids is a list of the numeric glyph ids to include.\n"
"The return value is a dictionary where the keys are glyph names and\n"
"the values are the stream content needed to render that glyph. This\n"
"is useful to generate the CharProcs dictionary in a PDF Type 3 font.\n"
},
{0, 0, 0, 0} /* Sentinel */
};
static const char* module_docstring =
"Module to handle converting and subsetting TrueType "
"fonts to Postscript Type 3, Postscript Type 42 and "
"Pdf Type 3 fonts.";
#if PY3K
static PyModuleDef ttconv_module = {
PyModuleDef_HEAD_INIT,
"ttconv",
module_docstring,
-1,
ttconv_methods,
NULL, NULL, NULL, NULL
};
PyMODINIT_FUNC
PyInit_ttconv(void)
{
PyObject* m;
m = PyModule_Create(&ttconv_module);
return m;
}
#else
PyMODINIT_FUNC
initttconv(void)
{
PyObject* m;
m = Py_InitModule3("ttconv", ttconv_methods, module_docstring);
}
#endif
Jump to Line
Something went wrong with that request. Please try again.