#include <freetype/ttnameid.h>
#include <freetype/ftoutln.h>
+#define FT_SCALE 1
+#define FT_SUBPIXELS 64
+
static int ft_move_to(FT_Vector* _to, void* user)
{
drawer_t* draw = (drawer_t*)user;
FPOINT to;
- to.x = _to->x/256.0;
- to.y = _to->y/256.0;
+ to.x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
+ to.y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
draw->moveTo(draw, &to);
return 0;
}
{
drawer_t* draw = (drawer_t*)user;
FPOINT to;
- to.x = _to->x/256.0;
- to.y = _to->y/256.0;
+ to.x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
+ to.y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
draw->lineTo(draw, &to);
return 0;
}
{
drawer_t* draw = (drawer_t*)user;
FPOINT c1,c2,to;
- to.x = _to->x/256.0;
- to.y = _to->y/256.0;
- c1.x = _c1->x/256.0;
- c1.y = _c1->y/256.0;
- c2.x = _c2->x/256.0;
- c2.y = _c2->y/256.0;
+ to.x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
+ to.y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
+ c1.x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
+ c1.y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
+ c2.x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
+ c2.y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
draw_cubicTo(draw, &c1, &c2, &to);
return 0;
}
{
drawer_t* draw = (drawer_t*)user;
FPOINT c,to;
- to.x = _to->x/256.0;
- to.y = _to->y/256.0;
- c.x = _c->x/256.0;
- c.y = _c->y/256.0;
+ to.x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
+ to.y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
+ c.x = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
+ c.y = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
draw_conicTo(draw, &c, &to);
return 0;
}
|((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
font->encoding = FONT_ENCODING_UNICODE;
font->glyph2ascii = malloc(face->num_glyphs*sizeof(U16));
+ memset(font->glyph2ascii, 0, face->num_glyphs*sizeof(U16));
font->maxascii = 0;
- memset(font->ascii2glyph, 0, font->maxascii*sizeof(int));
+ memset(font->ascii2glyph, -1, font->maxascii*sizeof(int));
font->glyph = malloc(face->num_glyphs*sizeof(SWFGLYPH));
memset(font->glyph, 0, face->num_glyphs*sizeof(U16));
if(FT_HAS_GLYPH_NAMES(face)) {
charcode = FT_Get_Next_Char(face, charcode, &gindex);
}
- memset(font->glyph2ascii, 0, face->num_glyphs*sizeof(U16));
font->ascii2glyph = malloc(font->maxascii*sizeof(int));
- for(t=0;t<font->maxascii;t++)
+ for(t=0;t<font->maxascii;t++) {
font->ascii2glyph[t] = FT_Get_Char_Index(face, t);
+ if(!font->ascii2glyph[t])
+ font->ascii2glyph[t] = -1;
+ }
for(t=0; t < face->num_glyphs; t++) {
FT_Glyph glyph;
FT_BBox bbox;
+ FT_Matrix matrix;
char name[128];
drawer_t draw;
+ int ret;
name[0]=0;
if(FT_HAS_GLYPH_NAMES(face)) {
error = FT_Get_Glyph_Name(face, t, name, 127);
if(error) return 0;
FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &bbox);
+ bbox.yMin = -bbox.yMin;
+ bbox.yMax = -bbox.yMax;
+ if(bbox.xMax < bbox.xMin) {
+ // swap
+ bbox.xMax ^= bbox.xMin;
+ bbox.xMin ^= bbox.xMax;
+ bbox.xMax ^= bbox.xMin;
+ }
+ if(bbox.yMax < bbox.yMin) {
+ // swap
+ bbox.yMax ^= bbox.yMin;
+ bbox.yMin ^= bbox.yMax;
+ bbox.yMax ^= bbox.yMin;
+ }
swf_Shape01DrawerInit(&draw, 0);
+ //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw);
error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw);
if(error) return 0;
draw.finish(&draw);
- font->glyph[t].advance = glyph->advance.x*20/256;
+#if 0
+ if(bbox.xMin > 0) {
+ font->glyph[t].advance = (bbox.xMax*FT_SCALE)/FT_SUBPIXELS;
+ } else {
+ font->glyph[t].advance = ((bbox.xMax - bbox.xMin)*FT_SCALE)/FT_SUBPIXELS;
+ }
+#else
+ font->glyph[t].advance = glyph->advance.x/65536;
+#endif
+
font->glyph[t].shape = swf_ShapeDrawerToShape(&draw);
- //swf_ShapeDrawerGetBBox(&draw);
+
+ font->layout->bounds[t].xmin = (bbox.xMin*FT_SCALE*20)/FT_SUBPIXELS;
+ font->layout->bounds[t].ymin = (bbox.yMin*FT_SCALE*20)/FT_SUBPIXELS;
+ font->layout->bounds[t].xmax = (bbox.xMax*FT_SCALE*20)/FT_SUBPIXELS;
+ font->layout->bounds[t].ymax = (bbox.yMax*FT_SCALE*20)/FT_SUBPIXELS;
+
draw.dealloc(&draw);
-
- font->layout->bounds[t].xmin = (bbox.xMin*5*20)/266;
- font->layout->bounds[t].ymin = (bbox.yMin*5*20)/266;
- font->layout->bounds[t].xmax = (bbox.xMax*5*20)/266;
- font->layout->bounds[t].ymax = (bbox.yMax*5*20)/266;
FT_Done_Glyph(glyph);
}
flags = swf_GetU8(t);
while(flags)
- { if (flags&TF_TEXTCONTROL)
+ {
+ // FIXME: according to open-swf@macromedia.com, this is wrong.
+ // it should alternate textcontrol and text arrays, not
+ // rely on the high bit. (and length can be 0-255).
+ if (flags&TF_TEXTCONTROL)
{ if (flags&TF_HASFONT) fid = swf_GetU16(t);
if (flags&TF_HASCOLOR)
{ swf_GetU8(t); // rgb
j = 0;
for (i=0;i<f->numchars;i++)
if (f->glyph[i].shape)
- { if (f->glyph2ascii[i]<MAX_CHAR_PER_FONT &&
+ { if (f->glyph2ascii[i]<f->numchars&&
use->code[f->glyph2ascii[i]])
{ f->ascii2glyph[f->glyph2ascii[i]] = j;
f->glyph2ascii[j] = f->glyph2ascii[i];
return j;
}
-int swf_FontInitUsage(FONTUSAGE * use)
+int swf_FontInitUsage(SWFFONT* f, FONTUSAGE * use)
{ if (!use) return -1;
- memset(use->code,0,sizeof(use->code[0])*MAX_CHAR_PER_FONT);
+ use->code = malloc(sizeof(use->code[0])*f->numchars);
+ memset(use->code,0,sizeof(use->code[0])*f->numchars);
return 0;
}
+void swf_FontClearUsage(SWFFONT* f, FONTUSAGE * use)
+{ if (!use) return;
+ free(use->code);
+}
+
int swf_FontUse(FONTUSAGE * use,U8 * s)
{ if ((!use)||(!s)) return -1;
while (s[0])
return 0;
}
+static inline int fontSize(SWFFONT*font)
+{
+ int t;
+ int size = 0;
+ for(t=0;t<font->numchars;t++) {
+ int l = (font->glyph[t].shape->bitlen+7)/8;
+ size += l+1;
+ }
+ return size + (font->numchars+1)*2;
+}
+
int swf_FontSetDefine2(TAG *tag, SWFFONT * f)
{
U8 flags = 0;
int pos;
int pos2;
swf_SetU16(tag, f->id);
+
if(f->layout)
flags |= 128; // haslayout
if(f->numchars>256)
flags |= 1; // bold
if(f->style & FONT_STYLE_ITALIC)
flags |= 2; // italic
- /* wideoffs 8 */
+ if(f->maxascii>=256)
+ flags |= 4; //wide codecs
+ if(fontSize(f)>65535)
+ flags |= 8; //wide offsets
+ flags |= 8; //FIXME: the above check doesn't work
+
if(f->encoding & FONT_ENCODING_ANSI)
flags |= 16; // ansi
if(f->encoding & FONT_ENCODING_UNICODE)
swf_SetU16(tag, f->numchars);
/* font offset table */
pos = tag->len;
- for(t=0;t<f->numchars;t++)
+ for(t=0;t<=f->numchars;t++)
{
- swf_SetU16(tag, /* fontoffset */ 0); /*placeholder*/
+ if(flags&8)
+ swf_SetU32(tag, /* fontoffset */ 0); /*placeholder*/
+ else
+ swf_SetU16(tag, /* fontoffset */ 0); /*placeholder*/
}
- pos2 = tag->len;
- swf_SetU16(tag, 0); //fontcode-fontoffset
- for(t=0;t<f->numchars;t++) {
- tag->data[pos + t*2] = (tag->len-pos);
- tag->data[pos + t*2 + 1] = (tag->len-pos) >> 8;
- swf_SetSimpleShape(tag, f->glyph[t].shape);
+
+ for(t=0;t<=f->numchars;t++) {
+ if(flags&8) {
+ tag->data[pos + t*4 ] = (tag->len-pos);
+ tag->data[pos + t*4 + 1] = (tag->len-pos) >> 8;
+ tag->data[pos + t*4 + 2] = (tag->len-pos) >> 16;
+ tag->data[pos + t*4 + 3] = (tag->len-pos) >> 24;
+ } else {
+ if(tag->len - pos > 65535) {
+ fprintf(stderr, "Internal error: Font too big and WideOffsets flag not set\n");
+ exit(1);
+ }
+ tag->data[pos + t*2 ] = (tag->len-pos);
+ tag->data[pos + t*2 + 1] = (tag->len-pos) >> 8;
+ }
+ if(t<f->numchars)
+ swf_SetSimpleShape(tag, f->glyph[t].shape);
}
- tag->data[pos2] = tag->len - pos;
- tag->data[pos2 + 1] = (tag->len - pos) >> 8;
/* font code table */
if(flags & 4) /* wide codes */ {
- for(t=0;t<f->numchars;t++)
+ for(t=0;t<f->numchars;t++) {
swf_SetU16(tag,f->glyph2ascii[t]);
+ }
} else {
for(t=0;t<f->numchars;t++)
swf_SetU8(tag,f->glyph2ascii[t]);
swf_SetU16(tag, f->layout->kerningcount);
for(t=0;t<f->layout->kerningcount;t++) {
if(flags & 4) /* wide codes */ {
- swf_SetU8(tag,f->layout->kerning[t].char1);
- swf_SetU8(tag,f->layout->kerning[t].char2);
- } else {
swf_SetU16(tag,f->layout->kerning[t].char1);
swf_SetU16(tag,f->layout->kerning[t].char2);
+ } else {
+ swf_SetU8(tag,f->layout->kerning[t].char1);
+ swf_SetU8(tag,f->layout->kerning[t].char2);
}
swf_SetU16(tag,f->layout->kerning[t].adjustment);
}
free(f->glyph2ascii);
f->glyph2ascii = NULL;
}
+ if(f->glyphnames) {
+ int t;
+ for(t=0;t<f->numchars;t++) {
+ free(f->glyphnames[t]);
+ }
+ free(f->glyphnames);
+ }
}
free(f);
}
did use definefont2 -mk*/
t = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
swf.firstTag = t;
- rgb.r = 0xff;
- rgb.g = 0xff;
+ rgb.r = 0xef;
+ rgb.g = 0xef;
rgb.b = 0xff;
swf_SetRGB(t,&rgb);
if(!useDefineFont2) {
swf_FontSetDefine2(t,font);
}
- if(1) //useDefineFont2
- { int textscale = 400;
+ 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 = textscale * 2 * (font->maxascii/16+1);
+ int ymax = 0;
+ int ypos = 1;
U8 gbits,abits;
- U8 text[MAX_CHAR_PER_FONT+1];
- int x,y;
- text[MAX_CHAR_PER_FONT]=0;
+ int x,y,c;
+
+ c=0;
for(s=0;s<font->maxascii;s++)
{
int g = font->ascii2glyph[s];
- text[s] = s;
if(g>=0) {
- if(font->glyph[g].advance*textscale/64 > xmax)
+ if(font->glyph[g].advance*textscale/64 > xmax) {
xmax = font->glyph[g].advance*textscale/64;
+ }
+ c++;
+ }
+ if((s&15)==0) {
+ if(c) {
+ ypos++;
+ }
+ c=0;
}
}
+ ymax = ypos*textscale*2;
+
swf.movieSize.xmax = xmax*20;
swf.movieSize.ymax = ymax;
r.xmin = 0;
r.ymin = 0;
- r.xmax = swf.movieSize.xmax*20;
+ r.xmax = swf.movieSize.xmax;
r.ymax = swf.movieSize.ymax;
swf_SetRect(t,&r);
rgb.r = 0x00;
rgb.g = 0x00;
rgb.b = 0x00;
- for(y=0;y<=((font->maxascii-1)/16);y++)
+ ypos = 1;
+ for(y=0;y<((font->maxascii+15)/16);y++)
{
int c=0,lastx=-1;
- /* TODO: firstx?? */
for(x=0;x<16;x++) {
int g = (y*16+x<font->maxascii)?font->ascii2glyph[y*16+x]:-1;
if(g>=0 && font->glyph[g].shape) {
}
}
if(c) {
- swf_TextSetInfoRecord(t,font,textscale,&rgb,lastx+1,textscale*y*2);
+ swf_TextSetInfoRecord(t,font,textscale,&rgb,lastx+1,textscale*ypos*2);
for(x=0;x<16;x++)
{
int g = (y*16+x<font->maxascii)?font->ascii2glyph[y*16+x]:-1;
swf_ResetWriteBits(t);
}
}
+ ypos++;
}
}
swf_SetU8(t,0);
swf_ObjectPlace(t,font->id+1,1,NULL,NULL,NULL);
t = swf_InsertTag(t,ST_SHOWFRAME);
+
}
t = swf_InsertTag(t,ST_END);
return *((*text)++);
}
-void swf_DrawText(SWFSHAPEDRAWER*draw, SWFFONT*font, char*text)
+void swf_DrawText(drawer_t*draw, SWFFONT*font, char*text)
{
char*s = text;
int advance = 0;
FPOINT to;
to.x = l->x/20.0+advance;
to.y = l->y/20.0;
- swf_DrawerMoveTo(draw, &to);
+ draw->moveTo(draw, &to);
} else if(l->type == lineTo) {
FPOINT to;
to.x = l->x/20.0+advance;
to.y = l->y/20.0;
- swf_DrawerLineTo(draw, &to);
+ draw->lineTo(draw, &to);
} else if(l->type == splineTo) {
FPOINT mid,to;
mid.x = l->sx/20.0+advance;
mid.y = l->sy/20.0;
to.x = l->x/20.0+advance;
to.y = l->y/20.0;
- swf_DrawerSplineTo(draw, &mid, &to);
+ draw->splineTo(draw, &mid, &to);
}
l = l->next;
}