[PATCH (try3)] sfnt2fnt: Fix broken .fon files on !x86 architectures

Hilko Bengen bengen at hilluzination.de
Mon Jun 18 16:27:49 CDT 2012


On Linux/PowerPC and Linux/Sparc, sfnt2fnt produced output that was
clearly broken due to endianess issues. Putting a few htole16()s here
and htole32()s there fix all the *.fon files but one (in the sense
that results are identical on x86 and PowerPC)...

... and bring out another problem that occurs on PowerPC, because
apparently char is unsigned unless specified otherwise. (Perhaps it
would be a good idea to specify signedness in the typedefs for CHAR,
SHORT, LONG in winnt.h?)
---
 tools/sfnt2fnt.c |  134 +++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 103 insertions(+), 31 deletions(-)

diff --git a/tools/sfnt2fnt.c b/tools/sfnt2fnt.c
index df43ec0..bc857a9 100644
--- a/tools/sfnt2fnt.c
+++ b/tools/sfnt2fnt.c
@@ -46,6 +46,29 @@
 
 #include "pshpack1.h"
 
+
+#include "basetsd.h"
+
+#if defined(WORDS_BIGENDIAN)
+static WORD switch_word_endianess(WORD x)
+{
+    return ( ( (x & 0xff) << 8) |
+	     ( (x & 0xff00) >> 8) );
+}
+static DWORD switch_dword_endianess(DWORD x)
+{
+    return ( ( (x & 0xff) << 24) |
+	     ( (x & 0xff00) << 8) |
+	     ( (x & 0xff0000) >> 8) |
+	     ( (x & 0xff000000) >> 24) );
+}
+# define H_TO_LE_16(_x) switch_word_endianess(_x)
+# define H_TO_LE_32(_x) switch_dword_endianess(_x)
+#else
+# define H_TO_LE_16(_x) (_x)
+# define H_TO_LE_32(_x) (_x)
+#endif
+
 typedef struct
 {
     INT16 dfType;
@@ -378,7 +401,7 @@ static struct fontinfo *fill_fontinfo( const char *face_name, int ppem, int enc,
         size_table = (bitmapSizeTable_t *)(eblc + 1);
         for(i = 0; i < num_sizes; i++)
         {
-            if(size_table->hori.ascender - size_table->hori.descender == ppem)
+            if( (signed char)size_table->hori.ascender - (signed char)size_table->hori.descender == ppem)
             {
                 ascent = size_table->hori.ascender;
                 break;
@@ -570,11 +593,50 @@ static struct fontinfo *fill_fontinfo( const char *face_name, int ppem, int enc,
     return info;
 }
 
+static void adjust_fontinfo( FONTINFO16 * fi )
+{
+    fi->dfType = H_TO_LE_16(fi->dfType);
+    fi->dfPoints = H_TO_LE_16(fi->dfPoints);
+    fi->dfVertRes = H_TO_LE_16(fi->dfVertRes);
+    fi->dfHorizRes = H_TO_LE_16(fi->dfHorizRes);
+    fi->dfAscent = H_TO_LE_16(fi->dfAscent);
+    fi->dfInternalLeading = H_TO_LE_16(fi->dfInternalLeading);
+    fi->dfExternalLeading = H_TO_LE_16(fi->dfExternalLeading);
+    fi->dfWeight = H_TO_LE_16(fi->dfWeight);
+    fi->dfPixWidth = H_TO_LE_16(fi->dfPixWidth);
+    fi->dfPixHeight = H_TO_LE_16(fi->dfPixHeight);
+    fi->dfAvgWidth = H_TO_LE_16(fi->dfAvgWidth);
+    fi->dfMaxWidth = H_TO_LE_16(fi->dfMaxWidth);
+    fi->dfWidthBytes = H_TO_LE_16(fi->dfWidthBytes);
+    fi->dfAspace = H_TO_LE_16(fi->dfAspace);
+    fi->dfBspace = H_TO_LE_16(fi->dfBspace);
+    fi->dfCspace = H_TO_LE_16(fi->dfCspace);
+    fi->dfDevice = H_TO_LE_32(fi->dfDevice);
+    fi->dfFace = H_TO_LE_32(fi->dfFace);
+    fi->dfBitsPointer = H_TO_LE_32(fi->dfBitsPointer);
+    fi->dfBitsOffset = H_TO_LE_32(fi->dfBitsOffset);
+    fi->dfFlags = H_TO_LE_32(fi->dfFlags);
+    fi->dfColorPointer = H_TO_LE_32(fi->dfColorPointer);
+}
+
 static void write_fontinfo( const struct fontinfo *info, FILE *fp )
 {
-    fwrite( &info->hdr, sizeof(info->hdr), 1, fp );
-    fwrite( info->dfCharTable + info->hdr.fi.dfFirstChar, sizeof(*info->dfCharTable),
-            ((unsigned char)info->hdr.fi.dfLastChar - (unsigned char)info->hdr.fi.dfFirstChar) + 3, fp );
+    FNT_HEADER tmp_hdr;
+    int num_chars, i;
+    CHAR_TABLE_ENTRY tmp_chartable[258];
+    memcpy(&tmp_hdr, &info->hdr, sizeof(info->hdr));
+    tmp_hdr.dfVersion = H_TO_LE_16(tmp_hdr.dfVersion);
+    tmp_hdr.dfSize = H_TO_LE_32(tmp_hdr.dfSize);
+    adjust_fontinfo(&(tmp_hdr.fi));
+    fwrite( &tmp_hdr, sizeof(info->hdr), 1, fp );
+    num_chars = ((unsigned char)info->hdr.fi.dfLastChar - (unsigned char)info->hdr.fi.dfFirstChar) + 3;
+
+    memcpy(&tmp_chartable, info->dfCharTable + info->hdr.fi.dfFirstChar, num_chars * sizeof(CHAR_TABLE_ENTRY));
+    for (i=0; i < num_chars; ++i) {
+        tmp_chartable[i].width = H_TO_LE_16(tmp_chartable[i].width);
+        tmp_chartable[i].offset = H_TO_LE_32(tmp_chartable[i].offset);
+    }
+    fwrite( tmp_chartable, sizeof(CHAR_TABLE_ENTRY), num_chars, fp );
     fwrite( info->data, info->hdr.dfSize - info->hdr.fi.dfBitsOffset, 1, fp );
 }
 
@@ -630,6 +692,7 @@ int main(int argc, char **argv)
     struct fontinfo **info;
     char *input_file;
     char **args;
+    short tmp16;
 
     args = parse_options( argc, argv );
 
@@ -696,21 +759,21 @@ int main(int argc, char **argv)
     non_resident_name_off = sizeof(MZ_hdr) + module_ref_off + sizeof(align);
 
     memset(&NE_hdr, 0, sizeof(NE_hdr));
-    NE_hdr.ne_magic = 0x454e;
+    NE_hdr.ne_magic = H_TO_LE_16(0x454e);
     NE_hdr.ne_ver = 5;
     NE_hdr.ne_rev = 1;
-    NE_hdr.ne_flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_GUI;
-    NE_hdr.ne_cbnrestab = non_resident_name_len;
-    NE_hdr.ne_segtab = sizeof(NE_hdr);
-    NE_hdr.ne_rsrctab = sizeof(NE_hdr);
-    NE_hdr.ne_restab = resident_name_off;
-    NE_hdr.ne_modtab = module_ref_off;
-    NE_hdr.ne_imptab = module_ref_off;
+    NE_hdr.ne_flags = H_TO_LE_16(NE_FFLAGS_LIBMODULE | NE_FFLAGS_GUI);
+    NE_hdr.ne_cbnrestab = H_TO_LE_16(non_resident_name_len);
+    NE_hdr.ne_segtab = H_TO_LE_16(sizeof(NE_hdr));
+    NE_hdr.ne_rsrctab = H_TO_LE_16(sizeof(NE_hdr));
+    NE_hdr.ne_restab = H_TO_LE_16(resident_name_off);
+    NE_hdr.ne_modtab = H_TO_LE_16(module_ref_off);
+    NE_hdr.ne_imptab = H_TO_LE_16(module_ref_off);
     NE_hdr.ne_enttab = NE_hdr.ne_modtab;
-    NE_hdr.ne_nrestab = non_resident_name_off;
-    NE_hdr.ne_align = 4;
+    NE_hdr.ne_nrestab = H_TO_LE_32(non_resident_name_off);
+    NE_hdr.ne_align = H_TO_LE_16(4);
     NE_hdr.ne_exetyp = NE_OSFLAGS_WINDOWS;
-    NE_hdr.ne_expver = 0x400;
+    NE_hdr.ne_expver = H_TO_LE_16(0x400);
 
     fontdir_off = (non_resident_name_off + non_resident_name_len + 15) & ~0xf;
     font_off = (fontdir_off + fontdir_len + 15) & ~0x0f;
@@ -749,34 +812,34 @@ int main(int argc, char **argv)
     fwrite(MZ_hdr, sizeof(MZ_hdr), 1, ofp);
     fwrite(&NE_hdr, sizeof(NE_hdr), 1, ofp);
 
-    align = 4;
+    align = H_TO_LE_16(4);
     fwrite(&align, sizeof(align), 1, ofp);
 
-    rc_type.type_id = NE_RSCTYPE_FONTDIR;
-    rc_type.count = 1;
+    rc_type.type_id = H_TO_LE_16(NE_RSCTYPE_FONTDIR);
+    rc_type.count = H_TO_LE_16(1);
     rc_type.resloader = 0;
     fwrite(&rc_type, sizeof(rc_type), 1, ofp);
 
-    rc_name.offset = fontdir_off >> 4;
-    rc_name.length = (fontdir_len + 15) >> 4;
-    rc_name.flags = NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_PRELOAD;
-    rc_name.id = resident_name_off - sizeof("FONTDIR") - NE_hdr.ne_rsrctab;
+    rc_name.offset = H_TO_LE_16(fontdir_off >> 4);
+    rc_name.length = H_TO_LE_16((fontdir_len + 15) >> 4);
+    rc_name.flags = H_TO_LE_16(NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_PRELOAD);
+    rc_name.id = H_TO_LE_16(resident_name_off - sizeof("FONTDIR") - sizeof(NE_hdr));
     rc_name.handle = 0;
     rc_name.usage = 0;
     fwrite(&rc_name, sizeof(rc_name), 1, ofp);
 
-    rc_type.type_id = NE_RSCTYPE_FONT;
-    rc_type.count = num_files;
+    rc_type.type_id = H_TO_LE_16(NE_RSCTYPE_FONT);
+    rc_type.count = H_TO_LE_16(num_files);
     rc_type.resloader = 0;
     fwrite(&rc_type, sizeof(rc_type), 1, ofp);
 
     for(res = first_res | 0x8000, i = 0; i < num_files; i++, res++) {
         int len = (info[i]->hdr.dfSize + 15) & ~0xf;
 
-        rc_name.offset = font_off >> 4;
-        rc_name.length = len >> 4;
-        rc_name.flags = NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_SHAREABLE | NE_SEGFLAGS_DISCARDABLE;
-        rc_name.id = res;
+        rc_name.offset = H_TO_LE_16(font_off >> 4);
+        rc_name.length = H_TO_LE_16(len >> 4);
+        rc_name.flags = H_TO_LE_16(NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_SHAREABLE | NE_SEGFLAGS_DISCARDABLE);
+        rc_name.id = H_TO_LE_16(res);
         rc_name.handle = 0;
         rc_name.usage = 0;
         fwrite(&rc_name, sizeof(rc_name), 1, ofp);
@@ -812,12 +875,21 @@ int main(int argc, char **argv)
         fputc(0x00, ofp);
 
     /* FONTDIR resource */
-    fwrite(&num_files, sizeof(num_files), 1, ofp);
+    tmp16 = H_TO_LE_16(num_files);
+    fwrite(&tmp16, sizeof(tmp16), 1, ofp);
 
     for(res = first_res, i = 0; i < num_files; i++, res++) {
+        FNT_HEADER tmp_hdr;
+        int sz;
         const char *name = get_face_name( info[i] );
-        fwrite(&res, sizeof(res), 1, ofp);
-        fwrite(&info[i]->hdr, FIELD_OFFSET(FNT_HEADER,fi.dfBitsOffset), 1, ofp);
+        tmp16 = H_TO_LE_16(res);
+        fwrite(&tmp16, sizeof(tmp16), 1, ofp);
+        sz = FIELD_OFFSET(FNT_HEADER,fi.dfBitsOffset);
+        memcpy(&tmp_hdr, &info[i]->hdr, sz);
+        tmp_hdr.dfVersion = H_TO_LE_16(tmp_hdr.dfVersion);
+        tmp_hdr.dfSize = H_TO_LE_32(tmp_hdr.dfSize);
+        adjust_fontinfo(&(tmp_hdr.fi));
+        fwrite(&tmp_hdr, FIELD_OFFSET(FNT_HEADER,fi.dfBitsOffset), 1, ofp);
         fputc(0x00, ofp);
         fwrite(name, strlen(name) + 1, 1, ofp);
     }
-- 
1.7.10




More information about the wine-patches mailing list