added eot support to ttf library
[swftools.git] / lib / ttf.c
1 /* ttf.c
2    Parser and writer for truetype font files.
3
4    Part of the swftools package.
5    
6    Copyright (c) 2010 Matthias Kramm <kramm@quiss.org> 
7  
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <memory.h>
25 #include <assert.h>
26 #include "log.h"
27 #include "os.h"
28 #include "q.h"
29 #include "mem.h"
30 #include "ttf.h"
31
32 #define TTCFTAG 0x74746366
33
34 #define OPENTYPE 0x4f54544f
35 #define TRUETYPE_MACOS 0x74727565
36 #define VERSION_1_0 0x00010000
37
38 #define TAG_OS2 0x4f532f32
39 #define TAG_CMAP 0x636d6170
40 #define TAG_GLYF 0x676c7966 //required for non opentype
41 #define TAG_HEAD 0x68656164 //required
42 #define TAG_HHEA 0x68686561 //required
43 #define TAG_HMTX 0x686d7478 //required
44 #define TAG_VHEA 0x86686561
45 #define TAG_VMTX 0x866d7478
46 #define TAG_KERN 0x6b65726e
47 #define TAG_LOCA 0x6c6f6361 //required for non opentype
48 #define TAG_MAXP 0x6d617870 //required
49 #define TAG_NAME 0x6e616d65
50 #define TAG_POST 0x706f7374
51 #define TAG_CFF  0x43464620 //required for opentype
52
53 /* TODO:
54     fpgm - assembly instructions
55     prep - assembly instructions
56     cvt - constant value table
57     gasp - gridfitting procedure
58 */
59
60 static U32 checksum_block(U8*_data, int len)
61 {
62     U32 sum = 0;
63     U8*data = (U8*)_data;
64
65     int pos;
66     int len_minus_4 = len-4;
67     for(pos=0;pos<=len_minus_4;pos+=4) {
68         sum += data[pos]<<24|data[pos+1]<<16|data[pos+2]<<8|data[pos+3];
69     }
70     int left = len-pos;
71     if(left == 1) sum+= data[pos+0]<<24;
72     if(left == 2) sum+= data[pos+0]<<24|data[pos+1]<<16;
73     if(left == 3) sum+= data[pos+0]<<24|data[pos+1]<<16|data[pos+2]<<8;
74     return sum;
75 }
76
77 typedef struct _memreader {
78     U8*mem;
79     int pos;
80     int size;
81 } memreader_t;
82
83 static U8 readU8(memreader_t*r)
84 {
85     return r->mem[r->pos++];
86 }
87 static inline U16 readU16(memreader_t*r)
88 {
89     if(r->pos+2>r->size) return 0;
90     U16 val = r->mem[r->pos]<<8|
91               r->mem[r->pos+1];
92     r->pos += 2;
93     return val;
94 }
95 static S16 readS16(memreader_t*r)
96 {
97     return (S16)readU16(r);
98 }
99 static U32 readU32(memreader_t*r)
100 {
101     if(r->pos+4>r->size) return 0;
102     U32 val = r->mem[r->pos]<<24|
103               r->mem[r->pos+1]<<16|
104               r->mem[r->pos+2]<<8|
105               r->mem[r->pos+3];
106     r->pos += 4;
107     return val;
108 }
109 static void readBlock(memreader_t*r, void*dest, int len)
110 {
111     int remaining = r->size-r->pos;
112     if(len > remaining) {
113         memcpy(dest, r->mem+r->pos, remaining);
114         memset(dest+remaining, 0, len - remaining);
115         r->pos += remaining;
116     } else {
117         memcpy(dest, r->mem+r->pos, len);
118         r->pos += len;
119     }
120 }
121 static void reader_reset(memreader_t*r) 
122 {
123     r->pos;
124 }
125 #define INIT_READ(r,data,length,pos) memreader_t r = {(data),(pos),(length)};
126
127 static void expand(ttf_table_t*w, int newsize)
128 {
129     int v1 = (newsize+63)&~63;
130     int v2 = w->len + w->len / 2;
131     w->memsize = v1>v2?v1:v2;
132     w->data = rfx_realloc(w->data, w->memsize);
133 }
134 static inline void writeU8(ttf_table_t*w, unsigned char b)
135 {
136     if(w->memsize<w->len+1)
137         expand(w, w->len+1);
138     w->data[w->len++] = b;
139 }
140 static inline void writeU16(ttf_table_t*w, unsigned short v)
141 {
142     if(w->memsize<w->len+2)
143         expand(w, w->len+2);
144     w->data[w->len++] = v>>8;
145     w->data[w->len++] = v;
146 }
147 static inline void writeU16_LE(ttf_table_t*w, unsigned short v)
148 {
149     if(w->memsize<w->len+2)
150         expand(w, w->len+2);
151     w->data[w->len++] = v;
152     w->data[w->len++] = v>>8;
153 }
154 #define writeS16 writeU16
155 static inline void writeU32(ttf_table_t*w, unsigned long v)
156 {
157     if(w->memsize<w->len+4)
158         expand(w, w->len+4);
159     w->data[w->len++] = v>>24;
160     w->data[w->len++] = v>>16;
161     w->data[w->len++] = v>>8;
162     w->data[w->len++] = v;
163 }
164 static inline void writeU32_LE(ttf_table_t*w, unsigned long v)
165 {
166     if(w->memsize<w->len+4)
167         expand(w, w->len+4);
168     w->data[w->len++] = v;
169     w->data[w->len++] = v>>8;
170     w->data[w->len++] = v>>16;
171     w->data[w->len++] = v>>24;
172 }
173 static inline void writeBlock(ttf_table_t*w, void*data, int len)
174 {
175     if(w->memsize<w->len+len)
176         expand(w, w->len+len);
177     memcpy(w->data+w->len, data, len);
178     w->len += len;
179 }
180
181 ttf_table_t*ttf_table_new(U32 id)
182 {
183     ttf_table_t*t = rfx_calloc(sizeof(ttf_table_t));
184     t->id = id;
185     return t;
186 }
187
188 ttf_table_t*ttf_addtable(ttf_t*ttf, U32 id)
189 {
190     ttf_table_t*t = ttf_table_new(id);
191
192     ttf_table_t*before,*after=0;
193     for(before=ttf->tables; before&&before->id<id; before=before->next) {
194         after=before;
195     }
196     if(before && before->id == id) {
197         msg("<error> Error: duplicate table %08x", id);
198         free(before->data);
199         before->data = 0;
200         before->len = 0;
201         return before;
202     }
203     
204     if(!after) {
205         t->next = ttf->tables;
206         ttf->tables = t;
207     } else {
208         t->prev = after;
209         t->next = after->next;
210         after->next = t;
211     }
212     if(t->next)
213         t->next->prev = t;
214     return t;
215 }
216 ttf_table_t*ttf_find_table(ttf_t*ttf, U32 id)
217 {
218     ttf_table_t*table = ttf->tables;
219     while(table) {
220         if(table->id == id) 
221             return table;
222         table = table->next;
223     }
224     return 0;
225 }
226 void ttf_table_delete(ttf_t*ttf, ttf_table_t*table)
227 {
228     if(ttf && ttf->tables == table) {
229         ttf->tables = table->next;
230     }
231     if(table->prev) 
232         table->prev->next = table->next;
233     if(table->next) 
234         table->next->prev = table->prev;
235     free(table->data);
236     free(table);
237 }
238 U32 ttf_table_checksum(ttf_table_t*t)
239 {
240     U32 checksum = checksum_block(t->data, t->len);
241     if(t->id==TAG_HEAD && t->len>=12) {
242         /* the checksum for the HEAD table is calculated by masking out
243            the checksumadjust field */
244         U32 adjust = t->data[8]<<24|t->data[9]<<16|t->data[10]<<8|t->data[11];
245         checksum -= adjust;
246     }
247     return checksum;
248 }
249 static U8 printable(U8 a)
250 {
251     if(a<32 || a==127) return '.';
252     else return a;
253 }
254 static void hexdump(U8*data, int len, const char*prefix)
255 {
256     int t;
257     char ascii[32];
258     printf("%s    -=> ",prefix);
259     for(t=0;t<len;t++) {
260         printf("%02x ", data[t]);
261         ascii[t&15] = printable(data[t]);
262         if((t && ((t&15)==15)) || (t==len-1))
263         {
264             int s,p=((t)&15)+1;
265             ascii[p] = 0;
266             for(s=p-1;s<16;s++) {
267                 printf("   ");
268             }
269             if(t==len-1)
270                 printf(" %s\n", ascii);
271             else
272                 printf(" %s\n%s    -=> ",ascii,prefix);
273         }
274     }
275 }
276 static void ttf_table_dump(ttf_table_t*t, const char*prefix)
277 {
278     if(!t) return;
279     hexdump(t->data, t->len, prefix);
280 }
281
282 static table_head_t*head_new(ttf_t*ttf)
283 {
284     table_head_t*head = rfx_calloc(sizeof(table_head_t));
285     head->units_per_em = 1024;
286     int t;
287     if(ttf->num_glyphs) {
288         head->xmin = ttf->glyphs[0].xmin;
289         head->ymin = ttf->glyphs[0].ymin;
290         head->xmax = ttf->glyphs[0].xmax;
291         head->ymax = ttf->glyphs[0].ymax;
292         for(t=1;t<ttf->num_glyphs;t++) {
293             if(ttf->glyphs[t].xmin < head->xmin) head->xmin = ttf->glyphs[t].xmin;
294             if(ttf->glyphs[t].ymin < head->ymin) head->ymin = ttf->glyphs[t].ymin;
295             if(ttf->glyphs[t].xmax > head->xmax) head->xmax = ttf->glyphs[t].xmax;
296             if(ttf->glyphs[t].ymax > head->ymax) head->ymax = ttf->glyphs[t].ymax;
297         }
298     }
299     head->macStyle = 0;
300     head->lowest_readable_size = 8; // not sure what font renderers actually do with this
301     head->dir_hint = 0;
302     return head;
303 }
304 static int head_parse(ttf_t*ttf, memreader_t*r)
305 {
306     ttf->head = rfx_calloc(sizeof(table_head_t));
307     U32 version = readU32(r);
308     if(version!=VERSION_1_0) 
309         msg("<warning> Font HEAD has unknown version %08x", version);
310     U32 revision = readU32(r);
311     U32 checksum2 = readU32(r);
312     U32 magic = readU32(r);
313     if(magic!=0x5f0f3cf5) 
314         msg("<warning> Font HEAD has unknown magic number %08x", magic);
315     ttf->head->flags = readU16(r);
316     ttf->head->units_per_em = readU16(r);
317     readU32(r);readU32(r); //created
318     readU32(r);readU32(r); //modified
319     ttf->head->xmin = readU16(r);
320     ttf->head->ymin = readU16(r);
321     ttf->head->xmax = readU16(r);
322     ttf->head->ymax = readU16(r);
323     ttf->head->macStyle = readU16(r);
324     ttf->head->lowest_readable_size = readU16(r); //in pixels
325     ttf->head->dir_hint = readS16(r);
326     int loc_index = readS16(r); //used in 'loca' table
327     if(loc_index>1)
328         msg("<warning> loca index format %d unknown", loc_index);
329     U16 glyph_data_format = readS16(r);
330     if(glyph_data_format!=0)
331         msg("<warning> Font glyph data format unknown: %04x", glyph_data_format);
332     if(r->pos < r->size) {
333         msg("<warning> Leftover bytes (%d) in HEAD tag", r->size - r->pos);
334     }
335     return loc_index;
336 }
337 static void head_write(ttf_t*ttf, ttf_table_t*w, int loca_size)
338 {
339     writeU32(w, 0x10000);
340     writeU32(w, 0x10000);
341     writeU32(w, 0); //checksum
342     writeU32(w, 0x5f0f3cf5); //magic
343     writeU16(w, ttf->head->flags);
344     writeU16(w, ttf->head->units_per_em);
345     writeU32(w, 0);writeU32(w, 0); //created
346     writeU32(w, 0);writeU32(w, 0); //modified
347     writeU16(w, ttf->head->xmin);
348     writeU16(w, ttf->head->ymin);
349     writeU16(w, ttf->head->xmax);
350     writeU16(w, ttf->head->ymax);
351     writeU16(w, ttf->head->macStyle);
352     writeU16(w, ttf->head->lowest_readable_size);
353     writeS16(w, ttf->head->dir_hint);
354     writeS16(w, loca_size); //loca index size (32 bit)
355     writeS16(w, 0); //glyph data format
356 }
357 static void head_dump(ttf_t*ttf)
358 {
359     printf("head->flags: %d\n", ttf->head->flags);
360     printf("head->units_per_em: %d\n", ttf->head->units_per_em);
361     printf("head->xmin: %d\n", ttf->head->xmin);
362     printf("head->ymin: %d\n", ttf->head->ymin);
363     printf("head->xmax: %d\n", ttf->head->xmax);
364     printf("head->ymax: %d\n", ttf->head->ymax);
365     printf("head->macStyle: %d\n", ttf->head->macStyle);
366     printf("head->lowest_readable_size: %d\n", ttf->head->lowest_readable_size);
367     printf("head->dir_hint: %d\n", ttf->head->dir_hint);
368 }
369 static void head_delete(ttf_t*ttf)
370 {
371     if(ttf->head) {
372         free(ttf->head);
373         ttf->head=0;
374     }
375 }
376
377 static table_os2_t*os2_new(ttf_t*ttf)
378 {
379     table_os2_t*os2 = rfx_calloc(sizeof(table_os2_t));
380     if(ttf->num_glyphs) {
381         int average_width=0;
382         int t;
383         for(t=0;t<ttf->num_glyphs;t++) {
384             average_width += (ttf->glyphs[t].advance + ttf->glyphs[t].bearing);
385         }
386         os2->xAvgCharWidth = average_width / ttf->num_glyphs;
387     }
388
389     /* that's what everybody seems to fill in */
390     os2->usWeightClass = 400;
391     os2->usWidthClass = 5;
392    
393     if(ttf->head) {
394         int advance = (ttf->head->xmax - ttf->head->xmin)/2;
395         int height = (ttf->head->xmax - ttf->head->xmin);
396         int ymid = height/2;
397         /* I do believe a sane font rendering engine will actually use
398            the font advance here- the subscript/superscript position will
399            not be the same for each glyph */
400         os2->ySuperscriptXSize = os2->ySubscriptXSize = (ttf->head->xmax - ttf->head->xmin)/2;
401         os2->ySuperscriptYSize = os2->ySubscriptYSize = (ttf->head->ymax - ttf->head->ymin)/2;
402         os2->ySubscriptXOffset = advance;
403         os2->ySubscriptYOffset = 0;
404         os2->ySuperscriptXOffset = advance;
405         os2->ySuperscriptYOffset = (ttf->head->ymax - ttf->head->ymin)/2;
406         os2->yStrikeoutSize = ttf->head->units_per_em / 10;
407         os2->yStrikeoutPosition = ymid;
408         os2->usWinAscent = ttf->head->ymax;
409         os2->usWinDescent = ttf->head->ymin<0?0:ttf->head->ymin;
410         os2->sxHeight = ymid;
411         os2->sCapHeight = height*2/3;
412     }
413     os2->panose_Weight = 4;
414
415     /* strictly speaking we'd have to set 92/64 bits in these tables, depending on
416        what parts of the unicode table is filled. (e.g. bit 90 = tibetan). */
417     os2->ulCharRange[0] = 1;
418     os2->ulCharRange[1] = 0;
419     os2->ulCharRange[2] = 0;
420     os2->ulCharRange[3] = 0;
421     os2->ulCodePageRange1 = 1;
422     os2->ulCodePageRange2 = 0;
423
424     if(ttf->unicode_size) {
425         int min,max;
426         for(min=0;min<ttf->unicode_size;min++)
427             if(ttf->unicode[min]) break;
428         for(max=ttf->unicode_size-1;max>=0;max--)
429             if(ttf->unicode[max]) break;
430         if(min<=max) {
431             os2->fsFirstCharIndex = min;
432             os2->fsLastCharIndex = max;
433         }
434     }
435     os2->sTypoAscender = ttf->ascent;
436     os2->sTypoDescender = ttf->descent;
437     os2->sTypoLineGap = ttf->lineGap;
438
439     os2->usDefaultChar = 0;
440     os2->usBreakChar = (ttf->unicode_size>0x20 && ttf->unicode[0x20])?0x20:0;
441     os2->usMaxContext = 0; // we don't use ligatures yet
442     return os2;
443 }
444 static table_os2_t*os2_parse(memreader_t*r)
445 {
446     table_os2_t*os2 = rfx_calloc(sizeof(table_os2_t));
447     U16 version = readU16(r);
448     /* 0 = TrueType 1.5
449        1 = TrueType 1.66
450        2 = OpenType 1.2
451        3 = OpenType 1.4 */
452     if(version!=0 && version!=1 && version!=2 && version!=3)
453         msg("<warning> Unknown OS2 version: %04x", version);
454     os2->xAvgCharWidth = readS16(r);
455     os2->usWeightClass = readU16(r);
456     os2->usWidthClass = readU16(r);
457     readU16(r); //fstype
458     os2->ySubscriptXSize = readU16(r);
459     os2->ySubscriptYSize = readU16(r);
460     os2->ySubscriptXOffset = readU16(r);
461     os2->ySubscriptYOffset = readU16(r);
462     os2->ySuperscriptXSize = readU16(r);
463     os2->ySuperscriptYSize = readU16(r);
464     os2->ySuperscriptXOffset = readU16(r);
465     os2->ySuperscriptYOffset = readU16(r);
466     os2->yStrikeoutSize = readU16(r);
467     os2->yStrikeoutPosition = readU16(r);
468     os2->sFamilyClass = readU16(r);
469     os2->panose_FamilyType = readU8(r);
470     os2->panose_SerifStyle = readU8(r);
471     os2->panose_Weight = readU8(r);
472     os2->panose_Proportion = readU8(r);
473     os2->panose_Contrast = readU8(r);
474     os2->panose_StrokeVariation = readU8(r);
475     os2->panose_ArmStyle = readU8(r);
476     os2->panose_Letterform = readU8(r);
477     os2->panose_Midline = readU8(r);
478     os2->panose_XHeight = readU8(r);
479     os2->ulCharRange[0] = readU32(r);
480     os2->ulCharRange[1] = readU32(r);
481     os2->ulCharRange[2] = readU32(r);
482     os2->ulCharRange[3] = readU32(r);
483     readU32(r); //vendor
484     os2->fsSelection = readU16(r);
485     os2->fsFirstCharIndex = readU16(r);
486     os2->fsLastCharIndex = readU16(r);
487     os2->sTypoAscender = readS16(r);
488     os2->sTypoDescender = readS16(r);
489     os2->sTypoLineGap = readS16(r);
490     os2->usWinAscent = readU16(r);
491     os2->usWinDescent = readU16(r);
492     if(version<1) return os2;
493     os2->ulCodePageRange1 = readU32(r);
494     os2->ulCodePageRange2 = readU32(r);
495     if(version<2) return os2;
496     os2->sxHeight = readS16(r);
497     os2->sCapHeight = readS16(r);
498     os2->usDefaultChar = readU16(r);
499     os2->usBreakChar = readU16(r);
500     os2->usMaxContext = readU16(r);
501     
502     if(r->pos < r->size) {
503         msg("<warning> Leftover bytes (%d) in OS2 tag", r->size - r->pos);
504     }
505     return os2;
506 }
507 static void os2_write(ttf_t*ttf, ttf_table_t*w)
508 {
509     table_os2_t*os2 = ttf->os2;
510     U16 version=1;
511     if(os2->sxHeight|os2->sCapHeight|os2->usDefaultChar|os2->usBreakChar|os2->usMaxContext) {
512         version=2;
513     }
514     writeU16(w, version);
515     writeS16(w, os2->xAvgCharWidth);
516     writeU16(w, os2->usWeightClass);
517     writeU16(w, os2->usWidthClass);
518     writeU16(w, 0); //fstype
519     writeU16(w, os2->ySubscriptXSize);
520     writeU16(w, os2->ySubscriptYSize);
521     writeU16(w, os2->ySubscriptXOffset);
522     writeU16(w, os2->ySubscriptYOffset);
523     writeU16(w, os2->ySuperscriptXSize);
524     writeU16(w, os2->ySuperscriptYSize);
525     writeU16(w, os2->ySuperscriptXOffset);
526     writeU16(w, os2->ySuperscriptYOffset);
527     writeU16(w, os2->yStrikeoutSize);
528     writeU16(w, os2->yStrikeoutPosition);
529     writeU16(w, os2->sFamilyClass);
530     writeU8(w, os2->panose_FamilyType);
531     writeU8(w, os2->panose_SerifStyle);
532     writeU8(w, os2->panose_Weight);
533     writeU8(w, os2->panose_Proportion);
534     writeU8(w, os2->panose_Contrast);
535     writeU8(w, os2->panose_StrokeVariation);
536     writeU8(w, os2->panose_ArmStyle);
537     writeU8(w, os2->panose_Letterform);
538     writeU8(w, os2->panose_Midline);
539     writeU8(w, os2->panose_XHeight);
540     writeU32(w, os2->ulCharRange[0]);
541     writeU32(w, os2->ulCharRange[1]);
542     writeU32(w, os2->ulCharRange[2]);
543     writeU32(w, os2->ulCharRange[3]);
544     writeU32(w, 0x53434244); //vendor
545     writeU16(w, os2->fsSelection);
546     writeU16(w, os2->fsFirstCharIndex);
547     writeU16(w, os2->fsLastCharIndex);
548     writeS16(w, os2->sTypoAscender);
549     writeS16(w, os2->sTypoDescender);
550     writeS16(w, os2->sTypoLineGap);
551     writeU16(w, os2->usWinAscent);
552     writeU16(w, os2->usWinDescent);
553     if(version<1) return;
554     writeU32(w, os2->ulCodePageRange1);
555     writeU32(w, os2->ulCodePageRange2);
556     if(version<2) return;
557     writeS16(w, os2->sxHeight);
558     writeS16(w, os2->sCapHeight);
559     writeU16(w, os2->usDefaultChar);
560     writeU16(w, os2->usBreakChar);
561     writeU16(w, os2->usMaxContext);
562 }
563 static void os2_dump(ttf_t*ttf)
564 {
565     table_os2_t*os2 = ttf->os2;
566     if(!os2) return;
567     printf("os2->xAvgCharWidth: %d\n", os2->xAvgCharWidth);
568     printf("os2->usWeightClass: %d\n", os2->usWeightClass);
569     printf("os2->usWidthClass: %d\n", os2->usWidthClass);
570     printf("os2->ySubscriptXSize: %d\n", os2->ySubscriptXSize);
571     printf("os2->ySubscriptYSize: %d\n", os2->ySubscriptYSize);
572     printf("os2->ySubscriptXOffset: %d\n", os2->ySubscriptXOffset);
573     printf("os2->ySubscriptYOffset: %d\n", os2->ySubscriptYOffset);
574     printf("os2->ySuperscriptXSize: %d\n", os2->ySuperscriptXSize);
575     printf("os2->ySuperscriptYSize: %d\n", os2->ySuperscriptYSize);
576     printf("os2->ySuperscriptXOffset: %d\n", os2->ySuperscriptXOffset);
577     printf("os2->ySuperscriptYOffset: %d\n", os2->ySuperscriptYOffset);
578     printf("os2->yStrikeoutSize: %d\n", os2->yStrikeoutSize);
579     printf("os2->yStrikeoutPosition: %d\n", os2->yStrikeoutPosition);
580     printf("os2->sFamilyClass: %d\n", os2->sFamilyClass);
581     printf("os2->panose_FamilyType: %d\n", os2->panose_FamilyType);
582     printf("os2->panose_SerifStyle: %d\n", os2->panose_SerifStyle);
583     printf("os2->panose_Weight: %d\n", os2->panose_Weight);
584     printf("os2->panose_Proportion: %d\n", os2->panose_Proportion);
585     printf("os2->panose_Contrast: %d\n", os2->panose_Contrast);
586     printf("os2->panose_StrokeVariation: %d\n", os2->panose_StrokeVariation);
587     printf("os2->panose_ArmStyle: %d\n", os2->panose_ArmStyle);
588     printf("os2->panose_Letterform: %d\n", os2->panose_Letterform);
589     printf("os2->panose_Midline: %d\n", os2->panose_Midline);
590     printf("os2->panose_XHeight: %d\n", os2->panose_XHeight);
591     printf("os2->ulCharRange[0]: %d\n", os2->ulCharRange[0]);
592     printf("os2->ulCharRange[1]: %d\n", os2->ulCharRange[1]);
593     printf("os2->ulCharRange[2]: %d\n", os2->ulCharRange[2]);
594     printf("os2->ulCharRange[3]: %d\n", os2->ulCharRange[3]);
595     printf("os2->fsSelection: %d\n", os2->fsSelection);
596     printf("os2->fsFirstCharIndex: %d\n", os2->fsFirstCharIndex);
597     printf("os2->fsLastCharIndex: %d\n", os2->fsLastCharIndex);
598     printf("os2->sTypoAscender: %d\n", os2->sTypoAscender);
599     printf("os2->sTypoDescender: %d\n", os2->sTypoDescender);
600     printf("os2->sTypoLineGap: %d\n", os2->sTypoLineGap);
601     printf("os2->usWinAscent: %d\n", os2->usWinAscent);
602     printf("os2->usWinDescent: %d\n", os2->usWinDescent);
603     printf("os2->ulCodePageRange1: %d\n", os2->ulCodePageRange1);
604     printf("os2->ulCodePageRange2: %d\n", os2->ulCodePageRange2);
605     printf("os2->sxHeight: %d\n", os2->sxHeight);
606     printf("os2->sCapHeight: %d\n", os2->sCapHeight);
607     printf("os2->usDefaultChar: %d\n", os2->usDefaultChar);
608     printf("os2->usBreakChar: %d\n", os2->usBreakChar);
609     printf("os2->usMaxContext: %d\n", os2->usMaxContext);
610 }
611 static void os2_delete(ttf_t*ttf)
612 {
613     if(ttf->os2)
614         free(ttf->os2);
615     ttf->os2=0;
616 }
617
618 static table_maxp_t*maxp_new(ttf_t*ttf)
619 {
620     table_maxp_t*maxp = rfx_calloc(sizeof(table_maxp_t));
621     int t;
622     maxp->maxContours=1;
623     if(ttf->num_glyphs) {
624         int max = 1;
625         for(t=0;t<ttf->num_glyphs;t++) {
626             if(ttf->glyphs[t].num_points>max)
627                 max = ttf->glyphs[t].num_points;
628             int contours = 0;
629             int s;
630             for(s=0;s<ttf->glyphs[t].num_points;s++) {
631                 if(ttf->glyphs[t].points[s].flags&GLYPH_CONTOUR_END)
632                     contours++;
633             }
634             if(maxp->maxContours < contours)
635                 maxp->maxContours = contours;
636         }
637         maxp->maxPoints = max;
638
639         /* we don't generate composite glyphs yet */
640         maxp->maxComponentPoints = 0;
641         maxp->maxComponentContours = 0;
642     }
643     return maxp;
644 }
645 static table_maxp_t* maxp_parse(ttf_t*ttf, memreader_t*r)
646 {
647     U32 version = readU32(r);
648     ttf->num_glyphs = readU16(r);
649     /* according to freetype, older fonts (version<0x10000) 
650        apparently only contain the number of glyphs. this is
651        rather rare, though. */
652     if(version<0x10000 && r->size==6) return 0;
653
654     if(r->size<32)
655         msg("<warning> Truncated maxp table (version %d)", version);
656
657     table_maxp_t*maxp = rfx_calloc(sizeof(table_maxp_t));
658     maxp->maxPoints = readU16(r);
659     maxp->maxContours = readU16(r);
660     maxp->maxComponentPoints = readU16(r);
661     maxp->maxComponentContours = readU16(r);
662     maxp->maxZones = readU16(r);
663     maxp->maxTwilightPoints = readU16(r);
664     maxp->maxStorage = readU16(r);
665     maxp->maxFunctionDefs = readU16(r);
666     maxp->maxInstructionDefs = readU16(r);
667     maxp->maxStackElements = readU16(r);
668     maxp->maxSizeOfInstructions = readU16(r);
669     maxp->maxComponentElements = readU16(r);
670     maxp->maxComponentDepth = readU16(r);
671     return maxp;
672 }
673 static void maxp_write(ttf_t*ttf, ttf_table_t*w)
674 {
675     table_maxp_t*maxp = ttf->maxp;
676     if(!maxp) {
677         /* version 0.5 simplified maxp table */
678         writeU32(w, 0x00005000);
679         writeU16(w, ttf->num_glyphs);
680         return;
681     }
682     writeU32(w, 0x10000); //version
683     writeU16(w, ttf->num_glyphs);
684     writeU16(w, maxp->maxPoints);
685     writeU16(w, maxp->maxContours);
686     writeU16(w, maxp->maxComponentPoints);
687     writeU16(w, maxp->maxComponentContours);
688     writeU16(w, maxp->maxZones);
689     writeU16(w, maxp->maxTwilightPoints);
690     writeU16(w, maxp->maxStorage);
691     writeU16(w, maxp->maxFunctionDefs);
692     writeU16(w, maxp->maxInstructionDefs);
693     writeU16(w, maxp->maxStackElements);
694     writeU16(w, maxp->maxSizeOfInstructions);
695     writeU16(w, maxp->maxComponentElements);
696     writeU16(w, maxp->maxComponentDepth);
697 }
698 static void maxp_dump(ttf_t*ttf)
699 {
700     table_maxp_t*maxp = ttf->maxp;
701     if(!maxp) return;
702     printf("maxp->maxPoints: %d\n", maxp->maxPoints);
703     printf("maxp->maxContours: %d\n", maxp->maxContours);
704     printf("maxp->maxComponentPoints: %d\n", maxp->maxComponentPoints);
705     printf("maxp->maxComponentContours: %d\n", maxp->maxComponentContours);
706     printf("maxp->maxZones: %d\n", maxp->maxZones);
707     printf("maxp->maxTwilightPoints: %d\n", maxp->maxTwilightPoints);
708     printf("maxp->maxStorage: %d\n", maxp->maxStorage);
709     printf("maxp->maxFunctionDefs: %d\n", maxp->maxFunctionDefs);
710     printf("maxp->maxInstructionDefs: %d\n", maxp->maxInstructionDefs);
711     printf("maxp->maxStackElements: %d\n", maxp->maxStackElements);
712     printf("maxp->maxSizeOfInstructions: %d\n", maxp->maxSizeOfInstructions);
713     printf("maxp->maxComponentElements: %d\n", maxp->maxComponentElements);
714     printf("maxp->maxComponentDepth: %d\n", maxp->maxComponentDepth);
715 }
716 static void maxp_delete(ttf_t*ttf)
717 {
718     if(ttf->maxp)
719         free(ttf->maxp);
720     ttf->maxp=0;
721 }
722
723 static table_hea_t*hea_new(ttf_t*ttf)
724 {
725     table_hea_t*hea = rfx_calloc(sizeof(table_hea_t));
726     if(ttf->num_glyphs) {
727         int t;
728         for(t=0;t<ttf->num_glyphs;t++) {
729             if(ttf->glyphs[t].advance > hea->advanceWidthMax)
730                 hea->advanceWidthMax = ttf->glyphs[t].advance;
731             if(ttf->glyphs[t].xmin < hea->minLeftSideBearing)
732                 hea->minLeftSideBearing = ttf->glyphs[t].xmin;
733             if(ttf->glyphs[t].xmax < hea->minRightSideBearing)
734                 hea->minRightSideBearing = ttf->glyphs[t].xmax;
735             int width = ttf->glyphs[t].xmax - ttf->glyphs[t].xmin;
736             if(width > hea->xMaxExtent)
737                 hea->xMaxExtent = width;
738         }
739         /* TODO: caret */
740     }
741     return hea;
742 }
743 static int hea_parse(memreader_t*r, ttf_t*ttf)
744 {
745     table_hea_t*hea = ttf->hea = rfx_calloc(sizeof(table_hea_t));
746     U32 version = readU32(r);
747     ttf->ascent = readS16(r);
748     ttf->descent = readS16(r);
749     ttf->lineGap = readS16(r);
750     hea->advanceWidthMax = readU16(r);
751     hea->minLeftSideBearing = readS16(r);
752     hea->minRightSideBearing = readS16(r);
753     hea->xMaxExtent = readS16(r);
754     hea->caretSlopeRise = readS16(r);
755     hea->caretSlopeRun = readS16(r);
756     hea->caretOffset = readS16(r);
757     readS16(r); //reserved[0]
758     readS16(r); //reserved[1]
759     readS16(r); //reserved[2]
760     readS16(r); //reserved[3]
761     S16 metricDataFormat = readS16(r); //should be 0
762     if(metricDataFormat!=0) {
763         msg("<warning> Unknown metric format %d", metricDataFormat);
764     }
765     int num_advances = readU16(r);
766     if(num_advances > ttf->num_glyphs) {
767         msg("<warning> bad number of horizontal metrics: %d", num_advances);
768         num_advances = ttf->num_glyphs;
769     }
770     return num_advances;
771 }
772 static table_hea_t*hea_write(ttf_t*ttf, ttf_table_t*w, int num_advances)
773 {
774     table_hea_t*hea = ttf->hea;
775     writeU32(w, 0x00010000);
776     writeS16(w, ttf->ascent);
777     writeS16(w, ttf->descent);
778     writeS16(w, ttf->lineGap);
779     writeU16(w, hea->advanceWidthMax);
780     writeS16(w, hea->minLeftSideBearing);
781     writeS16(w, hea->minRightSideBearing);
782     writeS16(w, hea->xMaxExtent);
783     writeS16(w, hea->caretSlopeRise);
784     writeS16(w, hea->caretSlopeRun);
785     writeS16(w, hea->caretOffset);
786     writeS16(w, 0); //reserved
787     writeS16(w, 0); //reserved
788     writeS16(w, 0); //reserved
789     writeS16(w, 0); //reserved
790     writeS16(w, 0); //metricDataFormat
791     writeU16(w, num_advances);
792     return hea;
793 }
794 static void hea_dump(ttf_t*ttf)
795 {
796     table_hea_t*hea = ttf->hea;
797     if(!hea) return;
798     const char*dir = ttf->is_vertical?"v":"h";
799     printf("%shea->ascent: %d\n", dir, ttf->ascent);
800     printf("%shea->descent: %d\n", dir, ttf->descent);
801     printf("%shea->lineGap: %d\n", dir, ttf->lineGap);
802     printf("%shea->advanceWidthMax: %d\n", dir, hea->advanceWidthMax);
803     printf("%shea->minLeftSideBearing: %d\n", dir, hea->minLeftSideBearing);
804     printf("%shea->minRightSideBearing: %d\n", dir, hea->minRightSideBearing);
805     printf("%shea->xMaxExtent: %d\n", dir, hea->xMaxExtent);
806     printf("%shea->caretSlopeRise: %d\n", dir, hea->caretSlopeRise);
807     printf("%shea->caretSlopeRun: %d\n", dir, hea->caretSlopeRun);
808     printf("%shea->caretOffset: %d\n", dir, hea->caretOffset);
809 }
810 static void hea_delete(ttf_t*ttf)
811 {
812     if(ttf->hea) {
813         free(ttf->hea);
814         ttf->hea=0;
815     }
816 }
817
818 static void mtx_parse(memreader_t*r, ttf_t*ttf, int num_advances)
819 {
820     U16 old_advance = 0;
821     int t;
822     if(num_advances > r->size/4)
823         num_advances = r->size/4;
824     for(t=0;t<num_advances;t++) {
825         old_advance = ttf->glyphs[t].advance = readU16(r);
826         ttf->glyphs[t].bearing = readS16(r);
827     }
828     int rest = (r->size - num_advances*4)/2;
829     if(ttf->num_glyphs < num_advances+rest) {
830         rest = ttf->num_glyphs-num_advances;
831     }
832     for(t=0;t<rest;t++) {
833         ttf->glyphs[t].advance = old_advance; 
834         ttf->glyphs[t].bearing = readS16(r);
835     }
836 }
837 static int mtx_write(ttf_t*ttf, ttf_table_t*w)
838 {
839     int num_advances = ttf->num_glyphs;
840     if(ttf->num_glyphs>=2) {
841         int t;
842         for(t=ttf->num_glyphs-1;t>0;t--) {
843             if(ttf->glyphs[t-1].advance !=
844                ttf->glyphs[t].advance) break;
845         }
846         /* we need to store all individual advances as well
847            as one entry for the constant */
848         num_advances = t+1;
849     }
850
851     int t;
852     for(t=0;t<num_advances;t++) {
853         writeU16(w, ttf->glyphs[t].advance);
854         writeU16(w, ttf->glyphs[t].bearing);
855     }
856     for(;t<ttf->num_glyphs;t++) {
857         writeU16(w, ttf->glyphs[t].bearing);
858     }
859     return num_advances;
860 }
861
862 static U32*loca_parse(memreader_t*r, ttf_t*ttf, int size)
863 {
864     int t;
865     int num = ttf->num_glyphs+1;
866     U32*locations = rfx_calloc(num*sizeof(U32));
867     U32 lastloc = 0;
868     U32 loc = 0;
869     char warn_unsorted = 1;
870     if(size) {
871         if(num*4 > r->size) {
872             msg("<warning> Short 'loca' table (32 bit): %d/%d", r->size/4, num);
873             num=r->size/4;
874         }
875         if(num*4 < r->size) {
876             msg("<warning> Extraneous data (%d bytes) in 'loca' table (32 bit)", r->size-num*4);
877         }
878         for(t=0;t<num;t++) {
879             locations[t] = loc = readU32(r);
880             if(lastloc > loc && warn_unsorted) {
881                 msg("<warning> Unsorted 'loca' table (32 bit)");
882                 warn_unsorted=0;
883             }
884             lastloc = loc;
885         }
886     } else {
887         if(num*2 > r->size) {
888             msg("<warning> Short 'loca' table (16 bit)");
889             num=r->size/2;
890         }
891         if(num*2 < r->size) {
892             msg("<warning> Extraneous data (%d bytes) in 'loca' table (16 bit)", r->size-num*2);
893         }
894         for(t=0;t<num;t++) {
895             locations[t] = loc = readU16(r)*2;
896             if(lastloc > loc && warn_unsorted) {
897                 msg("<warning> Unsorted 'loca' table");
898                 warn_unsorted=0;
899             }
900             lastloc = loc;
901         }
902     }
903     return locations;
904 }
905 static int loca_write(ttf_t*ttf, ttf_table_t*w, U32*locations)
906 {
907     int t;
908     char use_32bit = 0;
909     for(t=0;t<=ttf->num_glyphs;t++) {
910         if(locations[t]>=0x20000 || (locations[t]&1)) {
911             use_32bit = 1;
912             break;
913         }
914     }
915
916     if(use_32bit) {
917         for(t=0;t<=ttf->num_glyphs;t++) {
918             writeU32(w, locations[t]);
919         }
920         return 1;
921     } else {
922         for(t=0;t<=ttf->num_glyphs;t++) {
923             writeU16(w, locations[t]/2);
924         }
925         return 0;
926     }
927 }
928
929 static int parse_simple_glyph(ttf_t*ttf, memreader_t*r, int num_contours, int glyphnr)
930 {
931     ttfglyph_t*glyph = &ttf->glyphs[glyphnr];
932
933     U16*endpoints = 0;
934     if(num_contours>0) {
935         endpoints = malloc(sizeof(U16)*num_contours);
936         int s;
937         int lastpos = -1;
938         for(s=0;s<num_contours;s++) {
939             int pos = endpoints[s] = readU16(r);
940             if(pos<=lastpos) {
941                 msg("<warning> Unsorted endpoints array (len:%d) last=%d now=%d", s, pos, lastpos);
942             }
943             lastpos = pos;
944         }
945     }
946     U16 code_len = readU16(r);
947     if(code_len) {
948         glyph->code = malloc(sizeof(U16)*code_len);
949         readBlock(r, glyph->code, code_len);
950         glyph->code_size = code_len;
951     }
952
953     if(!endpoints) 
954         return 1;
955
956     /*msg("<notice> TTF Glyph %d) code_size=%d num_contours=%d glyph->num_points=%d %d/%d/%d/%d", 
957             glyphnr, code_len, num_contours, glyph->num_points,
958             xmin, ymin, xmax, ymax);*/
959     INIT_READ(fx, r->mem, r->size, r->pos);
960     INIT_READ(fy, r->mem, r->size, r->pos);
961     
962     glyph->num_points = endpoints[num_contours-1] + 1;
963     glyph->points = rfx_calloc(sizeof(ttfpoint_t)*glyph->num_points);
964
965     /* parse flag array (1st pass- to determine start of coordinates) */
966     int num=0;
967     while(num<glyph->num_points) {
968         U8 flag = readU8(r);
969         if(flag&0xc0) {
970             msg("<error> Bad flags in glyph outline: %02x (at pos %d)", flag, num);
971             free(glyph->points);
972             glyph->points = 0;
973             glyph->num_points = 0;
974             return 0;
975         }
976         int count = 1;
977         if(flag & 0x08) 
978             count += readU8(r);
979         if(count+num>glyph->num_points) {
980             msg("<warning> Bad count (%d) in glyph (%d) (at pos %d)", count, glyphnr, num);
981             count = glyph->num_points-num;
982         }
983         num+=count;
984     }
985
986     /* parse flag array (2nd pass) and x coordinates */
987     num=0;
988     int x = 0;
989     char is_start=1;
990     int contour_pos=0;
991     int bytepos = r->pos;
992     while(num<glyph->num_points) {
993         U8 flag = readU8(&fx);
994         int count = flag&8?readU8(&fx)+1:1;
995         count=count>glyph->num_points-num?glyph->num_points-num:(count?count:1);
996         do {
997             char is_end=0;
998             if(contour_pos<num_contours && num==endpoints[contour_pos]) {
999                 contour_pos++;
1000                 is_end=1;
1001             }
1002             int oldx = x;
1003             if((flag&0x12) == 0x12) x += readU8(r);
1004             else if((flag&0x12) == 0x02) x -= readU8(r);
1005             else if((flag&0x12) == 0x00) x += readS16(r);
1006             
1007             glyph->points[num].x = x;
1008             U8 f = flag&GLYPH_ON_CURVE;
1009             if(is_start) f|=GLYPH_CONTOUR_START;
1010             if(is_end) f|=GLYPH_CONTOUR_END;
1011             glyph->points[num].flags = f;
1012             num++;
1013             is_start = is_end;
1014         } while(--count);
1015     }
1016     
1017     /* parse flag array (3rd pass) and y coordinates */
1018     num=0;
1019     int y = 0;
1020     while(num<glyph->num_points) {
1021         U8 flag = readU8(&fy);
1022         int count = flag&8?readU8(&fy)+1:1;
1023         count=count>glyph->num_points-num?glyph->num_points-num:(count?count:1);
1024         do {
1025             if((flag&0x24) == 0x24) y += readU8(r);
1026             else if((flag&0x24) == 0x04) y -= readU8(r);
1027             else if((flag&0x24) == 0x00) y += readS16(r);
1028             glyph->points[num].y = y;
1029             num++;
1030         } while(--count);
1031     }
1032     free(endpoints);
1033     return 1;
1034 }
1035 static void glyf_parse(memreader_t*rr, ttf_t*ttf, U32*loca)
1036 {
1037     int t;
1038     char warn_about_compound_glyphs=0;
1039     for(t=0;t<ttf->num_glyphs;t++) {
1040         INIT_READ(r, rr->mem, rr->size, loca[t]);
1041         if(loca[t]==loca[t+1] || loca[t]==r.size)
1042             continue; //empty glyph
1043         if(r.pos+10>r.size) {
1044             msg("<warning> Truncated glyph entry %d/%d (or bad loca entry %d/%d, next loca: %d)", 
1045                     t, ttf->num_glyphs, loca[t], r.size, loca[t+1]);
1046             break;
1047         }
1048         S16 num_contours = readS16(&r);
1049         ttf->glyphs[t].xmin = readS16(&r);
1050         ttf->glyphs[t].ymin = readS16(&r);
1051         ttf->glyphs[t].xmax = readS16(&r);
1052         ttf->glyphs[t].ymax = readS16(&r);
1053         
1054         if(num_contours<0) {
1055             if(warn_about_compound_glyphs)
1056                 msg("<error> Compound glyphs not supported yet");
1057             warn_about_compound_glyphs=0;
1058         } else {
1059             if(!parse_simple_glyph(ttf, &r, num_contours, t))
1060                 return;
1061         }
1062     }
1063
1064 }
1065 void write_simple_glyph(ttf_table_t*w, ttfglyph_t*g)
1066 {
1067     /* endpoints array */
1068     int s;
1069     for(s=0;s<g->num_points;s++) {
1070         if(g->points[s].flags&GLYPH_CONTOUR_END)
1071             writeU16(w, s);
1072     }
1073     
1074     /* bytecode */
1075     writeU16(w, g->code_size);
1076     if(g->code_size)
1077         writeBlock(w, g->code, g->code_size);
1078
1079     /* flags */
1080     int lastx=0;
1081     int lasty=0;
1082     int lastflag=-1;
1083     int flagcount=0;
1084     for(s=0;s<g->num_points;s++) {
1085         ttfpoint_t*p = &g->points[s];
1086         int dx = p->x - lastx;
1087         int dy = p->y - lasty;
1088         U8 flags = p->flags&GLYPH_ON_CURVE;
1089         if(!dx) {
1090             flags|=0x10;
1091         } else if(dx<0 && dx>=-255) {
1092             flags|=0x02;
1093         } else if(dx>0 && dx<=255) {
1094             flags|=0x12;
1095         }
1096         if(!dy) {
1097             flags|=0x20;
1098         } else if(dy<0 && dy>=-255) {
1099             flags|=0x04;
1100         } else if(dy>0 && dy<=255) {
1101             flags|=0x24;
1102         }
1103         if(flags == lastflag && flagcount<255) {
1104             flagcount++;
1105         } else {
1106             if(lastflag>=0) {
1107                 if(flagcount) {
1108                     writeU8(w, lastflag|8);
1109                     writeU8(w, flagcount);
1110                 } else {
1111                     writeU8(w, lastflag);
1112                 }
1113             }
1114             lastflag = flags;
1115             flagcount = 0;
1116         }
1117         lastx = p->x;
1118         lasty = p->y;
1119     }
1120     if(lastflag>=0) {
1121         if(flagcount) {
1122             writeU8(w, lastflag|8);
1123             writeU8(w, flagcount);
1124         } else {
1125             writeU8(w, lastflag);
1126         }
1127     }
1128     /* coordinates */
1129     lastx=0;
1130     int bytepos = w->len;
1131     for(s=0;s<g->num_points;s++) {
1132         ttfpoint_t*p = &g->points[s];
1133         int dx = p->x - lastx;
1134         if(dx>32767 || dx<-32768) {
1135             msg("<error> Coordinate overflow in glyph");
1136         }
1137         lastx = p->x;
1138         if(dx>0 && dx<=255) writeU8(w, dx);
1139         else if(dx<0 && dx>=-255) writeU8(w, -dx);
1140         else if(dx) writeS16(w, dx);
1141     }
1142
1143     lasty=0;
1144     for(s=0;s<g->num_points;s++) {
1145         ttfpoint_t*p = &g->points[s];
1146         int dy = p->y - lasty;
1147         if(dy>32767 || dy<-32768) {
1148             msg("<error> Coordinate overflow in glyph");
1149         }
1150         lasty = p->y;
1151         if(dy>0 && dy<=255) writeU8(w, dy);
1152         else if(dy<0 && dy>=-255) writeU8(w, -dy);
1153         else if(dy) writeS16(w, dy);
1154     }
1155 }
1156 U32* glyf_write(ttf_t* ttf, ttf_table_t*w)
1157 {
1158     U32*locations = malloc(sizeof(U32)*(ttf->num_glyphs+1));
1159     int t;
1160     for(t=0;t<ttf->num_glyphs;t++) {
1161         locations[t] = w->len;
1162         ttfglyph_t*g = &ttf->glyphs[t];
1163         int s;
1164         int num_contours = 0;
1165         for(s=0;s<g->num_points;s++) {
1166             if(g->points[s].flags&GLYPH_CONTOUR_END)
1167                 num_contours++;
1168         }
1169         writeS16(w, num_contours?num_contours:1);
1170         writeS16(w, g->xmin);
1171         writeS16(w, g->ymin);
1172         writeS16(w, g->xmax);
1173         writeS16(w, g->ymax);
1174         
1175         if(!num_contours) {
1176             /* some ttf parsers can't deal with zero contours, so in the case
1177                of an empty glyph, write a single point (0,0) */
1178             writeU16(w, 0); //endpoint of 1st contour
1179             writeU16(w, g->code_size);
1180             if(g->code_size)
1181                 writeBlock(w, g->code, g->code_size);
1182             writeU8(w, 0x31); //flag (xy=(0,0),on curve)
1183         } else {
1184             write_simple_glyph(w, g);
1185         }
1186     }
1187     locations[t] = w->len;
1188     return locations;
1189 }
1190 void glyf_dump(ttf_t* ttf)
1191 {
1192     if(!ttf->glyphs) return;
1193     int t;
1194     for(t=0;t<ttf->num_glyphs;t++) {
1195         ttfglyph_t*g = &ttf->glyphs[t];
1196         printf("glyph %d)\n", t);
1197         printf("  advance=%d\n", g->advance);
1198         printf("  bearing=%d\n", g->bearing);
1199         printf("  bbox=(%d/%d/%d/%d)\n", g->xmin, g->ymin, g->xmax, g->ymax);
1200         printf("  points=(");
1201         int s;
1202         for(s=0;s<g->num_points;s++) {
1203             if(s) printf(",");
1204             printf("%d/%d/0x%02x", g->points[s].x, g->points[s].y, g->points[s].flags);
1205         }
1206         printf(")\n");
1207         if(g->code_size) 
1208             hexdump(g->code, g->code_size, "  ");
1209     }
1210 }
1211 void glyf_delete(ttf_t* ttf)
1212 {
1213     if(!ttf->glyphs) 
1214         return;
1215     int t;
1216     for(t=0;t<ttf->num_glyphs;t++) {
1217         if(ttf->glyphs[t].code) {
1218             free(ttf->glyphs[t].code);
1219             ttf->glyphs[t].code = 0;
1220         }
1221         if(ttf->glyphs[t].points) {
1222             free(ttf->glyphs[t].points);
1223             ttf->glyphs[t].points = 0;
1224         }
1225     }
1226     free(ttf->glyphs);ttf->glyphs=0;
1227 }
1228
1229 static void grow_unicode(ttf_t*ttf, int index)
1230 {
1231     int size = index+1;
1232     if(!ttf->unicode) {
1233         ttf->unicode = rfx_calloc(sizeof(ttf->unicode[0])*size);
1234     } else if(ttf->unicode_size<size) {
1235         ttf->unicode = rfx_realloc(ttf->unicode, sizeof(ttf->unicode[0])*size);
1236         memset(ttf->unicode+ttf->unicode_size, 0, sizeof(ttf->unicode[0])*(size - ttf->unicode_size));
1237     }
1238     ttf->unicode_size = size;
1239 }
1240 void cmap_parse(memreader_t*r, ttf_t*ttf)
1241 {
1242     readU16(r); // version (0)
1243     int num_subtables = readU16(r);
1244     int t;
1245     char warn=1;
1246     if(r->pos+num_subtables*8 > r->size) {
1247         msg("<warning> CMap overflow");
1248         num_subtables = (r->size-r->pos)/8;
1249     }
1250     unicode_t*data = 0;
1251     for(t=0;t<num_subtables;t++) {
1252         U16 platform = readU16(r);
1253         U16 encoding = readU16(r);
1254         U32 offset = readU32(r);
1255         if(offset>r->size) {
1256             msg("<warning> CMAP table %d %d is out of bounds (%d)", platform, encoding, offset);
1257             continue;
1258         }
1259
1260         int is_unicode = platform==0 ||
1261                          platform==3 && encoding == 1 ||
1262                          platform==3 && encoding == 10;
1263
1264         if(!is_unicode) 
1265             continue;
1266
1267         INIT_READ(t, r->mem, r->size, offset);
1268         U16 format = readU16(&t);
1269         int length = readU16(&t);
1270         U16 language = readU16(&t);
1271
1272         if(language)
1273             msg("<warning> Language code %02x in unicode mapping", language);
1274
1275         int num = 0;
1276         if(format == 0) {
1277             num = length-6;
1278             if(t.pos+length > t.size) {
1279                 msg("<warning> overflow in format 0 cmap table");
1280                 num = t.size-t.pos;
1281             }
1282             data = malloc(num*sizeof(unicode_t));
1283             int s;
1284             grow_unicode(ttf, num);
1285             for(s=0;s<num;s++) {
1286                 ttf->unicode[s] = readU8(&t);
1287             }
1288         } else if(format == 4) {
1289             U16 segment_count = readU16(&t); 
1290             if(segment_count&1) {
1291                 msg("<error> Bad segmentx2 count %d", segment_count);
1292                 continue;
1293             }
1294             segment_count>>=1;
1295             readU16(&t); //searchrange
1296             readU16(&t); //entry selector
1297             readU16(&t); //range shift
1298             INIT_READ(r_end, t.mem, t.size, t.pos);
1299             INIT_READ(r_start, t.mem, t.size, t.pos+2+segment_count*2);
1300             INIT_READ(r_delta, t.mem, t.size, t.pos+2+segment_count*4);
1301             INIT_READ(r_range, t.mem, t.size, t.pos+2+segment_count*6);
1302             int glyphmap_start = t.pos+2+segment_count*8;
1303             int glyphmap_size = t.size - glyphmap_start;
1304             int s;
1305             for(s=0;s<segment_count;s++) {
1306                 U16 start = readU16(&r_start);
1307                 U16 end = readU16(&r_end);
1308                 U16 delta = readU16(&r_delta);
1309                 U16 range = readU16(&r_range);
1310                 if(start==0xffff && end==0xffff && delta==1) {
1311                     /* this is a common (maybe even required) occurence in fonts 
1312                        which explicitly map "unicode undefined" (0xffff) to 
1313                        "glyph undefined" (0).
1314                        We don't want to blow our unicode table up to 65536 just
1315                        because of this, so ignore this entry.
1316                      */
1317                     continue;
1318                 }
1319                 grow_unicode(ttf, end);
1320                 int u;
1321                 if(!range) {
1322                     for(u=start;u<=end;u++) {
1323                         ttf->unicode[u] = (u + delta) & 0xffff;
1324                     }
1325                 } else {
1326                     int pos = r_range.pos-2+range;
1327                     if(warn && pos+end-start+1 > t.size) {
1328                         msg("<warning> glyphmap index out of bounds (%d-%d/%d)", pos, pos+end-start, t.size);
1329                         warn=0;
1330                     }
1331                     INIT_READ(g, t.mem, t.size, pos);
1332                     for(u=start;u<=end;u++) {
1333                         ttf->unicode[u] = readU16(&g);
1334                     }
1335                 }
1336             }
1337         }
1338     }
1339 }
1340 static int segment_size(unicode_t*unicode, int pos, int size)
1341 {
1342     int s;
1343     int count=0;
1344     for(s=pos;s<size;s++) {
1345         if(!unicode[s])
1346             count++;
1347         if(count>4) {
1348             /* a segment costs us 8 bytes, so for more than 4 consecutive 
1349                zero entries (16 bit each) in the glyph index array,
1350                it pays off to start a new segment */
1351             break;
1352         }
1353     }
1354     s -= count; // go to the last filled in entry
1355     if(s==size)
1356         return size-1;
1357     return s;
1358 }
1359 void cmap_write(ttf_t* ttf, ttf_table_t*w)
1360 {
1361     writeU16(w, 0);  //version
1362     writeU16(w, 2);  //two tables
1363
1364     writeU16(w, 0);  //platform (unicode)
1365     writeU16(w, 3);  //encoding (unicode 2.0)
1366     writeU32(w, 20); //offset
1367
1368     writeU16(w, 3);  //platform (windows)
1369     writeU16(w, 1);  //encoding (unicode basic multilingual plane UCS-2)
1370     writeU32(w, 20); //offset
1371
1372     writeU16(w, 4); // format=4
1373     int length_pos = w->len;
1374     writeU16(w, 0); // length: we don't know yet
1375     writeU16(w, 0); // language (n/a for unicode)
1376     int num_segments_pos = w->len;
1377     writeU16(w, 0); //number of segments: we don't know yet either
1378     writeU16(w, 0); //searchrange
1379     writeU16(w, 0); //entry selector
1380     writeU16(w, 0); //range shift
1381
1382     int pos=0;
1383     int num_segments=0;
1384     while(pos < ttf->unicode_size) {
1385         if(!ttf->unicode[pos]) {
1386             pos++;
1387             continue;
1388         }
1389         int s = segment_size(ttf->unicode, pos, ttf->unicode_size);
1390         pos = s+1;
1391         num_segments++;
1392     }
1393
1394     num_segments++; // account for 0xffff mapping
1395
1396     int glyphmap_start = w->len+2+num_segments*8;
1397     
1398     int t;
1399     int end_pos = w->len;
1400     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //end array
1401     writeU16(w, 0); //reserved byte
1402     int start_pos = w->len;
1403     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //start array
1404     int delta_pos = w->len;
1405     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //delta array
1406     int range_pos = w->len;
1407     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //range array
1408             
1409     w->data[num_segments_pos]=(num_segments*2)>>8;
1410     w->data[num_segments_pos+1]=(num_segments*2);
1411     
1412     pos=0;
1413     num_segments = 0;
1414     while(pos < ttf->unicode_size) {
1415         if(!ttf->unicode[pos]) {
1416             pos++;
1417             continue;
1418         }
1419         U16 end = segment_size(ttf->unicode, pos, ttf->unicode_size);
1420         w->data[end_pos++]=end>>8;
1421         w->data[end_pos++]=end;
1422         w->data[start_pos++]=pos>>8;
1423         w->data[start_pos++]=pos;
1424         int s;
1425         U16 delta = ttf->unicode[pos]-pos;
1426         char do_delta=1;
1427         for(s=pos+1;s<=end;s++) {
1428             U16 delta2 = ttf->unicode[s]-s;
1429             if(delta2!=delta) {
1430                 do_delta=0;
1431                 break;
1432             }
1433         }
1434         U16 range;
1435         if(do_delta) {
1436             range = 0;
1437         } else {
1438             delta = 0;
1439             range = w->len - range_pos;
1440             for(s=pos;s<=end;s++) {
1441                 writeU16(w, ttf->unicode[s]);
1442             }
1443         }
1444         w->data[delta_pos++]=delta>>8;
1445         w->data[delta_pos++]=delta;
1446         w->data[range_pos++]=range>>8;
1447         w->data[range_pos++]=range;
1448         num_segments++;
1449         pos = end+1;
1450     }
1451
1452     /* write out a mapping from 0xffff to 0- seems to be required
1453        by some libraries (e.g. fonttools) */
1454     w->data[end_pos++]=0xff;
1455     w->data[end_pos++]=0xff;
1456     w->data[start_pos++]=0xff;
1457     w->data[start_pos++]=0xff;
1458     w->data[delta_pos++]=0;
1459     w->data[delta_pos++]=1;
1460     w->data[range_pos++]=0;
1461     w->data[range_pos++]=0;
1462
1463     w->data[length_pos]=(w->len-20)>>8;
1464     w->data[length_pos+1]=w->len-20;
1465 }
1466 void cmap_delete(ttf_t*ttf)
1467 {
1468     if(ttf->unicode) {
1469         free(ttf->unicode);
1470         ttf->unicode=0;
1471     }
1472     ttf->unicode_size=0;
1473 }
1474 static char*readString(memreader_t*r, int len)
1475 {
1476     char*s = malloc(len+1);
1477     readBlock(r, s, len);
1478     s[len] = 0;
1479     return s;
1480 }
1481 void name_parse(memreader_t*r, ttf_t*ttf)
1482 {
1483     U16 format = readU16(r);
1484     U16 count = readU16(r);
1485     U16 offset = readU16(r);
1486    
1487     int t;
1488     for(t=0;t<count;t++) {
1489         U16 platform = readU16(r);
1490         U16 encoding = readU16(r);
1491         U16 language = readU16(r);
1492         U16 name_id = readU16(r);
1493         U16 len = readU16(r);
1494         U16 offset_2 = readU16(r);
1495         
1496         INIT_READ(ss, r->mem, r->size, offset+offset_2);
1497         if(!(platform==0 || (platform==1 && encoding==0)))
1498                 continue;
1499
1500         INIT_READ(s, r->mem, r->size, offset+offset_2);
1501
1502         if(name_id==1) {
1503             if(ttf->family_name) free(ttf->family_name);
1504             ttf->family_name = readString(&s, len);
1505         }
1506         if(name_id==2) {
1507             if(ttf->subfamily_name) free(ttf->subfamily_name);
1508             ttf->subfamily_name = readString(&s, len);
1509         }
1510         if(name_id==3) {
1511             if(ttf->version_string) free(ttf->version_string);
1512             ttf->version_string = readString(&s, len);
1513         }
1514         if(name_id==4) {
1515             if(ttf->full_name) free(ttf->full_name);
1516             ttf->full_name = readString(&s, len);
1517         }
1518     }
1519 }
1520 void name_write(ttf_t*ttf, ttf_table_t*table)
1521 {
1522     char*strings[4] = {ttf->full_name, ttf->family_name, ttf->subfamily_name, ttf->version_string};
1523     int codes[4] = {4,1,2,3};
1524
1525     writeU16(table, 0); //format
1526     int count = 0;
1527     int t;
1528     int nr = sizeof(strings)/sizeof(strings[0]);
1529     
1530     for(t=0;t<nr;t++) {
1531         if(strings[t])
1532             count++;
1533     }
1534     writeU16(table, count); //count
1535
1536     int offset_pos = table->len;
1537     writeU16(table, 0); //offset (will be filled in later)
1538
1539     int offset = 0;
1540     for(t=0;t<nr;t++) { 
1541         if(strings[t]) {
1542             writeU16(table, 1); //platform id
1543             writeU16(table, 0); //encoding id
1544             writeU16(table, 0); //language
1545             writeU16(table, codes[t]); //4: full name
1546             int len = strlen(strings[t]);
1547             writeU16(table, len);
1548             writeU16(table, offset);
1549             offset += len;
1550         }
1551     }
1552     table->data[offset_pos] = table->len>>8;
1553     table->data[offset_pos+1] = table->len;
1554
1555     for(t=0;t<nr;t++) { 
1556         if(strings[t]) {
1557             int len = strlen(strings[t]);
1558             writeBlock(table, strings[t], len);
1559         }
1560     }
1561 }
1562 void name_delete(ttf_t*ttf)
1563 {
1564     if(ttf->full_name) {
1565         free(ttf->full_name);
1566         ttf->full_name=0;
1567     }
1568     if(ttf->family_name) {
1569         free(ttf->family_name);
1570         ttf->family_name=0;
1571     }
1572     if(ttf->subfamily_name) {
1573         free(ttf->subfamily_name);
1574         ttf->subfamily_name=0;
1575     }
1576     if(ttf->version_string) {
1577         free(ttf->version_string);
1578         ttf->version_string=0;
1579     }
1580 }
1581
1582 static table_post_t*post_new(ttf_t*ttf)
1583 {
1584     table_post_t*post = rfx_calloc(sizeof(table_post_t));
1585     return post;
1586 }
1587 void post_parse(memreader_t*r, ttf_t*ttf)
1588 {
1589     table_post_t*post = ttf->post = rfx_calloc(sizeof(table_post_t));
1590     U16 format = readU16(r);
1591     post->italic_angle = readU16(r);
1592     post->underline_position = readU16(r);
1593     post->underline_thickness = readU16(r);
1594     U16 is_monospaced = readU16(r);
1595     readU16(r); // min mem 42
1596     readU16(r);
1597     readU16(r); // min mem 1
1598     readU16(r);
1599 }
1600 void post_write(ttf_t*ttf, ttf_table_t*table)
1601 {
1602     table_post_t*post = ttf->post;
1603     writeU32(table, 0x00030000);
1604     writeU32(table, post->italic_angle);
1605     writeU16(table, post->underline_position);
1606     writeU16(table, post->underline_thickness);
1607     writeU32(table, 0); //is monospaced TODO
1608     writeU32(table, 0); //min mem 42
1609     writeU32(table, 0);
1610     writeU32(table, 0); //min mem 1
1611     writeU32(table, 0);
1612 }
1613 void post_delete(ttf_t*ttf)
1614 {
1615     if(ttf->post) {
1616         free(ttf->post);
1617         ttf->post = 0;
1618     }
1619 }
1620
1621 static int ttf_parse_tables(ttf_t*ttf)
1622 {
1623     ttf_table_t*table;
1624
1625     table = ttf_find_table(ttf, TAG_HEAD);
1626     if(!table) {
1627         msg("<error> Font has no head table");
1628         return 0;
1629     }
1630     INIT_READ(m, table->data, table->len, 0);
1631     int loc_index = head_parse(ttf, &m);
1632     ttf_table_delete(ttf, table);
1633     
1634     table = ttf_find_table(ttf, TAG_MAXP);
1635     if(!table) {
1636         msg("<error> Font has no maxp table");
1637         return 0;
1638     }
1639     INIT_READ(m2, table->data, table->len, 0);
1640     ttf->maxp = maxp_parse(ttf, &m2);
1641     ttf_table_delete(ttf, table);
1642     
1643     if(!ttf->num_glyphs) {
1644         msg("<error> Invalid number of characters");
1645         return 0;
1646     }
1647     ttf->glyphs = rfx_calloc(sizeof(ttfglyph_t)*ttf->num_glyphs);
1648
1649     table = ttf_find_table(ttf, TAG_OS2);
1650     if(table) {
1651         INIT_READ(m, table->data, table->len, 0);
1652         ttf->os2 = os2_parse(&m);
1653         ttf_table_delete(ttf, table);
1654     }
1655
1656     table = ttf_find_table(ttf, TAG_HHEA);
1657     if(table) {
1658         INIT_READ(m, table->data, table->len, 0);
1659         int num_advances = hea_parse(&m, ttf);
1660         ttf_table_delete(ttf, table);
1661         
1662         table = ttf_find_table(ttf, TAG_HMTX);
1663         if(table) {
1664             INIT_READ(m, table->data, table->len, 0);
1665             mtx_parse(&m, ttf, num_advances);
1666             ttf_table_delete(ttf, table);
1667         }
1668     } else {
1669         table = ttf_find_table(ttf, TAG_VHEA);
1670         if(table) {
1671             ttf->is_vertical=1;
1672             INIT_READ(m, table->data, table->len, 0);
1673             int num_advances = hea_parse(&m, ttf);
1674             ttf_table_delete(ttf, table);
1675
1676             table = ttf_find_table(ttf, TAG_VMTX);
1677             if(table) {
1678                 INIT_READ(m, table->data, table->len, 0);
1679                 mtx_parse(&m, ttf, num_advances);
1680                 ttf_table_delete(ttf, table);
1681             }
1682         } else {
1683             msg("<error> Font contains neither HHEA nor VHEA");
1684         }
1685     }
1686     table = ttf_find_table(ttf, TAG_LOCA);
1687     if(table) {
1688         INIT_READ(m, table->data, table->len, 0);
1689         U32*loca = loca_parse(&m, ttf, loc_index);
1690         ttf_table_delete(ttf, table);
1691         table = ttf_find_table(ttf, TAG_GLYF);
1692         if(table) {
1693             INIT_READ(m, table->data, table->len, 0);
1694             glyf_parse(&m, ttf, loca);
1695             ttf_table_delete(ttf, table);
1696         }
1697         free(loca);
1698     }
1699     
1700     table = ttf_find_table(ttf, TAG_CMAP);
1701     if(table) {
1702         INIT_READ(m, table->data, table->len, 0);
1703         cmap_parse(&m, ttf);
1704         ttf_table_delete(ttf, table);
1705     }
1706     
1707     table = ttf_find_table(ttf, TAG_NAME);
1708     if(table) {
1709         INIT_READ(m, table->data, table->len, 0);
1710         name_parse(&m, ttf);
1711         ttf_table_delete(ttf, table);
1712     }
1713
1714     table = ttf_find_table(ttf, TAG_POST);
1715     if(table) {
1716         INIT_READ(m, table->data, table->len, 0);
1717         post_parse(&m, ttf);
1718         ttf_table_delete(ttf, table);
1719     }
1720
1721     return 1;
1722 }
1723 static void ttf_collapse_tables(ttf_t*ttf)
1724 {
1725     ttf_table_t*table;
1726     
1727     ttf_table_t*head = ttf_find_table(ttf, TAG_HEAD);
1728     if(head) 
1729         return; //already collapsed
1730   
1731     if(ttf->maxp) {
1732         table = ttf_addtable(ttf, TAG_MAXP);
1733         maxp_write(ttf, table);
1734         maxp_delete(ttf);
1735     }
1736
1737     if(ttf->os2) {
1738         table = ttf_addtable(ttf, TAG_OS2);
1739         os2_write(ttf, table);
1740         os2_delete(ttf);
1741     }
1742
1743     if(ttf->hea) {
1744         if(!ttf->is_vertical) {
1745             table = ttf_addtable(ttf, TAG_HMTX);
1746             int num_advances = mtx_write(ttf, table);
1747             table = ttf_addtable(ttf, TAG_HHEA);
1748             hea_write(ttf, table, num_advances);
1749             hea_delete(ttf);
1750         } else {
1751             table = ttf_addtable(ttf, TAG_VMTX);
1752             int num_advances = mtx_write(ttf, table);
1753             table = ttf_addtable(ttf, TAG_VHEA);
1754             hea_write(ttf, table, num_advances);
1755             hea_delete(ttf);
1756         }
1757     }
1758         
1759     int loca_size=0;
1760     if(ttf->num_glyphs) {
1761         if(ttf->unicode) {
1762             table = ttf_addtable(ttf, TAG_CMAP);
1763             cmap_write(ttf, table);
1764             cmap_delete(ttf);
1765         }
1766
1767         if(ttf->glyphs) {
1768             table = ttf_addtable(ttf, TAG_GLYF);
1769             U32*locations = glyf_write(ttf, table);
1770             table = ttf_addtable(ttf, TAG_LOCA);
1771             loca_size = loca_write(ttf, table, locations);
1772             free(locations);
1773             glyf_delete(ttf);
1774         }
1775     }
1776
1777     if(ttf->full_name || ttf->family_name || ttf->subfamily_name) {
1778         table = ttf_addtable(ttf, TAG_NAME);
1779         name_write(ttf, table);
1780         name_delete(ttf);
1781     }
1782     if(ttf->post) {
1783         table = ttf_addtable(ttf, TAG_POST);
1784         post_write(ttf, table);
1785         post_delete(ttf);
1786     }
1787     
1788     table = ttf_addtable(ttf, TAG_HEAD);
1789     head_write(ttf, table, loca_size);
1790     head_delete(ttf);
1791 }
1792
1793 ttf_t*ttf_new()
1794 {
1795     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
1796     ttf->version = VERSION_1_0;
1797     return ttf;
1798 }
1799 ttf_t* ttf_load(void*data, int length)
1800 {
1801     INIT_READ(r,data,length, 0);
1802
1803     if(length<12) {
1804         msg("<error> Truncated Truetype file (%d bytes)", length);
1805         return 0;
1806     }
1807
1808     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
1809     ttf->version = readU32(&r);
1810     if(ttf->version == SWAP32(length)) {
1811         U32 fontDataSize = readU32(&r);
1812         U32 version = readU32(&r);
1813         U32 flags  = readU32(&r);
1814         U8 panose[10]; 
1815         readBlock(&r, panose, 10);
1816         readU8(&r); //charset
1817         readU8(&r); //italoc
1818         readU32(&r); //weight
1819         readU16(&r); //fstype
1820         U16 magic = readU16(&r); //magicNumber
1821         /* we're being paranoid: it's entirely possible for the font
1822            size to be exactly 0x10000. Only treat this font as eot if
1823            it has the right magic number */
1824         if(magic == 0x4c50) {
1825             readU32(&r); //unicoderange[0]
1826             readU32(&r); //unicoderange[1]
1827             readU32(&r); //unicoderange[2]
1828             readU32(&r); //unicoderange[3]
1829             readU32(&r); //codepagerange[0]
1830             readU32(&r); //codepagerange[1]
1831             readU32(&r); //checksumadjustment
1832             readU32(&r); //reserved[0]
1833             readU32(&r); //reserved[1]
1834             readU32(&r); //reserved[2]
1835             readU32(&r); //reserved[3]
1836             readU16(&r); //padding
1837
1838             int nr=0;
1839             for(nr=0;nr<4;nr++) {
1840                 int t, len;
1841                 /* All of ttf is big-endian. All of ttf? No. One small eot table
1842                    of indomitable little-endian... */
1843                 len = readU8(&r);
1844                 len |= readU8(&r)<<8;
1845                 len /= 2;
1846                 for(t=0;t<len;t++) {
1847                     U8 c = readU16(&r)>>8;
1848                 }
1849                 readU16(&r); // zero terminator
1850             }
1851             readU16(&r); // more padding
1852
1853             /* adjust the offset to the start of the actual truetype
1854                data- the positions in the table header will be relative
1855                to the ttf data after the header, not to the file */
1856             r.mem += r.pos;
1857             r.size -= r.pos;
1858             r.pos = 0;
1859             ttf->version = readU32(&r);
1860         } else {
1861             reader_reset(&r);
1862             ttf->version = readU32(&r);
1863         }
1864     }
1865
1866     if(ttf->version == TTCFTAG) {
1867         /* a ttc collection is a number of truetype fonts
1868            packaged together */
1869         if(length<16) {
1870             msg("<error> Truncated TTC file (%d bytes)", length);
1871             return 0;
1872         }
1873         U32 ttcf_version = readU32(&r); // 0x00000100: v1.0, 0x00000200: v2.0, includes DSIG table
1874         U32 num_fonts = readU32(&r); // number of fonts
1875         U32 font1_position = readU32(&r);
1876         if(font1_position+12 > length) {\
1877             msg("<error> Truncated TTC file (%d bytes, first font at %d)", length, font1_position);
1878             return 0;
1879         }
1880         r.pos = font1_position;
1881         ttf->version = readU32(&r);
1882     }
1883     
1884     int num_tables = readU16(&r);
1885     
1886     readU16(&r); //search range
1887     readU16(&r); //entry selector
1888     readU16(&r); //range shift
1889
1890     if(num_tables*16 > length) {
1891         msg("<error> Truncated TTF file (table entries: %d)", num_tables);
1892         if(ttf->version != OPENTYPE && 
1893            ttf->version != TRUETYPE_MACOS && 
1894            ttf->version != VERSION_1_0) {
1895             // bad table length, weird version. This is probably not a ttf file.
1896             return 0;
1897         }
1898     }
1899
1900     U32*table_data = malloc(16*num_tables);
1901     int t;
1902     for(t=0;t<num_tables*4;t++) {
1903         table_data[t] = readU32(&r);
1904     }
1905     for(t=0;t<num_tables;t++) {
1906         U32 tag = table_data[t*4];
1907         U32 checksum = table_data[t*4+1];
1908         U32 pos = table_data[t*4+2];
1909         U32 len = table_data[t*4+3];
1910
1911         if(pos+len > length) {
1912             msg("<error> TTF Table %02x%02x%02x%02x outside of stream (pos %d)", (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, pos);
1913         } else {
1914             U8*mem = malloc(len);
1915             r.pos = pos;
1916             readBlock(&r, mem, len);
1917             
1918             ttf_table_t*table = ttf_addtable(ttf, tag);
1919             table->data = mem;
1920             table->len = table->memsize = len;
1921 #if 0
1922             U32 checksum2 = ttf_table_checksum(table);
1923             if(checksum2!=checksum) {
1924                 msg("<warning> Checksum mismatch in tag %02x%02x%02x%02x %c%c%c%c (%d bytes) %08x!=%08x", 
1925                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
1926                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
1927                         len, checksum2, checksum);
1928             }
1929 #endif
1930         }
1931     }
1932     free(table_data);
1933
1934     if(!ttf_parse_tables(ttf)) 
1935         return 0;
1936
1937     return ttf;
1938 }
1939 void ttf_create_truetype_tables(ttf_t*ttf)
1940 {
1941     if(!ttf->head) 
1942         ttf->head = head_new(ttf);
1943     if(!ttf->maxp) 
1944         ttf->maxp = maxp_new(ttf);
1945     if(!ttf->hea)
1946         ttf->hea = hea_new(ttf);
1947     if(!ttf->os2)
1948         ttf->os2 = os2_new(ttf);
1949     if(!ttf->post)
1950         ttf->post = post_new(ttf);
1951 }
1952
1953 ttf_table_t* ttf_write(ttf_t*ttf, U32*checksum_adjust)
1954 {
1955     ttf_collapse_tables(ttf);
1956    
1957     ttf_table_t*file = ttf_table_new(0);
1958     writeU32(file, VERSION_1_0);
1959
1960     /* write number of tables */
1961     int num_tables=0;
1962     ttf_table_t*t = ttf->tables;
1963     while(t) {
1964         num_tables++;
1965         t = t->next;
1966     }
1967     writeU16(file, num_tables);
1968     
1969     /* write search range */
1970     int tmp = num_tables;
1971     int search_range = 0;
1972     while(tmp) {
1973         search_range = tmp;
1974         tmp = tmp&(tmp-1);
1975     }
1976     tmp = search_range;
1977     search_range*=16;
1978     writeU16(file, search_range);
1979
1980     /* write entry selector */
1981     int entry_selector = 0;
1982     while(tmp>1) {
1983         tmp>>=1;
1984         entry_selector++;
1985     }
1986     writeU16(file, entry_selector);
1987
1988     /* write range shift */
1989     int range_shift = num_tables*16 - search_range;
1990     writeU16(file, range_shift);
1991
1992     /* write table dictionary */
1993     int table_dictionary_pos = file->len;
1994     int data_pos = file->len + num_tables*16;
1995     for(t=ttf->tables;t;t=t->next) {
1996         writeU32(file, t->id);
1997         writeU32(file, ttf_table_checksum(t));
1998         writeU32(file, data_pos);
1999         writeU32(file, t->len);
2000         data_pos += t->len;
2001         data_pos += (-t->len)&3; //pad
2002     }
2003
2004     /* write tables */
2005     int head_pos = 0;
2006     U8 zero[4]={0,0,0,0};
2007     for(t=ttf->tables;t;t=t->next) {
2008         if(t->id == TAG_HEAD)
2009             head_pos = file->len;
2010         writeBlock(file, t->data, t->len);
2011         writeBlock(file, zero, (-t->len)&3); //pad
2012     }
2013     U32 checksum = 0xb1b0afba - ttf_table_checksum(file);
2014     if(checksum_adjust)
2015         *checksum_adjust = checksum;
2016     U8*checksum2 = file->data + head_pos + 8;
2017     checksum2[0] = checksum>>24;
2018     checksum2[1] = checksum>>16;
2019     checksum2[2] = checksum>>8;
2020     checksum2[3] = checksum>>0;
2021     return file;
2022 }
2023
2024 ttf_table_t* ttf_eot_head(ttf_t*ttf)
2025 {
2026     ttf_table_t*file = ttf_table_new(0);
2027     writeU32(file, 0); //file size (filled in later)
2028     writeU32(file, 0); //fontdatasize (filled in later)
2029     writeU32(file, 0x01000200);
2030     writeU32(file, 0); //flags
2031     writeU8(file, ttf->os2->panose_FamilyType);
2032     writeU8(file, ttf->os2->panose_SerifStyle);
2033     writeU8(file, ttf->os2->panose_Weight);
2034     writeU8(file, ttf->os2->panose_Proportion);
2035     writeU8(file, ttf->os2->panose_Contrast);
2036     writeU8(file, ttf->os2->panose_StrokeVariation);
2037     writeU8(file, ttf->os2->panose_ArmStyle);
2038     writeU8(file, ttf->os2->panose_Letterform);
2039     writeU8(file, ttf->os2->panose_Midline);
2040     writeU8(file, ttf->os2->panose_XHeight);
2041     writeU8(file, 1); //charset (default)
2042     writeU8(file, ttf->os2->fsSelection&1); //italic
2043     writeU32_LE(file, ttf->os2->usWeightClass);
2044     writeU16(file, 0); //fstype
2045     writeU16(file, 0x4c50); //magic
2046     writeU32_LE(file, ttf->os2->ulCharRange[0]);
2047     writeU32_LE(file, ttf->os2->ulCharRange[1]);
2048     writeU32_LE(file, ttf->os2->ulCharRange[2]);
2049     writeU32_LE(file, ttf->os2->ulCharRange[3]);
2050     writeU32_LE(file, ttf->os2->ulCodePageRange1);
2051     writeU32_LE(file, ttf->os2->ulCodePageRange2);
2052     writeU32(file, 0); //checksum adjust (filled in later)
2053     writeU32(file, 0); //reserved[0]
2054     writeU32(file, 0); //reserved[1]
2055     writeU32(file, 0); //reserved[2]
2056     writeU32(file, 0); //reserved[3]
2057     writeU16(file, 0); //padding(1)
2058
2059     int t,len;
2060
2061     //family name
2062     len = strlen(ttf->family_name);
2063     writeU16_LE(file, len*2);
2064     for(t=0;t<len;t++) {
2065         writeU8(file, 0);
2066         writeU8(file, ttf->family_name[t]);
2067     }
2068     writeU16(file, 0); //zero byte pad
2069
2070     //subfamily name
2071     len = strlen(ttf->subfamily_name);
2072     writeU16_LE(file, len*2);
2073     for(t=0;t<len;t++) {
2074         writeU8(file, 0);
2075         writeU8(file, ttf->subfamily_name[t]);
2076     }
2077     writeU16(file, 0); //zero byte pad
2078
2079     //version string
2080     len = strlen(ttf->version_string);
2081     writeU16_LE(file, len*2); //len
2082     for(t=0;t<len;t++) {
2083         writeU8(file, 0);
2084         writeU8(file, ttf->version_string[t]);
2085     }
2086     writeU16(file, 0); //zero byte pad
2087
2088     //full name
2089     len = strlen(ttf->full_name);
2090     writeU16_LE(file, len*2); //len
2091     for(t=0;t<len;t++) {
2092         writeU8(file, 0);
2093         writeU8(file, ttf->full_name[t]);
2094     }
2095     writeU16(file, 0); //zero byte pad
2096
2097     writeU16(file, 0); //padding(2)
2098     return file;
2099 }
2100
2101 void ttf_save_eot(ttf_t*ttf, const char*filename)
2102 {
2103     ttf_table_t* eot = ttf_eot_head(ttf);
2104     U32 checksum_adjust = 0;
2105     ttf_table_t* t = ttf_write(ttf, &checksum_adjust);
2106
2107     U8*len_data = eot->data;
2108     U32 full_len = eot->len + t->len;
2109     len_data[0] = full_len>>0;
2110     len_data[1] = full_len>>8;
2111     len_data[2] = full_len>>16;
2112     len_data[3] = full_len>>24;
2113     
2114     U8*len_data2 = eot->data+4;
2115     len_data2[0] = t->len>>0;
2116     len_data2[1] = t->len>>8;
2117     len_data2[2] = t->len>>16;
2118     len_data2[3] = t->len>>24;
2119
2120     U8*checksum_data = eot->data + 60;
2121     checksum_data[0] = checksum_adjust>>0;
2122     checksum_data[1] = checksum_adjust>>8;
2123     checksum_data[2] = checksum_adjust>>16;
2124     checksum_data[3] = checksum_adjust>>24;
2125
2126     FILE*fi = fopen(filename, "wb");
2127     if(!fi) {
2128         perror(filename);
2129         return;
2130     }
2131
2132     fwrite(eot->data, eot->len, 1, fi);
2133     fwrite(t->data, t->len, 1, fi);
2134     fclose(fi);
2135     ttf_table_delete(0, t);
2136     ttf_table_delete(0, eot);
2137 }
2138
2139 void ttf_save(ttf_t*ttf, const char*filename)
2140 {
2141     ttf_table_t* t = ttf_write(ttf, 0);
2142     FILE*fi = fopen(filename, "wb");
2143     if(!fi) {
2144         perror(filename);
2145         return;
2146     }
2147     fwrite(t->data, t->len, 1, fi);
2148     fclose(fi);
2149     ttf_table_delete(0, t);
2150 }
2151
2152 void ttf_dump(ttf_t*ttf)
2153 {
2154     msg("<notice> Truetype file version %08x%s", ttf->version, ttf->version == OPENTYPE?" (opentype)":"");
2155     ttf_table_t*table = ttf->tables;
2156     while(table) {
2157         U32 tag = table->id;
2158         msg("<notice> Tag %02x%02x%02x%02x [%c%c%c%c] (length: %d)", 
2159                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, 
2160                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, table->len);
2161         table = table->next;
2162     }
2163     //ttf_table_dump(ttf_find_table(ttf, TAG_MAXP));
2164
2165     head_dump(ttf);
2166     hea_dump(ttf);
2167     os2_dump(ttf);
2168     maxp_dump(ttf);
2169     glyf_dump(ttf);
2170 }
2171 void ttf_destroy_tables(ttf_t*ttf)
2172 {
2173     ttf_table_t*table = ttf->tables;
2174     while(table) {
2175         ttf_table_t*next = table->next;
2176         free(table->data);
2177         free(table);
2178         table = next;
2179     }
2180     ttf->tables = 0;
2181 }
2182 void ttf_reduce(ttf_t*ttf)
2183 {
2184     ttf_destroy_tables(ttf);
2185 }
2186 void ttf_destroy(ttf_t*ttf)
2187 {
2188     ttf_destroy_tables(ttf);
2189     maxp_delete(ttf);
2190     os2_delete(ttf);
2191     head_delete(ttf);
2192     hea_delete(ttf);
2193     glyf_delete(ttf);
2194     post_delete(ttf);
2195     name_delete(ttf);
2196     free(ttf);
2197 }
2198
2199 #ifdef MAIN
2200 int main(int argn, const char*argv[])
2201 {
2202     setConsoleLogging(7);
2203     const char*filename = "comic.ttf";
2204     if(argn>1) 
2205         filename = argv[1];
2206     //msg("<notice> Loading %s", filename);
2207     memfile_t*m = memfile_open(filename);
2208     ttf_t*ttf = ttf_load(m->data, m->len);
2209     if(!ttf) {
2210         msg("<error> Couldn't load %s", filename);
2211         return 1;
2212     }
2213     ttf_reduce(ttf);
2214     
2215     ttf->full_name = strdup("Test-Normal");
2216     ttf->family_name = strdup("Test");
2217     ttf->subfamily_name = strdup("Normal");
2218     ttf->version_string = strdup("Version 1.0");
2219
2220     if(!ttf) return 1;
2221     memfile_close(m);
2222     //ttf_dump(ttf);
2223     //printf("os2 version: %04x (%d), maxp size: %d\n", 
2224 //          ttf->os2->version, ttf->os2->size, ttf->maxp->size);
2225     ttf_save_eot(ttf, "testfont.eot");
2226     ttf_save(ttf, "testfont.ttf");
2227     ttf_destroy(ttf);
2228     return 0;
2229
2230 }
2231 #endif