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