X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswftext.c;h=30e877fddc7b166ecf514b81b1f9f65c3a760ab8;hb=a96acf64e3570fd1ef0c91d9883d1238398b1b38;hp=dc7aead611ce2a726128f9dad7305ec8fe90bf41;hpb=ac01acb114280085987db02ecdd7d0608a5c2a67;p=swftools.git diff --git a/lib/modules/swftext.c b/lib/modules/swftext.c index dc7aead..30e877f 100644 --- a/lib/modules/swftext.c +++ b/lib/modules/swftext.c @@ -46,7 +46,7 @@ int swf_FontEnumerate(SWF * swf,void (*FontCallback) (U16,U8*)) n = 0; while (t) - { if (swf_GetTagID(t)==ST_DEFINEFONTINFO || + { if (swf_GetTagID(t)==ST_DEFINEFONTINFO || swf_GetTagID(t)==ST_DEFINEFONTINFO2 || swf_GetTagID(t)==ST_DEFINEFONT2) { n++; if (FontCallback) @@ -114,23 +114,18 @@ int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t) int i; if(f->version>1) { - // DefineFont2 doesn't have FontInfo fields - fprintf(stderr, "fixme: FontInfo field for DefineFont2 encountered\n"); - return -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 (l) - { if (f->name) free(f->name); - f->name = (U8*)malloc(l+1); - if (f->name) - { swf_GetBlock(t,f->name,l); - f->name[l] = 0; - } - else - { swf_RestoreTagPos(t); - return -1; - } - } + if (f->name) free(f->name); + + f->name = (U8*)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; @@ -143,6 +138,10 @@ int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t) if(flags & 32) f->encoding |= FONT_ENCODING_UNICODE; + if(t->id == ST_DEFINEFONTINFO2) { + f->language = swf_GetU8(t); + } + f->glyph2ascii = (U16*)malloc(sizeof(U16)*f->numchars); maxcode = 0; for(i=0; i < f->numchars; i++) { @@ -362,9 +361,7 @@ int swf_FontExtract(SWF * swf,int id,SWFFONT * * font) if ((!swf)||(!font)) return -1; - f = (SWFFONT *)malloc(sizeof(SWFFONT)); font[0] = f; - if (!f) return -1; - + f = (SWFFONT *)malloc(sizeof(SWFFONT)); memset(f,0x00,sizeof(SWFFONT)); t = swf->firstTag; @@ -392,6 +389,11 @@ int swf_FontExtract(SWF * swf,int id,SWFFONT * * font) if (nid>0) id = nid; t = swf_NextTag(t); } + if(f->id != id) { + free(f); + f=0; + } + font[0] = f; return 0; } @@ -456,6 +458,10 @@ int swf_FontSetDefine(TAG * t,SWFFONT * f) } for (i=0;inumchars;i++) if (f->glyph[i].shape) @@ -571,9 +577,10 @@ int swf_FontSetInfo(TAG * t,SWFFONT * f) if ((!t)||(!f)) return -1; swf_ResetWriteBits(t); swf_SetU16(t,f->id); - l = strlen(f->name); if (l>255) l = 255; + l = f->name?strlen(f->name):0; if (l>255) l = 255; swf_SetU8(t,l); - swf_SetBlock(t,f->name,l); + if(l) + swf_SetBlock(t,f->name,l); if(f->numchars>=256) wide=1; @@ -673,7 +680,9 @@ int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits) while(s[0]) { - int glyph = font->ascii2glyph[s[0]]; + int glyph = -1; + if(s[0] < font->maxascii) + glyph = font->ascii2glyph[s[0]]; if(glyph>=0) { g = swf_CountBits(glyph,g); a = swf_CountBits((((U32)font->glyph[glyph].advance)*scale)/100,a); @@ -688,23 +697,29 @@ int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits) } int swf_TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 abits) -{ int l,i; +{ int l=0,i,pos; if ((!t)||(!font)||(!s)||(!font->ascii2glyph)) return -1; - l = strlen(s); - if (l>0x7f) l = 0x7f; - swf_SetU8(t,l); + pos = t->len; + swf_SetU8(t, l); //placeholder - for (i=0;iascii2glyph[s[i]]; + int g = -1; + if(s[i] < font->maxascii) + g = font->ascii2glyph[s[i]]; if(g>=0) { swf_SetBits(t,g,gbits); swf_SetBits(t,(((U32)font->glyph[g].advance)*scale)/100,abits); + l++; + if(l==0x7f) + break; } } + PUT8(&t->data[pos], l); + swf_ResetWriteBits(t); return 0; } @@ -715,7 +730,9 @@ U32 swf_TextGetWidth(SWFFONT * font,U8 * s,int scale) if (font&&s) { while (s[0]) { - int g = font->ascii2glyph[*s]; + int g = -1; + if(*s < font->maxascii) + g = font->ascii2glyph[*s]; if(g>=0) res += font->glyph[g].advance; s++; @@ -796,7 +813,7 @@ void swf_WriteFont(SWFFONT*font, char* filename) int xmax = 0; int ymax = textscale * 2 * (font->maxascii/16+1); U8 gbits,abits; - char text[MAX_CHAR_PER_FONT+1]; + U8 text[MAX_CHAR_PER_FONT+1]; int x,y; text[MAX_CHAR_PER_FONT]=0; for(s=0;smaxascii;s++) @@ -920,21 +937,104 @@ void swf_SetEditText(TAG*tag, U16 flags, SRECT r, char*text, RGBA*color, swf_SetString(tag,text); } -void swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale) +SRECT swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale) { SRECT r; U8 gbits, abits; - - r.xmin = r.ymin = 0; /*FIXME*/ - r.xmax = r.ymax = 1024*20; + U8*c = (U8*)text; + int pos = 0; + swf_GetRect(0, &r); + if(font->layout) { + while(*c) { + if(*c < font->maxascii) { + int g = font->ascii2glyph[*c]; + if(g>=0) { + SRECT rn = font->layout->bounds[g]; + rn.xmin = (rn.xmin * scale)/100 + pos; + rn.xmax = (rn.xmax * scale)/100 + pos; + rn.ymin = (rn.ymin * scale)/100; + rn.ymax = (rn.ymax * scale)/100; + swf_ExpandRect2(&r, &rn); + pos += (font->glyph[g].advance*scale*20)/100; + } + } + c++; + } + } else { + /* Hm, without layout information, we can't compute a bounding + box. We could call swf_FontCreateLayout to create a layout, + but the caller probably doesn't want us to mess up his font + structure. + */ + r.xmin = r.ymin = 0; + r.xmax = r.ymax = 1024*20; + } swf_SetRect(tag,&r); swf_SetMatrix(tag,NULL); - swf_TextCountBits(font,text,scale,&gbits,&abits); + swf_TextCountBits(font,text,scale*20,&gbits,&abits); swf_SetU8(tag,gbits); swf_SetU8(tag,abits); - swf_TextSetInfoRecord(tag,font,scale,rgb,0,scale); - swf_TextSetCharRecord(tag,font,text,scale,gbits,abits); + + /* now set the text params- notice that a font size of + 1024 means that the glyphs will be displayed exactly + as they would be in/with a defineshape. (Try to find + *that* in the flash specs) + */ + swf_TextSetInfoRecord(tag,font,(scale*1024)/100,rgb,0,0); //scale + + /* set the actual text- notice that we just pass our scale + parameter over, as TextSetCharRecord calculates with + percent, too */ + swf_TextSetCharRecord(tag,font,text,scale*20,gbits,abits); + swf_SetU8(tag,0); + return r; } +void swf_FontCreateLayout(SWFFONT*f) +{ + S16 leading = 0; + int t; + if(f->layout) + return; + if(!f->numchars) + return; + + f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT)); + memset(f->layout, 0, sizeof(SWFLAYOUT)); + f->layout->bounds = (SRECT*)malloc(f->numchars*sizeof(SRECT)); + f->layout->ascent = -32767; + f->layout->descent = -32767; + + for(t=0;tnumchars;t++) { + SHAPE2*shape2; + SRECT bbox; + int width; + shape2 = swf_ShapeToShape2(f->glyph[t].shape); + if(!shape2) { + fprintf(stderr, "Shape parse error\n");exit(1); + } + bbox = swf_GetShapeBoundingBox(shape2->lines); + swf_Shape2Free(shape2); + f->layout->bounds[t] = bbox; + /* FIXME */ + //width = (bbox.xmax - bbox.xmin)/20; + width = (bbox.xmax)/20; + + /* The following is a heuristic- it may be that extractfont_DefineText + has already found out some widths for individual characters (from the way + they are used)- we now have to guess whether that width might be possible, + which is the case if it isn't either much too big or much too small */ + if(width > f->glyph[t].advance*3/2 || + width*2 < f->glyph[t].advance) + f->glyph[t].advance = width; + + if(-bbox.ymin > f->layout->ascent) + f->layout->ascent = bbox.ymin; + if(bbox.ymax > f->layout->descent) + f->layout->descent = bbox.ymax; + } +} + +