a0139f66d5ef49528ba39e3dcdf6fef761eda295
[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*_tag)
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 = _tag;
147     tag->tagmap = tagmap_new();
148     return (PyObject*)tag;
149 }
150
151 static PyObject* f_SetBackgroundColor(PyObject* self, PyObject* args, PyObject* kwargs)
152 {
153     static char *kwlist[] = {"color", NULL};
154     int r=0,g=0,b=0;
155     TagObject*tag;
156     PyObject*color;
157     
158     tag = (TagObject*)tag_new();
159
160     /* 1st try- copy constructor */
161     if(!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &ColorClass, &color)) {
162         /* 2nd try- color's contructor */
163         color = f_Color(NULL, args, kwargs);
164     }
165     if(!color)
166         return NULL;
167
168     tag->tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
169     RGBA rgba = color_getRGBA(color);
170     swf_SetU8(tag->tag, rgba.r);
171     swf_SetU8(tag->tag, rgba.g);
172     swf_SetU8(tag->tag, rgba.b);
173     mylog(" %08x(%d) SetBackgroundColor(%02x,%02x,%02x)\n", (int)tag, tag->ob_refcnt, rgba.r, rgba.g, rgba.b);
174     return (PyObject*)tag;
175 }
176 //----------------------------------------------------------------------------
177 static PyObject* f_DefineFont(PyObject* self, PyObject* args, PyObject* kwargs)
178 {
179     static char *kwlist[] = {"filename", NULL};
180     char*filename = 0;
181     TagObject*tag;
182     SWFFONT* font;
183
184     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &filename))
185         return NULL;
186
187     font = swf_LoadFont(filename);
188     mylog("font=%08x",font);
189     if(!font) {
190         PyErr_SetString(PyExc_Exception, setError("Could not load %s", filename));
191         return NULL;
192     }
193
194     tag = (TagObject*)tag_new();
195     tag->font = font;
196     tag->tag = swf_InsertTag(0, ST_DEFINEFONT2);
197     tag->font->id = 0;
198     swf_FontSetDefine2(tag->tag, tag->font);
199     mylog("+%08x(%d) DefineFont\n", (int)tag, tag->ob_refcnt);
200     return (PyObject*)tag;
201 }
202 //----------------------------------------------------------------------------
203 static PyObject* f_Protect(PyObject* self, PyObject* args, PyObject* kwargs)
204 {
205     static char *kwlist[] = {"password", NULL};
206     char*password = 0;
207     TagObject*tag;
208
209     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &password))
210         return NULL;
211
212     tag = (TagObject*)tag_new();
213     tag->tag = swf_InsertTag(0, ST_PROTECT);
214     if(password) {
215         swf_SetPassword(tag->tag, password);
216     }
217     mylog("+%08x(%d) f_Protect", (int)tag, tag->ob_refcnt);
218     return (PyObject*)tag;
219 }
220 //----------------------------------------------------------------------------
221 static PyObject* f_DefineText(PyObject* self, PyObject* args, PyObject* kwargs)
222 {
223     static char *kwlist[] = {"font", "text", "size", "color", NULL};
224     TagObject*tag = 0;
225     char*text = 0;
226     int textlen = 0;
227     PyObject*unicode16;
228     PyObject*unicode8;
229     int size = 0;
230     RGBA rgba = {255,0,0,0};
231     PyObject*color = 0;
232     TagObject*font = 0;
233     SRECT r;
234
235     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!u#i|O!", kwlist, &TagClass, &font, &text, &textlen, &size, &ColorClass, &color))
236         return NULL;
237     
238     unicode16 = PyUnicode_DecodeUTF16(text, textlen*2, NULL, NULL);
239     unicode8 = PyUnicode_AsUTF8String(unicode16);
240     text = PyString_AS_STRING(unicode8);
241
242     if(color)
243         rgba = color_getRGBA(color);
244
245     mylog("DefineText: text = %s", text);
246     
247     tag = (TagObject*)tag_new();
248
249     /* notice: we do modify the (passed) font object here, 
250        for the swf_SetDefineText call, who will write out the font id. */
251     font->font->id = tagmap_add(tag->tagmap,(PyObject*)font); // add dependency on font
252
253     tag ->tag= swf_InsertTag(0, ST_DEFINETEXT2);
254     swf_SetU16(tag->tag, /*ID*/0);
255     r = swf_SetDefineText(tag->tag, font->font, &rgba, text, size);
256     mylog("+%08x(%d) DefineText %08x -> %08x\n", (int)tag, tag->ob_refcnt);
257
258     return (PyObject*)tag;
259 }
260 //----------------------------------------------------------------------------
261 static PyObject* f_PlaceObject(PyObject* self, PyObject* args, PyObject* kwargs)
262 {
263     static char *kwlist[] = {"character", "depth", "matrix", "colortransform", "ratio", "name", "clipdepth", "action", NULL};
264     TagObject*tag;
265     
266     TagObject*character = 0;
267     int depth;
268     int clipdepth = 0;
269     PyObject*matrix = 0;
270     PyObject*cxform = 0;
271     PyObject*action = 0;
272     int ratio = 0;
273     char* name = 0;
274     SWFPLACEOBJECT* po;
275     po = malloc(sizeof(SWFPLACEOBJECT));
276     memset(po, 0, sizeof(SWFPLACEOBJECT));
277
278     swf_GetPlaceObject(0, po);
279
280     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!i|O!O!isiO!", kwlist, 
281                 &TagClass, &character, 
282                 &depth, 
283                 &MatrixClass, &matrix, 
284                 &CXFormClass, &cxform,
285                 &ratio,
286                 &name,
287                 &clipdepth,
288                 &action
289                 ))
290         return NULL;
291     po->depth = depth;
292     po->id = /*ID*/ 0;
293     po->clipdepth = clipdepth;
294     po->ratio = ratio;
295     po->name = name;
296     if(clipdepth) po->clipdepth = clipdepth;
297     if(matrix) po->matrix = matrix_getMatrix(matrix);
298     if(cxform) po->cxform = colortransform_getCXForm(cxform);
299     if(action) po->actions = action_getAction(action);
300
301     tag = (TagObject*)tag_new();
302     tag->placeobject = po;
303     Py_INCREF(character);
304     tag->character = (PyObject*)character;
305     tag->tag= swf_InsertTag(0, ST_PLACEOBJECT2);
306
307     po->id = tagmap_add(tag->tagmap,(PyObject*)character);
308
309     swf_SetPlaceObject(tag->tag, po);
310     mylog("+%08x(%d) PlaceObject %08x\n", (int)tag, tag->ob_refcnt, character);
311     return (PyObject*)tag;
312 }
313
314 TAG* tag_getRAWTAG(PyObject*self)
315 {
316     TagObject*tag = (TagObject*)self;
317     return tag->tag;
318 }
319
320 /* serialize */
321 TAG* tag_getTAG(PyObject*self, TAG*prevTag, PyObject*tagmap)
322 {
323     mylog(" %08x(%d) tag_getTAG tagmap=%08x \n", (int)self, self->ob_refcnt, tagmap);
324     TagObject*tag = (TagObject*)self;
325     TAG* t = tag_getRAWTAG(self);
326     t->next = 0;
327     t->prev = prevTag;
328     if(prevTag)
329         prevTag->next = t;
330
331     int num = swf_GetNumUsedIDs(t);
332     int * positions = malloc(num*sizeof(int));
333     swf_GetUsedIDs(t, positions);
334     int i;
335     for(i=0;i<num;i++) {
336         int id = GET16(&t->data[positions[i]]);
337         PyObject* obj =  tagmap_id2obj(tag->tagmap, id);
338         mylog(" %08x(%d) tag_getTAG: id %d is %08x\n", (int)tag, tag->ob_refcnt, id, obj);
339         assert(obj!=NULL);
340         TAG*othertag = tag_getRAWTAG(obj);
341         int newid = tagmap_add(tagmap, obj);
342         mylog(" %08x(%d) tag_getTAG: othertag->tagid=%d, new ID: %d\n", (int)tag, tag->ob_refcnt, othertag->id, newid);
343
344         /* here comes the big hack- we define the *other* tags define ID.
345            This assumes that the other tag is not yet written or processed,
346            and we are, apart from the calling taglist, the only ones who know
347            about it.  */
348         swf_SetDefineID(othertag, newid);
349
350         PUT16(&t->data[positions[i]], newid);
351     }
352     return t;
353 }
354
355 PyObject* tag_getDependencies(PyObject*self)
356 {
357     mylog("+%08x(%d) tag_getDependencies\n", (int)self, self->ob_refcnt);
358     TagObject*tag = (TagObject*)self;
359     return tagmap_getObjectList(tag->tagmap);
360 }
361
362 PyTypeObject TagClass = 
363 {
364     PyObject_HEAD_INIT(NULL)
365     0,
366     tp_name: "Tag",
367     tp_basicsize: sizeof(TagObject),
368     tp_itemsize: 0,
369     tp_dealloc: tag_dealloc,
370     tp_print: 0,
371     tp_getattr: tag_getattr,
372 };
373 static PyMethodDef TagMethods[] = 
374 {
375     /* TAGS */
376     {"SetBackgroundColor", (PyCFunction)f_SetBackgroundColor, METH_KEYWORDS, "Create a SetBackGroundColor Tag."},
377     {"Protect", (PyCFunction)f_Protect, METH_KEYWORDS, "Create a Protect Tag."},
378     {"DefineFont", (PyCFunction)f_DefineFont, METH_KEYWORDS, "Create a DefineFont Tag."},
379     {"DefineText", (PyCFunction)f_DefineText, METH_KEYWORDS, "Create a DefineText Tag."},
380     {"PlaceObject", (PyCFunction)f_PlaceObject, METH_KEYWORDS, "Create a PlaceObject Tag."},
381     {NULL, NULL, 0, NULL}
382 };
383 PyMethodDef* tag_getMethods()
384 {
385     TagClass.ob_type = &PyType_Type;
386     return TagMethods;
387 }
388