3edcc217e3a96cb666efa18810f957645ac4e3e2
[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 table_code_t*prep_new(ttf_t*ttf)
1743 {
1744     table_code_t*prep = ttf->prep = rfx_calloc(sizeof(table_code_t));
1745     ttf_table_t*t = ttf_table_new(0);
1746     writeU8(t,0xb8);writeU16(t,0x1ff); // pushword(0x1ff)
1747     writeU8(t,0x85); //scanctrl (always do dropout, for all sizes)
1748     writeU8(t,0xb0);writeU8(t,1); // pushbyte(1)
1749     writeU8(t,0x8d); //scantype (simple dropout control w/o stubs)
1750     writeU8(t,0xb0);writeU8(t,5); // pushbyte(5)
1751     writeU8(t,0x8d); //scantype (for windows) smart dropout control w/o stubs
1752     prep->code = t->data;
1753     prep->size = t->len;
1754     free(t);
1755     return prep;
1756
1757 }
1758 void fpgm_parse(memreader_t*r, ttf_t*ttf)
1759 {
1760     table_code_t*fpgm = ttf->fpgm  = rfx_calloc(sizeof(table_code_t));
1761     if(!r->size) return;
1762     fpgm->size = r->size;
1763     fpgm->code = malloc(r->size);
1764     readBlock(r, fpgm->code, r->size);
1765 }
1766 void fpgm_write(ttf_t*ttf, ttf_table_t*table)
1767 {
1768     table_code_t*code = ttf->fpgm;
1769     writeBlock(table, code->code, code->size);
1770 }
1771 void fpgm_delete(ttf_t*ttf)
1772 {
1773     if(ttf->fpgm) {
1774         if(ttf->fpgm->code)
1775             free(ttf->fpgm->code);
1776         free(ttf->fpgm);
1777         ttf->fpgm = 0;
1778     }
1779 }
1780
1781 void prep_parse(memreader_t*r, ttf_t*ttf)
1782 {
1783     table_code_t*prep = ttf->prep  = rfx_calloc(sizeof(table_code_t));
1784     if(!r->size) return;
1785     prep->size = r->size;
1786     prep->code = malloc(r->size);
1787     readBlock(r, prep->code, r->size);
1788 }
1789 void prep_write(ttf_t*ttf, ttf_table_t*table)
1790 {
1791     table_code_t*code = ttf->prep;
1792     writeBlock(table, code->code, code->size);
1793 }
1794 void prep_delete(ttf_t*ttf)
1795 {
1796     if(ttf->prep) {
1797         if(ttf->prep->code)
1798             free(ttf->prep->code);
1799         free(ttf->prep);
1800         ttf->prep = 0;
1801     }
1802 }
1803
1804 static int ttf_parse_tables(ttf_t*ttf)
1805 {
1806     ttf_table_t*table;
1807
1808     table = ttf_find_table(ttf, TAG_HEAD);
1809     if(!table) {
1810         msg("<error> Font has no head table");
1811         return 0;
1812     }
1813     INIT_READ(m, table->data, table->len, 0);
1814     int loc_index = head_parse(ttf, &m);
1815     ttf_table_delete(ttf, table);
1816
1817     table = ttf_find_table(ttf, TAG_MAXP);
1818     if(!table) {
1819         msg("<error> Font has no maxp table");
1820         return 0;
1821     }
1822     INIT_READ(m2, table->data, table->len, 0);
1823     ttf->maxp = maxp_parse(ttf, &m2);
1824     ttf_table_delete(ttf, table);
1825
1826     if(!ttf->num_glyphs) {
1827         msg("<error> Invalid number of characters");
1828         return 0;
1829     }
1830     ttf->glyphs = rfx_calloc(sizeof(ttfglyph_t)*ttf->num_glyphs);
1831
1832     table = ttf_find_table(ttf, TAG_OS2);
1833     if(table) {
1834         INIT_READ(m, table->data, table->len, 0);
1835         ttf->os2 = os2_parse(&m);
1836         ttf_table_delete(ttf, table);
1837     }
1838
1839
1840     table = ttf_find_table(ttf, TAG_HHEA);
1841     if(table) {
1842         INIT_READ(m, table->data, table->len, 0);
1843         int num_advances = hea_parse(&m, ttf);
1844         ttf_table_delete(ttf, table);
1845
1846         table = ttf_find_table(ttf, TAG_HMTX);
1847         if(table) {
1848             INIT_READ(m, table->data, table->len, 0);
1849             mtx_parse(&m, ttf, num_advances);
1850             ttf_table_delete(ttf, table);
1851         }
1852     } else {
1853         table = ttf_find_table(ttf, TAG_VHEA);
1854         if(table) {
1855             ttf->is_vertical=1;
1856             INIT_READ(m, table->data, table->len, 0);
1857             int num_advances = hea_parse(&m, ttf);
1858             ttf_table_delete(ttf, table);
1859
1860             table = ttf_find_table(ttf, TAG_VMTX);
1861             if(table) {
1862                 INIT_READ(m, table->data, table->len, 0);
1863                 mtx_parse(&m, ttf, num_advances);
1864                 ttf_table_delete(ttf, table);
1865             }
1866         } else {
1867             msg("<error> Font contains neither HHEA nor VHEA");
1868         }
1869     }
1870     table = ttf_find_table(ttf, TAG_LOCA);
1871     if(table) {
1872         INIT_READ(m, table->data, table->len, 0);
1873         U32*loca = loca_parse(&m, ttf, loc_index);
1874         ttf_table_delete(ttf, table);
1875         table = ttf_find_table(ttf, TAG_GLYF);
1876         if(table) {
1877             INIT_READ(m, table->data, table->len, 0);
1878             glyf_parse(&m, ttf, loca);
1879             ttf_table_delete(ttf, table);
1880         }
1881         free(loca);
1882     }
1883
1884     table = ttf_find_table(ttf, TAG_CMAP);
1885     if(table) {
1886         INIT_READ(m, table->data, table->len, 0);
1887         cmap_parse(&m, ttf);
1888         ttf_table_delete(ttf, table);
1889     }
1890
1891     table = ttf_find_table(ttf, TAG_POST);
1892     if(table) {
1893         INIT_READ(m, table->data, table->len, 0);
1894         post_parse(&m, ttf);
1895         ttf_table_delete(ttf, table);
1896     }
1897
1898     table = ttf_find_table(ttf, TAG_NAME);
1899     if(table) {
1900         INIT_READ(m, table->data, table->len, 0);
1901         name_parse(&m, ttf);
1902         ttf_table_delete(ttf, table);
1903     }
1904
1905     table = ttf_find_table(ttf, TAG_CVT);
1906     if(table) {
1907         INIT_READ(m, table->data, table->len, 0);
1908         cvt_parse(&m, ttf);
1909         ttf_table_delete(ttf, table);
1910     }
1911     
1912     table = ttf_find_table(ttf, TAG_GASP);
1913     if(table) {
1914         INIT_READ(m, table->data, table->len, 0);
1915         gasp_parse(&m, ttf);
1916         ttf_table_delete(ttf, table);
1917     }
1918     
1919     table = ttf_find_table(ttf, TAG_PREP);
1920     if(table) {
1921         INIT_READ(m, table->data, table->len, 0);
1922         prep_parse(&m, ttf);
1923         ttf_table_delete(ttf, table);
1924     }
1925     
1926     table = ttf_find_table(ttf, TAG_FPGM);
1927     if(table) {
1928         INIT_READ(m, table->data, table->len, 0);
1929         fpgm_parse(&m, ttf);
1930         ttf_table_delete(ttf, table);
1931     }
1932
1933     return 1;
1934 }
1935 static void ttf_collapse_tables(ttf_t*ttf)
1936 {
1937     ttf_table_t*table;
1938
1939     ttf_table_t*head = ttf_find_table(ttf, TAG_HEAD);
1940     if(head)
1941         return; //already collapsed
1942
1943     if(ttf->maxp) {
1944         table = ttf_addtable(ttf, TAG_MAXP);
1945         maxp_write(ttf, table);
1946         maxp_delete(ttf);
1947     }
1948
1949     if(ttf->os2) {
1950         table = ttf_addtable(ttf, TAG_OS2);
1951         os2_write(ttf, table);
1952         os2_delete(ttf);
1953     }
1954
1955     if(ttf->hea) {
1956         if(!ttf->is_vertical) {
1957             table = ttf_addtable(ttf, TAG_HMTX);
1958             int num_advances = mtx_write(ttf, table);
1959             table = ttf_addtable(ttf, TAG_HHEA);
1960             hea_write(ttf, table, num_advances);
1961             hea_delete(ttf);
1962         } else {
1963             table = ttf_addtable(ttf, TAG_VMTX);
1964             int num_advances = mtx_write(ttf, table);
1965             table = ttf_addtable(ttf, TAG_VHEA);
1966             hea_write(ttf, table, num_advances);
1967             hea_delete(ttf);
1968         }
1969     }
1970
1971     int loca_size=0;
1972     if(ttf->num_glyphs) {
1973         if(ttf->unicode) {
1974             table = ttf_addtable(ttf, TAG_CMAP);
1975             cmap_write(ttf, table);
1976             cmap_delete(ttf);
1977         }
1978
1979         if(ttf->glyphs) {
1980             table = ttf_addtable(ttf, TAG_GLYF);
1981             U32*locations = glyf_write(ttf, table);
1982             table = ttf_addtable(ttf, TAG_LOCA);
1983             loca_size = loca_write(ttf, table, locations);
1984             free(locations);
1985             glyf_delete(ttf);
1986         }
1987     }
1988
1989     if(ttf->full_name || ttf->family_name || ttf->subfamily_name || ttf->font_uid || ttf->postscript_name) {
1990         table = ttf_addtable(ttf, TAG_NAME);
1991         name_write(ttf, table);
1992         name_delete(ttf);
1993     }
1994     if(ttf->post) {
1995         table = ttf_addtable(ttf, TAG_POST);
1996         post_write(ttf, table);
1997         post_delete(ttf);
1998     }
1999     if(ttf->cvt) {
2000         table = ttf_addtable(ttf, TAG_CVT);
2001         cvt_write(ttf, table);
2002         cvt_delete(ttf);
2003     }
2004     if(ttf->gasp) {
2005         table = ttf_addtable(ttf, TAG_GASP);
2006         gasp_write(ttf, table);
2007         gasp_delete(ttf);
2008     }
2009     if(ttf->fpgm) {
2010         table = ttf_addtable(ttf, TAG_FPGM);
2011         fpgm_write(ttf, table);
2012         fpgm_delete(ttf);
2013     }
2014     if(ttf->prep) {
2015         table = ttf_addtable(ttf, TAG_PREP);
2016         prep_write(ttf, table);
2017         prep_delete(ttf);
2018     }
2019
2020     table = ttf_addtable(ttf, TAG_HEAD);
2021     head_write(ttf, table, loca_size);
2022     head_delete(ttf);
2023 }
2024
2025 ttf_t*ttf_new()
2026 {
2027     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
2028     ttf->version = VERSION_1_0;
2029     return ttf;
2030 }
2031 ttf_t* ttf_load(void*data, int length)
2032 {
2033     INIT_READ(r,data,length, 0);
2034
2035     if(length<12) {
2036         msg("<error> Truncated Truetype file (%d bytes)", length);
2037         return 0;
2038     }
2039
2040     ttf_t*ttf = rfx_calloc(sizeof(ttf_t));
2041     ttf->version = readU32(&r);
2042     if(ttf->version == SWAP32(length)) {
2043         U32 fontDataSize = readU32(&r);
2044         U32 version = readU32(&r);
2045         U32 flags  = readU32(&r);
2046         U8 panose[10];
2047         readBlock(&r, panose, 10);
2048         readU8(&r); //charset
2049         readU8(&r); //italoc
2050         readU32(&r); //weight
2051         readU16(&r); //fstype
2052         U16 magic = readU16(&r); //magicNumber
2053         /* we're being paranoid: it's entirely possible for the font
2054            size to be exactly 0x10000. Only treat this font as eot if
2055            it has the right magic number */
2056         if(magic == 0x4c50) {
2057             readU32(&r); //unicoderange[0]
2058             readU32(&r); //unicoderange[1]
2059             readU32(&r); //unicoderange[2]
2060             readU32(&r); //unicoderange[3]
2061             readU32(&r); //codepagerange[0]
2062             readU32(&r); //codepagerange[1]
2063             readU32(&r); //checksumadjustment
2064             readU32(&r); //reserved[0]
2065             readU32(&r); //reserved[1]
2066             readU32(&r); //reserved[2]
2067             readU32(&r); //reserved[3]
2068             readU16(&r); //padding
2069
2070             int nr=0;
2071             for(nr=0;nr<4;nr++) {
2072                 int t, len;
2073                 /* All of ttf is big-endian. All of ttf? No. One small eot table
2074                    of indomitable little-endian... */
2075                 len = readU8(&r);
2076                 len |= readU8(&r)<<8;
2077                 len /= 2;
2078                 for(t=0;t<len;t++) {
2079                     U8 c = readU16(&r)>>8;
2080                 }
2081                 readU16(&r); // zero terminator
2082             }
2083             readU16(&r); // more padding
2084
2085             /* adjust the offset to the start of the actual truetype
2086                data- the positions in the table header will be relative
2087                to the ttf data after the header, not to the file */
2088             r.mem += r.pos;
2089             r.size -= r.pos;
2090             r.pos = 0;
2091             ttf->version = readU32(&r);
2092         } else {
2093             reader_reset(&r);
2094             ttf->version = readU32(&r);
2095         }
2096     }
2097
2098     if(ttf->version == TTCFTAG) {
2099         /* a ttc collection is a number of truetype fonts
2100            packaged together */
2101         if(length<16) {
2102             msg("<error> Truncated TTC file (%d bytes)", length);
2103             return 0;
2104         }
2105         U32 ttcf_version = readU32(&r); // 0x00000100: v1.0, 0x00000200: v2.0, includes DSIG table
2106         U32 num_fonts = readU32(&r); // number of fonts
2107         U32 font1_position = readU32(&r);
2108         if(font1_position+12 > length) {\
2109             msg("<error> Truncated TTC file (%d bytes, first font at %d)", length, font1_position);
2110             return 0;
2111         }
2112         r.pos = font1_position;
2113         ttf->version = readU32(&r);
2114     }
2115
2116     int num_tables = readU16(&r);
2117
2118     readU16(&r); //search range
2119     readU16(&r); //entry selector
2120     readU16(&r); //range shift
2121
2122     if(num_tables*16 > length) {
2123         msg("<error> Truncated TTF file (table entries: %d)", num_tables);
2124         if(ttf->version != OPENTYPE &&
2125            ttf->version != TRUETYPE_MACOS &&
2126            ttf->version != VERSION_1_0) {
2127             // bad table length, weird version. This is probably not a ttf file.
2128             return 0;
2129         }
2130     }
2131
2132     U32*table_data = malloc(16*num_tables);
2133     int t;
2134     for(t=0;t<num_tables*4;t++) {
2135         table_data[t] = readU32(&r);
2136     }
2137     for(t=0;t<num_tables;t++) {
2138         U32 tag = table_data[t*4];
2139         U32 checksum = table_data[t*4+1];
2140         U32 pos = table_data[t*4+2];
2141         U32 len = table_data[t*4+3];
2142         
2143         if(pos+len > length) {
2144             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);
2145         } else {
2146             U8*mem = malloc(len);
2147             r.pos = pos;
2148             readBlock(&r, mem, len);
2149
2150             ttf_table_t*table = ttf_addtable(ttf, tag);
2151             table->data = mem;
2152             table->len = table->memsize = len;
2153 #if 0
2154             U32 checksum2 = ttf_table_checksum(table);
2155             if(checksum2!=checksum) {
2156                 msg("<warning> Checksum mismatch in tag %02x%02x%02x%02x %c%c%c%c (%d bytes) %08x!=%08x",
2157                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2158                         (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2159                         len, checksum2, checksum);
2160             }
2161 #endif
2162         }
2163     }
2164     free(table_data);
2165
2166     if(!ttf_parse_tables(ttf))
2167         return 0;
2168
2169     return ttf;
2170 }
2171 void ttf_create_truetype_tables(ttf_t*ttf)
2172 {
2173     if(!ttf->head)
2174         ttf->head = head_new(ttf);
2175     if(!ttf->maxp)
2176         ttf->maxp = maxp_new(ttf);
2177     if(!ttf->hea)
2178         ttf->hea = hea_new(ttf);
2179     if(!ttf->os2)
2180         ttf->os2 = os2_new(ttf);
2181     if(!ttf->post)
2182         ttf->post = post_new(ttf);
2183     if(!ttf->gasp)
2184         ttf->gasp = gasp_new(ttf);
2185     if(!ttf->prep)
2186         ttf->prep = prep_new(ttf);
2187 }
2188
2189 ttf_table_t* ttf_write(ttf_t*ttf, U32*checksum_adjust)
2190 {
2191     ttf_collapse_tables(ttf);
2192
2193     ttf_table_t*file = ttf_table_new(0);
2194     writeU32(file, VERSION_1_0);
2195
2196     /* write number of tables */
2197     int num_tables=0;
2198     ttf_table_t*t = ttf->tables;
2199     while(t) {
2200         num_tables++;
2201         t = t->next;
2202     }
2203     writeU16(file, num_tables);
2204
2205     /* write search range */
2206     int tmp = num_tables;
2207     int search_range = 0;
2208     while(tmp) {
2209         search_range = tmp;
2210         tmp = tmp&(tmp-1);
2211     }
2212     tmp = search_range;
2213     search_range*=16;
2214     writeU16(file, search_range);
2215
2216     /* write entry selector */
2217     int entry_selector = 0;
2218     while(tmp>1) {
2219         tmp>>=1;
2220         entry_selector++;
2221     }
2222     writeU16(file, entry_selector);
2223
2224     /* write range shift */
2225     int range_shift = num_tables*16 - search_range;
2226     writeU16(file, range_shift);
2227
2228     /* write table dictionary */
2229     int table_dictionary_pos = file->len;
2230     int data_pos = file->len + num_tables*16;
2231     for(t=ttf->tables;t;t=t->next) {
2232         writeU32(file, t->id);
2233         writeU32(file, ttf_table_checksum(t));
2234         writeU32(file, data_pos);
2235         writeU32(file, t->len);
2236         data_pos += t->len;
2237         data_pos += (-t->len)&3; //pad
2238     }
2239
2240     /* write tables */
2241     int head_pos = 0;
2242     U8 zero[4]={0,0,0,0};
2243     for(t=ttf->tables;t;t=t->next) {
2244         if(t->id == TAG_HEAD)
2245             head_pos = file->len;
2246         writeBlock(file, t->data, t->len);
2247         writeBlock(file, zero, (-t->len)&3); //pad
2248     }
2249     U32 checksum = 0xb1b0afba - ttf_table_checksum(file);
2250     if(checksum_adjust)
2251         *checksum_adjust = checksum;
2252     U8*checksum2 = file->data + head_pos + 8;
2253     checksum2[0] = checksum>>24;
2254     checksum2[1] = checksum>>16;
2255     checksum2[2] = checksum>>8;
2256     checksum2[3] = checksum>>0;
2257     return file;
2258 }
2259
2260 ttf_table_t* ttf_eot_head(ttf_t*ttf)
2261 {
2262     ttf_table_t*file = ttf_table_new(0);
2263     writeU32(file, 0); //file size (filled in later)
2264     writeU32(file, 0); //fontdatasize (filled in later)
2265     writeU32(file, 0x01000200);
2266     writeU32(file, 0); //flags
2267     writeU8(file, ttf->os2->panose_FamilyType);
2268     writeU8(file, ttf->os2->panose_SerifStyle);
2269     writeU8(file, ttf->os2->panose_Weight);
2270     writeU8(file, ttf->os2->panose_Proportion);
2271     writeU8(file, ttf->os2->panose_Contrast);
2272     writeU8(file, ttf->os2->panose_StrokeVariation);
2273     writeU8(file, ttf->os2->panose_ArmStyle);
2274     writeU8(file, ttf->os2->panose_Letterform);
2275     writeU8(file, ttf->os2->panose_Midline);
2276     writeU8(file, ttf->os2->panose_XHeight);
2277     writeU8(file, 1); //charset (default)
2278     writeU8(file, ttf->os2->fsSelection&1); //italic
2279     writeU32_LE(file, ttf->os2->usWeightClass);
2280     writeU16(file, 0); //fstype
2281     writeU16(file, 0x4c50); //magic
2282     writeU32_LE(file, ttf->os2->ulCharRange[0]);
2283     writeU32_LE(file, ttf->os2->ulCharRange[1]);
2284     writeU32_LE(file, ttf->os2->ulCharRange[2]);
2285     writeU32_LE(file, ttf->os2->ulCharRange[3]);
2286     writeU32_LE(file, ttf->os2->ulCodePageRange1);
2287     writeU32_LE(file, ttf->os2->ulCodePageRange2);
2288     writeU32(file, 0); //checksum adjust (filled in later)
2289     writeU32(file, 0); //reserved[0]
2290     writeU32(file, 0); //reserved[1]
2291     writeU32(file, 0); //reserved[2]
2292     writeU32(file, 0); //reserved[3]
2293     writeU16(file, 0); //padding(1)
2294
2295     int i,t,len;
2296
2297     char* strings[] = {ttf->family_name, ttf->subfamily_name, ttf->version_string, ttf->full_name};
2298     int nr = sizeof(strings)/sizeof(strings[0]);
2299
2300     for(i=0;i<nr;i++) {
2301         char *string = strings[i];
2302
2303         //family name
2304         len = strlen(string);
2305         writeU16_LE(file, len*2);
2306         for(t=0;t<len;t++) {
2307             writeU8(file, 0);
2308             writeU8(file, string[t]);
2309         }
2310         writeU16(file, 0); //zero byte pad
2311     }
2312
2313     writeU16(file, 0); //zero byte pad
2314
2315     writeU16(file, 0); //padding(2)
2316     return file;
2317 }
2318
2319 void ttf_save_eot(ttf_t*ttf, const char*filename)
2320 {
2321     ttf_table_t* eot = ttf_eot_head(ttf);
2322     U32 checksum_adjust = 0;
2323     ttf_table_t* t = ttf_write(ttf, &checksum_adjust);
2324
2325     U8*len_data = eot->data;
2326     U32 full_len = eot->len + t->len;
2327     len_data[0] = full_len>>0;
2328     len_data[1] = full_len>>8;
2329     len_data[2] = full_len>>16;
2330     len_data[3] = full_len>>24;
2331
2332     U8*len_data2 = eot->data+4;
2333     len_data2[0] = t->len>>0;
2334     len_data2[1] = t->len>>8;
2335     len_data2[2] = t->len>>16;
2336     len_data2[3] = t->len>>24;
2337
2338     U8*checksum_data = eot->data + 60;
2339     checksum_data[0] = checksum_adjust>>0;
2340     checksum_data[1] = checksum_adjust>>8;
2341     checksum_data[2] = checksum_adjust>>16;
2342     checksum_data[3] = checksum_adjust>>24;
2343
2344     FILE*fi = fopen(filename, "wb");
2345     if(!fi) {
2346         perror(filename);
2347         return;
2348     }
2349
2350     fwrite(eot->data, eot->len, 1, fi);
2351     fwrite(t->data, t->len, 1, fi);
2352     fclose(fi);
2353     ttf_table_delete(0, t);
2354     ttf_table_delete(0, eot);
2355 }
2356
2357 void ttf_save(ttf_t*ttf, const char*filename)
2358 {
2359     ttf_table_t* t = ttf_write(ttf, 0);
2360     FILE*fi = fopen(filename, "wb");
2361     if(!fi) {
2362         perror(filename);
2363         return;
2364     }
2365     fwrite(t->data, t->len, 1, fi);
2366     fclose(fi);
2367     ttf_table_delete(0, t);
2368 }
2369
2370 void ttf_dump(ttf_t*ttf)
2371 {
2372     msg("<notice> Truetype file version %08x%s", ttf->version, ttf->version == OPENTYPE?" (opentype)":"");
2373     ttf_table_t*table = ttf->tables;
2374     while(table) {
2375         U32 tag = table->id;
2376         msg("<notice> Tag %02x%02x%02x%02x [%c%c%c%c] (length: %d)",
2377                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff,
2378                 (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, table->len);
2379         table = table->next;
2380     }
2381     //ttf_table_dump(ttf_find_table(ttf, TAG_MAXP));
2382
2383     head_dump(ttf);
2384     hea_dump(ttf);
2385     os2_dump(ttf);
2386     maxp_dump(ttf);
2387     glyf_dump(ttf);
2388 }
2389 void ttf_destroy_tables(ttf_t*ttf)
2390 {
2391     ttf_table_t*table = ttf->tables;
2392     while(table) {
2393         ttf_table_t*next = table->next;
2394         free(table->data);
2395         free(table);
2396         table = next;
2397     }
2398     ttf->tables = 0;
2399 }
2400 void ttf_reduce(ttf_t*ttf)
2401 {
2402     ttf_destroy_tables(ttf);
2403 }
2404 void ttf_destroy(ttf_t*ttf)
2405 {
2406     ttf_destroy_tables(ttf);
2407     maxp_delete(ttf);
2408     os2_delete(ttf);
2409     head_delete(ttf);
2410     hea_delete(ttf);
2411     glyf_delete(ttf);
2412     post_delete(ttf);
2413     cvt_delete(ttf);
2414     name_delete(ttf);
2415     free(ttf);
2416 }
2417
2418 #ifdef MAIN
2419 int main(int argn, const char*argv[])
2420 {
2421     setConsoleLogging(7);
2422     const char*filename = "comic.ttf";
2423     if(argn>1)
2424         filename = argv[1];
2425     //msg("<notice> Loading %s", filename);
2426     memfile_t*m = memfile_open(filename);
2427     ttf_t*ttf = ttf_load(m->data, m->len);
2428
2429     if(!ttf) {
2430         msg("<error> Couldn't load %s", filename);
2431         return 1;
2432     }
2433     ttf_reduce(ttf);
2434
2435     ttf_create_truetype_tables(ttf);
2436
2437     if(!ttf) return 1;
2438     memfile_close(m);
2439     //ttf_dump(ttf);
2440     //printf("os2 version: %04x (%d), maxp size: %d\n",
2441 //          ttf->os2->version, ttf->os2->size, ttf->maxp->size);
2442     ttf_save_eot(ttf, "testfont.eot");
2443     ttf_save(ttf, "testfont.ttf");
2444     ttf_destroy(ttf);
2445     return 0;
2446
2447 }
2448 #endif