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 *not* be aborted.\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,
592 "Get one page from a document file. The nr parameter specifies\n"
593 "which page to retrieve. Counting starts at 1, so the first page\n"
594 "can be retrieved by\n"
595 " page = doc.getPage(1)\n"
597 "You can find out how many pages a document contains by querying\n"
598 "its pages field (doc.pages)\n"
600 static PyObject* doc_getPage(PyObject* _self, PyObject* args, PyObject* kwargs)
602 DocObject* self = (DocObject*)_self;
604 static char *kwlist[] = {"nr", NULL};
606 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &pagenr))
609 PageObject*page = PyObject_New(PageObject, &PageClass);
610 page->page = self->doc->getpage(self->doc, pagenr);
612 page->parent = _self;
613 Py_INCREF(page->parent);
616 return PY_ERROR("Couldn't extract page %d", pagenr);
618 return (PyObject*)page;
621 PyDoc_STRVAR(doc_getInfo_doc,
623 "Retrieve some information about a document. For PDF files, key\n"
624 "can have the following values:\n\n"
625 "\"title\", \"subject\", \"keywords\", \"author\", \"creator\", \"producer\",\n"
626 "\"creationdate\", \"moddate\", \"linearized\", \"tagged\", \"encrypted\",\n"
627 "\"oktoprint\", \"oktocopy\", \"oktochange\", \"oktoaddnotes\", \"version\".\n\n"
628 "If the \"oktocopy\" digital rights management flag is set to \"no\", then the\n"
629 "pdf parser won't allow you to access the PDF file. Trying to extract pages\n"
630 "from it will raise an exception.\n"
632 static PyObject* doc_getInfo(PyObject* _self, PyObject* args, PyObject* kwargs)
634 DocObject* self = (DocObject*)_self;
636 static char *kwlist[] = {"key", NULL};
638 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &key))
641 char*s = self->doc->getinfo(self->doc, key);
642 return PyString_FromString(s);
645 PyDoc_STRVAR(doc_setParameter_doc,
646 "setParameter(key, value)\n\n"
647 "Pass a parameter or setting to the document parser. Unlike\n"
648 "the module level setoption() function, the parameters set\n"
649 "using setParameter will only be valid for the object itself\n"
650 "during its lifetime.\n"
652 static PyObject* doc_setParameter(PyObject* _self, PyObject* args, PyObject* kwargs)
654 DocObject* self = (DocObject*)_self;
656 static char *kwlist[] = {"key", "value", NULL};
657 char*key = 0, *value=0;
658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key,&value))
661 self->doc->set_parameter(self->doc, key, value);
665 PyDoc_STRVAR(f_open_doc,
666 "open(type, filename) -> object\n\n"
667 "Open a PDF file. The type argument always has to be \"pdf\"\n"
668 "It returns a doc object which can be used to process the pdf\n"
670 " doc = open(\"pdf\", \"document.pdf\")\n"
671 "If the file is not a PDF file or is encrypted without\n"
672 "a proper password specified, an exception is being raised.\n"
673 "If the filename argument contains a '|' char, everything behind\n"
674 "the '|' is treated as password used for opening the file.\n"
676 " doc = open(\"pdf\", \"document.pdf|mysecretpassword\")\n"
678 static PyObject* f_open(PyObject* parent, PyObject* args, PyObject* kwargs)
680 static char *kwlist[] = {"type", "filename", NULL};
683 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &type, &filename)) {
686 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
690 DocObject*self = PyObject_New(DocObject, &DocClass);
692 if(!strcmp(type,"pdf"))
693 self->doc = pdfdriver->open(pdfdriver,filename);
695 return PY_ERROR("Unknown type %s", type);
699 return PY_ERROR("Couldn't open %s", filename);
701 self->filename = strdup(filename);
702 return (PyObject*)self;
705 static PyMethodDef doc_methods[] =
708 {"getPage", (PyCFunction)doc_getPage, METH_KEYWORDS, doc_getPage_doc},
709 {"getInfo", (PyCFunction)doc_getInfo, METH_KEYWORDS, doc_getInfo_doc},
710 {"setParameter", (PyCFunction)doc_setParameter, METH_KEYWORDS, doc_setParameter_doc},
714 static void doc_dealloc(PyObject* _self) {
715 DocObject* self = (DocObject*)_self;
717 self->doc->destroy(self->doc);
721 free(self->filename);self->filename=0;
725 static PyObject* doc_getattr(PyObject * _self, char* a)
727 DocObject*self = (DocObject*)_self;
728 if(!strcmp(a, "pages")) {
729 return PyInt_FromLong(self->doc->num_pages);
731 if(!strcmp(a, "filename")) {
732 return PyString_FromString(self->filename);
734 return Py_FindMethod(doc_methods, _self, a);
736 static int doc_setattr(PyObject * self, char* a, PyObject * o) {
739 static int doc_print(PyObject * _self, FILE *fi, int flags)
741 DocObject*self = (DocObject*)_self;
742 fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
746 //---------------------------------------------------------------------
748 PyDoc_STRVAR(output_doc,
749 "An Output object can be used as parameter to the render()\n"
750 "call of a page. It's not possible to create this type of\n"
751 "object directly (i.e., from a class), however you can\n"
752 "use a PassThrough() device to pass things over to Python.\n"
753 "Examples for classes implementing the Output class are: \n"
754 "ImageList, SWF, PlainText and PassThrough.\n"
756 static PyTypeObject OutputClass =
758 PyObject_HEAD_INIT(NULL)
760 tp_name: "gfx.Output",
761 tp_basicsize: sizeof(OutputObject),
763 tp_dealloc: output_dealloc,
764 tp_print: output_print,
765 tp_getattr: output_getattr,
766 tp_setattr: output_setattr,
768 tp_methods: output_methods
770 PyDoc_STRVAR(page_doc,
771 "A Page object contains a single page of a document.\n"
772 "page.width and page.height (or page.size) contain the\n"
773 "page dimensions. page.nr is the number of the page, and\n"
774 "page.doc is the parent document.\n"
776 static PyTypeObject PageClass =
778 PyObject_HEAD_INIT(NULL)
781 tp_basicsize: sizeof(PageObject),
783 tp_dealloc: page_dealloc,
784 tp_print: page_print,
785 tp_getattr: page_getattr,
786 tp_setattr: page_setattr,
788 tp_methods: page_methods
790 PyDoc_STRVAR(doc_doc,
791 "A Doc object is used for storing a document (like a PDF).\n"
792 "doc.pages contains the number of pages in the document,\n"
793 "and doc.filename the name of the file the document was\n"
794 "created (loaded) from\n"
796 static PyTypeObject DocClass =
798 PyObject_HEAD_INIT(NULL)
801 tp_basicsize: sizeof(DocObject),
803 tp_dealloc: doc_dealloc,
805 tp_getattr: doc_getattr,
806 tp_setattr: doc_setattr,
808 tp_methods: doc_methods,
811 //=====================================================================
813 PyDoc_STRVAR(f_setoption_doc, \
814 "setoption(key,value)\n\n"
815 "Set a parameter in the gfx module (which might affect the PDF\n"
816 "parser or any of the rendering backends). This is a parameter\n"
817 "which would usually be passed with the \"-s\" option to pdf2swf.\n"
818 "For a list of all parameters, see the output of\n"
821 " pdf2swf somefile.pdf -s help\n"
824 static PyObject* f_setoption(PyObject* self, PyObject* args, PyObject* kwargs)
826 static char *kwlist[] = {"key", "value", NULL};
828 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key, &value))
830 pdfdriver->set_parameter(pdfdriver,key,value);
834 PyDoc_STRVAR(f_verbose_doc, \
836 "Set the logging verbosity of the gfx module. Log levels are:\n"
837 "level=-1 Log nothing\n"
838 "level=0 (fatal) Log only fatal errors\n"
839 "level=1 (error) Log only fatal errors and errors\n"
840 "level=2 (warn) Log all errors and warnings\n"
841 "level=3 (notice) Log also some rudimentary data about the parsing/conversion\n"
842 "level=4 (verbose) Log some additional parsing information\n"
843 "level=5 (debug) Log debug statements\n"
844 "level=6 (trace) Log extended debug statements\n"
845 "All logging messages are written to stdout.\n"
847 static PyObject* f_verbose(PyObject* self, PyObject* args, PyObject* kwargs)
849 static char *kwlist[] = {"val", NULL};
851 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &val))
853 setConsoleLogging(val);
857 PyDoc_STRVAR(f_addfont_doc, \
858 "addfont(filename)\n\n"
859 "Passes an additional font file to the PDF parser. If a PDF contains\n"
860 "external fonts (i.e. fonts which are not contained in the PDF itself)\n"
861 "then the files added by addfont() will be searched.\n"
864 static PyObject* f_addfont(PyObject* self, PyObject* args, PyObject* kwargs)
866 static char *kwlist[] = {"filename", NULL};
868 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
870 pdfdriver->set_parameter(pdfdriver,"font", filename);
874 PyDoc_STRVAR(f_addfontdir_doc, \
875 "addfontdir(dirname)\n\n"
876 "Passes a complete directory containing fonts to the PDF parser. Any\n"
877 "font file within this directory might be used to resolve external fonts\n"
880 static PyObject* f_addfontdir(PyObject* self, PyObject* args, PyObject* kwargs)
882 static char *kwlist[] = {"filename", NULL};
884 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
886 pdfdriver->set_parameter(pdfdriver,"fontdir", filename);
890 static PyMethodDef pdf2swf_methods[] =
893 {"open", (PyCFunction)f_open, METH_KEYWORDS, f_open_doc},
894 {"addfont", (PyCFunction)f_addfont, METH_KEYWORDS, f_addfont_doc},
895 {"addfontdir", (PyCFunction)f_addfontdir, METH_KEYWORDS, f_addfontdir_doc},
896 {"setoption", (PyCFunction)f_setoption, METH_KEYWORDS, f_setoption_doc},
897 {"verbose", (PyCFunction)f_verbose, METH_KEYWORDS, f_verbose_doc},
900 {"SWF", (PyCFunction)f_createSWF, METH_KEYWORDS, f_createSWF_doc},
901 {"ImageList", (PyCFunction)f_createImageList, METH_KEYWORDS, f_createImageList_doc},
902 {"PlainText", (PyCFunction)f_createPlainText, METH_KEYWORDS, f_createPlainText_doc},
903 {"PassThrough", (PyCFunction)f_createPassThrough, METH_KEYWORDS, f_createPassThrough_doc},
909 PyDoc_STRVAR(gfx_doc, \
910 "This module contains a PDF parser (based on xpdf) and a number of\n"
911 "rendering backends. In particular, it can extract text from PDF pages,\n"
912 "create bitmaps from them, or convert PDF files to SWF.\n"
913 "The latter functionality is similar to what is offered by swftools'\n"
914 "(http://www.swftools.org) pdf2swf utility, however more powerful-\n"
915 "You can also create individual SWF files from single pages of the PDF\n"
916 "or combine more than one page into a bigger PDF.\n"
921 initLog(0,0,0,0,0,2);
922 OutputClass.ob_type = &PyType_Type;
923 PageClass.ob_type = &PyType_Type;
924 DocClass.ob_type = &PyType_Type;
926 pdfdriver = gfxsource_pdf_create();
928 PyObject*module = Py_InitModule3("gfx", pdf2swf_methods, gfx_doc);
929 PyObject*module_dict = PyModule_GetDict(module);
931 PyDict_SetItemString(module_dict, "Doc", (PyObject*)&DocClass);
932 PyDict_SetItemString(module_dict, "Page", (PyObject*)&PageClass);
933 PyDict_SetItemString(module_dict, "Output", (PyObject*)&OutputClass);