void swf_FontSetAlignZones(TAG*t, SWFFONT *f) { swf_SetU16(t, f->id); swf_SetU8(t, f->alignzone_flags); int i; for(i=0;i<f->numchars;i++) { ALIGNZONE*a = &f->alignzones[i]; U8 flags = 0; if((a->x & a->dx)!=0xffff) flags |= 1; if((a->y & a->dy)!=0xffff) flags |= 2; int num = 1; if(a->dx != 0xffff || a->dy != 0xffff) num++; swf_SetU8(t, num); if(flags&1) swf_SetU16(t, a->x); else swf_SetU16(t, 0); if(flags&2) swf_SetU16(t, a->y); else swf_SetU16(t, 0); if(num==2) { if((flags&1) && a->dx!=0xffff) swf_SetU16(t, a->dx); else swf_SetU16(t, 0); if((flags&2) && a->dy!=0xffff) swf_SetU16(t, a->dy); else swf_SetU16(t, 0); } swf_SetU8(t, flags); } }
TAG* write_sprite(TAG*tag, SWF*sprite, int spriteid, int replaceddefine) { TAG* definespritetag; TAG* rtag; int tmp; definespritetag = tag = swf_InsertTag(tag, ST_DEFINESPRITE); swf_SetU16(tag, spriteid); swf_SetU16(tag, sprite->frameCount); msg ("<notice> sprite id is %d", spriteid); tmp = sprite->frameCount; msg("<debug> %d frames to go",tmp); if(config.clip) { tag = swf_InsertTag(tag, ST_PLACEOBJECT2); swf_SetU8(tag, 2+64); //flags: character+clipdepth swf_SetU16(tag, 0); //depth swf_SetU16(tag, replaceddefine); //id swf_SetU16(tag, 65535); //clipdepth } if(config.overlay && !config.isframe) { tag = swf_InsertTag(tag, ST_PLACEOBJECT2); swf_SetU8(tag, 2); //flags: character swf_SetU16(tag, 1); //depth swf_SetU16(tag, replaceddefine); //id } rtag = sprite->firstTag; while(rtag && rtag->id!=ST_END) { if (swf_isAllowedSpriteTag(rtag)) { msg("<debug> [sprite main] write tag %02x (%d bytes in body)", rtag->id, rtag->len); tag = swf_InsertTag(tag, rtag->id); write_changepos(tag, rtag, config.movex, config.movey, config.scalex, config.scaley, 0); if(config.clip || (config.overlay && !config.isframe)) changedepth(tag, +2); if(tag->id == ST_SHOWFRAME) { tmp--; msg("<debug> %d frames to go",tmp); } } rtag = rtag->next; } tag = swf_InsertTag(tag, ST_END); return tag; }
static void swf_ShapeDrawerInit(drawer_t*draw, TAG*tag, int fillstylebits, int linestylebits) { SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)rfx_calloc(sizeof(SWFSHAPEDRAWER)); draw->internal = sdraw; draw->setLineStyle = swf_ShapeDrawerSetLineStyle; draw->setFillStyle = swf_ShapeDrawerSetFillStyle; draw->moveTo = swf_ShapeDrawerMoveTo; draw->lineTo = swf_ShapeDrawerLineTo; draw->splineTo = swf_ShapeDrawerSplineTo; draw->finish = swf_ShapeDrawerFinish; draw->dealloc = swf_ShapeDrawerClear; sdraw->tagfree = 0; if(tag == 0) { tag = swf_InsertTag(0, ST_DEFINESHAPE); sdraw->tagfree = 1; } sdraw->tag = tag; swf_ShapeNew(&sdraw->shape); draw->pos.x = 0; draw->pos.y = 0; swf_SetU8(sdraw->tag,0); sdraw->shape->bits.fill = fillstylebits; sdraw->shape->bits.line = linestylebits; sdraw->bbox.xmin = sdraw->bbox.ymin = SCOORD_MAX; sdraw->bbox.xmax = sdraw->bbox.ymax = SCOORD_MIN; sdraw->isfinished = 0; swf_ShapeSetStyle(sdraw->tag,sdraw->shape,linestylebits?1:0,fillstylebits?1:0,0/*?*/); }
void write_changepos(TAG*output, TAG*tag, int movex, int movey, float scalex, float scaley, int scalepos) { if(movex || movey || scalex != 1.0 || scaley != 1.0) { switch(tag->id) { case ST_PLACEOBJECT2: { MATRIX m; U8 flags; swf_GetMatrix(0, &m); tag->pos = 0; tag->readBit = 0; flags = swf_GetU8(tag); swf_SetU8(output, flags|4); swf_SetU16(output, swf_GetU16(tag)); //depth //flags&1: move if(flags&2) { swf_SetU16(output, swf_GetU16(tag)); //id } // flags & 4 if(flags&4) { swf_GetMatrix(tag, &m); } else { swf_GetMatrix(0, &m); } matrix_adjust(&m, movex, movey, scalex, scaley, scalepos); swf_SetMatrix(output, &m); if (tag->readBit) { tag->pos++; tag->readBit = 0; } //swf_ResetReadBits(tag); swf_SetBlock(output, &tag->data[tag->pos], tag->len - tag->pos); break; } case ST_PLACEOBJECT: { MATRIX m; swf_SetU16(output, swf_GetU16(tag)); //id swf_SetU16(output, swf_GetU16(tag)); //depth swf_GetMatrix(tag, &m); matrix_adjust(&m, movex, movey, scalex, scaley, scalepos); swf_SetMatrix(output, &m); if (tag->readBit) { tag->pos++; tag->readBit = 0; } //swf_ResetReadBits(tag); swf_SetBlock(output, &tag->data[tag->pos], tag->len - tag->pos); break; } default: swf_SetBlock(output, tag->data, tag->len); } } else { swf_SetBlock(output, tag->data, tag->len); } }
void swf_SetFilter(TAG*tag, FILTER*filter) { swf_SetU8(tag, filter->type); if(filter->type == FILTERTYPE_BLUR) { FILTER_BLUR*f = (FILTER_BLUR*)filter; swf_SetFixed(tag, f->blurx); swf_SetFixed(tag, f->blury); U8 flags = f->passes << 3; swf_SetU8(tag, flags); } else if(filter->type == FILTERTYPE_GLOW) { FILTER_GLOW*f = (FILTER_GLOW*)filter; } else if(filter->type == FILTERTYPE_DROPSHADOW) { FILTER_DROPSHADOW*f = (FILTER_DROPSHADOW*)filter; swf_SetRGBA(tag, &f->color); swf_SetFixed(tag, f->blurx); swf_SetFixed(tag, f->blury); swf_SetFixed(tag, f->angle); swf_SetFixed(tag, f->distance); swf_SetFixed8(tag, f->strength); U8 flags = f->innershadow<<7|f->knockout<<6|f->composite<<5|f->passes; swf_SetU8(tag, flags); } else if(filter->type == FILTERTYPE_GRADIENTGLOW) { FILTER_GRADIENTGLOW*f = (FILTER_GRADIENTGLOW*)filter; swf_SetU8(tag, f->gradient->num); int s; for(s=0;s<f->gradient->num;s++) swf_SetRGBA(tag, &f->gradient->rgba[s]); for(s=0;s<f->gradient->num;s++) swf_SetU8(tag, f->gradient->ratios[s]); swf_SetFixed(tag, f->blurx); swf_SetFixed(tag, f->blury); swf_SetFixed(tag, f->angle); swf_SetFixed(tag, f->distance); swf_SetFixed8(tag, f->strength); U8 flags = f->passes|f->innershadow<<7|f->knockout<<6|f->composite<<5|f->ontop<<4; swf_SetU8(tag, flags); } else if(filter->type == FILTERTYPE_BEVEL) { FILTER_BEVEL*f = (FILTER_BEVEL*)filter; swf_SetRGBA(tag, &f->shadow); swf_SetRGBA(tag, &f->highlight); swf_SetFixed(tag, f->blurx); swf_SetFixed(tag, f->blury); swf_SetFixed(tag, f->angle); swf_SetFixed(tag, f->distance); swf_SetFixed8(tag, f->strength); U8 flags = f->passes|f->innershadow<<7|f->knockout<<6|f->composite<<5|f->ontop<<4; swf_SetU8(tag, flags); } else { fprintf(stderr, "Writing of filter type %02x not supported yet\n", filter->type); } }
void swf_ActionSet(TAG*tag, ActionTAG*action) { if(!action) { return; } action=action->parent; while(action) { swf_SetU8(tag, action->op); if(action->op & 128) swf_SetU16(tag, action->len); swf_SetBlock(tag, action->data, action->len); action = action->next; } }
ActionTAG* swf_ActionCompile(const char* source, int version) { TAG* tag; ActionTAG* a = 0; void*buffer = 0; int len = 0; int ret; tag = swf_InsertTag(NULL, ST_DOACTION); ret = compileSWFActionCode(source, version, &buffer, &len); if(!ret || buffer==0 || len == 0) return 0; swf_SetBlock(tag, (U8*)buffer, len); swf_SetU8(tag, 0); rfx_free(buffer); a = swf_ActionGet(tag); swf_DeleteTag(0, tag); return a; }
static int opcode_write(TAG*tag, code_t*c, pool_t*pool, abc_file_t*file, int length) { opcode_t*op = opcode_get(c->opcode); char*p = op->params; int pos = 0; int len = 0; if(tag) swf_SetU8(tag, c->opcode); len++; if(op->flags & OP_INTERNAL) { if(c->opcode == OPCODE___BREAK__ || c->opcode == OPCODE___CONTINUE__) { fprintf(stderr, "Unresolved %s\n", op->name); } else { fprintf(stderr, "Error: writing undefined internal opcode %s\n", op->name); } } while(*p) { void*data = c->data[pos++]; assert(pos<=2); switch(*p) { case 'n': { // number len += swf_SetU30(tag, (ptroff_t)data); break; } case '2': { //multiname multiname_t*m = (multiname_t*)data; len += swf_SetU30(tag, pool_register_multiname(pool, m)); break; } case 'N': { //namespace namespace_t*ns = (namespace_t*)data; len += swf_SetU30(tag, pool_register_namespace(pool, ns)); break; } case 'm': { //method abc_method_t*m = (abc_method_t*)data; len += swf_SetU30(tag, m->index); break; } case 'c': { //classinfo abc_class_t*cls = (abc_class_t*)data; len += swf_SetU30(tag, cls->index); break; } case 'i': { //methodbody abc_method_body_t*m = (abc_method_body_t*)data; len += swf_SetU30(tag, m->index); break; } case 'I': { // int len += swf_SetU30(tag, pool_register_int(pool, (ptroff_t)data)); break; } case 'U': { // uint len += swf_SetU30(tag, pool_register_uint(pool, (ptroff_t)data)); break; } case 'f': { // float len += swf_SetU30(tag, pool_register_float(pool, *(double*)data)); break; } case 'u': { // integer len += swf_SetU30(tag, (ptroff_t)data); break; } case 'r': { // integer len += swf_SetU30(tag, (ptroff_t)data); break; } case 'b': { // byte if(tag) swf_SetU8(tag, (ptroff_t)data); len++; break; } case 'j': { // jump int skip = length-c->pos-4; if(c->branch) skip = (c->branch->pos) - c->pos - 4; len += swf_SetS24(tag, skip); break; } case 's': { // string int index = pool_register_string2(pool, (string_t*)data); len += swf_SetU30(tag, index); break; } case 'D': { // debug statement if(tag) swf_SetU8(tag, 1); len++; len+=swf_SetU30(tag, pool_register_string(pool,c->data[0])); if(tag) swf_SetU8(tag, (ptroff_t)c->data[1]); len++; len+=swf_SetU30(tag, 0); break; } case 'S': { // switch statement lookupswitch_t*l = (lookupswitch_t*)data; int offset = 0; len+=swf_SetS24(tag, l->def->pos-c->pos+offset); //default code_list_t*t = l->targets; if(list_length(t)) { len+=swf_SetU30(tag, list_length(t)-1); //nr-1 code_list_t*t = l->targets; while(t) { len+=swf_SetS24(tag, t->code->pos - c->pos+offset); t = t->next; } } else { len+=swf_SetU30(tag, 0); //nr-1 len+=swf_SetS24(tag, l->def->pos-c->pos+offset); } break; } default: printf("Can't parse opcode param type \"%c\"\n", *p); } p++; } return len; }
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; }
static void write_font(SWFFONT * font, char *filename) { SWF swf; TAG *t; SRECT r; RGBA rgb; int f; int useDefineFont2 = 1; int storeGlyphNames = 1; #define WRITEFONTID 8888 font->id = WRITEFONTID; memset(&swf, 0x00, sizeof(SWF)); swf.fileVersion = 9; swf.frameRate = 0x4000; t = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR); swf.firstTag = t; rgb.r = 0xef; rgb.g = 0xef; rgb.b = 0xff; swf_SetRGB(t, &rgb); t = swf_InsertTag(t, ST_DEFINEFONT3); swf_FontSetDefine2(t, font); t = swf_InsertTag(t, ST_DEFINEFONTALIGNZONES); swf_SetU16(t, font->id); swf_SetU8(t, 0); //thin int i; for(i=0;i<256;i++) { swf_SetU8(t, 2); swf_SetF16(t, 82.0 / 1024.0); swf_SetF16(t, 82.0 / 1024.0); swf_SetF16(t, ((i%16/2)*82.0) / 1024.0); swf_SetF16(t, ((i/16/2)*82.0) / 1024.0); /* if(i<128 && (i&15)<8) { swf_SetF16(t, 0.0); swf_SetF16(t, 0.0); swf_SetF16(t, 640.0 / 1024.0); swf_SetF16(t, 640.0 / 1024.0); } else if(i<128 && (i&15)>=8) { swf_SetF16(t, 0.0 / 1024.0); swf_SetF16(t, 0.0 / 1024.0); swf_SetF16(t, 330.0 / 1024.0); swf_SetF16(t, 640.0 / 1024.0); } else if(i>=128 && (i&15)<8) { swf_SetF16(t, 0.0 / 1024.0); swf_SetF16(t, 0.0 / 1024.0); swf_SetF16(t, 640.0 / 1024.0); swf_SetF16(t, 330.0 / 1024.0); } else { swf_SetF16(t, 0.0 / 1024.0); swf_SetF16(t, 0.0 / 1024.0); swf_SetF16(t, 330.0 / 1024.0); swf_SetF16(t, 330.0 / 1024.0); }*/ swf_SetU8(t, 3); // x and y } int s; int xmax = 0; int ymax = 0; int ypos = 1; U8 gbits, abits; int x, y, c; int range = font->maxascii; c = 0; range = 256; xmax = 1280; ymax = 1280*20; swf.movieSize.xmax = xmax * 20; swf.movieSize.ymax = ymax; t = swf_InsertTag(t, ST_DEFINETEXT); swf_SetU16(t, font->id + 1); // ID r.xmin = 0; r.ymin = 0; r.xmax = swf.movieSize.xmax; r.ymax = swf.movieSize.ymax; swf_SetRect(t, &r); swf_SetMatrix(t, NULL); abits = swf_CountBits(xmax * 16, 0); gbits = 8; swf_SetU8(t, gbits); swf_SetU8(t, abits); rgb.r = 0x00; rgb.g = 0x00; rgb.b = 0x00; ypos = 2; int textscale = 1024; for (y = 0; y < ((range + 15) / 16); y++) { for (x = 0; x < 16; x++) { //swf_TextSetInfoRecord(t, font, textscale, &rgb, x*64*20+64*20+10+(x+y)*20, y*64*20+128*20+10+(x^y)*20); swf_TextSetInfoRecord(t, font, textscale, &rgb, x*64*20+64*20+10, y*64*20+128*20+10); int g = y * 16 + x; swf_SetU8(t, 1); swf_SetBits(t, g, gbits); swf_SetBits(t, 0, abits); swf_ResetWriteBits(t); } } swf_SetU8(t, 0); t = swf_InsertTag(t, ST_CSMTEXTSETTINGS); swf_SetU16(t, font->id + 1); swf_SetU8(t, (1<<3)//grid |0x40//flashtype ); swf_SetU32(t, 0x20000);//thickness swf_SetU32(t, 0x800000);//sharpness swf_SetU8(t, 0);//reserved t = swf_InsertTag(t, ST_PLACEOBJECT2); swf_ObjectPlace(t, font->id + 1, 1, NULL, NULL, NULL); t = swf_InsertTag(t, ST_SHOWFRAME); t = swf_InsertTag(t, ST_END); f = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644); if FAILED (swf_WriteSWF(f, &swf)) fprintf(stderr, "WriteSWF() failed in writeFont().\n"); close(f); swf_FreeTags(&swf); }