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 DocClass;
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 PyDoc_STRVAR(output_save_doc, \
75 "Saves the contents of an output device to a file\n"
76 "Depending on what the output device is, the contents\n"
77 "of the file may be plain text, an image, an SWF file,\n"
79 static PyObject* output_save(PyObject* _self, PyObject* args, PyObject* kwargs)
81 OutputObject* self = (OutputObject*)_self;
83 static char *kwlist[] = {"filename", NULL};
84 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
87 gfxresult_t*result = self->output_device->finish(self->output_device);
88 self->output_device = 0;
89 if(result->save(result, filename) < 0) {
90 return PY_ERROR("Couldn't write to %s", filename);
92 result->destroy(result);
96 PyDoc_STRVAR(output_startpage_doc, \
97 "startpage(width, height)\n\n"
98 "Starts a new page/frame in the output device.\n"
99 "The usual way to render documents is to start a new page in the\n"
100 "device for each page in the document:\n"
102 "for pagenr in range(1,doc.pages+1):\n"
103 " page = doc.getPage(pagenr)\n"
104 " output.startpage(page.width, page.height)\n"
105 " page.render(output)\n"
106 " output.endpage()\n"
108 "It is, however, also possible to render more than one document page\n"
109 "to a single output page. E.g. for side-by-side or book views.\n"
111 static PyObject* output_startpage(PyObject* _self, PyObject* args, PyObject* kwargs)
113 OutputObject* self = (OutputObject*)_self;
114 int width=0, height=0;
115 if (!PyArg_ParseTuple(args, "ii", &width, &height))
117 self->output_device->startpage(self->output_device, width, height);
120 PyDoc_STRVAR(output_endpage_doc, \
122 "Ends a page in the output device. This function should be called\n"
123 "once for every startpage()\n"
125 static PyObject* output_endpage(PyObject* _self, PyObject* args, PyObject* kwargs)
127 OutputObject* self = (OutputObject*)_self;
128 if (!PyArg_ParseTuple(args, ""))
130 self->output_device->endpage(self->output_device);
133 PyDoc_STRVAR(f_createSWF_doc, \
135 "Creates a device which renders documents to SWF (Flash) files.\n"
136 "Depending on the way the document parser behaves (see the poly2bitmap\n"
137 "and bitmap parameters), the resulting SWF might use vector operations\n"
138 "and Flash Texts to display the document, or just a single bitmap\n"
140 static PyObject* f_createSWF(PyObject* parent, PyObject* args, PyObject* kwargs)
142 static char *kwlist[] = {NULL};
143 if (args && !PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
145 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
147 self->output_device = malloc(sizeof(gfxdevice_t));
148 gfxdevice_swf_init(self->output_device);
149 return (PyObject*)self;
152 PyDoc_STRVAR(f_createImageList_doc, \
154 "Creates a device which renders documents to bitmaps.\n"
155 "Each page that is rendered will create new bitmap.\n"
156 "As, right now, the only way to access the bitmaps is\n"
157 "by using the save() function on the imagelist, you can\n"
158 "currently only retrieve the first bitmap/page.\n"
160 static PyObject* f_createImageList(PyObject* parent, PyObject* args, PyObject* kwargs)
162 static char *kwlist[] = {NULL};
163 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
165 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
167 self->output_device = malloc(sizeof(gfxdevice_t));
168 gfxdevice_render_init(self->output_device);
169 return (PyObject*)self;
172 PyDoc_STRVAR(f_createPlainText_doc, \
174 "Creates a device which can be used to extract text from documents,\n"
175 "by passing it as parameter to page.render().\n"
176 "The extracted text can be saved by plaintext.save(filename).\n"
178 static PyObject* f_createPlainText(PyObject* parent, PyObject* args, PyObject* kwargs)
180 static char *kwlist[] = {NULL};
181 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
183 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
185 self->output_device = malloc(sizeof(gfxdevice_t));
186 gfxdevice_text_init(self->output_device);
187 return (PyObject*)self;
190 static PyObject*callback_python(char*function, gfxdevice_t*dev, const char*format, ...)
192 OutputObject*self = (OutputObject*)dev->internal;
194 if(!PyObject_HasAttrString(self->pyobj, function))
198 va_start(ap, format);
200 PyObject*tuple = PyTuple_New(strlen(format));
203 char p = format[pos];
205 char*s = va_arg(ap, char*);
206 PyTuple_SetItem(tuple, pos, PyString_FromString(s));
208 int i = va_arg(ap, int);
209 PyTuple_SetItem(tuple, pos, PyInt_FromLong(i));
211 void* ptr = va_arg(ap, void*);
212 gfxcolor_t*col = (gfxcolor_t*)ptr;
213 PyObject*colobj = PyTuple_New(4);
214 PyTuple_SetItem(colobj, 0, PyInt_FromLong(col->r));
215 PyTuple_SetItem(colobj, 1, PyInt_FromLong(col->g));
216 PyTuple_SetItem(colobj, 2, PyInt_FromLong(col->b));
217 PyTuple_SetItem(colobj, 3, PyInt_FromLong(col->a));
218 PyTuple_SetItem(tuple, pos, colobj);
220 void* ptr = va_arg(ap, void*);
221 gfxline_t*line = (gfxline_t*)ptr;
225 while(l) {l=l->next;len++;}
226 PyObject*list = PyList_New(len);
230 if(l->type == gfx_moveTo) {
231 point = PyTuple_New(3);
232 PyTuple_SetItem(point, 0, PyString_FromString("m"));
233 PyTuple_SetItem(point, 1, PyFloat_FromDouble(l->x));
234 PyTuple_SetItem(point, 2, PyFloat_FromDouble(l->y));
235 } else if(l->type == gfx_lineTo) {
236 point = PyTuple_New(3);
237 PyTuple_SetItem(point, 0, PyString_FromString("l"));
238 PyTuple_SetItem(point, 1, PyFloat_FromDouble(l->x));
239 PyTuple_SetItem(point, 2, PyFloat_FromDouble(l->y));
240 } else if(l->type == gfx_splineTo) {
241 point = PyTuple_New(5);
242 PyTuple_SetItem(point, 0, PyString_FromString("s"));
243 PyTuple_SetItem(point, 1, PyFloat_FromDouble(l->x));
244 PyTuple_SetItem(point, 2, PyFloat_FromDouble(l->y));
245 PyTuple_SetItem(point, 3, PyFloat_FromDouble(l->sx));
246 PyTuple_SetItem(point, 4, PyFloat_FromDouble(l->sy));
250 PyList_SetItem(list, i, point);
254 PyTuple_SetItem(tuple, pos, list);
256 PyTuple_SetItem(tuple, pos, PY_NONE);
261 PyObject*f = PyObject_GetAttrString(self->pyobj, function);
265 PyObject* result = PyObject_CallObject(f, tuple);
277 static int my_setparameter(gfxdevice_t*dev, const char*key, const char*value)
279 callback_python("setparameter", dev, "ss", key, value);
282 static void my_startpage(gfxdevice_t*dev, int width, int height)
284 callback_python("startpage", dev, "ii", width, height);
286 static void my_startclip(gfxdevice_t*dev, gfxline_t*line)
288 callback_python("startclip", dev, "l", line);
290 static void my_endclip(gfxdevice_t*dev)
292 callback_python("endclip", dev, "");
294 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)
298 if(cap_style == gfx_capButt)
300 else if(cap_style == gfx_capRound)
302 else if(cap_style == gfx_capSquare)
304 if(joint_style == gfx_joinMiter)
306 else if(joint_style == gfx_joinRound)
308 else if(joint_style == gfx_joinBevel)
310 callback_python("stroke", dev, "licssi", line, width, color, cap, joint, miterLimit);
312 static void my_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
314 callback_python("fill", dev, "lc", line, color);
316 static void my_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*imgcoord2devcoord, gfxcxform_t*cxform)
318 callback_python("fillbitmap", dev, "lImx", line, img, imgcoord2devcoord, cxform);
320 static void my_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
322 callback_python("fillgradient", dev, "lgsm", line, gradient, type, matrix);
324 static void my_addfont(gfxdevice_t*dev, gfxfont_t*font)
326 callback_python("addfont", dev, "f", font);
328 static void my_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
330 callback_python("drawchar", dev, "ficm", font, glyph, color, matrix);
332 static void my_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
334 callback_python("drawlink", dev, "ls", line, action);
336 static void my_endpage(gfxdevice_t*dev)
338 callback_python("drawlink", dev, "");
340 static gfxresult_t* my_finish(gfxdevice_t*dev)
342 callback_python("finish", dev, "");
347 PyDoc_STRVAR(f_createPassThrough_doc, \
348 "PassThrough(device)\n\n"
349 "Creates a PassThrough device, which can be used as parameter in calls\n"
350 "to page.render().\n"
351 "device needs to be a class implementing at least the following functions:\n\n"
352 "setparameter(key,value)\n"
353 "startpage(width,height)\n"
354 "startclip(outline)\n"
356 "stroke(outline, width, color, capstyle, jointstyle, miterLimit)\n"
357 "fill(outline, color)\n"
358 "fillbitmap(outline, image, matrix, colortransform)\n"
359 "fillgradient(outline, gradient, gradienttype, matrix)\n"
361 "drawchar(font, glyph, color, matrix)\n"
362 "drawlink(outline, url)\n"
364 "If any of these functions are not defined, a error message will be printed,\n"
365 "however the rendering process will be continued.\n"
367 static PyObject* f_createPassThrough(PyObject* parent, PyObject* args, PyObject* kwargs)
369 static char *kwlist[] = {"device", NULL};
371 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &obj))
373 OutputObject*self = PyObject_New(OutputObject, &OutputClass);
376 self->output_device = malloc(sizeof(gfxdevice_t));
377 memset(self->output_device, 0, sizeof(gfxdevice_t));
378 self->output_device->name = strdup("passthrough");
380 self->output_device->setparameter = my_setparameter;
381 self->output_device->startpage = my_startpage;
382 self->output_device->startclip = my_startclip;
383 self->output_device->addfont = my_addfont;
384 self->output_device->endclip = my_endclip;
385 self->output_device->stroke = my_stroke;
386 self->output_device->fill = my_fill;
387 self->output_device->fillbitmap = my_fillbitmap;
388 self->output_device->fillgradient = my_fillgradient;
389 self->output_device->drawchar = my_drawchar;
390 self->output_device->drawlink = my_drawlink;
391 self->output_device->endpage = my_endpage;
392 self->output_device->finish = my_finish;
393 self->output_device->internal = self;
395 return (PyObject*)self;
398 static PyMethodDef output_methods[] =
400 /* Output functions */
401 {"save", (PyCFunction)output_save, METH_KEYWORDS, output_save_doc},
402 {"startpage", (PyCFunction)output_startpage, METH_KEYWORDS, output_startpage_doc},
403 {"endpage", (PyCFunction)output_endpage, METH_KEYWORDS, output_endpage_doc},
407 static void output_dealloc(PyObject* _self) {
408 OutputObject* self = (OutputObject*)_self;
410 if(self->output_device) {
411 gfxresult_t*result = self->output_device->finish(self->output_device);
413 result->destroy(result);result=0;
415 self->output_device = 0;
420 static PyObject* output_getattr(PyObject * _self, char* a)
422 OutputObject*self = (OutputObject*)_self;
424 /* if(!strcmp(a, "x1")) {
425 return PyInt_FromLong(self->output_device->x1);
426 } else if(!strcmp(a, "y1")) {
427 return PyInt_FromLong(self->output_device->y1);
428 } else if(!strcmp(a, "x2")) {
429 return PyInt_FromLong(self->output_device->x2);
430 } else if(!strcmp(a, "y2")) {
431 return PyInt_FromLong(self->output_device->y2);
434 return Py_FindMethod(output_methods, _self, a);
436 static int output_setattr(PyObject * _self, char* a, PyObject * o)
438 OutputObject*self = (OutputObject*)_self;
439 if(!PyString_Check(o))
441 char*value = PyString_AsString(o);
442 self->output_device->setparameter(self->output_device, a, value);
445 static int output_print(PyObject * _self, FILE *fi, int flags)
447 OutputObject*self = (OutputObject*)_self;
448 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
452 //---------------------------------------------------------------------
453 staticforward PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs);
454 staticforward PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs);
456 PyDoc_STRVAR(page_render_doc, \
457 "render(output, move=(0,0), clip=None)\n\n"
458 "Renders a page to the rendering backend specified by the output\n"
459 "parameter. Rendering consists of calling a number of functions on the\n"
460 "output device, see the description of the \"PassThrough\" device.\n"
461 "The page may be shifted to a given position using the move parameter,\n"
462 "and may also be clipped to a specific size using the clip parameter.\n"
463 "The clipping operation is applied after the move operation.\n"
465 static PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs)
467 PageObject* self = (PageObject*)_self;
469 static char *kwlist[] = {"dev", "move", "clip", NULL};
470 OutputObject*output = 0;
473 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OO", kwlist, &OutputClass, &output,
479 int cx1=0,cy1=0,cx2=0,cy2=0;
482 if (!PyArg_ParseTuple(move, "ii", &x,&y))
486 if (!PyArg_ParseTuple(clip, "iiii", &cx1,&cy1,&cx2,&cy2))
490 if(x|y|cx1|cx2|cy1|cy2)
491 self->page->rendersection(self->page, output->output_device,x,y,cx1,cy1,cx2,cy2);
493 self->page->render(self->page, output->output_device);
497 PyDoc_STRVAR(page_asImage_doc, \
498 "asImage(width, height)\n\n"
499 "Creates a bitmap from a page. The bitmap will be returned as a string\n"
500 "containing RGB triplets. The bitmap will have the specified width and\n"
501 "height. The aspect ratio of width and height doesn't need to be the same\n"
504 static PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs)
506 PageObject* self = (PageObject*)_self;
508 static char *kwlist[] = {"width", "height", NULL};
509 int width=0,height=0;
510 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &width, &height))
513 if(!width || !height) {
514 return PY_ERROR("invalid dimensions: %dx%d", width,height);
517 gfxdevice_t dev1,dev2;
518 gfxdevice_render_init(&dev1);
519 dev1.setparameter(&dev1, "antialise", "2");
520 gfxdevice_rescale_init(&dev2, &dev1, width, height, 0);
521 dev2.startpage(&dev2, self->page->width, self->page->height);
522 self->page->render(self->page, &dev2);
524 gfxresult_t*result = dev2.finish(&dev2);
525 gfximage_t*img = (gfximage_t*)result->get(result,"page0");
526 int l = img->width*img->height;
527 unsigned char*data = malloc(img->width*img->height*3);
529 for(t=0,s=0;t<l;s+=3,t++) {
530 data[s+0] = img->data[t].r;
531 data[s+1] = img->data[t].g;
532 data[s+2] = img->data[t].b;
534 result->destroy(result);
535 return PyString_FromStringAndSize((char*)data,img->width*img->height*3);
538 static PyMethodDef page_methods[] =
541 {"render", (PyCFunction)page_render, METH_KEYWORDS, page_render_doc},
542 {"asImage", (PyCFunction)page_asImage, METH_KEYWORDS, page_asImage_doc},
545 static void page_dealloc(PyObject* _self) {
546 PageObject* self = (PageObject*)_self;
548 self->page->destroy(self->page);
552 Py_DECREF(self->parent);
559 static PyObject* page_getattr(PyObject * _self, char* a)
561 PageObject*self = (PageObject*)_self;
563 if(!strcmp(a, "size")) {
564 return Py_BuildValue("(ii)", self->page->width, self->page->height);
565 } if(!strcmp(a, "doc")) {
566 Py_INCREF(self->parent);
568 } if(!strcmp(a, "nr")) {
569 return PyInt_FromLong(self->nr);
570 } else if(!strcmp(a, "width")) {
571 return PyInt_FromLong(self->page->width);
572 } else if(!strcmp(a, "height")) {
573 return PyInt_FromLong(self->page->height);
575 return Py_FindMethod(page_methods, _self, a);
578 static int page_setattr(PyObject * self, char* a, PyObject * o) {
581 static int page_print(PyObject * _self, FILE *fi, int flags)
583 PageObject*self = (PageObject*)_self;
584 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
588 //---------------------------------------------------------------------
590 PyDoc_STRVAR(doc_getPage_doc,
593 "Get one page from a document file. The nr parameter specifies\n"
594 "which page to retrieve. Counting starts at 1, so the first page\n"
595 "can be retrieved by\n"
596 " page = doc.getPage(1)\n"
598 "You can find out how many pages a document contains by querying\n"
599 "it's pages field (doc.pages)\n"
601 static PyObject* doc_getPage(PyObject* _self, PyObject* args, PyObject* kwargs)
603 DocObject* self = (DocObject*)_self;
605 static char *kwlist[] = {"nr", NULL};
607 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &pagenr))
610 PageObject*page = PyObject_New(PageObject, &PageClass);
611 page->page = self->doc->getpage(self->doc, pagenr);
613 page->parent = _self;
614 Py_INCREF(page->parent);
617 return PY_ERROR("Couldn't extract page %d", pagenr);
619 return (PyObject*)page;
622 PyDoc_STRVAR(doc_getInfo_doc,
625 "Retrieve some information about a document. For PDF files, key\n"
626 "can have the following values:\n\n"
627 "\"title\", \"subject\", \"keywords\", \"author\", \"creator\", \"producer\",\n"
628 "\"creationdate\", \"moddate\", \"linearized\", \"tagged\", \"encrypted\",\n"
629 "\"oktoprint\", \"oktocopy\", \"oktochange\", \"oktoaddnotes\", \"version\".\n\n"
630 "If the \"oktocopy\" digital rights management flag is set to \"no\", then the\n"
631 "pdf parser won't allow you to access the PDF file. Trying to extract pages\n"
632 "from it will raise an exception.\n"
634 static PyObject* doc_getInfo(PyObject* _self, PyObject* args, PyObject* kwargs)
636 DocObject* self = (DocObject*)_self;
638 static char *kwlist[] = {"key", NULL};
640 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &key))
643 char*s = self->doc->getinfo(self->doc, key);
644 return PyString_FromString(s);
647 PyDoc_STRVAR(doc_setParameter_doc,
648 "setParameter(key, value)\n\n"
650 "Pass a parameter or setting to the document parser. Unlike\n"
651 "the module level setoption() function, the parameters set\n"
652 "using setParameter will only be valid for the object itself\n"
653 "during its lifetime.\n"
655 static PyObject* doc_setParameter(PyObject* _self, PyObject* args, PyObject* kwargs)
657 DocObject* self = (DocObject*)_self;
659 static char *kwlist[] = {"key", "value", NULL};
660 char*key = 0, *value=0;
661 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key,&value))
664 self->doc->set_parameter(self->doc, key, value);
668 PyDoc_STRVAR(f_open_doc,
669 "open(type, filename) -> object\n\n"
670 "Open a PDF file. The type argument always has to be \"pdf\"\n"
671 "It returns a doc object which can be used to process the pdf\n"
673 " doc = open(\"pdf\", \"document.pdf\")\n"
674 "If the file is not a PDF file or is encrypted without\n"
675 "a proper password specified, an exception is being raised.\n"
676 "If the filename argument contains a '|' char, everything behind\n"
677 "the '|' is treated as password used for opening the file.\n"
679 " doc = open(\"pdf\", \"document.pdf|mysecretpassword\")\n"
681 static PyObject* f_open(PyObject* parent, PyObject* args, PyObject* kwargs)
683 static char *kwlist[] = {"type", "filename", NULL};
686 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &type, &filename)) {
689 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
693 DocObject*self = PyObject_New(DocObject, &DocClass);
695 if(!strcmp(type,"pdf"))
696 self->doc = pdfdriver->open(pdfdriver,filename);
698 return PY_ERROR("Unknown type %s", type);
702 return PY_ERROR("Couldn't open %s", filename);
704 self->filename = strdup(filename);
705 return (PyObject*)self;
708 static PyMethodDef doc_methods[] =
711 {"getPage", (PyCFunction)doc_getPage, METH_KEYWORDS, doc_getPage_doc},
712 {"getInfo", (PyCFunction)doc_getInfo, METH_KEYWORDS, doc_getInfo_doc},
713 {"setParameter", (PyCFunction)doc_setParameter, METH_KEYWORDS, doc_setParameter_doc},
717 static void doc_dealloc(PyObject* _self) {
718 DocObject* self = (DocObject*)_self;
720 self->doc->destroy(self->doc);
724 free(self->filename);self->filename=0;
728 static PyObject* doc_getattr(PyObject * _self, char* a)
730 DocObject*self = (DocObject*)_self;
731 if(!strcmp(a, "pages")) {
732 return PyInt_FromLong(self->doc->num_pages);
734 if(!strcmp(a, "filename")) {
735 return PyString_FromString(self->filename);
737 return Py_FindMethod(doc_methods, _self, a);
739 static int doc_setattr(PyObject * self, char* a, PyObject * o) {
742 static int doc_print(PyObject * _self, FILE *fi, int flags)
744 DocObject*self = (DocObject*)_self;
745 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
749 //---------------------------------------------------------------------
751 PyDoc_STRVAR(output_doc,
752 "An Output object can be used as parameter to the render()\n"
753 "call of a page. It's not possible to create this type of\n"
754 "object directly (i.e., from a class), however you can\n"
755 "use a PassThrough() device to pass things over to Python.\n"
756 "Examples for classes implementing the Output class are: \n"
757 "ImageList, SWF, PlainText, PassThrough\n"
759 static PyTypeObject OutputClass =
761 PyObject_HEAD_INIT(NULL)
763 tp_name: "gfx.Output",
764 tp_basicsize: sizeof(OutputObject),
766 tp_dealloc: output_dealloc,
767 tp_print: output_print,
768 tp_getattr: output_getattr,
769 tp_setattr: output_setattr,
771 tp_methods: output_methods
773 PyDoc_STRVAR(page_doc,
774 "A Page object contains a single page of a document.\n"
775 "page.width and page.height (or page.size) contain the\n"
776 "page dimensions. page.nr is the number of the page, and\n"
777 "page.doc is the parent document.\n"
779 static PyTypeObject PageClass =
781 PyObject_HEAD_INIT(NULL)
784 tp_basicsize: sizeof(PageObject),
786 tp_dealloc: page_dealloc,
787 tp_print: page_print,
788 tp_getattr: page_getattr,
789 tp_setattr: page_setattr,
791 tp_methods: page_methods
793 PyDoc_STRVAR(doc_doc,
794 "A Doc object is used for storing a document (like a PDF).\n"
795 "doc.pages contains the number of pages in the document,\n"
796 "and doc.filename the name of the file the document was\n"
797 "created (loaded) from\n"
799 static PyTypeObject DocClass =
801 PyObject_HEAD_INIT(NULL)
804 tp_basicsize: sizeof(DocObject),
806 tp_dealloc: doc_dealloc,
808 tp_getattr: doc_getattr,
809 tp_setattr: doc_setattr,
811 tp_methods: doc_methods,
814 //=====================================================================
816 PyDoc_STRVAR(f_setoption_doc, \
817 "setoption(key,value)\n\n"
819 "Set a parameter in the gfx module (which might affect the PDF\n"
820 "parser or any of the rendering backends). This is a parameter\n"
821 "which would usually be passed with the \"-s\" option to pdf2swf\n"
822 "For a list of all parameters, see the output of\n"
825 " pdf2swf somefile.pdf -s help\n"
828 static PyObject* f_setoption(PyObject* self, PyObject* args, PyObject* kwargs)
830 static char *kwlist[] = {"key", "value", NULL};
832 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key, &value))
834 pdfdriver->set_parameter(pdfdriver,key,value);
838 PyDoc_STRVAR(f_verbose_doc, \
840 "Set the logging verbosity of the gfx module. Log levels are:\n"
841 "level=-1 Log nothing\n"
842 "level=0 (fatal) Log only fatal errors\n"
843 "level=1 (error) Log only fatal errors and errors\n"
844 "level=2 (warn) Log all errors and warnings\n"
845 "level=3 (notice) Log also some rudimentary data about the parsing/conversion\n"
846 "level=4 (verbose) Log some additional parsing information\n"
847 "level=5 (debug) Log debug statements\n"
848 "level=6 (trace) Log extended debug statements\n"
849 "All logging messages are written to stdout.\n"
851 static PyObject* f_verbose(PyObject* self, PyObject* args, PyObject* kwargs)
853 static char *kwlist[] = {"val", NULL};
855 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &val))
857 setConsoleLogging(val);
861 PyDoc_STRVAR(f_addfont_doc, \
862 "addfont(filename)\n\n"
863 "Passes an additional font file to the PDF parser. If a PDF contains\n"
864 "external fonts (i.e. fonts which are not contained in the PDF itself)\n"
865 "then the files added by addfont() will be searched.\n"
868 static PyObject* f_addfont(PyObject* self, PyObject* args, PyObject* kwargs)
870 static char *kwlist[] = {"filename", NULL};
872 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
874 pdfdriver->set_parameter(pdfdriver,"font", filename);
878 PyDoc_STRVAR(f_addfontdir_doc, \
879 "addfontdir(dirname)\n\n"
880 "Passes a complete directory containing fonts to the PDF parser. Any\n"
881 "font file within this directory might be used to resolve external fonts\n"
884 static PyObject* f_addfontdir(PyObject* self, PyObject* args, PyObject* kwargs)
886 static char *kwlist[] = {"filename", NULL};
888 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
890 pdfdriver->set_parameter(pdfdriver,"fontdir", filename);
894 static PyMethodDef pdf2swf_methods[] =
897 {"open", (PyCFunction)f_open, METH_KEYWORDS, f_open_doc},
898 {"addfont", (PyCFunction)f_addfont, METH_KEYWORDS, f_addfont_doc},
899 {"addfontdir", (PyCFunction)f_addfontdir, METH_KEYWORDS, f_addfontdir_doc},
900 {"setoption", (PyCFunction)f_setoption, METH_KEYWORDS, f_setoption_doc},
901 {"verbose", (PyCFunction)f_verbose, METH_KEYWORDS, f_verbose_doc},
904 {"SWF", (PyCFunction)f_createSWF, METH_KEYWORDS, f_createSWF_doc},
905 {"ImageList", (PyCFunction)f_createImageList, METH_KEYWORDS, f_createImageList_doc},
906 {"PlainText", (PyCFunction)f_createPlainText, METH_KEYWORDS, f_createPlainText_doc},
907 {"PassThrough", (PyCFunction)f_createPassThrough, METH_KEYWORDS, f_createPassThrough_doc},
913 PyDoc_STRVAR(gfx_doc, \
914 "This module contains a PDF parser (based on xpdf) and a number of\n"
915 "rendering backends. In particular, it can extract text from PDF pages,\n"
916 "create bitmaps from them, or convert PDF files to SWF.\n"
917 "The latter functionality is similar to what is offered by swftools'\n"
918 "(http://www.swftools.org) pdf2swf utility, however more powerful-\n"
919 "You can also create individual SWF files from single pages of the PDF\n"
920 "or combine more than one page into a bigger PDF.\n"
925 initLog(0,0,0,0,0,2);
926 OutputClass.ob_type = &PyType_Type;
927 PageClass.ob_type = &PyType_Type;
928 DocClass.ob_type = &PyType_Type;
930 pdfdriver = gfxsource_pdf_create();
932 PyObject*module = Py_InitModule3("gfx", pdf2swf_methods, gfx_doc);
933 PyObject*module_dict = PyModule_GetDict(module);
935 PyDict_SetItemString(module_dict, "Doc", (PyObject*)&DocClass);
936 PyDict_SetItemString(module_dict, "Page", (PyObject*)&PageClass);
937 PyDict_SetItemString(module_dict, "Output", (PyObject*)&OutputClass);