fixed compiler warnings.
[swftools.git] / lib / modules / swftext.c
1 /* swftext.c
2
3    Text and font routines
4       
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
9  
10    This file is distributed under the GPL, see file COPYING for details 
11
12 */
13
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
19
20 #define FF_WIDECODES    0x01
21 #define FF_BOLD         0x02
22 #define FF_ITALIC       0x04
23 #define FF_ANSI         0x08
24 #define FF_SHIFTJIS     0x10
25 #define FF_UNICODE      0x20
26
27 #define FF2_BOLD         0x01
28 #define FF2_ITALIC       0x02
29 #define FF2_WIDECODES    0x04
30 #define FF2_WIDEOFFSETS  0x08
31 #define FF2_ANSI         0x10
32 #define FF2_UNICODE      0x20
33 #define FF2_SHIFTJIS     0x40
34 #define FF2_LAYOUT       0x80
35
36 int swf_FontIsItalic(SWFFONT * f) { return f->style&FONT_STYLE_ITALIC;}
37 int swf_FontIsBold(SWFFONT * f)   { return f->style&FONT_STYLE_BOLD;}
38
39 static const int WRITEFONTID = 0x4e46; // font id for WriteFont and ReadFont
40
41 int swf_FontEnumerate(SWF * swf,void (*FontCallback) (U16,U8*))
42 { int n;
43   TAG * t;
44   if (!swf) return -1;
45   t = swf->firstTag;
46   n = 0;
47
48   while (t)
49   { if (swf_GetTagID(t)==ST_DEFINEFONTINFO ||
50           swf_GetTagID(t)==ST_DEFINEFONT2)
51     { n++;
52       if (FontCallback)
53       { U16 id;
54         int l;
55         U8 s[257];
56         swf_SaveTagPos(t);
57         swf_SetTagPos(t,0);
58         
59         id  = swf_GetU16(t);
60         if(swf_GetTagID(t) == ST_DEFINEFONT2)
61             swf_GetU16(t);
62         l   = swf_GetU8(t);
63         swf_GetBlock(t,s,l);
64         s[l] = 0;
65
66         (FontCallback)(id,s); 
67       
68         swf_RestoreTagPos(t);
69       }
70     }
71     t = swf_NextTag(t);
72   }
73   return n;
74 }
75
76 int swf_FontExtract_DefineFont(int id,SWFFONT * f,TAG * t)
77 { U16 fid;
78   swf_SaveTagPos(t);
79   swf_SetTagPos(t,0);
80
81   fid = swf_GetU16(t);
82   if ((!id)||(id==fid))
83   { U16 of;
84     int n,i;
85       
86     id = fid;
87     f->version = 1;
88     f->id = fid;
89
90     of = swf_GetU16(t);
91     n = of/2;
92     f->numchars = n;
93     f->glyph = malloc(sizeof(SWFGLYPH)*n);
94     memset(f->glyph, 0, sizeof(SWFGLYPH)*n);
95
96     for (i=1;i<n;i++) swf_GetU16(t);
97     for (i=0;i<n;i++) swf_GetSimpleShape(t,&f->glyph[i].shape);
98   }
99
100   swf_RestoreTagPos(t);
101   return id;
102 }
103
104 int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t)
105 { U16 fid;
106   U16 maxcode;
107   U8 flags;
108   swf_SaveTagPos(t);
109   swf_SetTagPos(t,0);
110
111   fid = swf_GetU16(t);
112   if (fid==id)
113   { U8 l = swf_GetU8(t);
114     int i;
115   
116     if(f->version>1) {
117       // DefineFont2 doesn't have FontInfo fields
118       fprintf(stderr, "fixme: FontInfo field for DefineFont2 encountered\n");
119       return -1;
120     }
121     
122     if (l)
123     { if (f->name) free(f->name);
124       f->name = (U8*)malloc(l+1);
125       if (f->name)
126       { swf_GetBlock(t,f->name,l);
127         f->name[l] = 0;
128       }
129       else
130       { swf_RestoreTagPos(t);
131         return -1;
132       }
133     }
134     flags = swf_GetU8(t);
135     if(flags & 2)
136         f->style |= FONT_STYLE_BOLD;
137     if(flags & 4)
138         f->style |= FONT_STYLE_ITALIC;
139     if(flags & 8)
140         f->encoding |= FONT_ENCODING_ANSI;
141     if(flags & 16)
142         f->encoding |= FONT_ENCODING_SHIFTJIS;
143     if(flags & 32)
144         f->encoding |= FONT_ENCODING_UNICODE;
145
146     f->glyph2ascii = (U16*)malloc(sizeof(U16)*f->numchars);
147     maxcode = 0;
148     for(i=0; i < f->numchars; i++) {
149       f->glyph2ascii[i] = ((flags&FF_WIDECODES)?swf_GetU16(t):swf_GetU8(t));
150       if(f->glyph2ascii[i] > maxcode)
151           maxcode = f->glyph2ascii[i];
152     }
153     maxcode++;
154     if(maxcode<256)
155         maxcode=256;
156     f->maxascii = maxcode;
157     f->ascii2glyph = (int*)malloc(sizeof(int)*maxcode);
158     memset(f->ascii2glyph, -1, sizeof(int)*maxcode);
159      
160     for(i = 0; i < f->numchars; i++)
161       f->ascii2glyph[f->glyph2ascii[i]] = i;
162   }
163
164   swf_RestoreTagPos(t);
165   return id;
166 }
167
168 int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag)
169 {
170     int t, glyphcount;
171     int maxcode;
172     int fid;
173     U8 flags1,flags2,namelen;
174     swf_SaveTagPos(tag);
175     swf_SetTagPos(tag,0);
176     font->version=2;
177     fid = swf_GetU16(tag);
178     if(id && id!=fid)
179         return id;
180     font->id = fid;
181     flags1 = swf_GetU8(tag);
182     flags2 = swf_GetU8(tag); //reserved flags
183
184     if(flags1 & 1)
185         font->style |= FONT_STYLE_BOLD;
186     if(flags1 & 2)
187         font->style |= FONT_STYLE_ITALIC;
188     if(flags1 & 16)
189         font->encoding |= FONT_ENCODING_ANSI;
190     if(flags1 & 32)
191         font->encoding |= FONT_ENCODING_UNICODE;
192     if(flags1 & 64)
193         font->encoding |= FONT_ENCODING_SHIFTJIS;
194
195     namelen = swf_GetU8(tag);
196     font->name = (U8*)malloc(namelen+1);
197     font->name[namelen]=0;
198     swf_GetBlock(tag, font->name, namelen);
199     font->version = 2;
200     glyphcount = swf_GetU16(tag);
201     font->numchars = glyphcount;
202     
203     font->glyph = (SWFGLYPH*)malloc(sizeof(SWFGLYPH)*glyphcount);
204     memset(font->glyph, 0, sizeof(SWFGLYPH)*glyphcount);
205     font->glyph2ascii = (U16*)malloc(sizeof(U16)*glyphcount);
206     memset(font->glyph2ascii, 0, sizeof(U16)*glyphcount);
207
208     if(flags1&8) { // wide offsets
209         for(t=0;t<glyphcount;t++)
210             swf_GetU32(tag); //offset[t]
211         swf_GetU32(tag); // fontcodeoffset
212     } else {
213         for(t=0;t<glyphcount;t++)
214             swf_GetU16(tag); //offset[t]
215         swf_GetU16(tag); // fontcodeoffset
216     }
217     for(t=0;t<glyphcount;t++)
218         swf_GetSimpleShape(tag,&(font->glyph[t].shape));
219
220     maxcode = 0;
221     for(t=0;t<glyphcount;t++) {
222         int code;
223         if(flags1&4) // wide codes
224             code = swf_GetU16(tag);
225         else
226             code = swf_GetU8(tag);
227         font->glyph2ascii[t] = code;
228         if(code > maxcode)
229             maxcode = code;
230     }
231     maxcode++;
232     if(maxcode<256)
233         maxcode=256;
234     font->maxascii = maxcode;
235     font->ascii2glyph = (int*)malloc(sizeof(int)*maxcode);
236     memset(font->ascii2glyph, -1, sizeof(int)*maxcode);
237     for(t=0;t<glyphcount;t++) 
238     {
239         font->ascii2glyph[font->glyph2ascii[t]] = t;
240     }
241
242     if(flags1&128) { // has layout
243         U16 kerningcount;
244         font->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
245         font->layout->ascent=swf_GetU16(tag);
246         font->layout->descent=swf_GetU16(tag);
247         font->layout->leading=swf_GetU16(tag);
248         for(t=0;t<glyphcount;t++) {
249             S16 advance = swf_GetS16(tag);
250             font->glyph[t].advance = advance;
251         }
252         font->layout->bounds = malloc(glyphcount*sizeof(SRECT));
253         for(t=0;t<glyphcount;t++) {
254             swf_ResetReadBits(tag);
255             swf_GetRect(tag, font->layout->bounds);
256         }
257         kerningcount = swf_GetU16(tag);
258         font->layout->kerningcount = kerningcount;
259         font->layout->kerning = (SWFKERNING*)malloc(sizeof(SWFKERNING)*kerningcount);
260         if(kerningcount) {
261             font->layout->kerning = 
262                 malloc(sizeof(*font->layout->kerning)* kerningcount);
263             for(t=0;t<kerningcount;t++)
264             {
265                 if(flags1&4) { // wide codes
266                     font->layout->kerning[t].char1 = swf_GetU16(tag);
267                     font->layout->kerning[t].char2 = swf_GetU16(tag);
268                 } else {
269                     font->layout->kerning[t].char1 = swf_GetU8(tag);
270                     font->layout->kerning[t].char2 = swf_GetU8(tag);
271                 }
272                 font->layout->kerning[t].adjustment = swf_GetS16(tag);
273             }
274         }
275     }
276     swf_RestoreTagPos(t);
277     return font->id;
278 }
279
280
281 #define FEDTJ_PRINT  0x01
282 #define FEDTJ_MODIFY 0x02
283 #define FEDTJ_CALLBACK 0x04
284
285 int swf_FontExtract_DefineTextCallback(int id,SWFFONT * f,TAG * t,int jobs, 
286         void(*callback)(int*chars, int nr, int fontid))
287 { U16    cid;
288   SRECT  r;
289   MATRIX m;
290   U8     gbits, abits, flags;
291   int    fid;
292
293   fid = 0;
294
295   swf_SaveTagPos(t);
296   swf_SetTagPos(t,0);
297
298   cid = swf_GetU16(t);
299   swf_GetRect(t,&r);
300   swf_GetMatrix(t,&m);
301   gbits = swf_GetU8(t);
302   abits = swf_GetU8(t);
303
304   flags = swf_GetU8(t);
305   
306   while(flags)
307   { if (flags&TF_TEXTCONTROL)
308     { if (flags&TF_HASFONT) fid = swf_GetU16(t);
309       if (flags&TF_HASCOLOR)
310       { swf_GetU8(t); // rgb
311         swf_GetU8(t);
312         swf_GetU8(t);
313         if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_GetU8(t);
314       }
315       if (flags&TF_HASXOFFSET) swf_GetS16(t);
316       if (flags&TF_HASYOFFSET) swf_GetS16(t);
317       if (flags&TF_HASFONT) swf_GetU16(t);
318     }
319     else
320     { int i;
321       int buf[256];
322       for (i=0;i<flags;i++)
323       { int glyph;
324         int adv;
325         glyph = swf_GetBits(t,gbits);
326         adv = swf_GetBits(t,abits);
327         if (id==fid)                    // mitlesen ?
328           if (jobs&FEDTJ_PRINT) {
329             { int code = f->glyph2ascii[glyph];
330               printf("%c",code);
331           }
332           if (jobs&FEDTJ_MODIFY)
333             /*if (!f->glyph[code].advance)*/ f->glyph[glyph].advance = adv;
334         }
335         buf[i] = glyph;
336       }
337       if ((id==fid)&&(jobs&FEDTJ_PRINT)) printf("\n");
338       if (jobs&FEDTJ_CALLBACK)
339           callback(buf, flags, fid);
340     }
341     flags = swf_GetU8(t);
342   }
343   
344   swf_RestoreTagPos(t);
345   return id;
346 }  
347
348 int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs)
349 {
350     return swf_FontExtract_DefineTextCallback(id,f,t,jobs,0);
351 }
352
353 int swf_FontExtract(SWF * swf,int id,SWFFONT * * font)
354 { TAG * t;
355   SWFFONT * f;
356     
357   if ((!swf)||(!font)) return -1;
358
359   f = (SWFFONT *)malloc(sizeof(SWFFONT)); font[0] = f;
360   if (!f) return -1;
361   
362   memset(f,0x00,sizeof(SWFFONT));
363
364   t = swf->firstTag;
365
366   while (t)
367   { int nid = 0;
368     switch (swf_GetTagID(t))
369     { case ST_DEFINEFONT:
370         nid = swf_FontExtract_DefineFont(id,f,t);
371         break;
372     
373       case ST_DEFINEFONT2:
374         nid = swf_FontExtract_DefineFont2(id,f,t);
375         break;
376         
377       case ST_DEFINEFONTINFO:
378         nid = swf_FontExtract_DefineFontInfo(id,f,t);
379         break;
380         
381       case ST_DEFINETEXT:
382       case ST_DEFINETEXT2:
383         nid = swf_FontExtract_DefineText(id,f,t,f->layout?0:FEDTJ_MODIFY);
384         break;
385     }
386     if (nid>0) id = nid;
387     t = swf_NextTag(t);
388   }
389   return 0;
390 }
391
392 int swf_FontSetID(SWFFONT * f,U16 id) { if (!f) return -1; f->id = id; return 0; }
393
394 int swf_FontReduce(SWFFONT * f,FONTUSAGE * use)
395 { int i,j;
396   if ((!f)||(!use)) return -1;
397
398   j = 0;
399   for (i=0;i<f->numchars;i++)
400     if (f->glyph[i].shape)
401     { if (f->glyph2ascii[i]<MAX_CHAR_PER_FONT && 
402             use->code[f->glyph2ascii[i]])
403       { f->ascii2glyph[f->glyph2ascii[i]] = j;
404         f->glyph2ascii[j] = f->glyph2ascii[i];
405         f->glyph[j] = f->glyph[i];
406         j++;
407       }
408       else
409       { swf_ShapeFree(f->glyph[i].shape);
410         f->ascii2glyph[f->glyph2ascii[i]] = -1;
411         f->glyph2ascii[i] = 0;
412         f->glyph[i].shape   = NULL;
413         f->glyph[i].advance = 0;
414       }
415     } else f->ascii2glyph[f->glyph2ascii[i]] = -1;
416
417   f->numchars = j;
418     
419   return j;
420 }
421
422 int swf_FontInitUsage(FONTUSAGE * use)
423 { if (!use) return -1;
424   memset(use->code,0,sizeof(use->code[0])*MAX_CHAR_PER_FONT);
425   return 0;
426 }
427
428 int swf_FontUse(FONTUSAGE * use,U8 * s)
429 { if ((!use)||(!s)) return -1;
430   while (s[0])
431   { use->code[s[0]] = 1;
432     s++;
433   }
434   return 0;  
435 }
436
437 int swf_FontSetDefine(TAG * t,SWFFONT * f)
438 { U16*ofs = (U16*)malloc(f->numchars*2);
439   int p,i,j;
440     
441   if ((!t)||(!f)) return -1;
442   swf_ResetWriteBits(t);
443   swf_SetU16(t,f->id);
444
445   p = 0; j = 0;
446   for (i=0;i<f->numchars;i++)
447     if (f->glyph[i].shape)
448     { ofs[j++] = p;
449       p+=swf_SetSimpleShape(NULL,f->glyph[i].shape);
450     }
451
452   for (i=0;i<j;i++) swf_SetU16(t,ofs[i]+j*2);
453   
454   for (i=0;i<f->numchars;i++)
455     if (f->glyph[i].shape)
456       swf_SetSimpleShape(t,f->glyph[i].shape);
457   
458   swf_ResetWriteBits(t);
459   free(ofs);
460   return 0;
461 }
462
463 int swf_FontSetDefine2(TAG *tag, SWFFONT * f)
464 {
465     U8 flags = 0;
466     int t;
467     int pos;
468     int pos2;
469     swf_SetU16(tag, f->id);
470     if(f->layout) 
471         flags |= 128; // haslayout
472     if(f->numchars>256)
473         flags |= 4; // widecodes
474     if(f->style & FONT_STYLE_BOLD)
475         flags |= 1; // bold
476     if(f->style & FONT_STYLE_ITALIC)
477         flags |= 2; // italic
478     /* wideoffs 8 */
479     if(f->encoding & FONT_ENCODING_ANSI)
480         flags |= 16; // ansi
481     if(f->encoding & FONT_ENCODING_UNICODE)
482         flags |= 32; // unicode
483     if(f->encoding & FONT_ENCODING_SHIFTJIS)
484         flags |= 64; // shiftjis
485
486     swf_SetU8(tag, flags);
487     swf_SetU8(tag, 0); //reserved flags
488     if(f->name) {
489         /* font name */
490         swf_SetU8(tag, strlen(f->name));
491         swf_SetBlock(tag, f->name, strlen(f->name));
492     } else {
493         /* font name (="") */
494         swf_SetU8(tag, 0); /*placeholder*/
495     }
496     /* number of glyphs */
497     swf_SetU16(tag, f->numchars);
498     /* font offset table */
499     pos = tag->len;
500     for(t=0;t<f->numchars;t++)
501     {
502         swf_SetU16(tag, /* fontoffset */ 0); /*placeholder*/
503     }
504     pos2 = tag->len;
505     swf_SetU16(tag, 0); //fontcode-fontoffset
506     for(t=0;t<f->numchars;t++) {
507         tag->data[pos + t*2] = (tag->len-pos);
508         tag->data[pos + t*2 + 1] = (tag->len-pos) >> 8;
509         swf_SetSimpleShape(tag, f->glyph[t].shape);
510     }
511
512     tag->data[pos2] = tag->len - pos;
513     tag->data[pos2 + 1] = (tag->len - pos) >> 8;
514     
515     /* font code table */
516     if(flags & 4) /* wide codes */ {
517         for(t=0;t<f->numchars;t++)
518             swf_SetU16(tag,f->glyph2ascii[t]);
519     } else {
520         for(t=0;t<f->numchars;t++)
521             swf_SetU8(tag,f->glyph2ascii[t]);
522     }
523     if(f->layout) 
524     {
525         swf_SetU16(tag,f->layout->ascent);
526         swf_SetU16(tag,f->layout->descent);
527         swf_SetU16(tag,f->layout->leading);
528         for(t=0;t<f->numchars;t++)
529             swf_SetU16(tag,f->glyph[t].advance);
530         for(t=0;t<f->numchars;t++) {
531             swf_ResetWriteBits(tag);
532             swf_SetRect(tag,&f->layout->bounds[t]);
533         }
534         swf_SetU16(tag, f->layout->kerningcount);
535         for(t=0;t<f->layout->kerningcount;t++) {
536             if(flags & 4) /* wide codes */ {
537                 swf_SetU8(tag,f->layout->kerning[t].char1);
538                 swf_SetU8(tag,f->layout->kerning[t].char2);
539             } else {
540                 swf_SetU16(tag,f->layout->kerning[t].char1);
541                 swf_SetU16(tag,f->layout->kerning[t].char2);
542             }
543             swf_SetU16(tag,f->layout->kerning[t].adjustment);
544         }
545     }
546     return 0;
547 }
548     
549 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading)
550 {
551     f->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
552     f->layout->ascent = ascent;
553     f->layout->descent = descent;
554     f->layout->leading = leading;
555     f->layout->kerningcount = 0;
556     f->layout->kerning = 0;
557     f->layout->bounds = (SRECT*)malloc(sizeof(SRECT)*f->numchars);
558     memset(f->layout->bounds, 0, sizeof(SRECT)*f->numchars);
559 }
560
561 int swf_FontSetInfo(TAG * t,SWFFONT * f)
562 { int l,i;
563   U8 wide=0;
564   U8 flags = 0;
565   if ((!t)||(!f)) return -1;
566   swf_ResetWriteBits(t);
567   swf_SetU16(t,f->id);
568   l = strlen(f->name); if (l>255) l = 255;
569   swf_SetU8(t,l);
570   swf_SetBlock(t,f->name,l);
571   if(f->numchars>=256)
572       wide=1;
573
574   if(f->style & FONT_STYLE_BOLD)
575       flags |= 2;
576   if(f->style & FONT_STYLE_ITALIC)
577       flags |= 4;
578   if(f->style & FONT_ENCODING_ANSI)
579       flags |= 8;
580   if(f->style & FONT_ENCODING_SHIFTJIS)
581       flags |= 16;
582   if(f->style & FONT_ENCODING_UNICODE)
583       flags |= 32;
584     
585   swf_SetU8(t,(flags&0xfe)|wide);
586
587   for (i=0;i<f->numchars;i++) {
588     if (f->glyph[i].shape)
589       wide?swf_SetU16(t,f->glyph2ascii[i]):
590            swf_SetU8(t,f->glyph2ascii[i]);
591   }
592   
593   return 0;
594 }
595
596 int swf_FontExport(int handle,SWFFONT * f)
597 { int l;
598   int i;
599   if (!f) return 0;
600
601   l = sizeof(SWFFONT);
602   if (handle>=0)
603     if (write(handle,f,sizeof(SWFFONT))!=sizeof(SWFFONT)) return -1;
604
605   if (f->name)
606   { U16 ln = strlen(f->name);
607     l+=2+ln;
608     if (handle>=0)
609     { if (write(handle,&ln,2)!=2) return -1;
610       if (write(handle,f->name,ln)!=ln) return -1;
611     }
612   }
613
614   if (f->layout)
615   { l+=sizeof(SWFLAYOUT);
616     if (handle>=0)
617       if (write(handle,f->layout,sizeof(SWFLAYOUT))!=sizeof(SWFLAYOUT)) return -1;
618 /*    new kerning struct. hope commenting this out doesn't break things
619       if (f->layout->kerning.data)
620     { l+=f->layout->kerning.count*4;
621       if (handle>=0)
622         if (write(handle,f->layout->kerning.data,f->layout->kerning.count*4)!=f->layout->kerning.count*4) return -1;
623     }*/
624   }
625
626   for (i=0;i<f->numchars;i++)
627   { if (f->glyph[i].shape)
628     { int ll = swf_ShapeExport(handle,f->glyph[i].shape);
629       if (ll<0) return -1;
630       l+=ll;
631     }  
632   }
633
634   return l;
635 }
636
637 int swf_FontImport(int handle,SWFFONT * * font)
638 { SWFFONT * f;
639   int layout;
640   int i = 0;
641
642   if ((!font)||(handle<0)) return -1;
643
644   f = (SWFFONT *)malloc(sizeof(SWFFONT)); font[0] = f;
645   if (!f) return -1;
646
647   memset(f,0x00,sizeof(SWFFONT));
648   
649   if (read(handle,f,sizeof(SWFFONT))!=sizeof(SWFFONT)) goto fehler;
650
651   layout = (f->layout)?1:0;             // avoid illegal free()
652   f->layout = NULL;
653
654   if (f->name)
655   { U16 ln;
656     f->name = NULL;
657     if (read(handle,&ln,2)!=2) goto fehler;
658     f->name = (U8*)malloc(ln+1);
659     if (!f->name) goto fehler;
660     if (read(handle,f->name,ln)!=ln) goto fehler;
661     f->name[ln] = 0;
662   }
663
664   if (f->layout)
665   { f->layout = (SWFLAYOUT *)malloc(sizeof(SWFLAYOUT));
666     if (!f->layout) goto fehler;
667     if (read(handle,f->layout,sizeof(SWFLAYOUT))!=sizeof(SWFLAYOUT)) goto fehler;
668     /* new kerning struct. hope commenting this out doesn't break things
669     if (f->layout->kerning.data)
670     { int l = f->layout->kerning.count*4;
671       f->layout->kerning.data = (U8*)malloc(l);
672       if (!f->layout->kerning.data) goto fehler;
673       if (read(handle,f->layout->kerning.data,l)!=l) goto fehler;
674     } */
675   }
676
677   for (i=0;i<f->numchars;i++)
678   { if (f->glyph[i].shape)
679     { if (swf_ShapeImport(handle,&f->glyph[i].shape)<0) goto fehler;
680     }
681   }
682
683   f->id = 0;
684   
685   return 0;
686   
687 fehler:
688   if (f) for (;i<MAX_CHAR_PER_FONT;i++) f->glyph[i].shape = NULL;
689   swf_FontFree(f);
690   font[0] = NULL;
691   return -1;
692 }
693
694 int swf_TextPrintDefineText(TAG * t,SWFFONT * f)
695 { int id = swf_GetTagID(t);
696   if ((id==ST_DEFINETEXT)||(id==ST_DEFINETEXT2)) swf_FontExtract_DefineText(f->id,f,t,FEDTJ_PRINT);
697     else return -1;
698   return 0;
699 }
700
701 void swf_LayoutFree(SWFLAYOUT * l)
702 { if (l)
703   { if (l->kerning) free(l->kerning);
704     l->kerning = NULL;
705     if (l->bounds) free(l->bounds);
706     l->bounds = NULL;
707   }
708   free(l);
709 }
710
711 void swf_FontFree(SWFFONT * f)
712 { if (f)
713   { int i;
714       
715     if (f->name) free(f->name);
716     if (f->layout) swf_LayoutFree(f->layout);
717
718     f->name = NULL;
719     f->layout = NULL;
720
721     if(f->glyph) {
722       for (i=0;i<f->numchars;i++)
723         if (f->glyph[i].shape)
724         { swf_ShapeFree(f->glyph[i].shape);
725           f->glyph[i].shape = NULL;
726         }
727       free(f->glyph);
728       f->glyph = NULL;
729     }
730     if(f->ascii2glyph) {
731       free(f->ascii2glyph);
732       f->ascii2glyph = NULL;
733     }
734     if(f->glyph2ascii) {
735       free(f->glyph2ascii);
736       f->glyph2ascii = NULL;
737     }
738   }
739   free(f);
740 }
741
742 int swf_TextSetInfoRecord(TAG * t,SWFFONT * font,U16 size,RGBA * color,S16 dx,S16 dy)
743 { U8 flags;
744   if (!t) return -1;
745
746   flags = TF_TEXTCONTROL|(font?TF_HASFONT:0)|(color?TF_HASCOLOR:0)|(dx?TF_HASXOFFSET:0)|(dy?TF_HASYOFFSET:0);
747
748   swf_SetU8(t,flags);
749   if (font) swf_SetU16(t,font->id);
750   if (color)
751   { if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_SetRGBA(t,color);
752     else swf_SetRGB(t,color);
753   }
754   if (dx) swf_SetS16(t,dx);
755   if (dy) swf_SetS16(t,dy);
756   if (font) swf_SetU16(t,size);
757   
758   return 0;
759 }
760
761 int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits)
762 { U16 g,a;
763   if ((!s)||(!font)||((!gbits)&&(!abits))||(!font->ascii2glyph)) return -1;
764   g = a = 0;
765
766   while(s[0])
767   { 
768     int glyph = font->ascii2glyph[s[0]];
769     if(glyph>=0) {
770        g = swf_CountBits(glyph,g);
771        a = swf_CountBits((((U32)font->glyph[glyph].advance)*scale)/100,a);
772     }
773     s++;
774   }
775
776   if (gbits) gbits[0] = (U8)g;
777   if (abits) abits[0] = (U8)a;
778
779   return 0;
780 }
781
782 int swf_TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 abits)
783 { int l,i;
784     
785   if ((!t)||(!font)||(!s)||(!font->ascii2glyph)) return -1;
786
787   l = strlen(s);
788   if (l>0x7f) l = 0x7f;
789   swf_SetU8(t,l);
790
791   for (i=0;i<l;i++)
792   { 
793     int g = font->ascii2glyph[s[i]];
794     if(g>=0) {
795       swf_SetBits(t,g,gbits);
796       swf_SetBits(t,(((U32)font->glyph[g].advance)*scale)/100,abits);
797     }
798   }
799
800   swf_ResetWriteBits(t);
801   return 0;
802 }
803
804 U32 swf_TextGetWidth(SWFFONT * font,U8 * s,int scale)
805 { U32 res = 0;
806
807   if (font&&s)
808   { while (s[0])
809     { 
810       int g = font->ascii2glyph[*s];
811       if(g>=0)
812         res += font->glyph[g].advance;
813       s++;
814     }
815     if (scale) res = (res*scale)/100;
816   }
817   return res;
818 }
819
820 SWFFONT* swf_ReadFont(char* filename)
821 {
822   int f;
823   SWF swf;
824   if(!filename)
825       return 0;
826   f = open(filename,O_RDONLY);
827   
828   if (f<0 || swf_ReadSWF(f,&swf)<0)
829   { fprintf(stderr,"%s is not a valid SWF font file or contains errors.\n",filename);
830     close(f);
831     return 0;
832   }
833   else
834   { SWFFONT*font;
835     close(f);
836     if(swf_FontExtract(&swf, WRITEFONTID, &font) < 0)
837        return 0;
838     swf_FreeTags(&swf);
839     return font;
840   }
841 }
842
843 void swf_WriteFont(SWFFONT*font, char* filename)
844 { SWF swf;
845   TAG * t;
846   SRECT r;
847   RGBA rgb;
848   int f;
849   int useDefineFont2 = 0;
850
851   if(font->layout)
852       useDefineFont2 = 1; /* the only thing new in definefont2 
853                              is layout information. */
854
855   font->id = WRITEFONTID; //"FN"
856
857   memset(&swf,0x00,sizeof(SWF));
858
859   swf.fileVersion    = 4;
860   swf.frameRate      = 0x4000;
861
862   /* if we use DefineFont1 to store the characters,
863      we have to build a textfield to store the
864      advance values. While at it, we can also
865      make the whole .swf viewable */
866
867   /* we now always create viewable swfs, even if we
868      did use definefont2 -mk*/
869   t = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
870   swf.firstTag = t;
871         rgb.r = 0xff;
872         rgb.g = 0xff;
873         rgb.b = 0xff;
874         swf_SetRGB(t,&rgb);
875   if(!useDefineFont2) {
876     t = swf_InsertTag(t,ST_DEFINEFONT);
877     swf_FontSetDefine(t,font);
878     t = swf_InsertTag(t,ST_DEFINEFONTINFO);
879     swf_FontSetInfo(t,font);
880   } else {
881     t = swf_InsertTag(t,ST_DEFINEFONT2);
882     swf_FontSetDefine2(t,font);
883   }
884
885   if(1) //useDefineFont2
886   {     int textscale = 400;
887         int s;
888         int xmax = 0;
889         int ymax = textscale * 2 * (font->maxascii/16+1);
890         U8 gbits,abits;
891         char text[MAX_CHAR_PER_FONT+1];
892         int x,y;
893         text[MAX_CHAR_PER_FONT]=0;
894         for(s=0;s<font->maxascii;s++)
895         {
896             int g = font->ascii2glyph[s];
897             text[s] = s;
898             if(g>=0) {
899                if(font->glyph[g].advance*textscale/200 > xmax)
900                    xmax = font->glyph[g].advance*textscale/200;
901             }
902         }
903         swf.movieSize.xmax = xmax*20;
904         swf.movieSize.ymax = ymax;
905
906         t = swf_InsertTag(t,ST_DEFINETEXT);
907
908             swf_SetU16(t,font->id+1);            // ID
909
910             r.xmin = 0;
911             r.ymin = 0;
912             r.xmax = swf.movieSize.xmax*20;
913             r.ymax = swf.movieSize.ymax;
914             
915             swf_SetRect(t,&r);
916
917             swf_SetMatrix(t,NULL);
918
919             abits = swf_CountBits(xmax*16, 0);
920             gbits = 8;
921             
922             swf_SetU8(t,gbits);
923             swf_SetU8(t,abits);
924
925             rgb.r = 0x00;
926             rgb.g = 0x00;
927             rgb.b = 0x00;
928             for(y=0;y<=((font->maxascii-1)/16);y++)
929             {
930                 int c=0,lastx=-1;
931                 /* TODO: firstx?? */
932                 for(x=0;x<16;x++) {
933                     int g = (y*16+x<font->maxascii)?font->ascii2glyph[y*16+x]:-1;
934                     if(g>=0 && font->glyph[g].shape) {
935                         c++;
936                         if(lastx<0) 
937                             lastx = x*xmax;
938                     }
939                 }
940                 if(c) {
941                   swf_TextSetInfoRecord(t,font,textscale,&rgb,lastx+1,textscale*y*2);
942                   for(x=0;x<16;x++)
943                   {
944                       int g = (y*16+x<font->maxascii)?font->ascii2glyph[y*16+x]:-1;
945                       if(g>=0 && font->glyph[g].shape) {
946                         if(lastx != x*xmax) {
947                             swf_TextSetInfoRecord(t,0,0,0,x*xmax+1,0);
948                         }
949                         swf_SetU8(t,1);
950                         swf_SetBits(t, g, gbits);
951                         swf_SetBits(t, font->glyph[g].advance, abits);
952                         lastx = x*xmax+font->glyph[g].advance;
953                         swf_ResetWriteBits(t);
954                       }
955                   }
956                 } 
957             }
958             swf_SetU8(t,0);
959
960         
961         t = swf_InsertTag(t,ST_PLACEOBJECT2);
962
963             swf_ObjectPlace(t,font->id+1,1,NULL,NULL,NULL);
964      
965         t = swf_InsertTag(t,ST_SHOWFRAME);
966   }
967   
968   t = swf_InsertTag(t,ST_END);
969
970   f = open(filename, O_RDWR|O_CREAT|O_TRUNC,0644);
971   if FAILED(swf_WriteSWF(f,&swf)) fprintf(stderr,"WriteSWF() failed in writeFont().\n");
972   close(f);
973
974   swf_FreeTags(&swf);
975 }
976
977
978 void swf_SetEditText(TAG*tag, U16 flags, SRECT r, char*text, RGBA*color, 
979         int maxlength, U16 font, U16 height, EditTextLayout*layout, char*variable)
980 {
981     swf_SetRect(tag,&r);
982     swf_ResetWriteBits(tag);
983
984     flags &= ~(ET_HASTEXT|ET_HASTEXTCOLOR|ET_HASMAXLENGTH|ET_HASFONT|ET_HASLAYOUT);
985     if(text) flags |= ET_HASTEXT;
986     if(color) flags |= ET_HASTEXTCOLOR;
987     if(maxlength) flags |= ET_HASMAXLENGTH;
988     if(font) flags |= ET_HASFONT;
989     if(layout) flags |= ET_HASLAYOUT;
990
991     swf_SetBits(tag, flags, 16);
992
993     if(flags & ET_HASFONT) {
994         swf_SetU16(tag, font); //font
995         swf_SetU16(tag, height); //fontheight
996     }
997     if(flags & ET_HASTEXTCOLOR) {
998         swf_SetRGBA(tag, color);
999     }
1000     if(flags & ET_HASMAXLENGTH) {
1001         swf_SetU16(tag, maxlength); //maxlength
1002     }
1003     if(flags & ET_HASLAYOUT) {
1004         swf_SetU8(tag,layout->align); //align
1005         swf_SetU16(tag,layout->leftmargin); //left margin
1006         swf_SetU16(tag,layout->rightmargin); //right margin
1007         swf_SetU16(tag,layout->indent); //indent
1008         swf_SetU16(tag,layout->leading); //leading
1009     }
1010     swf_SetString(tag, variable);
1011     if(flags & ET_HASTEXT)
1012         swf_SetString(tag,text);
1013 }
1014