Aric Stewart : sfnt2fnt: Use code from gdi32/ freetype to do a better job finding the TTAG_EBLC to deal with older version of freetype without having to fall back on unreliable hacks .

Alexandre Julliard julliard at winehq.org
Mon Dec 10 08:54:21 CST 2007


Module: wine
Branch: master
Commit: 8be27f68c77c37989f043c54b9360e9b75548747
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=8be27f68c77c37989f043c54b9360e9b75548747

Author: Aric Stewart <aric at codeweavers.com>
Date:   Mon Dec 10 16:24:10 2007 +0900

sfnt2fnt: Use code from gdi32/freetype to do a better job finding the TTAG_EBLC to deal with older version of freetype without having to fall back on unreliable hacks.

---

 tools/sfnt2fnt.c |   95 +++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 70 insertions(+), 25 deletions(-)

diff --git a/tools/sfnt2fnt.c b/tools/sfnt2fnt.c
index 955f61a..8868c66 100644
--- a/tools/sfnt2fnt.c
+++ b/tools/sfnt2fnt.c
@@ -36,6 +36,9 @@
 #include FT_SFNT_NAMES_H
 #include FT_TRUETYPE_TABLES_H
 #include FT_TRUETYPE_TAGS_H
+#ifdef HAVE_FREETYPE_INTERNAL_SFNT_H
+#include <freetype/internal/sfnt.h>
+#endif
 
 #include "wine/unicode.h"
 #include "wine/wingdi16.h"
@@ -90,6 +93,14 @@ typedef struct {
     CHAR flags;
 } bitmapSizeTable_t;
 
+typedef struct
+{
+    FT_Int major;
+    FT_Int minor;
+    FT_Int patch;
+} FT_Version_t;
+static FT_Version_t FT_Version;
+
 #define GET_BE_WORD(ptr)  MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
 #define GET_BE_DWORD(ptr) ((DWORD)MAKELONG( GET_BE_WORD(&((WORD *)(ptr))[1]), \
                                             GET_BE_WORD(&((WORD *)(ptr))[0]) ))
@@ -194,9 +205,38 @@ static int get_char(const union cptable *cptable, int enc, int index)
     return cptable->sbcs.cp2uni[index];
 }
 
+/* from gdi32/freetype.c */
+static FT_Error load_sfnt_table(FT_Face ft_face, FT_ULong table, FT_Long offset, FT_Byte *buf, FT_ULong *len)
+{
+
+    FT_Error err;
+
+    /* If the FT_Load_Sfnt_Table function is there we'll use it */
+#ifdef HAVE_FT_LOAD_SFNT_TABLE
+    err = FT_Load_Sfnt_Table(ft_face, table, offset, buf, len);
+#elif defined(HAVE_FREETYPE_INTERNAL_SFNT_H)
+    TT_Face tt_face = (TT_Face) ft_face;
+    SFNT_Interface *sfnt;
+    if (FT_Version.major==2 && FT_Version.minor==0)
+    {
+        /* 2.0.x */
+        sfnt = *(SFNT_Interface**)((char*)tt_face + 528);
+    }
+    else
+    {
+        /* A field was added in the middle of the structure in 2.1.x */
+        sfnt = *(SFNT_Interface**)((char*)tt_face + 532);
+    }
+    err = sfnt->load_any(tt_face, table, offset, buf, len);
+#else
+    err = FT_Err_Unimplemented_Feature;
+#endif
+    return err;
+}
+
 static void fill_fontinfo(FT_Face face, int enc, FILE *fp, int dpi, unsigned char def_char, int avg_width)
 {
-    int ascent = 0, il, ppem, descent = 0, width_bytes = 0, space_size, max_width = 0;
+    int ascent = 0, il, el, ppem, descent = 0, width_bytes = 0, space_size, max_width = 0;
     FNT_HEADER hdr;
     FONTINFO16 fi;
     BYTE left_byte, right_byte, byte;
@@ -208,13 +248,10 @@ static void fill_fontinfo(FT_Face face, int enc, FILE *fp, int dpi, unsigned cha
     const union cptable *cptable;
     FT_SfntName sfntname;
     TT_OS2 *os2;
-
-#ifdef HAVE_FT_LOAD_SFNT_TABLE
     FT_ULong needed;
     eblcHeader_t *eblc;
     bitmapSizeTable_t *size_table;
     int num_sizes;
-#endif
 
     cptable = wine_cp_get_table(enc);
     if(!cptable)
@@ -229,30 +266,30 @@ static void fill_fontinfo(FT_Face face, int enc, FILE *fp, int dpi, unsigned cha
 
     ppem = face->size->metrics.y_ppem;
 
-#ifdef HAVE_FT_LOAD_SFNT_TABLE
     needed = 0;
-    if(FT_Load_Sfnt_Table(face, TTAG_EBLC, 0, NULL, &needed))
-        error("Can't find EBLC table\n");
-
-    eblc = malloc(needed);
-    FT_Load_Sfnt_Table(face, TTAG_EBLC, 0, (FT_Byte *)eblc, &needed);
+    if (load_sfnt_table(face, TTAG_EBLC, 0, NULL, &needed))
+        fprintf(stderr,"Can't find EBLC table\n");
+    else
+    {
+        eblc = malloc(needed);
+        load_sfnt_table(face, TTAG_EBLC, 0, (FT_Byte *)eblc, &needed);
 
-    num_sizes = GET_BE_DWORD(&eblc->numSizes);
+        num_sizes = GET_BE_DWORD(&eblc->numSizes);
 
-    size_table = (bitmapSizeTable_t *)(eblc + 1);
-    for(i = 0; i < num_sizes; i++)
-    {
-        if(size_table->hori.ascender - size_table->hori.descender == ppem)
+        size_table = (bitmapSizeTable_t *)(eblc + 1);
+        for(i = 0; i < num_sizes; i++)
         {
-            ascent = size_table->hori.ascender;
-            descent = -size_table->hori.descender;
-            break;
+            if(size_table->hori.ascender - size_table->hori.descender == ppem)
+            {
+                ascent = size_table->hori.ascender;
+                descent = -size_table->hori.descender;
+                break;
+            }
+            size_table++;
         }
-        size_table++;
-    }
 
-    free(eblc);
-#endif
+        free(eblc);
+    }
 
     /* Versions of fontforge prior to early 2006 have incorrect
        ascender values in the eblc table, so we won't find the 
@@ -272,9 +309,14 @@ static void fill_fontinfo(FT_Face face, int enc, FILE *fp, int dpi, unsigned cha
         error("Can't find M\n");
     il = ascent - (face->glyph->metrics.height >> 6);
 
-    /* Hack: Courier has no internal leading, nor do any Chinese fonts */
-    if(!strcmp(face->family_name, "Courier") || enc == 936 || enc == 950)
+    /* Hack: Courier has no internal leading, nor do any Chinese or Japanese fonts */
+    if(!strcmp(face->family_name, "Courier") || enc == 936 || enc == 950 || enc == 932)
         il = 0;
+    /* Japanese fonts have an external leading */
+    if(enc == 932)
+        el = 2;
+    else
+        el = 0;
 
     first_char = FT_Get_First_Char(face, &gi);
     if(first_char == 0xd) /* fontforge's first glyph is 0xd, we'll catch this and skip it */
@@ -331,7 +373,7 @@ static void fill_fontinfo(FT_Face face, int enc, FILE *fp, int dpi, unsigned cha
     fi.dfHorizRes = dpi;
     fi.dfAscent = ascent;
     fi.dfInternalLeading = il;
-    fi.dfExternalLeading = 0;
+    fi.dfExternalLeading = el;
     fi.dfItalic = (face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0;
     fi.dfUnderline = 0;
     fi.dfStrikeOut = 0;
@@ -462,6 +504,9 @@ int main(int argc, char **argv)
     if(FT_Init_FreeType(&lib))
         error("ft init failure\n");
 
+    FT_Version.major=FT_Version.minor=FT_Version.patch=-1;
+    FT_Library_Version(lib,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
+
     if(FT_New_Face(lib, argv[1], 0, &face)) {
         fprintf(stderr, "Can't open face\n");
         usage(argv);




More information about the wine-cvs mailing list