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