OSX bearing fix
[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     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].bearing < hea->minLeftSideBearing)
730                 hea->minLeftSideBearing = ttf->glyphs[t].bearing;
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         writeS16(w, ttf->glyphs[t].bearing);
853     }
854     for(;t<ttf->num_glyphs;t++) {
855         writeS16(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     tmp = search_range;
1422     while(tmp>1) {tmp>>=1;entry_selector++;}
1423     w->data[num_segments_pos++]=entry_selector>>8;
1424     w->data[num_segments_pos++]=entry_selector;
1425     /* backpatch range shift */
1426     int range_shift = num_segments*2 - search_range*2;
1427     w->data[num_segments_pos++]=range_shift>>8;
1428     w->data[num_segments_pos++]=range_shift;
1429
1430     pos=0;
1431     num_segments = 0;
1432     while(pos < ttf->unicode_size) {
1433         if(!ttf->unicode[pos]) {
1434             pos++;
1435             continue;
1436         }
1437         U16 end = segment_size(ttf->unicode, pos, ttf->unicode_size);
1438         w->data[end_pos++]=end>>8;
1439         w->data[end_pos++]=end;
1440         w->data[start_pos++]=pos>>8;
1441         w->data[start_pos++]=pos;
1442         int s;
1443         U16 delta = ttf->unicode[pos]-pos;
1444         char do_delta=1;
1445         for(s=pos+1;s<=end;s++) {
1446             U16 delta2 = ttf->unicode[s]-s;
1447             if(delta2!=delta) {
1448                 do_delta=0;
1449                 break;
1450             }
1451         }
1452         U16 range;
1453         if(do_delta) {
1454             range = 0;
1455         } else {
1456             delta = 0;
1457             range = w->len - range_pos;
1458             for(s=pos;s<=end;s++) {
1459                 writeU16(w, ttf->unicode[s]);
1460             }
1461         }
1462         w->data[delta_pos++]=delta>>8;
1463         w->data[delta_pos++]=delta;
1464         w->data[range_pos++]=range>>8;
1465         w->data[range_pos++]=range;
1466         num_segments++;
1467         pos = end+1;
1468     }
1469
1470     /* write out a mapping from 0xffff to 0- seems to be required
1471        by some libraries (e.g. fonttools) */
1472     w->data[end_pos++]=0xff;
1473     w->data[end_pos++]=0xff;
1474     w->data[start_pos++]=0xff;
1475     w->data[start_pos++]=0xff;
1476     w->data[delta_pos++]=0;
1477     w->data[delta_pos++]=1;
1478     w->data[range_pos++]=0;
1479     w->data[range_pos++]=0;
1480
1481     w->data[length_pos]=(w->len-20)>>8;
1482     w->data[length_pos+1]=w->len-20;
1483 }
1484 void cmap_delete(ttf_t*ttf)
1485 {
1486     if(ttf->unicode) {
1487         free(ttf->unicode);
1488         ttf->unicode=0;
1489     }
1490     ttf->unicode_size=0;
1491 }
1492 static char*readString(memreader_t*r, int len)
1493 {
1494     char*s = malloc(len+1);
1495     readBlock(r, s, len);
1496     s[len] = 0;
1497     return s;
1498 }
1499 void name_parse(memreader_t*r, ttf_t*ttf)
1500 {
1501     U16 format = readU16(r);
1502     U16 count = readU16(r);
1503     U16 offset = readU16(r);
1504
1505     int t;
1506     for(t=0;t<count;t++) {
1507         U16 platform = readU16(r);
1508         U16 encoding = readU16(r);
1509         U16 language = readU16(r);
1510         U16 name_id = readU16(r);
1511         U16 len = readU16(r);
1512         U16 offset_2 = readU16(r);
1513
1514         char ** read_name = 0;
1515
1516         INIT_READ(ss, r->mem, r->size, offset+offset_2);
1517         if(!(platform==0 || (platform==1 && encoding==0)))
1518                 continue;
1519
1520         INIT_READ(s, r->mem, r->size, offset+offset_2);
1521
1522         switch (name_id) {
1523             case 1: read_name = &ttf->family_name; break;
1524             case 2: read_name = &ttf->subfamily_name; break;
1525             case 3: read_name = &ttf->font_uid; break;
1526             case 4: read_name = &ttf->full_name; break;
1527             case 5: read_name = &ttf->version_string; break;
1528             case 6: read_name = &ttf->postscript_name; break;
1529             default: read_name = 0;
1530         }
1531
1532         if (read_name) {
1533             if (*read_name) free(*read_name);
1534             *read_name = readString(&s, len);
1535         }
1536     }
1537 }
1538 void name_write(ttf_t*ttf, ttf_table_t*table)
1539 {
1540     char*strings[6] = {ttf->family_name, ttf->subfamily_name, ttf->font_uid, ttf->full_name, ttf->version_string, ttf->postscript_name};
1541     int codes[6] = {1,2,3,4,5,6};
1542
1543     writeU16(table, 0); //format
1544     int count = 0;
1545     int t;
1546     int nr = sizeof(strings)/sizeof(strings[0]);
1547
1548     for(t=0;t<nr;t++) {
1549         if(strings[t])
1550             count+=2;
1551     }
1552     writeU16(table, count); //count
1553
1554     int offset_pos = table->len;
1555     writeU16(table, 0); //offset (will be filled in later)
1556
1557     /* Windows expects the name table to be sorted by platform/encoding/language/name_id */
1558     int offset = 0;
1559     for(t=0;t<nr;t++) {
1560         if(strings[t]) {
1561             writeU16(table, 1); //platform id (mac)
1562             writeU16(table, 0); //encoding id (latin-1)
1563             writeU16(table, 0); //language (english)
1564             writeU16(table, codes[t]);
1565             int len = strlen(strings[t]);
1566             writeU16(table, len);
1567             writeU16(table, offset);
1568             offset += len;
1569         }
1570     }
1571     for(t=0;t<nr;t++) {
1572         if(strings[t]) {
1573             writeU16(table, 3); //platform id (windows)
1574             writeU16(table, 1); //encoding id (ucs-2)
1575             writeU16(table, 0x409); //language (US)
1576             writeU16(table, codes[t]);
1577             int len2 = strlen(strings[t]) * 2;
1578             writeU16(table, len2);
1579             writeU16(table, offset);
1580             offset += len2;
1581         }
1582     }
1583
1584     table->data[offset_pos] = table->len>>8;
1585     table->data[offset_pos+1] = table->len;
1586
1587     for(t=0;t<nr;t++) {
1588         if(strings[t]) {
1589             int len = strlen(strings[t]);
1590             writeBlock(table, strings[t], len);
1591         }
1592     }
1593     for(t=0;t<nr;t++) {
1594         if(strings[t]) {
1595             int s;
1596             int len = strlen(strings[t]);
1597             for(s=0;s<len;s++) {
1598                 writeU8(table, 0);
1599                 writeU8(table, strings[t][s]);
1600             }
1601         }
1602     }
1603 }
1604 void name_delete(ttf_t*ttf)
1605 {
1606     if(ttf->full_name) {
1607         free(ttf->full_name);
1608         ttf->full_name=0;
1609     }
1610     if(ttf->family_name) {
1611         free(ttf->family_name);
1612         ttf->family_name=0;
1613     }
1614     if(ttf->subfamily_name) {
1615         free(ttf->subfamily_name);
1616         ttf->subfamily_name=0;
1617     }
1618     if(ttf->version_string) {
1619         free(ttf->version_string);
1620         ttf->version_string=0;
1621     }
1622     if(ttf->font_uid) {
1623         free(ttf->font_uid);
1624         ttf->font_uid=0;
1625     }
1626     if(ttf->postscript_name) {
1627         free(ttf->postscript_name);
1628         ttf->postscript_name=0;
1629     }
1630 }
1631
1632 static table_post_t*post_new(ttf_t*ttf)
1633 {
1634     table_post_t*post = rfx_calloc(sizeof(table_post_t));
1635     return post;
1636 }
1637 void post_parse(memreader_t*r, ttf_t*ttf)
1638 {
1639     table_post_t*post = ttf->post = rfx_calloc(sizeof(table_post_t));
1640     U16 format = readU16(r);
1641     post->italic_angle = readU16(r);
1642     post->underline_position = readU16(r);
1643     post->underline_thickness = readU16(r);
1644     U16 is_monospaced = readU16(r);
1645     readU16(r); // min mem 42
1646     readU16(r);
1647     readU16(r); // min mem 1
1648     readU16(r);
1649 }
1650 void post_write(ttf_t*ttf, ttf_table_t*table)
1651 {
1652     table_post_t*post = ttf->post;
1653     writeU32(table, 0x00030000);
1654     writeU32(table, post->italic_angle);
1655     writeU16(table, post->underline_position);
1656     writeU16(table, post->underline_thickness);
1657     writeU32(table, 0); //is monospaced TODO
1658     writeU32(table, 0); //min mem 42
1659     writeU32(table, 0);
1660     writeU32(table, 0); //min mem 1
1661     writeU32(table, 0);
1662 }
1663 void post_delete(ttf_t*ttf)
1664 {
1665     if(ttf->post) {
1666         free(ttf->post);
1667         ttf->post = 0;
1668     }
1669 }
1670
1671 void cvt_parse(memreader_t*r, ttf_t*ttf)
1672 {
1673     table_cvt_t*cvt = ttf->cvt = rfx_calloc(sizeof(table_cvt_t));
1674     cvt->num = r->size/2;
1675     cvt->values = malloc(cvt->num*sizeof(S16));
1676     int t;
1677     for(t=0;t<cvt->num;t++) {
1678         cvt->values[t] = readS16(r);
1679     }
1680 }
1681 void cvt_write(ttf_t*ttf, ttf_table_t*table)
1682 {
1683     table_cvt_t*cvt = ttf->cvt;
1684     int t;
1685     for(t=0;t<cvt->num;t++) {
1686         writeS16(table, cvt->values[t]);
1687     }
1688 }
1689 void cvt_delete(ttf_t*ttf)
1690 {
1691     if(ttf->cvt) {
1692         if(ttf->cvt->values) 
1693             free(ttf->cvt->values);
1694         free(ttf->cvt);
1695         ttf->cvt = 0;
1696     }
1697 }
1698
1699 static table_gasp_t*gasp_new(ttf_t*ttf)
1700 {
1701     table_gasp_t*gasp = rfx_calloc(sizeof(table_gasp_t));
1702     gasp->num = 1;
1703     gasp->records = rfx_calloc(sizeof(gasp->records[0])*gasp->num);
1704
1705     gasp->records[0].size = 65535;
1706     gasp->records[0].behaviour = 15; //gridfit+grayscale rendering
1707     return gasp;
1708 }
1709 void gasp_parse(memreader_t*r, ttf_t*ttf)
1710 {
1711     table_gasp_t*gasp = ttf->gasp = rfx_calloc(sizeof(table_gasp_t));
1712     readU16(r); //version
1713     int num = readU16(r);
1714     int t;
1715     if(!num) return;
1716     gasp->records = malloc(sizeof(gasp->records[0])*num);
1717     for(t=0;t<num;t++) {
1718         gasp->records[t].size = readU16(r);
1719         gasp->records[t].behaviour = readU16(r);
1720     }
1721 }
1722 void gasp_write(ttf_t*ttf, ttf_table_t*table)
1723 {
1724     table_gasp_t*gasp = ttf->gasp;
1725     writeU16(table, 0);
1726     writeU16(table, gasp->num);
1727     int t;
1728     for(t=0;t<gasp->num;t++) {
1729         writeU16(table, gasp->records[t].size);
1730         writeU16(table, gasp->records[t].behaviour);
1731     }
1732 }
1733 void gasp_delete(ttf_t*ttf)
1734 {
1735     if(ttf->gasp) {
1736         if(ttf->gasp->records)
1737             free(ttf->gasp->records);
1738         free(ttf->gasp);
1739         ttf->gasp = 0;
1740     }
1741 }
1742
1743 table_code_t*prep_new(ttf_t*ttf)
1744 {
1745     table_code_t*prep = ttf->prep = rfx_calloc(sizeof(table_code_t));
1746     ttf_table_t*t = ttf_table_new(0);
1747     writeU8(t,0xb8);writeU16(t,0x1ff); // pushword(0x1ff)
1748     writeU8(t,0x85); //scanctrl (always do dropout, for all sizes)
1749     writeU8(t,0xb0);writeU8(t,1); // pushbyte(1)
1750     writeU8(t,0x8d); //scantype (simple dropout control w/o stubs)
1751     writeU8(t,0xb0);writeU8(t,5); // pushbyte(5)
1752     writeU8(t,0x8d); //scantype (for windows) smart dropout control w/o stubs
1753     prep->code = t->data;
1754     prep->size = t->len;
1755     free(t);
1756     return prep;
1757
1758 }
1759 void fpgm_parse(memreader_t*r, ttf_t*ttf)
1760 {
1761     table_code_t*fpgm = ttf->fpgm  = rfx_calloc(sizeof(table_code_t));
1762     if(!r->size) return;
1763     fpgm->size = r->size;
1764     fpgm->code = malloc(r->size);
1765     readBlock(r, fpgm->code, r->size);
1766 }
1767 void fpgm_write(ttf_t*ttf, ttf_table_t*table)
1768 {
1769     table_code_t*code = ttf->fpgm;
1770     writeBlock(table, code->code, code->size);
1771 }
1772 void fpgm_delete(ttf_t*ttf)
1773 {
1774     if(ttf->fpgm) {
1775         if(ttf->fpgm->code)
1776             free(ttf->fpgm->code);
1777         free(ttf->fpgm);
1778         ttf->fpgm = 0;
1779     }
1780 }
1781
1782 void prep_parse(memreader_t*r, ttf_t*ttf)
1783 {
1784     table_code_t*prep = ttf->prep  = rfx_calloc(sizeof(table_code_t));
1785     if(!r->size) return;
1786     prep->size = r->size;
1787     prep->code = malloc(r->size);
1788     readBlock(r, prep->code, r->size);
1789 }
1790 void prep_write(ttf_t*ttf, ttf_table_t*table)
1791 {
1792     table_code_t*code = ttf->prep;
1793     writeBlock(table, code->code, code->size);
1794 }
1795 void prep_delete(ttf_t*ttf)
1796 {
1797     if(ttf->prep) {
1798         if(ttf->prep->code)
1799             free(ttf->prep->code);
1800         free(ttf->prep);
1801         ttf->prep = 0;
1802     }
1803 }
1804
1805 static int ttf_parse_tables(ttf_t*ttf)
1806 {
1807     ttf_table_t*table;
1808
1809     table = ttf_find_table(ttf, TAG_HEAD);
1810     if(!table) {
1811         msg("<error> Font has no head table");
1812         return 0;
1813     }
1814     INIT_READ(m, table->data, table->len, 0);
1815     int loc_index = head_parse(ttf, &m);
1816     ttf_table_delete(ttf, table);
1817
1818     table = ttf_find_table(ttf, TAG_MAXP);
1819     if(!table) {
1820         msg("<error> Font has no maxp table");
1821         return 0;
1822     }
1823     INIT_READ(m2, table->data, table->len, 0);
1824     ttf->maxp = maxp_parse(ttf, &m2);
1825     ttf_table_delete(ttf, table);
1826
1827     if(!ttf->num_glyphs) {
1828         msg("<error> Invalid number of characters");
1829         return 0;
1830     }
1831     ttf->glyphs = rfx_calloc(sizeof(ttfglyph_t)*ttf->num_glyphs);
1832
1833     table = ttf_find_table(ttf, TAG_OS2);
1834     if(table) {
1835         INIT_READ(m, table->data, table->len, 0);
1836         ttf->os2 = os2_parse(&m);
1837         ttf_table_delete(ttf, table);
1838     }
1839
1840
1841     table = ttf_find_table(ttf, TAG_HHEA);
1842     if(table) {
1843         INIT_READ(m, table->data, table->len, 0);
1844         int num_advances = hea_parse(&m, ttf);
1845         ttf_table_delete(ttf, table);
1846
1847         table = ttf_find_table(ttf, TAG_HMTX);
1848         if(table) {
1849             INIT_READ(m, table->data, table->len, 0);
1850             mtx_parse(&m, ttf, num_advances);
1851             ttf_table_delete(ttf, table);
1852         }
1853     } else {
1854         table = ttf_find_table(ttf, TAG_VHEA);
1855         if(table) {
1856             ttf->is_vertical=1;
1857             INIT_READ(m, table->data, table->len, 0);
1858             int num_advances = hea_parse(&m, ttf);
1859             ttf_table_delete(ttf, table);
1860
1861             table = ttf_find_table(ttf, TAG_VMTX);
1862             if(table) {
1863                 INIT_READ(m, table->data, table->len, 0);
1864                 mtx_parse(&m, ttf, num_advances);
1865                 ttf_table_delete(ttf, table);
1866             }
1867         } else {
1868             msg("<error> Font contains neither HHEA nor VHEA");
1869         }
1870     }
1871     table = ttf_find_table(ttf, TAG_LOCA);
1872     if(table) {
1873         INIT_READ(m, table->data, table->len, 0);
1874         U32*loca = loca_parse(&m, ttf, loc_index);
1875         ttf_table_delete(ttf, table);
1876         table = ttf_find_table(ttf, TAG_GLYF);
1877         if(table) {
1878             INIT_READ(m, table->data, table->len, 0);
1879             glyf_parse(&m, ttf, loca);
1880             ttf_table_delete(ttf, table);
1881         }
1882         free(loca);
1883     }
1884
1885     table = ttf_find_table(ttf, TAG_CMAP);
1886     if(table) {
1887         INIT_READ(m, table->data, table->len, 0);
1888         cmap_parse(&m, ttf);
1889         ttf_table_delete(ttf, table);
1890     }
1891
1892     table = ttf_find_table(ttf, TAG_POST);
1893     if(table) {
1894         INIT_READ(m, table->data, table->len, 0);
1895         post_parse(&m, ttf);
1896         ttf_table_delete(ttf, table);
1897     }
1898
1899     table = ttf_find_table(ttf, TAG_NAME);
1900     if(table) {
1901         INIT_READ(m, table->data, table->len, 0);
1902         name_parse(&m, ttf);
1903         ttf_table_delete(ttf, table);
1904     }
1905
1906     table = ttf_find_table(ttf, TAG_CVT);
1907     if(table) {
1908         INIT_READ(m, table->data, table->len, 0);
1909         cvt_parse(&m, ttf);
1910         ttf_table_delete(ttf, table);
1911     }
1912     
1913     table = ttf_find_table(ttf, TAG_GASP);
1914     if(table) {
1915         INIT_READ(m, table->data, table->len, 0);
1916         gasp_parse(&m, ttf);
1917         ttf_table_delete(ttf, table);
1918     }
1919     
1920     table = ttf_find_table(ttf, TAG_PREP);
1921     if(table) {
1922         INIT_READ(m, table->data, table->len, 0);
1923         prep_parse(&m, ttf);
1924         ttf_table_delete(ttf, table);
1925     }
1926     
1927     table = ttf_find_table(ttf, TAG_FPGM);
1928     if(table) {
1929         INIT_READ(m, table->data, table->len, 0);
1930         fpgm_parse(&m, ttf);
1931         ttf_table_delete(ttf, table);
1932     }
1933
1934     return 1;
1935 }
1936 static void ttf_collapse_tables(ttf_t*ttf)
1937 {
1938     ttf_table_t*table;
1939
1940     ttf_table_t*head = ttf_find_table(ttf, TAG_HEAD);
1941     if(head)
1942         return; //already collapsed
1943
1944     if(ttf->maxp) {
1945         table = ttf_addtable(ttf, TAG_MAXP);
1946         maxp_write(ttf, table);
1947         maxp_delete(ttf);
1948     }
1949
1950     if(ttf->os2) {
1951         table = ttf_addtable(ttf, TAG_OS2);
1952         os2_write(ttf, table);
1953         os2_delete(ttf);
1954     }
1955
1956     if(ttf->hea) {
1957         if(!ttf->is_vertical) {
1958             table = ttf_addtable(ttf, TAG_HMTX);
1959             int num_advances = mtx_write(ttf, table);
1960             table = ttf_addtable(ttf, TAG_HHEA);
1961             hea_write(ttf, table, num_advances);
1962             hea_delete(ttf);
1963         } else {
1964             table = ttf_addtable(ttf, TAG_VMTX);
1965             int num_advances = mtx_write(ttf, table);
1966             table = ttf_addtable(ttf, TAG_VHEA);
1967             hea_write(ttf, table, num_advances);
1968             hea_delete(ttf);
1969         }
1970     }
1971
1972     int loca_size=0;
1973     if(ttf->num_glyphs) {
1974         if(ttf->unicode) {
1975             table = ttf_addtable(ttf, TAG_CMAP);
1976             cmap_write(ttf, table);
1977             cmap_delete(ttf);
1978         }
1979
1980         if(ttf->glyphs) {
1981             table = ttf_addtable(ttf, TAG_GLYF);
1982             U32*locations = glyf_write(ttf, table);
1983             table = ttf_addtable(ttf, TAG_LOCA);
1984             loca_size = loca_write(ttf, table, locations);
1985             free(locations);
1986             glyf_delete(ttf);
1987         }
1988     }
1989
1990     if(ttf->full_name || ttf->family_name || ttf->subfamily_name || ttf->font_uid || ttf->postscript_name) {
1991         table = ttf_addtable(ttf, TAG_NAME);
1992         name_write(ttf, table);
1993         name_delete(ttf);
1994     }
1995     if(ttf->post) {
1996         table = ttf_addtable(ttf, TAG_POST);
1997         post_write(ttf, table);
1998         post_delete(ttf);
1999     }
2000     if(ttf->cvt) {
2001         table = ttf_addtable(ttf, TAG_CVT);
2002         cvt_write(ttf, table);
2003         cvt_delete(ttf);
2004     }
2005     if(ttf->gasp) {
2006         table = ttf_addtable(ttf, TAG_GASP);
2007         gasp_write(ttf, table);
2008         gasp_delete(ttf);
2009     }
2010     if(ttf->fpgm) {
2011         table = ttf_addtable(ttf, TAG_FPGM);
2012         fpgm_write(ttf, table);
2013         fpgm_delete(ttf);
2014     }
2015     if(ttf->prep) {
2016         table = ttf_addtable(ttf, TAG_PREP);
2017         prep_write(ttf, table);
2018         prep_delete(ttf);
2019     }
2020
2021     table = ttf_addtable(ttf, TAG_HEAD);
2022     head_write(ttf, table, loca_size);
2023     head_delete(ttf);
2024 }
2025
2026 ttf_t*ttf_new()
2027 {
2028     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
2029     ttf->version = VERSION_1_0;
2030     return ttf;
2031 }
2032 ttf_t* ttf_load(void*data, int length)
2033 {
2034     INIT_READ(r,data,length, 0);
2035
2036     if(length<12) {
2037         msg("<error> Truncated Truetype file (%d bytes)", length);
2038         return 0;
2039     }
2040
2041     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
2042     ttf->version = readU32(&r);
2043     if(ttf->version == SWAP32(length)) {
2044         U32 fontDataSize = readU32(&r);
2045         U32 version = readU32(&r);
2046         U32 flags  = readU32(&r);
2047         U8 panose[10];
2048         readBlock(&r, panose, 10);
2049         readU8(&r); //charset
2050         readU8(&r); //italoc
2051         readU32(&r); //weight
2052         readU16(&r); //fstype
2053         U16 magic = readU16(&r); //magicNumber
2054         /* we're being paranoid: it's entirely possible for the font
2055            size to be exactly 0x10000. Only treat this font as eot if
2056            it has the right magic number */
2057         if(magic == 0x4c50) {
2058             readU32(&r); //unicoderange[0]
2059             readU32(&r); //unicoderange[1]
2060             readU32(&r); //unicoderange[2]
2061             readU32(&r); //unicoderange[3]
2062             readU32(&r); //codepagerange[0]
2063             readU32(&r); //codepagerange[1]
2064             readU32(&r); //checksumadjustment
2065             readU32(&r); //reserved[0]
2066             readU32(&r); //reserved[1]
2067             readU32(&r); //reserved[2]
2068             readU32(&r); //reserved[3]
2069             readU16(&r); //padding
2070
2071             int nr=0;
2072             for(nr=0;nr<4;nr++) {
2073                 int t, len;
2074                 /* All of ttf is big-endian. All of ttf? No. One small eot table
2075                    of indomitable little-endian... */
2076                 len = readU8(&r);
2077                 len |= readU8(&r)<<8;
2078                 len /= 2;
2079                 for(t=0;t<len;t++) {
2080                     U8 c = readU16(&r)>>8;
2081                 }
2082                 readU16(&r); // zero terminator
2083             }
2084             readU16(&r); // more padding
2085
2086             /* adjust the offset to the start of the actual truetype
2087                data- the positions in the table header will be relative
2088                to the ttf data after the header, not to the file */
2089             r.mem += r.pos;
2090             r.size -= r.pos;
2091             r.pos = 0;
2092             ttf->version = readU32(&r);
2093         } else {
2094             reader_reset(&r);
2095             ttf->version = readU32(&r);
2096         }
2097     }
2098
2099     if(ttf->version == TTCFTAG) {
2100         /* a ttc collection is a number of truetype fonts
2101            packaged together */
2102         if(length<16) {
2103             msg("<error> Truncated TTC file (%d bytes)", length);
2104             return 0;
2105         }
2106         U32 ttcf_version = readU32(&r); // 0x00000100: v1.0, 0x00000200: v2.0, includes DSIG table
2107         U32 num_fonts = readU32(&r); // number of fonts
2108         U32 font1_position = readU32(&r);
2109         if(font1_position+12 > length) {\
2110             msg("<error> Truncated TTC file (%d bytes, first font at %d)", length, font1_position);
2111             return 0;
2112         }
2113         r.pos = font1_position;
2114         ttf->version = readU32(&r);
2115     }
2116
2117     int num_tables = readU16(&r);
2118
2119     readU16(&r); //search range
2120     readU16(&r); //entry selector
2121     readU16(&r); //range shift
2122
2123     if(num_tables*16 > length) {
2124         msg("<error> Truncated TTF file (table entries: %d)", num_tables);
2125         if(ttf->version != OPENTYPE &&
2126            ttf->version != TRUETYPE_MACOS &&
2127            ttf->version != VERSION_1_0) {
2128             // bad table length, weird version. This is probably not a ttf file.
2129             return 0;
2130         }
2131     }
2132
2133     U32*table_data = malloc(16*num_tables);
2134     int t;
2135     for(t=0;t<num_tables*4;t++) {
2136         table_data[t] = readU32(&r);
2137     }
2138     for(t=0;t<num_tables;t++) {
2139         U32 tag = table_data[t*4];
2140         U32 checksum = table_data[t*4+1];
2141         U32 pos = table_data[t*4+2];
2142         U32 len = table_data[t*4+3];
2143         
2144         if(pos+len > length) {
2145             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);
2146         } else {
2147             U8*mem = malloc(len);
2148             r.pos = pos;
2149             readBlock(&r, mem, len);
2150
2151             ttf_table_t*table = ttf_addtable(ttf, tag);
2152             table->data = mem;
2153             table->len = table->memsize = len;
2154 #if 0
2155             U32 checksum2 = ttf_table_checksum(table);
2156             if(checksum2!=checksum) {
2157                 msg("<warning> Checksum mismatch in tag %02x%02x%02x%02x %c%c%c%c (%d bytes) %08x!=%08x",
2158                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2159                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2160                         len, checksum2, checksum);
2161             }
2162 #endif
2163         }
2164     }
2165     free(table_data);
2166
2167     if(!ttf_parse_tables(ttf))
2168         return 0;
2169
2170     return ttf;
2171 }
2172 void ttf_create_truetype_tables(ttf_t*ttf)
2173 {
2174     if(!ttf->head)
2175         ttf->head = head_new(ttf);
2176     if(!ttf->maxp)
2177         ttf->maxp = maxp_new(ttf);
2178     if(!ttf->hea)
2179         ttf->hea = hea_new(ttf);
2180     if(!ttf->os2)
2181         ttf->os2 = os2_new(ttf);
2182     if(!ttf->post)
2183         ttf->post = post_new(ttf);
2184     if(!ttf->gasp)
2185         ttf->gasp = gasp_new(ttf);
2186     if(!ttf->prep)
2187         ttf->prep = prep_new(ttf);
2188 }
2189
2190 ttf_table_t* ttf_write(ttf_t*ttf, U32*checksum_adjust)
2191 {
2192     ttf_collapse_tables(ttf);
2193
2194     ttf_table_t*file = ttf_table_new(0);
2195     writeU32(file, VERSION_1_0);
2196
2197     /* write number of tables */
2198     int num_tables=0;
2199     ttf_table_t*t = ttf->tables;
2200     while(t) {
2201         num_tables++;
2202         t = t->next;
2203     }
2204     writeU16(file, num_tables);
2205
2206     /* write search range */
2207     int tmp = num_tables;
2208     int search_range = 0;
2209     while(tmp) {
2210         search_range = tmp;
2211         tmp = tmp&(tmp-1);
2212     }
2213     tmp = search_range;
2214     search_range*=16;
2215     writeU16(file, search_range);
2216
2217     /* write entry selector */
2218     int entry_selector = 0;
2219     while(tmp>1) {
2220         tmp>>=1;
2221         entry_selector++;
2222     }
2223     writeU16(file, entry_selector);
2224
2225     /* write range shift */
2226     int range_shift = num_tables*16 - search_range;
2227     writeU16(file, range_shift);
2228
2229     /* write table dictionary */
2230     int table_dictionary_pos = file->len;
2231     int data_pos = file->len + num_tables*16;
2232     for(t=ttf->tables;t;t=t->next) {
2233         writeU32(file, t->id);
2234         writeU32(file, ttf_table_checksum(t));
2235         writeU32(file, data_pos);
2236         writeU32(file, t->len);
2237         data_pos += t->len;
2238         data_pos += (-t->len)&3; //pad
2239     }
2240
2241     /* write tables */
2242     int head_pos = 0;
2243     U8 zero[4]={0,0,0,0};
2244     for(t=ttf->tables;t;t=t->next) {
2245         if(t->id == TAG_HEAD)
2246             head_pos = file->len;
2247         writeBlock(file, t->data, t->len);
2248         writeBlock(file, zero, (-t->len)&3); //pad
2249     }
2250     U32 checksum = 0xb1b0afba - ttf_table_checksum(file);
2251     if(checksum_adjust)
2252         *checksum_adjust = checksum;
2253     U8*checksum2 = file->data + head_pos + 8;
2254     checksum2[0] = checksum>>24;
2255     checksum2[1] = checksum>>16;
2256     checksum2[2] = checksum>>8;
2257     checksum2[3] = checksum>>0;
2258     return file;
2259 }
2260
2261 ttf_table_t* ttf_eot_head(ttf_t*ttf)
2262 {
2263     ttf_table_t*file = ttf_table_new(0);
2264     writeU32(file, 0); //file size (filled in later)
2265     writeU32(file, 0); //fontdatasize (filled in later)
2266     writeU32(file, 0x01000200);
2267     writeU32(file, 0); //flags
2268     writeU8(file, ttf->os2->panose_FamilyType);
2269     writeU8(file, ttf->os2->panose_SerifStyle);
2270     writeU8(file, ttf->os2->panose_Weight);
2271     writeU8(file, ttf->os2->panose_Proportion);
2272     writeU8(file, ttf->os2->panose_Contrast);
2273     writeU8(file, ttf->os2->panose_StrokeVariation);
2274     writeU8(file, ttf->os2->panose_ArmStyle);
2275     writeU8(file, ttf->os2->panose_Letterform);
2276     writeU8(file, ttf->os2->panose_Midline);
2277     writeU8(file, ttf->os2->panose_XHeight);
2278     writeU8(file, 1); //charset (default)
2279     writeU8(file, ttf->os2->fsSelection&1); //italic
2280     writeU32_LE(file, ttf->os2->usWeightClass);
2281     writeU16(file, 0); //fstype
2282     writeU16(file, 0x4c50); //magic
2283     writeU32_LE(file, ttf->os2->ulCharRange[0]);
2284     writeU32_LE(file, ttf->os2->ulCharRange[1]);
2285     writeU32_LE(file, ttf->os2->ulCharRange[2]);
2286     writeU32_LE(file, ttf->os2->ulCharRange[3]);
2287     writeU32_LE(file, ttf->os2->ulCodePageRange1);
2288     writeU32_LE(file, ttf->os2->ulCodePageRange2);
2289     writeU32(file, 0); //checksum adjust (filled in later)
2290     writeU32(file, 0); //reserved[0]
2291     writeU32(file, 0); //reserved[1]
2292     writeU32(file, 0); //reserved[2]
2293     writeU32(file, 0); //reserved[3]
2294     writeU16(file, 0); //padding(1)
2295
2296     int i,t,len;
2297
2298     char* strings[] = {ttf->family_name, ttf->subfamily_name, ttf->version_string, ttf->full_name};
2299     int nr = sizeof(strings)/sizeof(strings[0]);
2300
2301     for(i=0;i<nr;i++) {
2302         char *string = strings[i];
2303
2304         //family name
2305         len = strlen(string);
2306         writeU16_LE(file, len*2);
2307         for(t=0;t<len;t++) {
2308             writeU8(file, 0);
2309             writeU8(file, string[t]);
2310         }
2311         writeU16(file, 0); //zero byte pad
2312     }
2313
2314     writeU16(file, 0); //zero byte pad
2315
2316     writeU16(file, 0); //padding(2)
2317     return file;
2318 }
2319
2320 void ttf_save_eot(ttf_t*ttf, const char*filename)
2321 {
2322     ttf_table_t* eot = ttf_eot_head(ttf);
2323     U32 checksum_adjust = 0;
2324     ttf_table_t* t = ttf_write(ttf, &checksum_adjust);
2325
2326     U8*len_data = eot->data;
2327     U32 full_len = eot->len + t->len;
2328     len_data[0] = full_len>>0;
2329     len_data[1] = full_len>>8;
2330     len_data[2] = full_len>>16;
2331     len_data[3] = full_len>>24;
2332
2333     U8*len_data2 = eot->data+4;
2334     len_data2[0] = t->len>>0;
2335     len_data2[1] = t->len>>8;
2336     len_data2[2] = t->len>>16;
2337     len_data2[3] = t->len>>24;
2338
2339     U8*checksum_data = eot->data + 60;
2340     checksum_data[0] = checksum_adjust>>0;
2341     checksum_data[1] = checksum_adjust>>8;
2342     checksum_data[2] = checksum_adjust>>16;
2343     checksum_data[3] = checksum_adjust>>24;
2344
2345     FILE*fi = fopen(filename, "wb");
2346     if(!fi) {
2347         perror(filename);
2348         return;
2349     }
2350
2351     fwrite(eot->data, eot->len, 1, fi);
2352     fwrite(t->data, t->len, 1, fi);
2353     fclose(fi);
2354     ttf_table_delete(0, t);
2355     ttf_table_delete(0, eot);
2356 }
2357
2358 void ttf_save(ttf_t*ttf, const char*filename)
2359 {
2360     ttf_table_t* t = ttf_write(ttf, 0);
2361     FILE*fi = fopen(filename, "wb");
2362     if(!fi) {
2363         perror(filename);
2364         return;
2365     }
2366     fwrite(t->data, t->len, 1, fi);
2367     fclose(fi);
2368     ttf_table_delete(0, t);
2369 }
2370
2371 void ttf_dump(ttf_t*ttf)
2372 {
2373     msg("<notice> Truetype file version %08x%s", ttf->version, ttf->version == OPENTYPE?" (opentype)":"");
2374     ttf_table_t*table = ttf->tables;
2375     while(table) {
2376         U32 tag = table->id;
2377         msg("<notice> Tag %02x%02x%02x%02x [%c%c%c%c] (length: %d)",
2378                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2379                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, table->len);
2380         table = table->next;
2381     }
2382     //ttf_table_dump(ttf_find_table(ttf, TAG_MAXP));
2383
2384     head_dump(ttf);
2385     hea_dump(ttf);
2386     os2_dump(ttf);
2387     maxp_dump(ttf);
2388     glyf_dump(ttf);
2389 }
2390 void ttf_destroy_tables(ttf_t*ttf)
2391 {
2392     ttf_table_t*table = ttf->tables;
2393     while(table) {
2394         ttf_table_t*next = table->next;
2395         free(table->data);
2396         free(table);
2397         table = next;
2398     }
2399     ttf->tables = 0;
2400 }
2401 void ttf_reduce(ttf_t*ttf)
2402 {
2403     ttf_destroy_tables(ttf);
2404 }
2405 void ttf_destroy(ttf_t*ttf)
2406 {
2407     ttf_destroy_tables(ttf);
2408     maxp_delete(ttf);
2409     os2_delete(ttf);
2410     head_delete(ttf);
2411     hea_delete(ttf);
2412     glyf_delete(ttf);
2413     post_delete(ttf);
2414     cvt_delete(ttf);
2415     name_delete(ttf);
2416     free(ttf);
2417 }
2418
2419 #ifdef MAIN
2420 int main(int argn, const char*argv[])
2421 {
2422     setConsoleLogging(7);
2423     const char*filename = "comic.ttf";
2424     if(argn>1)
2425         filename = argv[1];
2426     //msg("<notice> Loading %s", filename);
2427     memfile_t*m = memfile_open(filename);
2428     ttf_t*ttf = ttf_load(m->data, m->len);
2429
2430     if(!ttf) {
2431         msg("<error> Couldn't load %s", filename);
2432         return 1;
2433     }
2434     ttf_reduce(ttf);
2435
2436     ttf_create_truetype_tables(ttf);
2437
2438     if(!ttf) return 1;
2439     memfile_close(m);
2440     //ttf_dump(ttf);
2441     //printf("os2 version: %04x (%d), maxp size: %d\n",
2442 //          ttf->os2->version, ttf->os2->size, ttf->maxp->size);
2443     ttf_save_eot(ttf, "testfont.eot");
2444     ttf_save(ttf, "testfont.ttf");
2445     ttf_destroy(ttf);
2446     return 0;
2447
2448 }
2449 #endif