X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fmodules%2Fswffont.c;h=f8f7707e749c41ad902fe1928e7b6fa4acefe5c1;hp=d6f157b616600ebd8c8b77fcd055b26e8501038f;hb=c17ea569d3883466bc247f479ab202ff9ce7c638;hpb=71be4f61ae47306a9f52ae9e63bd7a380e73fc2f diff --git a/lib/modules/swffont.c b/lib/modules/swffont.c index d6f157b..f8f7707 100644 --- a/lib/modules/swffont.c +++ b/lib/modules/swffont.c @@ -21,7 +21,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef USE_FREETYPE +#ifdef HAVE_FREETYPE #include #include @@ -29,12 +29,15 @@ #include #include +#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; } @@ -42,8 +45,8 @@ static int ft_line_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->lineTo(draw, &to); return 0; } @@ -51,12 +54,12 @@ static int ft_cubic_to(FT_Vector* _c1, FT_Vector* _c2, FT_Vector* _to, void* use { 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; } @@ -64,10 +67,10 @@ static int ft_conic_to(FT_Vector* _c, FT_Vector* _to, void* user) { 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; } @@ -86,7 +89,7 @@ SWFFONT* swf_LoadTrueTypeFont(char*filename) { FT_Face face; FT_Error error; - const char* name; + const char* name = 0; FT_ULong charcode; FT_UInt gindex; SWFFONT* font; @@ -118,8 +121,9 @@ SWFFONT* swf_LoadTrueTypeFont(char*filename) |((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)) { @@ -131,8 +135,9 @@ SWFFONT* swf_LoadTrueTypeFont(char*filename) font->layout->leading = -face->bbox.xMin; font->layout->kerningcount = 0; + name = FT_Get_Postscript_Name(face); if(name && *name) - font->name = (U8*)strdup(FT_Get_Postscript_Name(face)); + font->name = (U8*)strdup(name); /* // Map Glyphs to Unicode, version 1 (quick and dirty): int t; @@ -162,17 +167,21 @@ SWFFONT* swf_LoadTrueTypeFont(char*filename) 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;tmaxascii;t++) + for(t=0;tmaxascii;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); @@ -185,23 +194,47 @@ SWFFONT* swf_LoadTrueTypeFont(char*filename) 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); } @@ -211,7 +244,7 @@ SWFFONT* swf_LoadTrueTypeFont(char*filename) return font; } -#else //USE_FREETYPE +#else //HAVE_FREETYPE SWFFONT* swf_LoadTrueTypeFont(char*filename) { @@ -225,6 +258,8 @@ SWFFONT* swf_LoadTrueTypeFont(char*filename) #include +static int t1lib_initialized = 0; + SWFFONT* swf_LoadT1Font(char*filename) { SWFFONT * font; @@ -235,12 +270,16 @@ SWFFONT* swf_LoadT1Font(char*filename) int s,num; char*encoding[256]; char**charnames; - char*charname; - - T1_SetBitmapPad( 16); - if ((T1_InitLib(NO_LOGFILE)==NULL)){ - fprintf(stderr, "Initialization of t1lib failed\n"); - return 0; + char**charname; + int c; + + if(!t1lib_initialized) { + T1_SetBitmapPad(16); + if ((T1_InitLib(NO_LOGFILE)==NULL)){ + fprintf(stderr, "Initialization of t1lib failed\n"); + return 0; + } + t1lib_initialized = 1; } nr = T1_AddFont(filename); T1_LoadFont(nr); @@ -266,13 +305,13 @@ SWFFONT* swf_LoadT1Font(char*filename) memset(font->layout, 0, sizeof(SWFLAYOUT)); num = 0; - charname = charnames[0]; + charname = charnames; while(*charname) { charname++; num++; } - font->maxascii = 256; + font->maxascii = num; font->numchars = num; font->style = (/*bold*/0?FONT_STYLE_BOLD:0) + (angle>0.05?FONT_STYLE_ITALIC:0); @@ -292,31 +331,69 @@ SWFFONT* swf_LoadT1Font(char*filename) memset(font->layout->bounds, 0, sizeof(SRECT)*num); font->layout->kerningcount = 0; font->layout->kerning = 0; + font->glyphnames = malloc(num*sizeof(char*)); + memset(font->glyphnames, 0, num*sizeof(char*)); num = 0; - - charname = charnames[0]; - while(*charname) { - int c; - T1_OUTLINE * outline = T1_GetCharOutline(nr, c, 100.0, 0); - int firstx = outline->dest.x/0xffff; - font->ascii2glyph[s] = num; - font->glyph2ascii[num] = s; - - /* fix bounding box */ - SHAPE2*shape2; + charname = charnames; + for(c=0;cnumchars;c++) { + drawer_t draw; SRECT bbox; - shape2 = swf_ShapeToShape2(font->glyph[s].shape); - if(!shape2) { fprintf(stderr, "Shape parse error\n");exit(1);} - bbox = swf_GetShapeBoundingBox(shape2); - swf_Shape2Free(shape2); - font->layout->bounds[num] = bbox; - //font->glyph[num].advance = (int)(width/6.4); // 128/20 - font->glyph[num].advance = bbox.xmax/20; - if(!font->glyph[num].advance) { - font->glyph[num].advance = firstx; + T1_OUTLINE * outline; + FPOINT pos,last; + int firstx; + + outline = T1_GetCharOutline(nr, c, 100.0, 0); + firstx = outline->dest.x/0xffff; + + pos.x = 0; + pos.y = 0; + last = pos; + + font->glyphnames[c] = strdup(*charname); + + if(cmaxascii) + font->ascii2glyph[c] = c; + font->glyph2ascii[c] = c; + + swf_Shape01DrawerInit(&draw, 0); + + while(outline) { + pos.x += (outline->dest.x/(float)0xffff); + pos.y += (outline->dest.y/(float)0xffff); + + if(outline->type == T1_PATHTYPE_MOVE) { + draw.moveTo(&draw,&pos); + } else if(outline->type == T1_PATHTYPE_LINE) { + draw.lineTo(&draw,&pos); + } else if(outline->type == T1_PATHTYPE_BEZIER) { + T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline; + FPOINT b,c; + b.x = o2->B.x/(float)0xffff+last.x; + b.y = o2->B.y/(float)0xffff+last.y; + c.x = o2->C.x/(float)0xffff+last.x; + c.y = o2->C.y/(float)0xffff+last.y; + draw_cubicTo(&draw,&b,&c,&pos); + } else { + fprintf(stderr, "loadT1Font: unknown outline type:%d\n", outline->type); + } + last = pos; + outline = outline->link; + } + + draw.finish(&draw); + + font->glyph[c].shape = swf_ShapeDrawerToShape(&draw); + bbox = swf_ShapeDrawerGetBBox(&draw); + draw.dealloc(&draw); + + font->layout->bounds[c] = bbox; + font->glyph[c].advance = bbox.xmax/20; + if(!font->glyph[c].advance) { + font->glyph[c].advance = firstx; } + charname++; } return font; } @@ -331,3 +408,36 @@ SWFFONT* swf_LoadT1Font(char*filename) #endif +static int isSWF(const char*filename) +{ + FILE*fi = fopen(filename, "rb"); + char a[8]; + if(!fi) { + perror(filename); + return 0; + } + memset(a, 0, sizeof(a)); + fread(a, 4, 1, fi); + fclose(fi); + + if(!strncmp(a, "FWS", 3) || !strncmp(a, "CWS", 3)) { + return 1; + } + return 0; +} + +SWFFONT* swf_LoadFont(char*filename) +{ + if(isSWF(filename)) { + return swf_ReadFont(filename); + } +#if defined(HAVE_FREETYPE) + return swf_LoadTrueTypeFont(filename); +#elif defined(HAVE_T1LIB) + return swf_LoadT1Font(filename); +#else + fprintf(stderr, "Error: Neither T1lib nor FreeType support compiled in. Could not load %s\n", infile); + return 0; +#endif +} +