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

Hilko Bengen bengen at hilluzination.de
Wed Jun 13 16:37:56 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 |  113 +++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 82 insertions(+), 31 deletions(-)

diff --git a/tools/sfnt2fnt.c b/tools/sfnt2fnt.c
index df43ec0..df9260f 100644
--- a/tools/sfnt2fnt.c
+++ b/tools/sfnt2fnt.c
@@ -46,6 +46,8 @@
 
 #include "pshpack1.h"
 
+#include <endian.h>
+
 typedef struct
 {
     INT16 dfType;
@@ -378,7 +380,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 +572,50 @@ static struct fontinfo *fill_fontinfo( const char *face_name, int ppem, int enc,
     return info;
 }
 
+static void adjust_fontinfo( FONTINFO16 * fi )
+{
+    fi->dfType = htole16(fi->dfType);
+    fi->dfPoints = htole16(fi->dfPoints);
+    fi->dfVertRes = htole16(fi->dfVertRes);
+    fi->dfHorizRes = htole16(fi->dfHorizRes);
+    fi->dfAscent = htole16(fi->dfAscent);
+    fi->dfInternalLeading = htole16(fi->dfInternalLeading);
+    fi->dfExternalLeading = htole16(fi->dfExternalLeading);
+    fi->dfWeight = htole16(fi->dfWeight);
+    fi->dfPixWidth = htole16(fi->dfPixWidth);
+    fi->dfPixHeight = htole16(fi->dfPixHeight);
+    fi->dfAvgWidth = htole16(fi->dfAvgWidth);
+    fi->dfMaxWidth = htole16(fi->dfMaxWidth);
+    fi->dfWidthBytes = htole16(fi->dfWidthBytes);
+    fi->dfAspace = htole16(fi->dfAspace);
+    fi->dfBspace = htole16(fi->dfBspace);
+    fi->dfCspace = htole16(fi->dfCspace);
+    fi->dfDevice = htole32(fi->dfDevice);
+    fi->dfFace = htole32(fi->dfFace);
+    fi->dfBitsPointer = htole32(fi->dfBitsPointer);
+    fi->dfBitsOffset = htole32(fi->dfBitsOffset);
+    fi->dfFlags = htole32(fi->dfFlags);
+    fi->dfColorPointer = htole32(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 = htole16(tmp_hdr.dfVersion);
+    tmp_hdr.dfSize = htole32(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 = htole16(tmp_chartable[i].width);
+        tmp_chartable[i].offset = htole32(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 +671,7 @@ int main(int argc, char **argv)
     struct fontinfo **info;
     char *input_file;
     char **args;
+    short tmp16;
 
     args = parse_options( argc, argv );
 
@@ -696,21 +738,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 = htole16(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 = htole16(NE_FFLAGS_LIBMODULE | NE_FFLAGS_GUI);
+    NE_hdr.ne_cbnrestab = htole16(non_resident_name_len);
+    NE_hdr.ne_segtab = htole16(sizeof(NE_hdr));
+    NE_hdr.ne_rsrctab = htole16(sizeof(NE_hdr));
+    NE_hdr.ne_restab = htole16(resident_name_off);
+    NE_hdr.ne_modtab = htole16(module_ref_off);
+    NE_hdr.ne_imptab = htole16(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 = htole32(non_resident_name_off);
+    NE_hdr.ne_align = htole16(4);
     NE_hdr.ne_exetyp = NE_OSFLAGS_WINDOWS;
-    NE_hdr.ne_expver = 0x400;
+    NE_hdr.ne_expver = htole16(0x400);
 
     fontdir_off = (non_resident_name_off + non_resident_name_len + 15) & ~0xf;
     font_off = (fontdir_off + fontdir_len + 15) & ~0x0f;
@@ -749,34 +791,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 = htole16(4);
     fwrite(&align, sizeof(align), 1, ofp);
 
-    rc_type.type_id = NE_RSCTYPE_FONTDIR;
-    rc_type.count = 1;
+    rc_type.type_id = htole16(NE_RSCTYPE_FONTDIR);
+    rc_type.count = htole16(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 = htole16(fontdir_off >> 4);
+    rc_name.length = htole16((fontdir_len + 15) >> 4);
+    rc_name.flags = htole16(NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_PRELOAD);
+    rc_name.id = htole16(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 = htole16(NE_RSCTYPE_FONT);
+    rc_type.count = htole16(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 = htole16(font_off >> 4);
+        rc_name.length = htole16(len >> 4);
+        rc_name.flags = htole16(NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_SHAREABLE | NE_SEGFLAGS_DISCARDABLE);
+        rc_name.id = htole16(res);
         rc_name.handle = 0;
         rc_name.usage = 0;
         fwrite(&rc_name, sizeof(rc_name), 1, ofp);
@@ -812,12 +854,21 @@ int main(int argc, char **argv)
         fputc(0x00, ofp);
 
     /* FONTDIR resource */
-    fwrite(&num_files, sizeof(num_files), 1, ofp);
+    tmp16 = htole16(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 = htole16(res);
+        fwrite(&tmp16, sizeof(tmp16), 1, ofp);
+        sz = FIELD_OFFSET(FNT_HEADER,fi.dfBitsOffset);
+        memcpy(&tmp_hdr, &info[i]->hdr, sz);
+        tmp_hdr.dfVersion = htole16(tmp_hdr.dfVersion);
+        tmp_hdr.dfSize = htole32(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