added pivotx,pivoty parameters to matrix constructor.
[swftools.git] / lib / modules / swftext.c
index cb55d76..3d6a49b 100644 (file)
@@ -6,6 +6,7 @@
    Part of the swftools package.
 
    Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+   Copyright (c) 2003,2004 Matthias Kramm
  
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -56,22 +57,26 @@ int swf_FontEnumerate(SWF * swf,void (*FontCallback) (U16,U8*))
   n = 0;
 
   while (t)
-  { if (swf_GetTagID(t)==ST_DEFINEFONTINFO || swf_GetTagID(t)==ST_DEFINEFONTINFO2 ||
-         swf_GetTagID(t)==ST_DEFINEFONT2)
+  { 
+    if (swf_GetTagID(t)==ST_DEFINEFONT2 || swf_GetTagID(t)==ST_DEFINEFONT)
     { n++;
       if (FontCallback)
       { U16 id;
         int l;
         U8 s[257];
+       s[0] = 0;
         swf_SaveTagPos(t);
         swf_SetTagPos(t,0);
        
         id  = swf_GetU16(t);
-       if(swf_GetTagID(t) == ST_DEFINEFONT2)
+       if(swf_GetTagID(t) == ST_DEFINEFONT2 ||
+          swf_GetTagID(t) == ST_DEFINEFONTINFO ||
+          swf_GetTagID(t) == ST_DEFINEFONTINFO2) {
            swf_GetU16(t);
-        l   = swf_GetU8(t);
-        swf_GetBlock(t,s,l);
-        s[l] = 0;
+           l = swf_GetU8(t);
+            swf_GetBlock(t,s,l);
+            s[l] = 0;
+       }
 
         (FontCallback)(id,s); 
       
@@ -174,6 +179,31 @@ int swf_FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t)
   return id;
 }
 
+int swf_FontExtract_GlyphNames(int id,SWFFONT * f,TAG * tag)
+{ 
+    U16 fid;
+    U16 maxcode;
+    U8 flags;
+    swf_SaveTagPos(tag);
+    swf_SetTagPos(tag,0);
+
+    fid = swf_GetU16(tag);
+
+    if (fid==id)
+    { 
+        int num = swf_GetU16(tag);
+       int t;
+       f->glyphnames = malloc(sizeof(char*)*num);
+       for(t=0;t<num;t++) {
+           f->glyphnames[t] = strdup(swf_GetString(tag));
+       }
+    }
+
+    swf_RestoreTagPos(tag);
+    return id;
+}
+
+
 int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag)
 {
     int t, glyphcount;
@@ -297,15 +327,18 @@ int swf_FontExtract_DefineFont2(int id,SWFFONT * font,TAG * tag)
 #define FEDTJ_MODIFY 0x02
 #define FEDTJ_CALLBACK 0x04
 
-int swf_FontExtract_DefineTextCallback(int id,SWFFONT * f,TAG * t,int jobs, 
-       void(*callback)(int*chars, int nr, int fontid))
+static int swf_FontExtract_DefineTextCallback(int id,SWFFONT * f,TAG * t,int jobs, 
+       void(*callback)(void*self, int*chars, int*ypos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA* color), void*self)
 { U16    cid;
   SRECT  r;
   MATRIX m;
-  U8     gbits, abits, flags;
-  int    fid;
+  U8     gbits, abits;
+  int    fid=0;
+  RGBA  color;
+  int   x=0,y=0;
+  int   fontsize=0;
 
-  fid = 0;
+  memset(&color, 0, sizeof(color));
 
   swf_SaveTagPos(t);
   swf_SetTagPos(t,0);
@@ -316,57 +349,77 @@ int swf_FontExtract_DefineTextCallback(int id,SWFFONT * f,TAG * t,int jobs,
   gbits = swf_GetU8(t);
   abits = swf_GetU8(t);
 
-  flags = swf_GetU8(t);
-  
-  while(flags)
+  while(1)
   { 
-    // FIXME: according to open-swf@macromedia.com, this is wrong.
-    // it should alternate textcontrol and text arrays, not
-    // rely on the high bit. (and length can be 0-255).
+    int flags,num;
+    flags = swf_GetU8(t);
+    if(!flags)
+       break;
+  
     if (flags&TF_TEXTCONTROL)
     { if (flags&TF_HASFONT) fid = swf_GetU16(t);
       if (flags&TF_HASCOLOR)
-      { swf_GetU8(t); // rgb
-        swf_GetU8(t);
-        swf_GetU8(t);
-        if (swf_GetTagID(t)==ST_DEFINETEXT2) swf_GetU8(t);
+      { color.r = swf_GetU8(t); // rgb
+        color.g = swf_GetU8(t);
+        color.b = swf_GetU8(t);
+        if (swf_GetTagID(t)==ST_DEFINETEXT2) color.a = swf_GetU8(t);
       }
-      if (flags&TF_HASXOFFSET) swf_GetS16(t);
-      if (flags&TF_HASYOFFSET) swf_GetS16(t);
-      if (flags&TF_HASFONT) swf_GetU16(t);
+      if (flags&TF_HASXOFFSET) x = swf_GetS16(t);
+      if (flags&TF_HASYOFFSET) y = swf_GetS16(t);
+      if (flags&TF_HASFONT) fontsize = swf_GetU16(t);
     }
-    else
+
+    num = swf_GetU8(t);
+    if(!num)
+       break;
+
     { int i;
       int buf[256];
-      for (i=0;i<flags;i++)
+      int advance[256];
+      int xpos = 0;
+      for (i=0;i<num;i++)
       { int glyph;
-        int adv;
+        int adv = 0;
+       advance[i] = xpos;
         glyph = swf_GetBits(t,gbits);
         adv = swf_GetBits(t,abits);
-        if (id==fid)                    // mitlesen ?
+       xpos+=adv;
+       
+       // <deprectated>
+       if (id==fid) {
           if (jobs&FEDTJ_PRINT) {
-           { int code = f->glyph2ascii[glyph];
+             int code = f->glyph2ascii[glyph];
              printf("%c",code);
          }
           if (jobs&FEDTJ_MODIFY)
-            /*if (!f->glyph[code].advance)*/ f->glyph[glyph].advance = adv;
-        }
+           f->glyph[glyph].advance = adv*20; //?
+        } else {
+            if (jobs&FEDTJ_PRINT) {
+               printf("?");
+           }
+       }
+       // </deprectated>
+
        buf[i] = glyph;
       }
       if ((id==fid)&&(jobs&FEDTJ_PRINT)) printf("\n");
       if (jobs&FEDTJ_CALLBACK)
-         callback(buf, flags, fid);
+         callback(self, buf, advance, num, fid, fontsize, x, y, &color);
+      x += xpos;
     }
-    flags = swf_GetU8(t);
   }
   
   swf_RestoreTagPos(t);
   return id;
 }  
+int swf_ParseDefineText(TAG * tag, void(*callback)(void*self, int*chars, int*ypos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA* color), void*self)
+{
+    return swf_FontExtract_DefineTextCallback(-1, 0, tag, FEDTJ_CALLBACK, callback, self);
+}
 
 int swf_FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs)
 {
-    return swf_FontExtract_DefineTextCallback(id,f,t,jobs,0);
+    return swf_FontExtract_DefineTextCallback(id,f,t,jobs,0,0);
 }
 
 int swf_FontExtract(SWF * swf,int id,SWFFONT * * font)
@@ -400,6 +453,10 @@ int swf_FontExtract(SWF * swf,int id,SWFFONT * * font)
       case ST_DEFINETEXT2:
         nid = swf_FontExtract_DefineText(id,f,t,f->layout?0:FEDTJ_MODIFY);
         break;
+      
+      case ST_GLYPHNAMES:
+        nid = swf_FontExtract_GlyphNames(id,f,t);
+        break;
     }
     if (nid>0) id = nid;
     t = swf_NextTag(t);
@@ -421,7 +478,7 @@ int swf_FontReduce(SWFFONT * f,FONTUSAGE * use)
   j = 0;
   for (i=0;i<f->numchars;i++)
     if (f->glyph[i].shape)
-    { if (f->glyph2ascii[i]<f->numchars&& 
+    { if (f->glyph2ascii[i]<f->maxascii&& 
            use->code[f->glyph2ascii[i]])
       { f->ascii2glyph[f->glyph2ascii[i]] = j;
         f->glyph2ascii[j] = f->glyph2ascii[i];
@@ -444,8 +501,8 @@ int swf_FontReduce(SWFFONT * f,FONTUSAGE * use)
 
 int swf_FontInitUsage(SWFFONT* f, FONTUSAGE * use)
 { if (!use) return -1;
-  use->code = malloc(sizeof(use->code[0])*f->numchars);
-  memset(use->code,0,sizeof(use->code[0])*f->numchars);
+  use->code = malloc(sizeof(use->code[0])*f->maxascii);
+  memset(use->code,0,sizeof(use->code[0])*f->maxascii);
   return 0;
 }
 
@@ -454,7 +511,7 @@ void swf_FontClearUsage(SWFFONT* f, FONTUSAGE * use)
   free(use->code);
 }
 
-int swf_FontUse(FONTUSAGE * use,U8 * s)
+int swf_FontUse(SWFFONT*f, FONTUSAGE * use,U8 * s)
 { if ((!use)||(!s)) return -1;
   while (s[0])
   { use->code[s[0]] = 1;
@@ -743,7 +800,7 @@ int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits)
        glyph = font->ascii2glyph[s[0]];
     if(glyph>=0) {
        g = swf_CountUBits(glyph,g);
-       a = swf_CountBits((((U32)font->glyph[glyph].advance)*scale)/100,a);
+       a = swf_CountBits(((((U32)font->glyph[glyph].advance)*scale)/20)/100,a);
     }
     s++;
   }
@@ -769,7 +826,7 @@ int swf_TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 ab
        g = font->ascii2glyph[s[i]];
     if(g>=0) {
       swf_SetBits(t,g,gbits);
-      swf_SetBits(t,(((U32)font->glyph[g].advance)*scale)/100,abits);
+      swf_SetBits(t,((((U32)font->glyph[g].advance)*scale)/20)/100,abits);
       l++;
       if(l==0x7f)
          break;
@@ -792,7 +849,7 @@ U32 swf_TextGetWidth(SWFFONT * font,U8 * s,int scale)
       if(*s < font->maxascii) 
          g = font->ascii2glyph[*s];
       if(g>=0)
-        res += font->glyph[g].advance;
+        res += font->glyph[g].advance/20;
       s++;
     }
     if (scale) res = (res*scale)/100;
@@ -830,6 +887,7 @@ void swf_WriteFont(SWFFONT*font, char* filename)
   RGBA rgb;
   int f;
   int useDefineFont2 = 0;
+  int storeGlyphNames = 1;
 
   if(font->layout)
       useDefineFont2 = 1; /* the only thing new in definefont2 
@@ -865,6 +923,17 @@ void swf_WriteFont(SWFFONT*font, char* filename)
     swf_FontSetDefine2(t,font);
   }
 
+  if(storeGlyphNames && font->glyphnames)
+  {
+    int c;
+    t = swf_InsertTag(t,ST_GLYPHNAMES);
+    swf_SetU16(t, font->id);
+    swf_SetU16(t, font->numchars);
+    for(c=0;c<font->numchars;c++) {
+       swf_SetString(t, font->glyphnames[c]);
+    }
+  }
+
   if(1) //neccessary only for df1, but pretty to look at anyhow, so do it always
   {
         int textscale = 400;
@@ -880,8 +949,8 @@ void swf_WriteFont(SWFFONT*font, char* filename)
        {
            int g = font->ascii2glyph[s];
            if(g>=0) {
-              if(font->glyph[g].advance*textscale/64 > xmax) {
-                  xmax = font->glyph[g].advance*textscale/64;
+              if((font->glyph[g].advance*textscale/20)/64 > xmax) {
+                  xmax = (font->glyph[g].advance*textscale/20)/64;
               }
               c++;
            }
@@ -942,8 +1011,8 @@ void swf_WriteFont(SWFFONT*font, char* filename)
                        }
                        swf_SetU8(t,1);
                        swf_SetBits(t, g, gbits);
-                       swf_SetBits(t, font->glyph[g].advance, abits);
-                       lastx = x*xmax+font->glyph[g].advance;
+                       swf_SetBits(t, font->glyph[g].advance/20, abits);
+                       lastx = x*xmax+(font->glyph[g].advance/20);
                        swf_ResetWriteBits(t);
                      }
                  }
@@ -1026,7 +1095,7 @@ SRECT swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale)
                    rn.ymin = (rn.ymin * scale)/100;
                    rn.ymax = (rn.ymax * scale)/100;
                    swf_ExpandRect2(&r, &rn);
-                   pos += (font->glyph[g].advance*scale*20)/100;
+                   pos += (font->glyph[g].advance*scale)/100;
                }
            }
            c++;
@@ -1089,9 +1158,8 @@ void swf_FontCreateLayout(SWFFONT*f)
        bbox = swf_GetShapeBoundingBox(shape2);
        swf_Shape2Free(shape2);
        f->layout->bounds[t] = bbox;
-       /* FIXME */
-       //width = (bbox.xmax - bbox.xmin)/20;
-       width = (bbox.xmax)/20;
+       
+       width = (bbox.xmax);
 
        /* The following is a heuristic- it may be that extractfont_DefineText
           has already found out some widths for individual characters (from the way
@@ -1159,11 +1227,12 @@ void swf_DrawText(drawer_t*draw, SWFFONT*font, char*text)
     while(*s) {
        SHAPE*shape;
        SHAPE2*shape2;
+       SHAPELINE*l;
        U32 c = readUTF8char(&s);
        int g = font->ascii2glyph[c];
        shape = font->glyph[g].shape;
        shape2 = swf_ShapeToShape2(shape);
-       SHAPELINE*l = shape2->lines;
+       l = shape2->lines;
        while(l) {
            if(l->type == moveTo) {
                FPOINT to;
@@ -1186,7 +1255,7 @@ void swf_DrawText(drawer_t*draw, SWFFONT*font, char*text)
            l = l->next;
        }
        swf_Shape2Free(shape2);
-       advance += font->glyph[g].advance;
+       advance += font->glyph[g].advance/20.0;
     }
 }