added swf_DrawText().
[swftools.git] / lib / modules / swftext.c
index 06dc3ff..433dc81 100644 (file)
@@ -7,9 +7,19 @@
 
    Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
  
-   This file is distributed under the GPL, see file COPYING for details 
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-*/
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #define TF_TEXTCONTROL  0x80
 #define TF_HASFONT      0x08
@@ -378,6 +388,7 @@ int swf_FontExtract(SWF * swf,int id,SWFFONT * * font)
         break;
         
       case ST_DEFINEFONTINFO:
+      case ST_DEFINEFONTINFO2:
         nid = swf_FontExtract_DefineFontInfo(id,f,t);
         break;
         
@@ -654,7 +665,7 @@ void swf_FontFree(SWFFONT * f)
   free(f);
 }
 
-int swf_TextSetInfoRecord(TAG * t,SWFFONT * font,U16 size,RGBA * color,S16 dx,S16 dy)
+int swf_TextSetInfoRecord(TAG * t,SWFFONT * font,U16 size,RGBA * color,int dx,int dy)
 { U8 flags;
   if (!t) return -1;
 
@@ -680,9 +691,11 @@ int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits)
 
   while(s[0])
   { 
-    int glyph = font->ascii2glyph[s[0]];
+    int glyph = -1;
+    if(s[0] < font->maxascii)
+       glyph = font->ascii2glyph[s[0]];
     if(glyph>=0) {
-       g = swf_CountBits(glyph,g);
+       g = swf_CountUBits(glyph,g);
        a = swf_CountBits((((U32)font->glyph[glyph].advance)*scale)/100,a);
     }
     s++;
@@ -695,23 +708,29 @@ int swf_TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits)
 }
 
 int swf_TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 abits)
-{ int l,i;
+{ int l=0,i,pos;
     
   if ((!t)||(!font)||(!s)||(!font->ascii2glyph)) return -1;
 
-  l = strlen(s);
-  if (l>0x7f) l = 0x7f;
-  swf_SetU8(t,l);
+  pos = t->len;
+  swf_SetU8(t, l); //placeholder
 
-  for (i=0;i<l;i++)
+  for (i=0;s[i];i++)
   { 
-    int g = font->ascii2glyph[s[i]];
+    int g = -1;
+    if(s[i] < font->maxascii) 
+       g = font->ascii2glyph[s[i]];
     if(g>=0) {
       swf_SetBits(t,g,gbits);
       swf_SetBits(t,(((U32)font->glyph[g].advance)*scale)/100,abits);
+      l++;
+      if(l==0x7f)
+         break;
     }
   }
 
+  PUT8(&t->data[pos], l);
+
   swf_ResetWriteBits(t);
   return 0;
 }
@@ -722,7 +741,9 @@ U32 swf_TextGetWidth(SWFFONT * font,U8 * s,int scale)
   if (font&&s)
   { while (s[0])
     { 
-      int g = font->ascii2glyph[*s];
+      int g = -1;
+      if(*s < font->maxascii) 
+         g = font->ascii2glyph[*s];
       if(g>=0)
         res += font->glyph[g].advance;
       s++;
@@ -803,7 +824,7 @@ void swf_WriteFont(SWFFONT*font, char* filename)
        int xmax = 0;
        int ymax = textscale * 2 * (font->maxascii/16+1);
        U8 gbits,abits;
-       char text[MAX_CHAR_PER_FONT+1];
+       U8 text[MAX_CHAR_PER_FONT+1];
        int x,y;
        text[MAX_CHAR_PER_FONT]=0;
        for(s=0;s<font->maxascii;s++)
@@ -938,13 +959,15 @@ SRECT swf_SetDefineText(TAG*tag, SWFFONT*font, RGBA*rgb, char*text, int scale)
        while(*c) {
            if(*c < font->maxascii) {
                int g = font->ascii2glyph[*c];
-               SRECT rn = font->layout->bounds[g];
-               rn.xmin = (rn.xmin * scale)/100 + pos;
-               rn.xmax = (rn.xmax * scale)/100 + pos;
-               rn.ymin = (rn.ymin * scale)/100;
-               rn.ymax = (rn.ymax * scale)/100;
-               swf_ExpandRect2(&r, &rn);
-               pos += (font->glyph[g].advance*scale*20)/100;
+               if(g>=0) {
+                   SRECT rn = font->layout->bounds[g];
+                   rn.xmin = (rn.xmin * scale)/100 + pos;
+                   rn.xmax = (rn.xmax * scale)/100 + pos;
+                   rn.ymin = (rn.ymin * scale)/100;
+                   rn.ymax = (rn.ymax * scale)/100;
+                   swf_ExpandRect2(&r, &rn);
+                   pos += (font->glyph[g].advance*scale*20)/100;
+               }
            }
            c++;
        }
@@ -1003,7 +1026,7 @@ void swf_FontCreateLayout(SWFFONT*f)
        if(!shape2) { 
            fprintf(stderr, "Shape parse error\n");exit(1);
        }
-       bbox = swf_GetShapeBoundingBox(shape2->lines);
+       bbox = swf_GetShapeBoundingBox(shape2);
        swf_Shape2Free(shape2);
        f->layout->bounds[t] = bbox;
        /* FIXME */
@@ -1025,4 +1048,86 @@ void swf_FontCreateLayout(SWFFONT*f)
     }
 }
        
+static U32 readUTF8char(char**text)
+{
+    U32 c = 0;
+    if(!(*(*text) & 0x80))
+       return *((*text)++);
+
+    /* 0000 0080-0000 07FF   110xxxxx 10xxxxxx */
+    if(((*text)[0] & 0xe0) == 0xc0 && (*text)[1])  
+    {
+       c = ((*text)[0] & 0x1f) << 6 | ((*text)[1] & 0x3f);
+       (*text) += 2;
+       return c;
+    }
+    /* 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx */
+    if(((*text)[0] & 0xf0) == 0xe0 && (*text)[1] && (*text)[2])
+    {
+       c = ((*text)[0] & 0x0f) << 12 | ((*text)[1] & 0x3f) << 6 | ((*text)[2] & 0x3f);
+       (*text) += 3;
+       return c;
+    }
+    /* 0001 0000-001F FFFF   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+    if(((*text)[0] & 0xf8) == 0xf0 && (*text)[1] && (*text)[2] && (*text)[3] )  
+    {
+       c = ((*text)[0] & 0x07) << 18 | ((*text)[1] & 0x3f) << 12 | ((*text)[2] & 0x3f)<<6 | ((*text)[3] & 0x3f);
+       (*text) += 4;
+       return c;
+    }
+    /* 0020 0000-03FF FFFF   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+    if(((*text)[0] & 0xfc) == 0xf8 && (*text)[1] && (*text)[2] && (*text)[3] && (*text)[4])  
+    {
+       c = ((*text)[0] & 0x03) << 24 | ((*text)[1] & 0x3f) << 18 | ((*text)[2] & 0x3f)<<12 | ((*text)[3] & 0x3f) << 6 | ((*text)[4] & 0x3f);
+       (*text) += 5;
+       return c;
+    }
+    /* 0400 0000-7FFF FFFF   1111110x 10xxxxxx ... 10xxxxxx */
+    if(((*text)[0] & 0xfe) == 0xfc && (*text)[1] && (*text)[2] && (*text)[3] && (*text)[4] && (*text)[5])  
+    {
+       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;
+       (*text) += 6;
+       return c;
+    }
+    return *((*text)++);
+}
+
+void swf_DrawText(SWFSHAPEDRAWER*draw, SWFFONT*font, char*text)
+{
+    char*s = text;
+    int advance = 0;
+    while(*s) {
+       SHAPE*shape;
+       SHAPE2*shape2;
+       U32 c = readUTF8char(&s);
+       int g = font->ascii2glyph[c];
+       shape = font->glyph[g].shape;
+       shape2 = swf_ShapeToShape2(shape);
+       SHAPELINE*l = shape2->lines;
+       while(l) {
+           if(l->type == moveTo) {
+               FPOINT to;
+               to.x = l->x/20.0+advance;
+               to.y = l->y/20.0;
+               swf_DrawerMoveTo(draw, &to);
+           } else if(l->type == lineTo) {
+               FPOINT to;
+               to.x = l->x/20.0+advance;
+               to.y = l->y/20.0;
+               swf_DrawerLineTo(draw, &to);
+           } else if(l->type == splineTo) {
+               FPOINT mid,to;
+               mid.x = l->sx/20.0+advance;
+               mid.y = l->sy/20.0;
+               to.x = l->x/20.0+advance;
+               to.y = l->y/20.0;
+               swf_DrawerSplineTo(draw, &mid, &to);
+           }
+           l = l->next;
+       }
+       swf_Shape2Free(shape2);
+       advance += font->glyph[g].advance;
+    }
+}
+