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 program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
24 #define TF_TEXTCONTROL 0x80
25 #define TF_HASFONT 0x08
26 #define TF_HASCOLOR 0x04
27 #define TF_HASYOFFSET 0x02
28 #define TF_HASXOFFSET 0x01
30 #define FF_WIDECODES 0x01
32 #define FF_ITALIC 0x04
34 #define FF_SHIFTJIS 0x10
35 #define FF_UNICODE 0x20
38 #define FF2_ITALIC 0x02
39 #define FF2_WIDECODES 0x04
40 #define FF2_WIDEOFFSETS 0x08
42 #define FF2_UNICODE 0x20
43 #define FF2_SHIFTJIS 0x40
44 #define FF2_LAYOUT 0x80
46 int swf_FontIsItalic(SWFFONT * f) { return f->style&FONT_STYLE_ITALIC;}
47 int swf_FontIsBold(SWFFONT * f) { return f->style&FONT_STYLE_BOLD;}
49 static const int WRITEFONTID = 0x4e46; // font id for WriteFont and ReadFont
51 int swf_FontEnumerate(SWF * swf,void (*FontCallback) (U16,U8*))
59 { if (swf_GetTagID(t)==ST_DEFINEFONTINFO || swf_GetTagID(t)==ST_DEFINEFONTINFO2 ||
60 swf_GetTagID(t)==ST_DEFINEFONT2)
70 if(swf_GetTagID(t) == ST_DEFINEFONT2)
86 int swf_FontExtract_DefineFont(int id,SWFFONT * f,TAG * t)
103 f->glyph = malloc(sizeof(SWFGLYPH)*n);
104 memset(f->glyph, 0, sizeof(SWFGLYPH)*n);
106 for (i=1;i<n;i++) swf_GetU16(t);
107 for (i=0;i<n;i++) swf_GetSimpleShape(t,&f->glyph[i].shape);
110 swf_RestoreTagPos(t);
114 int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t)
123 { U8 l = swf_GetU8(t);
127 /* Especially with Flash MX, DefineFont2 may have FontInfo fields,
128 too. However, they only add little information to what's already
129 inside the DefineFont2 tag */
133 if (f->name) free(f->name);
135 f->name = (U8*)malloc(l+1);
136 swf_GetBlock(t,f->name,l);
139 flags = swf_GetU8(t);
141 f->style |= FONT_STYLE_BOLD;
143 f->style |= FONT_STYLE_ITALIC;
145 f->encoding |= FONT_ENCODING_ANSI;
147 f->encoding |= FONT_ENCODING_SHIFTJIS;
149 f->encoding |= FONT_ENCODING_UNICODE;
151 if(t->id == ST_DEFINEFONTINFO2) {
152 f->language = swf_GetU8(t);
155 f->glyph2ascii = (U16*)malloc(sizeof(U16)*f->numchars);
157 for(i=0; i < f->numchars; i++) {
158 f->glyph2ascii[i] = ((flags&FF_WIDECODES)?swf_GetU16(t):swf_GetU8(t));
159 if(f->glyph2ascii[i] > maxcode)
160 maxcode = f->glyph2ascii[i];
165 f->maxascii = maxcode;
166 f->ascii2glyph = (int*)malloc(sizeof(int)*maxcode);
167 memset(f->ascii2glyph, -1, sizeof(int)*maxcode);
169 for(i = 0; i < f->numchars; i++)
170 f->ascii2glyph[f->glyph2ascii[i]] = i;
173 swf_RestoreTagPos(t);
177 int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag)
182 U8 flags1,flags2,namelen;
184 swf_SetTagPos(tag,0);
186 fid = swf_GetU16(tag);
190 flags1 = swf_GetU8(tag);
191 flags2 = swf_GetU8(tag); //reserved flags
194 font->style |= FONT_STYLE_BOLD;
196 font->style |= FONT_STYLE_ITALIC;
198 font->encoding |= FONT_ENCODING_ANSI;
200 font->encoding |= FONT_ENCODING_UNICODE;
202 font->encoding |= FONT_ENCODING_SHIFTJIS;
204 namelen = swf_GetU8(tag);
205 font->name = (U8*)malloc(namelen+1);
206 font->name[namelen]=0;
207 swf_GetBlock(tag, font->name, namelen);
209 glyphcount = swf_GetU16(tag);
210 font->numchars = glyphcount;
212 font->glyph = (SWFGLYPH*)malloc(sizeof(SWFGLYPH)*glyphcount);
213 memset(font->glyph, 0, sizeof(SWFGLYPH)*glyphcount);
214 font->glyph2ascii = (U16*)malloc(sizeof(U16)*glyphcount);
215 memset(font->glyph2ascii, 0, sizeof(U16)*glyphcount);
217 if(flags1&8) { // wide offsets
218 for(t=0;t<glyphcount;t++)
219 swf_GetU32(tag); //offset[t]
221 if(glyphcount) /* this _if_ is not in the specs */
222 swf_GetU32(tag); // fontcodeoffset
224 for(t=0;t<glyphcount;t++)
225 swf_GetU16(tag); //offset[t]
227 if(glyphcount) /* this _if_ is not in the specs */
228 swf_GetU16(tag); // fontcodeoffset
230 for(t=0;t<glyphcount;t++)
231 swf_GetSimpleShape(tag,&(font->glyph[t].shape));
234 for(t=0;t<glyphcount;t++) {
236 if(flags1&4) // wide codes
237 code = swf_GetU16(tag);
239 code = swf_GetU8(tag);
240 font->glyph2ascii[t] = code;
247 font->maxascii = maxcode;
248 font->ascii2glyph = (int*)malloc(sizeof(int)*maxcode);
249 memset(font->ascii2glyph, -1, sizeof(int)*maxcode);
250 for(t=0;t<glyphcount;t++)
252 font->ascii2glyph[font->glyph2ascii[t]] = t;
255 if(flags1&128) { // has layout
257 font->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
258 font->layout->ascent=swf_GetU16(tag);
259 font->layout->descent=swf_GetU16(tag);
260 font->layout->leading=swf_GetU16(tag);
261 for(t=0;t<glyphcount;t++) {
262 S16 advance = swf_GetS16(tag);
263 font->glyph[t].advance = advance;
265 font->layout->bounds = malloc(glyphcount*sizeof(SRECT));
266 for(t=0;t<glyphcount;t++) {
267 swf_ResetReadBits(tag);
268 swf_GetRect(tag, &font->layout->bounds[t]);
271 kerningcount = swf_GetU16(tag);
272 font->layout->kerningcount = kerningcount;
274 font->layout->kerning = (SWFKERNING*)malloc(sizeof(SWFKERNING)*kerningcount);
276 font->layout->kerning =
277 malloc(sizeof(*font->layout->kerning)* kerningcount);
278 for(t=0;t<kerningcount;t++)
280 if(flags1&4) { // wide codes
281 font->layout->kerning[t].char1 = swf_GetU16(tag);
282 font->layout->kerning[t].char2 = swf_GetU16(tag);
284 font->layout->kerning[t].char1 = swf_GetU8(tag);
285 font->layout->kerning[t].char2 = swf_GetU8(tag);
287 font->layout->kerning[t].adjustment = swf_GetS16(tag);
291 swf_RestoreTagPos(t);
296 #define FEDTJ_PRINT 0x01
297 #define FEDTJ_MODIFY 0x02
298 #define FEDTJ_CALLBACK 0x04
300 int swf_FontExtract_DefineTextCallback(int id,SWFFONT * f,TAG * t,int jobs,
301 void(*callback)(int*chars, int nr, int fontid))
305 U8 gbits, abits, flags;
316 gbits = swf_GetU8(t);
317 abits = swf_GetU8(t);
319 flags = swf_GetU8(t);
322 { if (flags&TF_TEXTCONTROL)
323 { if (flags&TF_HASFONT) fid = swf_GetU16(t);
324 if (flags&TF_HASCOLOR)
325 { swf_GetU8(t); // rgb
328 if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_GetU8(t);
330 if (flags&TF_HASXOFFSET) swf_GetS16(t);
331 if (flags&TF_HASYOFFSET) swf_GetS16(t);
332 if (flags&TF_HASFONT) swf_GetU16(t);
337 for (i=0;i<flags;i++)
340 glyph = swf_GetBits(t,gbits);
341 adv = swf_GetBits(t,abits);
342 if (id==fid) // mitlesen ?
343 if (jobs&FEDTJ_PRINT) {
344 { int code = f->glyph2ascii[glyph];
347 if (jobs&FEDTJ_MODIFY)
348 /*if (!f->glyph[code].advance)*/ f->glyph[glyph].advance = adv;
352 if ((id==fid)&&(jobs&FEDTJ_PRINT)) printf("\n");
353 if (jobs&FEDTJ_CALLBACK)
354 callback(buf, flags, fid);
356 flags = swf_GetU8(t);
359 swf_RestoreTagPos(t);
363 int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs)
365 return swf_FontExtract_DefineTextCallback(id,f,t,jobs,0);
368 int swf_FontExtract(SWF * swf,int id,SWFFONT * * font)
372 if ((!swf)||(!font)) return -1;
374 f = (SWFFONT *)malloc(sizeof(SWFFONT));
375 memset(f,0x00,sizeof(SWFFONT));
381 switch (swf_GetTagID(t))
382 { case ST_DEFINEFONT:
383 nid = swf_FontExtract_DefineFont(id,f,t);
387 nid = swf_FontExtract_DefineFont2(id,f,t);
390 case ST_DEFINEFONTINFO:
391 case ST_DEFINEFONTINFO2:
392 nid = swf_FontExtract_DefineFontInfo(id,f,t);
397 nid = swf_FontExtract_DefineText(id,f,t,f->layout?0:FEDTJ_MODIFY);
411 int swf_FontSetID(SWFFONT * f,U16 id) { if (!f) return -1; f->id = id; return 0; }
413 int swf_FontReduce(SWFFONT * f,FONTUSAGE * use)
415 if ((!f)||(!use)) return -1;
418 for (i=0;i<f->numchars;i++)
419 if (f->glyph[i].shape)
420 { if (f->glyph2ascii[i]<MAX_CHAR_PER_FONT &&
421 use->code[f->glyph2ascii[i]])
422 { f->ascii2glyph[f->glyph2ascii[i]] = j;
423 f->glyph2ascii[j] = f->glyph2ascii[i];
424 f->glyph[j] = f->glyph[i];
428 { swf_ShapeFree(f->glyph[i].shape);
429 f->ascii2glyph[f->glyph2ascii[i]] = -1;
430 f->glyph2ascii[i] = 0;
431 f->glyph[i].shape = NULL;
432 f->glyph[i].advance = 0;
434 } else f->ascii2glyph[f->glyph2ascii[i]] = -1;
441 int swf_FontInitUsage(FONTUSAGE * use)
442 { if (!use) return -1;
443 memset(use->code,0,sizeof(use->code[0])*MAX_CHAR_PER_FONT);
447 int swf_FontUse(FONTUSAGE * use,U8 * s)
448 { if ((!use)||(!s)) return -1;
450 { use->code[s[0]] = 1;
456 int swf_FontSetDefine(TAG * t,SWFFONT * f)
457 { U16*ofs = (U16*)malloc(f->numchars*2);
460 if ((!t)||(!f)) return -1;
461 swf_ResetWriteBits(t);
465 for (i=0;i<f->numchars;i++)
466 if (f->glyph[i].shape)
468 p+=swf_SetSimpleShape(NULL,f->glyph[i].shape);
471 for (i=0;i<j;i++) swf_SetU16(t,ofs[i]+j*2);
473 fprintf(stderr, "rfxswf: warning: Font is empty\n");
477 for (i=0;i<f->numchars;i++)
478 if (f->glyph[i].shape)
479 swf_SetSimpleShape(t,f->glyph[i].shape);
481 swf_ResetWriteBits(t);
486 int swf_FontSetDefine2(TAG *tag, SWFFONT * f)
492 swf_SetU16(tag, f->id);
494 flags |= 128; // haslayout
496 flags |= 4; // widecodes
497 if(f->style & FONT_STYLE_BOLD)
499 if(f->style & FONT_STYLE_ITALIC)
500 flags |= 2; // italic
502 if(f->encoding & FONT_ENCODING_ANSI)
504 if(f->encoding & FONT_ENCODING_UNICODE)
505 flags |= 32; // unicode
506 if(f->encoding & FONT_ENCODING_SHIFTJIS)
507 flags |= 64; // shiftjis
509 swf_SetU8(tag, flags);
510 swf_SetU8(tag, 0); //reserved flags
513 swf_SetU8(tag, strlen(f->name));
514 swf_SetBlock(tag, f->name, strlen(f->name));
516 /* font name (="") */
517 swf_SetU8(tag, 0); /*placeholder*/
519 /* number of glyphs */
520 swf_SetU16(tag, f->numchars);
521 /* font offset table */
523 for(t=0;t<f->numchars;t++)
525 swf_SetU16(tag, /* fontoffset */ 0); /*placeholder*/
528 swf_SetU16(tag, 0); //fontcode-fontoffset
529 for(t=0;t<f->numchars;t++) {
530 tag->data[pos + t*2] = (tag->len-pos);
531 tag->data[pos + t*2 + 1] = (tag->len-pos) >> 8;
532 swf_SetSimpleShape(tag, f->glyph[t].shape);
535 tag->data[pos2] = tag->len - pos;
536 tag->data[pos2 + 1] = (tag->len - pos) >> 8;
538 /* font code table */
539 if(flags & 4) /* wide codes */ {
540 for(t=0;t<f->numchars;t++)
541 swf_SetU16(tag,f->glyph2ascii[t]);
543 for(t=0;t<f->numchars;t++)
544 swf_SetU8(tag,f->glyph2ascii[t]);
548 swf_SetU16(tag,f->layout->ascent);
549 swf_SetU16(tag,f->layout->descent);
550 swf_SetU16(tag,f->layout->leading);
551 for(t=0;t<f->numchars;t++)
552 swf_SetU16(tag,f->glyph[t].advance);
553 for(t=0;t<f->numchars;t++) {
554 swf_ResetWriteBits(tag);
555 swf_SetRect(tag,&f->layout->bounds[t]);
557 swf_SetU16(tag, f->layout->kerningcount);
558 for(t=0;t<f->layout->kerningcount;t++) {
559 if(flags & 4) /* wide codes */ {
560 swf_SetU8(tag,f->layout->kerning[t].char1);
561 swf_SetU8(tag,f->layout->kerning[t].char2);
563 swf_SetU16(tag,f->layout->kerning[t].char1);
564 swf_SetU16(tag,f->layout->kerning[t].char2);
566 swf_SetU16(tag,f->layout->kerning[t].adjustment);
572 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading)
574 f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
575 f->layout->ascent = ascent;
576 f->layout->descent = descent;
577 f->layout->leading = leading;
578 f->layout->kerningcount = 0;
579 f->layout->kerning = 0;
580 f->layout->bounds = (SRECT*)malloc(sizeof(SRECT)*f->numchars);
581 memset(f->layout->bounds, 0, sizeof(SRECT)*f->numchars);
584 int swf_FontSetInfo(TAG * t,SWFFONT * f)
588 if ((!t)||(!f)) return -1;
589 swf_ResetWriteBits(t);
591 l = f->name?strlen(f->name):0; if (l>255) l = 255;
594 swf_SetBlock(t,f->name,l);
598 if(f->style & FONT_STYLE_BOLD)
600 if(f->style & FONT_STYLE_ITALIC)
602 if(f->style & FONT_ENCODING_ANSI)
604 if(f->style & FONT_ENCODING_SHIFTJIS)
606 if(f->style & FONT_ENCODING_UNICODE)
609 swf_SetU8(t,(flags&0xfe)|wide);
611 for (i=0;i<f->numchars;i++) {
612 if (f->glyph[i].shape)
613 wide?swf_SetU16(t,f->glyph2ascii[i]):
614 swf_SetU8(t,f->glyph2ascii[i]);
620 int swf_TextPrintDefineText(TAG * t,SWFFONT * f)
621 { int id = swf_GetTagID(t);
622 if ((id==ST_DEFINETEXT)||(id==ST_DEFINETEXT2)) swf_FontExtract_DefineText(f->id,f,t,FEDTJ_PRINT);
627 void swf_LayoutFree(SWFLAYOUT * l)
629 { if (l->kerning) free(l->kerning);
631 if (l->bounds) free(l->bounds);
637 void swf_FontFree(SWFFONT * f)
641 if (f->name) free(f->name);
642 if (f->layout) swf_LayoutFree(f->layout);
648 for (i=0;i<f->numchars;i++)
649 if (f->glyph[i].shape)
650 { swf_ShapeFree(f->glyph[i].shape);
651 f->glyph[i].shape = NULL;
657 free(f->ascii2glyph);
658 f->ascii2glyph = NULL;
661 free(f->glyph2ascii);
662 f->glyph2ascii = NULL;
668 int swf_TextSetInfoRecord(TAG * t,SWFFONT * font,U16 size,RGBA * color,int dx,int dy)
672 flags = TF_TEXTCONTROL|(font?TF_HASFONT:0)|(color?TF_HASCOLOR:0)|(dx?TF_HASXOFFSET:0)|(dy?TF_HASYOFFSET:0);
675 if (font) swf_SetU16(t,font->id);
677 { if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_SetRGBA(t,color);
678 else swf_SetRGB(t,color);
680 if (dx) swf_SetS16(t,dx);
681 if (dy) swf_SetS16(t,dy);
682 if (font) swf_SetU16(t,size);
687 int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits)
689 if ((!s)||(!font)||((!gbits)&&(!abits))||(!font->ascii2glyph)) return -1;
695 if(s[0] < font->maxascii)
696 glyph = font->ascii2glyph[s[0]];
698 g = swf_CountUBits(glyph,g);
699 a = swf_CountBits((((U32)font->glyph[glyph].advance)*scale)/100,a);
704 if (gbits) gbits[0] = (U8)g;
705 if (abits) abits[0] = (U8)a;
710 int swf_TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 abits)
713 if ((!t)||(!font)||(!s)||(!font->ascii2glyph)) return -1;
716 swf_SetU8(t, l); //placeholder
721 if(s[i] < font->maxascii)
722 g = font->ascii2glyph[s[i]];
724 swf_SetBits(t,g,gbits);
725 swf_SetBits(t,(((U32)font->glyph[g].advance)*scale)/100,abits);
732 PUT8(&t->data[pos], l);
734 swf_ResetWriteBits(t);
738 U32 swf_TextGetWidth(SWFFONT * font,U8 * s,int scale)
745 if(*s < font->maxascii)
746 g = font->ascii2glyph[*s];
748 res += font->glyph[g].advance;
751 if (scale) res = (res*scale)/100;
756 SWFFONT* swf_ReadFont(char* filename)
762 f = open(filename,O_RDONLY);
764 if (f<0 || swf_ReadSWF(f,&swf)<0)
765 { fprintf(stderr,"%s is not a valid SWF font file or contains errors.\n",filename);
772 if(swf_FontExtract(&swf, WRITEFONTID, &font) < 0)
779 void swf_WriteFont(SWFFONT*font, char* filename)
785 int useDefineFont2 = 0;
788 useDefineFont2 = 1; /* the only thing new in definefont2
789 is layout information. */
791 font->id = WRITEFONTID; //"FN"
793 memset(&swf,0x00,sizeof(SWF));
796 swf.frameRate = 0x4000;
798 /* if we use DefineFont1 to store the characters,
799 we have to build a textfield to store the
800 advance values. While at it, we can also
801 make the whole .swf viewable */
803 /* we now always create viewable swfs, even if we
804 did use definefont2 -mk*/
805 t = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
811 if(!useDefineFont2) {
812 t = swf_InsertTag(t,ST_DEFINEFONT);
813 swf_FontSetDefine(t,font);
814 t = swf_InsertTag(t,ST_DEFINEFONTINFO);
815 swf_FontSetInfo(t,font);
817 t = swf_InsertTag(t,ST_DEFINEFONT2);
818 swf_FontSetDefine2(t,font);
821 if(1) //useDefineFont2
822 { int textscale = 400;
825 int ymax = textscale * 2 * (font->maxascii/16+1);
827 U8 text[MAX_CHAR_PER_FONT+1];
829 text[MAX_CHAR_PER_FONT]=0;
830 for(s=0;s<font->maxascii;s++)
832 int g = font->ascii2glyph[s];
835 if(font->glyph[g].advance*textscale/64 > xmax)
836 xmax = font->glyph[g].advance*textscale/64;
839 swf.movieSize.xmax = xmax*20;
840 swf.movieSize.ymax = ymax;
842 t = swf_InsertTag(t,ST_DEFINETEXT);
844 swf_SetU16(t,font->id+1); // ID
848 r.xmax = swf.movieSize.xmax*20;
849 r.ymax = swf.movieSize.ymax;
853 swf_SetMatrix(t,NULL);
855 abits = swf_CountBits(xmax*16, 0);
864 for(y=0;y<=((font->maxascii-1)/16);y++)
869 int g = (y*16+x<font->maxascii)?font->ascii2glyph[y*16+x]:-1;
870 if(g>=0 && font->glyph[g].shape) {
877 swf_TextSetInfoRecord(t,font,textscale,&rgb,lastx+1,textscale*y*2);
880 int g = (y*16+x<font->maxascii)?font->ascii2glyph[y*16+x]:-1;
881 if(g>=0 && font->glyph[g].shape) {
882 if(lastx != x*xmax) {
883 swf_TextSetInfoRecord(t,0,0,0,x*xmax+1,0);
886 swf_SetBits(t, g, gbits);
887 swf_SetBits(t, font->glyph[g].advance, abits);
888 lastx = x*xmax+font->glyph[g].advance;
889 swf_ResetWriteBits(t);
897 t = swf_InsertTag(t,ST_PLACEOBJECT2);
899 swf_ObjectPlace(t,font->id+1,1,NULL,NULL,NULL);
901 t = swf_InsertTag(t,ST_SHOWFRAME);
904 t = swf_InsertTag(t,ST_END);
906 f = open(filename, O_RDWR|O_CREAT|O_TRUNC,0644);
907 if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed in writeFont().\n");
914 void swf_SetEditText(TAG*tag, U16 flags, SRECT r, char*text, RGBA*color,
915 int maxlength, U16 font, U16 height, EditTextLayout*layout, char*variable)
918 swf_ResetWriteBits(tag);
920 flags &= ~(ET_HASTEXT|ET_HASTEXTCOLOR|ET_HASMAXLENGTH|ET_HASFONT|ET_HASLAYOUT);
921 if(text) flags |= ET_HASTEXT;
922 if(color) flags |= ET_HASTEXTCOLOR;
923 if(maxlength) flags |= ET_HASMAXLENGTH;
924 if(font) flags |= ET_HASFONT;
925 if(layout) flags |= ET_HASLAYOUT;
927 swf_SetBits(tag, flags, 16);
929 if(flags & ET_HASFONT) {
930 swf_SetU16(tag, font); //font
931 swf_SetU16(tag, height); //fontheight
933 if(flags & ET_HASTEXTCOLOR) {
934 swf_SetRGBA(tag, color);
936 if(flags & ET_HASMAXLENGTH) {
937 swf_SetU16(tag, maxlength); //maxlength
939 if(flags & ET_HASLAYOUT) {
940 swf_SetU8(tag,layout->align); //align
941 swf_SetU16(tag,layout->leftmargin); //left margin
942 swf_SetU16(tag,layout->rightmargin); //right margin
943 swf_SetU16(tag,layout->indent); //indent
944 swf_SetU16(tag,layout->leading); //leading
946 swf_SetString(tag, variable);
947 if(flags & ET_HASTEXT)
948 swf_SetString(tag,text);
951 SRECT swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale)
960 if(*c < font->maxascii) {
961 int g = font->ascii2glyph[*c];
963 SRECT rn = font->layout->bounds[g];
964 rn.xmin = (rn.xmin * scale)/100 + pos;
965 rn.xmax = (rn.xmax * scale)/100 + pos;
966 rn.ymin = (rn.ymin * scale)/100;
967 rn.ymax = (rn.ymax * scale)/100;
968 swf_ExpandRect2(&r, &rn);
969 pos += (font->glyph[g].advance*scale*20)/100;
975 /* Hm, without layout information, we can't compute a bounding
976 box. We could call swf_FontCreateLayout to create a layout,
977 but the caller probably doesn't want us to mess up his font
981 r.xmax = r.ymax = 1024*20;
985 swf_SetMatrix(tag,NULL);
986 swf_TextCountBits(font,text,scale*20,&gbits,&abits);
987 swf_SetU8(tag,gbits);
988 swf_SetU8(tag,abits);
990 /* now set the text params- notice that a font size of
991 1024 means that the glyphs will be displayed exactly
992 as they would be in/with a defineshape. (Try to find
993 *that* in the flash specs)
995 swf_TextSetInfoRecord(tag,font,(scale*1024)/100,rgb,0,0); //scale
997 /* set the actual text- notice that we just pass our scale
998 parameter over, as TextSetCharRecord calculates with
1000 swf_TextSetCharRecord(tag,font,text,scale*20,gbits,abits);
1006 void swf_FontCreateLayout(SWFFONT*f)
1015 f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
1016 memset(f->layout, 0, sizeof(SWFLAYOUT));
1017 f->layout->bounds = (SRECT*)malloc(f->numchars*sizeof(SRECT));
1018 f->layout->ascent = -32767;
1019 f->layout->descent = -32767;
1021 for(t=0;t<f->numchars;t++) {
1025 shape2 = swf_ShapeToShape2(f->glyph[t].shape);
1027 fprintf(stderr, "Shape parse error\n");exit(1);
1029 bbox = swf_GetShapeBoundingBox(shape2);
1030 swf_Shape2Free(shape2);
1031 f->layout->bounds[t] = bbox;
1033 //width = (bbox.xmax - bbox.xmin)/20;
1034 width = (bbox.xmax)/20;
1036 /* The following is a heuristic- it may be that extractfont_DefineText
1037 has already found out some widths for individual characters (from the way
1038 they are used)- we now have to guess whether that width might be possible,
1039 which is the case if it isn't either much too big or much too small */
1040 if(width > f->glyph[t].advance*3/2 ||
1041 width*2 < f->glyph[t].advance)
1042 f->glyph[t].advance = width;
1044 if(-bbox.ymin > f->layout->ascent)
1045 f->layout->ascent = bbox.ymin;
1046 if(bbox.ymax > f->layout->descent)
1047 f->layout->descent = bbox.ymax;
1051 static U32 readUTF8char(char**text)
1054 if(!(*(*text) & 0x80))
1055 return *((*text)++);
1057 /* 0000 0080-0000 07FF 110xxxxx 10xxxxxx */
1058 if(((*text)[0] & 0xe0) == 0xc0 && (*text)[1])
1060 c = ((*text)[0] & 0x1f) << 6 | ((*text)[1] & 0x3f);
1064 /* 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx */
1065 if(((*text)[0] & 0xf0) == 0xe0 && (*text)[1] && (*text)[2])
1067 c = ((*text)[0] & 0x0f) << 12 | ((*text)[1] & 0x3f) << 6 | ((*text)[2] & 0x3f);
1071 /* 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
1072 if(((*text)[0] & 0xf8) == 0xf0 && (*text)[1] && (*text)[2] && (*text)[3] )
1074 c = ((*text)[0] & 0x07) << 18 | ((*text)[1] & 0x3f) << 12 | ((*text)[2] & 0x3f)<<6 | ((*text)[3] & 0x3f);
1078 /* 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
1079 if(((*text)[0] & 0xfc) == 0xf8 && (*text)[1] && (*text)[2] && (*text)[3] && (*text)[4])
1081 c = ((*text)[0] & 0x03) << 24 | ((*text)[1] & 0x3f) << 18 | ((*text)[2] & 0x3f)<<12 | ((*text)[3] & 0x3f) << 6 | ((*text)[4] & 0x3f);
1085 /* 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx */
1086 if(((*text)[0] & 0xfe) == 0xfc && (*text)[1] && (*text)[2] && (*text)[3] && (*text)[4] && (*text)[5])
1088 c = ((*text)[0] & 0x01) << 30 | ((*text)[1] & 0x3f) << 24 | ((*text)[2] & 0x3f)<<18 | ((*text)[3] & 0x3f) << 12 | ((*text)[4] & 0x3f) << 6 | ((*text)[5] & 0x3f) << 6;
1092 return *((*text)++);
1095 void swf_DrawText(SWFSHAPEDRAWER*draw, SWFFONT*font, char*text)
1102 U32 c = readUTF8char(&s);
1103 int g = font->ascii2glyph[c];
1104 shape = font->glyph[g].shape;
1105 shape2 = swf_ShapeToShape2(shape);
1106 SHAPELINE*l = shape2->lines;
1108 if(l->type == moveTo) {
1110 to.x = l->x/20.0+advance;
1112 swf_DrawerMoveTo(draw, &to);
1113 } else if(l->type == lineTo) {
1115 to.x = l->x/20.0+advance;
1117 swf_DrawerLineTo(draw, &to);
1118 } else if(l->type == splineTo) {
1120 mid.x = l->sx/20.0+advance;
1122 to.x = l->x/20.0+advance;
1124 swf_DrawerSplineTo(draw, &mid, &to);
1128 swf_Shape2Free(shape2);
1129 advance += font->glyph[g].advance;