6 #include "primitives.h"
11 //----------------------------------------------------------------------------
13 typedef struct _TagObject {
15 tag_internals_t internals;
18 //----------------------------------------------------------------------------
19 static PyMethodDef generic_methods[] =
23 static tag_internals_t generic_tag =
28 tagfunctions: generic_methods,
31 //----------------------------------------------------------------------------
33 static struct tag_parser {
36 struct tag_parser* next;
38 static char parsers_initialized = 0;
40 void register_tag(int id, tag_internals_t*spec)
42 assert(id>=0 && id<1024);
43 if(!parsers_initialized) {
44 memset(tag_parsers, 0, sizeof(tag_parsers));
45 parsers_initialized = 1;
47 tag_parsers[id].id = id;
48 tag_parsers[id].spec = spec;
51 static tag_internals_t* get_parser(int id)
53 if(parsers_initialized<2) {
55 struct tag_parser*last = &tag_parsers[0];
57 if(tag_parsers[t].spec) {
58 last->next = &tag_parsers[t];
59 last = &tag_parsers[t];
62 parsers_initialized = 2;
64 assert(id>=0 && id<1024);
65 return tag_parsers[id].spec;
68 //----------------------------------------------------------------------------
69 static void tag_dealloc(PyObject * self)
71 TagObject*tag = (TagObject*)self;
72 if(tag->internals.tag)
73 mylog("-%08x(%d) tag_dealoc [%s]\n", (int)self, self->ob_refcnt, swf_TagGetName(tag->internals.tag));
75 mylog("-%08x(%d) tag_dealoc [?]\n", (int)self, self->ob_refcnt);
76 if(tag->internals.dealloc) {
77 if(!tag->internals.data)
78 mylog("-%08x(%d) tag_dealoc: Warning: calling dealloc without any data(?)\n", (int)self, self->ob_refcnt);
79 tag->internals.dealloc(&tag->internals);
81 if(tag->internals.data) {
82 free(tag->internals.data);
83 tag->internals.data = 0;
85 if(tag->internals.tag) {
86 swf_DeleteTag(tag->internals.tag);
87 tag->internals.tag = 0;
89 Py_DECREF(tag->internals.tagmap);
90 tag->internals.tagmap = 0;
93 //----------------------------------------------------------------------------
94 static int fillTAG(PyObject*self)
96 TagObject*tag = (TagObject*)self;
97 if(tag->internals.tag)
99 if(!tag->internals.fillTAG) {
100 PyErr_SetString(PyExc_Exception, setError("No way to fill TAG with data"));
103 if(!tag->internals.fillTAG(&tag->internals)) {
104 return 0; // pass through exception
106 if(!tag->internals.tag) {
107 PyErr_SetString(PyExc_Exception, setError("Couldn't fill tag"));
112 //----------------------------------------------------------------------------
113 static PyObject* tag_isShape(PyObject * _self, PyObject*args)
115 TagObject*self = (TagObject*)_self;
116 if(!PyArg_ParseTuple(args, "")) return NULL;
117 if(!fillTAG((PyObject*)self)) return NULL;
118 return PyInt_FromLong(swf_isShapeTag(self->internals.tag));
120 static PyObject* tag_isImage(PyObject * _self, PyObject*args)
122 TagObject*self = (TagObject*)_self;
123 if(!PyArg_ParseTuple(args, "")) return NULL;
124 if(!fillTAG((PyObject*)self)) return NULL;
125 return PyInt_FromLong(swf_isImageTag(self->internals.tag));
127 static PyObject* tag_isDefiningTag(PyObject * _self, PyObject*args)
129 TagObject*self = (TagObject*)_self;
130 if(!PyArg_ParseTuple(args, "")) return NULL;
131 if(!fillTAG((PyObject*)self)) return NULL;
132 return PyInt_FromLong(swf_isDefiningTag(self->internals.tag));
134 static PyObject* tag_getBBox(PyObject * _self, PyObject*args)
136 TagObject*self = (TagObject*)_self;
137 if(!PyArg_ParseTuple(args, "")) return NULL;
138 if(!fillTAG((PyObject*)self)) return NULL;
139 return f_BBox2(swf_GetDefineBBox(self->internals.tag));
141 //----------------------------------------------------------------------------
142 static PyMethodDef common_tagfunctions[] =
143 {{"isShape", tag_isShape, METH_VARARGS, "tests whether the tag is a shape tag"},
144 {"isImage", tag_isImage, METH_VARARGS, "tests whether the tag is an image"},
145 {"isDefiningTag", tag_isDefiningTag, METH_VARARGS, "tests whether the tag is a defining tag"},
146 {"getBBox", tag_getBBox, METH_VARARGS, "get's the tags bounding box"},
147 {NULL, NULL, 0, NULL}
150 static PyObject* tag_getattr(PyObject * self, char* a)
152 TagObject*tag = (TagObject*)self;
153 PyObject* ret = NULL;
157 if(!strcmp(a, "tagid")) {
160 return Py_BuildValue("i", tag->internals.tag->id);
162 if(!strcmp(a, "name")) {
165 char* name = swf_TagGetName(tag->internals.tag);
166 return Py_BuildValue("s", name);
168 if(tag->internals.getattr) {
169 PyObject* ret = tag->internals.getattr(&tag->internals, a);
173 /* search for a tag specific function */
174 if(tag->internals.tagfunctions) {
175 mylog(" %08x(%d) tag_getattr: tag has specific functions\n", (int)self, self->ob_refcnt);
176 ret = Py_FindMethod(tag->internals.tagfunctions, self, a);
179 ret = FindMethodMore(ret, common_tagfunctions, self, a);
180 mylog(" %08x(%d) tag_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret);
185 ret = Py_FindMethod(common_tagfunctions, self, a);
187 mylog(" %08x(%d) tag_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret);
190 static int tag_setattr(PyObject * _self, char* a, PyObject * o)
192 TagObject*self= (TagObject*)_self;
193 /* a setattr will almost certainly change the tag data,
195 if(self->internals.tag) {
196 swf_DeleteTag(self->internals.tag);
197 self->internals.tag = 0;
199 if(self->internals.setattr) {
200 int ret = self->internals.setattr(&self->internals, a, o);
205 //----------------------------------------------------------------------------
207 //----------------------------------------------------------------------------
208 PyObject* tag_new(tag_internals_t*tag_internals)
210 TagObject*tag = PyObject_New(TagObject, &TagClass);
211 mylog("+%08x(%d) tag_new\n", (int)tag, tag->ob_refcnt);
212 memcpy(&tag->internals, tag_internals, sizeof(tag_internals_t));
213 if(tag->internals.datasize) {
214 tag->internals.data = malloc(tag->internals.datasize);
215 memset(tag->internals.data , 0, tag->internals.datasize);
217 tag->internals.data = 0;
219 tag->internals.tag = 0;
220 tag->internals.tagmap = tagmap_new();
222 return (PyObject*)tag;
224 PyObject* tag_new2(TAG*t, PyObject* tagmap)
226 TagObject*tag = PyObject_New(TagObject, &TagClass);
227 mylog("+%08x(%d) tag_new2 tag=%08x id=%d (%s)\n", (int)tag, tag->ob_refcnt, t, t->id, swf_TagGetName(t));
229 PyObject*mytagmap = tagmap_new();
231 int num = swf_GetNumUsedIDs(t);
232 if(num) { // tag has dependencies
233 int * positions = malloc(num*sizeof(int));
234 swf_GetUsedIDs(t, positions);
237 int id = GET16(&t->data[positions[i]]);
238 PyObject*obj = tagmap_id2obj(tagmap, id);
240 PyErr_SetString(PyExc_Exception, setError("TagID %d not defined", id));
243 //mylog("+%08x(%d) tag_new2 handling id %d at %d/%d\n", (int)tag, tag->ob_refcnt, id, positions[i], t->len);
244 //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);
245 tagmap_addMapping(mytagmap, id, obj);
250 tag_internals_t*spec = get_parser(t->id);
252 memcpy(&tag->internals, spec, sizeof(tag_internals_t));
254 memcpy(&tag->internals, &generic_tag, sizeof(tag_internals_t));
256 if(tag->internals.datasize) {
257 tag->internals.data = malloc(tag->internals.datasize);
258 memset(tag->internals.data, 0, tag->internals.datasize);
260 tag->internals.data = 0;
262 tag->internals.tag = swf_InsertTag(0, t->id);
263 swf_SetBlock(tag->internals.tag, t->data, t->len);
264 tag->internals.tagmap = mytagmap;
266 // call tag->internals.init()?
268 return (PyObject*)tag;
270 //----------------------------------------------------------------------------
272 TAG* tag_getTAG(PyObject*self, TAG*prevTag, PyObject*tagmap)
274 TagObject*tag = (TagObject*)self;
278 mylog(" %08x(%d) tag_getTAG: tag=%08x id=%d (%s)", (int)self, self->ob_refcnt, tag->internals.tag, tag->internals.tag->id, swf_TagGetName(tag->internals.tag));
280 TAG* t = swf_InsertTag(prevTag, tag->internals.tag->id);
281 swf_SetBlock(t, tag->internals.tag->data, tag->internals.tag->len);
283 if(swf_isDefiningTag(t)) {
284 int newid = tagmap_add(tagmap, self);
285 swf_SetDefineID(t, newid);
288 int num = swf_GetNumUsedIDs(t);
289 if(num) { // tag has dependencies
290 int * positions = malloc(num*sizeof(int));
291 swf_GetUsedIDs(t, positions);
294 int id = GET16(&t->data[positions[i]]);
295 PyObject* obj = tagmap_id2obj(tag->internals.tagmap, id);
297 PyErr_SetString(PyExc_Exception, setError("Internal error: id %d not known in taglist:"));
301 //int newid = tagmap_obj2id(tag->internals.tagmap, obj);
302 int newid = tagmap_obj2id(tagmap, obj);
304 mylog(" %08x(%d) tag_getTAG: dependency %d) %d->%08x -> assigning(%08x) id %d", (int)self, self->ob_refcnt, i, id, obj, tagmap, newid);
306 /* TODO: this is only needed for sprites, so maybe it should throw an
307 exception otherwise */
308 newid = tagmap_add(tagmap, obj);
309 mylog(" %08x(%d) tag_getTAG: added dependency %d) %d->%08x -> assigning(%08x) id %d", (int)self, self->ob_refcnt, i, id, obj, tagmap, newid);
311 PUT16(&t->data[positions[i]], newid);
317 //----------------------------------------------------------------------------
318 tag_internals_t* tag_getinternals(PyObject*self)
320 TagObject*tag = (TagObject*)self;
321 mylog(" %08x(%d) tag_getInternals\n", (int)self, self->ob_refcnt);
322 return &tag->internals;
324 //----------------------------------------------------------------------------
325 PyObject* tag_getDependencies(PyObject*self)
327 TagObject*tag = (TagObject*)self;
328 mylog(" %08x(%d) tag_getDependencies\n", (int)self, self->ob_refcnt);
329 return tagmap_getObjectList(tag->internals.tagmap);
331 //----------------------------------------------------------------------------
332 int tag_print(PyObject * self, FILE * fi, int flags)
334 TagObject*tag = (TagObject*)self;
335 mylog(" %08x(%d) tag_print flags=%08x\n", (int)self, self->ob_refcnt, flags);
338 //fprintf(fi, "tag-%08x-%d-%s", (int)tag->internals.tag, tag->internals.tag->id, swf_TagGetName(tag->internals.tag));
339 fprintf(fi, "%s", swf_TagGetName(tag->internals.tag));
342 //----------------------------------------------------------------------------
343 PyTypeObject TagClass =
345 PyObject_HEAD_INIT(NULL)
348 tp_basicsize: sizeof(TagObject),
350 tp_dealloc: tag_dealloc,
352 tp_getattr: tag_getattr,
353 tp_setattr: tag_setattr,