void swf_FontPostprocess(SWF*swf) { TAG*tag = swf->firstTag; while(tag) { TAG*next = tag->next; if(tag->id == ST_DEFINEFONT3) { U16 id = swf_GetDefineID(tag); SWFFONT*font = 0; swf_FontExtract(swf, id, &font); if(!font->alignzones) { swf_FontCreateAlignZones(font); tag = swf_InsertTag(tag, ST_DEFINEFONTALIGNZONES); swf_FontSetAlignZones(tag, font); } swf_FontFree(font); } tag = next; } }
int catcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf) { char* depths; int t; TAG*tag; TAG*mtag,*stag; if(config.isframe) { msg("<fatal> Can't combine --cat and --frame"); return 101; } if(config.flashversion) master->fileVersion = config.flashversion; tag = master->firstTag; while(tag) { if(swf_isDefiningTag(tag)) { int defineid = swf_GetDefineID(tag); msg("<debug> tagid %02x defines object %d", tag->id, defineid); masterbitmap[defineid] = 1; } tag = tag->next; } swf_Relocate(slave, masterbitmap); jpeg_assert(master, slave); memcpy(newswf, master, sizeof(SWF)); adjustheader(newswf); tag = newswf->firstTag = swf_InsertTag(0, ST_REFLEX); // to be removed later depths = malloc_safe(65536); if(!depths) { msg("<fatal> Couldn't allocate %d bytes of memory", 65536); return 111; } memset(depths, 0, 65536); mtag = master->firstTag; while(mtag && mtag->id!=ST_END) { int num=1; U16 depth; msg("<debug> [master] write tag %02x (%d bytes in body)", mtag->id, mtag->len); switch(mtag->id) { case ST_PLACEOBJECT2: num++; case ST_PLACEOBJECT: { depth = swf_GetDepth(mtag); depths[depth] = 1; } break; case ST_REMOVEOBJECT: { depth = swf_GetDepth(mtag); depths[depth] = 0; } break; case ST_REMOVEOBJECT2: { depth = swf_GetDepth(mtag); depths[depth] = 0; } break; } tag = swf_InsertTag(tag, mtag->id); swf_SetBlock(tag, mtag->data, mtag->len); mtag = mtag->next; } for(t=0;t<65536;t++) if(depths[t]) { char data[16]; int len; tag = swf_InsertTag(tag, ST_REMOVEOBJECT2); swf_SetU16(tag, t); } free(depths); stag = slave->firstTag; while(stag && stag->id!=ST_END) { msg("<debug> [slave] write tag %02x (%d bytes in body)", stag->id, stag->len); tag = swf_InsertTag(tag, stag->id); swf_SetBlock(tag, stag->data, stag->len); stag = stag->next; } tag = swf_InsertTag(tag, ST_END); swf_DeleteTag(newswf, tag); return 0; }
int normalcombine(SWF*master, char*slave_name, SWF*slave, SWF*newswf) { int spriteid = -1; int replaceddefine = -1; int frame = 0; char*framelabel; TAG * tag = master->firstTag; memset(depthbitmap, 0, sizeof(depthbitmap)); // set the idtab while(tag) { int depth = swf_GetDepth(tag); if(depth>=0) { depthbitmap[depth] = 1; } if(swf_isDefiningTag(tag)) { int defineid = swf_GetDefineID(tag); msg("<debug> tagid %02x defines object %d", tag->id, defineid); masterbitmap[defineid] = 1; if (!slavename && defineid==slaveid) { if(defineid>=0) { spriteid = defineid; msg("<notice> Slave file attached to object %d.", defineid); } } } else if(tag->id == ST_EXPORTASSETS) { int t; int num = swf_GetU16(tag); for(t=0;t<num;t++) { U16 id = swf_GetU16(tag); char*name = swf_GetString(tag); if(spriteid<0 && slavename && !strcmp(name,slavename)) { spriteid = id; msg("<notice> Slave file attached to object %d exported as %s.", id, name); } } } else if(tag->id == ST_SYMBOLCLASS) { /* a symbolclass tag is like a define tag: it defines id 0000 */ int num = swf_GetU16(tag); int t; for(t=0;t<num;t++) { U16 id = swf_GetU16(tag); if(!id) { masterbitmap[id] = 1; } swf_GetString(tag); } } else if(tag->id == ST_PLACEOBJECT2) { char * name = swf_GetName(tag); int id = swf_GetPlaceID(tag); { SWFPLACEOBJECT obj; swf_GetPlaceObject(tag, &obj); swf_PlaceObjectFree(&obj); if(obj.clipdepth) { depthbitmap[obj.clipdepth] = 1; } } if(name) msg("<verbose> tagid %02x places object %d named \"%s\"", tag->id, id, name); else msg("<verbose> tagid %02x places object %d (no name)", tag->id, id); if (name && slavename && !strcmp(name,slavename)) { if(id>=0) { spriteid = id; msg("<notice> Slave file attached to named object %s (%d).", name, id); } } } else if(tag->id == ST_SHOWFRAME) { if(slaveframe>=0 && frame==slaveframe) { msg("<notice> Slave file attached to frame %d.", frame); } frame++; } else if(tag->id == ST_FRAMELABEL) { char * name = (char *)tag->data; if(name && slavename && config.isframe && !strcmp(name, slavename)) { slaveframe = frame; msg("<notice> Slave file attached to frame %d (%s).", frame, name); } } tag = tag->next; }; if (spriteid<0 && !config.isframe) { if(slavename) { if(strcmp(slavename,"!!dummy!!")) { msg("<warning> Didn't find anything named %s in file. No substitutions will occur.", slavename); if(!strcmp(slavename, "swf")) { msg("<warning> (If you were trying to combine rfxview with a document, try replacing 'swf' with 'viewport'."); } } } else msg("<warning> Didn't find id %d in file. No substitutions will occur.", slaveid); spriteid = get_free_id(masterbitmap); } swf_Relocate (slave, masterbitmap); if(config.merge) swf_RelocateDepth (slave, depthbitmap); jpeg_assert(slave, master); if (config.overlay) replaceddefine = get_free_id(masterbitmap); // write file memcpy(newswf, master, sizeof(SWF)); adjustheader(newswf); newswf->firstTag = tag = swf_InsertTag(0, ST_REFLEX); // to be removed later if (config.antistream) { if (config.merge) { msg("<fatal> Can't combine --antistream and --merge"); } tag = write_sprite_defines(tag, slave); tag = write_sprite(tag, slave, spriteid, replaceddefine); tag = write_master(tag, master, slave, spriteid, replaceddefine, FLAGS_WRITEDEFINES); tag = write_master(tag, master, slave, spriteid, replaceddefine, FLAGS_WRITENONDEFINES); } else { if (config.merge) tag = write_master(tag, master, slave, spriteid, replaceddefine, FLAGS_WRITEDEFINES|FLAGS_WRITENONDEFINES| FLAGS_WRITESLAVE ); else tag = write_master(tag, master, slave, spriteid, replaceddefine, FLAGS_WRITEDEFINES|FLAGS_WRITENONDEFINES| FLAGS_WRITESPRITE ); } swf_DeleteTag(newswf, newswf->firstTag); return 0; }
TAG* write_master(TAG*tag, SWF*master, SWF*slave, int spriteid, int replaceddefine, int flags) { int outputslave = 0; int frame = 1; int sframe = 0; int slavewritten = 0; int deletedepth = -1; TAG* rtag = master->firstTag; TAG* stag = slave->firstTag; while(rtag && rtag->id!=ST_END) { if(rtag->id == ST_SHOWFRAME && outputslave) { while(stag && stag->id!=ST_END) { if(stag->id == ST_SHOWFRAME) { stag = stag->next; sframe++; break; } if(tag_ok_for_slave(stag->id)) { tag = swf_InsertTag(tag, stag->id); write_changepos(tag, stag, config.movex, config.movey, config.scalex, config.scaley, 0); } stag = stag->next; } } if(rtag->id == ST_SHOWFRAME) { frame ++; tag = swf_InsertTag(tag, ST_SHOWFRAME); if(deletedepth>=0) { tag = swf_InsertTag(tag, ST_REMOVEOBJECT2); swf_SetU16(tag, deletedepth); deletedepth=-1; } rtag = rtag->next; continue; } if(swf_isDefiningTag(rtag) && (flags&FLAGS_WRITEDEFINES)) { msg("<debug> [master] write tag %02x (%d bytes in body)", rtag->id, rtag->len); if(swf_GetDefineID(rtag) == spriteid && !config.isframe) { if(config.overlay) { tag = swf_InsertTag(tag, rtag->id); swf_SetBlock(tag, rtag->data, rtag->len); swf_SetDefineID(tag, replaceddefine); } else { /* don't write this tag */ msg("<verbose> replacing tag %d ID %d with sprite", rtag->id ,spriteid); } if(flags&FLAGS_WRITESPRITE) { msg("<debug> writing sprite defines"); tag = write_sprite_defines(tag, slave); msg("<debug> writing sprite"); tag = write_sprite(tag, slave, spriteid, replaceddefine); } if(flags&FLAGS_WRITESLAVE) { msg("<debug> writing slave"); outputslave = 1; } } else { tag = swf_InsertTag(tag, rtag->id); swf_SetBlock(tag, rtag->data, rtag->len); } } if(frame == slaveframe) /* only happens with config.isframe: put slave at specific frame */ { if(flags&FLAGS_WRITESLAVE) { outputslave = 1; slavewritten = 1; } if((flags&FLAGS_WRITESPRITE) && !slavewritten) { int id = get_free_id(masterbitmap); int depth = 65535; deletedepth = 65535; if(config.clip) { msg("<fatal> Can't combine --clip and --frame"); } tag = write_sprite_defines(tag, slave); tag = write_sprite(tag, slave, id, -1); tag = swf_InsertTag(tag, ST_PLACEOBJECT2); swf_SetU8(tag, 2); //flags: id swf_SetU16(tag, depth); swf_SetU16(tag, id); slavewritten = 1; } } if(!swf_isDefiningTag(rtag) && (flags&FLAGS_WRITENONDEFINES)) { int dontwrite = 0; switch(rtag->id) { case ST_PLACEOBJECT: case ST_PLACEOBJECT2: if(frame == slaveframe && !config.overlay) dontwrite = 1; case ST_REMOVEOBJECT: /* place/removetags for the object we replaced should be discarded, too, as the object to insert isn't a sprite */ if(spriteid>=0 && swf_GetPlaceID(rtag) == spriteid && !config.isframe && config.merge) dontwrite = 1; break; case ST_REMOVEOBJECT2: break; } if(!dontwrite) { msg("<debug> [master] write tag %02x (%d bytes in body)", rtag->id, rtag->len); tag = swf_InsertTag(tag, rtag->id); write_changepos(tag, rtag, config.mastermovex, config.mastermovey, config.masterscalex, config.masterscaley, 1); } } rtag = rtag->next; } if(outputslave) while(stag && stag->id!=ST_END) { if(tag_ok_for_slave(stag->id)) { msg("<debug> [slave] write tag %02x (%d bytes in body), %.2f %.2f", rtag->id, rtag->len, config.movex /20.0, config.movey /20.0); tag = swf_InsertTag(tag, stag->id); write_changepos(tag, stag, config.movex, config.movey, config.scalex, config.scaley, 0); } stag = stag->next; } if(!slavewritten && config.isframe && (flags&(FLAGS_WRITESLAVE|FLAGS_WRITESPRITE))) { if(slaveframe>=0) msg("<warning> Frame %d doesn't exist in file. No substitution will occur", slaveframe); else msg("<warning> Frame \"%s\" doesn't exist in file. No substitution will occur", slavename); } tag = swf_InsertTag(tag, ST_END); return tag; }
void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) { int num_frames = 0; int has_buttons = 0; TAG*tag=swf->firstTag; unsigned int checksum = 0; while(tag) { if(tag->id == ST_SHOWFRAME) num_frames++; if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) has_buttons = 1; crc32_add_bytes(checksum, tag->data, tag->len); tag = tag->next; } int t = time(0); checksum = crc32_add_bytes(checksum, &t, sizeof(t)); unsigned char h[16]; unsigned char file_signature[33]; sprintf((char*)file_signature, "%x", checksum); char scenename1[80], scenename2[80]; sprintf(scenename1, "rfx.MainTimeline_%s", file_signature); sprintf(scenename2, "rfx::MainTimeline_%s", file_signature); abc_file_t*file = abc_file_new(); abc_method_body_t*c = 0; abc_class_t*cls = abc_class_new2(file, scenename2, "flash.display::MovieClip"); TAG*abctag = swf_InsertTagBefore(swf, swf->firstTag, ST_DOABC); tag = swf_InsertTag(abctag, ST_SYMBOLCLASS); swf_SetU16(tag, 1); swf_SetU16(tag, 0); swf_SetString(tag, scenename1); c = abc_class_getstaticconstructor(cls, 0)->body; c->old.max_stack = 1; c->old.local_count = 1; c->old.init_scope_depth = 9; c->old.max_scope_depth = 10; __ getlocal_0(c); __ pushscope(c); __ returnvoid(c); c = abc_class_getconstructor(cls, 0)->body; c->old.max_stack = 3; c->old.local_count = 1; c->old.init_scope_depth = 10; c->old.max_scope_depth = 11; debugfile(c, "constructor.as"); __ getlocal_0(c); __ pushscope(c); __ getlocal_0(c); __ constructsuper(c,0); if(stop_each_frame || has_buttons) { int frame = 0; tag = swf->firstTag; abc_method_body_t*f = 0; //frame script while(tag && tag->id!=ST_END) { char framename[80]; char needs_framescript=0; char buttonname[80]; char functionname[80]; sprintf(framename, "[packageinternal]rfx::frame%d_%s", frame, file_signature); if(!f && (tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2 || stop_each_frame)) { /* make the contructor add a frame script */ __ findpropstrict(c,"[package]::addFrameScript"); __ pushuint(c,frame); __ getlex(c,framename); __ callpropvoid(c,"[package]::addFrameScript",2); f = abc_class_method(cls, 0, multiname_fromstring(framename))->body; f->old.max_stack = 3; f->old.local_count = 1; f->old.init_scope_depth = 10; f->old.max_scope_depth = 11; __ debugfile(f, "framescript.as"); __ debugline(f, 1); __ getlocal_0(f); __ pushscope(f); if(stop_each_frame) { __ findpropstrict(f, "[package]::stop"); __ callpropvoid(f, "[package]::stop", 0); } } if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) { U16 id = swf_GetDefineID(tag); sprintf(buttonname, "::button%d", swf_GetDefineID(tag)); __ getlex(f,buttonname); __ getlex(f,"flash.events::MouseEvent"); __ getproperty(f, "::CLICK"); sprintf(functionname, "::clickbutton%d_%s", swf_GetDefineID(tag), file_signature); __ getlex(f,functionname); __ callpropvoid(f, "::addEventListener" ,2); needs_framescript = 1; abc_method_body_t*h = abc_class_method(cls, 0, multiname_fromstring(functionname))->body; list_append(h->method->parameters, multiname_fromstring("flash.events::MouseEvent")); h->old.max_stack = 6; h->old.local_count = 2; h->old.init_scope_depth = 10; h->old.max_scope_depth = 11; __ getlocal_0(h); __ pushscope(h); ActionTAG*oldaction = swf_ButtonGetAction(tag); if(oldaction && oldaction->op == ACTION__GOTOFRAME) { int framenr = GET16(oldaction->data); if(!events) { __ findpropstrict(h,"[package]::gotoAndStop"); __ pushuint(h,framenr+1); __ callpropvoid(h,"[package]::gotoAndStop", 1); } else { char framename[80]; sprintf(framename, "frame%d_%s", framenr, file_signature); __ getlocal_0(h); //this __ findpropstrict(h, "[package]flash.events::TextEvent"); __ pushstring(h, "link"); __ pushtrue(h); __ pushtrue(h); __ pushstring(h, framename); __ constructprop(h,"[package]flash.events::TextEvent", 4); __ callpropvoid(h,"[package]::dispatchEvent", 1); } } else if(oldaction && oldaction->op == ACTION__GETURL) { if(!events) { __ findpropstrict(h,"flash.net::navigateToURL"); __ findpropstrict(h,"flash.net::URLRequest"); // TODO: target _blank __ pushstring(h,(char*)oldaction->data); //url __ constructprop(h,"flash.net::URLRequest", 1); __ callpropvoid(h,"flash.net::navigateToURL", 1); } else { __ getlocal_0(h); //this __ findpropstrict(h, "[package]flash.events::TextEvent"); __ pushstring(h, "link"); __ pushtrue(h); __ pushtrue(h); __ pushstring(h,(char*)oldaction->data); //url __ constructprop(h,"[package]flash.events::TextEvent", 4); __ callpropvoid(h,"[package]::dispatchEvent", 1); } } else if(oldaction) { fprintf(stderr, "Warning: Couldn't translate button code of button %d to flash 9 abc action\n", id); } __ returnvoid(h); swf_ActionFree(oldaction); } if(tag->id == ST_SHOWFRAME) { if(f) { __ returnvoid(f); f = 0; } frame++; } tag = tag->next; } if(f) { __ returnvoid(f); } } __ returnvoid(c); tag = swf->firstTag; while(tag) { if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) { char buttonname[80]; sprintf(buttonname, "::button%d", swf_GetDefineID(tag)); multiname_t*s = multiname_fromstring(buttonname); //abc_class_slot(cls, multiname_fromstring(buttonname), s); abc_class_slot(cls, multiname_fromstring(buttonname), multiname_fromstring("flash.display::SimpleButton")); } tag = tag->next; } abc_script_t*s = abc_initscript(file); c = s->method->body; c->old.max_stack = 2; c->old.local_count = 1; c->old.init_scope_depth = 1; c->old.max_scope_depth = 9; __ getlocal_0(c); __ pushscope(c); __ getscopeobject(c, 0); __ getlex(c,"::Object"); __ pushscope(c); __ getlex(c,"flash.events::EventDispatcher"); __ pushscope(c); __ getlex(c,"flash.display::DisplayObject"); __ pushscope(c); __ getlex(c,"flash.display::InteractiveObject"); __ pushscope(c); __ getlex(c,"flash.display::DisplayObjectContainer"); __ pushscope(c); __ getlex(c,"flash.display::Sprite"); __ pushscope(c); __ getlex(c,"flash.display::MovieClip"); __ pushscope(c); __ getlex(c,"flash.display::MovieClip"); __ newclass(c,cls); __ popscope(c); __ popscope(c); __ popscope(c); __ popscope(c); __ popscope(c); __ popscope(c); __ popscope(c); __ initproperty(c,scenename2); __ returnvoid(c); //abc_method_body_addClassTrait(c, "rfx:MainTimeline", 1, cls); multiname_t*classname = multiname_fromstring(scenename2); abc_initscript_addClassTrait(s, classname, cls); multiname_destroy(classname); swf_WriteABC(abctag, file); }