added more devices
[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_startframe(PyObject* _self, PyObject* args, PyObject* kwargs);
73 staticforward PyObject* output_endframe(PyObject* _self, PyObject* args, PyObject* kwargs);
74
75 static PyMethodDef output_methods[] =
76 {
77     /* Output functions */
78     {"save", (PyCFunction)output_save, METH_KEYWORDS, ""},
79     {"startframe", (PyCFunction)output_startframe, METH_KEYWORDS, ""},
80     {"endframe", (PyCFunction)output_endframe, 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     if(result->save(result, filename) < 0) {
93         return PY_ERROR("Couldn't write to %s", filename);
94     }
95     result->destroy(result);
96     return PY_NONE;
97 }
98 static PyObject* output_startframe(PyObject* _self, PyObject* args, PyObject* kwargs)
99 {
100     OutputObject* self = (OutputObject*)_self;
101     int width=0, height=0;
102     if (!PyArg_ParseTuple(args, "ii", &width, &height))
103         return NULL;
104     self->output_device->startpage(self->output_device, width, height);
105     return PY_NONE;
106 }
107 static PyObject* output_endframe(PyObject* _self, PyObject* args, PyObject* kwargs)
108 {
109     OutputObject* self = (OutputObject*)_self;
110     if (!PyArg_ParseTuple(args, ""))
111         return NULL;
112     self->output_device->endpage(self->output_device);
113     return PY_NONE;
114 }
115 static PyObject* f_createSWF(PyObject* parent, PyObject* args, PyObject* kwargs)
116 {
117     static char *kwlist[] = {NULL};
118     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
119         return NULL;
120     OutputObject*self = PyObject_New(OutputObject, &OutputClass);
121     
122     self->output_device = malloc(sizeof(gfxdevice_t));
123     gfxdevice_swf_init(self->output_device);
124     return (PyObject*)self;
125 }
126 static PyObject* f_createImageList(PyObject* parent, PyObject* args, PyObject* kwargs)
127 {
128     static char *kwlist[] = {NULL};
129     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
130         return NULL;
131     OutputObject*self = PyObject_New(OutputObject, &OutputClass);
132     
133     self->output_device = malloc(sizeof(gfxdevice_t));
134     gfxdevice_render_init(self->output_device);
135     return (PyObject*)self;
136 }
137 static PyObject* f_createPlainText(PyObject* parent, PyObject* args, PyObject* kwargs)
138 {
139     static char *kwlist[] = {NULL};
140     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
141         return NULL;
142     OutputObject*self = PyObject_New(OutputObject, &OutputClass);
143     
144     self->output_device = malloc(sizeof(gfxdevice_t));
145     gfxdevice_text_init(self->output_device);
146     return (PyObject*)self;
147 }
148
149
150 static void output_dealloc(PyObject* _self) {
151     OutputObject* self = (OutputObject*)_self;
152
153     if(self->output_device) {
154         gfxresult_t*result = self->output_device->finish(self->output_device);
155         result->destroy(result);result=0;
156         self->output_device = 0;
157     }
158     
159     PyObject_Del(self);
160 }
161 static PyObject* output_getattr(PyObject * _self, char* a)
162 {
163     OutputObject*self = (OutputObject*)_self;
164     
165 /*    if(!strcmp(a, "x1")) {
166         return PyInt_FromLong(self->output_device->x1);
167     } else if(!strcmp(a, "y1")) {
168         return PyInt_FromLong(self->output_device->y1);
169     } else if(!strcmp(a, "x2")) {
170         return PyInt_FromLong(self->output_device->x2);
171     } else if(!strcmp(a, "y2")) {
172         return PyInt_FromLong(self->output_device->y2);
173     }*/
174     
175     return Py_FindMethod(output_methods, _self, a);
176 }
177 static int output_setattr(PyObject * _self, char* a, PyObject * o) 
178 {
179     OutputObject*self = (OutputObject*)_self;
180     if(!PyString_Check(o))
181         return -1;
182     char*value = PyString_AsString(o);
183     self->output_device->setparameter(self->output_device, a, value);
184     return -1;
185 }
186 static int output_print(PyObject * _self, FILE *fi, int flags)
187 {
188     OutputObject*self = (OutputObject*)_self;
189     fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
190     return 0;
191 }
192
193 //---------------------------------------------------------------------
194 staticforward PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs);
195 staticforward PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs);
196
197 static PyMethodDef page_methods[] =
198 {
199     /* Page functions */
200     {"render", (PyCFunction)page_render, METH_KEYWORDS, ""},
201     {"asImage", (PyCFunction)page_asImage, METH_KEYWORDS, ""},
202     {0,0,0,0}
203 };
204 static PyObject* page_render(PyObject* _self, PyObject* args, PyObject* kwargs)
205 {
206     PageObject* self = (PageObject*)_self; 
207     
208     static char *kwlist[] = {"dev", "move", "clip", NULL};
209     OutputObject*output = 0;
210     PyObject*move=0;
211     PyObject*clip=0;
212     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OO", kwlist, &OutputClass, &output,
213                 &move,&clip
214                 ))
215         return NULL;
216
217     int x=0,y=0;
218     int cx1=0,cy1=0,cx2=0,cy2=0;
219
220     if(move) {
221         if (!PyArg_ParseTuple(move, "ii", &x,&y))
222             return NULL;
223     }
224     if(clip) {
225         if (!PyArg_ParseTuple(clip, "iiii", &cx1,&cy1,&cx2,&cy2))
226             return NULL;
227     }
228
229     if(x|y|cx1|cx2|cy1|cy2)
230         self->page->rendersection(self->page, output->output_device,x,y,cx1,cy1,cx2,cy2);
231     else
232         self->page->render(self->page, output->output_device);
233     return PY_NONE;
234 }
235
236 static PyObject* page_asImage(PyObject* _self, PyObject* args, PyObject* kwargs)
237 {
238     PageObject* self = (PageObject*)_self; 
239     
240     static char *kwlist[] = {"width", "height", NULL};
241     int width=0,height=0;
242     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &width, &height))
243         return NULL;
244
245     if(!width || !height) {
246         return PY_ERROR("invalid dimensions: %dx%d", width,height);
247     }
248
249     gfxdevice_t dev1,dev2;
250     gfxdevice_render_init(&dev1);
251     dev1.setparameter(&dev1, "antialise", "2");
252     gfxdevice_rescale_init(&dev2, &dev1, width, height);
253     dev2.startpage(&dev2, self->page->width, self->page->height);
254     self->page->render(self->page, &dev2);
255     dev2.endpage(&dev2);
256     gfxresult_t*result = dev2.finish(&dev2);
257     gfximage_t*img = (gfximage_t*)result->get(result,"page0");
258     int l = img->width*img->height;
259     unsigned char*data = malloc(img->width*img->height*3);
260     int s,t;
261     for(t=0,s=0;t<l;s+=3,t++) {
262         data[s+0] = img->data[t].r;
263         data[s+1] = img->data[t].g;
264         data[s+2] = img->data[t].b;
265     }
266     result->destroy(result);
267     return PyString_FromStringAndSize((char*)data,img->width*img->height*3);
268 }
269
270 static void page_dealloc(PyObject* _self) {
271     PageObject* self = (PageObject*)_self; 
272     if(self->page) {
273         self->page->destroy(self->page);
274         self->page=0;
275     }
276     if(self->parent) {
277         Py_DECREF(self->parent);
278         self->parent=0;
279     }
280     
281     PyObject_Del(self);
282 }
283 static PyObject* page_getattr(PyObject * _self, char* a)
284 {
285     PageObject*self = (PageObject*)_self;
286     
287     if(!strcmp(a, "size")) {
288         return Py_BuildValue("(ii)", self->page->width, self->page->height);
289     } if(!strcmp(a, "doc")) {
290         Py_INCREF(self->parent);
291         return self->parent;
292     } if(!strcmp(a, "nr")) {
293         return PyInt_FromLong(self->nr);
294     } else if(!strcmp(a, "width")) {
295         return PyInt_FromLong(self->page->width);
296     } else if(!strcmp(a, "height")) {
297         return PyInt_FromLong(self->page->height);
298     }
299     return Py_FindMethod(page_methods, _self, a);
300 }
301 static int page_setattr(PyObject * self, char* a, PyObject * o) {
302     return -1;
303 }
304 static int page_print(PyObject * _self, FILE *fi, int flags)
305 {
306     PageObject*self = (PageObject*)_self;
307     fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
308     return 0;
309 }
310
311 //---------------------------------------------------------------------
312
313 staticforward PyObject* doc_getPage(PyObject* parent, PyObject* args, PyObject* kwargs);
314
315 static PyMethodDef doc_methods[] =
316 {
317     /* PDF functions */
318     {"getPage", (PyCFunction)doc_getPage, METH_KEYWORDS, ""},
319     {0,0,0,0}
320 };
321
322 static PyObject* doc_getPage(PyObject* _self, PyObject* args, PyObject* kwargs)
323 {
324     DocObject* self = (DocObject*)_self;
325
326     static char *kwlist[] = {"nr", NULL};
327     int pagenr = 0;
328     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &pagenr))
329         return NULL;
330
331     PageObject*page = PyObject_New(PageObject, &PageClass);
332     page->page = self->doc->getpage(self->doc, pagenr);
333     page->nr = pagenr;
334     page->parent = _self;
335     Py_INCREF(page->parent);
336     if(!page->page) {
337         PyObject_Del(page);
338         return PY_ERROR("Couldn't extract page %d", pagenr);
339     }
340     return (PyObject*)page;
341 }
342
343 static PyObject* f_open(PyObject* parent, PyObject* args, PyObject* kwargs)
344 {
345     static char *kwlist[] = {"type", "filename", NULL};
346     char*filename;
347     char*type;
348     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &type, &filename))
349         return NULL;
350
351     DocObject*self = PyObject_New(DocObject, &DriverClass);
352    
353     if(!strcmp(type,"pdf"))
354         self->doc = pdfdriver->open(filename);
355     else
356         return PY_ERROR("Unknown type %s", type);
357
358     if(!self->doc) {
359         PyObject_Del(self);
360         return PY_ERROR("Couldn't open %s", filename);
361     }
362     self->filename = strdup(filename);
363     return (PyObject*)self;
364 }
365 static void doc_dealloc(PyObject* _self) {
366     DocObject* self = (DocObject*)_self;
367     if(self->doc) {
368         self->doc->destroy(self->doc);
369         self->doc=0;
370     }
371     if(self->filename) {
372         free(self->filename);self->filename=0;
373     }
374     PyObject_Del(self);
375 }
376 static PyObject* doc_getattr(PyObject * _self, char* a)
377 {
378     DocObject*self = (DocObject*)_self;
379     if(!strcmp(a, "pages")) {
380         return PyInt_FromLong(self->doc->num_pages);
381     }
382     if(!strcmp(a, "filename")) {
383         return PyString_FromString(self->filename);
384     }
385     return Py_FindMethod(doc_methods, _self, a);
386 }
387 static int doc_setattr(PyObject * self, char* a, PyObject * o) {
388     return -1;
389 }
390 static int doc_print(PyObject * _self, FILE *fi, int flags)
391 {
392     DocObject*self = (DocObject*)_self;
393     fprintf(fi, "%08x(%d)", (int)_self, _self?_self->ob_refcnt:0);
394     return 0;
395 }
396
397 //---------------------------------------------------------------------
398
399 static PyTypeObject OutputClass =
400 {
401     PyObject_HEAD_INIT(NULL)
402     0,
403     tp_name: "Output",
404     tp_basicsize: sizeof(OutputObject),
405     tp_itemsize: 0,
406     tp_dealloc: output_dealloc,
407     tp_print: output_print,
408     tp_getattr: output_getattr,
409     tp_setattr: output_setattr,
410 };
411 static PyTypeObject PageClass =
412 {
413     PyObject_HEAD_INIT(NULL)
414     0,
415     tp_name: "Page",
416     tp_basicsize: sizeof(PageObject),
417     tp_itemsize: 0,
418     tp_dealloc: page_dealloc,
419     tp_print: page_print,
420     tp_getattr: page_getattr,
421     tp_setattr: page_setattr,
422 };
423 static PyTypeObject DriverClass =
424 {
425     PyObject_HEAD_INIT(NULL)
426     0,
427     tp_name: "PDF",
428     tp_basicsize: sizeof(DocObject),
429     tp_itemsize: 0,
430     tp_dealloc: doc_dealloc,
431     tp_print: doc_print,
432     tp_getattr: doc_getattr,
433     tp_setattr: doc_setattr,
434 };
435
436 //=====================================================================
437
438 static PyObject* f_setoption(PyObject* self, PyObject* args, PyObject* kwargs)
439 {
440     static char *kwlist[] = {"key", "value", NULL};
441     char*key=0,*value=0;
442     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key, &value))
443         return NULL;
444     pdfdriver->set_parameter(key,value);
445     return PY_NONE;
446 }
447
448 static PyObject* f_addfont(PyObject* self, PyObject* args, PyObject* kwargs)
449 {
450     static char *kwlist[] = {"filename", NULL};
451     char*filename=0;
452     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
453         return NULL;
454     pdfdriver->set_parameter("font", filename);
455     return PY_NONE;
456 }
457
458 static PyObject* f_addfontdir(PyObject* self, PyObject* args, PyObject* kwargs)
459 {
460     static char *kwlist[] = {"filename", NULL};
461     char*filename=0;
462     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &filename))
463         return NULL;
464     pdfdriver->set_parameter("fontdir", filename);
465     return PY_NONE;
466 }
467
468 static PyMethodDef pdf2swf_methods[] =
469 {
470     /* sources */
471     {"open", (PyCFunction)f_open, METH_KEYWORDS, ""},
472     {"addfont", (PyCFunction)f_addfont, METH_KEYWORDS, ""},
473     {"addfontdir", (PyCFunction)f_addfontdir, METH_KEYWORDS, ""},
474     {"setoption", (PyCFunction)f_setoption, METH_KEYWORDS, ""},
475
476     /* devices */
477     {"SWF", (PyCFunction)f_createSWF, METH_KEYWORDS, ""},
478     {"ImageList", (PyCFunction)f_createImageList, METH_KEYWORDS, ""},
479     {"PlainText", (PyCFunction)f_createPlainText, METH_KEYWORDS, ""},
480
481     /* sentinel */
482     {0, 0, 0, 0}
483 };
484
485 void initgfx(void)
486 {
487     initLog(0,0,0,0,0,2);
488     OutputClass.ob_type = &PyType_Type;
489     PageClass.ob_type = &PyType_Type;
490     DriverClass.ob_type = &PyType_Type;
491  
492     pdfdriver = gfxsource_pdf_create();
493     
494     PyObject*module = Py_InitModule("gfx", pdf2swf_methods);
495 }