merged in fontalignzones branch
authorMatthias Kramm <kramm@quiss.org>
Mon, 26 Oct 2009 21:36:18 +0000 (14:36 -0700)
committerMatthias Kramm <kramm@quiss.org>
Mon, 26 Oct 2009 21:36:29 +0000 (14:36 -0700)
14 files changed:
lib/devices/swf.c
lib/example/Makefile
lib/example/alignzones.c [new file with mode: 0644]
lib/example/buttontest.c
lib/example/hexfont.c
lib/modules/swfaction.c
lib/modules/swfdraw.c
lib/modules/swfshape.c
lib/modules/swftext.c
lib/rfxswf.c
lib/rfxswf.h
src/Makefile.in
src/swfdump.c
src/swfextract.c

index 4f691b6..42bb610 100644 (file)
@@ -203,6 +203,8 @@ typedef struct _swfoutput_internal
     char* mark;
 
 } swfoutput_internal;
     char* mark;
 
 } swfoutput_internal;
+
+static const int NO_FONT3=0;
     
 static void swf_fillbitmap(gfxdevice_t*driver, gfxline_t*line, gfximage_t*img, gfxmatrix_t*move, gfxcxform_t*cxform);
 static int  swf_setparameter(gfxdevice_t*driver, const char*key, const char*value);
     
 static void swf_fillbitmap(gfxdevice_t*driver, gfxline_t*line, gfximage_t*img, gfxmatrix_t*move, gfxcxform_t*cxform);
 static int  swf_setparameter(gfxdevice_t*driver, const char*key, const char*value);
@@ -537,7 +539,7 @@ static inline int colorcompare(RGBA*a,RGBA*b)
     return 1;
 }
 
     return 1;
 }
 
-static SRECT getcharacterbbox(chararray_t*chardata, MATRIX* m)
+static SRECT getcharacterbbox(chararray_t*chardata, MATRIX* m, int flashversion)
 {
     SRECT r;
     char debug = 0;
 {
     SRECT r;
     char debug = 0;
@@ -546,17 +548,19 @@ static SRECT getcharacterbbox(chararray_t*chardata, MATRIX* m)
     int t;
     if(debug) printf("\n");
 
     int t;
     if(debug) printf("\n");
 
+    double div = 1.0 / 1024.0;
+    if(flashversion>=8 && !NO_FONT3) {
+       div = 1.0 / 20480.0;
+    }
+
     while(chardata) {
        for(t=0;t<chardata->pos;t++) {
            charatposition_t*chr = &chardata->chr[t];
            SRECT b = chr->font->layout->bounds[chr->charid];
     while(chardata) {
        for(t=0;t<chardata->pos;t++) {
            charatposition_t*chr = &chardata->chr[t];
            SRECT b = chr->font->layout->bounds[chr->charid];
-           b.xmin *= chr->size;
-           b.ymin *= chr->size;
-           b.xmax *= chr->size;
-           b.ymax *= chr->size;
-
-           /* divide by 1024, rounding xmax/ymax up */
-           b.xmax += 1023; b.ymax += 1023; b.xmin /= 1024; b.ymin /= 1024; b.xmax /= 1024; b.ymax /= 1024;
+           b.xmin = floor((b.xmin*(double)chr->size) *div);
+           b.ymin = floor((b.ymin*(double)chr->size) *div);
+           b.xmax = ceil((b.xmax*(double)chr->size)  *div);
+           b.ymax = ceil((b.ymax*(double)chr->size)  *div);
 
            b.xmin += chr->x;
            b.ymin += chr->y;
 
            b.xmin += chr->x;
            b.ymin += chr->y;
@@ -725,7 +729,7 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag)
                            newfont = &font;
 
                        tag->writeBit = 0; // Q&D
                            newfont = &font;
 
                        tag->writeBit = 0; // Q&D
-                       swf_TextSetInfoRecord(tag, newfont, chr->size, newcolor, newx,newy);
+                       swf_TextSetInfoRecord(tag, newfont, chr->size, newcolor, newx, newy);
                    }
 
                    lastfont = chr->font;
                    }
 
                    lastfont = chr->font;
@@ -814,7 +818,7 @@ static void chararray_writetodev(gfxdevice_t*dev, chararray_t*array, MATRIX*matr
     i->tag = swf_InsertTag(i->tag,ST_DEFINETEXT2);
     swf_SetU16(i->tag, textid);
     SRECT r;
     i->tag = swf_InsertTag(i->tag,ST_DEFINETEXT2);
     swf_SetU16(i->tag, textid);
     SRECT r;
-    r = getcharacterbbox(array, matrix);
+    r = getcharacterbbox(array, matrix, i->config_flashversion);
     r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
     swf_SetMatrix(i->tag, matrix);
     r = swf_ClipRect(i->pagebbox, r);
     swf_SetRect(i->tag,&r);
     swf_SetMatrix(i->tag, matrix);
@@ -834,6 +838,8 @@ static void chararray_writetodev(gfxdevice_t*dev, chararray_t*array, MATRIX*matr
 
        swf_SetU32(i->tag, 0);//thickness
        swf_SetU32(i->tag, 0);//sharpness
 
        swf_SetU32(i->tag, 0);//thickness
        swf_SetU32(i->tag, 0);//sharpness
+       //swf_SetU32(i->tag, 0x20000);//thickness
+       //swf_SetU32(i->tag, 0x800000);//sharpness
        swf_SetU8(i->tag, 0);//reserved
     }
     if(invisible && i->config_flashversion>=8) {
        swf_SetU8(i->tag, 0);//reserved
     }
     if(invisible && i->config_flashversion>=8) {
@@ -865,45 +871,6 @@ static void endtext(gfxdevice_t*dev)
     i->textmode = 0;
 }
 
     i->textmode = 0;
 }
 
-/* sets the matrix which is to be applied to characters drawn by swfoutput_drawchar() */
-static void setfontscale(gfxdevice_t*dev,double m11,double m12, double m21,double m22,double x, double y, char force)
-{
-    m11 *= 1024;
-    m12 *= 1024;
-    m21 *= 1024;
-    m22 *= 1024;
-    swfoutput_internal*i = (swfoutput_internal*)dev->internal;
-    if(i->lastfontm11 == m11 &&
-       i->lastfontm12 == m12 &&
-       i->lastfontm21 == m21 &&
-       i->lastfontm22 == m22 && !force)
-        return;
-   if(i->textmode)
-       endtext(dev);
-    
-    i->lastfontm11 = m11;
-    i->lastfontm12 = m12;
-    i->lastfontm21 = m21;
-    i->lastfontm22 = m22;
-
-    double xsize = sqrt(m11*m11 + m12*m12);
-    double ysize = sqrt(m21*m21 + m22*m22);
-    i->current_font_size = (xsize>ysize?xsize:ysize)*1;
-    if(i->current_font_size < 1)
-       i->current_font_size = 1;
-    double ifs = 1.0 / (i->current_font_size*GLYPH_SCALE);
-
-    MATRIX m;
-    m.sx = (S32)((m11*ifs)*65536); m.r1 = (S32)((m21*ifs)*65536);
-    m.r0 = (S32)((m12*ifs)*65536); m.sy = (S32)((m22*ifs)*65536); 
-    /* this is the position of the first char to set a new fontmatrix-
-       we hope that it's close enough to all other characters using the
-       font, so we use its position as origin for the matrix */
-    m.tx = x*20;
-    m.ty = y*20;
-    i->fontmatrix = m;
-}
-
 static int watermark2_width=47;
 static int watermark2_height=11;
 static int watermark2[47] = {95,1989,71,0,2015,337,1678,0,2015,5,1921,320,1938,25,2006,1024,
 static int watermark2_width=47;
 static int watermark2_height=11;
 static int watermark2[47] = {95,1989,71,0,2015,337,1678,0,2015,5,1921,320,1938,25,2006,1024,
@@ -1507,8 +1474,20 @@ void swfoutput_finalize(gfxdevice_t*dev)
            }
            int used = iterator->swffont->use && iterator->swffont->use->used_glyphs;
            if(used) {
            }
            int used = iterator->swffont->use && iterator->swffont->use->used_glyphs;
            if(used) {
-               mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
-               swf_FontSetDefine2(mtag, iterator->swffont);
+               if(i->config_flashversion<8 || NO_FONT3) {
+                   mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
+                   swf_FontSetDefine2(mtag, iterator->swffont);
+               } else {
+                   mtag = swf_InsertTag(mtag, ST_DEFINEFONT3);
+                   swf_FontSetDefine2(mtag, iterator->swffont);
+           
+                   swf_FontCreateAlignZones(iterator->swffont);
+                  
+                   if(iterator->swffont->alignzones) {
+                       mtag = swf_InsertTag(mtag, ST_DEFINEFONTALIGNZONES);
+                       swf_FontSetAlignZones(mtag, iterator->swffont);
+                   }
+               }
            }
        }
 
            }
        }
 
@@ -2180,7 +2159,7 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value)
         printf("linkcolor=<color)           color of links (format: RRGGBBAA)\n");
         printf("linknameurl                Link buttons will be named like the URL they refer to (handy for iterating through links with actionscript)\n");
         printf("storeallcharacters          don't reduce the fonts to used characters in the output file\n");
         printf("linkcolor=<color)           color of links (format: RRGGBBAA)\n");
         printf("linknameurl                Link buttons will be named like the URL they refer to (handy for iterating through links with actionscript)\n");
         printf("storeallcharacters          don't reduce the fonts to used characters in the output file\n");
-        printf("enablezlib                  switch on zlib compression (also done if flashversion>=7)\n");
+        printf("enablezlib                  switch on zlib compression (also done if flashversion>=6)\n");
         printf("bboxvars                    store the bounding box of the SWF file in actionscript variables\n");
         printf("dots                        Take care to handle dots correctly\n");
         printf("reordertags=0/1             (default: 1) perform some tag optimizations\n");
         printf("bboxvars                    store the bounding box of the SWF file in actionscript variables\n");
         printf("dots                        Take care to handle dots correctly\n");
         printf("reordertags=0/1             (default: 1) perform some tag optimizations\n");
@@ -2810,13 +2789,13 @@ static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*grad
     swf_FreeGradient(swfgradient);free(swfgradient);
 }
 
     swf_FreeGradient(swfgradient);free(swfgradient);
 }
 
-static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id)
+static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id, int version)
 {
     SWFFONT*swffont = (SWFFONT*)rfx_calloc(sizeof(SWFFONT));
     int t;
     SRECT bounds = {0,0,0,0};
     swffont->id = -1;
 {
     SWFFONT*swffont = (SWFFONT*)rfx_calloc(sizeof(SWFFONT));
     int t;
     SRECT bounds = {0,0,0,0};
     swffont->id = -1;
-    swffont->version = 2;
+    swffont->version = version;
     swffont->name = (U8*)strdup(id);
     swffont->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT));
     swffont->layout->ascent = 0;
     swffont->name = (U8*)strdup(id);
     swffont->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT));
     swffont->layout->ascent = 0;
@@ -2856,10 +2835,12 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id)
        swf_Shape01DrawerInit(&draw, 0);
        line = font->glyphs[t].line;
 
        swf_Shape01DrawerInit(&draw, 0);
        line = font->glyphs[t].line;
 
+       const double scale = GLYPH_SCALE;
        while(line) {
            FPOINT c,to;
        while(line) {
            FPOINT c,to;
-           c.x = line->sx * GLYPH_SCALE; c.y = line->sy * GLYPH_SCALE;
-           to.x = line->x * GLYPH_SCALE; to.y = line->y * GLYPH_SCALE;
+           c.x = line->sx * scale; c.y = -line->sy * scale;
+           //to.x = floor(line->x * scale); to.y = floor(-line->y * scale);
+           to.x = line->x * scale; to.y = -line->y * scale;
            if(line->type == gfx_moveTo) {
                draw.moveTo(&draw, &to);
            } else if(line->type == gfx_lineTo) {
            if(line->type == gfx_moveTo) {
                draw.moveTo(&draw, &to);
            } else if(line->type == gfx_lineTo) {
@@ -2915,12 +2896,8 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id)
        The baseline is defined as the y-position zero 
      */
 
        The baseline is defined as the y-position zero 
      */
 
-    swffont->layout->ascent = -bounds.ymin;
-    if(swffont->layout->ascent < 0)
-        swffont->layout->ascent = 0;
-    swffont->layout->descent = bounds.ymax;
-    if(swffont->layout->descent < 0)
-        swffont->layout->descent = 0;
+    swffont->layout->ascent = bounds.ymin<0?-bounds.ymin:0;
+    swffont->layout->descent = bounds.ymax>0?bounds.ymax:0;
     swffont->layout->leading = bounds.ymax - bounds.ymin;
 
     /* if the font has proper ascent/descent values (>0) and those define
     swffont->layout->leading = bounds.ymax - bounds.ymin;
 
     /* if the font has proper ascent/descent values (>0) and those define
@@ -2950,7 +2927,7 @@ static void swf_addfont(gfxdevice_t*dev, gfxfont_t*font)
        l = l->next;
     }
     l = (fontlist_t*)rfx_calloc(sizeof(fontlist_t));
        l = l->next;
     }
     l = (fontlist_t*)rfx_calloc(sizeof(fontlist_t));
-    l->swffont = gfxfont_to_swffont(font, font->id);
+    l->swffont = gfxfont_to_swffont(font, font->id, (i->config_flashversion>=8 && !NO_FONT3)?3:2);
     l->next = 0;
     if(last) {
        last->next = l;
     l->next = 0;
     if(last) {
        last->next = l;
@@ -3005,6 +2982,56 @@ static void swf_switchfont(gfxdevice_t*dev, const char*fontid)
     return;
 }
 
     return;
 }
 
+/* sets the matrix which is to be applied to characters drawn by swfoutput_drawchar() */
+static void setfontscale(gfxdevice_t*dev,double m11,double m12, double m21,double m22,double x, double y, char force)
+{
+    m11 *= 1024;
+    m12 *= 1024;
+    m21 *= 1024;
+    m22 *= 1024;
+    swfoutput_internal*i = (swfoutput_internal*)dev->internal;
+    if(i->lastfontm11 == m11 &&
+       i->lastfontm12 == m12 &&
+       i->lastfontm21 == m21 &&
+       i->lastfontm22 == m22 && !force)
+        return;
+   if(i->textmode)
+       endtext(dev);
+    
+    i->lastfontm11 = m11;
+    i->lastfontm12 = m12;
+    i->lastfontm21 = m21;
+    i->lastfontm22 = m22;
+
+    double xsize = sqrt(m11*m11 + m12*m12);
+    double ysize = sqrt(m21*m21 + m22*m22);
+
+    int extrazoom = 1;
+    if(i->config_flashversion>=8 && !NO_FONT3)
+       extrazoom = 20;
+
+    i->current_font_size = (xsize>ysize?xsize:ysize)*extrazoom;
+    if(i->current_font_size < 1)
+       i->current_font_size = 1;
+
+    MATRIX m;
+    swf_GetMatrix(0, &m);
+
+    if(m21 || m12 || fabs(m11+m22)>0.001) {
+       double ifs = (double)extrazoom/(i->current_font_size);
+       m.sx =  (S32)((m11*ifs)*65536); m.r1 = -(S32)((m21*ifs)*65536);
+       m.r0 =  (S32)((m12*ifs)*65536); m.sy = -(S32)((m22*ifs)*65536); 
+    }
+
+    /* this is the position of the first char to set a new fontmatrix-
+       we hope that it's close enough to all other characters using the
+       font, so we use its position as origin for the matrix */
+    m.tx = x*20;
+    m.ty = y*20;
+    i->fontmatrix = m;
+}
+
+
 static void swf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
 {
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
 static void swf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
 {
     swfoutput_internal*i = (swfoutput_internal*)dev->internal;
index 4f73cb0..f96acca 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile
 
 RFXSWF = ../librfxswf.a ../libbase.a 
 # Makefile
 
 RFXSWF = ../librfxswf.a ../libbase.a 
-LDLIBS = -L/usr/X11R6/lib -ljpeg -lm -lz -lX11 -lfreetype -lt1
+LDLIBS = -L/opt/local/lib/ -L/usr/X11R6/lib -ljpeg -lm -lz -lX11 -lfreetype -lt1
 #CFLAGS        = -funsigned-char
 CC     = gcc
 CXX    = g++
 #CFLAGS        = -funsigned-char
 CC     = gcc
 CXX    = g++
@@ -14,7 +14,7 @@ DBFLAGS       = -g2
 %.swf: %
                ./$<
 
 %.swf: %
                ./$<
 
-all: sound jpegtest box shape1 transtest zlibtest sprites buttontest dumpfont text glyphshape edittext protect hexfont
+all: alignzones.swf
 
 movies: sound.swf jpegtest.swf box.swf shape1.swf transtest.swf zlibtest.swf sprites.swf buttontest.swf dumpfont.swf text.swf glyphshape.swf edittext.swf
        
 
 movies: sound.swf jpegtest.swf box.swf shape1.swf transtest.swf zlibtest.swf sprites.swf buttontest.swf dumpfont.swf text.swf glyphshape.swf edittext.swf
        
@@ -51,6 +51,9 @@ transtest: $(RFXSWF) transtest.o $(RFXSWF)
 hexfont: $(RFXSWF) hexfont.o $(RFXSWF)
                $(CC) -o hexfont hexfont.o $(RFXSWF) $(LDLIBS) $(DBFLAGS)
 
 hexfont: $(RFXSWF) hexfont.o $(RFXSWF)
                $(CC) -o hexfont hexfont.o $(RFXSWF) $(LDLIBS) $(DBFLAGS)
 
+alignzones: $(RFXSWF) alignzones.o $(RFXSWF)
+               $(CC) -o alignzones alignzones.o $(RFXSWF) $(LDLIBS) $(DBFLAGS)
+
 text.o: demofont.c
 text: $(RFXSWF) text.o $(RFXSWF)
                $(CC) -o text text.o $(RFXSWF) $(LDLIBS) $(DBFLAGS)
 text.o: demofont.c
 text: $(RFXSWF) text.o $(RFXSWF)
                $(CC) -o text text.o $(RFXSWF) $(LDLIBS) $(DBFLAGS)
diff --git a/lib/example/alignzones.c b/lib/example/alignzones.c
new file mode 100644 (file)
index 0000000..57ce262
--- /dev/null
@@ -0,0 +1,245 @@
+/* hexfont.c
+
+   Example for how to construct an SWF font from another SWF font.
+   
+   Part of the swftools package.
+
+   Copyright (c) 2004 Matthias Kramm <kramm@quiss.org>
+   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 */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <math.h>
+#include "../rfxswf.h"
+
+static void write_font(SWFFONT * font, char *filename)
+{
+    SWF swf;
+    TAG *t;
+    SRECT r;
+    RGBA rgb;
+    int f;
+    int useDefineFont2 = 1;
+    int storeGlyphNames = 1;
+   
+#define WRITEFONTID 8888
+    font->id = WRITEFONTID;
+
+    memset(&swf, 0x00, sizeof(SWF));
+
+    swf.fileVersion = 9;
+    swf.frameRate = 0x4000;
+
+    t = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR);
+    swf.firstTag = t;
+    rgb.r = 0xef;
+    rgb.g = 0xef;
+    rgb.b = 0xff;
+    swf_SetRGB(t, &rgb);
+    
+    t = swf_InsertTag(t, ST_DEFINEFONT3);
+    swf_FontSetDefine2(t, font);
+
+    t = swf_InsertTag(t, ST_DEFINEFONTALIGNZONES);
+    swf_SetU16(t, font->id);
+    swf_SetU8(t, 0); //thin
+    int i;
+    for(i=0;i<256;i++) {
+       swf_SetU8(t, 2);
+       swf_SetF16(t, 82.0 / 1024.0);
+       swf_SetF16(t, 82.0 / 1024.0);
+       swf_SetF16(t, ((i%16/2)*82.0) / 1024.0);
+       swf_SetF16(t, ((i/16/2)*82.0) / 1024.0);
+       /*
+       if(i<128 && (i&15)<8) {
+           swf_SetF16(t, 0.0);
+           swf_SetF16(t, 0.0);
+           swf_SetF16(t, 640.0 / 1024.0);
+           swf_SetF16(t, 640.0 / 1024.0);
+       } else if(i<128 && (i&15)>=8) {
+           swf_SetF16(t, 0.0 / 1024.0);
+           swf_SetF16(t, 0.0   / 1024.0);
+           swf_SetF16(t, 330.0 / 1024.0);
+           swf_SetF16(t, 640.0 / 1024.0);
+       } else if(i>=128 && (i&15)<8) {
+           swf_SetF16(t, 0.0   / 1024.0);
+           swf_SetF16(t, 0.0 / 1024.0);
+           swf_SetF16(t, 640.0 / 1024.0);
+           swf_SetF16(t, 330.0 / 1024.0);
+       } else {
+           swf_SetF16(t, 0.0 / 1024.0);
+           swf_SetF16(t, 0.0 / 1024.0);
+           swf_SetF16(t, 330.0 / 1024.0);
+           swf_SetF16(t, 330.0 / 1024.0);
+       }*/
+       swf_SetU8(t, 3); // x and y
+    }
+
+    int s;
+    int xmax = 0;
+    int ymax = 0;
+    int ypos = 1;
+    U8 gbits, abits;
+    int x, y, c;
+    int range = font->maxascii;
+
+    c = 0;
+    range = 256;
+
+    xmax = 1280;
+    ymax = 1280*20;
+
+    swf.movieSize.xmax = xmax * 20;
+    swf.movieSize.ymax = ymax;
+
+    t = swf_InsertTag(t, ST_DEFINETEXT);
+    swf_SetU16(t, font->id + 1);       // ID
+    r.xmin = 0;
+    r.ymin = 0;
+    r.xmax = swf.movieSize.xmax;
+    r.ymax = swf.movieSize.ymax;
+    swf_SetRect(t, &r);
+    swf_SetMatrix(t, NULL);
+    abits = swf_CountBits(xmax * 16, 0);
+    gbits = 8;
+    swf_SetU8(t, gbits);
+    swf_SetU8(t, abits);
+
+    rgb.r = 0x00;
+    rgb.g = 0x00;
+    rgb.b = 0x00;
+    ypos = 2;
+    
+    int textscale = 1024;
+    for (y = 0; y < ((range + 15) / 16); y++) {
+       for (x = 0; x < 16; x++) {
+           //swf_TextSetInfoRecord(t, font, textscale, &rgb, x*64*20+64*20+10+(x+y)*20, y*64*20+128*20+10+(x^y)*20);
+           swf_TextSetInfoRecord(t, font, textscale, &rgb, x*64*20+64*20+10, y*64*20+128*20+10);
+           int g = y * 16 + x;
+           swf_SetU8(t, 1);
+           swf_SetBits(t, g, gbits);
+           swf_SetBits(t, 0, abits);
+           swf_ResetWriteBits(t);
+       }
+    }
+    swf_SetU8(t, 0);
+                
+    t = swf_InsertTag(t, ST_CSMTEXTSETTINGS);
+    swf_SetU16(t, font->id + 1);
+    swf_SetU8(t, (1<<3)//grid
+                |0x40//flashtype
+                );
+    swf_SetU32(t, 0x20000);//thickness
+    swf_SetU32(t, 0x800000);//sharpness
+    swf_SetU8(t, 0);//reserved
+
+    t = swf_InsertTag(t, ST_PLACEOBJECT2);
+    swf_ObjectPlace(t, font->id + 1, 1, NULL, NULL, NULL);
+
+    t = swf_InsertTag(t, ST_SHOWFRAME);
+    t = swf_InsertTag(t, ST_END);
+
+    f = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644);
+    if FAILED
+       (swf_WriteSWF(f, &swf)) fprintf(stderr, "WriteSWF() failed in writeFont().\n");
+    close(f);
+
+    swf_FreeTags(&swf);
+}
+
+
+int main()
+{
+    SWFFONT hexfont;
+
+    memset(&hexfont, 0, sizeof(hexfont));
+    hexfont.name = (U8*)"HexFont";
+    hexfont.layout = malloc(sizeof(SWFLAYOUT));
+    hexfont.numchars = 256;
+    hexfont.maxascii = 256;
+    hexfont.encoding = 32;
+    hexfont.glyph2ascii = malloc(sizeof(U16)*256);
+    hexfont.ascii2glyph = malloc(sizeof(int)*256);
+    hexfont.glyph = malloc(sizeof(SWFGLYPH)*256);
+    hexfont.glyphnames = malloc(sizeof(char*)*256);
+    hexfont.layout->bounds = malloc(sizeof(SRECT)*256);
+    hexfont.layout->kerningcount = 0;
+    hexfont.layout->kerning = 0;
+    int t;
+    int ymax =-0x7fffffff;
+    int ymin = 0x7fffffff;
+    for(t=0;t<256;t++) 
+    {
+       drawer_t _draw,*draw=&_draw;
+       swf_Shape01DrawerInit(draw, 0);
+       int x,y;
+       FPOINT d;
+       int rx = 0;//t&15;
+       int ry = 0;//(t&15)^0x05;
+#define S {d.x*=20*4+2;d.y*=20*4+2;}
+       if(1) {
+           for(x=0;x<8;x++) 
+           for(y=0;y<8;y++) {
+               if((x^y)&1) {
+                   d.x=x;d.y=-y;     S;draw->moveTo(draw, &d);
+                   d.x=x+1;d.y=-y;   S;draw->lineTo(draw, &d);
+                   d.x=x+1;d.y=-y-1; S;draw->lineTo(draw, &d);
+                   d.x=x;d.y=-y-1;   S;draw->lineTo(draw, &d);
+                   d.x=x;d.y=-y;     S;draw->lineTo(draw, &d);
+               }
+           }
+       } else {
+           d.x=0;d.y=-0;   S;draw->moveTo(draw, &d);
+           d.x=0;d.y=-8;   S;draw->lineTo(draw, &d);
+           d.x=8;d.y=-8;   S;draw->lineTo(draw, &d);
+           d.x=8;d.y=-0;   S;draw->lineTo(draw, &d);
+           d.x=0;d.y=-0;   S;draw->lineTo(draw, &d);
+
+           d.x=1;d.y=-1;   S;draw->moveTo(draw, &d);
+           d.x=7;d.y=-1;   S;draw->lineTo(draw, &d);
+           d.x=7;d.y=-7;   S;draw->lineTo(draw, &d);
+           d.x=1;d.y=-7;   S;draw->lineTo(draw, &d);
+           d.x=1;d.y=-1;   S;draw->lineTo(draw, &d);
+       }
+       draw->finish(draw);
+       hexfont.glyph[t].shape = swf_ShapeDrawerToShape(draw);
+       hexfont.layout->bounds[t] = swf_ShapeDrawerGetBBox(draw);
+       hexfont.glyph[t].advance = hexfont.layout->bounds[t].xmax + hexfont.layout->bounds[t].xmin;
+       draw->dealloc(draw);
+
+       hexfont.glyph2ascii[t] = t;
+       hexfont.ascii2glyph[t] = t;
+       hexfont.glyphnames[t] = 0;
+       if(hexfont.layout->bounds[t].ymax > ymax)
+           ymax = hexfont.layout->bounds[t].ymax;
+       if(hexfont.layout->bounds[t].ymin < ymin)
+           ymin = hexfont.layout->bounds[t].ymin;
+
+       if(t>=0xe4) {
+           /* breaks flashtype, but not (non-flashtype) definefont2 */
+           //hexfont.glyph2ascii[t] = 0;
+       }
+    }
+    hexfont.layout->ascent = ymin<0?-ymin:0;
+    hexfont.layout->descent = ymax>0?ymax:0;
+    hexfont.layout->leading = hexfont.layout->ascent + hexfont.layout->descent;
+
+    write_font(&hexfont, "alignzones.swf");
+    return 0;
+}
+
index 76ba207..1823817 100644 (file)
@@ -30,7 +30,7 @@ TAG* t;
 
 #define ID_BUTTON 31
 
 
 #define ID_BUTTON 31
 
-int useDefineButton2 = 0; // set this to 1 to use DefineButton2 Tags
+int useDefineButton2 = 1; // set this to 1 to use DefineButton2 Tags
                           // instead of DefineButton1
                
 int main (int argc,char ** argv)
                           // instead of DefineButton1
                
 int main (int argc,char ** argv)
@@ -46,7 +46,7 @@ int main (int argc,char ** argv)
 
   memset(&swf,0x00,sizeof(SWF));        // set global movie parameters
 
 
   memset(&swf,0x00,sizeof(SWF));        // set global movie parameters
 
-  swf.fileVersion    = 4;               // make flash 4 compatible swf
+  swf.fileVersion    = 8;               // make flash 4 compatible swf
   swf.frameRate      = 0x1900;          // about 0x19 frames per second
   
   swf.movieSize.xmax = 20*width;        // flash units: 1 pixel = 20 units
   swf.frameRate      = 0x1900;          // about 0x19 frames per second
   
   swf.movieSize.xmax = 20*width;        // flash units: 1 pixel = 20 units
@@ -116,8 +116,8 @@ int main (int argc,char ** argv)
       swf_ButtonSetRecord(t,BS_DOWN,36,1,NULL,NULL);
       swf_SetU8(t,0); // end of button records
 
       swf_ButtonSetRecord(t,BS_DOWN,36,1,NULL,NULL);
       swf_SetU8(t,0); // end of button records
 
-      swf_ButtonSetCondition(t, BC_OVERDOWN_OVERUP);
-       swf_ActionSet(t,actiontoset);
+      swf_ButtonSetCondition(t, BC_IDLE_OVERUP);
+      swf_ActionSet(t,actiontoset);
        
       swf_ButtonPostProcess(t, 1); // don't forget!
   }
        
       swf_ButtonPostProcess(t, 1); // don't forget!
   }
index bf5695b..1712112 100644 (file)
 int main()
 {
     char* hex = "0123456789ABCDEF";
 int main()
 {
     char* hex = "0123456789ABCDEF";
-    SWFFONT* font = swf_LoadFont("Courier.swf");
+    SWFFONT* font = swf_LoadFont("../../doc/Courier.swf");
     SWFFONT hexfont;
 
     memset(&hexfont, 0, sizeof(hexfont));
     SWFFONT hexfont;
 
     memset(&hexfont, 0, sizeof(hexfont));
-    hexfont.name = "HexFont";
+    hexfont.name = (char*)"HexFont";
     hexfont.layout = malloc(sizeof(SWFLAYOUT));
     hexfont.numchars = 256;
     hexfont.maxascii = 256;
     hexfont.layout = malloc(sizeof(SWFLAYOUT));
     hexfont.numchars = 256;
     hexfont.maxascii = 256;
index e16b3a4..fb7474d 100644 (file)
@@ -182,7 +182,6 @@ ActionTAG* swf_ActionGet(TAG*tag)
 void swf_ActionFree(ActionTAG*action)
 {
     if(!action) {
 void swf_ActionFree(ActionTAG*action)
 {
     if(!action) {
-       fprintf(stderr, "Warning: freeing zero action");
        return;
     }
     action = action->parent;
        return;
     }
     action = action->parent;
@@ -208,9 +207,10 @@ void swf_ActionFree(ActionTAG*action)
 
 void swf_ActionSet(TAG*tag, ActionTAG*action)
 {
 
 void swf_ActionSet(TAG*tag, ActionTAG*action)
 {
-    if(action) {
-       action=action->parent;
+    if(!action) {
+       return;
     }
     }
+    action=action->parent;
     while(action)
     {
        swf_SetU8(tag, action->op);
     while(action)
     {
        swf_SetU8(tag, action->op);
index 333fdb9..ae04aee 100644 (file)
@@ -97,8 +97,8 @@ static void fixEndPoint(drawer_t*draw)
 static void swf_ShapeDrawerMoveTo(drawer_t*draw, FPOINT * to)
 {
     SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
 static void swf_ShapeDrawerMoveTo(drawer_t*draw, FPOINT * to)
 {
     SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
-    int x = to->x*20+0.001;
-    int y = to->y*20+0.001;
+    int x = floor(to->x*20);
+    int y = floor(to->y*20);
 
     /* we need to write moveto always- it
        might be that it signals the end of a polygon, otherwise
 
     /* we need to write moveto always- it
        might be that it signals the end of a polygon, otherwise
@@ -119,8 +119,8 @@ static void swf_ShapeDrawerMoveTo(drawer_t*draw, FPOINT * to)
 static void swf_ShapeDrawerLineTo(drawer_t*draw, FPOINT * to)
 {
     SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
 static void swf_ShapeDrawerLineTo(drawer_t*draw, FPOINT * to)
 {
     SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
-    int x = to->x*20+0.001;
-    int y = to->y*20+0.001;
+    int x = floor(to->x*20);
+    int y = floor(to->y*20);
     if(sdraw->lastx < sdraw->bbox.xmin) sdraw->bbox.xmin = sdraw->lastx;
     if(sdraw->lasty < sdraw->bbox.ymin) sdraw->bbox.ymin = sdraw->lasty;
     if(sdraw->lastx > sdraw->bbox.xmax) sdraw->bbox.xmax = sdraw->lastx;
     if(sdraw->lastx < sdraw->bbox.xmin) sdraw->bbox.xmin = sdraw->lastx;
     if(sdraw->lasty < sdraw->bbox.ymin) sdraw->bbox.ymin = sdraw->lasty;
     if(sdraw->lastx > sdraw->bbox.xmax) sdraw->bbox.xmax = sdraw->lastx;
@@ -137,10 +137,10 @@ static void swf_ShapeDrawerLineTo(drawer_t*draw, FPOINT * to)
 static void swf_ShapeDrawerSplineTo(drawer_t*draw, FPOINT * c1, FPOINT*  to)
 {
     SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
 static void swf_ShapeDrawerSplineTo(drawer_t*draw, FPOINT * c1, FPOINT*  to)
 {
     SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
-    int tx = c1->x*20+0.001;
-    int ty = c1->y*20+0.001;
-    int x = to->x*20+0.001;
-    int y = to->y*20+0.001;
+    int tx = floor(c1->x*20);
+    int ty = floor(c1->y*20);
+    int x = floor(to->x*20);
+    int y = floor(to->y*20);
     if(sdraw->lastx < sdraw->bbox.xmin) sdraw->bbox.xmin = sdraw->lastx;
     if(sdraw->lasty < sdraw->bbox.ymin) sdraw->bbox.ymin = sdraw->lasty;
     if(sdraw->lastx > sdraw->bbox.xmax) sdraw->bbox.xmax = sdraw->lastx;
     if(sdraw->lastx < sdraw->bbox.xmin) sdraw->bbox.xmin = sdraw->lastx;
     if(sdraw->lasty < sdraw->bbox.ymin) sdraw->bbox.ymin = sdraw->lasty;
     if(sdraw->lastx > sdraw->bbox.xmax) sdraw->bbox.xmax = sdraw->lastx;
index deb9b3a..afa069c 100644 (file)
@@ -888,6 +888,59 @@ void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height)
     swf_ShapeFree(shape);
 }
 
     swf_ShapeFree(shape);
 }
 
+void swf_ShapeSetRectangle(TAG*tag, U16 shapeid, int width, int height, RGBA*rgba)
+{
+    RGBA white={255,255,255,255};
+    if(!rgba) {
+       rgba = &white;
+    }
+    SHAPE* s;
+    swf_ShapeNew(&s);
+    int fs = swf_ShapeAddSolidFillStyle(s, rgba);
+    swf_SetU16(tag,shapeid);
+    SRECT r;
+    r.xmin = 0;
+    r.xmax = 0;
+    r.ymin = width;
+    r.ymax = height;
+    swf_SetRect(tag,&r);
+    swf_SetShapeHeader(tag,s);
+    swf_ShapeSetAll(tag,s,0,0,0,fs,0);
+    swf_ShapeSetLine(tag,s,width,0);
+    swf_ShapeSetLine(tag,s,0,height);
+    swf_ShapeSetLine(tag,s,-width,0);
+    swf_ShapeSetLine(tag,s,0,-height);
+    swf_ShapeSetEnd(tag);
+    swf_ShapeFree(s);
+}
+
+void swf_ShapeSetRectangleWithBorder(TAG*tag, U16 shapeid, int width, int height, RGBA*rgba, int linewidth, RGBA*linecolor)
+{
+    RGBA white={255,255,255,255};
+    if(!rgba) {
+       rgba = &white;
+    }
+    SHAPE* s;
+    swf_ShapeNew(&s);
+    int fs = swf_ShapeAddSolidFillStyle(s, rgba);
+    int ls = swf_ShapeAddLineStyle(s, linewidth, linecolor);
+    swf_SetU16(tag,shapeid);
+    SRECT r;
+    r.xmin = 0;
+    r.xmax = 0;
+    r.ymin = width;
+    r.ymax = height;
+    swf_SetRect(tag,&r);
+    swf_SetShapeHeader(tag,s);
+    swf_ShapeSetAll(tag,s,0,0,ls,fs,0);
+    swf_ShapeSetLine(tag,s,width,0);
+    swf_ShapeSetLine(tag,s,0,height);
+    swf_ShapeSetLine(tag,s,-width,0);
+    swf_ShapeSetLine(tag,s,0,-height);
+    swf_ShapeSetEnd(tag);
+    swf_ShapeFree(s);
+}
+
 void swf_Shape2ToShape(SHAPE2*shape2, SHAPE*shape)
 {
     TAG*tag = swf_InsertTag(0,0);
 void swf_Shape2ToShape(SHAPE2*shape2, SHAPE*shape)
 {
     TAG*tag = swf_InsertTag(0,0);
index 6bd59f0..912e8fa 100644 (file)
@@ -113,7 +113,7 @@ int swf_FontEnumerate(SWF * swf, void (*FontCallback) (void*, U16, U8 *), void*s
     n = 0;
 
     while (t) {
     n = 0;
 
     while (t) {
-       if (swf_GetTagID(t) == ST_DEFINEFONT2 || swf_GetTagID(t) == ST_DEFINEFONT) {
+       if (swf_isFontTag(t)) {
            n++;
            if (FontCallback) {
                U16 id;
            n++;
            if (FontCallback) {
                U16 id;
@@ -373,6 +373,76 @@ int swf_FontExtract_DefineFont2(int id, SWFFONT * font, TAG * tag)
     return font->id;
 }
 
     return font->id;
 }
 
+static float F16toFloat(U16 x)
+{
+    TAG t;
+    t.data = (void*)&x;
+    t.readBit = 0;
+    t.pos = 0;
+    t.len = 2;
+    return swf_GetF16(&t);
+}
+
+static float floatToF16(float f)
+{
+    U16 u = 0;
+    TAG t;
+    t.data = (void*)&u;
+    t.len = 0;
+    t.memsize = 2;
+    t.writeBit = 0;
+    swf_SetF16(&t, f);
+    return u;
+}
+
+int swf_FontExtract_DefineFontAlignZones(int id, SWFFONT * font, TAG * tag)
+{
+    U16 fid;
+    swf_SetTagPos(tag, 0);
+    fid = swf_GetU16(tag);
+    
+    if (fid == id) {
+       font->alignzone_flags = swf_GetU8(tag);
+       font->alignzones = rfx_calloc(sizeof(ALIGNZONE)*font->numchars);
+       int i=0;
+       while(tag->pos < tag->len) {
+           if(i>=font->numchars)
+               break;
+           int nr = swf_GetU8(tag); // should be 2
+           if(nr!=1 && nr!=2) {
+               fprintf(stderr, "rfxswf: Can't parse alignzone tags with %d zones", nr);
+               break;
+           }
+           U16 x = swf_GetU16(tag);
+           U16 y = swf_GetU16(tag);
+           U16 dx = (nr==2)?swf_GetU16(tag):0xffff;
+           U16 dy = (nr==2)?swf_GetU16(tag):0xffff;
+           U8 xy = swf_GetU8(tag);
+
+#ifdef DEBUG_RFXSWF
+           if((!(xy&1) && (x!=0 || (dx!=0 && dx!=0xffff))) ||
+              (!(xy&2) && (y!=0 || (dy!=0 && dy!=0xffff)))) {
+               fprintf(stderr, "Warning: weird combination of alignzone bits and values (%d x:%04x-%04x y:%04x-%04x)\n", xy,
+                       x,dx,y,dy);
+           }
+#endif
+           if(!(xy&1)) {
+               x = 0xffff;
+               dx = 0xffff;
+           } else if(!(xy&2)) {
+               y = 0xffff;
+               dy = 0xffff;
+           }
+           font->alignzones[i].x = x;
+           font->alignzones[i].y = y;
+           font->alignzones[i].dx = dx;
+           font->alignzones[i].dy = dy;
+           i++;
+       }
+    }
+    return id;
+}
+
 
 #define FEDTJ_PRINT  0x01
 #define FEDTJ_MODIFY 0x02
 
 #define FEDTJ_PRINT  0x01
 #define FEDTJ_MODIFY 0x02
@@ -502,6 +572,10 @@ int swf_FontExtract(SWF * swf, int id, SWFFONT * *font)
            nid = swf_FontExtract_DefineFont2(id, f, t);
            break;
 
            nid = swf_FontExtract_DefineFont2(id, f, t);
            break;
 
+       case ST_DEFINEFONTALIGNZONES:
+           nid = swf_FontExtract_DefineFontAlignZones(id, f, t);
+           break;
+
        case ST_DEFINEFONTINFO:
        case ST_DEFINEFONTINFO2:
            nid = swf_FontExtract_DefineFontInfo(id, f, t);
        case ST_DEFINEFONTINFO:
        case ST_DEFINEFONTINFO2:
            nid = swf_FontExtract_DefineFontInfo(id, f, t);
@@ -1029,6 +1103,27 @@ int swf_FontSetDefine2(TAG * tag, SWFFONT * f)
     return 0;
 }
 
     return 0;
 }
 
+void swf_FontSetAlignZones(TAG*t, SWFFONT *f)
+{
+    swf_SetU16(t, f->id);
+    swf_SetU8(t, f->alignzone_flags);
+    int i;
+    for(i=0;i<f->numchars;i++) {
+       ALIGNZONE*a = &f->alignzones[i];
+       U8 flags = 0;
+       if((a->x & a->dx)!=0xffff)
+           flags |= 1;
+       if((a->y & a->dy)!=0xffff)
+           flags |= 2;
+       swf_SetU8(t, 2);
+       if(flags&1) swf_SetU16(t, a->x); else swf_SetU16(t, 0);
+       if(flags&2) swf_SetU16(t, a->y); else swf_SetU16(t, 0);
+       if((flags&1) && a->dx!=0xffff) swf_SetU16(t, a->dx); else swf_SetU16(t, 0);
+       if((flags&2) && a->dy!=0xffff) swf_SetU16(t, a->dy); else swf_SetU16(t, 0);
+       swf_SetU8(t, flags);
+    }
+}
+
 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading)
 {
     f->layout = (SWFLAYOUT *) rfx_alloc(sizeof(SWFLAYOUT));
 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading)
 {
     f->layout = (SWFLAYOUT *) rfx_alloc(sizeof(SWFLAYOUT));
@@ -1348,183 +1443,6 @@ SWFFONT *swf_ReadFont(const char *filename)
     }
 }
 
     }
 }
 
-void swf_WriteFont(SWFFONT * font, char *filename)
-{
-    SWF swf;
-    TAG *t;
-    SRECT r;
-    RGBA rgb;
-    int f;
-    int useDefineFont2 = 0;
-    int storeGlyphNames = 1;
-
-    if (font->layout)
-       useDefineFont2 = 1;     /* the only thing new in definefont2
-                                  is layout information. */
-
-    font->id = WRITEFONTID;    //"FN"
-
-    memset(&swf, 0x00, sizeof(SWF));
-
-    swf.fileVersion = 9;
-    swf.frameRate = 0x4000;
-
-    /* if we use DefineFont1 to store the characters,
-       we have to build a textfield to store the
-       advance values. While at it, we can also
-       make the whole .swf viewable */
-
-    /* we now always create viewable swfs, even if we
-       did use definefont2 -mk */
-    t = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR);
-    swf.firstTag = t;
-    rgb.r = 0xef;
-    rgb.g = 0xef;
-    rgb.b = 0xff;
-    swf_SetRGB(t, &rgb);
-    if (!useDefineFont2) {
-       t = swf_InsertTag(t, ST_DEFINEFONT);
-       swf_FontSetDefine(t, font);
-       t = swf_InsertTag(t, ST_DEFINEFONTINFO);
-       swf_FontSetInfo(t, font);
-    } else {
-       t = swf_InsertTag(t, ST_DEFINEFONT2);
-       swf_FontSetDefine2(t, font);
-    }
-    if(font->name) {
-       t = swf_InsertTag(t, ST_NAMECHARACTER);
-        swf_SetU16(t, WRITEFONTID);
-        swf_SetString(t, (char*)font->name);
-       t = swf_InsertTag(t, ST_EXPORTASSETS);
-        swf_SetU16(t, 1);
-        swf_SetU16(t, WRITEFONTID);
-        swf_SetString(t, (char*)font->name);
-
-        t = swf_AddAS3FontDefine(t, WRITEFONTID, (char*)font->name);
-    }
-
-    if (storeGlyphNames && font->glyphnames) {
-       int c;
-       t = swf_InsertTag(t, ST_GLYPHNAMES);
-       swf_SetU16(t, WRITEFONTID);
-       swf_SetU16(t, font->numchars);
-       for (c = 0; c < font->numchars; c++) {
-           if (font->glyphnames[c])
-               swf_SetString(t, font->glyphnames[c]);
-           else
-               swf_SetString(t, "");
-       }
-    }
-
-    if (1)                     //neccessary only for df1, but pretty to look at anyhow, so do it always
-    {
-       int textscale = 400;
-       int s;
-       int xmax = 0;
-       int ymax = 0;
-       int ypos = 1;
-       U8 gbits, abits;
-       int x, y, c;
-       int range = font->maxascii;
-
-       c = 0;
-       if (useDefineFont2 && range > 256) {
-           range = 256;
-       }
-
-       for (s = 0; s < range; s++) {
-           int g = font->ascii2glyph[s];
-           if (g >= 0) {
-               if ((font->glyph[g].advance * textscale / 20) / 64 > xmax) {
-                   xmax = (font->glyph[g].advance * textscale / 20) / 64;
-               }
-               c++;
-           }
-           if ((s & 15) == 0) {
-               if (c) {
-                   ypos++;
-               }
-               c = 0;
-           }
-       }
-       ymax = ypos * textscale * 2;
-
-       swf.movieSize.xmax = xmax * 20;
-       swf.movieSize.ymax = ymax;
-
-       t = swf_InsertTag(t, ST_DEFINETEXT);
-
-       swf_SetU16(t, font->id + 1);    // ID
-
-       r.xmin = 0;
-       r.ymin = 0;
-       r.xmax = swf.movieSize.xmax;
-       r.ymax = swf.movieSize.ymax;
-
-       swf_SetRect(t, &r);
-
-       swf_SetMatrix(t, NULL);
-
-       abits = swf_CountBits(xmax * 16, 0);
-       gbits = 8;
-
-       swf_SetU8(t, gbits);
-       swf_SetU8(t, abits);
-
-       rgb.r = 0x00;
-       rgb.g = 0x00;
-       rgb.b = 0x00;
-       ypos = 1;
-       for (y = 0; y < ((range + 15) / 16); y++) {
-           int c = 0, lastx = -1;
-           for (x = 0; x < 16; x++) {
-               int g = (y * 16 + x < range) ? font->ascii2glyph[y * 16 + x] : -1;
-               if (g >= 0 && font->glyph[g].shape) {
-                   c++;
-                   if (lastx < 0)
-                       lastx = x * xmax;
-               }
-           }
-           if (c) {
-               swf_TextSetInfoRecord(t, font, textscale, &rgb, lastx + 1, textscale * ypos * 2);
-               for (x = 0; x < 16; x++) {
-                   int g = (y * 16 + x < range) ? font->ascii2glyph[y * 16 + x] : -1;
-                   if (g >= 0 && font->glyph[g].shape) {
-                       if (lastx != x * xmax) {
-                           swf_TextSetInfoRecord(t, 0, 0, 0, x * xmax + 1, 0);
-                       }
-                       swf_SetU8(t, 1);
-                       swf_SetBits(t, g, gbits);
-                       swf_SetBits(t, font->glyph[g].advance / 20, abits);
-                       lastx = x * xmax + (font->glyph[g].advance / 20);
-                       swf_ResetWriteBits(t);
-                   }
-               }
-               ypos++;
-           }
-       }
-       swf_SetU8(t, 0);
-
-
-       t = swf_InsertTag(t, ST_PLACEOBJECT2);
-
-       swf_ObjectPlace(t, font->id + 1, 1, NULL, NULL, NULL);
-
-       t = swf_InsertTag(t, ST_SHOWFRAME);
-
-    }
-
-    t = swf_InsertTag(t, ST_END);
-
-    f = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644);
-    if FAILED
-       (swf_WriteSWF(f, &swf)) fprintf(stderr, "WriteSWF() failed in writeFont().\n");
-    close(f);
-
-    swf_FreeTags(&swf);
-}
-
-
 void swf_SetEditText(TAG * tag, U16 flags, SRECT r, const char *text, RGBA * color, int maxlength, U16 font, U16 height, EditTextLayout * layout, const char *variable)
 {
     swf_SetRect(tag, &r);
 void swf_SetEditText(TAG * tag, U16 flags, SRECT r, const char *text, RGBA * color, int maxlength, U16 font, U16 height, EditTextLayout * layout, const char *variable)
 {
     swf_SetRect(tag, &r);
@@ -1629,10 +1547,11 @@ SRECT swf_SetDefineText(TAG * tag, SWFFONT * font, RGBA * rgb, const char *text,
        }
 
        /* now set the text params- notice that a font size of
        }
 
        /* now set the text params- notice that a font size of
-          1024 means that the glyphs will be displayed exactly
-          as they would be in/with a defineshape. (Try to find
-          *that* in the flash specs)
+          1024 (or 1024*20 for definefont3) means that the glyphs will 
+          be displayed exactly as they would be in/with a defineshape.
+          This is not documented in the specs.
         */
         */
+
        /* set the actual text- notice that we just pass our scale
           parameter over, as TextSetCharRecord calculates with
           percent, too */
        /* set the actual text- notice that we just pass our scale
           parameter over, as TextSetCharRecord calculates with
           percent, too */
@@ -1657,8 +1576,8 @@ void swf_FontCreateLayout(SWFFONT * f)
 
     f->layout = (SWFLAYOUT *) rfx_calloc(sizeof(SWFLAYOUT));
     f->layout->bounds = (SRECT *) rfx_alloc(f->numchars * sizeof(SRECT));
 
     f->layout = (SWFLAYOUT *) rfx_calloc(sizeof(SWFLAYOUT));
     f->layout->bounds = (SRECT *) rfx_alloc(f->numchars * sizeof(SRECT));
-    f->layout->ascent = -32767;
-    f->layout->descent = -32767;
+    f->layout->ascent = 0;
+    f->layout->descent = 0;
 
     for (t = 0; t < f->numchars; t++) {
        SHAPE2 *shape2;
 
     for (t = 0; t < f->numchars; t++) {
        SHAPE2 *shape2;
@@ -1683,12 +1602,52 @@ void swf_FontCreateLayout(SWFFONT * f)
            f->glyph[t].advance = width;
 
        if (-bbox.ymin > f->layout->ascent)
            f->glyph[t].advance = width;
 
        if (-bbox.ymin > f->layout->ascent)
-           f->layout->ascent = bbox.ymin;
+           f->layout->ascent = -bbox.ymin;
        if (bbox.ymax > f->layout->descent)
            f->layout->descent = bbox.ymax;
     }
 }
 
        if (bbox.ymax > f->layout->descent)
            f->layout->descent = bbox.ymax;
     }
 }
 
+#define FONTALIGN_THIN
+#define FONTALIGN_MEDIUM
+#define FONTALIGN_THICK
+
+void swf_FontCreateAlignZones(SWFFONT * f)
+{
+    if(f->alignzones)
+       return;
+    
+    f->alignzones = (ALIGNZONE*)rfx_calloc(sizeof(ALIGNZONE)*f->numchars);
+    f->alignzone_flags = 0; // thin
+
+    if(!f->layout) {
+       int t;
+       for(t=0;t<f->numchars;t++) {
+           // just align the baseline
+           f->alignzones[t].x = 0xffff;
+           f->alignzones[t].y = 0;
+           f->alignzones[t].dx = 0xffff;
+           f->alignzones[t].dy = 0xffff;//floatToF16(460.80 / 1024.0);
+       }
+    } else {
+       int t;
+       for(t=0;t<f->numchars;t++) {
+           // just align the baseline
+           f->alignzones[t].x = 0xffff;
+           f->alignzones[t].y = 0;
+           f->alignzones[t].dx = 0xffff;
+           f->alignzones[t].dy = 0xffff;//floatToF16(460.80 / 1024.0);
+       }
+    }
+
+/*
+    "-^_~\xad\xaf+`\xac\xb7\xf7" //chars for which to detect one y value
+    "#=:;\xb1" //chars for which to detect two y values
+    "\"\xa8" //chars for which to detect two x values
+*/
+}
+
+
 void swf_DrawText(drawer_t * draw, SWFFONT * font, int size, const char *text)
 {
     U8 *s = (U8 *) text;
 void swf_DrawText(drawer_t * draw, SWFFONT * font, int size, const char *text)
 {
     U8 *s = (U8 *) text;
@@ -1731,3 +1690,396 @@ void swf_DrawText(drawer_t * draw, SWFFONT * font, int size, const char *text)
        advance += font->glyph[g].advance * size / 100.0 / 20.0;
     }
 }
        advance += font->glyph[g].advance * size / 100.0 / 20.0;
     }
 }
+
+void swf_WriteFont_AS3(SWFFONT * font, char *filename)
+{
+    if(!font->layout) 
+       swf_FontCreateLayout(font);
+    
+    SWF swf;
+    memset(&swf, 0, sizeof(SWF));
+    swf.fileVersion = 9;
+    swf.frameRate = 0x4000;
+    swf.movieSize.xmax = 200;
+    swf.movieSize.ymax = 200;
+    
+    if(!font->id) font->id=1;
+
+    TAG *tag;
+    swf.firstTag = tag = swf_InsertTag(tag, ST_DEFINEFONT3);
+    swf_FontSetDefine2(tag, font);
+
+    char*name = font->name?(char*)font->name:"font";
+
+    tag = swf_InsertTag(tag, ST_NAMECHARACTER);
+    swf_SetU16(tag, font->id);
+    swf_SetString(tag, name);
+    tag = swf_InsertTag(tag, ST_EXPORTASSETS);
+    swf_SetU16(tag, 1);
+    swf_SetU16(tag, font->id);
+    swf_SetString(tag, name);
+    tag = swf_AddAS3FontDefine(tag, font->id, (char*)font->name);
+    
+    tag = swf_InsertTag(tag, ST_END);
+    swf_SaveSWF(&swf, filename);
+    swf_FreeTags(&swf);
+}
+
+void swf_WriteFont(SWFFONT * font, char *filename)
+{
+    if(!font->layout)
+       swf_FontCreateLayout(font);
+
+    char viewer = 1;
+    U16 id = 1;
+    U16 depth = 1;
+
+    font->id = id++;
+    
+    SWF swf;
+    memset(&swf, 0, sizeof(SWF));
+    swf.fileVersion = 8;
+    swf.frameRate = 0x4000;
+    swf.movieSize.xmax = 1024*20;
+    swf.movieSize.ymax = 768*20;
+    
+    TAG *tag;
+    swf.firstTag = tag = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR);
+    swf_SetU8(tag, 0xe0);swf_SetU8(tag, 0xe0);swf_SetU8(tag, 0xff);
+
+    tag = swf_InsertTag(tag, ST_DEFINEFONT3);
+    swf_FontSetDefine2(tag, font);
+
+    if(font->glyphnames) {
+       int c;
+       tag = swf_InsertTag(tag, ST_GLYPHNAMES);
+       swf_SetU16(tag, font->id);
+       swf_SetU16(tag, font->numchars);
+       for (c = 0; c < font->numchars; c++) {
+           if (font->glyphnames[c])
+               swf_SetString(tag, font->glyphnames[c]);
+           else
+               swf_SetString(tag, "");
+       }
+    }
+
+    if(viewer)
+    {
+       RGBA white = {255,255,255,255};
+       RGBA black = {255,0,0,0};
+       RGBA gray50 = {255,128,128,128};
+       RGBA green = {255,0,255,0};
+       int t;
+       SCOORD miny = SCOORD_MAX;
+       SCOORD maxy = SCOORD_MIN;
+       double width = 0;
+       U16 max_advance = 0;
+       char*flags = rfx_calloc(font->numchars);
+       double*xmin = rfx_calloc(sizeof(double)*(font->numchars+1));
+       double*xmax = rfx_calloc(sizeof(double)*(font->numchars+1));
+       int*xpos = rfx_calloc(sizeof(int)*(font->numchars+1));
+       for(t=0;t<font->numchars;t++) {
+           SHAPE*s = font->glyph[t].shape;
+           SHAPE2*s2 = swf_ShapeToShape2(s);
+           SRECT r = swf_GetShapeBoundingBox(s2);
+
+           // inside a definefont3, everything is 20x the resolution:
+           double rx1 = r.xmin / 20.0;
+           double ry1 = r.ymin / 20.0;
+           double rx2 = r.xmax / 20.0;
+           double ry2 = r.ymax / 20.0;
+           
+           xmin[t]= rx1;
+           xmax[t]= rx2;
+
+           if(ry1<miny) {miny=ry1;}
+           if(ry2>maxy) {maxy=ry2;}
+           swf_Shape2Free(s2);free(s2);
+           width += font->glyph[t].advance;
+           if(font->glyph[t].advance>max_advance)
+               max_advance = font->glyph[t].advance;
+       }
+
+       if(miny==SCOORD_MAX) miny=maxy=0;
+       if(miny==maxy) maxy=miny+1;
+
+       /* scale the font so that it's 256 pixels high */
+       double scale = (int)((256.0*1024.0/(maxy-miny))*20.0);
+       double overlarge_factor;
+       int fontsize;
+       if(scale > 32767) {
+           fontsize = 32767;
+           overlarge_factor = scale / 32767.0;
+       } else {
+           fontsize = scale;
+           overlarge_factor = 1.0;
+       }
+
+       int textid = id++;
+       int spriteid = id++;
+       SRECT r;
+       r.xmin = 0;
+       r.ymin = miny*fontsize/1024;
+       r.xmax = width*fontsize/20480;
+       r.ymax = maxy*fontsize/1024;
+       tag = swf_InsertTag(tag, ST_DEFINETEXT);
+       swf_SetU16(tag, textid);
+       swf_SetRect(tag, &r);
+       swf_SetMatrix(tag, NULL);
+
+       U8 abits = 15;
+       U8 gbits = swf_CountBits(font->numchars, 0);
+       swf_SetU8(tag, gbits);
+       swf_SetU8(tag, abits);
+
+       RGBA rgb = {255,0,0,0};
+
+       swf_TextSetInfoRecord(tag, font, fontsize, &rgb, SET_TO_ZERO, SET_TO_ZERO);
+       ActionTAG*array = 0;
+       double x=0;
+       array = action_PushString(array, "xpos");
+       for(t=0;t<font->numchars;t++) {
+           swf_SetU8(tag, 1);
+           int width = abs((xmax[t] - xmin[t+1])*fontsize/1024) + 60;
+           array = action_PushInt(array, x/20 +(xmin[t]*scale/1024)/20);
+           x += width * overlarge_factor;
+           swf_SetBits(tag, t, gbits);
+           swf_SetBits(tag, width, abits);
+           swf_SetU8(tag, 128);
+       }
+       array = action_PushInt(array, x/20);
+       array = action_PushInt(array, font->numchars+1);
+       array = action_InitArray(array);
+       array = action_SetVariable(array);
+       swf_SetU8(tag, 0);
+
+       if(font->layout) {
+           tag = swf_InsertTag(tag, ST_DEFINESHAPE2);
+           SHAPE* s;
+           swf_ShapeNew(&s);
+           int ls = swf_ShapeAddLineStyle(s,20,&white);
+           int shapeid = id++;
+           swf_SetU16(tag,shapeid);
+           SRECT r;
+           r.xmin = 0;
+           r.xmax = 1024*20;
+           r.ymin = 0;
+           r.ymax = 256*20;
+           swf_SetRect(tag,&r);
+           swf_SetShapeHeader(tag,s);
+           swf_ShapeSetAll(tag,s,0,0,ls,0,0);
+
+           /* Ã‡ and Ã‚ are good chars to test ascent/descent extend */
+           int y1 = (-font->layout->ascent-miny*20.0)*256.0/(maxy-miny);
+           int y2 = (font->layout->descent-miny*20.0)*256.0/(maxy-miny);
+
+           swf_ShapeSetMove(tag,s,0,y1);
+           swf_ShapeSetLine(tag,s,width,0);
+           swf_ShapeSetMove(tag,s,0,y2);
+           swf_ShapeSetLine(tag,s,width,0);
+
+           swf_ShapeSetEnd(tag);
+           swf_ShapeFree(s);
+           tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+           swf_ObjectPlace(tag, shapeid, depth++, NULL, NULL, NULL);
+       }
+
+       /* shapes */
+       
+       for(t=0;t<font->numchars;t++) {
+           tag = swf_InsertTag(tag, ST_DEFINESHAPE2);
+           SHAPE* s;
+           swf_ShapeNew(&s);
+           int ls = swf_ShapeAddLineStyle(s,20*2,&black);
+           int ls2 = swf_ShapeAddLineStyle(s,20*2,&green);
+           int fs = swf_ShapeAddSolidFillStyle(s, &gray50);
+           int shapeid = id++;
+           swf_SetU16(tag,shapeid);
+           SRECT r;
+           r.xmin = 0;
+           r.xmax = 1024*20;
+           r.ymin = 0;
+           r.ymax = 512*20;
+           swf_SetRect(tag,&r);
+           swf_SetShapeHeader(tag,s);
+           swf_ShapeSetAll(tag,s,0,0,ls,fs,0);
+           SHAPE2*s2 = swf_ShapeToShape2(font->glyph[t].shape);
+           SHAPELINE*l = s2->lines;
+           int lastx=0,lasty=0;
+
+           double x1 = (1024*20 - (xmax[t] - xmin[t])*20*2*scale/20480.0)/2;
+           double y1 = -miny*20*scale*2/20480.0;
+           double scalex = scale*2/20480.0;
+           double scaley = scale*2/20480.0;
+
+           while(l) {
+               int lx = (l->x)*scalex+x1;
+               int ly = (l->y)*scaley+y1;
+               int sx = (l->sx)*scalex+x1;
+               int sy = (l->sy)*scaley+y1;
+               if(l->type == moveTo) {
+                   swf_ShapeSetMove(tag,s,lx,ly);
+               } else if(l->type == lineTo) {
+                   swf_ShapeSetLine(tag,s,lx-lastx,ly-lasty);
+               } else if(l->type == splineTo) {
+                   swf_ShapeSetCurve(tag,s,sx-lastx,sy-lasty,lx-sx,ly-sy);
+               }
+               lastx = lx;
+               lasty = ly;
+               l = l->next;
+           }
+           
+           if(font->alignzones) {
+               ALIGNZONE*zone = &font->alignzones[t];
+               swf_ShapeSetAll(tag,s,0,0,ls2,SET_TO_ZERO,SET_TO_ZERO);
+               if((zone->x&zone->dx)!=0xffff) {
+                   double x = F16toFloat(zone->x)*20480.0*scalex+x1;
+                   double dx = (F16toFloat(zone->x)+F16toFloat(zone->dx))*20480.0*scalex+x1;
+                   swf_ShapeSetMove(tag,s,x,0);
+                   swf_ShapeSetLine(tag,s,0,1024*20);
+                   swf_ShapeSetMove(tag,s,dx,0);
+                   swf_ShapeSetLine(tag,s,0,1024*20);
+               }
+               if((zone->y&zone->dy)!=0xffff) {
+                   double y = -F16toFloat(zone->y)*20480.0*scaley+y1;
+                   double dy = -(F16toFloat(zone->y)+F16toFloat(zone->dy))*20480.0*scaley+y1;
+                   swf_ShapeSetMove(tag,s,0,y);
+                   swf_ShapeSetLine(tag,s,1024*20,0);
+                   swf_ShapeSetMove(tag,s,0,dy);
+                   swf_ShapeSetLine(tag,s,1024*20,0);
+               }
+           }
+
+           swf_ShapeSetEnd(tag);
+           swf_ShapeFree(s);
+       
+           tag = swf_InsertTag(tag, ST_DEFINESPRITE);
+           U16 spriteid=id++;
+           swf_SetU16(tag, spriteid);
+           swf_SetU16(tag, 1);
+           tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+           swf_ObjectPlace(tag, shapeid, 1, NULL, NULL, NULL);
+           tag = swf_InsertTag(tag, ST_END);
+           tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+           MATRIX m;
+           swf_GetMatrix(0, &m);
+           m.ty = 20000;
+           char txt[80];
+           sprintf(txt, "char%d", font->numchars-t);
+           swf_ObjectPlace(tag, spriteid, depth++, &m, NULL, txt);
+       }
+       
+       /* marker */
+       tag = swf_InsertTag(tag, ST_DEFINESHAPE2);
+       int shapeid=id++;
+       RGBA blue = {0xff,0xc0,0xc0,0xff};
+       swf_ShapeSetRectangle(tag, shapeid, 20, 20, &blue);
+       tag = swf_InsertTag(tag, ST_DEFINESPRITE);
+       U16 spriteid2=id++;
+       swf_SetU16(tag, spriteid2);
+       swf_SetU16(tag, 1);
+       tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+       swf_ObjectPlace(tag, shapeid, 1, NULL, NULL, NULL);
+       tag = swf_InsertTag(tag, ST_END);
+       tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+       swf_ObjectPlace(tag, spriteid2, depth++, NULL, NULL, "marker");
+       
+       /* textbar */
+       tag = swf_InsertTag(tag, ST_DEFINESPRITE);
+       swf_SetU16(tag, spriteid);
+       swf_SetU16(tag, 1);
+       tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+       MATRIX m;
+       swf_GetMatrix(0, &m);
+       m.sx = 65536 * overlarge_factor;
+       m.sy = 65536 * overlarge_factor;
+       m.tx = 0;
+       m.ty = -miny*256*20/(maxy-miny);
+       swf_ObjectPlace(tag, textid, 1, &m, NULL, NULL);
+       tag = swf_InsertTag(tag, ST_END);
+       tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+       swf_ObjectPlace(tag, spriteid, depth++, NULL, NULL, "textbar");
+       
+       /* marker2 */
+       RGBA blue2 = {0x80,0x80,0xff,0x80};
+       tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
+       int shapeid2=id++;
+       swf_ShapeSetRectangleWithBorder(tag, shapeid2, 20, 20, &blue2, 0, &white);
+       tag = swf_InsertTag(tag, ST_DEFINESPRITE);
+       U16 spriteid3=id++;
+       swf_SetU16(tag, spriteid3);
+       swf_SetU16(tag, 1);
+       tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+       swf_ObjectPlace(tag, shapeid2, 1, NULL, NULL, NULL);
+       tag = swf_InsertTag(tag, ST_END);
+       tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
+       swf_ObjectPlace(tag, spriteid3, depth++, NULL, NULL, "marker2");
+
+
+char*data = 
+" var mouseListener = new Object();"
+" var speed = 0;"
+" var myx = 0;"
+" var currentMouseOver, currentChar;"
+" mouseListener.onMouseDown = function() { "
+"     eval(\"_root.char\"+currentChar)._y = 20000;"
+"     currentChar = currentMouseOver;"
+"     var i = currentMouseOver;"
+"     eval(\"_root.char\"+i)._y = 256;"
+"     _root.marker2._yscale=256*100;"
+"     _root.marker2._xscale=(xpos[i-1]-xpos[i])*100;"
+"     _root.marker2._x=xpos[i]+myx;"
+" };"
+" mouseListener.onMouseMove = function() { "
+"     if(_ymouse<256) {"
+"          speed = Math.abs(_xmouse-512)>256?(512-_xmouse)/8:0;"
+"     } else {"
+"         speed = 0;"
+"     }; "
+" }; "
+" setInterval( function(){ "
+"     if(_ymouse<256) {"
+"         var i, x=_xmouse-_root.textbar._x;"
+"         for(i=xpos.length-1;i>0;i--) {"
+"             if(x<xpos[i-1]) break;"
+"         }"
+"         currentMouseOver = i;"
+"         _root.marker._yscale=256*100;"
+"         _root.marker._xscale=(xpos[i-1]-xpos[i])*100;"
+"         _root.marker._x=xpos[i]+myx;"
+"         _root.textbar._x += 0.05;"
+"     }"
+"     if(myx+speed>0) {"
+"         speed=0;"
+"     } else if(myx+speed<-xpos[0]+1024) {"
+"         speed=0;"
+"     }"
+"     myx+=speed;"
+"     _root.textbar._x = myx;"
+"     _root.marker._x += speed;"
+"     _root.marker2._x += speed;"
+" }, 20);"
+" Mouse.addListener(mouseListener);"
+;
+       ActionTAG* atag = swf_ActionCompile(data, 6);
+
+       tag = swf_InsertTag(tag, ST_DOACTION);
+       swf_ActionSet(tag, array);
+       swf_ActionSet(tag, atag);
+       swf_SetU8(tag, 0);
+       swf_ActionFree(atag);
+
+       tag = swf_InsertTag(tag, ST_SHOWFRAME);
+
+       free(flags);
+       free(xmin);
+       free(xmax);
+    }
+
+    tag = swf_InsertTag(tag, ST_END);
+
+    swf.compressed = -1;
+    swf_SaveSWF(&swf, filename);
+    swf_FreeTags(&swf);
+}
+
index 2b46f53..025bcaf 100644 (file)
@@ -95,6 +95,7 @@ U8 swf_GetU8(TAG * t)
   #ifdef DEBUG_RFXSWF
     if ((int)t->pos>=(int)t->len) 
     { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
   #ifdef DEBUG_RFXSWF
     if ((int)t->pos>=(int)t->len) 
     { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
+      *(int*)0=0;
       return 0;
     }
   #endif
       return 0;
     }
   #endif
@@ -408,32 +409,69 @@ int swf_SetU30String(TAG*tag, const char*str, int l)
     swf_SetBlock(tag, (void*)str, l);
     return len;
 }
     swf_SetBlock(tag, (void*)str, l);
     return len;
 }
+
 float swf_GetF16(TAG * t)
 {
 float swf_GetF16(TAG * t)
 {
-    // D16 is 1-5-10
-    // D32 is 1-8-23
     U16 f1 = swf_GetU16(t);
     U16 f1 = swf_GetU16(t);
-    if(!f1) return 0;
-    U32 f2 = (f1&0x8000)<<16; //sign
-    f2 |= ((f1&0x7c00)<<13)+(0x40000000-(0x4000<<13)); //exp
-    f2 |= (f1&0x03ff)<<13; //mantissa
+    if(!(f1&0x3ff)) return 0.0;
+
+    // IEEE 16 is 1-5-10
+    // IEEE 32 is 1-8-23
+    /* gcc 4.1.2 seems to require a union here. *(float*)u doesn't work */
+    union {
+      U32 u;
+      float f;
+    } f2;
+
+    U16 e = (f1>>10)&0x1f;
+    U16 m = f1&0x3ff;
+    /* find highest bit in mantissa */
+    int h=0;
+    while(!(m&0x400)) {
+       m<<=1;
+       h++;
+    }
+    m&=0x3ff;
+    e -= h;
+    e += 0x6f;
+
+    f2.u = (f1&0x8000)<<16; //sign
+    f2.u |= e<<23; //exponent
+    f2.u |= m<<13; //mantissa
     return *(float*)&f2;
 }
     return *(float*)&f2;
 }
+
 void swf_SetF16(TAG * t, float f)
 {
 void swf_SetF16(TAG * t, float f)
 {
-    U32 f1 = *(U32*)&f;
-    U16 f2 = (f1>>16)&0x8000;
-    int exp = ((f1>>23)&0xff)-0x80+0x10;
-    if(exp<0) {
+    union {
+      U32 u;
+      float f;
+    } v;
+    v.f = f;
+
+    U16 result = (v.u>>16)&0x8000; //sign
+    int exp = ((v.u>>23)&0xff)-0x7f+0x10;
+    U16 m = (v.u>>13)&0x3ff;
+    //fprintf(stderr, "%f: %04x sign, %d exp, %04x mantissa\n", f, result, exp, m);
+    if(exp<-10) {
+       // underflow (clamp to 0.0)
+       exp = 0;
+       m = 0;
+    } else if(exp<0) {
+        // partial underflow- strip some bits
+       m = (m|0x400)>>-exp;
        exp = 0;
        exp = 0;
-       fprintf(stderr, "Exponent underflow in FLOAT16 encoding\n");
     } else if(exp>=32) {
        exp = 31;
     } else if(exp>=32) {
        exp = 31;
+       m = 0x3ff;
        fprintf(stderr, "Exponent overflow in FLOAT16 encoding\n");
        fprintf(stderr, "Exponent overflow in FLOAT16 encoding\n");
+    } else {
+       exp++;
+       m = (m>>1)|0x200;
     }
     }
-    f2 |= exp<<10;
-    f2 |= (f1>>13)&0x3ff;
-    swf_SetU16(t, f2);
+    result |= exp<<10;
+    result |= m;
+    swf_SetU16(t, result);
 }
 
 double swf_GetD64(TAG*tag)
 }
 
 double swf_GetD64(TAG*tag)
index a3420c9..f586849 100644 (file)
@@ -475,6 +475,8 @@ int   swf_SetFillStyle(TAG * t,FILLSTYLE * f);
 int   swf_SetLineStyle(TAG * t,LINESTYLE * l);
 
 
 int   swf_SetLineStyle(TAG * t,LINESTYLE * l);
 
 
+void swf_ShapeSetRectangle(TAG*tag, U16 shapeid, int width, int height, RGBA*rgba);
+void swf_ShapeSetRectangleWithBorder(TAG*tag, U16 shapeid, int width, int height, RGBA*rgba, int linewidth, RGBA*linecolor);
 void  swf_ShapeSetBitmapRect(TAG * t, U16 gfxid, int width, int height);
 
 //SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits);
 void  swf_ShapeSetBitmapRect(TAG * t, U16 gfxid, int width, int height);
 
 //SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits);
@@ -512,8 +514,8 @@ typedef struct _KERNING
 } SWFKERNING;
 
 typedef struct _SWFLAYOUT
 } SWFKERNING;
 
 typedef struct _SWFLAYOUT
-{ S16          ascent;
-  S16          descent;
+{ U16          ascent;
+  U16          descent;
   S16          leading;
   SRECT      * bounds;
   U16         kerningcount;
   S16          leading;
   SRECT      * bounds;
   U16         kerningcount;
@@ -538,6 +540,12 @@ typedef struct _FONTUSAGE
 #define FONT_ENCODING_ANSI 2
 #define FONT_ENCODING_SHIFTJIS 4
 
 #define FONT_ENCODING_ANSI 2
 #define FONT_ENCODING_SHIFTJIS 4
 
+typedef struct _ALIGNZONE
+{
+    U16 x,y;
+    U16 dx,dy;
+} ALIGNZONE;
+
 typedef struct _SWFFONT
 { int          id; // -1 = not set
   U8           version; // 0 = not set, 1 = definefont, 2 = definefont2
 typedef struct _SWFFONT
 { int          id; // -1 = not set
   U8           version; // 0 = not set, 1 = definefont, 2 = definefont2
@@ -552,6 +560,8 @@ typedef struct _SWFFONT
   U16  *       glyph2ascii;
   int  *       ascii2glyph;
   SWFGLYPH *   glyph;
   U16  *       glyph2ascii;
   int  *       ascii2glyph;
   SWFGLYPH *   glyph;
+  ALIGNZONE *  alignzones;
+  U8            alignzone_flags;
   U8           language;
   char **      glyphnames;
 
   U8           language;
   char **      glyphnames;
 
@@ -601,6 +611,8 @@ int swf_FontExtract_DefineFont2(int id, SWFFONT * font, TAG * tag);
 int swf_FontExtract_DefineFontInfo(int id, SWFFONT * f, TAG * t);
 int swf_FontExtract_DefineFont(int id, SWFFONT * f, TAG * t);
 int swf_FontExtract_GlyphNames(int id, SWFFONT * f, TAG * tag);
 int swf_FontExtract_DefineFontInfo(int id, SWFFONT * f, TAG * t);
 int swf_FontExtract_DefineFont(int id, SWFFONT * f, TAG * t);
 int swf_FontExtract_GlyphNames(int id, SWFFONT * f, TAG * tag);
+int swf_FontExtract_DefineFontAlignZones(int id, SWFFONT * font, TAG * tag);
+
 
 int swf_FontIsItalic(SWFFONT * f);
 int swf_FontIsBold(SWFFONT * f);
 
 int swf_FontIsItalic(SWFFONT * f);
 int swf_FontIsBold(SWFFONT * f);
@@ -618,8 +630,10 @@ int swf_FontUse(SWFFONT* f,U8 * s);
 int swf_FontSetDefine(TAG * t,SWFFONT * f);
 int swf_FontSetDefine2(TAG * t,SWFFONT * f);
 int swf_FontSetInfo(TAG * t,SWFFONT * f);
 int swf_FontSetDefine(TAG * t,SWFFONT * f);
 int swf_FontSetDefine2(TAG * t,SWFFONT * f);
 int swf_FontSetInfo(TAG * t,SWFFONT * f);
+void swf_FontSetAlignZones(TAG*t, SWFFONT *f);
 
 void swf_FontCreateLayout(SWFFONT*f);
 
 void swf_FontCreateLayout(SWFFONT*f);
+void swf_FontCreateAlignZones(SWFFONT * f);
 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading);
 
 int swf_ParseDefineText(TAG * t, void(*callback)(void*self, int*chars, int*xpos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA* color), void*self);
 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading);
 
 int swf_ParseDefineText(TAG * t, void(*callback)(void*self, int*chars, int*xpos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA* color), void*self);
index 6ef23d1..86cf573 100644 (file)
@@ -53,7 +53,7 @@ swfc-interpolation.$(O): swfc-interpolation.c swfc-interpolation.h ../lib/q.h
 parser.$(O): parser.yy.c parser.h ../lib/q.h
        $(C) parser.yy.c -o $@
 
 parser.$(O): parser.yy.c parser.h ../lib/q.h
        $(C) parser.yy.c -o $@
 
-../lib/librfxswf$(A): ../lib/modules/swfrender.c ../lib/modules/swfshape.c ../lib/modules/swfbits.c ../lib/rfxswf.c
+../lib/librfxswf$(A): ../lib/modules/swfrender.c ../lib/modules/swfshape.c ../lib/modules/swftext.c ../lib/modules/swffont.c ../lib/modules/swfbits.c ../lib/rfxswf.c ../lib/devices/swf.c
        cd ../lib;$(MAKE) librfxswf$(A);cd -
 
 # TODO: include the following rule only if lex is available
        cd ../lib;$(MAKE) librfxswf$(A);cd -
 
 # TODO: include the following rule only if lex is available
index 3df34df..acc1806 100644 (file)
@@ -323,7 +323,10 @@ void dumpFont(TAG*tag, char*prefix)
     int t;
     for(t=0;t<font->numchars;t++) {
        int u = font->glyph2ascii?font->glyph2ascii[t]:-1;
     int t;
     for(t=0;t<font->numchars;t++) {
        int u = font->glyph2ascii?font->glyph2ascii[t]:-1;
-       printf("%s== Glyph %d: advance=%d encoding=%d ==\n", prefix, t, font->glyph[t].advance, u);
+       char ustr[16];
+       if(u>=32) sprintf(ustr, " '%c'", u);
+       else      sprintf(ustr, " 0x%02x", u);
+       printf("%s== Glyph %d: advance=%d encoding=%d%s ==\n", prefix, t, font->glyph[t].advance, u, ustr);
        SHAPE2* shape = swf_ShapeToShape2(font->glyph[t].shape);
        SHAPELINE*line = shape->lines;
 
        SHAPE2* shape = swf_ShapeToShape2(font->glyph[t].shape);
        SHAPELINE*line = shape->lines;
 
@@ -379,10 +382,12 @@ static SWF swf;
 static int fontnum = 0;
 static SWFFONT**fonts;
 
 static int fontnum = 0;
 static SWFFONT**fonts;
 
-void textcallback(void*self, int*glyphs, int*ypos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color) 
+void textcallback(void*self, int*glyphs, int*xpos, int nr, int fontid, int fontsize, int startx, int starty, RGBA*color) 
 {
     int font=-1,t;
 {
     int font=-1,t;
-    printf("                <%2d glyphs in font %2d size %d, color #%02x%02x%02x%02x> ",nr, fontid, fontsize, color->r, color->g, color->b, color->a);
+    if(nr<1) 
+       return;
+    printf("                <%2d glyphs in font %04d size %d, color #%02x%02x%02x%02x at %.2f,%.2f> ",nr, fontid, fontsize, color->r, color->g, color->b, color->a, (startx+xpos[0])/20.0, starty/20.0);
     for(t=0;t<fontnum;t++)
     {
        if(fonts[t]->id == fontid) {
     for(t=0;t<fontnum;t++)
     {
        if(fonts[t]->id == fontid) {
@@ -990,25 +995,63 @@ static void handleFontAlign1(TAG*tag)
     printf(" %d glyphs", num);
 }
 
     printf(" %d glyphs", num);
 }
 
+#define ALIGN_WITH_GLYPHS
 static void handleFontAlign2(TAG*tag, char*prefix)
 {
     if(!showfonts)
        return;
     swf_SetTagPos(tag, 0);
 static void handleFontAlign2(TAG*tag, char*prefix)
 {
     if(!showfonts)
        return;
     swf_SetTagPos(tag, 0);
-    swf_GetU16(tag);
+    U16 id = swf_GetU16(tag);
     swf_GetU8(tag);
     int num = 0;
     swf_GetU8(tag);
     int num = 0;
+#ifdef ALIGN_WITH_GLYPHS
+    SWF swf;
+    swf.firstTag = tag;
+    while(swf.firstTag->prev) swf.firstTag = swf.firstTag->prev;
+    SWFFONT* font = 0;
+    swf_FontExtract(&swf, id, &font);
+#endif
+    swf_SetTagPos(tag, 3);
     while(tag->pos < tag->len) {
     while(tag->pos < tag->len) {
-       printf("%sglyph %d) ", prefix, num++);
+       printf("%sglyph %d) ", prefix, num);
        int nr = swf_GetU8(tag); // should be 2
        int t;
        for(t=0;t<nr;t++) {
        int nr = swf_GetU8(tag); // should be 2
        int t;
        for(t=0;t<nr;t++) {
-           float v1 = swf_GetF16(tag);
-           float v2 = swf_GetF16(tag);
-           printf("%f/%f ", v1,v2);
+           // pos
+           float v = swf_GetF16(tag);
+           printf("%f ", v*1024.0);
+       }
+       for(t=0;t<nr;t++) {
+           // width
+           float v = swf_GetF16(tag);
+           printf("+%f ", v*1024.0);
        }
        U8 xyflags = swf_GetU8(tag);
        printf("xy:%02x\n", xyflags);
        }
        U8 xyflags = swf_GetU8(tag);
        printf("xy:%02x\n", xyflags);
+
+#ifdef ALIGN_WITH_GLYPHS
+       if(font && num<font->numchars) {
+           SHAPE2* shape = swf_ShapeToShape2(font->glyph[num].shape);
+           SHAPELINE*line = shape->lines;
+           while(line) {
+               if(line->type == moveTo) {
+                   printf("%smoveTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
+               } else if(line->type == lineTo) {
+                   printf("%slineTo %.2f %.2f\n", prefix, line->x/20.0, line->y/20.0);
+               } else if(line->type == splineTo) {
+                   printf("%ssplineTo (%.2f %.2f) %.2f %.2f\n", prefix,
+                           line->sx/20.0, line->sy/20.0,
+                           line->x/20.0, line->y/20.0
+                           );
+               }
+               line = line->next;
+           }
+           swf_Shape2Free(shape);
+           free(shape);
+       }
+       if(num==font->numchars-1) break;
+#endif
+       num++;
     }
 }
 
     }
 }
 
index 3550731..4eeca60 100644 (file)
@@ -483,7 +483,7 @@ int isOfType(int t, TAG*tag)
     if(t == 4 && (tag->id == ST_DEFINESOUND)) {
        show = 1;
     }
     if(t == 4 && (tag->id == ST_DEFINESOUND)) {
        show = 1;
     }
-    if(t == 5 && (tag->id == ST_DEFINEFONT || tag->id == ST_DEFINEFONT2)) {
+    if(t == 5 && (tag->id == ST_DEFINEFONT || tag->id == ST_DEFINEFONT2 || tag->id == ST_DEFINEFONT3)) {
        show = 1;
     }
     return show;
        show = 1;
     }
     return show;
@@ -586,8 +586,6 @@ void handlefont(SWF*swf, TAG*tag)
        printf("Couldn't extract font %d\n", id);
        return;
     }
        printf("Couldn't extract font %d\n", id);
        return;
     }
-    if(!f->layout)
-       swf_FontCreateLayout(f);
 
     swf_WriteFont(f, filename);
     swf_FontFree(f);
 
     swf_WriteFont(f, filename);
     swf_FontFree(f);