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
27 static const int WRITEFONTID = 0x4e46; // font id for WriteFont and ReadFont
29 int swf_FontEnumerate(SWF * swf,void (*FontCallback) (U16,U8*))
37 { if (swf_GetTagID(t)==ST_DEFINEFONTINFO)
61 int swf_FontExtract_DefineFont(int id,SWFFONT * f,TAG * t,SHAPE * * shapes)
68 { U16 ofs[MAX_CHAR_PER_FONT];
74 ofs[0] = swf_GetU16(t);
77 for (i=1;i<n;i++) if (i<MAX_CHAR_PER_FONT) ofs[i] = swf_GetU16(t); else swf_GetU16(t);
78 for (i=0;i<n;i++) if (i<MAX_CHAR_PER_FONT) swf_GetSimpleShape(t,&shapes[i]);
86 int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t,SHAPE * * shapes)
93 { U8 l = swf_GetU8(t);
97 { if (f->name) free(f->name);
98 f->name = (U8*)malloc(l+1);
100 { swf_GetBlock(t,f->name,l);
104 { swf_RestoreTagPos(t);
108 f->flags = swf_GetU8(t);
112 { U16 code = ((f->flags&FF_WIDECODES)?swf_GetU16(t):swf_GetU8(t))%MAX_CHAR_PER_FONT;
114 f->glyph[code].shape = shapes[i];
115 f->glyph[code].gid = i;
116 if (i<MAX_CHAR_PER_FONT) f->codes[i] = code;
122 swf_RestoreTagPos(t);
126 #define FEDTJ_PRINT 0x01
127 #define FEDTJ_MODIFY 0x02
129 int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs)
133 U8 gbits, abits, flags;
144 gbits = swf_GetU8(t);
145 abits = swf_GetU8(t);
147 flags = swf_GetU8(t);
150 { if (flags&TF_TEXTCONTROL)
151 { if (flags&TF_HASFONT) fid = swf_GetU16(t);
152 if (flags&TF_HASCOLOR)
153 { swf_GetU8(t); // rgb
156 if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_GetU8(t);
158 if (flags&TF_HASXOFFSET) swf_GetS16(t);
159 if (flags&TF_HASYOFFSET) swf_GetS16(t);
160 if (flags&TF_HASFONT) swf_GetU16(t);
164 for (i=0;i<flags;i++)
167 glyph = swf_GetBits(t,gbits);
168 adv = swf_GetBits(t,abits);
169 if (id==fid) // mitlesen ?
170 { int code = f->codes[glyph];
171 if (jobs&FEDTJ_PRINT) printf("%c",code);
172 if (jobs&FEDTJ_MODIFY)
173 /*if (f->glyph[code].advance)*/ f->glyph[code].advance = adv;
176 if ((id==fid)&&(jobs&FEDTJ_PRINT)) printf("\n");
178 flags = swf_GetU8(t);
181 swf_RestoreTagPos(t);
185 int swf_FontExtract(SWF * swf,int id,SWFFONT * * font)
188 SHAPE * shapes[MAX_CHAR_PER_FONT];
190 if ((!swf)||(!font)) return -1;
192 f = (SWFFONT *)malloc(sizeof(SWFFONT)); font[0] = f;
195 memset(shapes,0x00,sizeof(shapes));
196 memset(f,0x00,sizeof(SWFFONT));
202 switch (swf_GetTagID(t))
203 { case ST_DEFINEFONT:
204 nid = swf_FontExtract_DefineFont(id,f,t,shapes);
207 case ST_DEFINEFONTINFO:
208 nid = swf_FontExtract_DefineFontInfo(id,f,t,shapes);
213 nid = swf_FontExtract_DefineText(id,f,t,FEDTJ_MODIFY);
222 int swf_FontIsItalic(SWFFONT * f) { return f->flags&FF_ITALIC; }
223 int swf_FontIsBold(SWFFONT * f) { return f->flags&FF_BOLD; }
225 int swf_FontSetID(SWFFONT * f,U16 id) { if (!f) return -1; f->id = id; return 0; }
227 int swf_FontReduce(SWFFONT * f,FONTUSAGE * use)
229 if ((!f)||(!use)) return -1;
231 memset(&f->codes,0x00,sizeof(f->codes));
234 for (i=0;i<MAX_CHAR_PER_FONT;i++)
235 if (f->glyph[i].shape)
237 { f->glyph[i].gid = j;
242 { swf_ShapeFree(f->glyph[i].shape);
243 f->glyph[i].shape = 0;
245 f->glyph[i].advance = 0;
247 } else f->glyph[i].gid = 0;
252 int swf_FontInitUsage(FONTUSAGE * use)
253 { if (!use) return -1;
254 memset(&use->code,0x00,sizeof(use->code));
258 int swf_FontUse(FONTUSAGE * use,U8 * s)
259 { if ((!use)||(!s)) return -1;
261 { use->code[s[0]] = 1;
267 int swf_FontSetDefine(TAG * t,SWFFONT * f)
268 { U16 ofs[MAX_CHAR_PER_FONT];
271 if ((!t)||(!f)) return -1;
272 swf_ResetWriteBits(t);
276 for (i=0;i<MAX_CHAR_PER_FONT;i++)
277 if (f->glyph[i].shape)
279 p+=swf_SetSimpleShape(NULL,f->glyph[i].shape);
282 for (i=0;i<j;i++) swf_SetU16(t,ofs[i]+j*2);
284 for (i=0;i<MAX_CHAR_PER_FONT;i++)
285 if (f->glyph[i].shape)
286 swf_SetSimpleShape(t,f->glyph[i].shape);
288 swf_ResetWriteBits(t);
292 int swf_FontSetInfo(TAG * t,SWFFONT * f)
294 if ((!t)||(!f)) return -1;
295 swf_ResetWriteBits(t);
297 l = strlen(f->name); if (l>255) l = 255;
299 swf_SetBlock(t,f->name,l);
300 swf_SetU8(t,f->flags&0xfe); // no Wide-Codes
302 for (i=0;i<MAX_CHAR_PER_FONT;i++)
303 if (f->glyph[i].shape)
309 int swf_FontExport(int handle,SWFFONT * f)
316 if (write(handle,f,sizeof(SWFFONT))!=sizeof(SWFFONT)) return -1;
319 { U16 ln = strlen(f->name);
322 { if (write(handle,&ln,2)!=2) return -1;
323 if (write(handle,f->name,ln)!=ln) return -1;
328 { l+=sizeof(SWFLAYOUT);
330 if (write(handle,f->layout,sizeof(SWFLAYOUT))!=sizeof(SWFLAYOUT)) return -1;
331 if (f->layout->kerning.data)
332 { l+=f->layout->kerning.count*4;
334 if (write(handle,f->layout->kerning.data,f->layout->kerning.count*4)!=f->layout->kerning.count*4) return -1;
338 for (i=0;i<MAX_CHAR_PER_FONT;i++)
339 { if (f->glyph[i].shape)
340 { int ll = swf_ShapeExport(handle,f->glyph[i].shape);
349 int swf_FontImport(int handle,SWFFONT * * font)
354 if ((!font)||(handle<0)) return -1;
356 f = (SWFFONT *)malloc(sizeof(SWFFONT)); font[0] = f;
359 memset(f,0x00,sizeof(SWFFONT));
361 if (read(handle,f,sizeof(SWFFONT))!=sizeof(SWFFONT)) goto fehler;
363 layout = (f->layout)?1:0; // avoid illegal free()
369 if (read(handle,&ln,2)!=2) goto fehler;
370 f->name = (U8*)malloc(ln+1);
371 if (!f->name) goto fehler;
372 if (read(handle,f->name,ln)!=ln) goto fehler;
377 { f->layout = (SWFLAYOUT *)malloc(sizeof(SWFLAYOUT));
378 if (!f->layout) goto fehler;
379 if (read(handle,f->layout,sizeof(SWFLAYOUT))!=sizeof(SWFLAYOUT)) goto fehler;
380 if (f->layout->kerning.data)
381 { int l = f->layout->kerning.count*4;
382 f->layout->kerning.data = (U8*)malloc(l);
383 if (!f->layout->kerning.data) goto fehler;
384 if (read(handle,f->layout->kerning.data,l)!=l) goto fehler;
388 for (i=0;i<MAX_CHAR_PER_FONT;i++)
389 { if (f->glyph[i].shape)
390 { if (swf_ShapeImport(handle,&f->glyph[i].shape)<0) goto fehler;
399 if (f) for (;i<MAX_CHAR_PER_FONT;i++) f->glyph[i].shape = NULL;
405 int swf_TextPrintDefineText(TAG * t,SWFFONT * f)
406 { int id = swf_GetTagID(t);
407 if ((id==ST_DEFINETEXT)||(id==ST_DEFINETEXT2)) swf_FontExtract_DefineText(f->id,f,t,FEDTJ_PRINT);
412 void swf_LayoutFree(SWFLAYOUT * l)
414 { if (l->kerning.data) free(l->kerning.data);
415 l->kerning.data = NULL;
420 void swf_FontFree(SWFFONT * f)
424 if (f->name) free(f->name);
425 if (f->layout) swf_LayoutFree(f->layout);
430 for (i=0;i<MAX_CHAR_PER_FONT;i++)
431 if (f->glyph[i].shape)
432 { swf_ShapeFree(f->glyph[i].shape);
433 f->glyph[i].shape = NULL;
439 int swf_TextSetInfoRecord(TAG * t,SWFFONT * font,U16 size,RGBA * color,S16 dx,S16 dy)
443 flags = TF_TEXTCONTROL|(font?TF_HASFONT:0)|(color?TF_HASCOLOR:0)|(dx?TF_HASXOFFSET:0)|(dy?TF_HASYOFFSET:0);
446 if (font) swf_SetU16(t,font->id);
448 { if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_SetRGBA(t,color);
449 else swf_SetRGB(t,color);
451 if (dx) swf_SetS16(t,dx);
452 if (dy) swf_SetS16(t,dy);
453 if (font) swf_SetU16(t,size);
458 int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits)
460 if ((!s)||(!font)||((!gbits)&&(!abits))) return -1;
464 { g = swf_CountBits(font->glyph[s[0]].gid,g);
465 a = swf_CountBits((((U32)font->glyph[s[0]].advance)*scale)/100,a);
469 if (gbits) gbits[0] = (U8)g;
470 if (abits) abits[0] = (U8)a;
475 int swf_TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 abits)
478 if ((!t)||(!font)||(!s)) return -1;
481 if (l>0x7f) l = 0x7f;
485 { swf_SetBits(t,font->glyph[s[i]].gid,gbits);
486 swf_SetBits(t,(((U32)font->glyph[s[i]].advance)*scale)/100,abits);
489 swf_ResetWriteBits(t);
493 U32 swf_TextGetWidth(SWFFONT * font,U8 * s,int scale)
498 { res += font->glyph[s[0]].advance;
501 if (scale) res = (res*scale)/100;
506 void swf_WriteFont(SWFFONT*font, char* filename, int useDefineFont2)
514 fprintf(stderr, "DefineFont2 is not yet supported!\n");
518 font->id = WRITEFONTID; //"FN"
520 memset(&swf,0x00,sizeof(SWF));
523 swf.frameRate = 0x4000;
524 swf.movieSize.xmax = 20*640;
525 swf.movieSize.ymax = 20*480;
528 /* if we use DefineFont1 to store the characters,
529 we have to build a textfield to store the
530 advance values. While at it, we can also
531 make the whole .swf viewable */
533 t = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
539 t = swf_InsertTag(t,ST_DEFINEFONT);
543 t = swf_InsertTag(NULL,ST_DEFINEFONT);
547 swf_FontSetDefine(t,font);
549 t = swf_InsertTag(t,ST_DEFINEFONTINFO);
550 swf_FontSetInfo(t,font);
557 int ymax = textscale * 20;
565 if(font->glyph[s].advance*textscale/100 > xmax)
566 xmax = font->glyph[s].advance*textscale/100;
568 swf.movieSize.xmax = xmax*20;
569 swf.movieSize.ymax = ymax;
571 t = swf_InsertTag(t,ST_DEFINETEXT);
573 swf_SetU16(t,font->id+1); // ID
577 r.xmax = swf.movieSize.xmax*20;
578 r.ymax = swf.movieSize.ymax;
582 swf_SetMatrix(t,NULL);
584 abits = swf_CountBits(xmax*16, 0);
595 int c=0,lastx=-1, firstx=0;
597 if(font->glyph[y*16+x].shape) {
604 swf_TextSetInfoRecord(t,font,textscale,&rgb,lastx+1,textscale*y);
607 if(font->glyph[y*16+x].shape) {
608 if(lastx != x*xmax) {
609 swf_TextSetInfoRecord(t,0,0,0,x*xmax+1,0);
612 swf_SetBits(t, font->glyph[y*16+x].gid, gbits);
613 swf_SetBits(t, font->glyph[y*16+x].advance, abits);
614 lastx = x*xmax+font->glyph[y*16+x].advance;
615 swf_ResetWriteBits(t);
622 t = swf_InsertTag(t,ST_PLACEOBJECT2);
624 swf_ObjectPlace(t,font->id+1,1,NULL,NULL,NULL);
626 t = swf_InsertTag(t,ST_SHOWFRAME);
629 t = swf_InsertTag(t,ST_END);
631 f = open(filename, O_RDWR|O_CREAT|O_TRUNC,0644);
632 if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed in writeFont().\n");
638 SWFFONT* swf_ReadFont(char* filename)
644 f = open(filename,O_RDONLY);
646 if (f<0 || swf_ReadSWF(f,&swf)<0)
647 { fprintf(stderr,"%s is not a valid SWF font file or contains errors.\n",filename);
654 if(swf_FontExtract(&swf, WRITEFONTID, &font) < 0)