added gasp,fpgm,prep and cvt tables
[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;
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     return maxp;
642 }
643 static table_maxp_t* maxp_parse(ttf_t*ttf, memreader_t*r)
644 {
645     U32 version = readU32(r);
646     ttf->num_glyphs = readU16(r);
647     /* according to freetype, older fonts (version<0x10000)
648        apparently only contain the number of glyphs. this is
649        rather rare, though. */
650     if(version<0x10000 && r->size==6) return 0;
651
652     if(r->size<32)
653         msg("<warning> Truncated maxp table (version %d)", version);
654
655     table_maxp_t*maxp = rfx_calloc(sizeof(table_maxp_t));
656     maxp->maxPoints = readU16(r);
657     maxp->maxContours = readU16(r);
658     maxp->maxComponentPoints = readU16(r);
659     maxp->maxComponentContours = readU16(r);
660     maxp->maxZones = readU16(r);
661     maxp->maxTwilightPoints = readU16(r);
662     maxp->maxStorage = readU16(r);
663     maxp->maxFunctionDefs = readU16(r);
664     maxp->maxInstructionDefs = readU16(r);
665     maxp->maxStackElements = readU16(r);
666     maxp->maxSizeOfInstructions = readU16(r);
667     maxp->maxComponentElements = readU16(r);
668     maxp->maxComponentDepth = readU16(r);
669     return maxp;
670 }
671 static void maxp_write(ttf_t*ttf, ttf_table_t*w)
672 {
673     table_maxp_t*maxp = ttf->maxp;
674     if(!maxp) {
675         /* version 0.5 simplified maxp table */
676         writeU32(w, 0x00005000);
677         writeU16(w, ttf->num_glyphs);
678         return;
679     }
680     writeU32(w, 0x10000); //version
681     writeU16(w, ttf->num_glyphs);
682     writeU16(w, maxp->maxPoints);
683     writeU16(w, maxp->maxContours);
684     writeU16(w, maxp->maxComponentPoints);
685     writeU16(w, maxp->maxComponentContours);
686     writeU16(w, maxp->maxZones);
687     writeU16(w, maxp->maxTwilightPoints);
688     writeU16(w, maxp->maxStorage);
689     writeU16(w, maxp->maxFunctionDefs);
690     writeU16(w, maxp->maxInstructionDefs);
691     writeU16(w, maxp->maxStackElements);
692     writeU16(w, maxp->maxSizeOfInstructions);
693     writeU16(w, maxp->maxComponentElements);
694     writeU16(w, maxp->maxComponentDepth);
695 }
696 static void maxp_dump(ttf_t*ttf)
697 {
698     table_maxp_t*maxp = ttf->maxp;
699     if(!maxp) return;
700     printf("maxp->maxPoints: %d\n", maxp->maxPoints);
701     printf("maxp->maxContours: %d\n", maxp->maxContours);
702     printf("maxp->maxComponentPoints: %d\n", maxp->maxComponentPoints);
703     printf("maxp->maxComponentContours: %d\n", maxp->maxComponentContours);
704     printf("maxp->maxZones: %d\n", maxp->maxZones);
705     printf("maxp->maxTwilightPoints: %d\n", maxp->maxTwilightPoints);
706     printf("maxp->maxStorage: %d\n", maxp->maxStorage);
707     printf("maxp->maxFunctionDefs: %d\n", maxp->maxFunctionDefs);
708     printf("maxp->maxInstructionDefs: %d\n", maxp->maxInstructionDefs);
709     printf("maxp->maxStackElements: %d\n", maxp->maxStackElements);
710     printf("maxp->maxSizeOfInstructions: %d\n", maxp->maxSizeOfInstructions);
711     printf("maxp->maxComponentElements: %d\n", maxp->maxComponentElements);
712     printf("maxp->maxComponentDepth: %d\n", maxp->maxComponentDepth);
713 }
714 static void maxp_delete(ttf_t*ttf)
715 {
716     if(ttf->maxp)
717         free(ttf->maxp);
718     ttf->maxp=0;
719 }
720
721 static table_hea_t*hea_new(ttf_t*ttf)
722 {
723     table_hea_t*hea = rfx_calloc(sizeof(table_hea_t));
724     if(ttf->num_glyphs) {
725         int t;
726         for(t=0;t<ttf->num_glyphs;t++) {
727             if(ttf->glyphs[t].advance > hea->advanceWidthMax)
728                 hea->advanceWidthMax = ttf->glyphs[t].advance;
729             if(ttf->glyphs[t].xmin < hea->minLeftSideBearing)
730                 hea->minLeftSideBearing = ttf->glyphs[t].xmin;
731             if(ttf->glyphs[t].xmax < hea->minRightSideBearing)
732                 hea->minRightSideBearing = ttf->glyphs[t].xmax;
733             int width = ttf->glyphs[t].xmax - ttf->glyphs[t].xmin;
734             if(width > hea->xMaxExtent)
735                 hea->xMaxExtent = width;
736         }
737         hea->caretSlopeRise = 1;
738     }
739     return hea;
740 }
741 static int hea_parse(memreader_t*r, ttf_t*ttf)
742 {
743     table_hea_t*hea = ttf->hea = rfx_calloc(sizeof(table_hea_t));
744     U32 version = readU32(r);
745     ttf->ascent = readS16(r);
746     ttf->descent = readS16(r);
747     ttf->lineGap = readS16(r);
748     hea->advanceWidthMax = readU16(r);
749     hea->minLeftSideBearing = readS16(r);
750     hea->minRightSideBearing = readS16(r);
751     hea->xMaxExtent = readS16(r);
752     hea->caretSlopeRise = readS16(r);
753     hea->caretSlopeRun = readS16(r);
754     hea->caretOffset = readS16(r);
755     readS16(r); //reserved[0]
756     readS16(r); //reserved[1]
757     readS16(r); //reserved[2]
758     readS16(r); //reserved[3]
759     S16 metricDataFormat = readS16(r); //should be 0
760     if(metricDataFormat!=0) {
761         msg("<warning> Unknown metric format %d", metricDataFormat);
762     }
763     int num_advances = readU16(r);
764     if(num_advances > ttf->num_glyphs) {
765         msg("<warning> bad number of horizontal metrics: %d", num_advances);
766         num_advances = ttf->num_glyphs;
767     }
768     return num_advances;
769 }
770 static table_hea_t*hea_write(ttf_t*ttf, ttf_table_t*w, int num_advances)
771 {
772     table_hea_t*hea = ttf->hea;
773     writeU32(w, 0x00010000);
774     writeS16(w, ttf->ascent);
775     writeS16(w, ttf->descent);
776     writeS16(w, ttf->lineGap);
777     writeU16(w, hea->advanceWidthMax);
778     writeS16(w, hea->minLeftSideBearing);
779     writeS16(w, hea->minRightSideBearing);
780     writeS16(w, hea->xMaxExtent);
781     writeS16(w, hea->caretSlopeRise);
782     writeS16(w, hea->caretSlopeRun);
783     writeS16(w, hea->caretOffset);
784     writeS16(w, 0); //reserved
785     writeS16(w, 0); //reserved
786     writeS16(w, 0); //reserved
787     writeS16(w, 0); //reserved
788     writeS16(w, 0); //metricDataFormat
789     writeU16(w, num_advances);
790     return hea;
791 }
792 static void hea_dump(ttf_t*ttf)
793 {
794     table_hea_t*hea = ttf->hea;
795     if(!hea) return;
796     const char*dir = ttf->is_vertical?"v":"h";
797     printf("%shea->ascent: %d\n", dir, ttf->ascent);
798     printf("%shea->descent: %d\n", dir, ttf->descent);
799     printf("%shea->lineGap: %d\n", dir, ttf->lineGap);
800     printf("%shea->advanceWidthMax: %d\n", dir, hea->advanceWidthMax);
801     printf("%shea->minLeftSideBearing: %d\n", dir, hea->minLeftSideBearing);
802     printf("%shea->minRightSideBearing: %d\n", dir, hea->minRightSideBearing);
803     printf("%shea->xMaxExtent: %d\n", dir, hea->xMaxExtent);
804     printf("%shea->caretSlopeRise: %d\n", dir, hea->caretSlopeRise);
805     printf("%shea->caretSlopeRun: %d\n", dir, hea->caretSlopeRun);
806     printf("%shea->caretOffset: %d\n", dir, hea->caretOffset);
807 }
808 static void hea_delete(ttf_t*ttf)
809 {
810     if(ttf->hea) {
811         free(ttf->hea);
812         ttf->hea=0;
813     }
814 }
815
816 static void mtx_parse(memreader_t*r, ttf_t*ttf, int num_advances)
817 {
818     U16 old_advance = 0;
819     int t;
820     if(num_advances > r->size/4)
821         num_advances = r->size/4;
822     for(t=0;t<num_advances;t++) {
823         old_advance = ttf->glyphs[t].advance = readU16(r);
824         ttf->glyphs[t].bearing = readS16(r);
825     }
826     int rest = (r->size - num_advances*4)/2;
827     if(ttf->num_glyphs < num_advances+rest) {
828         rest = ttf->num_glyphs-num_advances;
829     }
830     for(t=0;t<rest;t++) {
831         ttf->glyphs[t].advance = old_advance;
832         ttf->glyphs[t].bearing = readS16(r);
833     }
834 }
835 static int mtx_write(ttf_t*ttf, ttf_table_t*w)
836 {
837     int num_advances = ttf->num_glyphs;
838     if(ttf->num_glyphs>=2) {
839         int t;
840         for(t=ttf->num_glyphs-1;t>0;t--) {
841             if(ttf->glyphs[t-1].advance !=
842                ttf->glyphs[t].advance) break;
843         }
844         /* we need to store all individual advances as well
845            as one entry for the constant */
846         num_advances = t+1;
847     }
848
849     int t;
850     for(t=0;t<num_advances;t++) {
851         writeU16(w, ttf->glyphs[t].advance);
852         writeU16(w, ttf->glyphs[t].bearing);
853     }
854     for(;t<ttf->num_glyphs;t++) {
855         writeU16(w, ttf->glyphs[t].bearing);
856     }
857     return num_advances;
858 }
859
860 static U32*loca_parse(memreader_t*r, ttf_t*ttf, int size)
861 {
862     int t;
863     int num = ttf->num_glyphs+1;
864     U32*locations = rfx_calloc(num*sizeof(U32));
865     U32 lastloc = 0;
866     U32 loc = 0;
867     char warn_unsorted = 1;
868     if(size) {
869         if(num*4 > r->size) {
870             msg("<warning> Short 'loca' table (32 bit): %d/%d", r->size/4, num);
871             num=r->size/4;
872         }
873         if(num*4 < r->size) {
874             msg("<warning> Extraneous data (%d bytes) in 'loca' table (32 bit)", r->size-num*4);
875         }
876         for(t=0;t<num;t++) {
877             locations[t] = loc = readU32(r);
878             if(lastloc > loc && warn_unsorted) {
879                 msg("<warning> Unsorted 'loca' table (32 bit)");
880                 warn_unsorted=0;
881             }
882             lastloc = loc;
883         }
884     } else {
885         if(num*2 > r->size) {
886             msg("<warning> Short 'loca' table (16 bit)");
887             num=r->size/2;
888         }
889         if(num*2 < r->size) {
890             msg("<warning> Extraneous data (%d bytes) in 'loca' table (16 bit)", r->size-num*2);
891         }
892         for(t=0;t<num;t++) {
893             locations[t] = loc = readU16(r)*2;
894             if(lastloc > loc && warn_unsorted) {
895                 msg("<warning> Unsorted 'loca' table");
896                 warn_unsorted=0;
897             }
898             lastloc = loc;
899         }
900     }
901     return locations;
902 }
903 static int loca_write(ttf_t*ttf, ttf_table_t*w, U32*locations)
904 {
905     int t;
906     char use_32bit = 0;
907     for(t=0;t<=ttf->num_glyphs;t++) {
908         if(locations[t]>=0x20000 || (locations[t]&1)) {
909             use_32bit = 1;
910             break;
911         }
912     }
913
914     if(use_32bit) {
915         for(t=0;t<=ttf->num_glyphs;t++) {
916             writeU32(w, locations[t]);
917         }
918         return 1;
919     } else {
920         for(t=0;t<=ttf->num_glyphs;t++) {
921             writeU16(w, locations[t]/2);
922         }
923         return 0;
924     }
925 }
926
927 static int parse_simple_glyph(ttf_t*ttf, memreader_t*r, int num_contours, int glyphnr)
928 {
929     ttfglyph_t*glyph = &ttf->glyphs[glyphnr];
930
931     U16*endpoints = 0;
932     if(num_contours>0) {
933         endpoints = malloc(sizeof(U16)*num_contours);
934         int s;
935         int lastpos = -1;
936         for(s=0;s<num_contours;s++) {
937             int pos = endpoints[s] = readU16(r);
938             if(pos<=lastpos) {
939                 msg("<warning> Unsorted endpoints array (len:%d) last=%d now=%d", s, pos, lastpos);
940             }
941             lastpos = pos;
942         }
943     }
944     U16 code_len = readU16(r);
945     if(code_len) {
946         glyph->code = malloc(sizeof(U16)*code_len);
947         readBlock(r, glyph->code, code_len);
948         glyph->code_size = code_len;
949     }
950
951     if(!endpoints)
952         return 1;
953
954     /*msg("<notice> TTF Glyph %d) code_size=%d num_contours=%d glyph->num_points=%d %d/%d/%d/%d",
955             glyphnr, code_len, num_contours, glyph->num_points,
956             xmin, ymin, xmax, ymax);*/
957     INIT_READ(fx, r->mem, r->size, r->pos);
958     INIT_READ(fy, r->mem, r->size, r->pos);
959
960     glyph->num_points = endpoints[num_contours-1] + 1;
961     glyph->points = rfx_calloc(sizeof(ttfpoint_t)*glyph->num_points);
962
963     /* parse flag array (1st pass- to determine start of coordinates) */
964     int num=0;
965     while(num<glyph->num_points) {
966         U8 flag = readU8(r);
967         if(flag&0xc0) {
968             msg("<error> Bad flags in glyph outline: %02x (at pos %d)", flag, num);
969             free(glyph->points);
970             glyph->points = 0;
971             glyph->num_points = 0;
972             return 0;
973         }
974         int count = 1;
975         if(flag & 0x08)
976             count += readU8(r);
977         if(count+num>glyph->num_points) {
978             msg("<warning> Bad count (%d) in glyph (%d) (at pos %d)", count, glyphnr, num);
979             count = glyph->num_points-num;
980         }
981         num+=count;
982     }
983
984     /* parse flag array (2nd pass) and x coordinates */
985     num=0;
986     int x = 0;
987     char is_start=1;
988     int contour_pos=0;
989     int bytepos = r->pos;
990     while(num<glyph->num_points) {
991         U8 flag = readU8(&fx);
992         int count = flag&8?readU8(&fx)+1:1;
993         count=count>glyph->num_points-num?glyph->num_points-num:(count?count:1);
994         do {
995             char is_end=0;
996             if(contour_pos<num_contours && num==endpoints[contour_pos]) {
997                 contour_pos++;
998                 is_end=1;
999             }
1000             int oldx = x;
1001             if((flag&0x12) == 0x12) x += readU8(r);
1002             else if((flag&0x12) == 0x02) x -= readU8(r);
1003             else if((flag&0x12) == 0x00) x += readS16(r);
1004
1005             glyph->points[num].x = x;
1006             U8 f = flag&GLYPH_ON_CURVE;
1007             if(is_start) f|=GLYPH_CONTOUR_START;
1008             if(is_end) f|=GLYPH_CONTOUR_END;
1009             glyph->points[num].flags = f;
1010             num++;
1011             is_start = is_end;
1012         } while(--count);
1013     }
1014
1015     /* parse flag array (3rd pass) and y coordinates */
1016     num=0;
1017     int y = 0;
1018     while(num<glyph->num_points) {
1019         U8 flag = readU8(&fy);
1020         int count = flag&8?readU8(&fy)+1:1;
1021         count=count>glyph->num_points-num?glyph->num_points-num:(count?count:1);
1022         do {
1023             if((flag&0x24) == 0x24) y += readU8(r);
1024             else if((flag&0x24) == 0x04) y -= readU8(r);
1025             else if((flag&0x24) == 0x00) y += readS16(r);
1026             glyph->points[num].y = y;
1027             num++;
1028         } while(--count);
1029     }
1030     free(endpoints);
1031     return 1;
1032 }
1033 static void glyf_parse(memreader_t*rr, ttf_t*ttf, U32*loca)
1034 {
1035     int t;
1036     char warn_about_compound_glyphs=0;
1037     for(t=0;t<ttf->num_glyphs;t++) {
1038         INIT_READ(r, rr->mem, rr->size, loca[t]);
1039         if(loca[t]==loca[t+1] || loca[t]==r.size)
1040             continue; //empty glyph
1041         if(r.pos+10>r.size) {
1042             msg("<warning> Truncated glyph entry %d/%d (or bad loca entry %d/%d, next loca: %d)",
1043                     t, ttf->num_glyphs, loca[t], r.size, loca[t+1]);
1044             break;
1045         }
1046         S16 num_contours = readS16(&r);
1047         ttf->glyphs[t].xmin = readS16(&r);
1048         ttf->glyphs[t].ymin = readS16(&r);
1049         ttf->glyphs[t].xmax = readS16(&r);
1050         ttf->glyphs[t].ymax = readS16(&r);
1051
1052         if(num_contours<0) {
1053             if(warn_about_compound_glyphs)
1054                 msg("<error> Compound glyphs not supported yet");
1055             warn_about_compound_glyphs=0;
1056         } else {
1057             if(!parse_simple_glyph(ttf, &r, num_contours, t))
1058                 return;
1059         }
1060     }
1061
1062 }
1063 void write_simple_glyph(ttf_table_t*w, ttfglyph_t*g)
1064 {
1065     /* endpoints array */
1066     int s;
1067     for(s=0;s<g->num_points;s++) {
1068         if(g->points[s].flags&GLYPH_CONTOUR_END)
1069             writeU16(w, s);
1070     }
1071
1072     /* bytecode */
1073     writeU16(w, g->code_size);
1074     if(g->code_size)
1075         writeBlock(w, g->code, g->code_size);
1076
1077     /* flags */
1078     int lastx=0;
1079     int lasty=0;
1080     int lastflag=-1;
1081     int flagcount=0;
1082     for(s=0;s<g->num_points;s++) {
1083         ttfpoint_t*p = &g->points[s];
1084         int dx = p->x - lastx;
1085         int dy = p->y - lasty;
1086         U8 flags = p->flags&GLYPH_ON_CURVE;
1087         if(!dx) {
1088             flags|=0x10;
1089         } else if(dx<0 && dx>=-255) {
1090             flags|=0x02;
1091         } else if(dx>0 && dx<=255) {
1092             flags|=0x12;
1093         }
1094         if(!dy) {
1095             flags|=0x20;
1096         } else if(dy<0 && dy>=-255) {
1097             flags|=0x04;
1098         } else if(dy>0 && dy<=255) {
1099             flags|=0x24;
1100         }
1101         if(flags == lastflag && flagcount<255) {
1102             flagcount++;
1103         } else {
1104             if(lastflag>=0) {
1105                 if(flagcount) {
1106                     writeU8(w, lastflag|8);
1107                     writeU8(w, flagcount);
1108                 } else {
1109                     writeU8(w, lastflag);
1110                 }
1111             }
1112             lastflag = flags;
1113             flagcount = 0;
1114         }
1115         lastx = p->x;
1116         lasty = p->y;
1117     }
1118     if(lastflag>=0) {
1119         if(flagcount) {
1120             writeU8(w, lastflag|8);
1121             writeU8(w, flagcount);
1122         } else {
1123             writeU8(w, lastflag);
1124         }
1125     }
1126     /* coordinates */
1127     lastx=0;
1128     int bytepos = w->len;
1129     for(s=0;s<g->num_points;s++) {
1130         ttfpoint_t*p = &g->points[s];
1131         int dx = p->x - lastx;
1132         if(dx>32767 || dx<-32768) {
1133             msg("<error> Coordinate overflow in glyph");
1134         }
1135         lastx = p->x;
1136         if(dx>0 && dx<=255) writeU8(w, dx);
1137         else if(dx<0 && dx>=-255) writeU8(w, -dx);
1138         else if(dx) writeS16(w, dx);
1139     }
1140
1141     lasty=0;
1142     for(s=0;s<g->num_points;s++) {
1143         ttfpoint_t*p = &g->points[s];
1144         int dy = p->y - lasty;
1145         if(dy>32767 || dy<-32768) {
1146             msg("<error> Coordinate overflow in glyph");
1147         }
1148         lasty = p->y;
1149         if(dy>0 && dy<=255) writeU8(w, dy);
1150         else if(dy<0 && dy>=-255) writeU8(w, -dy);
1151         else if(dy) writeS16(w, dy);
1152     }
1153 }
1154 U32* glyf_write(ttf_t* ttf, ttf_table_t*w)
1155 {
1156     U32*locations = malloc(sizeof(U32)*(ttf->num_glyphs+1));
1157     int t;
1158     for(t=0;t<ttf->num_glyphs;t++) {
1159         locations[t] = w->len;
1160         ttfglyph_t*g = &ttf->glyphs[t];
1161         int s;
1162         int num_contours = 0;
1163         for(s=0;s<g->num_points;s++) {
1164             if(g->points[s].flags&GLYPH_CONTOUR_END)
1165                 num_contours++;
1166         }
1167         writeS16(w, num_contours?num_contours:1);
1168         writeS16(w, g->xmin);
1169         writeS16(w, g->ymin);
1170         writeS16(w, g->xmax);
1171         writeS16(w, g->ymax);
1172
1173         if(!num_contours) {
1174             /* some ttf parsers can't deal with zero contours, so in the case
1175                of an empty glyph, write a single point (0,0) */
1176             writeU16(w, 0); //endpoint of 1st contour
1177             writeU16(w, g->code_size);
1178             if(g->code_size)
1179                 writeBlock(w, g->code, g->code_size);
1180             writeU8(w, 0x31); //flag (xy=(0,0),on curve)
1181         } else {
1182             write_simple_glyph(w, g);
1183         }
1184     }
1185     locations[t] = w->len;
1186     return locations;
1187 }
1188 void glyf_dump(ttf_t* ttf)
1189 {
1190     if(!ttf->glyphs) return;
1191     int t;
1192     for(t=0;t<ttf->num_glyphs;t++) {
1193         ttfglyph_t*g = &ttf->glyphs[t];
1194         printf("glyph %d)\n", t);
1195         printf("  advance=%d\n", g->advance);
1196         printf("  bearing=%d\n", g->bearing);
1197         printf("  bbox=(%d/%d/%d/%d)\n", g->xmin, g->ymin, g->xmax, g->ymax);
1198         printf("  points=(");
1199         int s;
1200         for(s=0;s<g->num_points;s++) {
1201             if(s) printf(",");
1202             printf("%d/%d/0x%02x", g->points[s].x, g->points[s].y, g->points[s].flags);
1203         }
1204         printf(")\n");
1205         if(g->code_size)
1206             hexdump(g->code, g->code_size, "  ");
1207     }
1208 }
1209 void glyf_delete(ttf_t* ttf)
1210 {
1211     if(!ttf->glyphs)
1212         return;
1213     int t;
1214     for(t=0;t<ttf->num_glyphs;t++) {
1215         if(ttf->glyphs[t].code) {
1216             free(ttf->glyphs[t].code);
1217             ttf->glyphs[t].code = 0;
1218         }
1219         if(ttf->glyphs[t].points) {
1220             free(ttf->glyphs[t].points);
1221             ttf->glyphs[t].points = 0;
1222         }
1223     }
1224     free(ttf->glyphs);ttf->glyphs=0;
1225 }
1226
1227 static void grow_unicode(ttf_t*ttf, int index)
1228 {
1229     int size = index+1;
1230     if(!ttf->unicode) {
1231         ttf->unicode = rfx_calloc(sizeof(ttf->unicode[0])*size);
1232     } else if(ttf->unicode_size<size) {
1233         ttf->unicode = rfx_realloc(ttf->unicode, sizeof(ttf->unicode[0])*size);
1234         memset(ttf->unicode+ttf->unicode_size, 0, sizeof(ttf->unicode[0])*(size - ttf->unicode_size));
1235     }
1236     ttf->unicode_size = size;
1237 }
1238 void cmap_parse(memreader_t*r, ttf_t*ttf)
1239 {
1240     readU16(r); // version (0)
1241     int num_subtables = readU16(r);
1242     int t;
1243     char warn=1;
1244     if(r->pos+num_subtables*8 > r->size) {
1245         msg("<warning> CMap overflow");
1246         num_subtables = (r->size-r->pos)/8;
1247     }
1248     unicode_t*data = 0;
1249     for(t=0;t<num_subtables;t++) {
1250         U16 platform = readU16(r);
1251         U16 encoding = readU16(r);
1252         U32 offset = readU32(r);
1253         if(offset>r->size) {
1254             msg("<warning> CMAP table %d %d is out of bounds (%d)", platform, encoding, offset);
1255             continue;
1256         }
1257
1258         int is_unicode = platform==0 ||
1259                          platform==3 && encoding == 1 ||
1260                          platform==3 && encoding == 10;
1261
1262         if(!is_unicode)
1263             continue;
1264
1265         INIT_READ(t, r->mem, r->size, offset);
1266         U16 format = readU16(&t);
1267         int length = readU16(&t);
1268         U16 language = readU16(&t);
1269
1270         if(language)
1271             msg("<warning> Language code %02x in unicode mapping", language);
1272
1273         int num = 0;
1274         if(format == 0) {
1275             num = length-6;
1276             if(t.pos+length > t.size) {
1277                 msg("<warning> overflow in format 0 cmap table");
1278                 num = t.size-t.pos;
1279             }
1280             data = malloc(num*sizeof(unicode_t));
1281             int s;
1282             grow_unicode(ttf, num);
1283             for(s=0;s<num;s++) {
1284                 ttf->unicode[s] = readU8(&t);
1285             }
1286         } else if(format == 4) {
1287             U16 segment_count = readU16(&t);
1288             if(segment_count&1) {
1289                 msg("<error> Bad segmentx2 count %d", segment_count);
1290                 continue;
1291             }
1292             segment_count>>=1;
1293             readU16(&t); //searchrange
1294             readU16(&t); //entry selector
1295             readU16(&t); //range shift
1296             INIT_READ(r_end, t.mem, t.size, t.pos);
1297             INIT_READ(r_start, t.mem, t.size, t.pos+2+segment_count*2);
1298             INIT_READ(r_delta, t.mem, t.size, t.pos+2+segment_count*4);
1299             INIT_READ(r_range, t.mem, t.size, t.pos+2+segment_count*6);
1300             int glyphmap_start = t.pos+2+segment_count*8;
1301             int glyphmap_size = t.size - glyphmap_start;
1302             int s;
1303             for(s=0;s<segment_count;s++) {
1304                 U16 start = readU16(&r_start);
1305                 U16 end = readU16(&r_end);
1306                 U16 delta = readU16(&r_delta);
1307                 U16 range = readU16(&r_range);
1308                 if(start==0xffff && end==0xffff && delta==1) {
1309                     /* this is a common (maybe even required) occurence in fonts
1310                        which explicitly map "unicode undefined" (0xffff) to
1311                        "glyph undefined" (0).
1312                        We don't want to blow our unicode table up to 65536 just
1313                        because of this, so ignore this entry.
1314                      */
1315                     continue;
1316                 }
1317                 grow_unicode(ttf, end);
1318                 int u;
1319                 if(!range) {
1320                     for(u=start;u<=end;u++) {
1321                         ttf->unicode[u] = (u + delta) & 0xffff;
1322                     }
1323                 } else {
1324                     int pos = r_range.pos-2+range;
1325                     if(warn && pos+end-start+1 > t.size) {
1326                         msg("<warning> glyphmap index out of bounds (%d-%d/%d)", pos, pos+end-start, t.size);
1327                         warn=0;
1328                     }
1329                     INIT_READ(g, t.mem, t.size, pos);
1330                     for(u=start;u<=end;u++) {
1331                         ttf->unicode[u] = readU16(&g);
1332                     }
1333                 }
1334             }
1335         }
1336     }
1337 }
1338 static int segment_size(unicode_t*unicode, int pos, int size)
1339 {
1340     int s;
1341     int count=0;
1342     for(s=pos;s<size;s++) {
1343         if(!unicode[s])
1344             count++;
1345         if(count>4) {
1346             /* a segment costs us 8 bytes, so for more than 4 consecutive
1347                zero entries (16 bit each) in the glyph index array,
1348                it pays off to start a new segment */
1349             break;
1350         }
1351     }
1352     s -= count; // go to the last filled in entry
1353     if(s==size)
1354         return size-1;
1355     return s;
1356 }
1357 void cmap_write(ttf_t* ttf, ttf_table_t*w)
1358 {
1359     writeU16(w, 0);  //version
1360     writeU16(w, 2);  //two tables
1361
1362     writeU16(w, 0);  //platform (unicode)
1363     writeU16(w, 3);  //encoding (unicode 2.0)
1364     writeU32(w, 20); //offset
1365
1366     writeU16(w, 3);  //platform (windows)
1367     writeU16(w, 1);  //encoding (unicode basic multilingual plane UCS-2)
1368     writeU32(w, 20); //offset
1369
1370     writeU16(w, 4); // format=4
1371     int length_pos = w->len;
1372     writeU16(w, 0); // length: we don't know yet
1373     writeU16(w, 0); // language (n/a for unicode)
1374     int num_segments_pos = w->len;
1375     writeU16(w, 0); //number of segments: we don't know yet either
1376     writeU16(w, 0); //searchrange
1377     writeU16(w, 0); //entry selector
1378     writeU16(w, 0); //range shift
1379
1380     int pos=0;
1381     int num_segments=0;
1382     while(pos < ttf->unicode_size) {
1383         if(!ttf->unicode[pos]) {
1384             pos++;
1385             continue;
1386         }
1387         int s = segment_size(ttf->unicode, pos, ttf->unicode_size);
1388         pos = s+1;
1389         num_segments++;
1390     }
1391
1392     num_segments++; // account for 0xffff mapping
1393
1394     int glyphmap_start = w->len+2+num_segments*8;
1395
1396     int t;
1397     int end_pos = w->len;
1398     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //end array
1399     writeU16(w, 0); //reserved byte
1400     int start_pos = w->len;
1401     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //start array
1402     int delta_pos = w->len;
1403     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //delta array
1404     int range_pos = w->len;
1405     for(t=0;t<num_segments;t++) {writeU16(w, 0);} //range array
1406
1407     /* backpatch number of segments */
1408     w->data[num_segments_pos++]=(num_segments*2)>>8;
1409     w->data[num_segments_pos++]=(num_segments*2);
1410     /* backpatch search range */
1411     int tmp = num_segments;
1412     int search_range = 0;
1413     while(tmp) {
1414         search_range = tmp;
1415         tmp = tmp&(tmp-1);
1416     }
1417     w->data[num_segments_pos++]=(search_range*2)>>8;
1418     w->data[num_segments_pos++]=(search_range*2);
1419     /* backpatch entry selector */
1420     int entry_selector = 0;
1421     while(tmp>1) {tmp>>=1;entry_selector++;}
1422     w->data[num_segments_pos++]=entry_selector>>8;
1423     w->data[num_segments_pos++]=entry_selector;
1424     /* backpatch range shift */
1425     int range_shift = num_segments*2 - search_range;
1426     w->data[num_segments_pos++]=range_shift>>8;
1427     w->data[num_segments_pos++]=range_shift;
1428
1429     pos=0;
1430     num_segments = 0;
1431     while(pos < ttf->unicode_size) {
1432         if(!ttf->unicode[pos]) {
1433             pos++;
1434             continue;
1435         }
1436         U16 end = segment_size(ttf->unicode, pos, ttf->unicode_size);
1437         w->data[end_pos++]=end>>8;
1438         w->data[end_pos++]=end;
1439         w->data[start_pos++]=pos>>8;
1440         w->data[start_pos++]=pos;
1441         int s;
1442         U16 delta = ttf->unicode[pos]-pos;
1443         char do_delta=1;
1444         for(s=pos+1;s<=end;s++) {
1445             U16 delta2 = ttf->unicode[s]-s;
1446             if(delta2!=delta) {
1447                 do_delta=0;
1448                 break;
1449             }
1450         }
1451         U16 range;
1452         if(do_delta) {
1453             range = 0;
1454         } else {
1455             delta = 0;
1456             range = w->len - range_pos;
1457             for(s=pos;s<=end;s++) {
1458                 writeU16(w, ttf->unicode[s]);
1459             }
1460         }
1461         w->data[delta_pos++]=delta>>8;
1462         w->data[delta_pos++]=delta;
1463         w->data[range_pos++]=range>>8;
1464         w->data[range_pos++]=range;
1465         num_segments++;
1466         pos = end+1;
1467     }
1468
1469     /* write out a mapping from 0xffff to 0- seems to be required
1470        by some libraries (e.g. fonttools) */
1471     w->data[end_pos++]=0xff;
1472     w->data[end_pos++]=0xff;
1473     w->data[start_pos++]=0xff;
1474     w->data[start_pos++]=0xff;
1475     w->data[delta_pos++]=0;
1476     w->data[delta_pos++]=1;
1477     w->data[range_pos++]=0;
1478     w->data[range_pos++]=0;
1479
1480     w->data[length_pos]=(w->len-20)>>8;
1481     w->data[length_pos+1]=w->len-20;
1482 }
1483 void cmap_delete(ttf_t*ttf)
1484 {
1485     if(ttf->unicode) {
1486         free(ttf->unicode);
1487         ttf->unicode=0;
1488     }
1489     ttf->unicode_size=0;
1490 }
1491 static char*readString(memreader_t*r, int len)
1492 {
1493     char*s = malloc(len+1);
1494     readBlock(r, s, len);
1495     s[len] = 0;
1496     return s;
1497 }
1498 void name_parse(memreader_t*r, ttf_t*ttf)
1499 {
1500     U16 format = readU16(r);
1501     U16 count = readU16(r);
1502     U16 offset = readU16(r);
1503
1504     int t;
1505     for(t=0;t<count;t++) {
1506         U16 platform = readU16(r);
1507         U16 encoding = readU16(r);
1508         U16 language = readU16(r);
1509         U16 name_id = readU16(r);
1510         U16 len = readU16(r);
1511         U16 offset_2 = readU16(r);
1512
1513         char ** read_name = 0;
1514
1515         INIT_READ(ss, r->mem, r->size, offset+offset_2);
1516         if(!(platform==0 || (platform==1 && encoding==0)))
1517                 continue;
1518
1519         INIT_READ(s, r->mem, r->size, offset+offset_2);
1520
1521         switch (name_id) {
1522             case 1: read_name = &ttf->family_name; break;
1523             case 2: read_name = &ttf->subfamily_name; break;
1524             case 3: read_name = &ttf->font_uid; break;
1525             case 4: read_name = &ttf->full_name; break;
1526             case 5: read_name = &ttf->version_string; break;
1527             case 6: read_name = &ttf->postscript_name; break;
1528             default: read_name = 0;
1529         }
1530
1531         if (read_name) {
1532             if (*read_name) free(*read_name);
1533             *read_name = readString(&s, len);
1534         }
1535     }
1536 }
1537 void name_write(ttf_t*ttf, ttf_table_t*table)
1538 {
1539     char*strings[6] = {ttf->family_name, ttf->subfamily_name, ttf->font_uid, ttf->full_name, ttf->version_string, ttf->postscript_name};
1540     int codes[6] = {1,2,3,4,5,6};
1541
1542     writeU16(table, 0); //format
1543     int count = 0;
1544     int t;
1545     int nr = sizeof(strings)/sizeof(strings[0]);
1546
1547     for(t=0;t<nr;t++) {
1548         if(strings[t])
1549             count+=2;
1550     }
1551     writeU16(table, count); //count
1552
1553     int offset_pos = table->len;
1554     writeU16(table, 0); //offset (will be filled in later)
1555
1556     /* Windows expects the name table to be sorted by platform/encoding/language/name_id */
1557     int offset = 0;
1558     for(t=0;t<nr;t++) {
1559         if(strings[t]) {
1560             writeU16(table, 1); //platform id (mac)
1561             writeU16(table, 0); //encoding id (latin-1)
1562             writeU16(table, 0); //language (english)
1563             writeU16(table, codes[t]);
1564             int len = strlen(strings[t]);
1565             writeU16(table, len);
1566             writeU16(table, offset);
1567             offset += len;
1568         }
1569     }
1570     for(t=0;t<nr;t++) {
1571         if(strings[t]) {
1572             writeU16(table, 3); //platform id (windows)
1573             writeU16(table, 1); //encoding id (ucs-2)
1574             writeU16(table, 0x409); //language (US)
1575             writeU16(table, codes[t]);
1576             int len2 = strlen(strings[t]) * 2;
1577             writeU16(table, len2);
1578             writeU16(table, offset);
1579             offset += len2;
1580         }
1581     }
1582
1583     table->data[offset_pos] = table->len>>8;
1584     table->data[offset_pos+1] = table->len;
1585
1586     for(t=0;t<nr;t++) {
1587         if(strings[t]) {
1588             int len = strlen(strings[t]);
1589             writeBlock(table, strings[t], len);
1590         }
1591     }
1592     for(t=0;t<nr;t++) {
1593         if(strings[t]) {
1594             int s;
1595             int len = strlen(strings[t]);
1596             for(s=0;s<len;s++) {
1597                 writeU8(table, 0);
1598                 writeU8(table, strings[t][s]);
1599             }
1600         }
1601     }
1602 }
1603 void name_delete(ttf_t*ttf)
1604 {
1605     if(ttf->full_name) {
1606         free(ttf->full_name);
1607         ttf->full_name=0;
1608     }
1609     if(ttf->family_name) {
1610         free(ttf->family_name);
1611         ttf->family_name=0;
1612     }
1613     if(ttf->subfamily_name) {
1614         free(ttf->subfamily_name);
1615         ttf->subfamily_name=0;
1616     }
1617     if(ttf->version_string) {
1618         free(ttf->version_string);
1619         ttf->version_string=0;
1620     }
1621     if(ttf->font_uid) {
1622         free(ttf->font_uid);
1623         ttf->font_uid=0;
1624     }
1625     if(ttf->postscript_name) {
1626         free(ttf->postscript_name);
1627         ttf->postscript_name=0;
1628     }
1629 }
1630
1631 static table_post_t*post_new(ttf_t*ttf)
1632 {
1633     table_post_t*post = rfx_calloc(sizeof(table_post_t));
1634     return post;
1635 }
1636 void post_parse(memreader_t*r, ttf_t*ttf)
1637 {
1638     table_post_t*post = ttf->post = rfx_calloc(sizeof(table_post_t));
1639     U16 format = readU16(r);
1640     post->italic_angle = readU16(r);
1641     post->underline_position = readU16(r);
1642     post->underline_thickness = readU16(r);
1643     U16 is_monospaced = readU16(r);
1644     readU16(r); // min mem 42
1645     readU16(r);
1646     readU16(r); // min mem 1
1647     readU16(r);
1648 }
1649 void post_write(ttf_t*ttf, ttf_table_t*table)
1650 {
1651     table_post_t*post = ttf->post;
1652     writeU32(table, 0x00030000);
1653     writeU32(table, post->italic_angle);
1654     writeU16(table, post->underline_position);
1655     writeU16(table, post->underline_thickness);
1656     writeU32(table, 0); //is monospaced TODO
1657     writeU32(table, 0); //min mem 42
1658     writeU32(table, 0);
1659     writeU32(table, 0); //min mem 1
1660     writeU32(table, 0);
1661 }
1662 void post_delete(ttf_t*ttf)
1663 {
1664     if(ttf->post) {
1665         free(ttf->post);
1666         ttf->post = 0;
1667     }
1668 }
1669
1670 void cvt_parse(memreader_t*r, ttf_t*ttf)
1671 {
1672     table_cvt_t*cvt = ttf->cvt = rfx_calloc(sizeof(table_cvt_t));
1673     cvt->num = r->size/2;
1674     cvt->values = malloc(cvt->num*sizeof(S16));
1675     int t;
1676     for(t=0;t<cvt->num;t++) {
1677         cvt->values[t] = readS16(r);
1678     }
1679 }
1680 void cvt_write(ttf_t*ttf, ttf_table_t*table)
1681 {
1682     table_cvt_t*cvt = ttf->cvt;
1683     int t;
1684     for(t=0;t<cvt->num;t++) {
1685         writeS16(table, cvt->values[t]);
1686     }
1687 }
1688 void cvt_delete(ttf_t*ttf)
1689 {
1690     if(ttf->cvt) {
1691         if(ttf->cvt->values) 
1692             free(ttf->cvt->values);
1693         free(ttf->cvt);
1694         ttf->cvt = 0;
1695     }
1696 }
1697
1698 static table_gasp_t*gasp_new(ttf_t*ttf)
1699 {
1700     table_gasp_t*gasp = rfx_calloc(sizeof(table_gasp_t));
1701     gasp->num = 1;
1702     gasp->records = rfx_calloc(sizeof(gasp->records[0])*gasp->num);
1703
1704     gasp->records[0].size = 65535;
1705     gasp->records[0].behaviour = 15; //gridfit+grayscale rendering
1706     return gasp;
1707 }
1708 void gasp_parse(memreader_t*r, ttf_t*ttf)
1709 {
1710     table_gasp_t*gasp = ttf->gasp = rfx_calloc(sizeof(table_gasp_t));
1711     readU16(r); //version
1712     int num = readU16(r);
1713     int t;
1714     if(!num) return;
1715     gasp->records = malloc(sizeof(gasp->records[0])*num);
1716     for(t=0;t<num;t++) {
1717         gasp->records[t].size = readU16(r);
1718         gasp->records[t].behaviour = readU16(r);
1719     }
1720 }
1721 void gasp_write(ttf_t*ttf, ttf_table_t*table)
1722 {
1723     table_gasp_t*gasp = ttf->gasp;
1724     writeU16(table, 0);
1725     writeU16(table, gasp->num);
1726     int t;
1727     for(t=0;t<gasp->num;t++) {
1728         writeU16(table, gasp->records[t].size);
1729         writeU16(table, gasp->records[t].behaviour);
1730     }
1731 }
1732 void gasp_delete(ttf_t*ttf)
1733 {
1734     if(ttf->gasp) {
1735         if(ttf->gasp->records)
1736             free(ttf->gasp->records);
1737         free(ttf->gasp);
1738         ttf->gasp = 0;
1739     }
1740 }
1741
1742 void fpgm_new(ttf_t*ttf)
1743 {
1744     table_code_t*fpgm = ttf->fpgm = rfx_calloc(sizeof(table_code_t));
1745 }
1746 void fpgm_parse(memreader_t*r, ttf_t*ttf)
1747 {
1748     table_code_t*fpgm = ttf->fpgm  = rfx_calloc(sizeof(table_code_t));
1749     if(!r->size) return;
1750     fpgm->size = r->size;
1751     fpgm->code = malloc(r->size);
1752     readBlock(r, fpgm->code, r->size);
1753 }
1754 void fpgm_write(ttf_t*ttf, ttf_table_t*table)
1755 {
1756     table_code_t*code = ttf->fpgm;
1757     writeBlock(table, code->code, code->size);
1758 }
1759 void fpgm_delete(ttf_t*ttf)
1760 {
1761     if(ttf->fpgm) {
1762         if(ttf->fpgm->code)
1763             free(ttf->fpgm->code);
1764         free(ttf->fpgm);
1765         ttf->fpgm = 0;
1766     }
1767 }
1768
1769 void prep_parse(memreader_t*r, ttf_t*ttf)
1770 {
1771     table_code_t*prep = ttf->prep  = rfx_calloc(sizeof(table_code_t));
1772     if(!r->size) return;
1773     prep->size = r->size;
1774     prep->code = malloc(r->size);
1775     readBlock(r, prep->code, r->size);
1776 }
1777 void prep_write(ttf_t*ttf, ttf_table_t*table)
1778 {
1779     table_code_t*code = ttf->prep;
1780     writeBlock(table, code->code, code->size);
1781 }
1782 void prep_delete(ttf_t*ttf)
1783 {
1784     if(ttf->prep) {
1785         if(ttf->prep->code)
1786             free(ttf->prep->code);
1787         free(ttf->prep);
1788         ttf->prep = 0;
1789     }
1790 }
1791
1792 static int ttf_parse_tables(ttf_t*ttf)
1793 {
1794     ttf_table_t*table;
1795
1796     table = ttf_find_table(ttf, TAG_HEAD);
1797     if(!table) {
1798         msg("<error> Font has no head table");
1799         return 0;
1800     }
1801     INIT_READ(m, table->data, table->len, 0);
1802     int loc_index = head_parse(ttf, &m);
1803     ttf_table_delete(ttf, table);
1804
1805     table = ttf_find_table(ttf, TAG_MAXP);
1806     if(!table) {
1807         msg("<error> Font has no maxp table");
1808         return 0;
1809     }
1810     INIT_READ(m2, table->data, table->len, 0);
1811     ttf->maxp = maxp_parse(ttf, &m2);
1812     ttf_table_delete(ttf, table);
1813
1814     if(!ttf->num_glyphs) {
1815         msg("<error> Invalid number of characters");
1816         return 0;
1817     }
1818     ttf->glyphs = rfx_calloc(sizeof(ttfglyph_t)*ttf->num_glyphs);
1819
1820     table = ttf_find_table(ttf, TAG_OS2);
1821     if(table) {
1822         INIT_READ(m, table->data, table->len, 0);
1823         ttf->os2 = os2_parse(&m);
1824         ttf_table_delete(ttf, table);
1825     }
1826
1827
1828     table = ttf_find_table(ttf, TAG_HHEA);
1829     if(table) {
1830         INIT_READ(m, table->data, table->len, 0);
1831         int num_advances = hea_parse(&m, ttf);
1832         ttf_table_delete(ttf, table);
1833
1834         table = ttf_find_table(ttf, TAG_HMTX);
1835         if(table) {
1836             INIT_READ(m, table->data, table->len, 0);
1837             mtx_parse(&m, ttf, num_advances);
1838             ttf_table_delete(ttf, table);
1839         }
1840     } else {
1841         table = ttf_find_table(ttf, TAG_VHEA);
1842         if(table) {
1843             ttf->is_vertical=1;
1844             INIT_READ(m, table->data, table->len, 0);
1845             int num_advances = hea_parse(&m, ttf);
1846             ttf_table_delete(ttf, table);
1847
1848             table = ttf_find_table(ttf, TAG_VMTX);
1849             if(table) {
1850                 INIT_READ(m, table->data, table->len, 0);
1851                 mtx_parse(&m, ttf, num_advances);
1852                 ttf_table_delete(ttf, table);
1853             }
1854         } else {
1855             msg("<error> Font contains neither HHEA nor VHEA");
1856         }
1857     }
1858     table = ttf_find_table(ttf, TAG_LOCA);
1859     if(table) {
1860         INIT_READ(m, table->data, table->len, 0);
1861         U32*loca = loca_parse(&m, ttf, loc_index);
1862         ttf_table_delete(ttf, table);
1863         table = ttf_find_table(ttf, TAG_GLYF);
1864         if(table) {
1865             INIT_READ(m, table->data, table->len, 0);
1866             glyf_parse(&m, ttf, loca);
1867             ttf_table_delete(ttf, table);
1868         }
1869         free(loca);
1870     }
1871
1872     table = ttf_find_table(ttf, TAG_CMAP);
1873     if(table) {
1874         INIT_READ(m, table->data, table->len, 0);
1875         cmap_parse(&m, ttf);
1876         ttf_table_delete(ttf, table);
1877     }
1878
1879     table = ttf_find_table(ttf, TAG_POST);
1880     if(table) {
1881         INIT_READ(m, table->data, table->len, 0);
1882         post_parse(&m, ttf);
1883         ttf_table_delete(ttf, table);
1884     }
1885
1886     table = ttf_find_table(ttf, TAG_NAME);
1887     if(table) {
1888         INIT_READ(m, table->data, table->len, 0);
1889         name_parse(&m, ttf);
1890         ttf_table_delete(ttf, table);
1891     }
1892
1893     table = ttf_find_table(ttf, TAG_CVT);
1894     if(table) {
1895         INIT_READ(m, table->data, table->len, 0);
1896         cvt_parse(&m, ttf);
1897         ttf_table_delete(ttf, table);
1898     }
1899     
1900     table = ttf_find_table(ttf, TAG_GASP);
1901     if(table) {
1902         INIT_READ(m, table->data, table->len, 0);
1903         gasp_parse(&m, ttf);
1904         ttf_table_delete(ttf, table);
1905     }
1906     
1907     table = ttf_find_table(ttf, TAG_PREP);
1908     if(table) {
1909         INIT_READ(m, table->data, table->len, 0);
1910         prep_parse(&m, ttf);
1911         ttf_table_delete(ttf, table);
1912     }
1913     
1914     table = ttf_find_table(ttf, TAG_FPGM);
1915     if(table) {
1916         INIT_READ(m, table->data, table->len, 0);
1917         fpgm_parse(&m, ttf);
1918         ttf_table_delete(ttf, table);
1919     }
1920
1921     return 1;
1922 }
1923 static void ttf_collapse_tables(ttf_t*ttf)
1924 {
1925     ttf_table_t*table;
1926
1927     ttf_table_t*head = ttf_find_table(ttf, TAG_HEAD);
1928     if(head)
1929         return; //already collapsed
1930
1931     if(ttf->maxp) {
1932         table = ttf_addtable(ttf, TAG_MAXP);
1933         maxp_write(ttf, table);
1934         maxp_delete(ttf);
1935     }
1936
1937     if(ttf->os2) {
1938         table = ttf_addtable(ttf, TAG_OS2);
1939         os2_write(ttf, table);
1940         os2_delete(ttf);
1941     }
1942
1943     if(ttf->hea) {
1944         if(!ttf->is_vertical) {
1945             table = ttf_addtable(ttf, TAG_HMTX);
1946             int num_advances = mtx_write(ttf, table);
1947             table = ttf_addtable(ttf, TAG_HHEA);
1948             hea_write(ttf, table, num_advances);
1949             hea_delete(ttf);
1950         } else {
1951             table = ttf_addtable(ttf, TAG_VMTX);
1952             int num_advances = mtx_write(ttf, table);
1953             table = ttf_addtable(ttf, TAG_VHEA);
1954             hea_write(ttf, table, num_advances);
1955             hea_delete(ttf);
1956         }
1957     }
1958
1959     int loca_size=0;
1960     if(ttf->num_glyphs) {
1961         if(ttf->unicode) {
1962             table = ttf_addtable(ttf, TAG_CMAP);
1963             cmap_write(ttf, table);
1964             cmap_delete(ttf);
1965         }
1966
1967         if(ttf->glyphs) {
1968             table = ttf_addtable(ttf, TAG_GLYF);
1969             U32*locations = glyf_write(ttf, table);
1970             table = ttf_addtable(ttf, TAG_LOCA);
1971             loca_size = loca_write(ttf, table, locations);
1972             free(locations);
1973             glyf_delete(ttf);
1974         }
1975     }
1976
1977     if(ttf->full_name || ttf->family_name || ttf->subfamily_name || ttf->font_uid || ttf->postscript_name) {
1978         table = ttf_addtable(ttf, TAG_NAME);
1979         name_write(ttf, table);
1980         name_delete(ttf);
1981     }
1982     if(ttf->post) {
1983         table = ttf_addtable(ttf, TAG_POST);
1984         post_write(ttf, table);
1985         post_delete(ttf);
1986     }
1987     if(ttf->cvt) {
1988         table = ttf_addtable(ttf, TAG_CVT);
1989         cvt_write(ttf, table);
1990         cvt_delete(ttf);
1991     }
1992     if(ttf->gasp) {
1993         table = ttf_addtable(ttf, TAG_GASP);
1994         gasp_write(ttf, table);
1995         gasp_delete(ttf);
1996     }
1997
1998     table = ttf_addtable(ttf, TAG_HEAD);
1999     head_write(ttf, table, loca_size);
2000     head_delete(ttf);
2001 }
2002
2003 ttf_t*ttf_new()
2004 {
2005     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
2006     ttf->version = VERSION_1_0;
2007     return ttf;
2008 }
2009 ttf_t* ttf_load(void*data, int length)
2010 {
2011     INIT_READ(r,data,length, 0);
2012
2013     if(length<12) {
2014         msg("<error> Truncated Truetype file (%d bytes)", length);
2015         return 0;
2016     }
2017
2018     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
2019     ttf->version = readU32(&r);
2020     if(ttf->version == SWAP32(length)) {
2021         U32 fontDataSize = readU32(&r);
2022         U32 version = readU32(&r);
2023         U32 flags  = readU32(&r);
2024         U8 panose[10];
2025         readBlock(&r, panose, 10);
2026         readU8(&r); //charset
2027         readU8(&r); //italoc
2028         readU32(&r); //weight
2029         readU16(&r); //fstype
2030         U16 magic = readU16(&r); //magicNumber
2031         /* we're being paranoid: it's entirely possible for the font
2032            size to be exactly 0x10000. Only treat this font as eot if
2033            it has the right magic number */
2034         if(magic == 0x4c50) {
2035             readU32(&r); //unicoderange[0]
2036             readU32(&r); //unicoderange[1]
2037             readU32(&r); //unicoderange[2]
2038             readU32(&r); //unicoderange[3]
2039             readU32(&r); //codepagerange[0]
2040             readU32(&r); //codepagerange[1]
2041             readU32(&r); //checksumadjustment
2042             readU32(&r); //reserved[0]
2043             readU32(&r); //reserved[1]
2044             readU32(&r); //reserved[2]
2045             readU32(&r); //reserved[3]
2046             readU16(&r); //padding
2047
2048             int nr=0;
2049             for(nr=0;nr<4;nr++) {
2050                 int t, len;
2051                 /* All of ttf is big-endian. All of ttf? No. One small eot table
2052                    of indomitable little-endian... */
2053                 len = readU8(&r);
2054                 len |= readU8(&r)<<8;
2055                 len /= 2;
2056                 for(t=0;t<len;t++) {
2057                     U8 c = readU16(&r)>>8;
2058                 }
2059                 readU16(&r); // zero terminator
2060             }
2061             readU16(&r); // more padding
2062
2063             /* adjust the offset to the start of the actual truetype
2064                data- the positions in the table header will be relative
2065                to the ttf data after the header, not to the file */
2066             r.mem += r.pos;
2067             r.size -= r.pos;
2068             r.pos = 0;
2069             ttf->version = readU32(&r);
2070         } else {
2071             reader_reset(&r);
2072             ttf->version = readU32(&r);
2073         }
2074     }
2075
2076     if(ttf->version == TTCFTAG) {
2077         /* a ttc collection is a number of truetype fonts
2078            packaged together */
2079         if(length<16) {
2080             msg("<error> Truncated TTC file (%d bytes)", length);
2081             return 0;
2082         }
2083         U32 ttcf_version = readU32(&r); // 0x00000100: v1.0, 0x00000200: v2.0, includes DSIG table
2084         U32 num_fonts = readU32(&r); // number of fonts
2085         U32 font1_position = readU32(&r);
2086         if(font1_position+12 > length) {\
2087             msg("<error> Truncated TTC file (%d bytes, first font at %d)", length, font1_position);
2088             return 0;
2089         }
2090         r.pos = font1_position;
2091         ttf->version = readU32(&r);
2092     }
2093
2094     int num_tables = readU16(&r);
2095
2096     readU16(&r); //search range
2097     readU16(&r); //entry selector
2098     readU16(&r); //range shift
2099
2100     if(num_tables*16 > length) {
2101         msg("<error> Truncated TTF file (table entries: %d)", num_tables);
2102         if(ttf->version != OPENTYPE &&
2103            ttf->version != TRUETYPE_MACOS &&
2104            ttf->version != VERSION_1_0) {
2105             // bad table length, weird version. This is probably not a ttf file.
2106             return 0;
2107         }
2108     }
2109
2110     U32*table_data = malloc(16*num_tables);
2111     int t;
2112     for(t=0;t<num_tables*4;t++) {
2113         table_data[t] = readU32(&r);
2114     }
2115     for(t=0;t<num_tables;t++) {
2116         U32 tag = table_data[t*4];
2117         U32 checksum = table_data[t*4+1];
2118         U32 pos = table_data[t*4+2];
2119         U32 len = table_data[t*4+3];
2120         
2121         printf("TTF Table %02x%02x%02x%02x %c%c%c%c\n", 
2122                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, 
2123                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff
2124                 );
2125
2126         if(pos+len > length) {
2127             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);
2128         } else {
2129             U8*mem = malloc(len);
2130             r.pos = pos;
2131             readBlock(&r, mem, len);
2132
2133             ttf_table_t*table = ttf_addtable(ttf, tag);
2134             table->data = mem;
2135             table->len = table->memsize = len;
2136 #if 0
2137             U32 checksum2 = ttf_table_checksum(table);
2138             if(checksum2!=checksum) {
2139                 msg("<warning> Checksum mismatch in tag %02x%02x%02x%02x %c%c%c%c (%d bytes) %08x!=%08x",
2140                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2141                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2142                         len, checksum2, checksum);
2143             }
2144 #endif
2145         }
2146     }
2147     free(table_data);
2148
2149     if(!ttf_parse_tables(ttf))
2150         return 0;
2151
2152     return ttf;
2153 }
2154 void ttf_create_truetype_tables(ttf_t*ttf)
2155 {
2156     if(!ttf->head)
2157         ttf->head = head_new(ttf);
2158     if(!ttf->maxp)
2159         ttf->maxp = maxp_new(ttf);
2160     if(!ttf->hea)
2161         ttf->hea = hea_new(ttf);
2162     if(!ttf->os2)
2163         ttf->os2 = os2_new(ttf);
2164     if(!ttf->post)
2165         ttf->post = post_new(ttf);
2166     if(!ttf->gasp)
2167         ttf->gasp = gasp_new(ttf);
2168     if(!ttf->fpgm)
2169         ttf->fpgm = fpgm_new(ttf);
2170 }
2171
2172 ttf_table_t* ttf_write(ttf_t*ttf, U32*checksum_adjust)
2173 {
2174     ttf_collapse_tables(ttf);
2175
2176     ttf_table_t*file = ttf_table_new(0);
2177     writeU32(file, VERSION_1_0);
2178
2179     /* write number of tables */
2180     int num_tables=0;
2181     ttf_table_t*t = ttf->tables;
2182     while(t) {
2183         num_tables++;
2184         t = t->next;
2185     }
2186     writeU16(file, num_tables);
2187
2188     /* write search range */
2189     int tmp = num_tables;
2190     int search_range = 0;
2191     while(tmp) {
2192         search_range = tmp;
2193         tmp = tmp&(tmp-1);
2194     }
2195     tmp = search_range;
2196     search_range*=16;
2197     writeU16(file, search_range);
2198
2199     /* write entry selector */
2200     int entry_selector = 0;
2201     while(tmp>1) {
2202         tmp>>=1;
2203         entry_selector++;
2204     }
2205     writeU16(file, entry_selector);
2206
2207     /* write range shift */
2208     int range_shift = num_tables*16 - search_range;
2209     writeU16(file, range_shift);
2210
2211     /* write table dictionary */
2212     int table_dictionary_pos = file->len;
2213     int data_pos = file->len + num_tables*16;
2214     for(t=ttf->tables;t;t=t->next) {
2215         writeU32(file, t->id);
2216         writeU32(file, ttf_table_checksum(t));
2217         writeU32(file, data_pos);
2218         writeU32(file, t->len);
2219         data_pos += t->len;
2220         data_pos += (-t->len)&3; //pad
2221     }
2222
2223     /* write tables */
2224     int head_pos = 0;
2225     U8 zero[4]={0,0,0,0};
2226     for(t=ttf->tables;t;t=t->next) {
2227         if(t->id == TAG_HEAD)
2228             head_pos = file->len;
2229         writeBlock(file, t->data, t->len);
2230         writeBlock(file, zero, (-t->len)&3); //pad
2231     }
2232     U32 checksum = 0xb1b0afba - ttf_table_checksum(file);
2233     if(checksum_adjust)
2234         *checksum_adjust = checksum;
2235     U8*checksum2 = file->data + head_pos + 8;
2236     checksum2[0] = checksum>>24;
2237     checksum2[1] = checksum>>16;
2238     checksum2[2] = checksum>>8;
2239     checksum2[3] = checksum>>0;
2240     return file;
2241 }
2242
2243 ttf_table_t* ttf_eot_head(ttf_t*ttf)
2244 {
2245     ttf_table_t*file = ttf_table_new(0);
2246     writeU32(file, 0); //file size (filled in later)
2247     writeU32(file, 0); //fontdatasize (filled in later)
2248     writeU32(file, 0x01000200);
2249     writeU32(file, 0); //flags
2250     writeU8(file, ttf->os2->panose_FamilyType);
2251     writeU8(file, ttf->os2->panose_SerifStyle);
2252     writeU8(file, ttf->os2->panose_Weight);
2253     writeU8(file, ttf->os2->panose_Proportion);
2254     writeU8(file, ttf->os2->panose_Contrast);
2255     writeU8(file, ttf->os2->panose_StrokeVariation);
2256     writeU8(file, ttf->os2->panose_ArmStyle);
2257     writeU8(file, ttf->os2->panose_Letterform);
2258     writeU8(file, ttf->os2->panose_Midline);
2259     writeU8(file, ttf->os2->panose_XHeight);
2260     writeU8(file, 1); //charset (default)
2261     writeU8(file, ttf->os2->fsSelection&1); //italic
2262     writeU32_LE(file, ttf->os2->usWeightClass);
2263     writeU16(file, 0); //fstype
2264     writeU16(file, 0x4c50); //magic
2265     writeU32_LE(file, ttf->os2->ulCharRange[0]);
2266     writeU32_LE(file, ttf->os2->ulCharRange[1]);
2267     writeU32_LE(file, ttf->os2->ulCharRange[2]);
2268     writeU32_LE(file, ttf->os2->ulCharRange[3]);
2269     writeU32_LE(file, ttf->os2->ulCodePageRange1);
2270     writeU32_LE(file, ttf->os2->ulCodePageRange2);
2271     writeU32(file, 0); //checksum adjust (filled in later)
2272     writeU32(file, 0); //reserved[0]
2273     writeU32(file, 0); //reserved[1]
2274     writeU32(file, 0); //reserved[2]
2275     writeU32(file, 0); //reserved[3]
2276     writeU16(file, 0); //padding(1)
2277
2278     int i,t,len;
2279
2280     char* strings[] = {ttf->family_name, ttf->subfamily_name, ttf->version_string, ttf->full_name};
2281     int nr = sizeof(strings)/sizeof(strings[0]);
2282
2283     for(i=0;i<nr;i++) {
2284         char *string = strings[i];
2285
2286         //family name
2287         len = strlen(string);
2288         writeU16_LE(file, len*2);
2289         for(t=0;t<len;t++) {
2290             writeU8(file, 0);
2291             writeU8(file, string[t]);
2292         }
2293         writeU16(file, 0); //zero byte pad
2294     }
2295
2296     writeU16(file, 0); //zero byte pad
2297
2298     writeU16(file, 0); //padding(2)
2299     return file;
2300 }
2301
2302 void ttf_save_eot(ttf_t*ttf, const char*filename)
2303 {
2304     ttf_table_t* eot = ttf_eot_head(ttf);
2305     U32 checksum_adjust = 0;
2306     ttf_table_t* t = ttf_write(ttf, &checksum_adjust);
2307
2308     U8*len_data = eot->data;
2309     U32 full_len = eot->len + t->len;
2310     len_data[0] = full_len>>0;
2311     len_data[1] = full_len>>8;
2312     len_data[2] = full_len>>16;
2313     len_data[3] = full_len>>24;
2314
2315     U8*len_data2 = eot->data+4;
2316     len_data2[0] = t->len>>0;
2317     len_data2[1] = t->len>>8;
2318     len_data2[2] = t->len>>16;
2319     len_data2[3] = t->len>>24;
2320
2321     U8*checksum_data = eot->data + 60;
2322     checksum_data[0] = checksum_adjust>>0;
2323     checksum_data[1] = checksum_adjust>>8;
2324     checksum_data[2] = checksum_adjust>>16;
2325     checksum_data[3] = checksum_adjust>>24;
2326
2327     FILE*fi = fopen(filename, "wb");
2328     if(!fi) {
2329         perror(filename);
2330         return;
2331     }
2332
2333     fwrite(eot->data, eot->len, 1, fi);
2334     fwrite(t->data, t->len, 1, fi);
2335     fclose(fi);
2336     ttf_table_delete(0, t);
2337     ttf_table_delete(0, eot);
2338 }
2339
2340 void ttf_save(ttf_t*ttf, const char*filename)
2341 {
2342     ttf_table_t* t = ttf_write(ttf, 0);
2343     FILE*fi = fopen(filename, "wb");
2344     if(!fi) {
2345         perror(filename);
2346         return;
2347     }
2348     fwrite(t->data, t->len, 1, fi);
2349     fclose(fi);
2350     ttf_table_delete(0, t);
2351 }
2352
2353 void ttf_dump(ttf_t*ttf)
2354 {
2355     msg("<notice> Truetype file version %08x%s", ttf->version, ttf->version == OPENTYPE?" (opentype)":"");
2356     ttf_table_t*table = ttf->tables;
2357     while(table) {
2358         U32 tag = table->id;
2359         msg("<notice> Tag %02x%02x%02x%02x [%c%c%c%c] (length: %d)",
2360                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2361                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, table->len);
2362         table = table->next;
2363     }
2364     //ttf_table_dump(ttf_find_table(ttf, TAG_MAXP));
2365
2366     head_dump(ttf);
2367     hea_dump(ttf);
2368     os2_dump(ttf);
2369     maxp_dump(ttf);
2370     glyf_dump(ttf);
2371 }
2372 void ttf_destroy_tables(ttf_t*ttf)
2373 {
2374     ttf_table_t*table = ttf->tables;
2375     while(table) {
2376         ttf_table_t*next = table->next;
2377         free(table->data);
2378         free(table);
2379         table = next;
2380     }
2381     ttf->tables = 0;
2382 }
2383 void ttf_reduce(ttf_t*ttf)
2384 {
2385     ttf_destroy_tables(ttf);
2386 }
2387 void ttf_destroy(ttf_t*ttf)
2388 {
2389     ttf_destroy_tables(ttf);
2390     maxp_delete(ttf);
2391     os2_delete(ttf);
2392     head_delete(ttf);
2393     hea_delete(ttf);
2394     glyf_delete(ttf);
2395     post_delete(ttf);
2396     cvt_delete(ttf);
2397     name_delete(ttf);
2398     free(ttf);
2399 }
2400
2401 #ifdef MAIN
2402 int main(int argn, const char*argv[])
2403 {
2404     setConsoleLogging(7);
2405     const char*filename = "comic.ttf";
2406     if(argn>1)
2407         filename = argv[1];
2408     //msg("<notice> Loading %s", filename);
2409     memfile_t*m = memfile_open(filename);
2410     ttf_t*ttf = ttf_load(m->data, m->len);
2411
2412     if(!ttf) {
2413         msg("<error> Couldn't load %s", filename);
2414         return 1;
2415     }
2416     ttf_reduce(ttf);
2417
2418     ttf->full_name = strdup("Test-Normal");
2419     ttf->family_name = strdup("Test");
2420     ttf->subfamily_name = strdup("Normal");
2421     ttf->version_string = strdup("Version 1.0");
2422     ttf->font_uid = strdup("omguid");
2423     ttf->postscript_name = strdup("Test-psname");
2424
2425     if(!ttf) return 1;
2426     memfile_close(m);
2427     //ttf_dump(ttf);
2428     //printf("os2 version: %04x (%d), maxp size: %d\n",
2429 //          ttf->os2->version, ttf->os2->size, ttf->maxp->size);
2430     ttf_save_eot(ttf, "testfont.eot");
2431     ttf_save(ttf, "testfont.ttf");
2432     ttf_destroy(ttf);
2433     return 0;
2434
2435 }
2436 #endif