X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswftext.c;h=500d6c962834d39542fc916dd217a1ad787aea10;hb=b0b810eccb37070019e586d12adf14765c1cd354;hp=c1eafaf7f1c313ab152aeba04e29461da30a5835;hpb=6c8cd5189daa2577ca5f0d1ce4ba7ae74496467f;p=swftools.git diff --git a/lib/modules/swftext.c b/lib/modules/swftext.c index c1eafaf..500d6c9 100644 --- a/lib/modules/swftext.c +++ b/lib/modules/swftext.c @@ -33,8 +33,8 @@ #define FF2_SHIFTJIS 0x40 #define FF2_LAYOUT 0x80 -int swf_FontIsItalic(SWFFONT * f) { return f->version==2?f->flags&FF2_ITALIC:f->flags&FF_ITALIC; } -int swf_FontIsBold(SWFFONT * f) { return f->version==2?f->flags&FF2_BOLD:f->flags&FF_BOLD; } +int swf_FontIsItalic(SWFFONT * f) { return f->style&FONT_STYLE_ITALIC;} +int swf_FontIsBold(SWFFONT * f) { return f->style&FONT_STYLE_BOLD;} static const int WRITEFONTID = 0x4e46; // font id for WriteFont and ReadFont @@ -80,7 +80,7 @@ int swf_FontExtract_DefineFont(int id,SWFFONT * f,TAG * t) fid = swf_GetU16(t); if ((!id)||(id==fid)) - { U16 of,*ofs; + { U16 of; int n,i; id = fid; @@ -104,19 +104,20 @@ int swf_FontExtract_DefineFont(int id,SWFFONT * f,TAG * t) int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t) { U16 fid; U16 maxcode; + U8 flags; swf_SaveTagPos(t); swf_SetTagPos(t,0); - if(f->version>1) { - // DefineFont2 doesn't have FontInfo fields - fprintf(stderr, "fixme: FontInfo field for DefineFont2 encountered\n"); - return -1; - } - fid = swf_GetU16(t); if (fid==id) { U8 l = swf_GetU8(t); int i; + + if(f->version>1) { + // DefineFont2 doesn't have FontInfo fields + fprintf(stderr, "fixme: FontInfo field for DefineFont2 encountered\n"); + return -1; + } if (l) { if (f->name) free(f->name); @@ -130,12 +131,22 @@ int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t) return -1; } } - f->flags = swf_GetU8(t); + 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; f->glyph2ascii = (U16*)malloc(sizeof(U16)*f->numchars); maxcode = 0; for(i=0; i < f->numchars; i++) { - f->glyph2ascii[i] = ((f->flags&FF_WIDECODES)?swf_GetU16(t):swf_GetU8(t)); + f->glyph2ascii[i] = ((flags&FF_WIDECODES)?swf_GetU16(t):swf_GetU8(t)); if(f->glyph2ascii[i] > maxcode) maxcode = f->glyph2ascii[i]; } @@ -158,13 +169,30 @@ int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag) { int t, glyphcount; int maxcode; + int fid; U8 flags1,flags2,namelen; + swf_SaveTagPos(tag); + swf_SetTagPos(tag,0); font->version=2; - font->id = swf_GetU16(tag); + fid = swf_GetU16(tag); + if(id && id!=fid) + return id; + font->id = fid; flags1 = swf_GetU8(tag); flags2 = 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->flags = flags1; font->name = (U8*)malloc(namelen+1); font->name[namelen]=0; swf_GetBlock(tag, font->name, namelen); @@ -180,11 +208,15 @@ int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag) if(flags1&8) { // wide offsets for(t=0;tglyph[t].shape)); @@ -224,10 +256,12 @@ int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag) font->layout->bounds = malloc(glyphcount*sizeof(SRECT)); for(t=0;tlayout->bounds); + swf_GetRect(tag, &font->layout->bounds[t]); } + kerningcount = swf_GetU16(tag); font->layout->kerningcount = kerningcount; + font->layout->kerning = (SWFKERNING*)malloc(sizeof(SWFKERNING)*kerningcount); if(kerningcount) { font->layout->kerning = @@ -238,21 +272,24 @@ int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag) font->layout->kerning[t].char1 = swf_GetU16(tag); font->layout->kerning[t].char2 = swf_GetU16(tag); } else { - font->layout->kerning[t].char1 = swf_GetU16(tag); - font->layout->kerning[t].char2 = swf_GetU16(tag); + font->layout->kerning[t].char1 = swf_GetU8(tag); + font->layout->kerning[t].char2 = swf_GetU8(tag); } font->layout->kerning[t].adjustment = swf_GetS16(tag); } } } + swf_RestoreTagPos(t); return font->id; } #define FEDTJ_PRINT 0x01 #define FEDTJ_MODIFY 0x02 +#define FEDTJ_CALLBACK 0x04 -int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs) +int swf_FontExtract_DefineTextCallback(int id,SWFFONT * f,TAG * t,int jobs, + void(*callback)(int*chars, int nr, int fontid)) { U16 cid; SRECT r; MATRIX m; @@ -287,19 +324,25 @@ int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs) } else { int i; + int buf[256]; for (i=0;iglyph2ascii[glyph]; - if (jobs&FEDTJ_PRINT) printf("%c",code); + if (jobs&FEDTJ_PRINT) { + { int code = f->glyph2ascii[glyph]; + printf("%c",code); + } if (jobs&FEDTJ_MODIFY) /*if (!f->glyph[code].advance)*/ f->glyph[glyph].advance = adv; } + buf[i] = glyph; } if ((id==fid)&&(jobs&FEDTJ_PRINT)) printf("\n"); + if (jobs&FEDTJ_CALLBACK) + callback(buf, flags, fid); } flags = swf_GetU8(t); } @@ -308,6 +351,11 @@ int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs) return id; } +int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs) +{ + return swf_FontExtract_DefineTextCallback(id,f,t,jobs,0); +} + int swf_FontExtract(SWF * swf,int id,SWFFONT * * font) { TAG * t; SWFFONT * f; @@ -350,7 +398,7 @@ int swf_FontExtract(SWF * swf,int id,SWFFONT * * font) int swf_FontSetID(SWFFONT * f,U16 id) { if (!f) return -1; f->id = id; return 0; } int swf_FontReduce(SWFFONT * f,FONTUSAGE * use) -{ int i,j,num; +{ int i,j; if ((!f)||(!use)) return -1; j = 0; @@ -365,9 +413,9 @@ int swf_FontReduce(SWFFONT * f,FONTUSAGE * use) } else { swf_ShapeFree(f->glyph[i].shape); - f->ascii2glyph[f->glyph2ascii[i]] = -1; + f->ascii2glyph[f->glyph2ascii[i]] = -1; f->glyph2ascii[i] = 0; - f->glyph[i].shape = 0; + f->glyph[i].shape = NULL; f->glyph[i].advance = 0; } } else f->ascii2glyph[f->glyph2ascii[i]] = -1; @@ -418,9 +466,108 @@ int swf_FontSetDefine(TAG * t,SWFFONT * f) return 0; } +int swf_FontSetDefine2(TAG *tag, SWFFONT * f) +{ + U8 flags = 0; + int t; + int pos; + int pos2; + swf_SetU16(tag, f->id); + if(f->layout) + flags |= 128; // haslayout + if(f->numchars>256) + flags |= 4; // widecodes + if(f->style & FONT_STYLE_BOLD) + flags |= 1; // bold + if(f->style & FONT_STYLE_ITALIC) + flags |= 2; // italic + /* wideoffs 8 */ + if(f->encoding & FONT_ENCODING_ANSI) + flags |= 16; // ansi + if(f->encoding & FONT_ENCODING_UNICODE) + flags |= 32; // unicode + if(f->encoding & FONT_ENCODING_SHIFTJIS) + flags |= 64; // shiftjis + + swf_SetU8(tag, flags); + swf_SetU8(tag, 0); //reserved flags + if(f->name) { + /* font name */ + swf_SetU8(tag, strlen(f->name)); + swf_SetBlock(tag, f->name, strlen(f->name)); + } else { + /* font name (="") */ + swf_SetU8(tag, 0); /*placeholder*/ + } + /* number of glyphs */ + swf_SetU16(tag, f->numchars); + /* font offset table */ + pos = tag->len; + for(t=0;tnumchars;t++) + { + swf_SetU16(tag, /* fontoffset */ 0); /*placeholder*/ + } + pos2 = tag->len; + swf_SetU16(tag, 0); //fontcode-fontoffset + for(t=0;tnumchars;t++) { + tag->data[pos + t*2] = (tag->len-pos); + tag->data[pos + t*2 + 1] = (tag->len-pos) >> 8; + swf_SetSimpleShape(tag, f->glyph[t].shape); + } + + tag->data[pos2] = tag->len - pos; + tag->data[pos2 + 1] = (tag->len - pos) >> 8; + + /* font code table */ + if(flags & 4) /* wide codes */ { + for(t=0;tnumchars;t++) + swf_SetU16(tag,f->glyph2ascii[t]); + } else { + for(t=0;tnumchars;t++) + swf_SetU8(tag,f->glyph2ascii[t]); + } + if(f->layout) + { + swf_SetU16(tag,f->layout->ascent); + swf_SetU16(tag,f->layout->descent); + swf_SetU16(tag,f->layout->leading); + for(t=0;tnumchars;t++) + swf_SetU16(tag,f->glyph[t].advance); + for(t=0;tnumchars;t++) { + swf_ResetWriteBits(tag); + swf_SetRect(tag,&f->layout->bounds[t]); + } + swf_SetU16(tag, f->layout->kerningcount); + for(t=0;tlayout->kerningcount;t++) { + if(flags & 4) /* wide codes */ { + swf_SetU8(tag,f->layout->kerning[t].char1); + swf_SetU8(tag,f->layout->kerning[t].char2); + } else { + swf_SetU16(tag,f->layout->kerning[t].char1); + swf_SetU16(tag,f->layout->kerning[t].char2); + } + swf_SetU16(tag,f->layout->kerning[t].adjustment); + } + } + return 0; +} + +void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading) +{ + f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT)); + f->layout->ascent = ascent; + f->layout->descent = descent; + f->layout->leading = leading; + f->layout->kerningcount = 0; + f->layout->kerning = 0; + f->layout->bounds = (SRECT*)malloc(sizeof(SRECT)*f->numchars); + memset(f->layout->bounds, 0, sizeof(SRECT)*f->numchars); +} + int swf_FontSetInfo(TAG * t,SWFFONT * f) { int l,i; U8 wide=0; + U8 flags = 0; if ((!t)||(!f)) return -1; swf_ResetWriteBits(t); swf_SetU16(t,f->id); @@ -429,7 +576,19 @@ int swf_FontSetInfo(TAG * t,SWFFONT * f) swf_SetBlock(t,f->name,l); if(f->numchars>=256) wide=1; - swf_SetU8(t,(f->flags&0xfe)|wide); + + if(f->style & FONT_STYLE_BOLD) + flags |= 2; + if(f->style & FONT_STYLE_ITALIC) + flags |= 4; + if(f->style & FONT_ENCODING_ANSI) + flags |= 8; + if(f->style & FONT_ENCODING_SHIFTJIS) + flags |= 16; + if(f->style & FONT_ENCODING_UNICODE) + flags |= 32; + + swf_SetU8(t,(flags&0xfe)|wide); for (i=0;inumchars;i++) { if (f->glyph[i].shape) @@ -664,17 +823,40 @@ U32 swf_TextGetWidth(SWFFONT * font,U8 * s,int scale) return res; } -void swf_WriteFont(SWFFONT*font, char* filename, int useDefineFont2) +SWFFONT* swf_ReadFont(char* filename) +{ + int f; + SWF swf; + if(!filename) + return 0; + f = open(filename,O_RDONLY); + + if (f<0 || swf_ReadSWF(f,&swf)<0) + { fprintf(stderr,"%s is not a valid SWF font file or contains errors.\n",filename); + close(f); + return 0; + } + else + { SWFFONT*font; + close(f); + if(swf_FontExtract(&swf, WRITEFONTID, &font) < 0) + return 0; + swf_FreeTags(&swf); + return font; + } +} + +void swf_WriteFont(SWFFONT*font, char* filename) { SWF swf; TAG * t; SRECT r; RGBA rgb; int f; + int useDefineFont2 = 0; - if(useDefineFont2) { - fprintf(stderr, "DefineFont2 is not yet supported!\n"); - useDefineFont2 = 0; - } + if(font->layout) + useDefineFont2 = 1; /* the only thing new in definefont2 + is layout information. */ font->id = WRITEFONTID; //"FN" @@ -682,51 +864,46 @@ void swf_WriteFont(SWFFONT*font, char* filename, int useDefineFont2) swf.fileVersion = 4; swf.frameRate = 0x4000; - swf.movieSize.xmax = 20*640; - swf.movieSize.ymax = 20*480; - if(!useDefineFont2) /* if we use DefineFont1 to store the characters, we have to build a textfield to store the advance values. While at it, we can also make the whole .swf viewable */ - { - t = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); - swf.firstTag = t; - rgb.r = 0xff; - rgb.g = 0xff; - rgb.b = 0xff; - swf_SetRGB(t,&rgb); - t = swf_InsertTag(t,ST_DEFINEFONT); - } - else - { - t = swf_InsertTag(NULL,ST_DEFINEFONT); - swf.firstTag = t; - } - swf_FontSetDefine(t,font); - - t = swf_InsertTag(t,ST_DEFINEFONTINFO); - swf_FontSetInfo(t,font); + /* we now always create viewable swfs, even if we + did use definefont2 -mk*/ + t = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + swf.firstTag = t; + rgb.r = 0xff; + rgb.g = 0xff; + rgb.b = 0xff; + swf_SetRGB(t,&rgb); + if(!useDefineFont2) { + t = swf_InsertTag(t,ST_DEFINEFONT); + swf_FontSetDefine(t,font); + t = swf_InsertTag(t,ST_DEFINEFONTINFO); + swf_FontSetInfo(t,font); + } else { + t = swf_InsertTag(t,ST_DEFINEFONT2); + swf_FontSetDefine2(t,font); + } - if(!useDefineFont2) - { - int textscale = 400; + if(1) //useDefineFont2 + { int textscale = 400; int s; int xmax = 0; - int ymax = textscale * 20; + int ymax = textscale * 2 * (font->maxascii/16+1); U8 gbits,abits; - char text[257]; + char text[MAX_CHAR_PER_FONT+1]; int x,y; - text[256]=0; - for(s=0;s<256;s++) + text[MAX_CHAR_PER_FONT]=0; + for(s=0;smaxascii;s++) { int g = font->ascii2glyph[s]; text[s] = s; if(g>=0) { - if(font->glyph[g].advance*textscale/100 > xmax) - xmax = font->glyph[g].advance*textscale/100; + if(font->glyph[g].advance*textscale/200 > xmax) + xmax = font->glyph[g].advance*textscale/200; } } swf.movieSize.xmax = xmax*20; @@ -754,11 +931,12 @@ void swf_WriteFont(SWFFONT*font, char* filename, int useDefineFont2) rgb.r = 0x00; rgb.g = 0x00; rgb.b = 0x00; - for(y=0;y<16;y++) + for(y=0;y<=((font->maxascii-1)/16);y++) { - int c=0,lastx=-1, firstx=0; + int c=0,lastx=-1; + /* TODO: firstx?? */ for(x=0;x<16;x++) { - int g = font->ascii2glyph[y*16+x]; + int g = (y*16+xmaxascii)?font->ascii2glyph[y*16+x]:-1; if(g>=0 && font->glyph[g].shape) { c++; if(lastx<0) @@ -766,10 +944,10 @@ void swf_WriteFont(SWFFONT*font, char* filename, int useDefineFont2) } } if(c) { - swf_TextSetInfoRecord(t,font,textscale,&rgb,lastx+1,textscale*y); + swf_TextSetInfoRecord(t,font,textscale,&rgb,lastx+1,textscale*y*2); for(x=0;x<16;x++) { - int g = font->ascii2glyph[y*16+x]; + int g = (y*16+xmaxascii)?font->ascii2glyph[y*16+x]:-1; if(g>=0 && font->glyph[g].shape) { if(lastx != x*xmax) { swf_TextSetInfoRecord(t,0,0,0,x*xmax+1,0); @@ -784,12 +962,13 @@ void swf_WriteFont(SWFFONT*font, char* filename, int useDefineFont2) } } swf_SetU8(t,0); + - t = swf_InsertTag(t,ST_PLACEOBJECT2); + t = swf_InsertTag(t,ST_PLACEOBJECT2); - swf_ObjectPlace(t,font->id+1,1,NULL,NULL,NULL); + swf_ObjectPlace(t,font->id+1,1,NULL,NULL,NULL); - t = swf_InsertTag(t,ST_SHOWFRAME); + t = swf_InsertTag(t,ST_SHOWFRAME); } t = swf_InsertTag(t,ST_END); @@ -801,26 +980,41 @@ void swf_WriteFont(SWFFONT*font, char* filename, int useDefineFont2) swf_FreeTags(&swf); } -SWFFONT* swf_ReadFont(char* filename) + +void swf_SetEditText(TAG*tag, U16 flags, SRECT r, char*text, RGBA*color, + int maxlength, U16 font, U16 height, EditTextLayout*layout, char*variable) { - int f; - SWF swf; - if(!filename) - return 0; - f = open(filename,O_RDONLY); - - if (f<0 || swf_ReadSWF(f,&swf)<0) - { fprintf(stderr,"%s is not a valid SWF font file or contains errors.\n",filename); - close(f); - return 0; - } - else - { SWFFONT*font; - close(f); - if(swf_FontExtract(&swf, WRITEFONTID, &font) < 0) - return 0; - swf_FreeTags(&swf); - return font; - } + swf_SetRect(tag,&r); + swf_ResetWriteBits(tag); + + flags &= ~(ET_HASTEXT|ET_HASTEXTCOLOR|ET_HASMAXLENGTH|ET_HASFONT|ET_HASLAYOUT); + if(text) flags |= ET_HASTEXT; + if(color) flags |= ET_HASTEXTCOLOR; + if(maxlength) flags |= ET_HASMAXLENGTH; + if(font) flags |= ET_HASFONT; + if(layout) flags |= ET_HASLAYOUT; + + swf_SetBits(tag, flags, 16); + + if(flags & ET_HASFONT) { + swf_SetU16(tag, font); //font + swf_SetU16(tag, height); //fontheight + } + if(flags & ET_HASTEXTCOLOR) { + swf_SetRGBA(tag, color); + } + if(flags & ET_HASMAXLENGTH) { + swf_SetU16(tag, maxlength); //maxlength + } + if(flags & ET_HASLAYOUT) { + swf_SetU8(tag,layout->align); //align + swf_SetU16(tag,layout->leftmargin); //left margin + swf_SetU16(tag,layout->rightmargin); //right margin + swf_SetU16(tag,layout->indent); //indent + swf_SetU16(tag,layout->leading); //leading + } + swf_SetString(tag, variable); + if(flags & ET_HASTEXT) + swf_SetString(tag,text); }