gfxsource now has a getinfo function
[swftools.git] / lib / python / gfx.c
1 /* gfx.c
2
3    Python wrapper for gfx convert
4
5    Part of the swftools package.
6
7    Copyright (c) 2003 Matthias Kramm <kramm@quiss.org>
8  
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.
13
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.
18
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 */
22
23 #include <Python.h>
24 #undef HAVE_STAT
25 #include "../devices/swf.h"
26 #include "../devices/render.h"
27 #include "../devices/rescale.h"
28 #include "../devices/text.h"
29 #include "../pdf/pdf.h"
30 #include "../log.h"
31 #include "../utf8.h"
32
33 gfxsource_t*pdfdriver;
34
35 staticforward PyTypeObject OutputClass;
36 staticforward PyTypeObject PageClass;
37 staticforward PyTypeObject DriverClass;
38
39 typedef struct {
40     PyObject_HEAD
41     gfxdevice_t*output_device;
42 } OutputObject;
43
44 typedef struct {
45     PyObject_HEAD
46     PyObject*parent;
47     gfxpage_t*page;
48     int nr;
49 } PageObject;
50
51 typedef struct {
52     PyObject_HEAD
53     gfxdocument_t*doc;
54     char*filename;
55 } DocObject;
56
57 static char* strf(char*format, ...)
58 {
59     char buf[1024];
60     int l;
61     va_list arglist;
62     va_start(arglist, format);
63     vsprintf(buf, format, arglist);
64     va_end(arglist);
65     return strdup(buf);
66 }
67 #define PY_ERROR(s,args...) (PyErr_SetString(PyExc_Exception, strf(s, ## args)),NULL)
68 #define PY_NONE Py_BuildValue("s", 0)
69
70 //---------------------------------------------------------------------
71 staticforward PyObject* output_save(PyObject* _self, PyObject* args, PyObject* kwargs);
72 staticforward PyObject* output_startpage(PyObject* _self, PyObject* args, PyObject* kwargs);
73 staticforward PyObject* output_endpage(PyObject* _self, PyObject* args, PyObject* kwargs);
74
75 static PyMethodDef output_methods[] =
76 {
77     /* Output functions */
78     {"save", (PyCFunction)output_save, METH_KEYWORDS, ""},
79     {"startpage", (PyCFunction)output_startpage, METH_KEYWORDS, ""},
80     {"endpage", (PyCFunction)output_endpage, METH_KEYWORDS, ""},
81     {0,0,0,0}
82 };
83 static PyObject* output_save(PyObject* _self, PyObject* args, PyObject* kwargs)
84 {
85     OutputObject* self = (OutputObject*)_self;
86     char*filename = 0;
87     static char *kwlist[] = {"filename", NULL};
88     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
89         return NULL;
90
91     gfxresult_t*result = self->output_device->finish(self->output_device);
92     self->output_device = 0;
93     if(result->save(result, filename) < 0) {
94         return PY_ERROR("Couldn't write to %s", filename);
95     }
96     result->destroy(result);
97     return PY_NONE;
98 }
99 static PyObject* output_startpage(PyObject* _self, PyObject* args, PyObject* kwargs)
100 {
101     OutputObject* self = (OutputObject*)_self;
102     int width=0, height=0;
103     if (!PyArg_ParseTuple(args, "ii", &width, &height))
104         return NULL;
105     self->output_device->startpage(self->output_device, width, height);
106     return PY_NONE;
107 }
108 static PyObject* output_endpage(PyObject* _self, PyObject* args, PyObject* kwargs)
109 {
110     OutputObject* self = (OutputObject*)_self;
111     if (!PyArg_ParseTuple(args, ""))
112         return NULL;
113     self->output_device->endpage(self->output_device);
114     return PY_NONE;
115 }
116 static PyObject* f_createSWF(PyObject* parent, PyObject* args, PyObject* kwargs)
117 {
118     static char *kwlist[] = {NULL};
119     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
120         return NULL;
121     OutputObject*self = PyObject_New(OutputObject, &OutputClass);
122     
123     self->output_device = malloc(sizeof(gfxdevice_t));
124     gfxdevice_swf_init(self->output_device);
125     return (PyObject*)self;
126 }
127 static PyObject* f_createImageList(PyObject* parent, PyObject* args, PyObject* kwargs)
128 {
129     static char *kwlist[] = {NULL};
130     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
131         return NULL;
132     OutputObject*self = PyObject_New(OutputObject, &OutputClass);
133     
134     self->output_device = malloc(sizeof(gfxdevice_t));
135     gfxdevice_render_init(self->output_device);
136     return (PyObject*)self;
137 }
138 static PyObject* f_createPlainText(PyObject* parent, PyObject* args, PyObject* kwargs)
139 {
140     static char *kwlist[] = {NULL};
141     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
142         return NULL;
143     OutputObject*self = PyObject_New(OutputObject, &OutputClass);
144     
145     self->output_device = malloc(sizeof(gfxdevice_t));
146     gfxdevice_text_init(self->output_device);
147     return (PyObject*)self;
148 }
149
150
151 static void output_dealloc(PyObject* _self) {
152     OutputObject* self = (OutputObject*)_self;
153
154     if(self->output_device) {
155         gfxresult_t*result = self->output_device->finish(self->output_device);
156         result->destroy(result);result=0;
157         self->output_device = 0;
158     }
159     
160     PyObject_Del(self);
161 }
162 static PyObject* output_getattr(PyObject * _self, char* a)
163 {
164     OutputObject*self = (OutputObject*)_self;
165     
166 /*    if(!strcmp(a, "x1")) {
167         return PyInt_FromLong(self->output_device->x1);
168     } else if(!strcmp(a, "y1")) {
169         return PyInt_FromLong(self->output_device->y1);
170     } else if(!strcmp(a, "x2")) {
171         return PyInt_FromLong(self->output_device->x2);
172     } else if(!strcmp(a, "y2")) {
173         return PyInt_FromLong(self->output_device->y2);
174     }*/
175     
176     return Py_FindMethod(output_methods, _self, a);
177 }
178 static int output_setattr(PyObject * _self, char* a, PyObject * o) 
179 {
180     OutputObject*self = (OutputObject*)_self;
181     if(!PyString_Check(o))
182         return -1;
183     char*value = PyString_AsString(o);
184     self->output_device->setparameter(self->output_device, a, value);
185     return -1;
186 }
187 static int output_print(PyObject * _self, FILE *fi, int flags)
188 {
189     OutputObject*self = (OutputObject*)_self;
190     fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
191     return 0;
192 }
193
194 //---------------------------------------------------------------------
195 staticforward PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs);
196 staticforward PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs);
197
198 static PyMethodDef page_methods[] =
199 {
200     /* Page functions */
201     {"render", (PyCFunction)page_render, METH_KEYWORDS, ""},
202     {"asImage", (PyCFunction)page_asImage, METH_KEYWORDS, ""},
203     {0,0,0,0}
204 };
205 static PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs)
206 {
207     PageObject* self = (PageObject*)_self; 
208     
209     static char *kwlist[] = {"dev", "move", "clip", NULL};
210     OutputObject*output = 0;
211     PyObject*move=0;
212     PyObject*clip=0;
213     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OO", kwlist, &OutputClass, &output,
214                 &move,&clip
215                 ))
216         return NULL;
217
218     int x=0,y=0;
219     int cx1=0,cy1=0,cx2=0,cy2=0;
220
221     if(move) {
222         if (!PyArg_ParseTuple(move, "ii", &x,&y))
223             return NULL;
224     }
225     if(clip) {
226         if (!PyArg_ParseTuple(clip, "iiii", &cx1,&cy1,&cx2,&cy2))
227             return NULL;
228     }
229
230     if(x|y|cx1|cx2|cy1|cy2)
231         self->page->rendersection(self->page, output->output_device,x,y,cx1,cy1,cx2,cy2);
232     else
233         self->page->render(self->page, output->output_device);
234     return PY_NONE;
235 }
236
237 static PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs)
238 {
239     PageObject* self = (PageObject*)_self; 
240     
241     static char *kwlist[] = {"width", "height", NULL};
242     int width=0,height=0;
243     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &width, &height))
244         return NULL;
245
246     if(!width || !height) {
247         return PY_ERROR("invalid dimensions: %dx%d", width,height);
248     }
249
250     gfxdevice_t dev1,dev2;
251     gfxdevice_render_init(&dev1);
252     dev1.setparameter(&dev1, "antialise", "2");
253     gfxdevice_rescale_init(&dev2, &dev1, width, height);
254     dev2.startpage(&dev2, self->page->width, self->page->height);
255     self->page->render(self->page, &dev2);
256     dev2.endpage(&dev2);
257     gfxresult_t*result = dev2.finish(&dev2);
258     gfximage_t*img = (gfximage_t*)result->get(result,"page0");
259     int l = img->width*img->height;
260     unsigned char*data = malloc(img->width*img->height*3);
261     int s,t;
262     for(t=0,s=0;t<l;s+=3,t++) {
263         data[s+0] = img->data[t].r;
264         data[s+1] = img->data[t].g;
265         data[s+2] = img->data[t].b;
266     }
267     result->destroy(result);
268     return PyString_FromStringAndSize((char*)data,img->width*img->height*3);
269 }
270
271 static void page_dealloc(PyObject* _self) {
272     PageObject* self = (PageObject*)_self; 
273     if(self->page) {
274         self->page->destroy(self->page);
275         self->page=0;
276     }
277     if(self->parent) {
278         Py_DECREF(self->parent);
279         self->parent=0;
280     }
281     
282     PyObject_Del(self);
283 }
284 static PyObject* page_getattr(PyObject * _self, char* a)
285 {
286     PageObject*self = (PageObject*)_self;
287     
288     if(!strcmp(a, "size")) {
289         return Py_BuildValue("(ii)", self->page->width, self->page->height);
290     } if(!strcmp(a, "doc")) {
291         Py_INCREF(self->parent);
292         return self->parent;
293     } if(!strcmp(a, "nr")) {
294         return PyInt_FromLong(self->nr);
295     } else if(!strcmp(a, "width")) {
296         return PyInt_FromLong(self->page->width);
297     } else if(!strcmp(a, "height")) {
298         return PyInt_FromLong(self->page->height);
299     }
300     return Py_FindMethod(page_methods, _self, a);
301 }
302 static int page_setattr(PyObject * self, char* a, PyObject * o) {
303     return -1;
304 }
305 static int page_print(PyObject * _self, FILE *fi, int flags)
306 {
307     PageObject*self = (PageObject*)_self;
308     fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
309     return 0;
310 }
311
312 //---------------------------------------------------------------------
313
314 staticforward PyObject* doc_getPage(PyObject* parent, PyObject* args, PyObject* kwargs);
315 staticforward PyObject* doc_getInfo(PyObject* parent, PyObject* args, PyObject* kwargs);
316
317 static PyMethodDef doc_methods[] =
318 {
319     /* PDF functions */
320     {"getPage", (PyCFunction)doc_getPage, METH_KEYWORDS, ""},
321     {"getInfo", (PyCFunction)doc_getInfo, METH_KEYWORDS, ""},
322     {0,0,0,0}
323 };
324
325 static PyObject* doc_getPage(PyObject* _self, PyObject* args, PyObject* kwargs)
326 {
327     DocObject* self = (DocObject*)_self;
328
329     static char *kwlist[] = {"nr", NULL};
330     int pagenr = 0;
331     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &pagenr))
332         return NULL;
333
334     PageObject*page = PyObject_New(PageObject, &PageClass);
335     page->page = self->doc->getpage(self->doc, pagenr);
336     page->nr = pagenr;
337     page->parent = _self;
338     Py_INCREF(page->parent);
339     if(!page->page) {
340         PyObject_Del(page);
341         return PY_ERROR("Couldn't extract page %d", pagenr);
342     }
343     return (PyObject*)page;
344 }
345
346 static PyObject* doc_getInfo(PyObject* _self, PyObject* args, PyObject* kwargs)
347 {
348     DocObject* self = (DocObject*)_self;
349
350     static char *kwlist[] = {"key", NULL};
351     char*key = 0;
352     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &key))
353         return NULL;
354
355     char*s = self->doc->getinfo(self->doc, key);
356     return PyString_FromString(s);
357 }
358
359 static PyObject* f_open(PyObject* parent, PyObject* args, PyObject* kwargs)
360 {
361     static char *kwlist[] = {"type", "filename", NULL};
362     char*filename;
363     char*type;
364     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &type, &filename))
365         return NULL;
366
367     DocObject*self = PyObject_New(DocObject, &DriverClass);
368    
369     if(!strcmp(type,"pdf"))
370         self->doc = pdfdriver->open(filename);
371     else
372         return PY_ERROR("Unknown type %s", type);
373
374     if(!self->doc) {
375         PyObject_Del(self);
376         return PY_ERROR("Couldn't open %s", filename);
377     }
378     self->filename = strdup(filename);
379     return (PyObject*)self;
380 }
381 static void doc_dealloc(PyObject* _self) {
382     DocObject* self = (DocObject*)_self;
383     if(self->doc) {
384         self->doc->destroy(self->doc);
385         self->doc=0;
386     }
387     if(self->filename) {
388         free(self->filename);self->filename=0;
389     }
390     PyObject_Del(self);
391 }
392 static PyObject* doc_getattr(PyObject * _self, char* a)
393 {
394     DocObject*self = (DocObject*)_self;
395     if(!strcmp(a, "pages")) {
396         return PyInt_FromLong(self->doc->num_pages);
397     }
398     if(!strcmp(a, "filename")) {
399         return PyString_FromString(self->filename);
400     }
401     return Py_FindMethod(doc_methods, _self, a);
402 }
403 static int doc_setattr(PyObject * self, char* a, PyObject * o) {
404     return -1;
405 }
406 static int doc_print(PyObject * _self, FILE *fi, int flags)
407 {
408     DocObject*self = (DocObject*)_self;
409     fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
410     return 0;
411 }
412
413 //---------------------------------------------------------------------
414
415 static PyTypeObject OutputClass =
416 {
417     PyObject_HEAD_INIT(NULL)
418     0,
419     tp_name: "Output",
420     tp_basicsize: sizeof(OutputObject),
421     tp_itemsize: 0,
422     tp_dealloc: output_dealloc,
423     tp_print: output_print,
424     tp_getattr: output_getattr,
425     tp_setattr: output_setattr,
426 };
427 static PyTypeObject PageClass =
428 {
429     PyObject_HEAD_INIT(NULL)
430     0,
431     tp_name: "Page",
432     tp_basicsize: sizeof(PageObject),
433     tp_itemsize: 0,
434     tp_dealloc: page_dealloc,
435     tp_print: page_print,
436     tp_getattr: page_getattr,
437     tp_setattr: page_setattr,
438 };
439 static PyTypeObject DriverClass =
440 {
441     PyObject_HEAD_INIT(NULL)
442     0,
443     tp_name: "PDF",
444     tp_basicsize: sizeof(DocObject),
445     tp_itemsize: 0,
446     tp_dealloc: doc_dealloc,
447     tp_print: doc_print,
448     tp_getattr: doc_getattr,
449     tp_setattr: doc_setattr,
450 };
451
452 //=====================================================================
453
454 static PyObject* f_setoption(PyObject* self, PyObject* args, PyObject* kwargs)
455 {
456     static char *kwlist[] = {"key", "value", NULL};
457     char*key=0,*value=0;
458     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key, &value))
459         return NULL;
460     pdfdriver->set_parameter(key,value);
461     return PY_NONE;
462 }
463
464 static PyObject* f_verbose(PyObject* self, PyObject* args, PyObject* kwargs)
465 {
466     static char *kwlist[] = {"val", NULL};
467     int val;
468     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &val))
469         return NULL;
470     setConsoleLogging(val);
471     return PY_NONE;
472 }
473
474 static PyObject* f_addfont(PyObject* self, PyObject* args, PyObject* kwargs)
475 {
476     static char *kwlist[] = {"filename", NULL};
477     char*filename=0;
478     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
479         return NULL;
480     pdfdriver->set_parameter("font", filename);
481     return PY_NONE;
482 }
483
484 static PyObject* f_addfontdir(PyObject* self, PyObject* args, PyObject* kwargs)
485 {
486     static char *kwlist[] = {"filename", NULL};
487     char*filename=0;
488     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
489         return NULL;
490     pdfdriver->set_parameter("fontdir", filename);
491     return PY_NONE;
492 }
493
494 static PyMethodDef pdf2swf_methods[] =
495 {
496     /* sources */
497     {"open", (PyCFunction)f_open, METH_KEYWORDS, ""},
498     {"addfont", (PyCFunction)f_addfont, METH_KEYWORDS, ""},
499     {"addfontdir", (PyCFunction)f_addfontdir, METH_KEYWORDS, ""},
500     {"setoption", (PyCFunction)f_setoption, METH_KEYWORDS, ""},
501     {"verbose", (PyCFunction)f_verbose, METH_KEYWORDS, ""},
502
503     /* devices */
504     {"SWF", (PyCFunction)f_createSWF, METH_KEYWORDS, ""},
505     {"ImageList", (PyCFunction)f_createImageList, METH_KEYWORDS, ""},
506     {"PlainText", (PyCFunction)f_createPlainText, METH_KEYWORDS, ""},
507
508     /* sentinel */
509     {0, 0, 0, 0}
510 };
511
512 void initgfx(void)
513 {
514     initLog(0,0,0,0,0,2);
515     OutputClass.ob_type = &PyType_Type;
516     PageClass.ob_type = &PyType_Type;
517     DriverClass.ob_type = &PyType_Type;
518  
519     pdfdriver = gfxsource_pdf_create();
520     
521     PyObject*module = Py_InitModule("gfx", pdf2swf_methods);
522 }