5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
10 This file is distributed under the GPL, see file COPYING for details
14 #define TF_TEXTCONTROL 0x80
15 #define TF_HASFONT 0x08
16 #define TF_HASCOLOR 0x04
17 #define TF_HASYOFFSET 0x02
18 #define TF_HASXOFFSET 0x01
20 #define FF_WIDECODES 0x01
22 #define FF_ITALIC 0x04
24 #define FF_SHIFTJIS 0x10
25 #define FF_UNICODE 0x20
28 #define FF2_ITALIC 0x02
29 #define FF2_WIDECODES 0x04
30 #define FF2_WIDEOFFSETS 0x08
32 #define FF2_UNICODE 0x20
33 #define FF2_SHIFTJIS 0x40
34 #define FF2_LAYOUT 0x80
36 int swf_FontIsItalic(SWFFONT * f) { return f->style&FONT_STYLE_ITALIC;}
37 int swf_FontIsBold(SWFFONT * f) { return f->style&FONT_STYLE_BOLD;}
39 static const int WRITEFONTID = 0x4e46; // font id for WriteFont and ReadFont
41 int swf_FontEnumerate(SWF * swf,void (*FontCallback) (U16,U8*))
49 { if (swf_GetTagID(t)==ST_DEFINEFONTINFO || swf_GetTagID(t)==ST_DEFINEFONTINFO2 ||
50 swf_GetTagID(t)==ST_DEFINEFONT2)
60 if(swf_GetTagID(t) == ST_DEFINEFONT2)
76 int swf_FontExtract_DefineFont(int id,SWFFONT * f,TAG * t)
93 f->glyph = malloc(sizeof(SWFGLYPH)*n);
94 memset(f->glyph, 0, sizeof(SWFGLYPH)*n);
96 for (i=1;i<n;i++) swf_GetU16(t);
97 for (i=0;i<n;i++) swf_GetSimpleShape(t,&f->glyph[i].shape);
100 swf_RestoreTagPos(t);
104 int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t)
113 { U8 l = swf_GetU8(t);
117 /* Especially with Flash MX, DefineFont2 may have FontInfo fields,
118 too. However, they only add little information to what's already
119 inside the DefineFont2 tag */
123 if (f->name) free(f->name);
125 f->name = (U8*)malloc(l+1);
126 swf_GetBlock(t,f->name,l);
129 flags = swf_GetU8(t);
131 f->style |= FONT_STYLE_BOLD;
133 f->style |= FONT_STYLE_ITALIC;
135 f->encoding |= FONT_ENCODING_ANSI;
137 f->encoding |= FONT_ENCODING_SHIFTJIS;
139 f->encoding |= FONT_ENCODING_UNICODE;
141 if(t->id == ST_DEFINEFONTINFO2) {
142 f->language = swf_GetU8(t);
145 f->glyph2ascii = (U16*)malloc(sizeof(U16)*f->numchars);
147 for(i=0; i < f->numchars; i++) {
148 f->glyph2ascii[i] = ((flags&FF_WIDECODES)?swf_GetU16(t):swf_GetU8(t));
149 if(f->glyph2ascii[i] > maxcode)
150 maxcode = f->glyph2ascii[i];
155 f->maxascii = maxcode;
156 f->ascii2glyph = (int*)malloc(sizeof(int)*maxcode);
157 memset(f->ascii2glyph, -1, sizeof(int)*maxcode);
159 for(i = 0; i < f->numchars; i++)
160 f->ascii2glyph[f->glyph2ascii[i]] = i;
163 swf_RestoreTagPos(t);
167 int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag)
172 U8 flags1,flags2,namelen;
174 swf_SetTagPos(tag,0);
176 fid = swf_GetU16(tag);
180 flags1 = swf_GetU8(tag);
181 flags2 = swf_GetU8(tag); //reserved flags
184 font->style |= FONT_STYLE_BOLD;
186 font->style |= FONT_STYLE_ITALIC;
188 font->encoding |= FONT_ENCODING_ANSI;
190 font->encoding |= FONT_ENCODING_UNICODE;
192 font->encoding |= FONT_ENCODING_SHIFTJIS;
194 namelen = swf_GetU8(tag);
195 font->name = (U8*)malloc(namelen+1);
196 font->name[namelen]=0;
197 swf_GetBlock(tag, font->name, namelen);
199 glyphcount = swf_GetU16(tag);
200 font->numchars = glyphcount;
202 font->glyph = (SWFGLYPH*)malloc(sizeof(SWFGLYPH)*glyphcount);
203 memset(font->glyph, 0, sizeof(SWFGLYPH)*glyphcount);
204 font->glyph2ascii = (U16*)malloc(sizeof(U16)*glyphcount);
205 memset(font->glyph2ascii, 0, sizeof(U16)*glyphcount);
207 if(flags1&8) { // wide offsets
208 for(t=0;t<glyphcount;t++)
209 swf_GetU32(tag); //offset[t]
211 if(glyphcount) /* this _if_ is not in the specs */
212 swf_GetU32(tag); // fontcodeoffset
214 for(t=0;t<glyphcount;t++)
215 swf_GetU16(tag); //offset[t]
217 if(glyphcount) /* this _if_ is not in the specs */
218 swf_GetU16(tag); // fontcodeoffset
220 for(t=0;t<glyphcount;t++)
221 swf_GetSimpleShape(tag,&(font->glyph[t].shape));
224 for(t=0;t<glyphcount;t++) {
226 if(flags1&4) // wide codes
227 code = swf_GetU16(tag);
229 code = swf_GetU8(tag);
230 font->glyph2ascii[t] = code;
237 font->maxascii = maxcode;
238 font->ascii2glyph = (int*)malloc(sizeof(int)*maxcode);
239 memset(font->ascii2glyph, -1, sizeof(int)*maxcode);
240 for(t=0;t<glyphcount;t++)
242 font->ascii2glyph[font->glyph2ascii[t]] = t;
245 if(flags1&128) { // has layout
247 font->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
248 font->layout->ascent=swf_GetU16(tag);
249 font->layout->descent=swf_GetU16(tag);
250 font->layout->leading=swf_GetU16(tag);
251 for(t=0;t<glyphcount;t++) {
252 S16 advance = swf_GetS16(tag);
253 font->glyph[t].advance = advance;
255 font->layout->bounds = malloc(glyphcount*sizeof(SRECT));
256 for(t=0;t<glyphcount;t++) {
257 swf_ResetReadBits(tag);
258 swf_GetRect(tag, &font->layout->bounds[t]);
261 kerningcount = swf_GetU16(tag);
262 font->layout->kerningcount = kerningcount;
264 font->layout->kerning = (SWFKERNING*)malloc(sizeof(SWFKERNING)*kerningcount);
266 font->layout->kerning =
267 malloc(sizeof(*font->layout->kerning)* kerningcount);
268 for(t=0;t<kerningcount;t++)
270 if(flags1&4) { // wide codes
271 font->layout->kerning[t].char1 = swf_GetU16(tag);
272 font->layout->kerning[t].char2 = swf_GetU16(tag);
274 font->layout->kerning[t].char1 = swf_GetU8(tag);
275 font->layout->kerning[t].char2 = swf_GetU8(tag);
277 font->layout->kerning[t].adjustment = swf_GetS16(tag);
281 swf_RestoreTagPos(t);
286 #define FEDTJ_PRINT 0x01
287 #define FEDTJ_MODIFY 0x02
288 #define FEDTJ_CALLBACK 0x04
290 int swf_FontExtract_DefineTextCallback(int id,SWFFONT * f,TAG * t,int jobs,
291 void(*callback)(int*chars, int nr, int fontid))
295 U8 gbits, abits, flags;
306 gbits = swf_GetU8(t);
307 abits = swf_GetU8(t);
309 flags = swf_GetU8(t);
312 { if (flags&TF_TEXTCONTROL)
313 { if (flags&TF_HASFONT) fid = swf_GetU16(t);
314 if (flags&TF_HASCOLOR)
315 { swf_GetU8(t); // rgb
318 if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_GetU8(t);
320 if (flags&TF_HASXOFFSET) swf_GetS16(t);
321 if (flags&TF_HASYOFFSET) swf_GetS16(t);
322 if (flags&TF_HASFONT) swf_GetU16(t);
327 for (i=0;i<flags;i++)
330 glyph = swf_GetBits(t,gbits);
331 adv = swf_GetBits(t,abits);
332 if (id==fid) // mitlesen ?
333 if (jobs&FEDTJ_PRINT) {
334 { int code = f->glyph2ascii[glyph];
337 if (jobs&FEDTJ_MODIFY)
338 /*if (!f->glyph[code].advance)*/ f->glyph[glyph].advance = adv;
342 if ((id==fid)&&(jobs&FEDTJ_PRINT)) printf("\n");
343 if (jobs&FEDTJ_CALLBACK)
344 callback(buf, flags, fid);
346 flags = swf_GetU8(t);
349 swf_RestoreTagPos(t);
353 int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs)
355 return swf_FontExtract_DefineTextCallback(id,f,t,jobs,0);
358 int swf_FontExtract(SWF * swf,int id,SWFFONT * * font)
362 if ((!swf)||(!font)) return -1;
364 f = (SWFFONT *)malloc(sizeof(SWFFONT));
365 memset(f,0x00,sizeof(SWFFONT));
371 switch (swf_GetTagID(t))
372 { case ST_DEFINEFONT:
373 nid = swf_FontExtract_DefineFont(id,f,t);
377 nid = swf_FontExtract_DefineFont2(id,f,t);
380 case ST_DEFINEFONTINFO:
381 case ST_DEFINEFONTINFO2:
382 nid = swf_FontExtract_DefineFontInfo(id,f,t);
387 nid = swf_FontExtract_DefineText(id,f,t,f->layout?0:FEDTJ_MODIFY);
401 int swf_FontSetID(SWFFONT * f,U16 id) { if (!f) return -1; f->id = id; return 0; }
403 int swf_FontReduce(SWFFONT * f,FONTUSAGE * use)
405 if ((!f)||(!use)) return -1;
408 for (i=0;i<f->numchars;i++)
409 if (f->glyph[i].shape)
410 { if (f->glyph2ascii[i]<MAX_CHAR_PER_FONT &&
411 use->code[f->glyph2ascii[i]])
412 { f->ascii2glyph[f->glyph2ascii[i]] = j;
413 f->glyph2ascii[j] = f->glyph2ascii[i];
414 f->glyph[j] = f->glyph[i];
418 { swf_ShapeFree(f->glyph[i].shape);
419 f->ascii2glyph[f->glyph2ascii[i]] = -1;
420 f->glyph2ascii[i] = 0;
421 f->glyph[i].shape = NULL;
422 f->glyph[i].advance = 0;
424 } else f->ascii2glyph[f->glyph2ascii[i]] = -1;
431 int swf_FontInitUsage(FONTUSAGE * use)
432 { if (!use) return -1;
433 memset(use->code,0,sizeof(use->code[0])*MAX_CHAR_PER_FONT);
437 int swf_FontUse(FONTUSAGE * use,U8 * s)
438 { if ((!use)||(!s)) return -1;
440 { use->code[s[0]] = 1;
446 int swf_FontSetDefine(TAG * t,SWFFONT * f)
447 { U16*ofs = (U16*)malloc(f->numchars*2);
450 if ((!t)||(!f)) return -1;
451 swf_ResetWriteBits(t);
455 for (i=0;i<f->numchars;i++)
456 if (f->glyph[i].shape)
458 p+=swf_SetSimpleShape(NULL,f->glyph[i].shape);
461 for (i=0;i<j;i++) swf_SetU16(t,ofs[i]+j*2);
463 fprintf(stderr, "rfxswf: warning: Font is empty\n");
467 for (i=0;i<f->numchars;i++)
468 if (f->glyph[i].shape)
469 swf_SetSimpleShape(t,f->glyph[i].shape);
471 swf_ResetWriteBits(t);
476 int swf_FontSetDefine2(TAG *tag, SWFFONT * f)
482 swf_SetU16(tag, f->id);
484 flags |= 128; // haslayout
486 flags |= 4; // widecodes
487 if(f->style & FONT_STYLE_BOLD)
489 if(f->style & FONT_STYLE_ITALIC)
490 flags |= 2; // italic
492 if(f->encoding & FONT_ENCODING_ANSI)
494 if(f->encoding & FONT_ENCODING_UNICODE)
495 flags |= 32; // unicode
496 if(f->encoding & FONT_ENCODING_SHIFTJIS)
497 flags |= 64; // shiftjis
499 swf_SetU8(tag, flags);
500 swf_SetU8(tag, 0); //reserved flags
503 swf_SetU8(tag, strlen(f->name));
504 swf_SetBlock(tag, f->name, strlen(f->name));
506 /* font name (="") */
507 swf_SetU8(tag, 0); /*placeholder*/
509 /* number of glyphs */
510 swf_SetU16(tag, f->numchars);
511 /* font offset table */
513 for(t=0;t<f->numchars;t++)
515 swf_SetU16(tag, /* fontoffset */ 0); /*placeholder*/
518 swf_SetU16(tag, 0); //fontcode-fontoffset
519 for(t=0;t<f->numchars;t++) {
520 tag->data[pos + t*2] = (tag->len-pos);
521 tag->data[pos + t*2 + 1] = (tag->len-pos) >> 8;
522 swf_SetSimpleShape(tag, f->glyph[t].shape);
525 tag->data[pos2] = tag->len - pos;
526 tag->data[pos2 + 1] = (tag->len - pos) >> 8;
528 /* font code table */
529 if(flags & 4) /* wide codes */ {
530 for(t=0;t<f->numchars;t++)
531 swf_SetU16(tag,f->glyph2ascii[t]);
533 for(t=0;t<f->numchars;t++)
534 swf_SetU8(tag,f->glyph2ascii[t]);
538 swf_SetU16(tag,f->layout->ascent);
539 swf_SetU16(tag,f->layout->descent);
540 swf_SetU16(tag,f->layout->leading);
541 for(t=0;t<f->numchars;t++)
542 swf_SetU16(tag,f->glyph[t].advance);
543 for(t=0;t<f->numchars;t++) {
544 swf_ResetWriteBits(tag);
545 swf_SetRect(tag,&f->layout->bounds[t]);
547 swf_SetU16(tag, f->layout->kerningcount);
548 for(t=0;t<f->layout->kerningcount;t++) {
549 if(flags & 4) /* wide codes */ {
550 swf_SetU8(tag,f->layout->kerning[t].char1);
551 swf_SetU8(tag,f->layout->kerning[t].char2);
553 swf_SetU16(tag,f->layout->kerning[t].char1);
554 swf_SetU16(tag,f->layout->kerning[t].char2);
556 swf_SetU16(tag,f->layout->kerning[t].adjustment);
562 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading)
564 f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
565 f->layout->ascent = ascent;
566 f->layout->descent = descent;
567 f->layout->leading = leading;
568 f->layout->kerningcount = 0;
569 f->layout->kerning = 0;
570 f->layout->bounds = (SRECT*)malloc(sizeof(SRECT)*f->numchars);
571 memset(f->layout->bounds, 0, sizeof(SRECT)*f->numchars);
574 int swf_FontSetInfo(TAG * t,SWFFONT * f)
578 if ((!t)||(!f)) return -1;
579 swf_ResetWriteBits(t);
581 l = f->name?strlen(f->name):0; if (l>255) l = 255;
584 swf_SetBlock(t,f->name,l);
588 if(f->style & FONT_STYLE_BOLD)
590 if(f->style & FONT_STYLE_ITALIC)
592 if(f->style & FONT_ENCODING_ANSI)
594 if(f->style & FONT_ENCODING_SHIFTJIS)
596 if(f->style & FONT_ENCODING_UNICODE)
599 swf_SetU8(t,(flags&0xfe)|wide);
601 for (i=0;i<f->numchars;i++) {
602 if (f->glyph[i].shape)
603 wide?swf_SetU16(t,f->glyph2ascii[i]):
604 swf_SetU8(t,f->glyph2ascii[i]);
610 int swf_TextPrintDefineText(TAG * t,SWFFONT * f)
611 { int id = swf_GetTagID(t);
612 if ((id==ST_DEFINETEXT)||(id==ST_DEFINETEXT2)) swf_FontExtract_DefineText(f->id,f,t,FEDTJ_PRINT);
617 void swf_LayoutFree(SWFLAYOUT * l)
619 { if (l->kerning) free(l->kerning);
621 if (l->bounds) free(l->bounds);
627 void swf_FontFree(SWFFONT * f)
631 if (f->name) free(f->name);
632 if (f->layout) swf_LayoutFree(f->layout);
638 for (i=0;i<f->numchars;i++)
639 if (f->glyph[i].shape)
640 { swf_ShapeFree(f->glyph[i].shape);
641 f->glyph[i].shape = NULL;
647 free(f->ascii2glyph);
648 f->ascii2glyph = NULL;
651 free(f->glyph2ascii);
652 f->glyph2ascii = NULL;
658 int swf_TextSetInfoRecord(TAG * t,SWFFONT * font,U16 size,RGBA * color,S16 dx,S16 dy)
662 flags = TF_TEXTCONTROL|(font?TF_HASFONT:0)|(color?TF_HASCOLOR:0)|(dx?TF_HASXOFFSET:0)|(dy?TF_HASYOFFSET:0);
665 if (font) swf_SetU16(t,font->id);
667 { if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_SetRGBA(t,color);
668 else swf_SetRGB(t,color);
670 if (dx) swf_SetS16(t,dx);
671 if (dy) swf_SetS16(t,dy);
672 if (font) swf_SetU16(t,size);
677 int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits)
679 if ((!s)||(!font)||((!gbits)&&(!abits))||(!font->ascii2glyph)) return -1;
685 if(s[0] < font->maxascii)
686 glyph = font->ascii2glyph[s[0]];
688 g = swf_CountBits(glyph,g);
689 a = swf_CountBits((((U32)font->glyph[glyph].advance)*scale)/100,a);
694 if (gbits) gbits[0] = (U8)g;
695 if (abits) abits[0] = (U8)a;
700 int swf_TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 abits)
703 if ((!t)||(!font)||(!s)||(!font->ascii2glyph)) return -1;
706 swf_SetU8(t, l); //placeholder
711 if(s[i] < font->maxascii)
712 g = font->ascii2glyph[s[i]];
714 swf_SetBits(t,g,gbits);
715 swf_SetBits(t,(((U32)font->glyph[g].advance)*scale)/100,abits);
722 PUT8(&t->data[pos], l);
724 swf_ResetWriteBits(t);
728 U32 swf_TextGetWidth(SWFFONT * font,U8 * s,int scale)
735 if(*s < font->maxascii)
736 g = font->ascii2glyph[*s];
738 res += font->glyph[g].advance;
741 if (scale) res = (res*scale)/100;
746 SWFFONT* swf_ReadFont(char* filename)
752 f = open(filename,O_RDONLY);
754 if (f<0 || swf_ReadSWF(f,&swf)<0)
755 { fprintf(stderr,"%s is not a valid SWF font file or contains errors.\n",filename);
762 if(swf_FontExtract(&swf, WRITEFONTID, &font) < 0)
769 void swf_WriteFont(SWFFONT*font, char* filename)
775 int useDefineFont2 = 0;
778 useDefineFont2 = 1; /* the only thing new in definefont2
779 is layout information. */
781 font->id = WRITEFONTID; //"FN"
783 memset(&swf,0x00,sizeof(SWF));
786 swf.frameRate = 0x4000;
788 /* if we use DefineFont1 to store the characters,
789 we have to build a textfield to store the
790 advance values. While at it, we can also
791 make the whole .swf viewable */
793 /* we now always create viewable swfs, even if we
794 did use definefont2 -mk*/
795 t = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
801 if(!useDefineFont2) {
802 t = swf_InsertTag(t,ST_DEFINEFONT);
803 swf_FontSetDefine(t,font);
804 t = swf_InsertTag(t,ST_DEFINEFONTINFO);
805 swf_FontSetInfo(t,font);
807 t = swf_InsertTag(t,ST_DEFINEFONT2);
808 swf_FontSetDefine2(t,font);
811 if(1) //useDefineFont2
812 { int textscale = 400;
815 int ymax = textscale * 2 * (font->maxascii/16+1);
817 U8 text[MAX_CHAR_PER_FONT+1];
819 text[MAX_CHAR_PER_FONT]=0;
820 for(s=0;s<font->maxascii;s++)
822 int g = font->ascii2glyph[s];
825 if(font->glyph[g].advance*textscale/64 > xmax)
826 xmax = font->glyph[g].advance*textscale/64;
829 swf.movieSize.xmax = xmax*20;
830 swf.movieSize.ymax = ymax;
832 t = swf_InsertTag(t,ST_DEFINETEXT);
834 swf_SetU16(t,font->id+1); // ID
838 r.xmax = swf.movieSize.xmax*20;
839 r.ymax = swf.movieSize.ymax;
843 swf_SetMatrix(t,NULL);
845 abits = swf_CountBits(xmax*16, 0);
854 for(y=0;y<=((font->maxascii-1)/16);y++)
859 int g = (y*16+x<font->maxascii)?font->ascii2glyph[y*16+x]:-1;
860 if(g>=0 && font->glyph[g].shape) {
867 swf_TextSetInfoRecord(t,font,textscale,&rgb,lastx+1,textscale*y*2);
870 int g = (y*16+x<font->maxascii)?font->ascii2glyph[y*16+x]:-1;
871 if(g>=0 && font->glyph[g].shape) {
872 if(lastx != x*xmax) {
873 swf_TextSetInfoRecord(t,0,0,0,x*xmax+1,0);
876 swf_SetBits(t, g, gbits);
877 swf_SetBits(t, font->glyph[g].advance, abits);
878 lastx = x*xmax+font->glyph[g].advance;
879 swf_ResetWriteBits(t);
887 t = swf_InsertTag(t,ST_PLACEOBJECT2);
889 swf_ObjectPlace(t,font->id+1,1,NULL,NULL,NULL);
891 t = swf_InsertTag(t,ST_SHOWFRAME);
894 t = swf_InsertTag(t,ST_END);
896 f = open(filename, O_RDWR|O_CREAT|O_TRUNC,0644);
897 if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed in writeFont().\n");
904 void swf_SetEditText(TAG*tag, U16 flags, SRECT r, char*text, RGBA*color,
905 int maxlength, U16 font, U16 height, EditTextLayout*layout, char*variable)
908 swf_ResetWriteBits(tag);
910 flags &= ~(ET_HASTEXT|ET_HASTEXTCOLOR|ET_HASMAXLENGTH|ET_HASFONT|ET_HASLAYOUT);
911 if(text) flags |= ET_HASTEXT;
912 if(color) flags |= ET_HASTEXTCOLOR;
913 if(maxlength) flags |= ET_HASMAXLENGTH;
914 if(font) flags |= ET_HASFONT;
915 if(layout) flags |= ET_HASLAYOUT;
917 swf_SetBits(tag, flags, 16);
919 if(flags & ET_HASFONT) {
920 swf_SetU16(tag, font); //font
921 swf_SetU16(tag, height); //fontheight
923 if(flags & ET_HASTEXTCOLOR) {
924 swf_SetRGBA(tag, color);
926 if(flags & ET_HASMAXLENGTH) {
927 swf_SetU16(tag, maxlength); //maxlength
929 if(flags & ET_HASLAYOUT) {
930 swf_SetU8(tag,layout->align); //align
931 swf_SetU16(tag,layout->leftmargin); //left margin
932 swf_SetU16(tag,layout->rightmargin); //right margin
933 swf_SetU16(tag,layout->indent); //indent
934 swf_SetU16(tag,layout->leading); //leading
936 swf_SetString(tag, variable);
937 if(flags & ET_HASTEXT)
938 swf_SetString(tag,text);
941 SRECT swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale)
950 if(*c < font->maxascii) {
951 int g = font->ascii2glyph[*c];
953 SRECT rn = font->layout->bounds[g];
954 rn.xmin = (rn.xmin * scale)/100 + pos;
955 rn.xmax = (rn.xmax * scale)/100 + pos;
956 rn.ymin = (rn.ymin * scale)/100;
957 rn.ymax = (rn.ymax * scale)/100;
958 swf_ExpandRect2(&r, &rn);
959 pos += (font->glyph[g].advance*scale*20)/100;
965 /* Hm, without layout information, we can't compute a bounding
966 box. We could call swf_FontCreateLayout to create a layout,
967 but the caller probably doesn't want us to mess up his font
971 r.xmax = r.ymax = 1024*20;
975 swf_SetMatrix(tag,NULL);
976 swf_TextCountBits(font,text,scale*20,&gbits,&abits);
977 swf_SetU8(tag,gbits);
978 swf_SetU8(tag,abits);
980 /* now set the text params- notice that a font size of
981 1024 means that the glyphs will be displayed exactly
982 as they would be in/with a defineshape. (Try to find
983 *that* in the flash specs)
985 swf_TextSetInfoRecord(tag,font,(scale*1024)/100,rgb,0,0); //scale
987 /* set the actual text- notice that we just pass our scale
988 parameter over, as TextSetCharRecord calculates with
990 swf_TextSetCharRecord(tag,font,text,scale*20,gbits,abits);
996 void swf_FontCreateLayout(SWFFONT*f)
1005 f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
1006 memset(f->layout, 0, sizeof(SWFLAYOUT));
1007 f->layout->bounds = (SRECT*)malloc(f->numchars*sizeof(SRECT));
1008 f->layout->ascent = -32767;
1009 f->layout->descent = -32767;
1011 for(t=0;t<f->numchars;t++) {
1015 shape2 = swf_ShapeToShape2(f->glyph[t].shape);
1017 fprintf(stderr, "Shape parse error\n");exit(1);
1019 bbox = swf_GetShapeBoundingBox(shape2->lines);
1020 swf_Shape2Free(shape2);
1021 f->layout->bounds[t] = bbox;
1023 //width = (bbox.xmax - bbox.xmin)/20;
1024 width = (bbox.xmax)/20;
1026 /* The following is a heuristic- it may be that extractfont_DefineText
1027 has already found out some widths for individual characters (from the way
1028 they are used)- we now have to guess whether that width might be possible,
1029 which is the case if it isn't either much too big or much too small */
1030 if(width > f->glyph[t].advance*3/2 ||
1031 width*2 < f->glyph[t].advance)
1032 f->glyph[t].advance = width;
1034 if(-bbox.ymin > f->layout->ascent)
1035 f->layout->ascent = bbox.ymin;
1036 if(bbox.ymax > f->layout->descent)
1037 f->layout->descent = bbox.ymax;