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