3 Python wrapper for gfx convert
5 Part of the swftools package.
7 Copyright (c) 2003 Matthias Kramm <kramm@quiss.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
26 #include "../devices/swf.h"
27 #include "../devices/render.h"
28 #include "../devices/rescale.h"
29 #include "../devices/text.h"
30 #include "../pdf/pdf.h"
34 gfxsource_t*pdfdriver;
36 staticforward PyTypeObject OutputClass;
37 staticforward PyTypeObject PageClass;
38 staticforward PyTypeObject DriverClass;
42 gfxdevice_t*output_device;
43 PyObject*pyobj; //only for passthrough
59 static char* strf(char*format, ...)
64 va_start(arglist, format);
65 vsprintf(buf, format, arglist);
69 #define PY_ERROR(s,args...) (PyErr_SetString(PyExc_Exception, strf(s, ## args)),NULL)
70 #define PY_NONE Py_BuildValue("s", 0)
72 //---------------------------------------------------------------------
73 staticforward PyObject* output_save(PyObject* _self, PyObject* args, PyObject* kwargs);
74 staticforward PyObject* output_startpage(PyObject* _self, PyObject* args, PyObject* kwargs);
75 staticforward PyObject* output_endpage(PyObject* _self, PyObject* args, PyObject* kwargs);
77 static PyMethodDef output_methods[] =
79 /* Output functions */
80 {"save", (PyCFunction)output_save, METH_KEYWORDS, ""},
81 {"startpage", (PyCFunction)output_startpage, METH_KEYWORDS, ""},
82 {"endpage", (PyCFunction)output_endpage, METH_KEYWORDS, ""},
85 static PyObject* output_save(PyObject* _self, PyObject* args, PyObject* kwargs)
87 OutputObject* self = (OutputObject*)_self;
89 static char *kwlist[] = {"filename", NULL};
90 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
93 gfxresult_t*result = self->output_device->finish(self->output_device);
94 self->output_device = 0;
95 if(result->save(result, filename) < 0) {
96 return PY_ERROR("Couldn't write to %s", filename);
98 result->destroy(result);
101 static PyObject* output_startpage(PyObject* _self, PyObject* args, PyObject* kwargs)
103 OutputObject* self = (OutputObject*)_self;
104 int width=0, height=0;
105 if (!PyArg_ParseTuple(args, "ii", &width, &height))
107 self->output_device->startpage(self->output_device, width, height);
110 static PyObject* output_endpage(PyObject* _self, PyObject* args, PyObject* kwargs)
112 OutputObject* self = (OutputObject*)_self;
113 if (!PyArg_ParseTuple(args, ""))
115 self->output_device->endpage(self->output_device);
118 static PyObject* f_createSWF(PyObject* parent, PyObject* args, PyObject* kwargs)
120 static char *kwlist[] = {NULL};
121 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
123 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
125 self->output_device = malloc(sizeof(gfxdevice_t));
126 gfxdevice_swf_init(self->output_device);
127 return (PyObject*)self;
129 static PyObject* f_createImageList(PyObject* parent, PyObject* args, PyObject* kwargs)
131 static char *kwlist[] = {NULL};
132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
134 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
136 self->output_device = malloc(sizeof(gfxdevice_t));
137 gfxdevice_render_init(self->output_device);
138 return (PyObject*)self;
140 static PyObject* f_createPlainText(PyObject* parent, PyObject* args, PyObject* kwargs)
142 static char *kwlist[] = {NULL};
143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
145 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
147 self->output_device = malloc(sizeof(gfxdevice_t));
148 gfxdevice_text_init(self->output_device);
149 return (PyObject*)self;
152 static PyObject*callback_python(char*function, gfxdevice_t*dev, const char*format, ...)
154 OutputObject*self = (OutputObject*)dev->internal;
156 if(!PyObject_HasAttrString(self->pyobj, function))
160 va_start(ap, format);
162 PyObject*tuple = PyTuple_New(strlen(format));
165 char p = format[pos];
167 char*s = va_arg(ap, char*);
168 PyTuple_SetItem(tuple, pos, PyString_FromString(s));
170 int i = va_arg(ap, int);
171 PyTuple_SetItem(tuple, pos, PyInt_FromLong(i));
173 void* ptr = va_arg(ap, void*);
174 gfxcolor_t*col = (gfxcolor_t*)ptr;
175 PyObject*colobj = PyTuple_New(4);
176 PyTuple_SetItem(colobj, 0, PyInt_FromLong(col->r));
177 PyTuple_SetItem(colobj, 1, PyInt_FromLong(col->g));
178 PyTuple_SetItem(colobj, 2, PyInt_FromLong(col->b));
179 PyTuple_SetItem(colobj, 3, PyInt_FromLong(col->a));
180 PyTuple_SetItem(tuple, pos, colobj);
182 void* ptr = va_arg(ap, void*);
183 gfxline_t*line = (gfxline_t*)ptr;
187 while(l) {l=l->next;len++;}
188 PyObject*list = PyList_New(len);
192 if(l->type == gfx_moveTo) {
193 point = PyTuple_New(3);
194 PyTuple_SetItem(point, 0, PyString_FromString("m"));
195 PyTuple_SetItem(point, 1, PyFloat_FromDouble(l->x));
196 PyTuple_SetItem(point, 2, PyFloat_FromDouble(l->y));
197 } else if(l->type == gfx_lineTo) {
198 point = PyTuple_New(3);
199 PyTuple_SetItem(point, 0, PyString_FromString("l"));
200 PyTuple_SetItem(point, 1, PyFloat_FromDouble(l->x));
201 PyTuple_SetItem(point, 2, PyFloat_FromDouble(l->y));
202 } else if(l->type == gfx_splineTo) {
203 point = PyTuple_New(5);
204 PyTuple_SetItem(point, 0, PyString_FromString("l"));
205 PyTuple_SetItem(point, 1, PyFloat_FromDouble(l->x));
206 PyTuple_SetItem(point, 2, PyFloat_FromDouble(l->y));
207 PyTuple_SetItem(point, 3, PyFloat_FromDouble(l->sy));
208 PyTuple_SetItem(point, 4, PyFloat_FromDouble(l->sy));
212 PyList_SetItem(list, i, point);
216 PyTuple_SetItem(tuple, pos, list);
218 PyTuple_SetItem(tuple, pos, PY_NONE);
223 PyObject*f = PyObject_GetAttrString(self->pyobj, function);
227 PyObject* result = PyObject_CallObject(f, tuple);
229 if(!result) // should we do some error handling here?
236 static int my_setparameter(gfxdevice_t*dev, const char*key, const char*value)
238 callback_python("setparameter", dev, "ss", key, value);
241 static void my_startpage(gfxdevice_t*dev, int width, int height)
243 callback_python("startpage", dev, "ii", width, height);
245 static void my_startclip(gfxdevice_t*dev, gfxline_t*line)
247 callback_python("startclip", dev, "l", line);
249 static void my_endclip(gfxdevice_t*dev)
251 callback_python("endclip", dev, "");
253 static void my_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit)
257 if(cap_style == gfx_capButt)
259 else if(cap_style == gfx_capRound)
261 else if(cap_style == gfx_capSquare)
263 if(joint_style == gfx_joinMiter)
265 else if(joint_style == gfx_joinRound)
267 else if(joint_style == gfx_joinBevel)
269 callback_python("stroke", dev, "licssi", line, width, color, cap, joint, miterLimit);
271 static void my_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
273 callback_python("fill", dev, "lc", line, color);
275 static void my_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*imgcoord2devcoord, gfxcxform_t*cxform)
277 callback_python("fillbitmap", dev, "lImx", line, img, imgcoord2devcoord, cxform);
279 static void my_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
281 callback_python("fillgradient", dev, "lgsm", line, gradient, type, matrix);
283 static void my_addfont(gfxdevice_t*dev, gfxfont_t*font)
285 callback_python("addfont", dev, "f", font);
287 static void my_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
289 callback_python("drawchar", dev, "ficm", font, glyph, color, matrix);
291 static void my_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
293 callback_python("drawlink", dev, "ls", line, action);
295 static void my_endpage(gfxdevice_t*dev)
297 callback_python("drawlink", dev, "");
299 static gfxresult_t* my_finish(gfxdevice_t*dev)
301 callback_python("finish", dev, "");
305 static PyObject* f_createPassThrough(PyObject* parent, PyObject* args, PyObject* kwargs)
307 static char *kwlist[] = {"device", NULL};
309 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &obj))
311 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
314 self->output_device = malloc(sizeof(gfxdevice_t));
315 memset(self->output_device, 0, sizeof(gfxdevice_t));
316 self->output_device->name = strdup("passthrough");
318 self->output_device->setparameter = my_setparameter;
319 self->output_device->startpage = my_startpage;
320 self->output_device->startclip = my_startclip;
321 self->output_device->addfont = my_addfont;
322 self->output_device->endclip = my_endclip;
323 self->output_device->stroke = my_stroke;
324 self->output_device->fill = my_fill;
325 self->output_device->fillbitmap = my_fillbitmap;
326 self->output_device->fillgradient = my_fillgradient;
327 self->output_device->drawchar = my_drawchar;
328 self->output_device->drawlink = my_drawlink;
329 self->output_device->endpage = my_endpage;
330 self->output_device->finish = my_finish;
331 self->output_device->internal = self;
333 return (PyObject*)self;
337 static void output_dealloc(PyObject* _self) {
338 OutputObject* self = (OutputObject*)_self;
340 if(self->output_device) {
341 gfxresult_t*result = self->output_device->finish(self->output_device);
343 result->destroy(result);result=0;
345 self->output_device = 0;
350 static PyObject* output_getattr(PyObject * _self, char* a)
352 OutputObject*self = (OutputObject*)_self;
354 /* if(!strcmp(a, "x1")) {
355 return PyInt_FromLong(self->output_device->x1);
356 } else if(!strcmp(a, "y1")) {
357 return PyInt_FromLong(self->output_device->y1);
358 } else if(!strcmp(a, "x2")) {
359 return PyInt_FromLong(self->output_device->x2);
360 } else if(!strcmp(a, "y2")) {
361 return PyInt_FromLong(self->output_device->y2);
364 return Py_FindMethod(output_methods, _self, a);
366 static int output_setattr(PyObject * _self, char* a, PyObject * o)
368 OutputObject*self = (OutputObject*)_self;
369 if(!PyString_Check(o))
371 char*value = PyString_AsString(o);
372 self->output_device->setparameter(self->output_device, a, value);
375 static int output_print(PyObject * _self, FILE *fi, int flags)
377 OutputObject*self = (OutputObject*)_self;
378 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
382 //---------------------------------------------------------------------
383 staticforward PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs);
384 staticforward PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs);
386 static PyMethodDef page_methods[] =
389 {"render", (PyCFunction)page_render, METH_KEYWORDS, ""},
390 {"asImage", (PyCFunction)page_asImage, METH_KEYWORDS, ""},
393 static PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs)
395 PageObject* self = (PageObject*)_self;
397 static char *kwlist[] = {"dev", "move", "clip", NULL};
398 OutputObject*output = 0;
401 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OO", kwlist, &OutputClass, &output,
407 int cx1=0,cy1=0,cx2=0,cy2=0;
410 if (!PyArg_ParseTuple(move, "ii", &x,&y))
414 if (!PyArg_ParseTuple(clip, "iiii", &cx1,&cy1,&cx2,&cy2))
418 if(x|y|cx1|cx2|cy1|cy2)
419 self->page->rendersection(self->page, output->output_device,x,y,cx1,cy1,cx2,cy2);
421 self->page->render(self->page, output->output_device);
425 static PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs)
427 PageObject* self = (PageObject*)_self;
429 static char *kwlist[] = {"width", "height", NULL};
430 int width=0,height=0;
431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &width, &height))
434 if(!width || !height) {
435 return PY_ERROR("invalid dimensions: %dx%d", width,height);
438 gfxdevice_t dev1,dev2;
439 gfxdevice_render_init(&dev1);
440 dev1.setparameter(&dev1, "antialise", "2");
441 gfxdevice_rescale_init(&dev2, &dev1, width, height);
442 dev2.startpage(&dev2, self->page->width, self->page->height);
443 self->page->render(self->page, &dev2);
445 gfxresult_t*result = dev2.finish(&dev2);
446 gfximage_t*img = (gfximage_t*)result->get(result,"page0");
447 int l = img->width*img->height;
448 unsigned char*data = malloc(img->width*img->height*3);
450 for(t=0,s=0;t<l;s+=3,t++) {
451 data[s+0] = img->data[t].r;
452 data[s+1] = img->data[t].g;
453 data[s+2] = img->data[t].b;
455 result->destroy(result);
456 return PyString_FromStringAndSize((char*)data,img->width*img->height*3);
459 static void page_dealloc(PyObject* _self) {
460 PageObject* self = (PageObject*)_self;
462 self->page->destroy(self->page);
466 Py_DECREF(self->parent);
472 static PyObject* page_getattr(PyObject * _self, char* a)
474 PageObject*self = (PageObject*)_self;
476 if(!strcmp(a, "size")) {
477 return Py_BuildValue("(ii)", self->page->width, self->page->height);
478 } if(!strcmp(a, "doc")) {
479 Py_INCREF(self->parent);
481 } if(!strcmp(a, "nr")) {
482 return PyInt_FromLong(self->nr);
483 } else if(!strcmp(a, "width")) {
484 return PyInt_FromLong(self->page->width);
485 } else if(!strcmp(a, "height")) {
486 return PyInt_FromLong(self->page->height);
488 return Py_FindMethod(page_methods, _self, a);
490 static int page_setattr(PyObject * self, char* a, PyObject * o) {
493 static int page_print(PyObject * _self, FILE *fi, int flags)
495 PageObject*self = (PageObject*)_self;
496 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
500 //---------------------------------------------------------------------
502 staticforward PyObject* doc_getPage(PyObject* parent, PyObject* args, PyObject* kwargs);
503 staticforward PyObject* doc_getInfo(PyObject* parent, PyObject* args, PyObject* kwargs);
504 staticforward PyObject* doc_setParameter(PyObject* parent, PyObject* args, PyObject* kwargs);
506 static PyMethodDef doc_methods[] =
509 {"getPage", (PyCFunction)doc_getPage, METH_KEYWORDS, ""},
510 {"getInfo", (PyCFunction)doc_getInfo, METH_KEYWORDS, ""},
511 {"setParameter", (PyCFunction)doc_setParameter, METH_KEYWORDS, ""},
515 static PyObject* doc_getPage(PyObject* _self, PyObject* args, PyObject* kwargs)
517 DocObject* self = (DocObject*)_self;
519 static char *kwlist[] = {"nr", NULL};
521 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &pagenr))
524 PageObject*page = PyObject_New(PageObject, &PageClass);
525 page->page = self->doc->getpage(self->doc, pagenr);
527 page->parent = _self;
528 Py_INCREF(page->parent);
531 return PY_ERROR("Couldn't extract page %d", pagenr);
533 return (PyObject*)page;
536 static PyObject* doc_getInfo(PyObject* _self, PyObject* args, PyObject* kwargs)
538 DocObject* self = (DocObject*)_self;
540 static char *kwlist[] = {"key", NULL};
542 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &key))
545 char*s = self->doc->getinfo(self->doc, key);
546 return PyString_FromString(s);
549 static PyObject* doc_setParameter(PyObject* _self, PyObject* args, PyObject* kwargs)
551 DocObject* self = (DocObject*)_self;
553 static char *kwlist[] = {"key", "value", NULL};
554 char*key = 0, *value=0;
555 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key,&value))
558 self->doc->set_parameter(self->doc, key, value);
562 static PyObject* f_open(PyObject* parent, PyObject* args, PyObject* kwargs)
564 static char *kwlist[] = {"type", "filename", NULL};
567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &type, &filename))
570 DocObject*self = PyObject_New(DocObject, &DriverClass);
572 if(!strcmp(type,"pdf"))
573 self->doc = pdfdriver->open(pdfdriver,filename);
575 return PY_ERROR("Unknown type %s", type);
579 return PY_ERROR("Couldn't open %s", filename);
581 self->filename = strdup(filename);
582 return (PyObject*)self;
584 static void doc_dealloc(PyObject* _self) {
585 DocObject* self = (DocObject*)_self;
587 self->doc->destroy(self->doc);
591 free(self->filename);self->filename=0;
595 static PyObject* doc_getattr(PyObject * _self, char* a)
597 DocObject*self = (DocObject*)_self;
598 if(!strcmp(a, "pages")) {
599 return PyInt_FromLong(self->doc->num_pages);
601 if(!strcmp(a, "filename")) {
602 return PyString_FromString(self->filename);
604 return Py_FindMethod(doc_methods, _self, a);
606 static int doc_setattr(PyObject * self, char* a, PyObject * o) {
609 static int doc_print(PyObject * _self, FILE *fi, int flags)
611 DocObject*self = (DocObject*)_self;
612 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
616 //---------------------------------------------------------------------
618 static PyTypeObject OutputClass =
620 PyObject_HEAD_INIT(NULL)
623 tp_basicsize: sizeof(OutputObject),
625 tp_dealloc: output_dealloc,
626 tp_print: output_print,
627 tp_getattr: output_getattr,
628 tp_setattr: output_setattr,
630 static PyTypeObject PageClass =
632 PyObject_HEAD_INIT(NULL)
635 tp_basicsize: sizeof(PageObject),
637 tp_dealloc: page_dealloc,
638 tp_print: page_print,
639 tp_getattr: page_getattr,
640 tp_setattr: page_setattr,
642 static PyTypeObject DriverClass =
644 PyObject_HEAD_INIT(NULL)
647 tp_basicsize: sizeof(DocObject),
649 tp_dealloc: doc_dealloc,
651 tp_getattr: doc_getattr,
652 tp_setattr: doc_setattr,
655 //=====================================================================
657 static PyObject* f_setoption(PyObject* self, PyObject* args, PyObject* kwargs)
659 static char *kwlist[] = {"key", "value", NULL};
661 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key, &value))
663 pdfdriver->set_parameter(pdfdriver,key,value);
667 static PyObject* f_verbose(PyObject* self, PyObject* args, PyObject* kwargs)
669 static char *kwlist[] = {"val", NULL};
671 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &val))
673 setConsoleLogging(val);
677 static PyObject* f_addfont(PyObject* self, PyObject* args, PyObject* kwargs)
679 static char *kwlist[] = {"filename", NULL};
681 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
683 pdfdriver->set_parameter(pdfdriver,"font", filename);
687 static PyObject* f_addfontdir(PyObject* self, PyObject* args, PyObject* kwargs)
689 static char *kwlist[] = {"filename", NULL};
691 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
693 pdfdriver->set_parameter(pdfdriver,"fontdir", filename);
697 static PyMethodDef pdf2swf_methods[] =
700 {"open", (PyCFunction)f_open, METH_KEYWORDS, ""},
701 {"addfont", (PyCFunction)f_addfont, METH_KEYWORDS, ""},
702 {"addfontdir", (PyCFunction)f_addfontdir, METH_KEYWORDS, ""},
703 {"setoption", (PyCFunction)f_setoption, METH_KEYWORDS, ""},
704 {"verbose", (PyCFunction)f_verbose, METH_KEYWORDS, ""},
707 {"SWF", (PyCFunction)f_createSWF, METH_KEYWORDS, ""},
708 {"ImageList", (PyCFunction)f_createImageList, METH_KEYWORDS, ""},
709 {"PlainText", (PyCFunction)f_createPlainText, METH_KEYWORDS, ""},
710 {"PassThrough", (PyCFunction)f_createPassThrough, METH_KEYWORDS, ""},
718 initLog(0,0,0,0,0,2);
719 OutputClass.ob_type = &PyType_Type;
720 PageClass.ob_type = &PyType_Type;
721 DriverClass.ob_type = &PyType_Type;
723 pdfdriver = gfxsource_pdf_create();
725 PyObject*module = Py_InitModule("gfx", pdf2swf_methods);