X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fpython%2Ftag.c;h=5d55fb3e3a9e462992e9c9fe0e886a202bfb6afb;hb=8cbc895c917357a0dea4b8a8b81ff0920eea66e3;hp=5bc539fb599fe57e063fb324953d24dc78e62748;hpb=bca384002f56244001b335fc22b289d58832d8d4;p=swftools.git diff --git a/lib/python/tag.c b/lib/python/tag.c index 5bc539f..5d55fb3 100644 --- a/lib/python/tag.c +++ b/lib/python/tag.c @@ -9,76 +9,141 @@ #include "tagmap.h" //---------------------------------------------------------------------------- -typedef struct { + +typedef struct _TagObject { PyObject_HEAD - PyObject* tagmap; - TAG*tag; - /* ST_DEFINEFONT*/ - SWFFONT* font; - /* ST_PLACEOBJECT, ST_PLACEOBJECT2*/ - SWFPLACEOBJECT* placeobject; - PyObject* character; + tag_internals_t internals; } TagObject; //---------------------------------------------------------------------------- +static PyMethodDef generic_methods[] = +{ + {NULL, NULL, 0, NULL} +}; +static tag_internals_t generic_tag = +{ + parse: 0, + dealloc: 0, + fillTAG: 0, + tagfunctions: generic_methods, + datasize: 0, +}; +//---------------------------------------------------------------------------- + +static struct tag_parser { + int id; + tag_internals_t*spec; + struct tag_parser* next; +} tag_parsers[1024]; +static char parsers_initialized = 0; + +void register_tag(int id, tag_internals_t*spec) +{ + assert(id>=0 && id<1024); + if(!parsers_initialized) { + memset(tag_parsers, 0, sizeof(tag_parsers)); + parsers_initialized = 1; + } + tag_parsers[id].id = id; + tag_parsers[id].spec = spec; +}; + +static tag_internals_t* get_parser(int id) +{ + if(parsers_initialized<2) { + int t; + struct tag_parser*last = &tag_parsers[0]; + for(t=0;t<1024;t++) { + if(tag_parsers[t].spec) { + last->next = &tag_parsers[t]; + last = &tag_parsers[t]; + } + } + parsers_initialized = 2; + } + assert(id>=0 && id<1024); + return tag_parsers[id].spec; +} + +//---------------------------------------------------------------------------- static void tag_dealloc(PyObject * self) { TagObject*tag = (TagObject*)self; - if(tag->tag) - mylog("-%08x(%d) tag_dealoc [%s]\n", (int)self, self->ob_refcnt, swf_TagGetName(tag->tag)); + if(tag->internals.tag) + mylog("-%08x(%d) tag_dealoc [%s]\n", (int)self, self->ob_refcnt, swf_TagGetName(tag->internals.tag)); else mylog("-%08x(%d) tag_dealoc [?]\n", (int)self, self->ob_refcnt); - if(tag->placeobject) { - swf_PlaceObjectFree(tag->placeobject); - tag->placeobject = 0; + if(tag->internals.dealloc) { + if(!tag->internals.data) + mylog("-%08x(%d) tag_dealoc: Warning: calling dealloc without any data(?)\n", (int)self, self->ob_refcnt); + tag->internals.dealloc(&tag->internals); } - if(tag->font) { - swf_FontFree(tag->font); - tag->font = 0; + if(tag->internals.data) { + free(tag->internals.data); + tag->internals.data = 0; } - if(tag->character) { - Py_DECREF(tag->character); - tag->character = 0; + if(tag->internals.tag) { + swf_DeleteTag(tag->internals.tag); + tag->internals.tag = 0; } - if(tag->tag) { - swf_DeleteTag(tag->tag); - tag->tag = 0; - } - Py_DECREF(tag->tagmap); - tag->tagmap = 0; + Py_DECREF(tag->internals.tagmap); + tag->internals.tagmap = 0; PyObject_Del(self); } //---------------------------------------------------------------------------- -static PyObject* tag_setU8(PyObject * self, PyObject*other) +static int fillTAG(PyObject*self) { - return NULL; + TagObject*tag = (TagObject*)self; + if(tag->internals.tag) + return 1; + if(!tag->internals.fillTAG) { + PyErr_SetString(PyExc_Exception, setError("No way to fill TAG with data")); + return 0; + } + if(!tag->internals.fillTAG(&tag->internals)) { + return 0; // pass through exception + } + if(!tag->internals.tag) { + PyErr_SetString(PyExc_Exception, setError("Couldn't fill tag")); + return 0; + } + return 1; } //---------------------------------------------------------------------------- -static PyObject* tag_setbackgroundcolor_getrgb(PyObject * self, PyObject*other) +static PyObject* tag_isShape(PyObject * _self, PyObject*args) { - TagObject*tag = (TagObject*)self; - int r,g,b; - r = tag->tag->data[0]; - g = tag->tag->data[1]; - b = tag->tag->data[2]; - return Py_BuildValue("(iii)", r,g,b); + TagObject*self = (TagObject*)_self; + if(!PyArg_ParseTuple(args, "")) return NULL; + if(!fillTAG((PyObject*)self)) return NULL; + return PyInt_FromLong(swf_isShapeTag(self->internals.tag)); } -//---------------------------------------------------------------------------- - -static struct tagfunctions { - int id; - PyMethodDef f[8]; -} tagfunctions[] = +static PyObject* tag_isImage(PyObject * _self, PyObject*args) { - { - ST_SETBACKGROUNDCOLOR, - {{"getRGB", tag_setbackgroundcolor_getrgb, METH_VARARGS, "get's the color set by this tag"}, - {NULL, NULL, 0, NULL} - } - } -}; + TagObject*self = (TagObject*)_self; + if(!PyArg_ParseTuple(args, "")) return NULL; + if(!fillTAG((PyObject*)self)) return NULL; + return PyInt_FromLong(swf_isImageTag(self->internals.tag)); +} +static PyObject* tag_isDefiningTag(PyObject * _self, PyObject*args) +{ + TagObject*self = (TagObject*)_self; + if(!PyArg_ParseTuple(args, "")) return NULL; + if(!fillTAG((PyObject*)self)) return NULL; + return PyInt_FromLong(swf_isDefiningTag(self->internals.tag)); +} +static PyObject* tag_getBBox(PyObject * _self, PyObject*args) +{ + TagObject*self = (TagObject*)_self; + if(!PyArg_ParseTuple(args, "")) return NULL; + if(!fillTAG((PyObject*)self)) return NULL; + return f_BBox2(swf_GetDefineBBox(self->internals.tag)); +} +//---------------------------------------------------------------------------- static PyMethodDef common_tagfunctions[] = -{{"setU8", tag_setU8, METH_VARARGS, "sets a byte to the tag data"}, +{{"isShape", tag_isShape, METH_VARARGS, "tests whether the tag is a shape tag"}, + {"isImage", tag_isImage, METH_VARARGS, "tests whether the tag is an image"}, + {"isDefiningTag", tag_isDefiningTag, METH_VARARGS, "tests whether the tag is a defining tag"}, + {"getBBox", tag_getBBox, METH_VARARGS, "get's the tags bounding box"}, {NULL, NULL, 0, NULL} }; @@ -86,72 +151,83 @@ static PyObject* tag_getattr(PyObject * self, char* a) { TagObject*tag = (TagObject*)self; PyObject* ret = NULL; - int id = tag->tag->id; int t; /* -- fields -- */ - if(!strcmp(a, "id")) { - return Py_BuildValue("i", id); + if(!strcmp(a, "tagid")) { + if(!fillTAG(self)) + return 0; + return Py_BuildValue("i", tag->internals.tag->id); } if(!strcmp(a, "name")) { - char* name = swf_TagGetName(tag->tag); + if(!fillTAG(self)) + return 0; + char* name = swf_TagGetName(tag->internals.tag); return Py_BuildValue("s", name); } -/* if(!strcmp(a, "swf")) { - if(tag->swf == 0) - return Py_BuildValue("s", 0); - else { - Py_INCREF(tag->swf); - return tag->swf; - } - }*/ - /* ------------ */ - + if(tag->internals.getattr) { + PyObject* ret = tag->internals.getattr(&tag->internals, a); + if(ret) return ret; + } + /* search for a tag specific function */ - for(t=0;tob_refcnt, id); - ret = Py_FindMethod(tagfunctions[t].f, self, a); - if(!ret) return ret; - ret = FindMethodMore(ret, common_tagfunctions, self, a); - mylog(" %08x(%d) tag_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret); - return ret; - } + if(tag->internals.tagfunctions) { + mylog(" %08x(%d) tag_getattr: tag has specific functions\n", (int)self, self->ob_refcnt); + ret = Py_FindMethod(tag->internals.tagfunctions, self, a); + if(ret) return ret; + PyErr_Clear(); + ret = FindMethodMore(ret, common_tagfunctions, self, a); + mylog(" %08x(%d) tag_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret); + if(ret) return ret; + PyErr_Clear(); } - + ret = Py_FindMethod(common_tagfunctions, self, a); mylog(" %08x(%d) tag_getattr %s: %08x\n", (int)self, self->ob_refcnt, a, ret); return ret; } +static int tag_setattr(PyObject * _self, char* a, PyObject * o) +{ + TagObject*self= (TagObject*)_self; + /* a setattr will almost certainly change the tag data, + so delete the tag */ + if(self->internals.tag) { + swf_DeleteTag(self->internals.tag); + self->internals.tag = 0; + } + if(self->internals.setattr) { + int ret = self->internals.setattr(&self->internals, a, o); + return ret; + } + return 1; +} //---------------------------------------------------------------------------- -// Tag Contructors +// Tag Constructors //---------------------------------------------------------------------------- -PyObject* tag_new() +PyObject* tag_new(tag_internals_t*tag_internals) { TagObject*tag = PyObject_New(TagObject, &TagClass); mylog("+%08x(%d) tag_new\n", (int)tag, tag->ob_refcnt); - tag->font = 0; - tag->character = 0; - tag->placeobject = 0; - tag->tag = 0; - tag->tagmap = tagmap_new(); + memcpy(&tag->internals, tag_internals, sizeof(tag_internals_t)); + if(tag->internals.datasize) { + tag->internals.data = malloc(tag->internals.datasize); + memset(tag->internals.data , 0, tag->internals.datasize); + } else { + tag->internals.data = 0; + } + tag->internals.tag = 0; + tag->internals.tagmap = tagmap_new(); + return (PyObject*)tag; } PyObject* tag_new2(TAG*t, PyObject* tagmap) { TagObject*tag = PyObject_New(TagObject, &TagClass); mylog("+%08x(%d) tag_new2 tag=%08x id=%d (%s)\n", (int)tag, tag->ob_refcnt, t, t->id, swf_TagGetName(t)); - tag->font = 0; - tag->character = 0; - tag->placeobject = 0; - tag->tagmap = tagmap_new(); - // copy tag - tag->tag = swf_InsertTag(0, t->id); - swf_SetBlock(tag->tag, t->data, t->len); - t = tag->tag; + PyObject*mytagmap = tagmap_new(); + int num = swf_GetNumUsedIDs(t); if(num) { // tag has dependencies int * positions = malloc(num*sizeof(int)); @@ -166,195 +242,43 @@ PyObject* tag_new2(TAG*t, PyObject* tagmap) } //mylog("+%08x(%d) tag_new2 handling id %d at %d/%d\n", (int)tag, tag->ob_refcnt, id, positions[i], t->len); //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); - tagmap_addMapping(tag->tagmap, id, obj); + tagmap_addMapping(mytagmap, id, obj); } free(positions); } - return (PyObject*)tag; -} -static PyObject* f_SetBackgroundColor(PyObject* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"color", NULL}; - int r=0,g=0,b=0; - TagObject*tag; - PyObject*color; - - tag = (TagObject*)tag_new(); - - /* 1st try- copy constructor */ - if(!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist, &ColorClass, &color)) { - /* 2nd try- color's contructor */ - color = f_Color(NULL, args, kwargs); + tag_internals_t*spec = get_parser(t->id); + if(spec) { + memcpy(&tag->internals, spec, sizeof(tag_internals_t)); + } else { + memcpy(&tag->internals, &generic_tag, sizeof(tag_internals_t)); } - if(!color) - return NULL; - - tag->tag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR); - RGBA rgba = color_getRGBA(color); - swf_SetU8(tag->tag, rgba.r); - swf_SetU8(tag->tag, rgba.g); - swf_SetU8(tag->tag, rgba.b); - 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); - return (PyObject*)tag; -} -//---------------------------------------------------------------------------- -static PyObject* f_DefineFont(PyObject* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"filename", NULL}; - char*filename = 0; - TagObject*tag; - SWFFONT* font; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &filename)) - return NULL; - - font = swf_LoadFont(filename); - if(!font) { - PyErr_SetString(PyExc_Exception, setError("Could not load %s", filename)); - return NULL; + if(tag->internals.datasize) { + tag->internals.data = malloc(tag->internals.datasize); + memset(tag->internals.data, 0, tag->internals.datasize); + } else { + tag->internals.data = 0; } + tag->internals.tag = swf_InsertTag(0, t->id); + swf_SetBlock(tag->internals.tag, t->data, t->len); + tag->internals.tagmap = mytagmap; - tag = (TagObject*)tag_new(); - tag->font = font; - tag->tag = swf_InsertTag(0, ST_DEFINEFONT2); - tag->font->id = 0; - swf_FontSetDefine2(tag->tag, tag->font); - mylog("+%08x(%d) DefineFont\n", (int)tag, tag->ob_refcnt); - return (PyObject*)tag; -} -static SWFFONT* fonttag_getSWFFONT(PyObject*self) -{ - PY_ASSERT_TYPE(self, &TagClass); - TagObject*font = (TagObject*)self; - return font->font; -} -//---------------------------------------------------------------------------- -static PyObject* f_Protect(PyObject* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"password", NULL}; - char*password = 0; - TagObject*tag; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &password)) - return NULL; + // call tag->internals.init()? - tag = (TagObject*)tag_new(); - tag->tag = swf_InsertTag(0, ST_PROTECT); - if(password) { - swf_SetPassword(tag->tag, password); - } - mylog("+%08x(%d) f_Protect", (int)tag, tag->ob_refcnt); return (PyObject*)tag; } //---------------------------------------------------------------------------- -static PyObject* f_DefineText(PyObject* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"font", "text", "size", "color", NULL}; - TagObject*tag = 0; - char*text = 0; - int textlen = 0; - PyObject*unicode16; - PyObject*unicode8; - int size = 0; - RGBA rgba = {255,0,0,0}; - PyObject*color = 0; - PyObject*font = 0; - SRECT r; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!u#i|O!", kwlist, &TagClass, &font, &text, &textlen, &size, &ColorClass, &color)) - return NULL; - - unicode16 = PyUnicode_DecodeUTF16(text, textlen*2, NULL, NULL); - unicode8 = PyUnicode_AsUTF8String(unicode16); - text = PyString_AS_STRING(unicode8); - - if(color) - rgba = color_getRGBA(color); - - mylog("DefineText: text = %s", text); - - tag = (TagObject*)tag_new(); - - int font_id = tagmap_add(tag->tagmap, font); // add dependency on font - - fonttag_getSWFFONT(font)->id = font_id; - - tag ->tag= swf_InsertTag(0, ST_DEFINETEXT2); - swf_SetU16(tag->tag, /*ID*/0); - r = swf_SetDefineText(tag->tag, fonttag_getSWFFONT(font), &rgba, text, size); - mylog("+%08x(%d) DefineText tag=%08x \n", (int)tag, tag->ob_refcnt); - - //Py_DECREF(unicode16); - //Py_DECREF(unicode8); - //free(text); - - return (PyObject*)tag; -} -//---------------------------------------------------------------------------- -static PyObject* f_PlaceObject(PyObject* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"character", "depth", "matrix", "colortransform", "ratio", "name", "clipdepth", "action", NULL}; - TagObject*tag; - - TagObject*character = 0; - int depth; - int clipdepth = 0; - PyObject*matrix = 0; - PyObject*cxform = 0; - PyObject*action = 0; - int ratio = 0; - char* name = 0; - SWFPLACEOBJECT* po; - po = malloc(sizeof(SWFPLACEOBJECT)); - memset(po, 0, sizeof(SWFPLACEOBJECT)); - - swf_GetPlaceObject(0, po); - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!i|O!O!isiO!", kwlist, - &TagClass, &character, - &depth, - &MatrixClass, &matrix, - &CXFormClass, &cxform, - &ratio, - &name, - &clipdepth, - &ActionClass, &action - )) - return NULL; - po->depth = depth; - po->id = /*ID*/ 0; - po->clipdepth = clipdepth; - po->ratio = ratio; - po->name = name; - if(clipdepth) po->clipdepth = clipdepth; - if(matrix) po->matrix = matrix_getMatrix(matrix); - if(cxform) po->cxform = colortransform_getCXForm(cxform); - if(action) po->actions = action_getAction(action); - - tag = (TagObject*)tag_new(); - tag->placeobject = po; - Py_INCREF(character); - tag->character = (PyObject*)character; - tag->tag= swf_InsertTag(0, ST_PLACEOBJECT2); - - po->id = tagmap_add(tag->tagmap,(PyObject*)character); - - swf_SetPlaceObject(tag->tag, po); - mylog("+%08x(%d) PlaceObject %08x(%d)\n", (int)tag, tag->ob_refcnt, character, character->ob_refcnt); - - return (PyObject*)tag; -} - /* serialize */ TAG* tag_getTAG(PyObject*self, TAG*prevTag, PyObject*tagmap) { TagObject*tag = (TagObject*)self; - - mylog(" %08x(%d) tag_getTAG: tag=%08x id=%d (%s)", (int)self, self->ob_refcnt, tag->tag, tag->tag->id, swf_TagGetName(tag->tag)); - TAG* t = swf_InsertTag(prevTag, tag->tag->id); - swf_SetBlock(t, tag->tag->data, tag->tag->len); + if(!fillTAG(self)) + return 0; + 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)); + + TAG* t = swf_InsertTag(prevTag, tag->internals.tag->id); + swf_SetBlock(t, tag->internals.tag->data, tag->internals.tag->len); if(swf_isDefiningTag(t)) { int newid = tagmap_add(tagmap, self); @@ -362,37 +286,60 @@ TAG* tag_getTAG(PyObject*self, TAG*prevTag, PyObject*tagmap) } int num = swf_GetNumUsedIDs(t); - int * positions = malloc(num*sizeof(int)); - swf_GetUsedIDs(t, positions); - int i; - for(i=0;idata[positions[i]]); - PyObject* obj = tagmap_id2obj(tag->tagmap, id); - if(obj==NULL) { - PyErr_SetString(PyExc_Exception, setError("Internal error: id %d not known in taglist:")); - free(positions); - return 0; + if(num) { // tag has dependencies + int * positions = malloc(num*sizeof(int)); + swf_GetUsedIDs(t, positions); + int i; + for(i=0;idata[positions[i]]); + PyObject* obj = tagmap_id2obj(tag->internals.tagmap, id); + if(obj==NULL) { + PyErr_SetString(PyExc_Exception, setError("Internal error: id %d not known in taglist:")); + free(positions); + return 0; + } + //int newid = tagmap_obj2id(tag->internals.tagmap, obj); + int newid = tagmap_obj2id(tagmap, obj); + if(newid>=0) { + mylog(" %08x(%d) tag_getTAG: dependency %d) %d->%08x -> assigning(%08x) id %d", (int)self, self->ob_refcnt, i, id, obj, tagmap, newid); + } else { + /* TODO: this is only needed for sprites, so maybe it should throw an + exception otherwise */ + newid = tagmap_add(tagmap, obj); + mylog(" %08x(%d) tag_getTAG: added dependency %d) %d->%08x -> assigning(%08x) id %d", (int)self, self->ob_refcnt, i, id, obj, tagmap, newid); + } + PUT16(&t->data[positions[i]], newid); } - int newid = tagmap_obj2id(tagmap, obj); - PUT16(&t->data[positions[i]], newid); + free(positions); } - free(positions); return t; } - +//---------------------------------------------------------------------------- +tag_internals_t* tag_getinternals(PyObject*self) +{ + TagObject*tag = (TagObject*)self; + mylog(" %08x(%d) tag_getInternals\n", (int)self, self->ob_refcnt); + return &tag->internals; +} +//---------------------------------------------------------------------------- PyObject* tag_getDependencies(PyObject*self) { TagObject*tag = (TagObject*)self; - mylog(" %08x(%d) tag_getDependencies id=%d tag=%s\n", (int)self, self->ob_refcnt, tag->tag->id, swf_TagGetName(tag->tag)); - return tagmap_getObjectList(tag->tagmap); + mylog(" %08x(%d) tag_getDependencies\n", (int)self, self->ob_refcnt); + return tagmap_getObjectList(tag->internals.tagmap); } - -int tag_print (PyObject * self, FILE * fi, int flags) +//---------------------------------------------------------------------------- +int tag_print(PyObject * self, FILE * fi, int flags) { + TagObject*tag = (TagObject*)self; mylog(" %08x(%d) tag_print flags=%08x\n", (int)self, self->ob_refcnt, flags); + if(!fillTAG(self)) + return -1; + //fprintf(fi, "tag-%08x-%d-%s", (int)tag->internals.tag, tag->internals.tag->id, swf_TagGetName(tag->internals.tag)); + fprintf(fi, "%s", swf_TagGetName(tag->internals.tag)); return 0; } - +//---------------------------------------------------------------------------- PyTypeObject TagClass = { PyObject_HEAD_INIT(NULL) @@ -403,20 +350,5 @@ PyTypeObject TagClass = tp_dealloc: tag_dealloc, tp_print: tag_print, tp_getattr: tag_getattr, + tp_setattr: tag_setattr, }; -static PyMethodDef TagMethods[] = -{ - /* TAGS */ - {"SetBackgroundColor", (PyCFunction)f_SetBackgroundColor, METH_KEYWORDS, "Create a SetBackGroundColor Tag."}, - {"Protect", (PyCFunction)f_Protect, METH_KEYWORDS, "Create a Protect Tag."}, - {"DefineFont", (PyCFunction)f_DefineFont, METH_KEYWORDS, "Create a DefineFont Tag."}, - {"DefineText", (PyCFunction)f_DefineText, METH_KEYWORDS, "Create a DefineText Tag."}, - {"PlaceObject", (PyCFunction)f_PlaceObject, METH_KEYWORDS, "Create a PlaceObject Tag."}, - {NULL, NULL, 0, NULL} -}; -PyMethodDef* tag_getMethods() -{ - TagClass.ob_type = &PyType_Type; - return TagMethods; -} -