several fixes
[swftools.git] / lib / python / tag.c
1 #include <Python.h>
2 #undef HAVE_STAT
3 #include "../rfxswf.h"
4 #include "../log.h"
5 #include "./pyutils.h"
6 #include "primitives.h"
7 #include "action.h"
8 #include "tag.h"
9 #include "tagmap.h"
10
11 //----------------------------------------------------------------------------
12 typedef struct {
13     PyObject_HEAD
14     PyObject* tagmap;
15     TAG*tag;
16     /* ST_DEFINEFONT*/
17     SWFFONT* font;
18     /* ST_PLACEOBJECT, ST_PLACEOBJECT2*/
19     SWFPLACEOBJECT* placeobject;
20     PyObject* character;
21 } TagObject;
22
23 //----------------------------------------------------------------------------
24 static void tag_dealloc(PyObject * self)
25 {
26     TagObject*tag = (TagObject*)self;
27     mylog(" %08x(%d) tag_dealoc\n", (int)self, self->ob_refcnt);
28     if(tag->placeobject) {
29         swf_PlaceObjectFree(tag->placeobject);
30         tag->placeobject = 0;
31     }
32     if(tag->font) {
33         swf_FontFree(tag->font);
34         tag->font = 0;
35     }
36     if(tag->character) {
37         Py_DECREF(tag->character);
38         tag->character = 0;
39     }
40     if(tag->tag) {
41         swf_DeleteTag(tag->tag);
42         tag->tag = 0;
43     }
44     Py_DECREF(tag->tagmap);
45     tag->tagmap = 0;
46     PyObject_Del(self);
47 }
48 //----------------------------------------------------------------------------
49 static PyObject* tag_setU8(PyObject * self, PyObject*other)
50 {
51     return NULL;
52 }
53 //----------------------------------------------------------------------------
54 static PyObject* tag_setbackgroundcolor_getrgb(PyObject * self, PyObject*other)
55 {
56     TagObject*tag = (TagObject*)self;
57     int r,g,b;
58     r = tag->tag->data[0];
59     g = tag->tag->data[1];
60     b = tag->tag->data[2];
61     return Py_BuildValue("(iii)", r,g,b);
62 }
63 //----------------------------------------------------------------------------
64
65 static struct tagfunctions {
66     int id;
67     PyMethodDef f[8];
68 } tagfunctions[] =
69 {
70  { 
71    ST_SETBACKGROUNDCOLOR, 
72    {{"getRGB", tag_setbackgroundcolor_getrgb, METH_VARARGS, "get's the color set by this tag"},
73     {NULL, NULL, 0, NULL}
74    }
75  }
76 };
77 static PyMethodDef common_tagfunctions[] =
78 {{"setU8", tag_setU8, METH_VARARGS, "sets a byte to the tag data"},
79  {NULL, NULL, 0, NULL}
80 };
81
82 static PyObject* tag_getattr(PyObject * self, char* a)
83 {
84     TagObject*tag = (TagObject*)self;
85     PyObject* ret = NULL;
86     int id =  tag->tag->id;
87     int t;
88
89     /* -- fields -- */
90     if(!strcmp(a, "id")) {
91         return Py_BuildValue("i", id);
92     }
93     if(!strcmp(a, "name")) {
94         char* name = swf_TagGetName(tag->tag);
95         return Py_BuildValue("s", name);
96     }
97 /*    if(!strcmp(a, "swf")) {
98         if(tag->swf == 0)
99             return Py_BuildValue("s", 0);
100         else {
101             Py_INCREF(tag->swf);
102             return tag->swf;
103         }
104     }*/
105     /* ------------ */
106    
107     /* search for a tag specific function */
108     for(t=0;t<sizeof(tagfunctions)/sizeof(tagfunctions[0]);t++)
109     {
110         if(id==tagfunctions[t].id) {
111             mylog(" %08x(%d) tag_getattr: id %d found\n", (int)self, self->ob_refcnt, id);
112             ret = Py_FindMethod(tagfunctions[t].f, self, a);
113             if(!ret) return ret;
114             ret = FindMethodMore(ret, common_tagfunctions, self, a);
115             mylog(" %08x(%d) tag_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret);
116             return ret;
117         }
118     }
119    
120     ret = Py_FindMethod(common_tagfunctions, self, a);
121
122     mylog(" %08x(%d) tag_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret);
123     return ret;
124 }
125 //----------------------------------------------------------------------------
126 //                     Tag Contructors
127 //----------------------------------------------------------------------------
128 PyObject* tag_new()
129 {
130     TagObject*tag = PyObject_New(TagObject, &TagClass);
131     mylog("+%08x(%d) tag_new\n", (int)tag, tag->ob_refcnt);
132     tag->font = 0;
133     tag->character = 0;
134     tag->placeobject = 0;
135     tag->tag = 0;
136     tag->tagmap = tagmap_new();
137     return (PyObject*)tag;
138 }
139 PyObject* tag_new2(TAG*t, PyObject* tagmap)
140 {
141     TagObject*tag = PyObject_New(TagObject, &TagClass);
142     mylog("+%08x(%d) tag_new\n", (int)tag, tag->ob_refcnt);
143     tag->font = 0;
144     tag->character = 0;
145     tag->placeobject = 0;
146     tag->tag = t;
147     tag->tagmap = tagmap_new();
148     
149     int num = swf_GetNumUsedIDs(t);
150     int * positions = malloc(num*sizeof(int));
151     swf_GetUsedIDs(t, positions);
152     int i;
153     for(i=0;i<num;i++) {
154         int id = GET16(&t->data[positions[i]]);
155         PyObject*obj = tagmap_id2obj(tagmap, id);
156         if(obj==NULL) {
157             PyErr_SetString(PyExc_Exception, setError("TagID %d not defined", id));
158             return NULL;
159         }
160         tagmap_addMapping(tag->tagmap, id, obj);
161     }
162     return (PyObject*)tag;
163 }
164
165 static PyObject* f_SetBackgroundColor(PyObject* self, PyObject* args, PyObject* kwargs)
166 {
167     static char *kwlist[] = {"color", NULL};
168     int r=0,g=0,b=0;
169     TagObject*tag;
170     PyObject*color;
171     
172     tag = (TagObject*)tag_new();
173
174     /* 1st try- copy constructor */
175     if(!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &ColorClass, &color)) {
176         /* 2nd try- color's contructor */
177         color = f_Color(NULL, args, kwargs);
178     }
179     if(!color)
180         return NULL;
181
182     tag->tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
183     RGBA rgba = color_getRGBA(color);
184     swf_SetU8(tag->tag, rgba.r);
185     swf_SetU8(tag->tag, rgba.g);
186     swf_SetU8(tag->tag, rgba.b);
187     mylog(" %08x(%d) SetBackgroundColor(%02x,%02x,%02x)\n", (int)tag, tag->ob_refcnt, rgba.r, rgba.g, rgba.b);
188     return (PyObject*)tag;
189 }
190 //----------------------------------------------------------------------------
191 static PyObject* f_DefineFont(PyObject* self, PyObject* args, PyObject* kwargs)
192 {
193     static char *kwlist[] = {"filename", NULL};
194     char*filename = 0;
195     TagObject*tag;
196     SWFFONT* font;
197
198     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &filename))
199         return NULL;
200
201     font = swf_LoadFont(filename);
202     mylog("font=%08x",font);
203     if(!font) {
204         PyErr_SetString(PyExc_Exception, setError("Could not load %s", filename));
205         return NULL;
206     }
207
208     tag = (TagObject*)tag_new();
209     tag->font = font;
210     tag->tag = swf_InsertTag(0, ST_DEFINEFONT2);
211     tag->font->id = 0;
212     swf_FontSetDefine2(tag->tag, tag->font);
213     mylog("+%08x(%d) DefineFont\n", (int)tag, tag->ob_refcnt);
214     return (PyObject*)tag;
215 }
216 //----------------------------------------------------------------------------
217 static PyObject* f_Protect(PyObject* self, PyObject* args, PyObject* kwargs)
218 {
219     static char *kwlist[] = {"password", NULL};
220     char*password = 0;
221     TagObject*tag;
222
223     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &password))
224         return NULL;
225
226     tag = (TagObject*)tag_new();
227     tag->tag = swf_InsertTag(0, ST_PROTECT);
228     if(password) {
229         swf_SetPassword(tag->tag, password);
230     }
231     mylog("+%08x(%d) f_Protect", (int)tag, tag->ob_refcnt);
232     return (PyObject*)tag;
233 }
234 //----------------------------------------------------------------------------
235 static PyObject* f_DefineText(PyObject* self, PyObject* args, PyObject* kwargs)
236 {
237     static char *kwlist[] = {"font", "text", "size", "color", NULL};
238     TagObject*tag = 0;
239     char*text = 0;
240     int textlen = 0;
241     PyObject*unicode16;
242     PyObject*unicode8;
243     int size = 0;
244     RGBA rgba = {255,0,0,0};
245     PyObject*color = 0;
246     TagObject*font = 0;
247     SRECT r;
248
249     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!u#i|O!", kwlist, &TagClass, &font, &text, &textlen, &size, &ColorClass, &color))
250         return NULL;
251     
252     unicode16 = PyUnicode_DecodeUTF16(text, textlen*2, NULL, NULL);
253     unicode8 = PyUnicode_AsUTF8String(unicode16);
254     text = PyString_AS_STRING(unicode8);
255
256     if(color)
257         rgba = color_getRGBA(color);
258
259     mylog("DefineText: text = %s", text);
260     
261     tag = (TagObject*)tag_new();
262
263     /* notice: we do modify the (passed) font object here, 
264        for the swf_SetDefineText call, who will write out the font id. */
265     font->font->id = tagmap_add(tag->tagmap,(PyObject*)font); // add dependency on font
266
267     tag ->tag= swf_InsertTag(0, ST_DEFINETEXT2);
268     swf_SetU16(tag->tag, /*ID*/0);
269     r = swf_SetDefineText(tag->tag, font->font, &rgba, text, size);
270     mylog("+%08x(%d) DefineText %08x -> %08x\n", (int)tag, tag->ob_refcnt);
271
272     return (PyObject*)tag;
273 }
274 //----------------------------------------------------------------------------
275 static PyObject* f_PlaceObject(PyObject* self, PyObject* args, PyObject* kwargs)
276 {
277     static char *kwlist[] = {"character", "depth", "matrix", "colortransform", "ratio", "name", "clipdepth", "action", NULL};
278     TagObject*tag;
279     
280     TagObject*character = 0;
281     int depth;
282     int clipdepth = 0;
283     PyObject*matrix = 0;
284     PyObject*cxform = 0;
285     PyObject*action = 0;
286     int ratio = 0;
287     char* name = 0;
288     SWFPLACEOBJECT* po;
289     po = malloc(sizeof(SWFPLACEOBJECT));
290     memset(po, 0, sizeof(SWFPLACEOBJECT));
291
292     swf_GetPlaceObject(0, po);
293
294     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!i|O!O!isiO!", kwlist, 
295                 &TagClass, &character, 
296                 &depth, 
297                 &MatrixClass, &matrix, 
298                 &CXFormClass, &cxform,
299                 &ratio,
300                 &name,
301                 &clipdepth,
302                 &action
303                 ))
304         return NULL;
305     po->depth = depth;
306     po->id = /*ID*/ 0;
307     po->clipdepth = clipdepth;
308     po->ratio = ratio;
309     po->name = name;
310     if(clipdepth) po->clipdepth = clipdepth;
311     if(matrix) po->matrix = matrix_getMatrix(matrix);
312     if(cxform) po->cxform = colortransform_getCXForm(cxform);
313     if(action) po->actions = action_getAction(action);
314
315     tag = (TagObject*)tag_new();
316     tag->placeobject = po;
317     Py_INCREF(character);
318     tag->character = (PyObject*)character;
319     tag->tag= swf_InsertTag(0, ST_PLACEOBJECT2);
320
321     po->id = tagmap_add(tag->tagmap,(PyObject*)character);
322
323     swf_SetPlaceObject(tag->tag, po);
324     mylog("+%08x(%d) PlaceObject %08x\n", (int)tag, tag->ob_refcnt, character);
325     return (PyObject*)tag;
326 }
327
328 TAG* tag_getRAWTAG(PyObject*self)
329 {
330     TagObject*tag = (TagObject*)self;
331     return tag->tag;
332 }
333
334 /* serialize */
335 TAG* tag_getTAG(PyObject*self, TAG*prevTag, PyObject*tagmap)
336 {
337     mylog(" %08x(%d) tag_getTAG tagmap=%08x \n", (int)self, self->ob_refcnt, tagmap);
338     TagObject*tag = (TagObject*)self;
339     TAG* t = tag_getRAWTAG(self);
340     t->next = 0;
341     t->prev = prevTag;
342     if(prevTag)
343         prevTag->next = t;
344
345     int num = swf_GetNumUsedIDs(t);
346     int * positions = malloc(num*sizeof(int));
347     swf_GetUsedIDs(t, positions);
348     int i;
349     for(i=0;i<num;i++) {
350         int id = GET16(&t->data[positions[i]]);
351         PyObject* obj =  tagmap_id2obj(tag->tagmap, id);
352         mylog(" %08x(%d) tag_getTAG: id %d is %08x\n", (int)tag, tag->ob_refcnt, id, obj);
353         assert(obj!=NULL);
354         TAG*othertag = tag_getRAWTAG(obj);
355         int newid = tagmap_add(tagmap, obj);
356         mylog(" %08x(%d) tag_getTAG: othertag->tagid=%d, new ID: %d\n", (int)tag, tag->ob_refcnt, othertag->id, newid);
357
358         /* here comes the big hack- we define the *other* tags define ID.
359            This assumes that the other tag is not yet written or processed,
360            and we are, apart from the calling taglist, the only ones who know
361            about it.  */
362         swf_SetDefineID(othertag, newid);
363
364         PUT16(&t->data[positions[i]], newid);
365     }
366     return t;
367 }
368
369 PyObject* tag_getDependencies(PyObject*self)
370 {
371     mylog("+%08x(%d) tag_getDependencies\n", (int)self, self->ob_refcnt);
372     TagObject*tag = (TagObject*)self;
373     return tagmap_getObjectList(tag->tagmap);
374 }
375
376 PyTypeObject TagClass = 
377 {
378     PyObject_HEAD_INIT(NULL)
379     0,
380     tp_name: "Tag",
381     tp_basicsize: sizeof(TagObject),
382     tp_itemsize: 0,
383     tp_dealloc: tag_dealloc,
384     tp_print: 0,
385     tp_getattr: tag_getattr,
386 };
387 static PyMethodDef TagMethods[] = 
388 {
389     /* TAGS */
390     {"SetBackgroundColor", (PyCFunction)f_SetBackgroundColor, METH_KEYWORDS, "Create a SetBackGroundColor Tag."},
391     {"Protect", (PyCFunction)f_Protect, METH_KEYWORDS, "Create a Protect Tag."},
392     {"DefineFont", (PyCFunction)f_DefineFont, METH_KEYWORDS, "Create a DefineFont Tag."},
393     {"DefineText", (PyCFunction)f_DefineText, METH_KEYWORDS, "Create a DefineText Tag."},
394     {"PlaceObject", (PyCFunction)f_PlaceObject, METH_KEYWORDS, "Create a PlaceObject Tag."},
395     {NULL, NULL, 0, NULL}
396 };
397 PyMethodDef* tag_getMethods()
398 {
399     TagClass.ob_type = &PyType_Type;
400     return TagMethods;
401 }
402