FILTER*swf_GetFilter(TAG*tag) { U8 type = swf_GetU8(tag); FILTER*filter; if(type == FILTERTYPE_BLUR) { FILTER_BLUR* f = (FILTER_BLUR*)rfx_calloc(sizeof(FILTER_BLUR)); f->type = type; f->blurx = swf_GetFixed(tag); f->blury = swf_GetFixed(tag); U8 flags = swf_GetU8(tag); f->passes = (flags&15)<<3; return (FILTER*)f; } else if(type == FILTERTYPE_GLOW) { FILTER_GLOW* f = (FILTER_GLOW*)rfx_calloc(sizeof(FILTER_GLOW)); f->type = type; swf_GetRGBA(tag, &f->rgba); f->blurx = swf_GetFixed(tag); f->blury = swf_GetFixed(tag); f->strength = swf_GetFixed8(tag); U8 flags = swf_GetU8(tag); f->passes = flags&31; f->innerglow = (flags>>7)&1; f->knockout = (flags>>6)&1; f->composite = (flags>>5)&1; return (FILTER*)f; } else if(type == FILTERTYPE_GRADIENTGLOW) {
int swf_FontExtract_DefineFontAlignZones(int id, SWFFONT *font, TAG *tag) { uint16_t fid; swf_SetTagPos(tag, 0); fid = swf_GetU16(tag); if (fid == id) { font->alignzone_flags = swf_GetU8(tag); font->alignzones = calloc(1, sizeof(ALIGNZONE)*font->numchars); int i = 0; while (tag->pos < tag->len) { if (i >= font->numchars) break; int nr = swf_GetU8(tag); // should be 2 if (nr != 1 && nr != 2) { #ifdef _DEBUG printf("rfxswf: Can't parse alignzone tags with %d zones", nr); #endif break; } uint16_t x = swf_GetU16(tag); uint16_t y = swf_GetU16(tag); uint16_t dx = (nr == 2) ? swf_GetU16(tag) : 0xffff; uint16_t dy = (nr == 2) ? swf_GetU16(tag) : 0xffff; uint8_t xy = swf_GetU8(tag); #ifdef _DEBUG if ((!(xy & 1) && (x != 0 || (dx != 0 && dx != 0xffff))) || (!(xy & 2) && (y != 0 || (dy != 0 && dy != 0xffff)))) { printf("Warning: weird combination of alignzone bits and values (%d x:%04x-%04x y:%04x-%04x)\n", xy, x, dx, y, dy); } #endif if (!(xy & 1)) { x = 0xffff; dx = 0xffff; } else if (!(xy & 2)) { y = 0xffff; dy = 0xffff; } font->alignzones[i].x = x; font->alignzones[i].y = y; font->alignzones[i].dx = dx; font->alignzones[i].dy = dy; i++; } } return id; }
void changedepth(TAG*tag, int add) { if(tag->id == ST_PLACEOBJECT) PUT16(&tag->data[2],GET16(&tag->data[2])+add); if(tag->id == ST_PLACEOBJECT2) PUT16(&tag->data[1],GET16(&tag->data[1])+add); if(tag->id == ST_REMOVEOBJECT) PUT16(&tag->data[2],GET16(&tag->data[2])+add); if(tag->id == ST_REMOVEOBJECT2) PUT16(&tag->data[0],GET16(&tag->data[0])+add); if(tag->id == ST_PLACEOBJECT2) { SWFPLACEOBJECT obj; U8 flags; swf_SetTagPos(tag, 0); flags = swf_GetU8(tag); if(flags&2) swf_GetU16(tag); //id if(flags&4) swf_GetMatrix(tag, 0); if(flags&8) swf_GetCXForm(tag, 0,1); if(flags&16) swf_GetU16(tag); //ratio if(flags&64) { swf_ResetReadBits(tag); printf("%d->%d\n", GET16(&tag->data[tag->pos]), GET16(&tag->data[tag->pos])+add); PUT16(&tag->data[tag->pos],GET16(&tag->data[tag->pos])+add); } msg("<warning> Depth relocation not fully working yet with clipdepths", tag->id); } }
ActionTAG* swf_ActionGet(TAG*tag) { U8 op = 1; int length; ActionTAG tmp; ActionTAG*action = &tmp; U8*data; while(op) { action->next = (ActionTAG*)rfx_calloc(sizeof(ActionTAG)); action->next->prev = action; action->next->next = 0; action->next->parent = tmp.next; action = action->next; op = swf_GetU8(tag); if(op<0x80) length = 0; else length = swf_GetU16(tag); if(length) { data = (U8*)rfx_alloc(length); swf_GetBlock(tag, data, length); } else { data = 0; } action->op = op; action->len = length; action->data = data; } return tmp.next; }
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); } }
code_t*code_parse(TAG*tag, int len, abc_file_t*file, pool_t*pool, codelookup_t**codelookup) { code_t*head=0; code_t*code=0; int start=tag->pos; int end=tag->pos+len; //printf("-->\n");fflush(stdout); code_t**bytepos = rfx_calloc(sizeof(code_t*)*len); while(tag->pos<end) { int codepos = tag->pos-start; U8 opcode = swf_GetU8(tag); opcode_t*op = opcode_get(opcode); if(!op) { fprintf(stderr, "Can't parse opcode %02x\n", opcode); continue; } //printf("%s\n", op->name);fflush(stdout); NEW(code_t,c); c->pos = codepos; bytepos[codepos] = c; if(!head) { head = code = c; } else { code->next = c; c->prev = code; code = c; } c->opcode = opcode; char*p = op->params; int pos = 0; while(*p) { void*data = 0; if(*p == 'n') { // number data = (void*)(ptroff_t)swf_GetU30(tag); } else if(*p == '2') { //multiname data = multiname_clone(pool_lookup_multiname(pool, swf_GetU30(tag))); } else if(*p == 'N') { //namespace data = namespace_clone(pool_lookup_namespace(pool, swf_GetU30(tag))); } else if(*p == 'U') { //uint data = (void*)(ptroff_t)pool_lookup_uint(pool, swf_GetU30(tag)); } else if(*p == 'I') { //int data = (void*)(ptroff_t)pool_lookup_int(pool, swf_GetU30(tag)); } else if(*p == 'f') { //int double*fp = malloc(sizeof(double)); *fp = pool_lookup_float(pool, swf_GetU30(tag)); data = fp; } else if(*p == 'm') { //method data = array_getvalue(file->methods, swf_GetU30(tag)); } else if(*p == 'c') { //classinfo data = array_getvalue(file->classes, swf_GetU30(tag)); } else if(*p == 'i') { data = array_getvalue(file->method_bodies, swf_GetU30(tag)); } else if(*p == 'u') { // generic integer data = (void*)(ptroff_t)swf_GetU30(tag); } else if(*p == 'r') { // local register data = (void*)(ptroff_t)swf_GetU30(tag); } else if(*p == 'b') { // byte data = (void*)(ptroff_t)swf_GetU8(tag); } else if(*p == 'j') { // jump int j = swf_GetS24(tag); data = (void*)(ptroff_t)j; } else if(*p == 's') { // string string_t s = pool_lookup_string2(pool, swf_GetU30(tag)); data = string_dup3(&s); } else if(*p == 'D') { // debug /*type, usually 1*/ U8 type = swf_GetU8(tag); if(type!=1) fprintf(stderr, "Unknown debug type: %02x\n", type); /*register name*/ code->data[0] = strdup((char*)pool_lookup_string(pool, swf_GetU30(tag))); /*register index*/ code->data[1] = (void*)(ptroff_t)swf_GetU8(tag); /*unused*/ swf_GetU30(tag); } else if(*p == 'S') { // switch statement lookupswitch_t*l = malloc(sizeof(lookupswitch_t)); l->def = (code_t*)(ptroff_t)swf_GetS24(tag); l->targets = list_new(); int num = swf_GetU30(tag)+1; int t; for(t=0;t<num;t++) list_append(l->targets, (code_t*)(ptroff_t)swf_GetS24(tag)); data = l; } else { printf("Can't parse opcode param type \"%c\" (for op %02x %s).\n", *p, code->opcode, op->name); return 0; } if(data) code->data[pos++] = data; p++; } } //#define DEBUG_BYTES #ifdef DEBUG_BYTES int t; for(t=0;t<len;t++) { code_t*c = bytepos[t]; if(c) { opcode_t*op = opcode_get(c->opcode); if(op->flags & (OP_JUMP|OP_BRANCH)) { printf("%50d) %02x %s %d\n", t, tag->data[start+t], op->name, c->data[0]); } else { printf("%50d) %02x %s\n", t, tag->data[start+t], op->name); } } else { printf("%50d) %02x\n", t, tag->data[start+t]); } } //printf("%05d) %02x\n", t, tag->data[start+t]); #endif code_t*c = head; while(c) { opcode_t*op = opcode_get(c->opcode); if(op->flags & (OP_JUMP|OP_BRANCH)) { int j = ((int)(ptroff_t)c->data[0]); c->branch = pos2code(bytepos,c,j+4,len); } else if(op->flags & (OP_LOOKUPSWITCH)) { lookupswitch_t*l = (lookupswitch_t*)c->data[0]; int offset = 0; l->def = pos2code(bytepos,c,(ptroff_t)l->def+offset,len); code_list_t*t=l->targets; while(t) { t->code = pos2code(bytepos,c,(ptroff_t)t->code+offset,len); t = t->next; } } c = c->next; } if(codelookup) { (*codelookup) = malloc(sizeof(codelookup_t)); (*codelookup)->bytepos = bytepos; (*codelookup)->len = len; } else { free(bytepos); } return head; }
int swf_FontExtract_DefineFontInfo(int id, SWFFONT *f, TAG *t) { uint16_t fid; uint16_t maxcode; uint8_t flags; swf_SetTagPos(t, 0); fid = swf_GetU16(t); if (fid == id) { uint8_t l = swf_GetU8(t); int i; if (f->version > 1) { /* Especially with Flash MX, DefineFont2 may have FontInfo fields, too. However, they only add little information to what's already inside the DefineFont2 tag */ return id; } if (f->name) free(f->name); f->name = (uint8_t *) malloc(l + 1); swf_GetBlock(t, f->name, l); f->name[l] = 0; flags = swf_GetU8(t); if (flags & 2) f->style |= FONT_STYLE_BOLD; if (flags & 4) f->style |= FONT_STYLE_ITALIC; if (flags & 8) f->encoding |= FONT_ENCODING_ANSI; if (flags & 16) f->encoding |= FONT_ENCODING_SHIFTJIS; if (flags & 32) f->encoding |= FONT_ENCODING_UNICODE; if (t->id == ST_DEFINEFONTINFO2) { f->language = swf_GetU8(t); } f->glyph2ascii = (uint16_t *) malloc(sizeof(uint16_t) * f->numchars); maxcode = 0; for (i = 0; i < f->numchars; i++) { f->glyph2ascii[i] = ((flags & FF_WIDECODES) ? swf_GetU16(t) : swf_GetU8(t)); if (f->glyph2ascii[i] > maxcode) maxcode = f->glyph2ascii[i]; } maxcode++; if (maxcode < 256) maxcode = 256; f->maxascii = maxcode; f->ascii2glyph = (int *)malloc(sizeof(int) * maxcode); memset(f->ascii2glyph, -1, sizeof(int) * maxcode); for (i = 0; i < f->numchars; i++) f->ascii2glyph[f->glyph2ascii[i]] = i; } return id; }
int swf_FontExtract_DefineFont2(int id, SWFFONT *font, TAG *tag) { int t, glyphcount; int maxcode; int fid; uint32_t offset_start; uint32_t *offset; uint8_t flags1, /*langcode, */namelen; swf_SetTagPos(tag, 0); font->version = tag->id == ST_DEFINEFONT3 ? 3 : 2; fid = swf_GetU16(tag); if (id && id != fid) return id; font->id = fid; flags1 = swf_GetU8(tag); /*langcode = */swf_GetU8(tag); //reserved flags if (flags1 & 1) font->style |= FONT_STYLE_BOLD; if (flags1 & 2) font->style |= FONT_STYLE_ITALIC; if (flags1 & 16) font->encoding |= FONT_ENCODING_ANSI; if (flags1 & 32) font->encoding |= FONT_ENCODING_UNICODE; if (flags1 & 64) font->encoding |= FONT_ENCODING_SHIFTJIS; namelen = swf_GetU8(tag); font->name = (uint8_t *) malloc(namelen + 1); font->name[namelen] = 0; swf_GetBlock(tag, font->name, namelen); glyphcount = swf_GetU16(tag); font->numchars = glyphcount; font->glyph = (SWFGLYPH *) calloc(1, sizeof(SWFGLYPH) * glyphcount); font->glyph2ascii = (uint16_t *) calloc(1, sizeof(uint16_t) * glyphcount); offset = (uint32_t*)calloc(1, sizeof(uint32_t)*(glyphcount + 1)); offset_start = tag->pos; if (flags1 & 8) { // wide offsets for (t = 0; t < glyphcount; t++) offset[t] = swf_GetU32(tag); //offset[t] if (glyphcount) /* this _if_ is not in the specs */ offset[glyphcount] = swf_GetU32(tag); // fontcodeoffset else offset[glyphcount] = tag->pos; } else { for (t = 0; t < glyphcount; t++) offset[t] = swf_GetU16(tag); //offset[t] if (glyphcount) /* this _if_ is not in the specs */ offset[glyphcount] = swf_GetU16(tag); // fontcodeoffset else offset[glyphcount] = tag->pos; } for (t = 0; t < glyphcount; t++) { swf_SetTagPos(tag, offset[t] + offset_start); swf_GetSimpleShape(tag, &(font->glyph[t].shape)); } if (glyphcount) swf_SetTagPos(tag, offset[glyphcount] + offset_start); free(offset); maxcode = 0; for (t = 0; t < glyphcount; t++) { int code; if (flags1 & 4) // wide codes (always on for definefont3) code = swf_GetU16(tag); else code = swf_GetU8(tag); font->glyph2ascii[t] = code; if (code > maxcode) maxcode = code; } maxcode++; if (maxcode < 256) maxcode = 256; font->maxascii = maxcode; font->ascii2glyph = (int *) malloc(sizeof(int) * maxcode); memset(font->ascii2glyph, -1, sizeof(int) * maxcode); for (t = 0; t < glyphcount; t++) { font->ascii2glyph[font->glyph2ascii[t]] = t; } if (flags1 & 128) { // has layout uint16_t kerningcount; font->layout = (SWFLAYOUT *) malloc(sizeof(SWFLAYOUT)); font->layout->ascent = swf_GetU16(tag); font->layout->descent = swf_GetU16(tag); font->layout->leading = swf_GetU16(tag); for (t = 0; t < glyphcount; t++) { int16_t advance = swf_GetS16(tag); font->glyph[t].advance = advance; } font->layout->bounds = (SRECT*)malloc(glyphcount * sizeof(SRECT)); for (t = 0; t < glyphcount; t++) { swf_ResetReadBits(tag); swf_GetRect(tag, &font->layout->bounds[t]); SRECT b = font->layout->bounds[t]; if ((b.xmin | b.xmax | b.ymin | b.ymax) == 0) { // recalculate bounding box SHAPE2 *shape2 = swf_ShapeToShape2(font->glyph[t].shape); font->layout->bounds[t] = swf_GetShapeBoundingBox(shape2); swf_Shape2Free(shape2); free(shape2); } } kerningcount = swf_GetU16(tag); font->layout->kerningcount = kerningcount; font->layout->kerning = (SWFKERNING *) malloc(sizeof(SWFKERNING) * kerningcount); if (kerningcount) { font->layout->kerning = (SWFKERNING*)malloc(sizeof(*font->layout->kerning) * kerningcount); for (t = 0; t < kerningcount; t++) { if (flags1 & 4) { // wide codes font->layout->kerning[t].char1 = swf_GetU16(tag); font->layout->kerning[t].char2 = swf_GetU16(tag); } else { font->layout->kerning[t].char1 = swf_GetU8(tag); font->layout->kerning[t].char2 = swf_GetU8(tag); } font->layout->kerning[t].adjustment = swf_GetS16(tag); } } } return font->id; }