summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/devices/swf.c153
-rw-r--r--lib/example/Makefile7
-rw-r--r--lib/example/alignzones.c245
-rw-r--r--lib/example/buttontest.c8
-rw-r--r--lib/example/hexfont.c4
-rw-r--r--lib/modules/swfaction.c6
-rw-r--r--lib/modules/swfdraw.c16
-rw-r--r--lib/modules/swfshape.c53
-rw-r--r--lib/modules/swftext.c720
-rw-r--r--lib/rfxswf.c66
-rw-r--r--lib/rfxswf.h18
-rw-r--r--src/Makefile.in2
-rw-r--r--src/swfdump.c59
-rw-r--r--src/swfextract.c4
-rw-r--r--swfs/rfxview.swfbin4857 -> 5134 bytes
15 files changed, 1067 insertions, 294 deletions
diff --git a/lib/devices/swf.c b/lib/devices/swf.c
index 4f691b60..42bb610f 100644
--- a/lib/devices/swf.c
+++ b/lib/devices/swf.c
@@ -203,6 +203,8 @@ typedef struct _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);
@@ -537,7 +539,7 @@ static inline int colorcompare(RGBA*a,RGBA*b)
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;
@@ -546,17 +548,19 @@ static SRECT getcharacterbbox(chararray_t*chardata, MATRIX* m)
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];
- 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;
@@ -725,7 +729,7 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag)
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;
@@ -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;
- 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);
@@ -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, 0x20000);//thickness
+ //swf_SetU32(i->tag, 0x800000);//sharpness
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;
}
-/* 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,
@@ -1507,8 +1474,20 @@ void swfoutput_finalize(gfxdevice_t*dev)
}
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("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");
@@ -2810,13 +2789,13 @@ static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*grad
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->version = 2;
+ swffont->version = version;
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;
+ const double scale = GLYPH_SCALE;
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) {
@@ -2915,12 +2896,8 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id)
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
@@ -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->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;
@@ -3005,6 +2982,56 @@ static void swf_switchfont(gfxdevice_t*dev, const char*fontid)
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;
diff --git a/lib/example/Makefile b/lib/example/Makefile
index 4f73cb0a..f96accae 100644
--- a/lib/example/Makefile
+++ b/lib/example/Makefile
@@ -1,7 +1,7 @@
# 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++
@@ -14,7 +14,7 @@ DBFLAGS = -g2
%.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
@@ -51,6 +51,9 @@ transtest: $(RFXSWF) transtest.o $(RFXSWF)
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)
diff --git a/lib/example/alignzones.c b/lib/example/alignzones.c
new file mode 100644
index 00000000..57ce2625
--- /dev/null
+++ b/lib/example/alignzones.c
@@ -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;
+}
+
diff --git a/lib/example/buttontest.c b/lib/example/buttontest.c
index 76ba207c..18238175 100644
--- a/lib/example/buttontest.c
+++ b/lib/example/buttontest.c
@@ -30,7 +30,7 @@ TAG* t;
#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)
@@ -46,7 +46,7 @@ int main (int argc,char ** argv)
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
@@ -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_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!
}
diff --git a/lib/example/hexfont.c b/lib/example/hexfont.c
index bf5695b8..17121129 100644
--- a/lib/example/hexfont.c
+++ b/lib/example/hexfont.c
@@ -30,11 +30,11 @@
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));
- hexfont.name = "HexFont";
+ hexfont.name = (char*)"HexFont";
hexfont.layout = malloc(sizeof(SWFLAYOUT));
hexfont.numchars = 256;
hexfont.maxascii = 256;
diff --git a/lib/modules/swfaction.c b/lib/modules/swfaction.c
index e16b3a49..fb7474d1 100644
--- a/lib/modules/swfaction.c
+++ b/lib/modules/swfaction.c
@@ -182,7 +182,6 @@ ActionTAG* swf_ActionGet(TAG*tag)
void swf_ActionFree(ActionTAG*action)
{
if(!action) {
- fprintf(stderr, "Warning: freeing zero action");
return;
}
action = action->parent;
@@ -208,9 +207,10 @@ void swf_ActionFree(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);
diff --git a/lib/modules/swfdraw.c b/lib/modules/swfdraw.c
index 333fdb99..ae04aeee 100644
--- a/lib/modules/swfdraw.c
+++ b/lib/modules/swfdraw.c
@@ -97,8 +97,8 @@ static void fixEndPoint(drawer_t*draw)
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
@@ -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;
- 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;
@@ -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;
- 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;
diff --git a/lib/modules/swfshape.c b/lib/modules/swfshape.c
index deb9b3a6..afa069c8 100644
--- a/lib/modules/swfshape.c
+++ b/lib/modules/swfshape.c
@@ -888,6 +888,59 @@ void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height)
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);
diff --git a/lib/modules/swftext.c b/lib/modules/swftext.c
index 6bd59f05..912e8fa4 100644
--- a/lib/modules/swftext.c
+++ b/lib/modules/swftext.c
@@ -113,7 +113,7 @@ int swf_FontEnumerate(SWF * swf, void (*FontCallback) (void*, U16, U8 *), void*s
n = 0;
while (t) {
- if (swf_GetTagID(t) == ST_DEFINEFONT2 || swf_GetTagID(t) == ST_DEFINEFONT) {
+ if (swf_isFontTag(t)) {
n++;
if (FontCallback) {
U16 id;
@@ -373,6 +373,76 @@ int swf_FontExtract_DefineFont2(int id, SWFFONT * font, TAG * tag)
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
@@ -502,6 +572,10 @@ int swf_FontExtract(SWF * swf, int id, SWFFONT * *font)
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);
@@ -1029,6 +1103,27 @@ int swf_FontSetDefine2(TAG * tag, SWFFONT * f)
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));
@@ -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);
@@ -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
- 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 */
@@ -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->ascent = -32767;
- f->layout->descent = -32767;
+ f->layout->ascent = 0;
+ f->layout->descent = 0;
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->layout->ascent = bbox.ymin;
+ f->layout->ascent = -bbox.ymin;
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;
@@ -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;
}
}
+
+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);
+}
+
diff --git a/lib/rfxswf.c b/lib/rfxswf.c
index 2b46f53e..025bcaf4 100644
--- a/lib/rfxswf.c
+++ b/lib/rfxswf.c
@@ -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);
+ *(int*)0=0;
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;
}
+
float swf_GetF16(TAG * t)
{
- // D16 is 1-5-10
- // D32 is 1-8-23
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;
}
+
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;
- fprintf(stderr, "Exponent underflow in FLOAT16 encoding\n");
} else if(exp>=32) {
exp = 31;
+ m = 0x3ff;
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)
diff --git a/lib/rfxswf.h b/lib/rfxswf.h
index a3420c93..f5868490 100644
--- a/lib/rfxswf.h
+++ b/lib/rfxswf.h
@@ -475,6 +475,8 @@ int swf_SetFillStyle(TAG * t,FILLSTYLE * f);
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);
@@ -512,8 +514,8 @@ typedef struct _KERNING
} SWFKERNING;
typedef struct _SWFLAYOUT
-{ S16 ascent;
- S16 descent;
+{ U16 ascent;
+ U16 descent;
S16 leading;
SRECT * bounds;
U16 kerningcount;
@@ -538,6 +540,12 @@ typedef struct _FONTUSAGE
#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
@@ -552,6 +560,8 @@ typedef struct _SWFFONT
U16 * glyph2ascii;
int * ascii2glyph;
SWFGLYPH * glyph;
+ ALIGNZONE * alignzones;
+ U8 alignzone_flags;
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_DefineFontAlignZones(int id, SWFFONT * font, TAG * tag);
+
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);
+void swf_FontSetAlignZones(TAG*t, 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);
diff --git a/src/Makefile.in b/src/Makefile.in
index 6ef23d1d..86cf5731 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -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 $@
-../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
diff --git a/src/swfdump.c b/src/swfdump.c
index 3df34df4..acc18067 100644
--- a/src/swfdump.c
+++ b/src/swfdump.c
@@ -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;
- 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;
@@ -379,10 +382,12 @@ static SWF swf;
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;
- 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) {
@@ -990,25 +995,63 @@ static void handleFontAlign1(TAG*tag)
printf(" %d glyphs", num);
}
+#define ALIGN_WITH_GLYPHS
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;
+#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) {
- 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++) {
- 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);
+
+#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++;
}
}
diff --git a/src/swfextract.c b/src/swfextract.c
index 3550731e..4eeca601 100644
--- a/src/swfextract.c
+++ b/src/swfextract.c
@@ -483,7 +483,7 @@ int isOfType(int t, TAG*tag)
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;
@@ -586,8 +586,6 @@ void handlefont(SWF*swf, TAG*tag)
printf("Couldn't extract font %d\n", id);
return;
}
- if(!f->layout)
- swf_FontCreateLayout(f);
swf_WriteFont(f, filename);
swf_FontFree(f);
diff --git a/swfs/rfxview.swf b/swfs/rfxview.swf
index 1862ee73..c6a3fdf3 100644
--- a/swfs/rfxview.swf
+++ b/swfs/rfxview.swf
Binary files differ