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("s"));
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->sx));
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);
239 static int my_setparameter(gfxdevice_t*dev, const char*key, const char*value)
241 callback_python("setparameter", dev, "ss", key, value);
244 static void my_startpage(gfxdevice_t*dev, int width, int height)
246 callback_python("startpage", dev, "ii", width, height);
248 static void my_startclip(gfxdevice_t*dev, gfxline_t*line)
250 callback_python("startclip", dev, "l", line);
252 static void my_endclip(gfxdevice_t*dev)
254 callback_python("endclip", dev, "");
256 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)
260 if(cap_style == gfx_capButt)
262 else if(cap_style == gfx_capRound)
264 else if(cap_style == gfx_capSquare)
266 if(joint_style == gfx_joinMiter)
268 else if(joint_style == gfx_joinRound)
270 else if(joint_style == gfx_joinBevel)
272 callback_python("stroke", dev, "licssi", line, width, color, cap, joint, miterLimit);
274 static void my_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
276 callback_python("fill", dev, "lc", line, color);
278 static void my_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*imgcoord2devcoord, gfxcxform_t*cxform)
280 callback_python("fillbitmap", dev, "lImx", line, img, imgcoord2devcoord, cxform);
282 static void my_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
284 callback_python("fillgradient", dev, "lgsm", line, gradient, type, matrix);
286 static void my_addfont(gfxdevice_t*dev, gfxfont_t*font)
288 callback_python("addfont", dev, "f", font);
290 static void my_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
292 callback_python("drawchar", dev, "ficm", font, glyph, color, matrix);
294 static void my_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
296 callback_python("drawlink", dev, "ls", line, action);
298 static void my_endpage(gfxdevice_t*dev)
300 callback_python("drawlink", dev, "");
302 static gfxresult_t* my_finish(gfxdevice_t*dev)
304 callback_python("finish", dev, "");
308 static PyObject* f_createPassThrough(PyObject* parent, PyObject* args, PyObject* kwargs)
310 static char *kwlist[] = {"device", NULL};
312 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &obj))
314 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
317 self->output_device = malloc(sizeof(gfxdevice_t));
318 memset(self->output_device, 0, sizeof(gfxdevice_t));
319 self->output_device->name = strdup("passthrough");
321 self->output_device->setparameter = my_setparameter;
322 self->output_device->startpage = my_startpage;
323 self->output_device->startclip = my_startclip;
324 self->output_device->addfont = my_addfont;
325 self->output_device->endclip = my_endclip;
326 self->output_device->stroke = my_stroke;
327 self->output_device->fill = my_fill;
328 self->output_device->fillbitmap = my_fillbitmap;
329 self->output_device->fillgradient = my_fillgradient;
330 self->output_device->drawchar = my_drawchar;
331 self->output_device->drawlink = my_drawlink;
332 self->output_device->endpage = my_endpage;
333 self->output_device->finish = my_finish;
334 self->output_device->internal = self;
336 return (PyObject*)self;
340 static void output_dealloc(PyObject* _self) {
341 OutputObject* self = (OutputObject*)_self;
343 if(self->output_device) {
344 gfxresult_t*result = self->output_device->finish(self->output_device);
346 result->destroy(result);result=0;
348 self->output_device = 0;
353 static PyObject* output_getattr(PyObject * _self, char* a)
355 OutputObject*self = (OutputObject*)_self;
357 /* if(!strcmp(a, "x1")) {
358 return PyInt_FromLong(self->output_device->x1);
359 } else if(!strcmp(a, "y1")) {
360 return PyInt_FromLong(self->output_device->y1);
361 } else if(!strcmp(a, "x2")) {
362 return PyInt_FromLong(self->output_device->x2);
363 } else if(!strcmp(a, "y2")) {
364 return PyInt_FromLong(self->output_device->y2);
367 return Py_FindMethod(output_methods, _self, a);
369 static int output_setattr(PyObject * _self, char* a, PyObject * o)
371 OutputObject*self = (OutputObject*)_self;
372 if(!PyString_Check(o))
374 char*value = PyString_AsString(o);
375 self->output_device->setparameter(self->output_device, a, value);
378 static int output_print(PyObject * _self, FILE *fi, int flags)
380 OutputObject*self = (OutputObject*)_self;
381 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
385 //---------------------------------------------------------------------
386 staticforward PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs);
387 staticforward PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs);
389 static PyMethodDef page_methods[] =
392 {"render", (PyCFunction)page_render, METH_KEYWORDS, ""},
393 {"asImage", (PyCFunction)page_asImage, METH_KEYWORDS, ""},
396 static PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs)
398 PageObject* self = (PageObject*)_self;
400 static char *kwlist[] = {"dev", "move", "clip", NULL};
401 OutputObject*output = 0;
404 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OO", kwlist, &OutputClass, &output,
410 int cx1=0,cy1=0,cx2=0,cy2=0;
413 if (!PyArg_ParseTuple(move, "ii", &x,&y))
417 if (!PyArg_ParseTuple(clip, "iiii", &cx1,&cy1,&cx2,&cy2))
421 if(x|y|cx1|cx2|cy1|cy2)
422 self->page->rendersection(self->page, output->output_device,x,y,cx1,cy1,cx2,cy2);
424 self->page->render(self->page, output->output_device);
428 static PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs)
430 PageObject* self = (PageObject*)_self;
432 static char *kwlist[] = {"width", "height", NULL};
433 int width=0,height=0;
434 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &width, &height))
437 if(!width || !height) {
438 return PY_ERROR("invalid dimensions: %dx%d", width,height);
441 gfxdevice_t dev1,dev2;
442 gfxdevice_render_init(&dev1);
443 dev1.setparameter(&dev1, "antialise", "2");
444 gfxdevice_rescale_init(&dev2, &dev1, width, height, 0);
445 dev2.startpage(&dev2, self->page->width, self->page->height);
446 self->page->render(self->page, &dev2);
448 gfxresult_t*result = dev2.finish(&dev2);
449 gfximage_t*img = (gfximage_t*)result->get(result,"page0");
450 int l = img->width*img->height;
451 unsigned char*data = malloc(img->width*img->height*3);
453 for(t=0,s=0;t<l;s+=3,t++) {
454 data[s+0] = img->data[t].r;
455 data[s+1] = img->data[t].g;
456 data[s+2] = img->data[t].b;
458 result->destroy(result);
459 return PyString_FromStringAndSize((char*)data,img->width*img->height*3);
462 static void page_dealloc(PyObject* _self) {
463 PageObject* self = (PageObject*)_self;
465 self->page->destroy(self->page);
469 Py_DECREF(self->parent);
475 static PyObject* page_getattr(PyObject * _self, char* a)
477 PageObject*self = (PageObject*)_self;
479 if(!strcmp(a, "size")) {
480 return Py_BuildValue("(ii)", self->page->width, self->page->height);
481 } if(!strcmp(a, "doc")) {
482 Py_INCREF(self->parent);
484 } if(!strcmp(a, "nr")) {
485 return PyInt_FromLong(self->nr);
486 } else if(!strcmp(a, "width")) {
487 return PyInt_FromLong(self->page->width);
488 } else if(!strcmp(a, "height")) {
489 return PyInt_FromLong(self->page->height);
491 return Py_FindMethod(page_methods, _self, a);
493 static int page_setattr(PyObject * self, char* a, PyObject * o) {
496 static int page_print(PyObject * _self, FILE *fi, int flags)
498 PageObject*self = (PageObject*)_self;
499 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
503 //---------------------------------------------------------------------
505 staticforward PyObject* doc_getPage(PyObject* parent, PyObject* args, PyObject* kwargs);
506 staticforward PyObject* doc_getInfo(PyObject* parent, PyObject* args, PyObject* kwargs);
507 staticforward PyObject* doc_setParameter(PyObject* parent, PyObject* args, PyObject* kwargs);
509 static PyMethodDef doc_methods[] =
512 {"getPage", (PyCFunction)doc_getPage, METH_KEYWORDS, ""},
513 {"getInfo", (PyCFunction)doc_getInfo, METH_KEYWORDS, ""},
514 {"setParameter", (PyCFunction)doc_setParameter, METH_KEYWORDS, ""},
518 static PyObject* doc_getPage(PyObject* _self, PyObject* args, PyObject* kwargs)
520 DocObject* self = (DocObject*)_self;
522 static char *kwlist[] = {"nr", NULL};
524 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &pagenr))
527 PageObject*page = PyObject_New(PageObject, &PageClass);
528 page->page = self->doc->getpage(self->doc, pagenr);
530 page->parent = _self;
531 Py_INCREF(page->parent);
534 return PY_ERROR("Couldn't extract page %d", pagenr);
536 return (PyObject*)page;
539 static PyObject* doc_getInfo(PyObject* _self, PyObject* args, PyObject* kwargs)
541 DocObject* self = (DocObject*)_self;
543 static char *kwlist[] = {"key", NULL};
545 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &key))
548 char*s = self->doc->getinfo(self->doc, key);
549 return PyString_FromString(s);
552 static PyObject* doc_setParameter(PyObject* _self, PyObject* args, PyObject* kwargs)
554 DocObject* self = (DocObject*)_self;
556 static char *kwlist[] = {"key", "value", NULL};
557 char*key = 0, *value=0;
558 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key,&value))
561 self->doc->set_parameter(self->doc, key, value);
565 static PyObject* f_open(PyObject* parent, PyObject* args, PyObject* kwargs)
567 static char *kwlist[] = {"type", "filename", NULL};
570 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &type, &filename))
573 DocObject*self = PyObject_New(DocObject, &DriverClass);
575 if(!strcmp(type,"pdf"))
576 self->doc = pdfdriver->open(pdfdriver,filename);
578 return PY_ERROR("Unknown type %s", type);
582 return PY_ERROR("Couldn't open %s", filename);
584 self->filename = strdup(filename);
585 return (PyObject*)self;
587 static void doc_dealloc(PyObject* _self) {
588 DocObject* self = (DocObject*)_self;
590 self->doc->destroy(self->doc);
594 free(self->filename);self->filename=0;
598 static PyObject* doc_getattr(PyObject * _self, char* a)
600 DocObject*self = (DocObject*)_self;
601 if(!strcmp(a, "pages")) {
602 return PyInt_FromLong(self->doc->num_pages);
604 if(!strcmp(a, "filename")) {
605 return PyString_FromString(self->filename);
607 return Py_FindMethod(doc_methods, _self, a);
609 static int doc_setattr(PyObject * self, char* a, PyObject * o) {
612 static int doc_print(PyObject * _self, FILE *fi, int flags)
614 DocObject*self = (DocObject*)_self;
615 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
619 //---------------------------------------------------------------------
621 static PyTypeObject OutputClass =
623 PyObject_HEAD_INIT(NULL)
626 tp_basicsize: sizeof(OutputObject),
628 tp_dealloc: output_dealloc,
629 tp_print: output_print,
630 tp_getattr: output_getattr,
631 tp_setattr: output_setattr,
633 static PyTypeObject PageClass =
635 PyObject_HEAD_INIT(NULL)
638 tp_basicsize: sizeof(PageObject),
640 tp_dealloc: page_dealloc,
641 tp_print: page_print,
642 tp_getattr: page_getattr,
643 tp_setattr: page_setattr,
645 static PyTypeObject DriverClass =
647 PyObject_HEAD_INIT(NULL)
650 tp_basicsize: sizeof(DocObject),
652 tp_dealloc: doc_dealloc,
654 tp_getattr: doc_getattr,
655 tp_setattr: doc_setattr,
658 //=====================================================================
660 static PyObject* f_setoption(PyObject* self, PyObject* args, PyObject* kwargs)
662 static char *kwlist[] = {"key", "value", NULL};
664 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key, &value))
666 pdfdriver->set_parameter(pdfdriver,key,value);
670 static PyObject* f_verbose(PyObject* self, PyObject* args, PyObject* kwargs)
672 static char *kwlist[] = {"val", NULL};
674 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &val))
676 setConsoleLogging(val);
680 static PyObject* f_addfont(PyObject* self, PyObject* args, PyObject* kwargs)
682 static char *kwlist[] = {"filename", NULL};
684 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
686 pdfdriver->set_parameter(pdfdriver,"font", filename);
690 static PyObject* f_addfontdir(PyObject* self, PyObject* args, PyObject* kwargs)
692 static char *kwlist[] = {"filename", NULL};
694 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
696 pdfdriver->set_parameter(pdfdriver,"fontdir", filename);
700 static PyMethodDef pdf2swf_methods[] =
703 {"open", (PyCFunction)f_open, METH_KEYWORDS, ""},
704 {"addfont", (PyCFunction)f_addfont, METH_KEYWORDS, ""},
705 {"addfontdir", (PyCFunction)f_addfontdir, METH_KEYWORDS, ""},
706 {"setoption", (PyCFunction)f_setoption, METH_KEYWORDS, ""},
707 {"verbose", (PyCFunction)f_verbose, METH_KEYWORDS, ""},
710 {"SWF", (PyCFunction)f_createSWF, METH_KEYWORDS, ""},
711 {"ImageList", (PyCFunction)f_createImageList, METH_KEYWORDS, ""},
712 {"PlainText", (PyCFunction)f_createPlainText, METH_KEYWORDS, ""},
713 {"PassThrough", (PyCFunction)f_createPassThrough, METH_KEYWORDS, ""},
721 initLog(0,0,0,0,0,2);
722 OutputClass.ob_type = &PyType_Type;
723 PageClass.ob_type = &PyType_Type;
724 DriverClass.ob_type = &PyType_Type;
726 pdfdriver = gfxsource_pdf_create();
728 PyObject*module = Py_InitModule("gfx", pdf2swf_methods);