made .ttf files work on windows
[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+=2;
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 (mac)
1543             writeU16(table, 0); //encoding id (latin-1)
1544             writeU16(table, 0); //language (english)
1545             writeU16(table, codes[t]);
1546             int len = strlen(strings[t]);
1547             writeU16(table, len);
1548             writeU16(table, offset);
1549             offset += len;
1550
1551             writeU16(table, 3); //platform id (windows)
1552             writeU16(table, 1); //encoding id (ucs-2)
1553             writeU16(table, 0x409); //language (US)
1554             writeU16(table, codes[t]);
1555             int len2 = len * 2;
1556             writeU16(table, len2);
1557             writeU16(table, offset);
1558             offset += len2;
1559         }
1560     }
1561     table->data[offset_pos] = table->len>>8;
1562     table->data[offset_pos+1] = table->len;
1563
1564     for(t=0;t<nr;t++) { 
1565         if(strings[t]) {
1566             int len = strlen(strings[t]);
1567             writeBlock(table, strings[t], len);
1568             int s;
1569             for(s=0;s<len;s++) {
1570                 writeU8(table, 0);
1571                 writeU8(table, strings[t][s]);
1572             }
1573         }
1574     }
1575 }
1576 void name_delete(ttf_t*ttf)
1577 {
1578     if(ttf->full_name) {
1579         free(ttf->full_name);
1580         ttf->full_name=0;
1581     }
1582     if(ttf->family_name) {
1583         free(ttf->family_name);
1584         ttf->family_name=0;
1585     }
1586     if(ttf->subfamily_name) {
1587         free(ttf->subfamily_name);
1588         ttf->subfamily_name=0;
1589     }
1590     if(ttf->version_string) {
1591         free(ttf->version_string);
1592         ttf->version_string=0;
1593     }
1594 }
1595
1596 static table_post_t*post_new(ttf_t*ttf)
1597 {
1598     table_post_t*post = rfx_calloc(sizeof(table_post_t));
1599     return post;
1600 }
1601 void post_parse(memreader_t*r, ttf_t*ttf)
1602 {
1603     table_post_t*post = ttf->post = rfx_calloc(sizeof(table_post_t));
1604     U16 format = readU16(r);
1605     post->italic_angle = readU16(r);
1606     post->underline_position = readU16(r);
1607     post->underline_thickness = readU16(r);
1608     U16 is_monospaced = readU16(r);
1609     readU16(r); // min mem 42
1610     readU16(r);
1611     readU16(r); // min mem 1
1612     readU16(r);
1613 }
1614 void post_write(ttf_t*ttf, ttf_table_t*table)
1615 {
1616     table_post_t*post = ttf->post;
1617     writeU32(table, 0x00030000);
1618     writeU32(table, post->italic_angle);
1619     writeU16(table, post->underline_position);
1620     writeU16(table, post->underline_thickness);
1621     writeU32(table, 0); //is monospaced TODO
1622     writeU32(table, 0); //min mem 42
1623     writeU32(table, 0);
1624     writeU32(table, 0); //min mem 1
1625     writeU32(table, 0);
1626 }
1627 void post_delete(ttf_t*ttf)
1628 {
1629     if(ttf->post) {
1630         free(ttf->post);
1631         ttf->post = 0;
1632     }
1633 }
1634
1635 static int ttf_parse_tables(ttf_t*ttf)
1636 {
1637     ttf_table_t*table;
1638
1639     table = ttf_find_table(ttf, TAG_HEAD);
1640     if(!table) {
1641         msg("<error> Font has no head table");
1642         return 0;
1643     }
1644     INIT_READ(m, table->data, table->len, 0);
1645     int loc_index = head_parse(ttf, &m);
1646     ttf_table_delete(ttf, table);
1647     
1648     table = ttf_find_table(ttf, TAG_MAXP);
1649     if(!table) {
1650         msg("<error> Font has no maxp table");
1651         return 0;
1652     }
1653     INIT_READ(m2, table->data, table->len, 0);
1654     ttf->maxp = maxp_parse(ttf, &m2);
1655     ttf_table_delete(ttf, table);
1656     
1657     if(!ttf->num_glyphs) {
1658         msg("<error> Invalid number of characters");
1659         return 0;
1660     }
1661     ttf->glyphs = rfx_calloc(sizeof(ttfglyph_t)*ttf->num_glyphs);
1662
1663     table = ttf_find_table(ttf, TAG_OS2);
1664     if(table) {
1665         INIT_READ(m, table->data, table->len, 0);
1666         ttf->os2 = os2_parse(&m);
1667         ttf_table_delete(ttf, table);
1668     }
1669
1670     table = ttf_find_table(ttf, TAG_HHEA);
1671     if(table) {
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_HMTX);
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         table = ttf_find_table(ttf, TAG_VHEA);
1684         if(table) {
1685             ttf->is_vertical=1;
1686             INIT_READ(m, table->data, table->len, 0);
1687             int num_advances = hea_parse(&m, ttf);
1688             ttf_table_delete(ttf, table);
1689
1690             table = ttf_find_table(ttf, TAG_VMTX);
1691             if(table) {
1692                 INIT_READ(m, table->data, table->len, 0);
1693                 mtx_parse(&m, ttf, num_advances);
1694                 ttf_table_delete(ttf, table);
1695             }
1696         } else {
1697             msg("<error> Font contains neither HHEA nor VHEA");
1698         }
1699     }
1700     table = ttf_find_table(ttf, TAG_LOCA);
1701     if(table) {
1702         INIT_READ(m, table->data, table->len, 0);
1703         U32*loca = loca_parse(&m, ttf, loc_index);
1704         ttf_table_delete(ttf, table);
1705         table = ttf_find_table(ttf, TAG_GLYF);
1706         if(table) {
1707             INIT_READ(m, table->data, table->len, 0);
1708             glyf_parse(&m, ttf, loca);
1709             ttf_table_delete(ttf, table);
1710         }
1711         free(loca);
1712     }
1713     
1714     table = ttf_find_table(ttf, TAG_CMAP);
1715     if(table) {
1716         INIT_READ(m, table->data, table->len, 0);
1717         cmap_parse(&m, ttf);
1718         ttf_table_delete(ttf, table);
1719     }
1720     
1721     table = ttf_find_table(ttf, TAG_NAME);
1722     if(table) {
1723         INIT_READ(m, table->data, table->len, 0);
1724         name_parse(&m, ttf);
1725         ttf_table_delete(ttf, table);
1726     }
1727
1728     table = ttf_find_table(ttf, TAG_POST);
1729     if(table) {
1730         INIT_READ(m, table->data, table->len, 0);
1731         post_parse(&m, ttf);
1732         ttf_table_delete(ttf, table);
1733     }
1734
1735     return 1;
1736 }
1737 static void ttf_collapse_tables(ttf_t*ttf)
1738 {
1739     ttf_table_t*table;
1740     
1741     ttf_table_t*head = ttf_find_table(ttf, TAG_HEAD);
1742     if(head) 
1743         return; //already collapsed
1744   
1745     if(ttf->maxp) {
1746         table = ttf_addtable(ttf, TAG_MAXP);
1747         maxp_write(ttf, table);
1748         maxp_delete(ttf);
1749     }
1750
1751     if(ttf->os2) {
1752         table = ttf_addtable(ttf, TAG_OS2);
1753         os2_write(ttf, table);
1754         os2_delete(ttf);
1755     }
1756
1757     if(ttf->hea) {
1758         if(!ttf->is_vertical) {
1759             table = ttf_addtable(ttf, TAG_HMTX);
1760             int num_advances = mtx_write(ttf, table);
1761             table = ttf_addtable(ttf, TAG_HHEA);
1762             hea_write(ttf, table, num_advances);
1763             hea_delete(ttf);
1764         } else {
1765             table = ttf_addtable(ttf, TAG_VMTX);
1766             int num_advances = mtx_write(ttf, table);
1767             table = ttf_addtable(ttf, TAG_VHEA);
1768             hea_write(ttf, table, num_advances);
1769             hea_delete(ttf);
1770         }
1771     }
1772         
1773     int loca_size=0;
1774     if(ttf->num_glyphs) {
1775         if(ttf->unicode) {
1776             table = ttf_addtable(ttf, TAG_CMAP);
1777             cmap_write(ttf, table);
1778             cmap_delete(ttf);
1779         }
1780
1781         if(ttf->glyphs) {
1782             table = ttf_addtable(ttf, TAG_GLYF);
1783             U32*locations = glyf_write(ttf, table);
1784             table = ttf_addtable(ttf, TAG_LOCA);
1785             loca_size = loca_write(ttf, table, locations);
1786             free(locations);
1787             glyf_delete(ttf);
1788         }
1789     }
1790
1791     if(ttf->full_name || ttf->family_name || ttf->subfamily_name) {
1792         table = ttf_addtable(ttf, TAG_NAME);
1793         name_write(ttf, table);
1794         name_delete(ttf);
1795     }
1796     if(ttf->post) {
1797         table = ttf_addtable(ttf, TAG_POST);
1798         post_write(ttf, table);
1799         post_delete(ttf);
1800     }
1801     
1802     table = ttf_addtable(ttf, TAG_HEAD);
1803     head_write(ttf, table, loca_size);
1804     head_delete(ttf);
1805 }
1806
1807 ttf_t*ttf_new()
1808 {
1809     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
1810     ttf->version = VERSION_1_0;
1811     return ttf;
1812 }
1813 ttf_t* ttf_load(void*data, int length)
1814 {
1815     INIT_READ(r,data,length, 0);
1816
1817     if(length<12) {
1818         msg("<error> Truncated Truetype file (%d bytes)", length);
1819         return 0;
1820     }
1821
1822     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
1823     ttf->version = readU32(&r);
1824     if(ttf->version == SWAP32(length)) {
1825         U32 fontDataSize = readU32(&r);
1826         U32 version = readU32(&r);
1827         U32 flags  = readU32(&r);
1828         U8 panose[10]; 
1829         readBlock(&r, panose, 10);
1830         readU8(&r); //charset
1831         readU8(&r); //italoc
1832         readU32(&r); //weight
1833         readU16(&r); //fstype
1834         U16 magic = readU16(&r); //magicNumber
1835         /* we're being paranoid: it's entirely possible for the font
1836            size to be exactly 0x10000. Only treat this font as eot if
1837            it has the right magic number */
1838         if(magic == 0x4c50) {
1839             readU32(&r); //unicoderange[0]
1840             readU32(&r); //unicoderange[1]
1841             readU32(&r); //unicoderange[2]
1842             readU32(&r); //unicoderange[3]
1843             readU32(&r); //codepagerange[0]
1844             readU32(&r); //codepagerange[1]
1845             readU32(&r); //checksumadjustment
1846             readU32(&r); //reserved[0]
1847             readU32(&r); //reserved[1]
1848             readU32(&r); //reserved[2]
1849             readU32(&r); //reserved[3]
1850             readU16(&r); //padding
1851
1852             int nr=0;
1853             for(nr=0;nr<4;nr++) {
1854                 int t, len;
1855                 /* All of ttf is big-endian. All of ttf? No. One small eot table
1856                    of indomitable little-endian... */
1857                 len = readU8(&r);
1858                 len |= readU8(&r)<<8;
1859                 len /= 2;
1860                 for(t=0;t<len;t++) {
1861                     U8 c = readU16(&r)>>8;
1862                 }
1863                 readU16(&r); // zero terminator
1864             }
1865             readU16(&r); // more padding
1866
1867             /* adjust the offset to the start of the actual truetype
1868                data- the positions in the table header will be relative
1869                to the ttf data after the header, not to the file */
1870             r.mem += r.pos;
1871             r.size -= r.pos;
1872             r.pos = 0;
1873             ttf->version = readU32(&r);
1874         } else {
1875             reader_reset(&r);
1876             ttf->version = readU32(&r);
1877         }
1878     }
1879
1880     if(ttf->version == TTCFTAG) {
1881         /* a ttc collection is a number of truetype fonts
1882            packaged together */
1883         if(length<16) {
1884             msg("<error> Truncated TTC file (%d bytes)", length);
1885             return 0;
1886         }
1887         U32 ttcf_version = readU32(&r); // 0x00000100: v1.0, 0x00000200: v2.0, includes DSIG table
1888         U32 num_fonts = readU32(&r); // number of fonts
1889         U32 font1_position = readU32(&r);
1890         if(font1_position+12 > length) {\
1891             msg("<error> Truncated TTC file (%d bytes, first font at %d)", length, font1_position);
1892             return 0;
1893         }
1894         r.pos = font1_position;
1895         ttf->version = readU32(&r);
1896     }
1897     
1898     int num_tables = readU16(&r);
1899     
1900     readU16(&r); //search range
1901     readU16(&r); //entry selector
1902     readU16(&r); //range shift
1903
1904     if(num_tables*16 > length) {
1905         msg("<error> Truncated TTF file (table entries: %d)", num_tables);
1906         if(ttf->version != OPENTYPE && 
1907            ttf->version != TRUETYPE_MACOS && 
1908            ttf->version != VERSION_1_0) {
1909             // bad table length, weird version. This is probably not a ttf file.
1910             return 0;
1911         }
1912     }
1913
1914     U32*table_data = malloc(16*num_tables);
1915     int t;
1916     for(t=0;t<num_tables*4;t++) {
1917         table_data[t] = readU32(&r);
1918     }
1919     for(t=0;t<num_tables;t++) {
1920         U32 tag = table_data[t*4];
1921         U32 checksum = table_data[t*4+1];
1922         U32 pos = table_data[t*4+2];
1923         U32 len = table_data[t*4+3];
1924
1925         if(pos+len > length) {
1926             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);
1927         } else {
1928             U8*mem = malloc(len);
1929             r.pos = pos;
1930             readBlock(&r, mem, len);
1931             
1932             ttf_table_t*table = ttf_addtable(ttf, tag);
1933             table->data = mem;
1934             table->len = table->memsize = len;
1935 #if 0
1936             U32 checksum2 = ttf_table_checksum(table);
1937             if(checksum2!=checksum) {
1938                 msg("<warning> Checksum mismatch in tag %02x%02x%02x%02x %c%c%c%c (%d bytes) %08x!=%08x", 
1939                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
1940                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
1941                         len, checksum2, checksum);
1942             }
1943 #endif
1944         }
1945     }
1946     free(table_data);
1947
1948     if(!ttf_parse_tables(ttf)) 
1949         return 0;
1950
1951     return ttf;
1952 }
1953 void ttf_create_truetype_tables(ttf_t*ttf)
1954 {
1955     if(!ttf->head) 
1956         ttf->head = head_new(ttf);
1957     if(!ttf->maxp) 
1958         ttf->maxp = maxp_new(ttf);
1959     if(!ttf->hea)
1960         ttf->hea = hea_new(ttf);
1961     if(!ttf->os2)
1962         ttf->os2 = os2_new(ttf);
1963     if(!ttf->post)
1964         ttf->post = post_new(ttf);
1965 }
1966
1967 ttf_table_t* ttf_write(ttf_t*ttf, U32*checksum_adjust)
1968 {
1969     ttf_collapse_tables(ttf);
1970    
1971     ttf_table_t*file = ttf_table_new(0);
1972     writeU32(file, VERSION_1_0);
1973
1974     /* write number of tables */
1975     int num_tables=0;
1976     ttf_table_t*t = ttf->tables;
1977     while(t) {
1978         num_tables++;
1979         t = t->next;
1980     }
1981     writeU16(file, num_tables);
1982     
1983     /* write search range */
1984     int tmp = num_tables;
1985     int search_range = 0;
1986     while(tmp) {
1987         search_range = tmp;
1988         tmp = tmp&(tmp-1);
1989     }
1990     tmp = search_range;
1991     search_range*=16;
1992     writeU16(file, search_range);
1993
1994     /* write entry selector */
1995     int entry_selector = 0;
1996     while(tmp>1) {
1997         tmp>>=1;
1998         entry_selector++;
1999     }
2000     writeU16(file, entry_selector);
2001
2002     /* write range shift */
2003     int range_shift = num_tables*16 - search_range;
2004     writeU16(file, range_shift);
2005
2006     /* write table dictionary */
2007     int table_dictionary_pos = file->len;
2008     int data_pos = file->len + num_tables*16;
2009     for(t=ttf->tables;t;t=t->next) {
2010         writeU32(file, t->id);
2011         writeU32(file, ttf_table_checksum(t));
2012         writeU32(file, data_pos);
2013         writeU32(file, t->len);
2014         data_pos += t->len;
2015         data_pos += (-t->len)&3; //pad
2016     }
2017
2018     /* write tables */
2019     int head_pos = 0;
2020     U8 zero[4]={0,0,0,0};
2021     for(t=ttf->tables;t;t=t->next) {
2022         if(t->id == TAG_HEAD)
2023             head_pos = file->len;
2024         writeBlock(file, t->data, t->len);
2025         writeBlock(file, zero, (-t->len)&3); //pad
2026     }
2027     U32 checksum = 0xb1b0afba - ttf_table_checksum(file);
2028     if(checksum_adjust)
2029         *checksum_adjust = checksum;
2030     U8*checksum2 = file->data + head_pos + 8;
2031     checksum2[0] = checksum>>24;
2032     checksum2[1] = checksum>>16;
2033     checksum2[2] = checksum>>8;
2034     checksum2[3] = checksum>>0;
2035     return file;
2036 }
2037
2038 ttf_table_t* ttf_eot_head(ttf_t*ttf)
2039 {
2040     ttf_table_t*file = ttf_table_new(0);
2041     writeU32(file, 0); //file size (filled in later)
2042     writeU32(file, 0); //fontdatasize (filled in later)
2043     writeU32(file, 0x01000200);
2044     writeU32(file, 0); //flags
2045     writeU8(file, ttf->os2->panose_FamilyType);
2046     writeU8(file, ttf->os2->panose_SerifStyle);
2047     writeU8(file, ttf->os2->panose_Weight);
2048     writeU8(file, ttf->os2->panose_Proportion);
2049     writeU8(file, ttf->os2->panose_Contrast);
2050     writeU8(file, ttf->os2->panose_StrokeVariation);
2051     writeU8(file, ttf->os2->panose_ArmStyle);
2052     writeU8(file, ttf->os2->panose_Letterform);
2053     writeU8(file, ttf->os2->panose_Midline);
2054     writeU8(file, ttf->os2->panose_XHeight);
2055     writeU8(file, 1); //charset (default)
2056     writeU8(file, ttf->os2->fsSelection&1); //italic
2057     writeU32_LE(file, ttf->os2->usWeightClass);
2058     writeU16(file, 0); //fstype
2059     writeU16(file, 0x4c50); //magic
2060     writeU32_LE(file, ttf->os2->ulCharRange[0]);
2061     writeU32_LE(file, ttf->os2->ulCharRange[1]);
2062     writeU32_LE(file, ttf->os2->ulCharRange[2]);
2063     writeU32_LE(file, ttf->os2->ulCharRange[3]);
2064     writeU32_LE(file, ttf->os2->ulCodePageRange1);
2065     writeU32_LE(file, ttf->os2->ulCodePageRange2);
2066     writeU32(file, 0); //checksum adjust (filled in later)
2067     writeU32(file, 0); //reserved[0]
2068     writeU32(file, 0); //reserved[1]
2069     writeU32(file, 0); //reserved[2]
2070     writeU32(file, 0); //reserved[3]
2071     writeU16(file, 0); //padding(1)
2072
2073     int t,len;
2074
2075     //family name
2076     len = strlen(ttf->family_name);
2077     writeU16_LE(file, len*2);
2078     for(t=0;t<len;t++) {
2079         writeU8(file, 0);
2080         writeU8(file, ttf->family_name[t]);
2081     }
2082     writeU16(file, 0); //zero byte pad
2083
2084     //subfamily name
2085     len = strlen(ttf->subfamily_name);
2086     writeU16_LE(file, len*2);
2087     for(t=0;t<len;t++) {
2088         writeU8(file, 0);
2089         writeU8(file, ttf->subfamily_name[t]);
2090     }
2091     writeU16(file, 0); //zero byte pad
2092
2093     //version string
2094     len = strlen(ttf->version_string);
2095     writeU16_LE(file, len*2); //len
2096     for(t=0;t<len;t++) {
2097         writeU8(file, 0);
2098         writeU8(file, ttf->version_string[t]);
2099     }
2100     writeU16(file, 0); //zero byte pad
2101
2102     //full name
2103     len = strlen(ttf->full_name);
2104     writeU16_LE(file, len*2); //len
2105     for(t=0;t<len;t++) {
2106         writeU8(file, 0);
2107         writeU8(file, ttf->full_name[t]);
2108     }
2109     writeU16(file, 0); //zero byte pad
2110
2111     writeU16(file, 0); //padding(2)
2112     return file;
2113 }
2114
2115 void ttf_save_eot(ttf_t*ttf, const char*filename)
2116 {
2117     ttf_table_t* eot = ttf_eot_head(ttf);
2118     U32 checksum_adjust = 0;
2119     ttf_table_t* t = ttf_write(ttf, &checksum_adjust);
2120
2121     U8*len_data = eot->data;
2122     U32 full_len = eot->len + t->len;
2123     len_data[0] = full_len>>0;
2124     len_data[1] = full_len>>8;
2125     len_data[2] = full_len>>16;
2126     len_data[3] = full_len>>24;
2127     
2128     U8*len_data2 = eot->data+4;
2129     len_data2[0] = t->len>>0;
2130     len_data2[1] = t->len>>8;
2131     len_data2[2] = t->len>>16;
2132     len_data2[3] = t->len>>24;
2133
2134     U8*checksum_data = eot->data + 60;
2135     checksum_data[0] = checksum_adjust>>0;
2136     checksum_data[1] = checksum_adjust>>8;
2137     checksum_data[2] = checksum_adjust>>16;
2138     checksum_data[3] = checksum_adjust>>24;
2139
2140     FILE*fi = fopen(filename, "wb");
2141     if(!fi) {
2142         perror(filename);
2143         return;
2144     }
2145
2146     fwrite(eot->data, eot->len, 1, fi);
2147     fwrite(t->data, t->len, 1, fi);
2148     fclose(fi);
2149     ttf_table_delete(0, t);
2150     ttf_table_delete(0, eot);
2151 }
2152
2153 void ttf_save(ttf_t*ttf, const char*filename)
2154 {
2155     ttf_table_t* t = ttf_write(ttf, 0);
2156     FILE*fi = fopen(filename, "wb");
2157     if(!fi) {
2158         perror(filename);
2159         return;
2160     }
2161     fwrite(t->data, t->len, 1, fi);
2162     fclose(fi);
2163     ttf_table_delete(0, t);
2164 }
2165
2166 void ttf_dump(ttf_t*ttf)
2167 {
2168     msg("<notice> Truetype file version %08x%s", ttf->version, ttf->version == OPENTYPE?" (opentype)":"");
2169     ttf_table_t*table = ttf->tables;
2170     while(table) {
2171         U32 tag = table->id;
2172         msg("<notice> Tag %02x%02x%02x%02x [%c%c%c%c] (length: %d)", 
2173                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, 
2174                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, table->len);
2175         table = table->next;
2176     }
2177     //ttf_table_dump(ttf_find_table(ttf, TAG_MAXP));
2178
2179     head_dump(ttf);
2180     hea_dump(ttf);
2181     os2_dump(ttf);
2182     maxp_dump(ttf);
2183     glyf_dump(ttf);
2184 }
2185 void ttf_destroy_tables(ttf_t*ttf)
2186 {
2187     ttf_table_t*table = ttf->tables;
2188     while(table) {
2189         ttf_table_t*next = table->next;
2190         free(table->data);
2191         free(table);
2192         table = next;
2193     }
2194     ttf->tables = 0;
2195 }
2196 void ttf_reduce(ttf_t*ttf)
2197 {
2198     ttf_destroy_tables(ttf);
2199 }
2200 void ttf_destroy(ttf_t*ttf)
2201 {
2202     ttf_destroy_tables(ttf);
2203     maxp_delete(ttf);
2204     os2_delete(ttf);
2205     head_delete(ttf);
2206     hea_delete(ttf);
2207     glyf_delete(ttf);
2208     post_delete(ttf);
2209     name_delete(ttf);
2210     free(ttf);
2211 }
2212
2213 #ifdef MAIN
2214 int main(int argn, const char*argv[])
2215 {
2216     setConsoleLogging(7);
2217     const char*filename = "comic.ttf";
2218     if(argn>1) 
2219         filename = argv[1];
2220     //msg("<notice> Loading %s", filename);
2221     memfile_t*m = memfile_open(filename);
2222     ttf_t*ttf = ttf_load(m->data, m->len);
2223     if(!ttf) {
2224         msg("<error> Couldn't load %s", filename);
2225         return 1;
2226     }
2227     ttf_reduce(ttf);
2228     
2229     ttf->full_name = strdup("Test-Normal");
2230     ttf->family_name = strdup("Test");
2231     ttf->subfamily_name = strdup("Normal");
2232     ttf->version_string = strdup("Version 1.0");
2233
2234     if(!ttf) return 1;
2235     memfile_close(m);
2236     //ttf_dump(ttf);
2237     //printf("os2 version: %04x (%d), maxp size: %d\n", 
2238 //          ttf->os2->version, ttf->os2->size, ttf->maxp->size);
2239     ttf_save_eot(ttf, "testfont.eot");
2240     ttf_save(ttf, "testfont.ttf");
2241     ttf_destroy(ttf);
2242     return 0;
2243
2244 }
2245 #endif