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