fixed os/2 descent
[swftools.git] / lib / ttf.c
index 5aa6e10..3349aa9 100644 (file)
--- a/lib/ttf.c
+++ b/lib/ttf.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <memory.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <memory.h>
+#include <assert.h>
 #include "log.h"
 #include "os.h"
 #include "q.h"
 #include "log.h"
 #include "os.h"
 #include "q.h"
@@ -117,6 +118,10 @@ static void readBlock(memreader_t*r, void*dest, int len)
        r->pos += len;
     }
 }
        r->pos += len;
     }
 }
+static void reader_reset(memreader_t*r)
+{
+    r->pos;
+}
 #define INIT_READ(r,data,length,pos) memreader_t r = {(data),(pos),(length)};
 
 static void expand(ttf_table_t*w, int newsize)
 #define INIT_READ(r,data,length,pos) memreader_t r = {(data),(pos),(length)};
 
 static void expand(ttf_table_t*w, int newsize)
@@ -139,6 +144,13 @@ static inline void writeU16(ttf_table_t*w, unsigned short v)
     w->data[w->len++] = v>>8;
     w->data[w->len++] = v;
 }
     w->data[w->len++] = v>>8;
     w->data[w->len++] = v;
 }
+static inline void writeU16_LE(ttf_table_t*w, unsigned short v)
+{
+    if(w->memsize<w->len+2)
+       expand(w, w->len+2);
+    w->data[w->len++] = v;
+    w->data[w->len++] = v>>8;
+}
 #define writeS16 writeU16
 static inline void writeU32(ttf_table_t*w, unsigned long v)
 {
 #define writeS16 writeU16
 static inline void writeU32(ttf_table_t*w, unsigned long v)
 {
@@ -149,6 +161,15 @@ static inline void writeU32(ttf_table_t*w, unsigned long v)
     w->data[w->len++] = v>>8;
     w->data[w->len++] = v;
 }
     w->data[w->len++] = v>>8;
     w->data[w->len++] = v;
 }
+static inline void writeU32_LE(ttf_table_t*w, unsigned long v)
+{
+    if(w->memsize<w->len+4)
+       expand(w, w->len+4);
+    w->data[w->len++] = v;
+    w->data[w->len++] = v>>8;
+    w->data[w->len++] = v>>16;
+    w->data[w->len++] = v>>24;
+}
 static inline void writeBlock(ttf_table_t*w, void*data, int len)
 {
     if(w->memsize<w->len+len)
 static inline void writeBlock(ttf_table_t*w, void*data, int len)
 {
     if(w->memsize<w->len+len)
@@ -179,7 +200,7 @@ ttf_table_t*ttf_addtable(ttf_t*ttf, U32 id)
        before->len = 0;
        return before;
     }
        before->len = 0;
        return before;
     }
-    
+
     if(!after) {
        t->next = ttf->tables;
        ttf->tables = t;
     if(!after) {
        t->next = ttf->tables;
        ttf->tables = t;
@@ -196,7 +217,7 @@ ttf_table_t*ttf_find_table(ttf_t*ttf, U32 id)
 {
     ttf_table_t*table = ttf->tables;
     while(table) {
 {
     ttf_table_t*table = ttf->tables;
     while(table) {
-       if(table->id == id) 
+       if(table->id == id)
            return table;
        table = table->next;
     }
            return table;
        table = table->next;
     }
@@ -207,9 +228,9 @@ void ttf_table_delete(ttf_t*ttf, ttf_table_t*table)
     if(ttf && ttf->tables == table) {
        ttf->tables = table->next;
     }
     if(ttf && ttf->tables == table) {
        ttf->tables = table->next;
     }
-    if(table->prev) 
+    if(table->prev)
        table->prev->next = table->next;
        table->prev->next = table->next;
-    if(table->next) 
+    if(table->next)
        table->next->prev = table->prev;
     free(table->data);
     free(table);
        table->next->prev = table->prev;
     free(table->data);
     free(table);
@@ -284,12 +305,12 @@ static int head_parse(ttf_t*ttf, memreader_t*r)
 {
     ttf->head = rfx_calloc(sizeof(table_head_t));
     U32 version = readU32(r);
 {
     ttf->head = rfx_calloc(sizeof(table_head_t));
     U32 version = readU32(r);
-    if(version!=VERSION_1_0) 
+    if(version!=VERSION_1_0)
        msg("<warning> Font HEAD has unknown version %08x", version);
     U32 revision = readU32(r);
     U32 checksum2 = readU32(r);
     U32 magic = readU32(r);
        msg("<warning> Font HEAD has unknown version %08x", version);
     U32 revision = readU32(r);
     U32 checksum2 = readU32(r);
     U32 magic = readU32(r);
-    if(magic!=0x5f0f3cf5) 
+    if(magic!=0x5f0f3cf5)
        msg("<warning> Font HEAD has unknown magic number %08x", magic);
     ttf->head->flags = readU16(r);
     ttf->head->units_per_em = readU16(r);
        msg("<warning> Font HEAD has unknown magic number %08x", magic);
     ttf->head->flags = readU16(r);
     ttf->head->units_per_em = readU16(r);
@@ -368,7 +389,7 @@ static table_os2_t*os2_new(ttf_t*ttf)
     /* that's what everybody seems to fill in */
     os2->usWeightClass = 400;
     os2->usWidthClass = 5;
     /* that's what everybody seems to fill in */
     os2->usWeightClass = 400;
     os2->usWidthClass = 5;
-   
+
     if(ttf->head) {
        int advance = (ttf->head->xmax - ttf->head->xmin)/2;
        int height = (ttf->head->xmax - ttf->head->xmin);
     if(ttf->head) {
        int advance = (ttf->head->xmax - ttf->head->xmin)/2;
        int height = (ttf->head->xmax - ttf->head->xmin);
@@ -384,8 +405,8 @@ static table_os2_t*os2_new(ttf_t*ttf)
        os2->ySuperscriptYOffset = (ttf->head->ymax - ttf->head->ymin)/2;
        os2->yStrikeoutSize = ttf->head->units_per_em / 10;
        os2->yStrikeoutPosition = ymid;
        os2->ySuperscriptYOffset = (ttf->head->ymax - ttf->head->ymin)/2;
        os2->yStrikeoutSize = ttf->head->units_per_em / 10;
        os2->yStrikeoutPosition = ymid;
-       os2->usWinAscent = ttf->head->ymax;
-       os2->usWinDescent = ttf->head->ymin<0?0:ttf->head->ymin;
+       os2->usWinAscent = ttf->head->ymax>0?ttf->head->ymax:0;
+       os2->usWinDescent = ttf->head->ymin<0?-ttf->head->ymin:0;
        os2->sxHeight = ymid;
        os2->sCapHeight = height*2/3;
     }
        os2->sxHeight = ymid;
        os2->sCapHeight = height*2/3;
     }
@@ -477,7 +498,7 @@ static table_os2_t*os2_parse(memreader_t*r)
     os2->usDefaultChar = readU16(r);
     os2->usBreakChar = readU16(r);
     os2->usMaxContext = readU16(r);
     os2->usDefaultChar = readU16(r);
     os2->usBreakChar = readU16(r);
     os2->usMaxContext = readU16(r);
-    
+
     if(r->pos < r->size) {
        msg("<warning> Leftover bytes (%d) in OS2 tag", r->size - r->pos);
     }
     if(r->pos < r->size) {
        msg("<warning> Leftover bytes (%d) in OS2 tag", r->size - r->pos);
     }
@@ -625,7 +646,7 @@ static table_maxp_t* maxp_parse(ttf_t*ttf, memreader_t*r)
 {
     U32 version = readU32(r);
     ttf->num_glyphs = readU16(r);
 {
     U32 version = readU32(r);
     ttf->num_glyphs = readU16(r);
-    /* according to freetype, older fonts (version<0x10000) 
+    /* according to freetype, older fonts (version<0x10000)
        apparently only contain the number of glyphs. this is
        rather rare, though. */
     if(version<0x10000 && r->size==6) return 0;
        apparently only contain the number of glyphs. this is
        rather rare, though. */
     if(version<0x10000 && r->size==6) return 0;
@@ -809,7 +830,7 @@ static void mtx_parse(memreader_t*r, ttf_t*ttf, int num_advances)
        rest = ttf->num_glyphs-num_advances;
     }
     for(t=0;t<rest;t++) {
        rest = ttf->num_glyphs-num_advances;
     }
     for(t=0;t<rest;t++) {
-       ttf->glyphs[t].advance = old_advance; 
+       ttf->glyphs[t].advance = old_advance;
        ttf->glyphs[t].bearing = readS16(r);
     }
 }
        ttf->glyphs[t].bearing = readS16(r);
     }
 }
@@ -929,15 +950,15 @@ static int parse_simple_glyph(ttf_t*ttf, memreader_t*r, int num_contours, int gl
        glyph->code_size = code_len;
     }
 
        glyph->code_size = code_len;
     }
 
-    if(!endpoints) 
+    if(!endpoints)
        return 1;
 
        return 1;
 
-    /*msg("<notice> TTF Glyph %d) code_size=%d num_contours=%d glyph->num_points=%d %d/%d/%d/%d", 
+    /*msg("<notice> TTF Glyph %d) code_size=%d num_contours=%d glyph->num_points=%d %d/%d/%d/%d",
            glyphnr, code_len, num_contours, glyph->num_points,
            xmin, ymin, xmax, ymax);*/
     INIT_READ(fx, r->mem, r->size, r->pos);
     INIT_READ(fy, r->mem, r->size, r->pos);
            glyphnr, code_len, num_contours, glyph->num_points,
            xmin, ymin, xmax, ymax);*/
     INIT_READ(fx, r->mem, r->size, r->pos);
     INIT_READ(fy, r->mem, r->size, r->pos);
-    
+
     glyph->num_points = endpoints[num_contours-1] + 1;
     glyph->points = rfx_calloc(sizeof(ttfpoint_t)*glyph->num_points);
 
     glyph->num_points = endpoints[num_contours-1] + 1;
     glyph->points = rfx_calloc(sizeof(ttfpoint_t)*glyph->num_points);
 
@@ -953,7 +974,7 @@ static int parse_simple_glyph(ttf_t*ttf, memreader_t*r, int num_contours, int gl
            return 0;
        }
        int count = 1;
            return 0;
        }
        int count = 1;
-       if(flag & 0x08) 
+       if(flag & 0x08)
            count += readU8(r);
        if(count+num>glyph->num_points) {
            msg("<warning> Bad count (%d) in glyph (%d) (at pos %d)", count, glyphnr, num);
            count += readU8(r);
        if(count+num>glyph->num_points) {
            msg("<warning> Bad count (%d) in glyph (%d) (at pos %d)", count, glyphnr, num);
@@ -982,7 +1003,7 @@ static int parse_simple_glyph(ttf_t*ttf, memreader_t*r, int num_contours, int gl
            if((flag&0x12) == 0x12) x += readU8(r);
            else if((flag&0x12) == 0x02) x -= readU8(r);
            else if((flag&0x12) == 0x00) x += readS16(r);
            if((flag&0x12) == 0x12) x += readU8(r);
            else if((flag&0x12) == 0x02) x -= readU8(r);
            else if((flag&0x12) == 0x00) x += readS16(r);
-           
+
            glyph->points[num].x = x;
            U8 f = flag&GLYPH_ON_CURVE;
            if(is_start) f|=GLYPH_CONTOUR_START;
            glyph->points[num].x = x;
            U8 f = flag&GLYPH_ON_CURVE;
            if(is_start) f|=GLYPH_CONTOUR_START;
@@ -992,7 +1013,7 @@ static int parse_simple_glyph(ttf_t*ttf, memreader_t*r, int num_contours, int gl
            is_start = is_end;
        } while(--count);
     }
            is_start = is_end;
        } while(--count);
     }
-    
+
     /* parse flag array (3rd pass) and y coordinates */
     num=0;
     int y = 0;
     /* parse flag array (3rd pass) and y coordinates */
     num=0;
     int y = 0;
@@ -1020,7 +1041,7 @@ static void glyf_parse(memreader_t*rr, ttf_t*ttf, U32*loca)
        if(loca[t]==loca[t+1] || loca[t]==r.size)
            continue; //empty glyph
        if(r.pos+10>r.size) {
        if(loca[t]==loca[t+1] || loca[t]==r.size)
            continue; //empty glyph
        if(r.pos+10>r.size) {
-           msg("<warning> Truncated glyph entry %d/%d (or bad loca entry %d/%d, next loca: %d)", 
+           msg("<warning> Truncated glyph entry %d/%d (or bad loca entry %d/%d, next loca: %d)",
                    t, ttf->num_glyphs, loca[t], r.size, loca[t+1]);
            break;
        }
                    t, ttf->num_glyphs, loca[t], r.size, loca[t+1]);
            break;
        }
@@ -1029,7 +1050,7 @@ static void glyf_parse(memreader_t*rr, ttf_t*ttf, U32*loca)
        ttf->glyphs[t].ymin = readS16(&r);
        ttf->glyphs[t].xmax = readS16(&r);
        ttf->glyphs[t].ymax = readS16(&r);
        ttf->glyphs[t].ymin = readS16(&r);
        ttf->glyphs[t].xmax = readS16(&r);
        ttf->glyphs[t].ymax = readS16(&r);
-       
+
        if(num_contours<0) {
            if(warn_about_compound_glyphs)
                msg("<error> Compound glyphs not supported yet");
        if(num_contours<0) {
            if(warn_about_compound_glyphs)
                msg("<error> Compound glyphs not supported yet");
@@ -1049,7 +1070,7 @@ void write_simple_glyph(ttf_table_t*w, ttfglyph_t*g)
        if(g->points[s].flags&GLYPH_CONTOUR_END)
            writeU16(w, s);
     }
        if(g->points[s].flags&GLYPH_CONTOUR_END)
            writeU16(w, s);
     }
-    
+
     /* bytecode */
     writeU16(w, g->code_size);
     if(g->code_size)
     /* bytecode */
     writeU16(w, g->code_size);
     if(g->code_size)
@@ -1150,7 +1171,7 @@ U32* glyf_write(ttf_t* ttf, ttf_table_t*w)
        writeS16(w, g->ymin);
        writeS16(w, g->xmax);
        writeS16(w, g->ymax);
        writeS16(w, g->ymin);
        writeS16(w, g->xmax);
        writeS16(w, g->ymax);
-       
+
        if(!num_contours) {
            /* some ttf parsers can't deal with zero contours, so in the case
               of an empty glyph, write a single point (0,0) */
        if(!num_contours) {
            /* some ttf parsers can't deal with zero contours, so in the case
               of an empty glyph, write a single point (0,0) */
@@ -1183,13 +1204,13 @@ void glyf_dump(ttf_t* ttf)
            printf("%d/%d/0x%02x", g->points[s].x, g->points[s].y, g->points[s].flags);
        }
        printf(")\n");
            printf("%d/%d/0x%02x", g->points[s].x, g->points[s].y, g->points[s].flags);
        }
        printf(")\n");
-       if(g->code_size) 
+       if(g->code_size)
            hexdump(g->code, g->code_size, "  ");
     }
 }
 void glyf_delete(ttf_t* ttf)
 {
            hexdump(g->code, g->code_size, "  ");
     }
 }
 void glyf_delete(ttf_t* ttf)
 {
-    if(!ttf->glyphs) 
+    if(!ttf->glyphs)
        return;
     int t;
     for(t=0;t<ttf->num_glyphs;t++) {
        return;
     int t;
     for(t=0;t<ttf->num_glyphs;t++) {
@@ -1240,7 +1261,7 @@ void cmap_parse(memreader_t*r, ttf_t*ttf)
                         platform==3 && encoding == 1 ||
                         platform==3 && encoding == 10;
 
                         platform==3 && encoding == 1 ||
                         platform==3 && encoding == 10;
 
-       if(!is_unicode) 
+       if(!is_unicode)
            continue;
 
        INIT_READ(t, r->mem, r->size, offset);
            continue;
 
        INIT_READ(t, r->mem, r->size, offset);
@@ -1265,7 +1286,7 @@ void cmap_parse(memreader_t*r, ttf_t*ttf)
                ttf->unicode[s] = readU8(&t);
            }
        } else if(format == 4) {
                ttf->unicode[s] = readU8(&t);
            }
        } else if(format == 4) {
-           U16 segment_count = readU16(&t); 
+           U16 segment_count = readU16(&t);
            if(segment_count&1) {
                msg("<error> Bad segmentx2 count %d", segment_count);
                continue;
            if(segment_count&1) {
                msg("<error> Bad segmentx2 count %d", segment_count);
                continue;
@@ -1287,8 +1308,8 @@ void cmap_parse(memreader_t*r, ttf_t*ttf)
                U16 delta = readU16(&r_delta);
                U16 range = readU16(&r_range);
                if(start==0xffff && end==0xffff && delta==1) {
                U16 delta = readU16(&r_delta);
                U16 range = readU16(&r_range);
                if(start==0xffff && end==0xffff && delta==1) {
-                   /* this is a common (maybe even required) occurence in fonts 
-                      which explicitly map "unicode undefined" (0xffff) to 
+                   /* this is a common (maybe even required) occurence in fonts
+                      which explicitly map "unicode undefined" (0xffff) to
                       "glyph undefined" (0).
                       We don't want to blow our unicode table up to 65536 just
                       because of this, so ignore this entry.
                       "glyph undefined" (0).
                       We don't want to blow our unicode table up to 65536 just
                       because of this, so ignore this entry.
@@ -1324,7 +1345,7 @@ static int segment_size(unicode_t*unicode, int pos, int size)
        if(!unicode[s])
            count++;
        if(count>4) {
        if(!unicode[s])
            count++;
        if(count>4) {
-           /* a segment costs us 8 bytes, so for more than 4 consecutive 
+           /* a segment costs us 8 bytes, so for more than 4 consecutive
               zero entries (16 bit each) in the glyph index array,
               it pays off to start a new segment */
            break;
               zero entries (16 bit each) in the glyph index array,
               it pays off to start a new segment */
            break;
@@ -1373,7 +1394,7 @@ void cmap_write(ttf_t* ttf, ttf_table_t*w)
     num_segments++; // account for 0xffff mapping
 
     int glyphmap_start = w->len+2+num_segments*8;
     num_segments++; // account for 0xffff mapping
 
     int glyphmap_start = w->len+2+num_segments*8;
-    
+
     int t;
     int end_pos = w->len;
     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //end array
     int t;
     int end_pos = w->len;
     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //end array
@@ -1384,10 +1405,29 @@ void cmap_write(ttf_t* ttf, ttf_table_t*w)
     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //delta array
     int range_pos = w->len;
     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //range array
     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //delta array
     int range_pos = w->len;
     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //range array
-           
-    w->data[num_segments_pos]=(num_segments*2)>>8;
-    w->data[num_segments_pos+1]=(num_segments*2);
-    
+
+    /* backpatch number of segments */
+    w->data[num_segments_pos++]=(num_segments*2)>>8;
+    w->data[num_segments_pos++]=(num_segments*2);
+    /* backpatch search range */
+    int tmp = num_segments;
+    int search_range = 0;
+    while(tmp) {
+       search_range = tmp;
+       tmp = tmp&(tmp-1);
+    }
+    w->data[num_segments_pos++]=(search_range*2)>>8;
+    w->data[num_segments_pos++]=(search_range*2);
+    /* backpatch entry selector */
+    int entry_selector = 0;
+    while(tmp>1) {tmp>>=1;entry_selector++;}
+    w->data[num_segments_pos++]=entry_selector>>8;
+    w->data[num_segments_pos++]=entry_selector;
+    /* backpatch range shift */
+    int range_shift = num_segments*2 - search_range;
+    w->data[num_segments_pos++]=range_shift>>8;
+    w->data[num_segments_pos++]=range_shift;
+
     pos=0;
     num_segments = 0;
     while(pos < ttf->unicode_size) {
     pos=0;
     num_segments = 0;
     while(pos < ttf->unicode_size) {
@@ -1450,12 +1490,19 @@ void cmap_delete(ttf_t*ttf)
     }
     ttf->unicode_size=0;
 }
     }
     ttf->unicode_size=0;
 }
+static char*readString(memreader_t*r, int len)
+{
+    char*s = malloc(len+1);
+    readBlock(r, s, len);
+    s[len] = 0;
+    return s;
+}
 void name_parse(memreader_t*r, ttf_t*ttf)
 {
     U16 format = readU16(r);
     U16 count = readU16(r);
     U16 offset = readU16(r);
 void name_parse(memreader_t*r, ttf_t*ttf)
 {
     U16 format = readU16(r);
     U16 count = readU16(r);
     U16 offset = readU16(r);
-   
+
     int t;
     for(t=0;t<count;t++) {
        U16 platform = readU16(r);
     int t;
     for(t=0;t<count;t++) {
        U16 platform = readU16(r);
@@ -1464,37 +1511,114 @@ void name_parse(memreader_t*r, ttf_t*ttf)
        U16 name_id = readU16(r);
        U16 len = readU16(r);
        U16 offset_2 = readU16(r);
        U16 name_id = readU16(r);
        U16 len = readU16(r);
        U16 offset_2 = readU16(r);
+
+       INIT_READ(ss, r->mem, r->size, offset+offset_2);
+       if(!(platform==0 || (platform==1 && encoding==0)))
+               continue;
+
+       INIT_READ(s, r->mem, r->size, offset+offset_2);
+
+       if(name_id==1) {
+           if(ttf->family_name) free(ttf->family_name);
+           ttf->family_name = readString(&s, len);
+       }
+       if(name_id==2) {
+           if(ttf->subfamily_name) free(ttf->subfamily_name);
+           ttf->subfamily_name = readString(&s, len);
+       }
+       if(name_id==3) {
+           if(ttf->version_string) free(ttf->version_string);
+           ttf->version_string = readString(&s, len);
+       }
        if(name_id==4) {
        if(name_id==4) {
-           if(ttf->name)
-               free(ttf->name);
-           ttf->name = strdup_n(&r->mem[offset+offset_2], len);
+           if(ttf->full_name) free(ttf->full_name);
+           ttf->full_name = readString(&s, len);
        }
     }
 }
 void name_write(ttf_t*ttf, ttf_table_t*table)
 {
        }
     }
 }
 void name_write(ttf_t*ttf, ttf_table_t*table)
 {
+    char*strings[4] = {ttf->family_name, ttf->subfamily_name, ttf->version_string, ttf->full_name};
+    int codes[4] = {1,2,3,4};
+
     writeU16(table, 0); //format
     writeU16(table, 0); //format
-    writeU16(table, 1); //count
-    int offset = 18;
-    writeU16(table, offset); //offset
-
-    writeU16(table, 1); //platform id
-    writeU16(table, 0); //encoding id
-    writeU16(table, 0); //language
-    writeU16(table, 4); //4: full name
-    int len = strlen(ttf->name);
-    writeU16(table, len);
-    writeU16(table, table->len+2 - offset);
+    int count = 0;
     int t;
     int t;
-    for(t=0;t<len;t++) {
-       writeU8(table, ttf->name[t]);
+    int nr = sizeof(strings)/sizeof(strings[0]);
+
+    for(t=0;t<nr;t++) {
+       if(strings[t])
+           count+=2;
+    }
+    writeU16(table, count); //count
+
+    int offset_pos = table->len;
+    writeU16(table, 0); //offset (will be filled in later)
+
+    /* Windows expects the name table to be sorted by platform/encoding/language/name_id */
+    int offset = 0;
+    for(t=0;t<nr;t++) {
+       if(strings[t]) {
+           writeU16(table, 1); //platform id (mac)
+           writeU16(table, 0); //encoding id (latin-1)
+           writeU16(table, 0); //language (english)
+           writeU16(table, codes[t]);
+           int len = strlen(strings[t]);
+           writeU16(table, len);
+           writeU16(table, offset);
+           offset += len;
+       }
+    }
+    for(t=0;t<nr;t++) {
+       if(strings[t]) {
+           writeU16(table, 3); //platform id (windows)
+           writeU16(table, 1); //encoding id (ucs-2)
+           writeU16(table, 0x409); //language (US)
+           writeU16(table, codes[t]);
+           int len2 = strlen(strings[t]) * 2;
+           writeU16(table, len2);
+           writeU16(table, offset);
+           offset += len2;
+       }
+    }
+
+    table->data[offset_pos] = table->len>>8;
+    table->data[offset_pos+1] = table->len;
+
+    for(t=0;t<nr;t++) {
+       if(strings[t]) {
+           int len = strlen(strings[t]);
+           writeBlock(table, strings[t], len);
+       }
+    }
+    for(t=0;t<nr;t++) {
+       if(strings[t]) {
+           int s;
+           int len = strlen(strings[t]);
+           for(s=0;s<len;s++) {
+               writeU8(table, 0);
+               writeU8(table, strings[t][s]);
+           }
+       }
     }
 }
 void name_delete(ttf_t*ttf)
 {
     }
 }
 void name_delete(ttf_t*ttf)
 {
-    if(ttf->name) {
-       free(ttf->name);
-       ttf->name=0;
+    if(ttf->full_name) {
+       free(ttf->full_name);
+       ttf->full_name=0;
+    }
+    if(ttf->family_name) {
+       free(ttf->family_name);
+       ttf->family_name=0;
+    }
+    if(ttf->subfamily_name) {
+       free(ttf->subfamily_name);
+       ttf->subfamily_name=0;
+    }
+    if(ttf->version_string) {
+       free(ttf->version_string);
+       ttf->version_string=0;
     }
 }
 
     }
 }
 
@@ -1549,7 +1673,7 @@ static int ttf_parse_tables(ttf_t*ttf)
     INIT_READ(m, table->data, table->len, 0);
     int loc_index = head_parse(ttf, &m);
     ttf_table_delete(ttf, table);
     INIT_READ(m, table->data, table->len, 0);
     int loc_index = head_parse(ttf, &m);
     ttf_table_delete(ttf, table);
-    
+
     table = ttf_find_table(ttf, TAG_MAXP);
     if(!table) {
        msg("<error> Font has no maxp table");
     table = ttf_find_table(ttf, TAG_MAXP);
     if(!table) {
        msg("<error> Font has no maxp table");
@@ -1558,7 +1682,7 @@ static int ttf_parse_tables(ttf_t*ttf)
     INIT_READ(m2, table->data, table->len, 0);
     ttf->maxp = maxp_parse(ttf, &m2);
     ttf_table_delete(ttf, table);
     INIT_READ(m2, table->data, table->len, 0);
     ttf->maxp = maxp_parse(ttf, &m2);
     ttf_table_delete(ttf, table);
-    
+
     if(!ttf->num_glyphs) {
        msg("<error> Invalid number of characters");
        return 0;
     if(!ttf->num_glyphs) {
        msg("<error> Invalid number of characters");
        return 0;
@@ -1572,12 +1696,13 @@ static int ttf_parse_tables(ttf_t*ttf)
         ttf_table_delete(ttf, table);
     }
 
         ttf_table_delete(ttf, table);
     }
 
+
     table = ttf_find_table(ttf, TAG_HHEA);
     if(table) {
        INIT_READ(m, table->data, table->len, 0);
        int num_advances = hea_parse(&m, ttf);
         ttf_table_delete(ttf, table);
     table = ttf_find_table(ttf, TAG_HHEA);
     if(table) {
        INIT_READ(m, table->data, table->len, 0);
        int num_advances = hea_parse(&m, ttf);
         ttf_table_delete(ttf, table);
-       
+
        table = ttf_find_table(ttf, TAG_HMTX);
        if(table) {
            INIT_READ(m, table->data, table->len, 0);
        table = ttf_find_table(ttf, TAG_HMTX);
        if(table) {
            INIT_READ(m, table->data, table->len, 0);
@@ -1615,25 +1740,25 @@ static int ttf_parse_tables(ttf_t*ttf)
        }
        free(loca);
     }
        }
        free(loca);
     }
-    
+
     table = ttf_find_table(ttf, TAG_CMAP);
     if(table) {
        INIT_READ(m, table->data, table->len, 0);
        cmap_parse(&m, ttf);
        ttf_table_delete(ttf, table);
     }
     table = ttf_find_table(ttf, TAG_CMAP);
     if(table) {
        INIT_READ(m, table->data, table->len, 0);
        cmap_parse(&m, ttf);
        ttf_table_delete(ttf, table);
     }
-    
-    table = ttf_find_table(ttf, TAG_NAME);
+
+    table = ttf_find_table(ttf, TAG_POST);
     if(table) {
        INIT_READ(m, table->data, table->len, 0);
     if(table) {
        INIT_READ(m, table->data, table->len, 0);
-       name_parse(&m, ttf);
+       post_parse(&m, ttf);
        ttf_table_delete(ttf, table);
     }
 
        ttf_table_delete(ttf, table);
     }
 
-    table = ttf_find_table(ttf, TAG_POST);
+    table = ttf_find_table(ttf, TAG_NAME);
     if(table) {
        INIT_READ(m, table->data, table->len, 0);
     if(table) {
        INIT_READ(m, table->data, table->len, 0);
-       post_parse(&m, ttf);
+       name_parse(&m, ttf);
        ttf_table_delete(ttf, table);
     }
 
        ttf_table_delete(ttf, table);
     }
 
@@ -1642,43 +1767,58 @@ static int ttf_parse_tables(ttf_t*ttf)
 static void ttf_collapse_tables(ttf_t*ttf)
 {
     ttf_table_t*table;
 static void ttf_collapse_tables(ttf_t*ttf)
 {
     ttf_table_t*table;
-   
-    table = ttf_addtable(ttf, TAG_MAXP);
-    maxp_write(ttf, table);
-    maxp_delete(ttf);
 
 
-    table = ttf_addtable(ttf, TAG_OS2);
-    os2_write(ttf, table);
-    os2_delete(ttf);
+    ttf_table_t*head = ttf_find_table(ttf, TAG_HEAD);
+    if(head)
+       return; //already collapsed
 
 
-    if(!ttf->is_vertical) {
-       table = ttf_addtable(ttf, TAG_HMTX);
-       int num_advances = mtx_write(ttf, table);
-       table = ttf_addtable(ttf, TAG_HHEA);
-       hea_write(ttf, table, num_advances);
-    } else {
-       table = ttf_addtable(ttf, TAG_VMTX);
-       int num_advances = mtx_write(ttf, table);
-       table = ttf_addtable(ttf, TAG_VHEA);
-       hea_write(ttf, table, num_advances);
+    if(ttf->maxp) {
+       table = ttf_addtable(ttf, TAG_MAXP);
+       maxp_write(ttf, table);
+       maxp_delete(ttf);
     }
     }
-       
+
+    if(ttf->os2) {
+       table = ttf_addtable(ttf, TAG_OS2);
+       os2_write(ttf, table);
+       os2_delete(ttf);
+    }
+
+    if(ttf->hea) {
+       if(!ttf->is_vertical) {
+           table = ttf_addtable(ttf, TAG_HMTX);
+           int num_advances = mtx_write(ttf, table);
+           table = ttf_addtable(ttf, TAG_HHEA);
+           hea_write(ttf, table, num_advances);
+           hea_delete(ttf);
+       } else {
+           table = ttf_addtable(ttf, TAG_VMTX);
+           int num_advances = mtx_write(ttf, table);
+           table = ttf_addtable(ttf, TAG_VHEA);
+           hea_write(ttf, table, num_advances);
+           hea_delete(ttf);
+       }
+    }
+
     int loca_size=0;
     if(ttf->num_glyphs) {
     int loca_size=0;
     if(ttf->num_glyphs) {
-       table = ttf_addtable(ttf, TAG_CMAP);
-       cmap_write(ttf, table);
-       cmap_delete(ttf);
+       if(ttf->unicode) {
+           table = ttf_addtable(ttf, TAG_CMAP);
+           cmap_write(ttf, table);
+           cmap_delete(ttf);
+       }
 
 
-       table = ttf_addtable(ttf, TAG_GLYF);
-       U32*locations = glyf_write(ttf, table);
-       glyf_delete(ttf);
-       
-       table = ttf_addtable(ttf, TAG_LOCA);
-       loca_size = loca_write(ttf, table, locations);
-       free(locations);
+       if(ttf->glyphs) {
+           table = ttf_addtable(ttf, TAG_GLYF);
+           U32*locations = glyf_write(ttf, table);
+           table = ttf_addtable(ttf, TAG_LOCA);
+           loca_size = loca_write(ttf, table, locations);
+           free(locations);
+           glyf_delete(ttf);
+       }
     }
 
     }
 
-    if(ttf->name) {
+    if(ttf->full_name || ttf->family_name || ttf->subfamily_name) {
        table = ttf_addtable(ttf, TAG_NAME);
        name_write(ttf, table);
        name_delete(ttf);
        table = ttf_addtable(ttf, TAG_NAME);
        name_write(ttf, table);
        name_delete(ttf);
@@ -1688,7 +1828,7 @@ static void ttf_collapse_tables(ttf_t*ttf)
        post_write(ttf, table);
        post_delete(ttf);
     }
        post_write(ttf, table);
        post_delete(ttf);
     }
-    
+
     table = ttf_addtable(ttf, TAG_HEAD);
     head_write(ttf, table, loca_size);
     head_delete(ttf);
     table = ttf_addtable(ttf, TAG_HEAD);
     head_write(ttf, table, loca_size);
     head_delete(ttf);
@@ -1711,6 +1851,62 @@ ttf_t* ttf_load(void*data, int length)
 
     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
     ttf->version = readU32(&r);
 
     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
     ttf->version = readU32(&r);
+    if(ttf->version == SWAP32(length)) {
+       U32 fontDataSize = readU32(&r);
+       U32 version = readU32(&r);
+       U32 flags  = readU32(&r);
+       U8 panose[10];
+       readBlock(&r, panose, 10);
+       readU8(&r); //charset
+       readU8(&r); //italoc
+       readU32(&r); //weight
+       readU16(&r); //fstype
+       U16 magic = readU16(&r); //magicNumber
+       /* we're being paranoid: it's entirely possible for the font
+          size to be exactly 0x10000. Only treat this font as eot if
+          it has the right magic number */
+       if(magic == 0x4c50) {
+           readU32(&r); //unicoderange[0]
+           readU32(&r); //unicoderange[1]
+           readU32(&r); //unicoderange[2]
+           readU32(&r); //unicoderange[3]
+           readU32(&r); //codepagerange[0]
+           readU32(&r); //codepagerange[1]
+           readU32(&r); //checksumadjustment
+           readU32(&r); //reserved[0]
+           readU32(&r); //reserved[1]
+           readU32(&r); //reserved[2]
+           readU32(&r); //reserved[3]
+           readU16(&r); //padding
+
+           int nr=0;
+           for(nr=0;nr<4;nr++) {
+               int t, len;
+               /* All of ttf is big-endian. All of ttf? No. One small eot table
+                  of indomitable little-endian... */
+               len = readU8(&r);
+               len |= readU8(&r)<<8;
+               len /= 2;
+               for(t=0;t<len;t++) {
+                   U8 c = readU16(&r)>>8;
+               }
+               readU16(&r); // zero terminator
+           }
+           readU16(&r); // more padding
+
+           /* adjust the offset to the start of the actual truetype
+              data- the positions in the table header will be relative
+              to the ttf data after the header, not to the file */
+           r.mem += r.pos;
+           r.size -= r.pos;
+           r.pos = 0;
+           ttf->version = readU32(&r);
+       } else {
+           reader_reset(&r);
+           ttf->version = readU32(&r);
+       }
+    }
+
     if(ttf->version == TTCFTAG) {
        /* a ttc collection is a number of truetype fonts
           packaged together */
     if(ttf->version == TTCFTAG) {
        /* a ttc collection is a number of truetype fonts
           packaged together */
@@ -1728,17 +1924,17 @@ ttf_t* ttf_load(void*data, int length)
        r.pos = font1_position;
        ttf->version = readU32(&r);
     }
        r.pos = font1_position;
        ttf->version = readU32(&r);
     }
-    
+
     int num_tables = readU16(&r);
     int num_tables = readU16(&r);
-    
+
     readU16(&r); //search range
     readU16(&r); //entry selector
     readU16(&r); //range shift
 
     if(num_tables*16 > length) {
     readU16(&r); //search range
     readU16(&r); //entry selector
     readU16(&r); //range shift
 
     if(num_tables*16 > length) {
-       msg("<error> Truncated TTC file (table entries: %d)", num_tables);
-       if(ttf->version != OPENTYPE && 
-          ttf->version != TRUETYPE_MACOS && 
+       msg("<error> Truncated TTF file (table entries: %d)", num_tables);
+       if(ttf->version != OPENTYPE &&
+          ttf->version != TRUETYPE_MACOS &&
           ttf->version != VERSION_1_0) {
            // bad table length, weird version. This is probably not a ttf file.
            return 0;
           ttf->version != VERSION_1_0) {
            // bad table length, weird version. This is probably not a ttf file.
            return 0;
@@ -1762,14 +1958,14 @@ ttf_t* ttf_load(void*data, int length)
            U8*mem = malloc(len);
            r.pos = pos;
            readBlock(&r, mem, len);
            U8*mem = malloc(len);
            r.pos = pos;
            readBlock(&r, mem, len);
-           
+
            ttf_table_t*table = ttf_addtable(ttf, tag);
            table->data = mem;
            table->len = table->memsize = len;
 #if 0
            U32 checksum2 = ttf_table_checksum(table);
            if(checksum2!=checksum) {
            ttf_table_t*table = ttf_addtable(ttf, tag);
            table->data = mem;
            table->len = table->memsize = len;
 #if 0
            U32 checksum2 = ttf_table_checksum(table);
            if(checksum2!=checksum) {
-               msg("<warning> Checksum mismatch in tag %02x%02x%02x%02x %c%c%c%c (%d bytes) %08x!=%08x", 
+               msg("<warning> Checksum mismatch in tag %02x%02x%02x%02x %c%c%c%c (%d bytes) %08x!=%08x",
                        (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
                        (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
                        len, checksum2, checksum);
                        (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
                        (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
                        len, checksum2, checksum);
@@ -1779,16 +1975,16 @@ ttf_t* ttf_load(void*data, int length)
     }
     free(table_data);
 
     }
     free(table_data);
 
-    if(!ttf_parse_tables(ttf)) 
+    if(!ttf_parse_tables(ttf))
        return 0;
 
     return ttf;
 }
 void ttf_create_truetype_tables(ttf_t*ttf)
 {
        return 0;
 
     return ttf;
 }
 void ttf_create_truetype_tables(ttf_t*ttf)
 {
-    if(!ttf->head) 
+    if(!ttf->head)
        ttf->head = head_new(ttf);
        ttf->head = head_new(ttf);
-    if(!ttf->maxp) 
+    if(!ttf->maxp)
        ttf->maxp = maxp_new(ttf);
     if(!ttf->hea)
        ttf->hea = hea_new(ttf);
        ttf->maxp = maxp_new(ttf);
     if(!ttf->hea)
        ttf->hea = hea_new(ttf);
@@ -1797,10 +1993,11 @@ void ttf_create_truetype_tables(ttf_t*ttf)
     if(!ttf->post)
        ttf->post = post_new(ttf);
 }
     if(!ttf->post)
        ttf->post = post_new(ttf);
 }
-ttf_table_t* ttf_write(ttf_t*ttf)
+
+ttf_table_t* ttf_write(ttf_t*ttf, U32*checksum_adjust)
 {
     ttf_collapse_tables(ttf);
 {
     ttf_collapse_tables(ttf);
-   
+
     ttf_table_t*file = ttf_table_new(0);
     writeU32(file, VERSION_1_0);
 
     ttf_table_t*file = ttf_table_new(0);
     writeU32(file, VERSION_1_0);
 
@@ -1812,7 +2009,7 @@ ttf_table_t* ttf_write(ttf_t*ttf)
        t = t->next;
     }
     writeU16(file, num_tables);
        t = t->next;
     }
     writeU16(file, num_tables);
-    
+
     /* write search range */
     int tmp = num_tables;
     int search_range = 0;
     /* write search range */
     int tmp = num_tables;
     int search_range = 0;
@@ -1858,6 +2055,8 @@ ttf_table_t* ttf_write(ttf_t*ttf)
        writeBlock(file, zero, (-t->len)&3); //pad
     }
     U32 checksum = 0xb1b0afba - ttf_table_checksum(file);
        writeBlock(file, zero, (-t->len)&3); //pad
     }
     U32 checksum = 0xb1b0afba - ttf_table_checksum(file);
+    if(checksum_adjust)
+       *checksum_adjust = checksum;
     U8*checksum2 = file->data + head_pos + 8;
     checksum2[0] = checksum>>24;
     checksum2[1] = checksum>>16;
     U8*checksum2 = file->data + head_pos + 8;
     checksum2[0] = checksum>>24;
     checksum2[1] = checksum>>16;
@@ -1865,9 +2064,125 @@ ttf_table_t* ttf_write(ttf_t*ttf)
     checksum2[3] = checksum>>0;
     return file;
 }
     checksum2[3] = checksum>>0;
     return file;
 }
+
+ttf_table_t* ttf_eot_head(ttf_t*ttf)
+{
+    ttf_table_t*file = ttf_table_new(0);
+    writeU32(file, 0); //file size (filled in later)
+    writeU32(file, 0); //fontdatasize (filled in later)
+    writeU32(file, 0x01000200);
+    writeU32(file, 0); //flags
+    writeU8(file, ttf->os2->panose_FamilyType);
+    writeU8(file, ttf->os2->panose_SerifStyle);
+    writeU8(file, ttf->os2->panose_Weight);
+    writeU8(file, ttf->os2->panose_Proportion);
+    writeU8(file, ttf->os2->panose_Contrast);
+    writeU8(file, ttf->os2->panose_StrokeVariation);
+    writeU8(file, ttf->os2->panose_ArmStyle);
+    writeU8(file, ttf->os2->panose_Letterform);
+    writeU8(file, ttf->os2->panose_Midline);
+    writeU8(file, ttf->os2->panose_XHeight);
+    writeU8(file, 1); //charset (default)
+    writeU8(file, ttf->os2->fsSelection&1); //italic
+    writeU32_LE(file, ttf->os2->usWeightClass);
+    writeU16(file, 0); //fstype
+    writeU16(file, 0x4c50); //magic
+    writeU32_LE(file, ttf->os2->ulCharRange[0]);
+    writeU32_LE(file, ttf->os2->ulCharRange[1]);
+    writeU32_LE(file, ttf->os2->ulCharRange[2]);
+    writeU32_LE(file, ttf->os2->ulCharRange[3]);
+    writeU32_LE(file, ttf->os2->ulCodePageRange1);
+    writeU32_LE(file, ttf->os2->ulCodePageRange2);
+    writeU32(file, 0); //checksum adjust (filled in later)
+    writeU32(file, 0); //reserved[0]
+    writeU32(file, 0); //reserved[1]
+    writeU32(file, 0); //reserved[2]
+    writeU32(file, 0); //reserved[3]
+    writeU16(file, 0); //padding(1)
+
+    int t,len;
+
+    //family name
+    len = strlen(ttf->family_name);
+    writeU16_LE(file, len*2);
+    for(t=0;t<len;t++) {
+       writeU8(file, 0);
+       writeU8(file, ttf->family_name[t]);
+    }
+    writeU16(file, 0); //zero byte pad
+
+    //subfamily name
+    len = strlen(ttf->subfamily_name);
+    writeU16_LE(file, len*2);
+    for(t=0;t<len;t++) {
+       writeU8(file, 0);
+       writeU8(file, ttf->subfamily_name[t]);
+    }
+    writeU16(file, 0); //zero byte pad
+
+    //version string
+    len = strlen(ttf->version_string);
+    writeU16_LE(file, len*2); //len
+    for(t=0;t<len;t++) {
+       writeU8(file, 0);
+       writeU8(file, ttf->version_string[t]);
+    }
+    writeU16(file, 0); //zero byte pad
+
+    //full name
+    len = strlen(ttf->full_name);
+    writeU16_LE(file, len*2); //len
+    for(t=0;t<len;t++) {
+       writeU8(file, 0);
+       writeU8(file, ttf->full_name[t]);
+    }
+    writeU16(file, 0); //zero byte pad
+
+    writeU16(file, 0); //padding(2)
+    return file;
+}
+
+void ttf_save_eot(ttf_t*ttf, const char*filename)
+{
+    ttf_table_t* eot = ttf_eot_head(ttf);
+    U32 checksum_adjust = 0;
+    ttf_table_t* t = ttf_write(ttf, &checksum_adjust);
+
+    U8*len_data = eot->data;
+    U32 full_len = eot->len + t->len;
+    len_data[0] = full_len>>0;
+    len_data[1] = full_len>>8;
+    len_data[2] = full_len>>16;
+    len_data[3] = full_len>>24;
+
+    U8*len_data2 = eot->data+4;
+    len_data2[0] = t->len>>0;
+    len_data2[1] = t->len>>8;
+    len_data2[2] = t->len>>16;
+    len_data2[3] = t->len>>24;
+
+    U8*checksum_data = eot->data + 60;
+    checksum_data[0] = checksum_adjust>>0;
+    checksum_data[1] = checksum_adjust>>8;
+    checksum_data[2] = checksum_adjust>>16;
+    checksum_data[3] = checksum_adjust>>24;
+
+    FILE*fi = fopen(filename, "wb");
+    if(!fi) {
+       perror(filename);
+       return;
+    }
+
+    fwrite(eot->data, eot->len, 1, fi);
+    fwrite(t->data, t->len, 1, fi);
+    fclose(fi);
+    ttf_table_delete(0, t);
+    ttf_table_delete(0, eot);
+}
+
 void ttf_save(ttf_t*ttf, const char*filename)
 {
 void ttf_save(ttf_t*ttf, const char*filename)
 {
-    ttf_table_t* t = ttf_write(ttf);
+    ttf_table_t* t = ttf_write(ttf, 0);
     FILE*fi = fopen(filename, "wb");
     if(!fi) {
        perror(filename);
     FILE*fi = fopen(filename, "wb");
     if(!fi) {
        perror(filename);
@@ -1877,14 +2192,15 @@ void ttf_save(ttf_t*ttf, const char*filename)
     fclose(fi);
     ttf_table_delete(0, t);
 }
     fclose(fi);
     ttf_table_delete(0, t);
 }
+
 void ttf_dump(ttf_t*ttf)
 {
     msg("<notice> Truetype file version %08x%s", ttf->version, ttf->version == OPENTYPE?" (opentype)":"");
     ttf_table_t*table = ttf->tables;
     while(table) {
        U32 tag = table->id;
 void ttf_dump(ttf_t*ttf)
 {
     msg("<notice> Truetype file version %08x%s", ttf->version, ttf->version == OPENTYPE?" (opentype)":"");
     ttf_table_t*table = ttf->tables;
     while(table) {
        U32 tag = table->id;
-       msg("<notice> Tag %02x%02x%02x%02x [%c%c%c%c] (length: %d)", 
-               (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, 
+       msg("<notice> Tag %02x%02x%02x%02x [%c%c%c%c] (length: %d)",
+               (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
                (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, table->len);
        table = table->next;
     }
                (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, table->len);
        table = table->next;
     }
@@ -1929,22 +2245,29 @@ int main(int argn, const char*argv[])
 {
     setConsoleLogging(7);
     const char*filename = "comic.ttf";
 {
     setConsoleLogging(7);
     const char*filename = "comic.ttf";
-    if(argn>1) 
+    if(argn>1)
        filename = argv[1];
     //msg("<notice> Loading %s", filename);
     memfile_t*m = memfile_open(filename);
     ttf_t*ttf = ttf_load(m->data, m->len);
        filename = argv[1];
     //msg("<notice> Loading %s", filename);
     memfile_t*m = memfile_open(filename);
     ttf_t*ttf = ttf_load(m->data, m->len);
+
     if(!ttf) {
        msg("<error> Couldn't load %s", filename);
        return 1;
     }
     ttf_reduce(ttf);
     if(!ttf) {
        msg("<error> Couldn't load %s", filename);
        return 1;
     }
     ttf_reduce(ttf);
-    ttf->name = strdup("testfont");
+
+    ttf->full_name = strdup("Test-Normal");
+    ttf->family_name = strdup("Test");
+    ttf->subfamily_name = strdup("Normal");
+    ttf->version_string = strdup("Version 1.0");
+
     if(!ttf) return 1;
     memfile_close(m);
     //ttf_dump(ttf);
     if(!ttf) return 1;
     memfile_close(m);
     //ttf_dump(ttf);
-    //printf("os2 version: %04x (%d), maxp size: %d\n", 
+    //printf("os2 version: %04x (%d), maxp size: %d\n",
 //         ttf->os2->version, ttf->os2->size, ttf->maxp->size);
 //         ttf->os2->version, ttf->os2->size, ttf->maxp->size);
+    ttf_save_eot(ttf, "testfont.eot");
     ttf_save(ttf, "testfont.ttf");
     ttf_destroy(ttf);
     return 0;
     ttf_save(ttf, "testfont.ttf");
     ttf_destroy(ttf);
     return 0;