]> git.donarmstrong.com Git - xournal.git/blob - src/ttsubset/sft.c
Print via gtk-print instead of libgnomeprint
[xournal.git] / src / ttsubset / sft.c
1 /*
2  * Copyright © 2002, 2003 Sun Microsystems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of Sun Microsystems, Inc. nor the names of 
17  *    contributors may be used to endorse or promote products derived from
18  *    this software without specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind.
21  *
22  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
23  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
24  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
25  * SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR
26  * LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE,
27  * MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES.
28  * IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE,
29  * PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
30  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE
31  * THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE
32  * SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33  *
34  */
35
36 /* $Id$ */
37 /* @(#)sft.c 1.17 03/01/08 SMI */
38
39 /*
40  * @file sft.c
41  * @brief Sun Font Tools
42  * @author Alexander Gelfenbain <adg@sun.com>
43  * @version 1.0
44  */
45
46 #include <assert.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <fcntl.h>
50 #include "sft.h"
51 #ifdef USE_GSUB
52 #include "gsub.h"
53 #endif
54 #if ! (defined(NO_TTCR) && defined(NO_TYPE42))
55 #include "ttcr.h"
56 #endif
57 #ifdef NO_LIST
58 #include "list.h"             /* list.h does not get included in the sft.h */
59 #endif
60 #ifndef NO_MAPPERS            /* include MapChar() and MapString() */
61 #include "xlat.h"
62 #endif
63 #if ! (defined(NO_TYPE3) && defined(NO_TYPE42))
64 #include "crc32.h"
65 #endif
66
67 #ifdef TEST7
68 #include <ctype.h>
69 #endif
70
71 /*- module identification */
72
73 const char *modname  = "SunTypeTools-TT";
74 const char *modver   = "1.0";
75 const char *modextra = "gelf";
76
77 /*- private functions, constants and data types */ /*FOLD00*/
78
79 enum PathSegmentType {
80     PS_NOOP      = 0,
81     PS_MOVETO    = 1,
82     PS_LINETO    = 2,
83     PS_CURVETO   = 3,
84     PS_CLOSEPATH = 4
85 };
86     
87 typedef struct {
88     int type;
89     int x1, y1;
90     int x2, y2;
91     int x3, y3;
92 } PSPathElement;
93
94
95 #define HFORMAT_LINELEN 64
96
97 typedef struct {
98     FILE *o;
99     char buffer[HFORMAT_LINELEN];
100     int bufpos;
101     int total;
102 } HexFmt;
103
104 typedef struct {
105     guint32 nGlyphs;           /* number of glyphs in the font + 1 */
106     guint32 *offs;             /* array of nGlyphs offsets */
107 } GlyphOffsets;
108
109 /* private tags */
110 static const guint32 TTFontClassTag = 0x74746663;  /* 'ttfc' */
111
112 static const guint32 T_true = 0x74727565;        /* 'true' */
113 static const guint32 T_ttcf = 0x74746366;        /* 'ttcf' */
114
115 /* standard TrueType table tags and their ordinal numbers */
116 static const guint32 T_maxp = 0x6D617870;    static const guint32 O_maxp = 0;     /* 'maxp' */
117 static const guint32 T_glyf = 0x676C7966;    static const guint32 O_glyf = 1;     /* 'glyf' */
118 static const guint32 T_head = 0x68656164;    static const guint32 O_head = 2;     /* 'head' */
119 static const guint32 T_loca = 0x6C6F6361;    static const guint32 O_loca = 3;     /* 'loca' */
120 static const guint32 T_name = 0x6E616D65;    static const guint32 O_name = 4;     /* 'name' */
121 static const guint32 T_hhea = 0x68686561;    static const guint32 O_hhea = 5;     /* 'hhea' */
122 static const guint32 T_hmtx = 0x686D7478;    static const guint32 O_hmtx = 6;     /* 'hmtx' */
123 static const guint32 T_cmap = 0x636D6170;    static const guint32 O_cmap = 7;     /* 'cmap' */
124 static const guint32 T_vhea = 0x76686561;    static const guint32 O_vhea = 8;     /* 'vhea' */
125 static const guint32 T_vmtx = 0x766D7478;    static const guint32 O_vmtx = 9;     /* 'vmtx' */
126 static const guint32 T_OS2  = 0x4F532F32;    static const guint32 O_OS2  = 10;    /* 'OS/2' */
127 static const guint32 T_post = 0x706F7374;    static const guint32 O_post = 11;    /* 'post' */
128 static const guint32 T_kern = 0x6B65726E;    static const guint32 O_kern = 12;    /* 'kern' */
129 static const guint32 T_cvt  = 0x63767420;    static const guint32 O_cvt  = 13;    /* 'cvt_' - only used in TT->TT generation */
130 static const guint32 T_prep = 0x70726570;    static const guint32 O_prep = 14;    /* 'prep' - only used in TT->TT generation */
131 static const guint32 T_fpgm = 0x6670676D;    static const guint32 O_fpgm = 15;    /* 'fpgm' - only used in TT->TT generation */
132 static const guint32 T_gsub = 0x47535542;    static const guint32 O_gsub = 16;    /* 'GSUB' */
133 #define NUM_TAGS 17
134
135 #define LAST_URANGE_BIT 69
136 const char *ulcodes[LAST_URANGE_BIT+2] = {
137     /*  0   */  "Basic Latin",
138     /*  1   */  "Latin-1 Supplement",
139     /*  2   */  "Latin Extended-A",
140     /*  3   */  "Latin Extended-B",
141     /*  4   */  "IPA Extensions",
142     /*  5   */  "Spacing Modifier Letters",
143     /*  6   */  "Combining Diacritical Marks",
144     /*  7   */  "Basic Greek",
145     /*  8   */  "Greek Symbols And Coptic",
146     /*  9   */  "Cyrillic",
147     /*  10  */  "Armenian",
148     /*  11  */  "Basic Hebrew",
149     /*  12  */  "Hebrew Extended (A and B blocks combined)",
150     /*  13  */  "Basic Arabic",
151     /*  14  */  "Arabic Extended",
152     /*  15  */  "Devanagari",
153     /*  16  */  "Bengali",
154     /*  17  */  "Gurmukhi",
155     /*  18  */  "Gujarati",
156     /*  19  */  "Oriya",
157     /*  20  */  "Tamil",
158     /*  21  */  "Telugu",
159     /*  22  */  "Kannada",
160     /*  23  */  "Malayalam",
161     /*  24  */  "Thai",
162     /*  25  */  "Lao",
163     /*  26  */  "Basic Georgian",
164     /*  27  */  "Georgian Extended",
165     /*  28  */  "Hangul Jamo",
166     /*  29  */  "Latin Extended Additional",
167     /*  30  */  "Greek Extended",
168     /*  31  */  "General Punctuation",
169     /*  32  */  "Superscripts And Subscripts",
170     /*  33  */  "Currency Symbols",
171     /*  34  */  "Combining Diacritical Marks For Symbols",
172     /*  35  */  "Letterlike Symbols",
173     /*  36  */  "Number Forms",
174     /*  37  */  "Arrows",
175     /*  38  */  "Mathematical Operators",
176     /*  39  */  "Miscellaneous Technical",
177     /*  40  */  "Control Pictures",
178     /*  41  */  "Optical Character Recognition",
179     /*  42  */  "Enclosed Alphanumerics",
180     /*  43  */  "Box Drawing",
181     /*  44  */  "Block Elements",
182     /*  45  */  "Geometric Shapes",
183     /*  46  */  "Miscellaneous Symbols",
184     /*  47  */  "Dingbats",
185     /*  48  */  "CJK Symbols And Punctuation",
186     /*  49  */  "Hiragana",
187     /*  50  */  "Katakana",
188     /*  51  */  "Bopomofo",
189     /*  52  */  "Hangul Compatibility Jamo",
190     /*  53  */  "CJK Miscellaneous",
191     /*  54  */  "Enclosed CJK Letters And Months",
192     /*  55  */  "CJK Compatibility",
193     /*  56  */  "Hangul",
194     /*  57  */  "Reserved for Unicode SubRanges",
195     /*  58  */  "Reserved for Unicode SubRanges",
196     /*  59  */  "CJK Unified Ideographs",
197     /*  60  */  "Private Use Area",
198     /*  61  */  "CJK Compatibility Ideographs",
199     /*  62  */  "Alphabetic Presentation Forms",
200     /*  63  */  "Arabic Presentation Forms-A",
201     /*  64  */  "Combining Half Marks",
202     /*  65  */  "CJK Compatibility Forms",
203     /*  66  */  "Small Form Variants",
204     /*  67  */  "Arabic Presentation Forms-B",
205     /*  68  */  "Halfwidth And Fullwidth Forms",
206     /*  69  */  "Specials",
207     /*70-127*/  "Reserved for Unicode SubRanges"
208 };
209
210 /*- inline functions */ /*FOLD01*/
211 #ifdef __GNUC__
212 #define _inline static __inline__
213 #else
214 #define _inline static
215 #endif
216
217 _inline void *smalloc(size_t size)
218 {
219     void *res = malloc(size);
220     assert(res != 0);
221     return res;
222 }
223
224 _inline void *scalloc(size_t n, size_t size)
225 {
226     void *res = calloc(n, size);
227     assert(res != 0);
228     return res;
229 }
230
231 #if !defined(STSF)
232
233 _inline guint32 mkTag(guint8 a, guint8 b, guint8 c, guint8 d) {
234     return (a << 24) | (b << 16) | (c << 8) | d;
235 }
236
237 /*- Data access macros for data stored in big-endian or little-endian format */
238 _inline gint16 GetInt16(const guint8 *ptr, size_t offset, int bigendian)
239 {
240     gint16 t;
241     assert(ptr != 0);
242     
243     if (bigendian) {
244         t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
245     } else {
246         t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
247     }
248         
249     return t;
250 }
251
252 _inline guint16 GetUInt16(const guint8 *ptr, size_t offset, int bigendian)
253 {
254     guint16 t;
255     assert(ptr != 0);
256
257     if (bigendian) {
258         t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
259     } else {
260         t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
261     }
262
263     return t;
264 }
265
266 _inline gint32  GetInt32(const guint8 *ptr, size_t offset, int bigendian)
267 {
268     gint32 t;
269     assert(ptr != 0);
270     
271     if (bigendian) {
272         t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
273             (ptr+offset)[2] << 8  | (ptr+offset)[3];
274     } else {
275         t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
276             (ptr+offset)[1] << 8  | (ptr+offset)[0];
277     }
278         
279     return t;
280 }
281
282 _inline guint32 GetUInt32(const guint8 *ptr, size_t offset, int bigendian)
283 {
284     guint32 t;
285     assert(ptr != 0);
286     
287
288     if (bigendian) {
289         t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
290             (ptr+offset)[2] << 8  | (ptr+offset)[3];
291     } else {
292         t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
293             (ptr+offset)[1] << 8  | (ptr+offset)[0];
294     }
295         
296     return t;
297 }
298
299 _inline void PutInt16(gint16 val, guint8 *ptr, size_t offset, int bigendian)
300 {
301     assert(ptr != 0);
302
303     if (bigendian) {
304         ptr[offset] = (val >> 8) & 0xFF;
305         ptr[offset+1] = val & 0xFF;
306     } else {
307         ptr[offset+1] = (val >> 8) & 0xFF;
308         ptr[offset] = val & 0xFF;
309     }
310
311 }
312 #else
313 #include "inlines.h"
314 #endif
315
316 #if G_BYTE_ORDER == G_BIG_ENDIAN
317 #define Int16FromMOTA(a) (a)
318 #else
319 static guint16 Int16FromMOTA(guint16 a) {
320   return (guint16) (((guint8)((a) >> 8)) | ((guint8)(a) << 8));
321 }
322 #endif
323
324 _inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b)
325 {
326     unsigned int a1, b1;
327     unsigned int a2, b2;
328     F16Dot16 res;
329     int sign;
330
331     sign = (a & 0x80000000) ^ (b & 0x80000000);
332     if (a < 0) a = -a;
333     if (b < 0) b = -b;
334
335     a1 = a >> 16;
336     b1 = a & 0xFFFF;
337     a2 = b >> 16;
338     b2 = b & 0xFFFF;
339
340     res = a1 * a2;
341
342     /* if (res  > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */
343
344     res <<= 16;
345     res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16);
346
347     return sign ? -res : res;
348 }
349
350
351 _inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b)
352 {
353     unsigned int f, r;
354     F16Dot16 res;
355     int sign;
356
357     sign = (a & 0x80000000) ^ (b & 0x80000000);
358     if (a < 0) a = -a;
359     if (b < 0) b = -b;
360
361     f = a / b;
362     r = a % b;
363
364     /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */
365
366     while (r > 0xFFFF) {
367         r >>= 1;
368         b >>= 1;
369     }
370
371     res = (f << 16) + (r << 16) / b;
372
373     return sign ? -res : res;
374 }
375
376 /*- returns a * b / c -*/
377 /* XXX provide a real implementation that preserves accuracy */
378 _inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c)
379 {
380     F16Dot16 res;
381
382     res = fixedMul(a, b);
383     return fixedDiv(res, c);
384 }
385
386 /*- Translate units from TT to PS (standard 1/1000) -*/
387 _inline int XUnits(int unitsPerEm, int n)
388 {
389     return (n * 1000) / unitsPerEm;
390 }
391
392 _inline const char *UnicodeRangeName(guint16 bit)
393 {
394   if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1;
395   
396   return ulcodes[bit];
397 }
398
399
400 #if 0
401 /* It would have been nice if it worked, but I found so many fonts that don't
402  * follow the TrueType spec (sorted table directory) that I have to re-write this
403  * stuff.
404  */
405
406 static guint8 *getTDEntry(TrueTypeFont *ttf, guint32 tag) /*FOLD01*/
407 {
408     int l = 0, r = ttf->ntables-1, i;
409     guint32 t;
410
411     do {
412         i = (l + r) >> 1;
413         t = GetUInt32(ttf->ptr + 12, i << 4, 1);
414         if (tag >= t) l = i + 1;
415         if (tag <= t) r = i - 1;
416     } while (l <= r);
417
418     if (l - r == 2) {
419         return ttf->ptr + 12 + 16 * (l - 1);
420     }
421     return 0;
422 }
423     
424 static guint8 *getTable(TrueTypeFont *ttf, guint32 tag) /*FOLD01*/
425 {
426     guint8 *ptr = getTDEntry(ttf, tag);
427     if (!ptr) return 0;
428     
429     return ttf->ptr + GetUInt32(ptr, 8, 1);
430 }
431
432 static guint32 getTableSize(TrueTypeFont *ttf, guint32 tag) /*FOLD01*/
433 {
434     guint8 *ptr = getTDEntry(ttf, tag);
435     if (!ptr) return 0;
436
437     return GetUInt32(ptr, 12, 1);
438 }
439
440 #endif
441
442 _inline guint8 *getTable(TrueTypeFont *ttf, guint32 ord)
443 {
444     return ttf->tables[ord];
445 }
446
447 _inline guint32 getTableSize(TrueTypeFont *ttf, guint32 ord)
448 {
449     return ttf->tlens[ord];
450 }
451
452 static guint32 tagToOrd(guint32 tag)
453 {
454     if (tag == T_maxp) {
455         return O_maxp;
456     } else if (tag == T_glyf) {
457         return O_glyf;
458     } else if (tag == T_head) {
459         return O_head;
460     } else if (tag == T_loca) {
461         return O_loca;
462     } else if (tag == T_name) {
463         return O_name;
464     } else if (tag == T_hhea) {
465         return O_hhea;
466     } else if (tag == T_hmtx) {
467         return O_hmtx;
468     } else if (tag == T_cmap) {
469         return O_cmap;
470     } else if (tag == T_vhea) {
471         return O_vhea;
472     } else if (tag == T_vmtx) {
473         return O_vmtx;
474     } else if (tag == T_OS2) {
475         return O_OS2;
476     } else if (tag == T_post) {
477         return O_post;
478     } else if (tag == T_kern) {
479         return O_kern;
480     } else if (tag == T_cvt) {
481         return O_cvt;
482     } else if (tag == T_prep) {
483         return O_prep;
484     } else if (tag == T_fpgm) {
485         return O_fpgm;
486     } else if (tag == T_gsub) {
487         return O_gsub;
488     }
489     return 0xFFFFFFFF;
490 }
491
492 #ifndef NO_TYPE42
493 /* Hex Formatter functions */
494 static char HexChars[] = "0123456789ABCDEF";
495
496 static HexFmt *HexFmtNew(FILE *outf)
497 {
498     HexFmt *res = smalloc(sizeof(HexFmt));
499     res->bufpos = res->total = 0;
500     res->o = outf;
501     return res;
502 }
503
504 static void HexFmtFlush(HexFmt *_this)
505 {
506     if (_this->bufpos) {
507         fwrite(_this->buffer, 1, _this->bufpos, _this->o);
508         _this->bufpos = 0;
509     }
510 }
511
512
513 _inline void HexFmtOpenString(HexFmt *_this)
514 {
515     fputs("<\n", _this->o);
516 }
517
518 _inline void HexFmtCloseString(HexFmt *_this)
519 {
520     HexFmtFlush(_this);
521     fputs("00\n>\n", _this->o);
522 }
523
524 _inline void HexFmtDispose(HexFmt *_this)
525 {
526     HexFmtFlush(_this);
527     free(_this);
528 }
529
530 static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, off_t size)
531 {
532     guint8 Ch;
533     off_t i;
534   
535     if (_this->total + size > 65534) {
536         HexFmtFlush(_this);
537         HexFmtCloseString(_this);
538         _this->total = 0;
539         HexFmtOpenString(_this);
540     }
541     for (i=0; i<size; i++) {
542         Ch = ((guint8 *) ptr)[i];
543         _this->buffer[_this->bufpos++] = HexChars[Ch >> 4];
544         _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF];
545         if (_this->bufpos == HFORMAT_LINELEN) {
546             HexFmtFlush(_this);
547             fputc('\n', _this->o);
548         }
549
550     }
551     _this->total += size;
552 }
553 #endif
554
555
556
557 /* Outline Extraction functions */ /*FOLD01*/
558
559 /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
560 static void GetMetrics(TrueTypeFont *ttf, guint32 glyphID, TTGlyphMetrics *metrics)
561 {
562     guint8 *table = getTable(ttf, O_hmtx);
563
564     metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0;
565     if (!table || !ttf->numberOfHMetrics) return;
566
567     if (glyphID < ttf->numberOfHMetrics) {
568         metrics->aw  = GetUInt16(table, 4 * glyphID, 1);
569         metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1);
570     } else {
571         metrics->aw  = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1);
572         metrics->lsb = GetInt16(table + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1);
573     }
574
575     table = getTable(ttf, O_vmtx);
576     if (!table || !ttf->numOfLongVerMetrics) return;
577
578     if (glyphID < ttf->numOfLongVerMetrics) {
579         metrics->ah  = GetUInt16(table, 4 * glyphID, 1);
580         metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1);
581     } else {
582         metrics->ah  = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1);
583         metrics->tsb = GetInt16(table + ttf->numOfLongVerMetrics * 4, (glyphID - ttf->numOfLongVerMetrics) * 2, 1);
584     }
585 }
586
587 FUnitBBox *GetTTGlyphBoundingBoxes(TrueTypeFont *ttf)
588 {
589     guint8 *table = getTable(ttf, O_glyf);
590     FUnitBBox *b = calloc(ttf->nglyphs, sizeof(FUnitBBox));
591     
592     if (b != NULL) {
593         int i;
594
595         for (i = 0; i< ttf->nglyphs; i++) {
596             guint8 *ptr = table + ttf->goffsets[i];
597             b[i].xMin = XUnits(ttf->unitsPerEm, GetInt16(ptr, 2, 1));
598             b[i].yMin = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4, 1));
599             b[i].xMax = XUnits(ttf->unitsPerEm, GetInt16(ptr, 6, 1));
600             b[i].yMax = XUnits(ttf->unitsPerEm, GetInt16(ptr, 8, 1));
601         }
602     }
603
604     return b;
605 }
606
607
608 static int GetTTGlyphOutline(TrueTypeFont *, guint32 , ControlPoint **, TTGlyphMetrics *, list );
609
610 /* returns the number of control points, allocates the pointArray */
611 static int GetSimpleTTOutline(TrueTypeFont *ttf, guint32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/
612 {
613     guint8 *table = getTable(ttf, O_glyf);
614     guint8 *ptr, *p, flag, n;
615     gint16 numberOfContours;
616     guint16 t, instLen, lastPoint=0;
617     int i, j, z;
618     ControlPoint* pa;
619
620     *pointArray = NULL;
621
622     /* printf("GetSimpleTTOutline(%d)\n", glyphID); */
623
624     if (glyphID >= ttf->nglyphs) return 0;                            /*- glyph is not present in the font */
625     ptr = table + ttf->goffsets[glyphID];
626     if ((numberOfContours = GetInt16(ptr, 0, 1)) <= 0) return 0;      /*- glyph is not simple */
627
628     if (metrics) {                                                    /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
629         metrics->xMin = GetInt16(ptr, 2, 1);
630         metrics->yMin = GetInt16(ptr, 4, 1);
631         metrics->xMax = GetInt16(ptr, 6, 1);
632         metrics->yMax = GetInt16(ptr, 8, 1);
633         GetMetrics(ttf, glyphID, metrics);
634     }
635
636     /* determine the last point and be extra safe about it. But probably this code is not needed */
637     
638     for (i=0; i<numberOfContours; i++) {
639         if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t;
640     }
641
642     instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1);
643     p = ptr + 10 + 2 * numberOfContours + 2 + instLen;
644     pa = calloc(lastPoint+1, sizeof(ControlPoint));
645
646     i = 0;
647     while (i <= lastPoint) {
648         pa[i++].flags = flag = (guint32) *p++;
649         if (flag & 8) {                                     /*- repeat flag */
650             n = *p++;
651             for (j=0; j<n; j++) {
652                 if (i > lastPoint) {                        /*- if the font is really broken */
653                     free(pa);
654                     return 0;
655                 }
656                 pa[i++].flags = flag;
657             }
658         }
659     }
660
661     /*- Process the X coordinate */
662     z = 0;
663     for (i = 0; i <= lastPoint; i++) {
664         if (pa[i].flags & 0x02) {
665             if (pa[i].flags & 0x10) {
666                 z += (int) (*p++);
667             } else {
668                 z -= (int) (*p++);
669             }
670         } else if ( !(pa[i].flags & 0x10)) {
671             z += GetInt16(p, 0, 1);
672             p += 2;
673         }
674         pa[i].x = z;
675     }
676
677     /*- Process the Y coordinate */
678     z = 0;
679     for (i = 0; i <= lastPoint; i++) {
680         if (pa[i].flags & 0x04) {
681             if (pa[i].flags & 0x20) {
682                 z += *p++;
683             } else {
684                 z -= *p++;
685             }
686         } else if ( !(pa[i].flags & 0x20)) {
687             z += GetInt16(p, 0, 1);
688             p += 2;
689         }
690         pa[i].y = z;
691     }
692
693     for (i=0; i<numberOfContours; i++) {
694         pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000;      /*- set the end contour flag */
695     }
696
697     *pointArray = pa;
698     return lastPoint + 1;
699 }
700
701 static int GetCompoundTTOutline(TrueTypeFont *ttf, guint32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, list glyphlist) /*FOLD02*/
702 {
703     guint16 flags, index;
704     gint16 e, f, numberOfContours;
705     guint8 *table = getTable(ttf, O_glyf);
706     guint8 *ptr;
707     list myPoints;
708     ControlPoint *nextComponent, *pa;
709     int i, np;
710     F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3;
711
712     *pointArray = NULL;
713     /* printf("GetCompoundTTOutline(%d)\n", glyphID); */
714
715     if (glyphID >= ttf->nglyphs) {                          /*- incorrect glyphID */
716         return 0;
717     }
718     ptr = table + ttf->goffsets[glyphID];
719     if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) {   /*- glyph is not compound */
720         return 0;
721     }
722
723     myPoints = listNewEmpty();
724     listSetElementDtor(myPoints, free);
725
726     if (metrics) {
727         metrics->xMin = GetInt16(ptr, 2, 1);
728         metrics->yMin = GetInt16(ptr, 4, 1);
729         metrics->xMax = GetInt16(ptr, 6, 1);
730         metrics->yMax = GetInt16(ptr, 8, 1);
731         GetMetrics(ttf, glyphID, metrics);
732     }
733
734     ptr += 10;
735
736     do {
737         flags = GetUInt16(ptr, 0, 1);
738         /* printf("flags: 0x%X\n", flags); */
739         index = GetUInt16(ptr, 2, 1);
740         ptr += 4;
741
742         if (listFind(glyphlist, (void *) (int) index)) {
743 #ifdef DEBUG
744             fprintf(stderr, "Endless loop found in a compound glyph.\n");
745             fprintf(stderr, "%d -> ", index);
746             listToFirst(glyphlist);
747             fprintf(stderr," [");
748             do {
749                 fprintf(stderr,"%d ", (int) listCurrent(glyphlist));
750             } while (listNext(glyphlist));
751             fprintf(stderr,"]\n");
752         /**/
753 #endif
754         }
755
756         listAppend(glyphlist, (void *) (int) index);
757
758 #ifdef DEBUG2
759         fprintf(stderr,"glyphlist: += %d\n", index);
760 #endif
761            
762         if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, NULL, glyphlist)) == 0) {
763             /* XXX that probably indicates a corrupted font */
764 #ifdef DEBUG
765             fprintf(stderr, "An empty compound!\n");
766             /* assert(!"An empty compound"); */
767 #endif
768         }
769
770         listToLast(glyphlist);
771 #ifdef DEBUG2
772         listToFirst(glyphlist);
773         fprintf(stderr,"%d [", listCount(glyphlist));
774         if (!listIsEmpty(glyphlist)) {
775             do {
776                 fprintf(stderr,"%d ", (int) listCurrent(glyphlist));
777             } while (listNext(glyphlist));
778         }
779         fprintf(stderr, "]\n");
780         fprintf(stderr, "glyphlist: -= %d\n", (int) listCurrent(glyphlist));
781         
782 #endif
783         listRemove(glyphlist);
784
785         if (flags & USE_MY_METRICS) {
786             if (metrics) GetMetrics(ttf, index, metrics);
787         }
788
789         if (flags & ARG_1_AND_2_ARE_WORDS) {
790             e = GetInt16(ptr, 0, 1);
791             f = GetInt16(ptr, 2, 1);
792             /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
793             ptr += 4;
794         } else {
795             if (flags & ARGS_ARE_XY_VALUES) {     /* args are signed */
796                 e = (gint8) *ptr++;
797                 f = (gint8) *ptr++;
798                 /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
799             } else {                              /* args are unsigned */
800                 /* printf("!ARGS_ARE_XY_VALUES\n"); */
801                 e = *ptr++;
802                 f = *ptr++;
803             }
804
805         }
806
807         a = d = 0x10000;
808         b = c = 0;
809
810         if (flags & WE_HAVE_A_SCALE) {
811 #ifdef DEBUG2
812             fprintf(stderr, "WE_HAVE_A_SCALE\n");
813 #endif
814             a = GetInt16(ptr, 0, 1) << 2;
815             d = a;
816             ptr += 2;
817         } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
818 #ifdef DEBUG2
819             fprintf(stderr, "WE_HAVE_AN_X_AND_Y_SCALE\n");
820 #endif
821             a = GetInt16(ptr, 0, 1) << 2;
822             d = GetInt16(ptr, 2, 1) << 2;
823             ptr += 4;
824         } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
825 #ifdef DEBUG2
826             fprintf(stderr, "WE_HAVE_A_TWO_BY_TWO\n");
827 #endif
828             a = GetInt16(ptr, 0, 1) << 2;
829             b = GetInt16(ptr, 2, 1) << 2;
830             c = GetInt16(ptr, 4, 1) << 2;
831             d = GetInt16(ptr, 6, 1) << 2;
832             ptr += 8;
833         }
834
835         abs1 = (a < 0) ? -a : a;
836         abs2 = (b < 0) ? -b : b;
837         m    = (abs1 > abs2) ? abs1 : abs2;
838         abs3 = abs1 - abs2;
839         if (abs3 < 0) abs3 = -abs3;
840         if (abs3 <= 33) m *= 2;
841
842         abs1 = (c < 0) ? -c : c;
843         abs2 = (d < 0) ? -d : d;
844         n    = (abs1 > abs2) ? abs1 : abs2;
845         abs3 = abs1 - abs2;
846         if (abs3 < 0) abs3 = -abs3;
847         if (abs3 <= 33) n *= 2;
848
849         if (!ARGS_ARE_XY_VALUES) {      /* match the points */
850             assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n");
851         }
852
853 #ifdef DEBUG2
854         fprintf(stderr, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n",
855                 ((double) a) / 65536,
856                 ((double) b) / 65536,
857                 ((double) c) / 65536,
858                 ((double) d) / 65536,
859                 ((double) e) / 65536,
860                 ((double) f) / 65536,
861                 ((double) m) / 65536,
862                 ((double) n) / 65536);
863 #endif
864
865         for (i=0; i<np; i++) {
866             F16Dot16 t;
867             ControlPoint *cp = malloc(sizeof(ControlPoint));
868             cp->flags = nextComponent[i].flags;
869             t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16);
870             cp->x = fixedMul(t, m) >> 16;
871             t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16);
872             cp->y = fixedMul(t, n) >> 16;
873
874 #ifdef DEBUG2
875             fprintf(stderr, "( %d %d ) -> ( %d %d )\n", nextComponent[i].x, nextComponent[i].y, cp->x, cp->y);
876 #endif
877             
878             listAppend(myPoints, cp);
879         }
880             
881         free(nextComponent);
882
883     } while (flags & MORE_COMPONENTS);
884
885     
886
887     np = listCount(myPoints);
888
889     pa = calloc(np, sizeof(ControlPoint));
890     assert(pa != 0);
891     listToFirst(myPoints);
892     for (i=0; i<np; i++) {
893         memcpy(pa+i, listCurrent(myPoints), sizeof(ControlPoint));
894         listNext(myPoints);
895     }
896     listDispose(myPoints);
897
898     *pointArray = pa;
899     return np;
900 }
901
902 /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect, 
903  * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
904  *
905  * NOTE: glyphlist is the stack of glyphs traversed while constructing
906  * a composite glyph. This is a safequard against endless recursion
907  * in corrupted fonts.
908  */
909 static int GetTTGlyphOutline(TrueTypeFont *ttf, guint32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, list glyphlist)
910 {
911     guint8 *ptr, *table = getTable(ttf, O_glyf);
912     gint16 numberOfContours;
913     int length;
914     int res;
915     *pointArray = NULL;
916
917     if (metrics) {
918         memset(metrics, 0, sizeof(TTGlyphMetrics));         /*- metrics is initialized to all zeroes */
919     }
920
921     if (glyphID >= ttf->nglyphs) return -1;                 /**/
922     
923     ptr = table + ttf->goffsets[glyphID];
924     length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
925
926     if (length == 0) {                                      /*- empty glyphs still have hmtx and vmtx metrics values */
927         if (metrics) GetMetrics(ttf, glyphID, metrics);
928         return 0;
929     }
930     
931     numberOfContours = GetInt16(ptr, 0, 1);
932
933     if (numberOfContours >= 0) {
934         res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics);
935     } else {
936         int glyphlistFlag = 0;
937         if (!glyphlist) {
938             glyphlistFlag = 1;
939             glyphlist = listNewEmpty();
940             listAppend(glyphlist, (void *) glyphID);
941         }
942         res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist);
943         if (glyphlistFlag) {
944             glyphlistFlag = 0;
945             listDispose(glyphlist);
946             glyphlist = NULL;
947         }
948     }
949
950 #ifdef DEBUG3
951     {
952         int i;
953         FILE *out = fopen("points.dat", "ab");
954         assert(out != 0);
955         fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res);
956         for (i=0; i<res; i++) {
957             fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.');
958             fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-');
959             fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y);
960         }
961         fclose(out);
962     }
963 #endif
964
965     return res;
966 }
967
968 #ifndef NO_TYPE3
969
970 static PSPathElement *newPSPathElement(int t)
971 {
972     PSPathElement *p = malloc(sizeof(PSPathElement));
973     assert(p != 0);
974
975     p->type = t;
976     return p;
977 }
978
979 /*- returns the number of items in the path -*/
980
981 static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path)
982 {
983     list pList = listNewEmpty();
984     int i = 0, pCount = 0;
985     PSPathElement *p;
986
987     int x0, y0, x1, y1, x2, y2, curx, cury;
988     int lastOff = 0;                                        /*- last point was off-contour */
989     int scflag = 1;                                         /*- start contour flag */
990     int ecflag = 0;                                         /*- end contour flag */
991     int cp = 0;                                             /*- current point */
992
993     listSetElementDtor(pList, free);
994     *path = 0;
995
996     /* if (srcCount > 0) for(;;) */
997     while (srcCount > 0) {                                  /*- srcCount does not get changed inside the loop. */
998         int StartContour, EndContour;
999
1000         if (scflag) {
1001             int l = cp;
1002             StartContour = cp;
1003             while (!(srcA[l].flags & 0x8000)) l++;
1004             EndContour = l;
1005             if (StartContour == EndContour) {
1006                 if (cp + 1 < srcCount) {
1007                     cp++;
1008                     continue;
1009                 } else {
1010                     break;
1011                 }
1012             }
1013             p = newPSPathElement(PS_MOVETO);
1014             if (!(srcA[cp].flags & 1)) {
1015                 if (!(srcA[EndContour].flags & 1)) {
1016                     p->x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2;
1017                     p->y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2;
1018                 } else {
1019                     p->x1 = x0 = srcA[EndContour].x;
1020                     p->y1 = y0 = srcA[EndContour].y;
1021                 }
1022             } else {
1023                 p->x1 = x0 = srcA[cp].x;
1024                 p->y1 = y0 = srcA[cp].y;
1025                 cp++;
1026             }
1027             listAppend(pList, p);
1028             lastOff = 0;
1029             scflag = 0;
1030         }
1031
1032         curx = srcA[cp].x;
1033         cury = srcA[cp].y;
1034
1035         if (srcA[cp].flags & 1) {
1036             if (lastOff) {
1037                 p = newPSPathElement(PS_CURVETO);
1038                 p->x1 = x0 + (2 * (x1 - x0) + 1) / 3;
1039                 p->y1 = y0 + (2 * (y1 - y0) + 1) / 3;
1040                 p->x2 = x1 + (curx - x1 + 1) / 3;
1041                 p->y2 = y1 + (cury - y1 + 1) / 3;
1042                 p->x3 = curx;
1043                 p->y3 = cury;
1044                 listAppend(pList, p);
1045             } else {
1046                 if (!(x0 == curx && y0 == cury)) {                              /* eliminate empty lines */
1047                     p = newPSPathElement(PS_LINETO);
1048                     p->x1 = curx;
1049                     p->y1 = cury;
1050                     listAppend(pList, p);
1051                 }
1052             }
1053                 
1054             x0 = curx; y0 = cury; lastOff = 0;
1055         } else {
1056             if (lastOff) {
1057                 x2 = (x1 + curx + 1) / 2;
1058                 y2 = (y1 + cury + 1) / 2;
1059                 p = newPSPathElement(PS_CURVETO);
1060                 p->x1 = x0 + (2 * (x1 - x0) + 1) / 3;
1061                 p->y1 = y0 + (2 * (y1 - y0) + 1) / 3;
1062                 p->x2 = x1 + (x2 - x1 + 1) / 3;
1063                 p->y2 = y1 + (y2 - y1 + 1) / 3;
1064                 p->x3 = x2;
1065                 p->y3 = y2;
1066                 listAppend(pList, p);
1067                 x0 = x2; y0 = y2;
1068                 x1 = curx; y1 = cury;
1069             } else {
1070                 x1 = curx; y1 = cury;
1071             }
1072             lastOff = true;
1073         }
1074
1075         if (ecflag) {
1076             listAppend(pList, newPSPathElement(PS_CLOSEPATH));
1077             scflag = 1;
1078             ecflag = 0;
1079             cp = EndContour + 1;
1080             if (cp >= srcCount) break;
1081             continue;
1082         }
1083
1084         if (cp == EndContour) {
1085             cp = StartContour;
1086             ecflag = true;
1087         } else {
1088             cp++;
1089         }
1090     }
1091
1092     if ((pCount = listCount(pList)) > 0) {
1093         p = calloc(pCount, sizeof(PSPathElement));
1094         assert(p != 0);
1095         listToFirst(pList);
1096         for (i=0; i<pCount; i++) {
1097             memcpy(p + i, listCurrent(pList), sizeof(PSPathElement));
1098             listNext(pList);
1099         }
1100         listDispose(pList);
1101         *path = p;
1102     }
1103     
1104     return pCount;
1105 }
1106
1107 #endif
1108
1109 /*- Extracts a string from the name table and allocates memory for it -*/
1110
1111 static char *nameExtract(guint8 *name, int n, int dbFlag, guint16** ucs2result )
1112 {
1113     int i;
1114     char *res;
1115     guint8 *ptr =  name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1);
1116     int len = GetUInt16(name+6, 12 * n + 8, 1);
1117
1118     if (ucs2result) *ucs2result = NULL;
1119     
1120     if (dbFlag) {
1121         res = malloc(1 + len/2);
1122         assert(res != 0);
1123         for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1);
1124         res[len/2] = 0;
1125         if (ucs2result) {
1126             *ucs2result = malloc(len + 2);
1127             for (i = 0; i < len/2; i++ ) (*ucs2result)[i] = GetUInt16(ptr, 2*i, 1);
1128             (*ucs2result)[len/2] = 0;
1129         }
1130     } else {
1131         res = malloc(1 + len);
1132         assert(res != 0);
1133         memcpy(res, ptr, len);
1134         res[len] = 0;
1135     }
1136
1137     return res;
1138 }
1139
1140 static int findname(guint8 *name, guint16 n, guint16 platformID, guint16 encodingID, guint16 languageID, guint16 nameID)
1141 {
1142     int l = 0, r = n-1, i;
1143     guint32 t1, t2;
1144     guint32 m1, m2;
1145
1146     if (n == 0) return -1;
1147
1148     m1 = (platformID << 16) | encodingID;
1149     m2 = (languageID << 16) | nameID;
1150
1151     do {
1152         i = (l + r) >> 1;
1153         t1 = GetUInt32(name + 6, i * 12 + 0, 1);
1154         t2 = GetUInt32(name + 6, i * 12 + 4, 1);
1155
1156         if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1;
1157         if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1;
1158     } while (l <= r);
1159
1160     if (l - r == 2) {
1161         return l - 1;
1162     }
1163
1164     return -1;
1165 }
1166
1167 /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables. 
1168  * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
1169  *
1170  * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
1171  * and does not have (3, 1, 1033)
1172  * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
1173  * require a change in algorithm
1174  *
1175  * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID,
1176  * but (1, 0, 1042) strings usable
1177  * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
1178  */
1179
1180 static void GetNames(TrueTypeFont *t)
1181 {
1182     guint8 *table = getTable(t, O_name);
1183     guint16 n = GetUInt16(table, 2, 1);
1184     int i, r;
1185
1186     /* PostScript name: preferred Microsoft */
1187     if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1) {
1188         t->psname = nameExtract(table, r, 1, NULL);
1189     } else if ((r = findname(table, n, 1, 0, 0, 6)) != -1) {
1190         t->psname = nameExtract(table, r, 0, NULL);
1191     } else {
1192         char* pReverse = t->fname + strlen(t->fname);
1193         /* take only last token of filename */
1194         while(pReverse != t->fname && *pReverse != '/') pReverse--;
1195         if(*pReverse == '/') pReverse++;
1196         t->psname = strdup(pReverse);
1197         assert(t->psname != 0);
1198         for (i=strlen(t->psname) - 1; i > 0; i--) {                                /*- Remove the suffix  -*/
1199             if (t->psname[i] == '.' ) {
1200                 t->psname[i] = 0;
1201                 break;
1202             }
1203         }
1204     }
1205
1206     /* Font family and subfamily names: preferred Apple */
1207     if ((r = findname(table, n, 0, 0, 0, 1)) != -1) {
1208         t->family = nameExtract(table, r, 1, &t->ufamily);
1209     } else if ((r = findname(table, n, 3, 1, 0x0409, 1)) != -1) {
1210         t->family = nameExtract(table, r, 1, &t->ufamily);
1211     } else if ((r = findname(table, n, 1, 0, 0, 1)) != -1) {
1212         t->family = nameExtract(table, r, 0, NULL);
1213     } else if ((r = findname(table, n, 3, 1, 0x0411, 1)) != -1) {
1214         t->family = nameExtract(table, r, 1, &t->ufamily);
1215     } else {
1216         t->family = strdup(t->psname);
1217         assert(t->family != 0);
1218     }
1219
1220     if ((r = findname(table, n, 1, 0, 0, 2)) != -1) {
1221         t->subfamily = nameExtract(table, r, 0, NULL);
1222     } else if ((r = findname(table, n, 3, 1, 0x0409, 2)) != -1) {
1223         t->subfamily = nameExtract(table, r, 1, NULL);
1224     } else {
1225         t->subfamily = strdup("");
1226         assert(t->family != 0);
1227     }
1228
1229 }
1230         
1231 enum cmapType {
1232     CMAP_NOT_USABLE           = -1,
1233     CMAP_MS_Symbol            = 10,
1234     CMAP_MS_Unicode           = 11,
1235     CMAP_MS_ShiftJIS          = 12,
1236     CMAP_MS_Big5              = 13,
1237     CMAP_MS_PRC               = 14,
1238     CMAP_MS_Wansung           = 15,
1239     CMAP_MS_Johab             = 16
1240 };
1241
1242 #define MISSING_GLYPH_INDEX 0
1243
1244 /*
1245  * All getGlyph?() functions and freinds are implemented by:
1246  * @author Manpreet Singh
1247  */
1248 static guint16 getGlyph0(const guint8* cmap, guint16 c) {
1249     if (c <= 255) {
1250         return *(cmap + 6 + c);
1251     } else {
1252         return MISSING_GLYPH_INDEX;
1253     }
1254 }
1255
1256 typedef struct _subHeader2 {
1257     guint16 firstCode;
1258     guint16 entryCount;
1259     guint16 idDelta;
1260     guint16 idRangeOffset;
1261 } subHeader2;
1262
1263 static guint16 getGlyph2(const guint8 *cmap, guint16 c) {
1264     guint16 *CMAP2 = (guint16 *) cmap;
1265     guint8 theHighByte;
1266     guint8 theLowByte;
1267     subHeader2* subHeader2s; 
1268     guint16* subHeader2Keys;
1269     guint16 firstCode;
1270     int k;
1271     int ToReturn;
1272
1273     theHighByte = (guint8)((c >> 8) & 0x00ff);
1274     theLowByte = (guint8)(c & 0x00ff);
1275     subHeader2Keys = CMAP2 + 3;
1276     subHeader2s = (subHeader2 *)(subHeader2Keys + 256);
1277     k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8;
1278     
1279     if(k == 0) {
1280         firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
1281         if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
1282             return *((&(subHeader2s[0].idRangeOffset))
1283                      + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2)             /* + offset        */
1284                      + theLowByte                                                  /* + to_look       */
1285                      - Int16FromMOTA(subHeader2s[0].firstCode)
1286                      );
1287         } else {
1288             return MISSING_GLYPH_INDEX;
1289         }
1290     } else if (k > 0) {
1291         firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
1292         if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
1293             ToReturn = *((&(subHeader2s[k].idRangeOffset))
1294                          + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2)
1295                          + theLowByte - firstCode);
1296             if(ToReturn == 0) {
1297                 return MISSING_GLYPH_INDEX;
1298             } else {
1299                 return (guint16)((ToReturn + Int16FromMOTA(subHeader2s[k].idDelta)) % 0xFFFF);
1300             }
1301         } else {
1302             return MISSING_GLYPH_INDEX;
1303         }
1304     } else {
1305         return MISSING_GLYPH_INDEX;
1306     }
1307 }
1308
1309 static guint16 getGlyph6(const guint8 *cmap, guint16 c) {
1310     guint16 firstCode;
1311     guint16 *CMAP6 = (guint16 *) cmap;
1312     
1313     firstCode = *(CMAP6 + 3);
1314     if (c < firstCode ||  c > (firstCode + (*(CMAP6 + 4))/*entryCount*/ - 1)) {
1315         return MISSING_GLYPH_INDEX;
1316     } else {
1317         return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode));
1318     }
1319 }
1320
1321 static guint16 GEbinsearch(guint16 *ar, guint16 length, guint16 toSearch) {
1322     signed int low, mid, high, lastfound = 0xffff;
1323     guint16 res;
1324     if(length == (guint16)0 || length == (guint16)0xFFFF) {
1325         return (guint16)0xFFFF;
1326     }
1327     low = 0;
1328     high = length - 1;
1329     while(high >= low) {
1330         mid = (high + low)/2;
1331         res = Int16FromMOTA(*(ar+mid));
1332         if(res >= toSearch) {
1333             lastfound = mid;
1334             high = --mid; 
1335         } else {
1336             low = ++mid;
1337         }
1338     }
1339     return lastfound;
1340 }
1341
1342
1343 static guint16 getGlyph4(const guint8 *cmap, guint16 c) {
1344     guint16  i;
1345     int ToReturn;
1346     guint16  segCount;
1347     guint16 * startCode;
1348     guint16 * endCode;
1349     guint16 * idDelta;
1350     /* guint16 * glyphIdArray; */
1351     guint16 * idRangeOffset;
1352     guint16 * glyphIndexArray;
1353     guint16  *CMAP4 = (guint16 *) cmap;
1354     /* guint16  GEbinsearch(guint16 *ar, guint16 length, guint16 toSearch); */
1355
1356     segCount = Int16FromMOTA(*(CMAP4 + 3))/2;
1357     endCode = CMAP4 + 7;
1358     i = GEbinsearch(endCode, segCount, c); 
1359
1360     if (i == (guint16) 0xFFFF) {
1361         return MISSING_GLYPH_INDEX;
1362     }
1363     startCode = endCode + segCount + 1;
1364     
1365     if(Int16FromMOTA(startCode[i]) > c) {
1366         return MISSING_GLYPH_INDEX;
1367     }
1368     idDelta = startCode + segCount;
1369     idRangeOffset = idDelta + segCount;
1370     glyphIndexArray = idRangeOffset + segCount;
1371
1372     if(Int16FromMOTA(idRangeOffset[i]) != 0) {
1373         ToReturn = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i])))));
1374     } else {
1375         ToReturn = (Int16FromMOTA(idDelta[i]) + c)%65536;
1376     }
1377     return ToReturn;
1378 }
1379
1380 static void FindCmap(TrueTypeFont *ttf)
1381 {
1382     guint8 *table = getTable(ttf, O_cmap);
1383     guint16 ncmaps = GetUInt16(table, 2, 1);
1384     int i;
1385     guint32 ThreeZero  = 0;              /* MS Symbol            */
1386     guint32 ThreeOne   = 0;              /* MS Unicode           */
1387     guint32 ThreeTwo   = 0;              /* MS ShiftJIS          */
1388     guint32 ThreeThree = 0;              /* MS Big5              */
1389     guint32 ThreeFour  = 0;              /* MS PRC               */
1390     guint32 ThreeFive  = 0;              /* MS Wansung           */
1391     guint32 ThreeSix   = 0;              /* MS Johab             */
1392
1393     for (i = 0; i < ncmaps; i++) {
1394         guint32 offset;
1395         guint16 pID, eID;
1396
1397         pID = GetUInt16(table, 4 + i * 8, 1);
1398         eID = GetUInt16(table, 6 + i * 8, 1);
1399         offset = GetUInt32(table, 8 + i * 8, 1);
1400
1401         if (pID == 3) {
1402             switch (eID) {
1403               case 0: ThreeZero  = offset; break;
1404               case 1: ThreeOne   = offset; break;
1405               case 2: ThreeTwo   = offset; break;
1406               case 3: ThreeThree = offset; break;
1407               case 4: ThreeFour  = offset; break;
1408               case 5: ThreeFive  = offset; break;
1409               case 6: ThreeSix   = offset; break;
1410             }
1411         }
1412     }
1413
1414     if (ThreeOne) {
1415         ttf->cmapType = CMAP_MS_Unicode;
1416         ttf->cmap = table + ThreeOne;
1417     } else if (ThreeTwo) {
1418         ttf->cmapType = CMAP_MS_ShiftJIS;
1419         ttf->cmap = table + ThreeTwo;
1420     } else if (ThreeThree) {
1421         ttf->cmapType = CMAP_MS_Big5;
1422         ttf->cmap = table + ThreeThree;
1423     } else if (ThreeFour) {
1424         ttf->cmapType = CMAP_MS_PRC;
1425         ttf->cmap = table + ThreeFour;
1426     } else if (ThreeFive) {
1427         ttf->cmapType = CMAP_MS_Wansung;
1428         ttf->cmap = table + ThreeFive;
1429     } else if (ThreeSix) {
1430         ttf->cmapType = CMAP_MS_Johab;
1431         ttf->cmap = table + ThreeSix;
1432     } else if (ThreeZero) {
1433         ttf->cmapType = CMAP_MS_Symbol;
1434         ttf->cmap = table + ThreeZero;
1435     } else {
1436         ttf->cmapType = CMAP_NOT_USABLE;
1437         ttf->cmap = NULL; 
1438     }
1439
1440     if (ttf->cmapType != CMAP_NOT_USABLE) {
1441         
1442         switch (GetUInt16(ttf->cmap, 0, 1)) {
1443           case 0: ttf->mapper = getGlyph0; break;
1444           case 2: ttf->mapper = getGlyph2; break;
1445           case 4: ttf->mapper = getGlyph4; break;
1446           case 6: ttf->mapper = getGlyph6; break;
1447           default:
1448 #ifdef DEBUG
1449                 /*- if the cmap table is really broken */
1450             printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1));
1451 #endif
1452             ttf->cmapType = CMAP_NOT_USABLE;
1453             ttf->cmap = NULL;
1454             ttf->mapper = NULL;
1455         }
1456     }
1457 }
1458
1459 static void GetKern(TrueTypeFont *ttf)
1460 {
1461     guint8 *table = getTable(ttf, O_kern);
1462     guint8 *ptr;
1463     int i;
1464
1465     if (!table) goto badtable;
1466
1467     if (getTableSize(ttf, O_kern) < 32) goto badtable;
1468
1469     if (GetUInt16(table, 0, 1) == 0) {                                /* Traditional Microsoft style table with USHORT version and nTables fields */
1470         ttf->nkern = GetUInt16(table, 2, 1);
1471         ttf->kerntables = calloc(ttf->nkern, sizeof(guint8 *));
1472         assert(ttf->kerntables != 0);
1473         memset(ttf->kerntables, 0, ttf->nkern * sizeof(guint8 *));
1474         ttf->kerntype = KT_MICROSOFT;
1475         ptr = table + 4;
1476         for (i=0; i < ttf->nkern; i++) {
1477             ttf->kerntables[i] = ptr;
1478             ptr += GetUInt16(ptr, 2, 1);
1479             /* sanity check */
1480             if( ptr > ttf->ptr+ttf->fsize ) {
1481                 free( ttf->kerntables );
1482                 goto badtable;
1483             }
1484         }
1485         return;
1486     }
1487
1488     if (GetUInt32(table, 0, 1) == 0x00010000) {                       /* MacOS style kern tables: fixed32 version and guint32 nTables fields */
1489         ttf->nkern = GetUInt32(table, 4, 1);
1490         ttf->kerntables = calloc(ttf->nkern, sizeof(guint8 *));
1491         assert(ttf->kerntables != 0);
1492         memset(ttf->kerntables, 0, ttf->nkern * sizeof(guint8 *));
1493         ttf->kerntype = KT_APPLE_NEW;
1494         ptr = table + 8;
1495         for (i = 0; i < ttf->nkern; i++) {
1496             ttf->kerntables[i] = ptr;
1497             ptr += GetUInt32(ptr, 0, 1);
1498             /* sanity check; there are some fonts that are broken in this regard */
1499             if( ptr > ttf->ptr+ttf->fsize ) {
1500                 free( ttf->kerntables );
1501                 goto badtable;
1502             }
1503         }
1504         return;
1505     }
1506
1507   badtable:
1508     ttf->kerntype = KT_NONE;
1509     ttf->kerntables = NULL;
1510     
1511     return;
1512 }
1513
1514 /* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and
1515  * that x and y elements of the kern array are initialized to zeroes
1516  */
1517 static void KernGlyphsPrim1(TrueTypeFont *ttf, guint16 *glyphs, int nglyphs, int wmode, KernData *kern)
1518 {
1519     fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n");
1520 }
1521
1522 static void KernGlyphsPrim2(TrueTypeFont *ttf, guint16 *glyphs, int nglyphs, int wmode, KernData *kern)
1523 {
1524     int i, j;
1525     guint32 gpair;
1526
1527     for (i = 0; i < nglyphs - 1; i++) {
1528         gpair = (glyphs[i] << 16) | glyphs[i+1];
1529 #ifdef DEBUG2
1530         /* All fonts with MS kern table that I've seen so far contain just one kern subtable.
1531          * MS kern documentation is very poor and I doubt that font developers will be using
1532          * several subtables. I expect them to be using OpenType tables instead.
1533          * According to MS documention, format 2 subtables are not supported by Windows and OS/2.
1534          */
1535         if (ttf->nkern > 1) {
1536             fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern);
1537         }
1538 #endif
1539         for (j = 0; j < ttf->nkern; j++) {
1540             guint16 coverage = GetUInt16(ttf->kerntables[j], 4, 1);
1541             guint8 *ptr;
1542             int npairs;
1543             guint32 t;
1544             int l, r, k;
1545             
1546             if (! ((coverage & 1) ^ wmode)) continue;
1547             if ((coverage & 0xFFFE) != 0) {
1548 #ifdef DEBUG2
1549                 fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage);
1550 #endif
1551                 continue;
1552             }
1553             ptr = ttf->kerntables[j];
1554             npairs = GetUInt16(ptr, 6, 1);
1555             ptr += 14;
1556             l = 0;
1557             r = npairs;
1558             do {
1559                 k = (l + r) >> 1;
1560                 t = GetUInt32(ptr, k * 6, 1);
1561                 if (gpair >= t) l = k + 1;
1562                 if (gpair <= t) r = k - 1;
1563             } while (l <= r);
1564             if (l - r == 2) {
1565                 if (!wmode) {
1566                     kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1));
1567                 } else {
1568                     kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1));
1569                 }
1570                 /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */
1571             }
1572         }
1573     }
1574 }
1575
1576 static void KernGlyphPairPrim1(guint32 nkern, guint8 **kerntables, int upem, int wmode, guint32 a, guint32 b, int *x, int *y)
1577 {
1578     fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n");
1579 }
1580
1581 static void KernGlyphPairPrim2(guint32 nkern, guint8 **kerntables, int upem, int wmode, guint32 a, guint32 b, int *x, int *y)
1582 {
1583     int j;
1584     guint32 gpair;
1585
1586     if (a > 0xFFFF || b > 0xFFFF) return;                   /* 32 bit glyphs are not supported by 'kern' */
1587     gpair = a << 16 | b;
1588
1589     for (j = 0; j < nkern; j++) {
1590         guint16 coverage = GetUInt16(kerntables[j], 4, 1);
1591         guint8 *ptr;
1592         int npairs;
1593         guint32 t;
1594         int l, r, k;
1595             
1596         if (! ((coverage & 1) ^ wmode)) continue;
1597         if ((coverage & 0xFFFE) != 0) {
1598 #ifdef DEBUG2
1599             fprintf(stderr, "KernGlyphPairPrim2: coverage flags are not supported: %04X.\n", coverage);
1600 #endif
1601             continue;
1602         }
1603         ptr = kerntables[j];
1604         npairs = GetUInt16(ptr, 6, 1);
1605         ptr += 14;
1606         l = 0;
1607         r = npairs;
1608         do {
1609             k = (l + r) >> 1;
1610             t = GetUInt32(ptr, k * 6, 1);
1611             if (gpair >= t) l = k + 1;
1612             if (gpair <= t) r = k - 1;
1613         } while (l <= r);
1614         if (l - r == 2) {
1615             if (!wmode) {
1616                 *x = XUnits(upem, GetInt16(ptr, 4 + (l-1) * 6, 1));
1617             } else {
1618                 *y = XUnits(upem, GetInt16(ptr, 4 + (l-1) * 6, 1));
1619             }
1620         }
1621     }
1622 }
1623
1624         
1625 /*- Public functions */ /*FOLD00*/
1626
1627 int CountTTCFonts(const char* fname)
1628 {
1629     int nFonts = 0;
1630     guint8 buffer[12];
1631     int fd = open(fname, O_RDONLY);
1632     if( fd != -1 ) {
1633         if (read(fd, buffer, 12) == 12) {
1634             if(GetUInt32(buffer, 0, 1) == T_ttcf )
1635                 nFonts = GetUInt32(buffer, 8, 1);
1636         }
1637         close(fd);
1638     }
1639     return nFonts;
1640 }
1641
1642
1643 int OpenTTFont(const char *fname, guint32 facenum, TrueTypeFont** ttf)
1644 {
1645     TrueTypeFont *t;
1646     int ret, i, fd = -1;
1647     guint32 version;
1648     guint8 *table, *offset;
1649     guint32 length, tag;
1650     gsize filelength;
1651 #if 0
1652     guint32 tdoffset = 0;               /* offset to TableDirectory in a TTC file. For TTF files is 0 */
1653 #endif
1654
1655     int indexfmt, k;
1656
1657     *ttf = NULL;
1658
1659     if (!fname || !*fname) return SF_BADFILE;
1660
1661     t = calloc(1,sizeof(TrueTypeFont));
1662     assert(t != 0);
1663     t->tag = 0;
1664     t->fname = NULL;
1665     t->fsize = -1;
1666     t->ptr = NULL;
1667     t->nglyphs = 0xFFFFFFFF;
1668
1669 #ifdef USE_GSUB
1670     t->pGSubstitution = 0;
1671 #endif
1672
1673     t->fname = strdup(fname);
1674     assert(t->fname != 0);
1675
1676     if (!g_file_get_contents(t->fname, (gchar **)&t->ptr, &filelength, NULL)) {
1677         ret = SF_FILEIO;
1678         goto cleanup;
1679     }
1680     t->fsize = filelength;
1681
1682     if (t->ptr == NULL) {
1683         ret = SF_MEMORY;
1684         goto cleanup;
1685     }
1686
1687     version = GetInt32(t->ptr, 0, 1);
1688
1689     if ((version == 0x00010000) || (version == T_true)) {
1690         t->tdoffset = 0;
1691     } else if (version == T_ttcf) {                         /*- TrueType collection */
1692         if (GetUInt32(t->ptr, 4, 1) != 0x00010000) {
1693             CloseTTFont(t);
1694             return SF_TTFORMAT;
1695         }
1696         if (facenum >= GetUInt32(t->ptr, 8, 1)) {
1697             CloseTTFont(t);
1698             return SF_FONTNO;
1699         }
1700         t->tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1);
1701     } else {
1702         CloseTTFont(t);
1703         return SF_TTFORMAT;
1704     }
1705
1706 #ifdef DEBUG2
1707     fprintf(stderr, "t->tdoffset: %d\n", t->tdoffset);
1708 #endif
1709
1710     /* magic number */
1711     t->tag = TTFontClassTag;
1712
1713     t->ntables = GetUInt16(t->ptr + t->tdoffset, 4, 1);
1714
1715     t->tables = calloc(NUM_TAGS, sizeof(void *));
1716     assert(t->tables != 0);
1717     t->tlens = calloc(NUM_TAGS, sizeof(guint32));
1718     assert(t->tlens != 0);
1719
1720     memset(t->tables, 0, NUM_TAGS * sizeof(void *));
1721     memset(t->tlens, 0, NUM_TAGS * sizeof(guint32));
1722     
1723
1724     /* parse the tables */
1725     for (i=0; i<t->ntables; i++) {
1726         tag = GetUInt32(t->ptr + t->tdoffset + 12, 16 * i, 1);
1727         offset = t->ptr + GetUInt32(t->ptr + t->tdoffset + 12, 16 * i + 8, 1);
1728         length = GetUInt32(t->ptr + t->tdoffset + 12, 16 * i + 12, 1);
1729         
1730         if (tag == T_maxp) { t->tables[O_maxp] = offset; t->tlens[O_maxp] = length; continue; }
1731         if (tag == T_glyf) { t->tables[O_glyf] = offset; t->tlens[O_glyf] = length; continue; }
1732         if (tag == T_head) { t->tables[O_head] = offset; t->tlens[O_head] = length; continue; }
1733         if (tag == T_loca) { t->tables[O_loca] = offset; t->tlens[O_loca] = length; continue; }
1734         if (tag == T_name) { t->tables[O_name] = offset; t->tlens[O_name] = length; continue; }
1735         if (tag == T_hhea) { t->tables[O_hhea] = offset; t->tlens[O_hhea] = length; continue; }
1736         if (tag == T_hmtx) { t->tables[O_hmtx] = offset; t->tlens[O_hmtx] = length; continue; }
1737         if (tag == T_cmap) { t->tables[O_cmap] = offset; t->tlens[O_cmap] = length; continue; }
1738         if (tag == T_vhea) { t->tables[O_vhea] = offset; t->tlens[O_vhea] = length; continue; }
1739         if (tag == T_vmtx) { t->tables[O_vmtx] = offset; t->tlens[O_vmtx] = length; continue; }
1740         if (tag == T_OS2 ) { t->tables[O_OS2 ] = offset; t->tlens[O_OS2 ] = length; continue; }
1741         if (tag == T_post) { t->tables[O_post] = offset; t->tlens[O_post] = length; continue; }
1742         if (tag == T_kern) { t->tables[O_kern] = offset; t->tlens[O_kern] = length; continue; }
1743         if (tag == T_cvt ) { t->tables[O_cvt ] = offset; t->tlens[O_cvt ] = length; continue; }
1744         if (tag == T_prep) { t->tables[O_prep] = offset; t->tlens[O_prep] = length; continue; }
1745         if (tag == T_fpgm) { t->tables[O_fpgm] = offset; t->tlens[O_fpgm] = length; continue; }
1746         if (tag == T_gsub) { t->tables[O_gsub] = offset; t->tlens[O_gsub] = length; continue; }
1747     }
1748     
1749
1750     /* At this point TrueTypeFont is constructed, now need to verify the font format
1751        and read the basic font properties */
1752
1753     /* The following tables are absolutely required:
1754      * maxp, head, glyf, loca, name, cmap
1755      */
1756
1757     if (!(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_glyf) && getTable(t, O_loca) && getTable(t, O_name) && getTable(t, O_cmap) )) {
1758         CloseTTFont(t);
1759         return SF_TTFORMAT;
1760     }
1761      
1762     table = getTable(t, O_maxp);
1763     t->nglyphs = GetUInt16(table, 4, 1);
1764
1765     table = getTable(t, O_head);
1766     t->unitsPerEm = GetUInt16(table, 18, 1);
1767     indexfmt = GetInt16(table, 50, 1);  
1768
1769     if (!((indexfmt == 0) || indexfmt == 1)) {
1770         CloseTTFont(t);
1771         return SF_TTFORMAT;
1772     }
1773
1774     k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1;
1775     if (k < t->nglyphs) t->nglyphs = k;       /* Hack for broken Chinese fonts */
1776
1777     table = getTable(t, O_loca);
1778
1779     t->goffsets = (guint32 *) calloc(1+t->nglyphs, sizeof(guint32));
1780     assert(t->goffsets != 0);
1781     
1782     for (i = 0; i <= t->nglyphs; i++) {
1783         t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : GetUInt16(table, i << 1, 1) << 1;
1784     }
1785
1786     table = getTable(t, O_hhea);
1787     t->numberOfHMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0;
1788
1789     table = getTable(t, O_vhea);
1790     t->numOfLongVerMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0;
1791
1792     GetNames(t);
1793     FindCmap(t);
1794     GetKern(t);
1795 #ifdef USE_GSUB
1796     ReadGSUB(t,t->tables[O_gsub],0,0);
1797 #endif
1798
1799     *ttf = t;
1800     return SF_OK;
1801
1802   cleanup:
1803     /*- t and t->fname have been allocated! */
1804     free(t->fname);
1805     free(t);
1806     if (fd != -1) close(fd);
1807     return ret;
1808 }
1809
1810
1811
1812 void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/
1813 {
1814     if (ttf->tag != TTFontClassTag) return;
1815
1816     free(ttf->ptr);
1817     free(ttf->fname);
1818     free(ttf->goffsets);
1819     free(ttf->psname);
1820     free(ttf->family);
1821     if( ttf->ufamily )
1822         free( ttf->ufamily );
1823     free(ttf->subfamily);
1824     free(ttf->tables);
1825     free(ttf->tlens);
1826     free(ttf->kerntables);
1827     free(ttf);
1828     return;
1829 }
1830
1831 int GetTTGlyphPoints(TrueTypeFont *ttf, guint32 glyphID, ControlPoint **pointArray)
1832 {
1833     return GetTTGlyphOutline(ttf, glyphID, pointArray, NULL, NULL);
1834 }
1835
1836 #ifdef NO_LIST
1837 static
1838 #endif
1839 int GetTTGlyphComponents(TrueTypeFont *ttf, guint32 glyphID, list glyphlist)
1840 {
1841     guint8 *ptr, *glyf = getTable(ttf, O_glyf);
1842     int n = 1;
1843
1844     if (glyphID >= ttf->nglyphs) return 0;
1845     ptr = glyf + ttf->goffsets[glyphID];
1846
1847     listAppend(glyphlist, (void *) glyphID);
1848
1849     if (GetInt16(ptr, 0, 1) == -1) {
1850         guint16 flags, index;
1851         ptr += 10;
1852         do {
1853             flags = GetUInt16(ptr, 0, 1);
1854             index = GetUInt16(ptr, 2, 1);
1855
1856             ptr += 4;
1857             n += GetTTGlyphComponents(ttf, index, glyphlist);
1858
1859             if (flags & ARG_1_AND_2_ARE_WORDS) {
1860                 ptr += 4;
1861             } else {
1862                 ptr += 2;
1863             }
1864
1865             if (flags & WE_HAVE_A_SCALE) {
1866                 ptr += 2;
1867             } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
1868                 ptr += 4;
1869             } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
1870                 ptr += 8;
1871             }
1872         } while (flags & MORE_COMPONENTS);
1873     }
1874
1875     return n;
1876 }
1877
1878 #ifndef NO_TYPE3
1879 int  CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/
1880                           guint16 *glyphArray, guint8 *encoding, int nGlyphs,
1881                           int wmode)
1882 {
1883     ControlPoint *pa;
1884     PSPathElement *path;
1885     int i, j, r, n;
1886     guint8 *table = getTable(ttf, O_head);
1887     TTGlyphMetrics metrics;
1888     int UPEm = ttf->unitsPerEm;
1889     
1890     const char *h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n";
1891     const char *h02 = "%%%%Creator: %s %s %s\n";
1892     const char *h03 = "%%%%Title: %s\n";
1893     const char *h04 = "%%%%CreationDate: %s\n";
1894     const char *h05 = "%%%%Pages: 0\n";
1895     const char *h06 = "%%%%EndComments\n";
1896     const char *h07 = "%%%%BeginResource: font %s\n";
1897     const char *h08 = "%%%%EndResource\n";
1898     const char *h09 = "%% Original font name: %s\n";
1899
1900     const char *h10 =
1901         "30 dict begin\n"
1902         "/PaintType 0 def\n"
1903         "/FontType 3 def\n"
1904         "/StrokeWidth 0 def\n";
1905
1906     const char *h11 = "/FontName /%s def\n";
1907
1908     /*
1909       const char *h12 = "%/UniqueID %d def\n";
1910     */
1911     const char *h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n";
1912     const char *h14 = "/FontBBox [%d %d %d %d] def\n";
1913
1914     const char *h15=
1915         "/Encoding 256 array def\n"
1916         "    0 1 255 {Encoding exch /.notdef put} for\n";
1917
1918     const char *h16 = "    Encoding %d /glyph%d put\n";
1919     const char *h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n";
1920
1921     const char *h30 = "/CharProcs %d dict def\n";
1922     const char *h31 = "  CharProcs begin\n";
1923     const char *h32 = "    /.notdef {} def\n";
1924     const char *h33 = "    /glyph%d {\n";
1925     const char *h34 = "    } bind def\n";
1926     const char *h35 = "  end\n";
1927
1928     const char *h40 =
1929         "/BuildGlyph {\n"
1930         "  exch /CharProcs get exch\n"
1931         "  2 copy known not\n"
1932         "    {pop /.notdef} if\n"
1933         "  get exec\n"
1934         "} bind def\n"
1935         "/BuildChar {\n"
1936         "  1 index /Encoding get exch get\n"
1937         "  1 index /BuildGlyph get exec\n"
1938         "} bind def\n"
1939         "currentdict end\n";
1940
1941     const char *h41 = "/%s exch definefont pop\n";
1942
1943     
1944     if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM;
1945     if (!glyphArray) return SF_BADARG;
1946     if (!fname) fname = ttf->psname;
1947
1948     fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1));
1949     fprintf(outf, h02, modname, modver, modextra);
1950     fprintf(outf, h03, fname);
1951     fprintf(outf, h04, " ");
1952     fprintf(outf, h05);
1953     fprintf(outf, h06);
1954     fprintf(outf, h07, fname);
1955     fprintf(outf, h09, ttf->psname);
1956
1957     fprintf(outf, h10);
1958     fprintf(outf, h11, fname);
1959 /*    fprintf(outf, h12, 4000000); */
1960
1961     /* XUID generation:
1962      * 103 0 0 C1 C2 C3 C4
1963      * C1 - CRC-32 of the entire source TrueType font
1964      * C2 - number of glyphs in the subset
1965      * C3 - CRC-32 of the glyph array
1966      * C4 - CRC-32 of the encoding array
1967      *
1968      * All CRC-32 numbers are presented as hexadecimal numbers
1969      */
1970
1971     fprintf(outf, h17, crc32(ttf->ptr, ttf->fsize), nGlyphs, crc32(glyphArray, nGlyphs * 2), crc32(encoding, nGlyphs));
1972     fprintf(outf, h13);
1973     fprintf(outf, h14, XUnits(UPEm, GetInt16(table, 36, 1)), XUnits(UPEm, GetInt16(table, 38, 1)), XUnits(UPEm, GetInt16(table, 40, 1)), XUnits(UPEm, GetInt16(table, 42, 1)));
1974     fprintf(outf, h15);
1975
1976     for (i = 0; i < nGlyphs; i++) {
1977         fprintf(outf, h16, encoding[i], i);
1978     }
1979
1980     fprintf(outf, h30, nGlyphs+1);
1981     fprintf(outf, h31);
1982     fprintf(outf, h32);
1983
1984     for (i = 0; i < nGlyphs; i++) {
1985         fprintf(outf, h33, i);
1986         r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0);
1987         
1988         if (r > 0) {
1989             n =  BSplineToPSPath(pa, r, &path);
1990         } else {
1991             n = 0;                      /* glyph might have zero contours but valid metrics ??? */
1992             path = 0;
1993             if (r < 0) {                /* glyph is not present in the font - pa array was not allocated, so no need to free it */
1994                 continue;
1995             }
1996         }
1997         fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n",
1998                 wmode == 0 ? XUnits(UPEm, metrics.aw) : 0,
1999                 wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah),
2000                 XUnits(UPEm, metrics.xMin),
2001                 XUnits(UPEm, metrics.yMin),
2002                 XUnits(UPEm, metrics.xMax),
2003                 XUnits(UPEm, metrics.yMax));
2004         
2005         for (j = 0; j < n; j++) {
2006             switch (path[j].type) {
2007                 case PS_MOVETO:
2008                   fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
2009                   break;
2010
2011                 case PS_LINETO:
2012                   fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
2013                   break;
2014
2015                 case PS_CURVETO:
2016                   fprintf(outf, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3));
2017                   break;
2018
2019                 case PS_CLOSEPATH:
2020                   fprintf(outf, "\tclosepath\n");
2021                   break;
2022             }
2023         }
2024         if (n > 0) fprintf(outf, "\tfill\n");     /* if glyph is not a whitespace character */
2025
2026         fprintf(outf, h34);
2027
2028         free(pa);
2029         free(path);
2030     }
2031     fprintf(outf, h35);
2032
2033     fprintf(outf, h40);
2034     fprintf(outf, h41, fname);
2035
2036     fprintf(outf, h08);
2037     return SF_OK;
2038 }
2039 #endif
2040
2041 #ifndef NO_TTCR
2042 int  CreateTTFromTTGlyphs(TrueTypeFont  *ttf,
2043                           const char    *fname,
2044                           guint16        *glyphArray,
2045                           guint8          *encoding,
2046                           int            nGlyphs,
2047                           int            nNameRecs,
2048                           NameRecord    *nr,
2049                           guint32        flags)
2050 {
2051     TrueTypeCreator *ttcr;
2052     TrueTypeTable *head = NULL, *hhea = NULL, *maxp = NULL, *cvt = NULL, *prep = NULL, *glyf = NULL, *fpgm = NULL, *cmap = NULL, *name = NULL, *post = NULL, *os2 = NULL;
2053     guint8 *p;
2054     int i;
2055     int res;
2056     guint32 *gID;
2057
2058     TrueTypeCreatorNewEmpty(T_true, &ttcr);
2059
2060     /**                       name                         **/
2061
2062     if (flags & TTCF_AutoName) {
2063         /* not implemented yet
2064            NameRecord *names;
2065            NameRecord newname;
2066            int n = GetTTNameRecords(ttf, &names);
2067            int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
2068            guint8 *cp1;
2069            guint8 suffix[32];
2070            guint32 c1 = crc32(glyphArray, nGlyphs * 2);
2071            guint32 c2 = crc32(encoding, nGlyphs);
2072            int len;
2073            snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs);
2074         
2075            name = TrueTypeTableNew_name(0, 0);
2076            for (i = 0; i < n; i++) {
2077            if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) {
2078
2079            memcpy(newname, names+i, sizeof(NameRecord));
2080            newname.slen = name[i].slen + strlen(suffix);
2081         */
2082         const guint8 ptr[] = {0,'T',0,'r',0,'u',0,'e',0,'T',0,'y',0,'p',0,'e',0,'S',0,'u',0,'b',0,'s',0,'e',0,'t'};
2083         NameRecord n1 = {1, 0, 0, 6, 14, (guint8 *) "TrueTypeSubset"};
2084         NameRecord n2 = {3, 1, 1033, 6, 28, NULL};
2085         n2.sptr = (guint8 *) ptr;
2086         name = TrueTypeTableNew_name(0, NULL);
2087         nameAdd(name, &n1);
2088         nameAdd(name, &n2);
2089     } else {
2090         if (nNameRecs == 0) {
2091             NameRecord *names;
2092             int n = GetTTNameRecords(ttf, &names);
2093             name = TrueTypeTableNew_name(n, names);
2094             DisposeNameRecords(names, n);
2095         } else {
2096             name = TrueTypeTableNew_name(nNameRecs, nr);
2097         }
2098     }
2099
2100     /**                       maxp                         **/
2101     maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
2102
2103     /**                       hhea                         **/
2104     p = getTable(ttf, O_hhea);
2105     if (p) {
2106         hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
2107     } else {
2108         hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2109     }
2110
2111     /**                       head                         **/
2112
2113     p = getTable(ttf, O_head);
2114     assert(p != 0);
2115     head = TrueTypeTableNew_head(GetUInt32(p, 4, 1),
2116                                  GetUInt16(p, 16, 1),
2117                                  GetUInt16(p, 18, 1),
2118                                  p+20,
2119                                  GetUInt16(p, 44, 1),
2120                                  GetUInt16(p, 46, 1),
2121                                  GetInt16(p, 48, 1));
2122
2123
2124     /**                       glyf                          **/
2125
2126     glyf = TrueTypeTableNew_glyf();
2127     gID = scalloc(nGlyphs, sizeof(guint32));
2128     
2129     for (i = 0; i < nGlyphs; i++) {
2130         gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
2131     }
2132         
2133
2134     /**                       cmap                          **/
2135     cmap = TrueTypeTableNew_cmap();
2136
2137     for (i=0; i < nGlyphs; i++) {
2138         cmapAdd(cmap, 0x0100, encoding[i], gID[i]);
2139     }
2140
2141     /**                       cvt                           **/
2142     if ((p = getTable(ttf, O_cvt)) != 0) {
2143         cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
2144     }
2145
2146     /**                       prep                          **/
2147     if ((p = getTable(ttf, O_prep)) != 0) {
2148         prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
2149     }
2150
2151     /**                       fpgm                          **/
2152     if ((p = getTable(ttf, O_fpgm)) != 0) {
2153         fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
2154     }
2155
2156     /**                       post                          **/
2157     if ((p = getTable(ttf, O_post)) != 0) {
2158         post = TrueTypeTableNew_post(0x00030000,
2159                                      GetUInt32(p, 4, 1),
2160                                      GetUInt16(p, 8, 1),
2161                                      GetUInt16(p, 10, 1),
2162                                      GetUInt16(p, 12, 1));
2163     } else {
2164         post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
2165     }
2166
2167     if (flags & TTCF_IncludeOS2) {
2168         if ((p = getTable(ttf, O_OS2)) != 0) {
2169             os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p);
2170         }
2171     }
2172
2173     AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea);
2174     AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap);
2175     AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm);
2176     AddTable(ttcr, post); AddTable(ttcr, os2);
2177     
2178     if ((res = StreamToFile(ttcr, fname)) != SF_OK) {
2179 #ifdef DEBUG
2180         fprintf(stderr, "StreamToFile: error code: %d.\n", res);
2181 #endif
2182     }
2183
2184     TrueTypeCreatorDispose(ttcr);
2185     free(gID);
2186
2187     return res;
2188 }
2189
2190
2191 // THE SAME, BUT TO MEMORY
2192
2193 int  CreateTTFromTTGlyphs_tomemory
2194                          (TrueTypeFont  *ttf,
2195                           guint8        **out_buf,
2196                           guint32       *out_len,
2197                           guint16        *glyphArray,
2198                           guint8          *encoding,
2199                           int            nGlyphs,
2200                           int            nNameRecs,
2201                           NameRecord    *nr,
2202                           guint32        flags)
2203 {
2204     TrueTypeCreator *ttcr;
2205     TrueTypeTable *head = NULL, *hhea = NULL, *maxp = NULL, *cvt = NULL, *prep = NULL, *glyf = NULL, *fpgm = NULL, *cmap = NULL, *name = NULL, *post = NULL, *os2 = NULL;
2206     guint8 *p;
2207     int i;
2208     int res;
2209     guint32 *gID;
2210
2211     TrueTypeCreatorNewEmpty(T_true, &ttcr);
2212
2213     /**                       name                         **/
2214
2215     if (flags & TTCF_AutoName) {
2216         /* not implemented yet
2217            NameRecord *names;
2218            NameRecord newname;
2219            int n = GetTTNameRecords(ttf, &names);
2220            int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
2221            guint8 *cp1;
2222            guint8 suffix[32];
2223            guint32 c1 = crc32(glyphArray, nGlyphs * 2);
2224            guint32 c2 = crc32(encoding, nGlyphs);
2225            int len;
2226            snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs);
2227         
2228            name = TrueTypeTableNew_name(0, 0);
2229            for (i = 0; i < n; i++) {
2230            if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) {
2231
2232            memcpy(newname, names+i, sizeof(NameRecord));
2233            newname.slen = name[i].slen + strlen(suffix);
2234         */
2235         const guint8 ptr[] = {0,'T',0,'r',0,'u',0,'e',0,'T',0,'y',0,'p',0,'e',0,'S',0,'u',0,'b',0,'s',0,'e',0,'t'};
2236         NameRecord n1 = {1, 0, 0, 6, 14, (guint8 *) "TrueTypeSubset"};
2237         NameRecord n2 = {3, 1, 1033, 6, 28, NULL};
2238         n2.sptr = (guint8 *) ptr;
2239         name = TrueTypeTableNew_name(0, NULL);
2240         nameAdd(name, &n1);
2241         nameAdd(name, &n2);
2242     } else {
2243         if (nNameRecs == 0) {
2244             NameRecord *names;
2245             int n = GetTTNameRecords(ttf, &names);
2246             name = TrueTypeTableNew_name(n, names);
2247             DisposeNameRecords(names, n);
2248         } else {
2249             name = TrueTypeTableNew_name(nNameRecs, nr);
2250         }
2251     }
2252
2253     /**                       maxp                         **/
2254     maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
2255
2256     /**                       hhea                         **/
2257     p = getTable(ttf, O_hhea);
2258     if (p) {
2259         hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
2260     } else {
2261         hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2262     }
2263
2264     /**                       head                         **/
2265
2266     p = getTable(ttf, O_head);
2267     assert(p != 0);
2268     head = TrueTypeTableNew_head(GetUInt32(p, 4, 1),
2269                                  GetUInt16(p, 16, 1),
2270                                  GetUInt16(p, 18, 1),
2271                                  p+20,
2272                                  GetUInt16(p, 44, 1),
2273                                  GetUInt16(p, 46, 1),
2274                                  GetInt16(p, 48, 1));
2275
2276
2277     /**                       glyf                          **/
2278
2279     glyf = TrueTypeTableNew_glyf();
2280     gID = scalloc(nGlyphs, sizeof(guint32));
2281     
2282     for (i = 0; i < nGlyphs; i++) {
2283         gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
2284     }
2285         
2286
2287     /**                       cmap                          **/
2288     cmap = TrueTypeTableNew_cmap();
2289
2290     for (i=0; i < nGlyphs; i++) {
2291         cmapAdd(cmap, 0x0100, encoding[i], gID[i]);
2292     }
2293
2294     /**                       cvt                           **/
2295     if ((p = getTable(ttf, O_cvt)) != 0) {
2296         cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
2297     }
2298
2299     /**                       prep                          **/
2300     if ((p = getTable(ttf, O_prep)) != 0) {
2301         prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
2302     }
2303
2304     /**                       fpgm                          **/
2305     if ((p = getTable(ttf, O_fpgm)) != 0) {
2306         fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
2307     }
2308
2309     /**                       post                          **/
2310     if ((p = getTable(ttf, O_post)) != 0) {
2311         post = TrueTypeTableNew_post(0x00030000,
2312                                      GetUInt32(p, 4, 1),
2313                                      GetUInt16(p, 8, 1),
2314                                      GetUInt16(p, 10, 1),
2315                                      GetUInt16(p, 12, 1));
2316     } else {
2317         post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
2318     }
2319
2320     if (flags & TTCF_IncludeOS2) {
2321         if ((p = getTable(ttf, O_OS2)) != 0) {
2322             os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p);
2323         }
2324     }
2325
2326     AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea);
2327     AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap);
2328     AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm);
2329     AddTable(ttcr, post); AddTable(ttcr, os2);
2330     
2331     if ((res = StreamToMemory(ttcr, out_buf, out_len)) != SF_OK) {
2332 #ifdef DEBUG
2333         fprintf(stderr, "StreamToMemory: error code: %d.\n", res);
2334 #endif
2335     }
2336
2337     TrueTypeCreatorDispose(ttcr);
2338     free(gID);
2339
2340     return res;
2341 }
2342
2343
2344 #endif
2345
2346
2347 #ifndef NO_TYPE42
2348 static GlyphOffsets *GlyphOffsetsNew(guint8 *sfntP)
2349 {
2350     GlyphOffsets *res = smalloc(sizeof(GlyphOffsets));
2351     guint16 i, numTables = GetUInt16(sfntP, 4, 1);
2352     guint32 locaLen = 0;
2353     gint16 indexToLocFormat = 1;
2354     guint8 *loca = sfntP + 12 + 16*numTables;
2355
2356     for (i = 0; i < numTables; i++) {
2357         guint32 tag = GetUInt32(sfntP + 12, 16 * i, 1);
2358         guint32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1);
2359         guint32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1);
2360
2361         if (tag == T_loca) {
2362             loca = sfntP + off;
2363             locaLen = len;
2364         } else if (tag == T_head) {
2365             indexToLocFormat = GetInt16(sfntP + off, 50, 1);
2366         }
2367     }
2368
2369     res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2);
2370     assert(res->nGlyphs != 0);
2371     res->offs = scalloc(res->nGlyphs, sizeof(guint32));
2372
2373     for (i = 0; i < res->nGlyphs; i++) {
2374         if (indexToLocFormat == 1) {
2375             res->offs[i] = GetUInt32(loca, i * 4, 1);
2376         } else {
2377             res->offs[i] = GetUInt16(loca, i * 2, 1) << 1;
2378         }
2379     }
2380     return res;
2381 }
2382
2383 static void GlyphOffsetsDispose(GlyphOffsets *_this)
2384 {
2385     if (_this) {
2386         free(_this->offs);
2387         free(_this);
2388     }
2389 }
2390
2391 static void DumpSfnts(FILE *outf, guint8 *sfntP)
2392 {
2393     HexFmt *h = HexFmtNew(outf);
2394     guint16 i, numTables = GetUInt16(sfntP, 4, 1);
2395     guint32 j, *offs, *len;
2396     GlyphOffsets *go = GlyphOffsetsNew(sfntP);
2397     guint8 pad[] = {0,0,0,0};                     /* zeroes                       */
2398
2399     assert(numTables <= 9);                                 /* Type42 has 9 required tables */
2400
2401     offs = scalloc(numTables, sizeof(guint32));
2402     len = scalloc(numTables, sizeof(guint32));
2403
2404     fputs("/sfnts [", outf);
2405     HexFmtOpenString(h);
2406     HexFmtBlockWrite(h, sfntP, 12);                         /* stream out the Offset Table    */
2407     HexFmtBlockWrite(h, sfntP+12, 16 * numTables);          /* stream out the Table Directory */
2408
2409     for (i=0; i<numTables; i++) {
2410         guint32 tag = GetUInt32(sfntP + 12, 16 * i, 1);
2411         guint32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1);
2412         guint32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1);
2413
2414         if (tag != T_glyf) {
2415             HexFmtBlockWrite(h, sfntP + off, len);
2416         } else {
2417             guint8 *glyf = sfntP + off;
2418             guint32 o, l;
2419             for (j = 0; j < go->nGlyphs - 1; j++) {
2420                 o = go->offs[j];
2421                 l = go->offs[j + 1] - o;
2422                 HexFmtBlockWrite(h, glyf + o, l);
2423             }
2424         }
2425         HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3);
2426     }
2427     HexFmtCloseString(h);
2428     fputs("] def\n", outf);
2429     GlyphOffsetsDispose(go);
2430     HexFmtDispose(h);
2431     free(offs);
2432     free(len);
2433 }
2434
2435 int  CreateT42FromTTGlyphs(TrueTypeFont  *ttf,
2436                            FILE          *outf,
2437                            const char    *psname,
2438                            guint16        *glyphArray,
2439                            guint8          *encoding,
2440                            int            nGlyphs)
2441 {
2442     TrueTypeCreator *ttcr;
2443     TrueTypeTable *head = NULL, *hhea = NULL, *maxp = NULL, *cvt = NULL, *prep = NULL, *glyf = NULL, *fpgm = NULL;
2444     guint8 *p;
2445     int i;
2446     int res;
2447
2448     guint32 ver, rev;
2449     guint8 *headP;
2450
2451     guint8 *sfntP;
2452     guint32 sfntLen;
2453     int UPEm = ttf->unitsPerEm;
2454
2455     guint16 *gID;
2456
2457     /*
2458     if (nGlyphs >= 256) return SF_GLYPHNUM;
2459     */
2460     
2461     assert(psname != 0);
2462
2463     TrueTypeCreatorNewEmpty(T_true, &ttcr);
2464
2465     /*                        head                          */
2466     headP = p = getTable(ttf, O_head);
2467     assert(p != 0);
2468     head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), GetUInt16(p, 16, 1), GetUInt16(p, 18, 1), p+20, GetUInt16(p, 44, 1), GetUInt16(p, 46, 1), GetInt16(p, 48, 1));
2469     ver = GetUInt32(p, 0, 1);
2470     rev = GetUInt32(p, 4, 1);
2471
2472     /**                       hhea                         **/
2473     p = getTable(ttf, O_hhea);
2474     if (p) {
2475         hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
2476     } else {
2477         hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2478     }
2479
2480     /**                       maxp                         **/
2481     maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
2482     
2483     /**                       cvt                           **/
2484     if ((p = getTable(ttf, O_cvt)) != 0) {
2485         cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
2486     }
2487
2488     /**                       prep                          **/
2489     if ((p = getTable(ttf, O_prep)) != 0) {
2490         prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
2491     }
2492
2493     /**                       fpgm                          **/
2494     if ((p = getTable(ttf, O_fpgm)) != 0) {
2495         fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
2496     }
2497
2498     /**                       glyf                          **/
2499     glyf = TrueTypeTableNew_glyf();
2500     gID = scalloc(nGlyphs, sizeof(guint32));
2501     
2502     for (i = 0; i < nGlyphs; i++) {
2503         gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
2504     }
2505
2506     AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt);
2507     AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm);
2508
2509     if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) {
2510         TrueTypeCreatorDispose(ttcr);
2511         free(gID);
2512         return res;
2513     }
2514
2515     fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", ver>>16, ver & 0xFFFF, rev>>16, rev & 0xFFFF);
2516     fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra);
2517     fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname);
2518     fprintf(outf, "%%- Original font name: %s\n", ttf->psname);
2519     fprintf(outf, "%%- Original font family: %s\n", ttf->family);
2520     fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily);
2521     fprintf(outf, "11 dict begin\n");
2522     fprintf(outf, "/FontName /%s def\n", psname);
2523     fprintf(outf, "/PaintType 0 def\n");
2524     fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n");
2525     fprintf(outf, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, 36, 1)), XUnits(UPEm, GetInt16(headP, 38, 1)), XUnits(UPEm, GetInt16(headP, 40, 1)), XUnits(UPEm, GetInt16(headP, 42, 1)));
2526     fprintf(outf, "/FontType 42 def\n");
2527     fprintf(outf, "/Encoding 256 array def\n");
2528     fprintf(outf, "    0 1 255 {Encoding exch /.notdef put} for\n");
2529
2530     for (i = 1; i<nGlyphs; i++) {
2531         fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]);
2532     }
2533     fprintf(outf, "/XUID [103 0 1 16#%08X %d 16#%08X 16#%08X] def\n", crc32(ttf->ptr, ttf->fsize), nGlyphs, crc32(glyphArray, nGlyphs * 2), crc32(encoding, nGlyphs));
2534
2535     DumpSfnts(outf, sfntP);
2536     /* dump charstrings */
2537     fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs);
2538     fprintf(outf, "/.notdef 0 def\n");
2539     for (i = 1; i < glyfCount(glyf); i++) {
2540         fprintf(outf,"/glyph%d %d def\n", i, i);
2541     }
2542     fprintf(outf, "end readonly def\n");
2543
2544     fprintf(outf, "FontName currentdict end definefont pop\n");
2545     TrueTypeCreatorDispose(ttcr);
2546     free(gID);
2547     free(sfntP);
2548     return SF_OK;
2549 }
2550 #endif
2551     
2552
2553 #ifndef NO_MAPPERS
2554 #ifdef USE_GSUB
2555 int MapString(TrueTypeFont *ttf, guint16 *str, int nchars, guint16 *glyphArray, int bvertical)
2556 #else
2557 int MapString(TrueTypeFont *ttf, guint16 *str, int nchars, guint16 *glyphArray)
2558 #endif
2559 {
2560     int i;
2561     guint16 *cp;
2562
2563     if (ttf->cmapType == CMAP_NOT_USABLE ) return -1;
2564     if (!nchars) return 0;
2565
2566     if (glyphArray == 0) {
2567         cp = str;
2568     } else {
2569         cp = glyphArray;
2570     }
2571
2572     switch (ttf->cmapType) {
2573         case CMAP_MS_Symbol:
2574             if( ttf->mapper == getGlyph0 ) {
2575                 guint16 aChar;
2576                 for( i = 0; i < nchars; i++ ) {
2577                     aChar = str[i];
2578                     if( ( aChar & 0xf000 ) == 0xf000 ) {
2579                         aChar &= 0x00ff;
2580                     }
2581                     cp[i] = aChar;
2582                 }
2583             }
2584             else if( glyphArray )
2585                 memcpy(glyphArray, str, nchars * 2);
2586             break;
2587
2588         case CMAP_MS_Unicode:
2589             if (glyphArray != 0) {
2590                 memcpy(glyphArray, str, nchars * 2);
2591             }
2592             break;
2593         
2594         case CMAP_MS_ShiftJIS:  TranslateString12(str, cp, nchars); break;
2595         case CMAP_MS_Big5:      TranslateString13(str, cp, nchars); break;
2596         case CMAP_MS_PRC:       TranslateString14(str, cp, nchars); break;
2597         case CMAP_MS_Wansung:   TranslateString15(str, cp, nchars); break;
2598         case CMAP_MS_Johab:     TranslateString16(str, cp, nchars); break;
2599     }
2600
2601     for (i = 0; i < nchars; i++) {
2602         cp[i] = ttf->mapper(ttf->cmap, cp[i]);
2603 #ifdef USE_GSUB
2604         if (cp[i]!=0 && bvertical!=0)
2605             cp[i] = UseGSUB(ttf,cp[i],bvertical);
2606 #endif
2607     }
2608     return nchars;
2609 }
2610 #ifdef USE_GSUB
2611 guint16 MapChar(TrueTypeFont *ttf, guint16 ch, int bvertical)
2612 #else
2613 guint16 MapChar(TrueTypeFont *ttf, guint16 ch)
2614 #endif
2615
2616 {
2617     switch (ttf->cmapType) {
2618       case CMAP_MS_Symbol:
2619         if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 ) {
2620             ch &= 0x00ff;
2621         }
2622         return ttf->mapper(ttf->cmap, ch );
2623
2624         case CMAP_MS_Unicode:   break;
2625         case CMAP_MS_ShiftJIS:  ch = TranslateChar12(ch); break;
2626         case CMAP_MS_Big5:      ch = TranslateChar13(ch); break;
2627         case CMAP_MS_PRC:       ch = TranslateChar14(ch); break;
2628         case CMAP_MS_Wansung:   ch = TranslateChar15(ch); break;
2629         case CMAP_MS_Johab:     ch = TranslateChar16(ch); break;
2630         default:                return 0;
2631     }
2632     ch = ttf->mapper(ttf->cmap, ch);
2633 #ifdef USE_GSUB
2634     if (ch != 0 && bvertical != 0) {
2635         ch = UseGSUB(ttf,ch,bvertical);
2636     }
2637 #endif
2638     return ch;
2639 }
2640 #endif
2641
2642 void GetTTGlyphMetrics(TrueTypeFont *ttf, guint32 glyphID, TTGlyphMetrics *metrics)
2643 {
2644     GetMetrics(ttf, glyphID, metrics);
2645 }
2646     
2647 TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, guint16 *glyphArray, int nGlyphs, int mode)
2648 {
2649     guint8 *table;
2650     TTSimpleGlyphMetrics *res;
2651     int i;
2652     guint16 glyphID;
2653     int n;
2654     int UPEm = ttf->unitsPerEm;
2655
2656     if (mode == 0) {
2657         table = getTable(ttf, O_hmtx);
2658         n = ttf->numberOfHMetrics;
2659     } else {
2660         table = getTable(ttf, O_vmtx);
2661         n = ttf->numOfLongVerMetrics;
2662     }
2663
2664     if (!nGlyphs || !glyphArray) return NULL;        /* invalid parameters */
2665     if (!n || !table) return NULL;                   /* the font does not contain the requested metrics */
2666     
2667     res = calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics));
2668     assert(res != 0);
2669         
2670     for (i=0; i<nGlyphs; i++) {
2671         glyphID = glyphArray[i];
2672
2673         if (glyphID < n) {
2674             res[i].adv = XUnits(UPEm, GetUInt16(table, 4 * glyphID, 1));
2675             res[i].sb  = XUnits(UPEm, GetInt16(table, 4 * glyphID + 2, 1));
2676         } else {
2677             res[i].adv = XUnits(UPEm, GetUInt16(table, 4 * (n - 1), 1));
2678             if( glyphID-n < ttf->nglyphs ) {
2679                 res[i].sb = XUnits(UPEm, GetInt16(table + n * 4, (glyphID - n) * 2, 1));
2680             } else {                              /* font is broken */
2681                 res[i].sb = XUnits(UPEm, GetInt16(table, 4*(n-1) + 2, 1));
2682             }
2683         }
2684     }
2685     
2686     return res;
2687 }
2688
2689 #ifndef NO_MAPPERS
2690 TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, guint16 firstChar, int nChars, int mode)
2691 {
2692     TTSimpleGlyphMetrics *res = 0;
2693     guint16 *str;
2694     int i, n;
2695
2696     str = malloc(nChars * 2);
2697     assert(str != 0);
2698
2699     for (i=0; i<nChars; i++) str[i] = firstChar + i;
2700
2701     if ((n = MapString(ttf, str, nChars, 0
2702 #ifdef USE_GSUB
2703                        , mode
2704 #endif
2705                       )) != -1) {
2706
2707         res = GetTTSimpleGlyphMetrics(ttf, str, n, mode);
2708     }
2709
2710     free(str);
2711
2712     return res;
2713 }
2714 #endif
2715
2716 void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info)
2717 {
2718     guint8 *table;
2719     int UPEm = ttf->unitsPerEm;
2720
2721     memset(info, 0, sizeof(TTGlobalFontInfo));
2722     
2723     info->family = ttf->family;
2724     info->ufamily = ttf->ufamily;
2725     info->subfamily = ttf->subfamily;
2726     info->psname = ttf->psname;
2727     info->symbolEncoded = ttf->cmapType == CMAP_MS_Symbol ? 1 : 0;
2728
2729     table = getTable(ttf, O_OS2);
2730     if (table) {
2731         info->weight = GetUInt16(table, 4, 1);
2732         info->width  = GetUInt16(table, 6, 1);
2733         info->fsSelection = GetUInt16(table, 62, 1);
2734
2735         /* There are 3 different versions of OS/2 table: original (68 bytes long),
2736          * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,)
2737          * Apple's documentation recommends looking at the table length.
2738          */
2739         if (getTableSize(ttf, O_OS2) > 68) {
2740             info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1));
2741             info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1));
2742             info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1));
2743             info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1));
2744             info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1));
2745         }
2746         if (ttf->cmapType == CMAP_MS_Unicode) {
2747             info->rangeFlag = 1;
2748             info->ur1 = GetUInt32(table, 42, 1);
2749             info->ur2 = GetUInt32(table, 46, 1);
2750             info->ur3 = GetUInt32(table, 50, 1);
2751             info->ur4 = GetUInt32(table, 54, 1);
2752         }
2753         memcpy(info->panose, table + 32, 10);
2754         info->typeFlags = GetUInt16( table, 8, 1 );
2755     }
2756
2757
2758     table = getTable(ttf, O_post);
2759     if (table) {
2760         info->pitch  = GetUInt32(table, 12, 1);
2761         info->italicAngle = GetInt32(table, 4, 1);
2762     }
2763
2764     table = getTable(ttf, O_head);      /* 'head' tables is always there */
2765     info->xMin = XUnits(UPEm, GetInt16(table, 36, 1));
2766     info->yMin = XUnits(UPEm, GetInt16(table, 38, 1));
2767     info->xMax = XUnits(UPEm, GetInt16(table, 40, 1));
2768     info->yMax = XUnits(UPEm, GetInt16(table, 42, 1));
2769
2770     table = getTable(ttf, O_hhea);
2771     if (table) {
2772         info->ascender  = XUnits(UPEm, GetInt16(table, 4, 1));
2773         info->descender = XUnits(UPEm, GetInt16(table, 6, 1));
2774         info->linegap   = XUnits(UPEm, GetInt16(table, 8, 1));
2775     }
2776
2777     table = getTable(ttf, O_vhea);
2778     if (table) {
2779         info->vascent  = XUnits(UPEm, GetInt16(table, 4, 1));
2780         info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1));
2781     }
2782 }
2783
2784 #if 0
2785
2786 guint8 *ExtractCmap(TrueTypeFont *ttf)
2787 {
2788     guint8 *ptr = 0;
2789     guint32 s;
2790
2791     if ((s = getTableSize(ttf, O_cmap)) != 0) {
2792         ptr = smalloc(s);
2793         memcpy(ptr, getTable(ttf, O_cmap), s);
2794     }
2795
2796     return ptr;
2797 }
2798
2799 #endif
2800
2801 guint8 *ExtractTable(TrueTypeFont *ttf, guint32 tag)
2802 {
2803     guint8 *ptr = NULL;
2804     int o = tagToOrd(tag);
2805     guint32 s;
2806
2807     if (o != 0xFFFFFFFF) {                        /* Tag is one of the predefined tags */
2808         if ((s = getTableSize(ttf, o)) != 0) {
2809             ptr = smalloc(s);
2810             memcpy(ptr, getTable(ttf, o), s);
2811         }
2812     } else {                                      /* Need to do everything by hand */
2813         int i;
2814         guint32 t;
2815         
2816         for (i=0; i<ttf->ntables; i++) {
2817             guint8 *table;
2818             
2819             t = GetUInt32(ttf->ptr + ttf->tdoffset + 12, 16 * i, 1);
2820             if (t == tag) {
2821                 table = ttf->ptr + GetUInt32(ttf->ptr + ttf->tdoffset + 12, 16 * i + 8, 1);
2822                 s = GetUInt32(ttf->ptr + ttf->tdoffset + 12, 16 * i + 12, 1);
2823
2824                 ptr = smalloc(s);
2825                 memcpy(ptr, table, s);
2826                 break;
2827             }
2828         }
2829     }
2830
2831     return ptr;
2832 }
2833
2834 const guint8 *GetTable(TrueTypeFont *ttf, guint32 tag)
2835 {
2836     guint8 *ptr = NULL;
2837     int o = tagToOrd(tag);
2838     guint32 s;
2839
2840     if (o != 0xFFFFFFFF) {                        /* Tag is one of the predefined tags */
2841         if ((s = getTableSize(ttf, o)) != 0) {
2842             ptr = getTable(ttf, o);
2843         }
2844     } else {                                      /* Need to do everything by hand */
2845         int i;
2846         guint32 t;
2847         
2848         for (i=0; i<ttf->ntables; i++) {
2849             t = GetUInt32(ttf->ptr + ttf->tdoffset + 12, 16 * i, 1);
2850             if (t == tag) {
2851                 ptr = ttf->ptr + GetUInt32(ttf->ptr + ttf->tdoffset + 12, 16 * i + 8, 1);
2852                 break;
2853             }
2854         }
2855     }
2856
2857     return ptr;
2858 }
2859
2860
2861 void KernGlyphs(TrueTypeFont *ttf, guint16 *glyphs, int nglyphs, int wmode, KernData *kern)
2862 {
2863     int i;
2864     
2865     if (!nglyphs || !glyphs || !kern) return;
2866
2867     for (i = 0; i < nglyphs-1; i++) kern[i].x = kern[i].y = 0;
2868     
2869     switch (ttf->kerntype) {
2870       case KT_APPLE_NEW: KernGlyphsPrim1(ttf, glyphs, nglyphs, wmode, kern);    return;
2871       case KT_MICROSOFT: KernGlyphsPrim2(ttf, glyphs, nglyphs, wmode, kern);    return;
2872       default: return;
2873     }
2874 }
2875
2876 GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, guint32 glyphID)
2877 {
2878     guint8 *glyf = getTable(ttf, O_glyf);
2879     guint8 *hmtx = getTable(ttf, O_hmtx);
2880     guint8 *ptr;
2881     guint32 length;
2882     GlyphData *d;
2883     ControlPoint *cp;
2884     int i, n, m;
2885
2886     if (glyphID >= ttf->nglyphs) return NULL;
2887
2888     ptr = glyf + ttf->goffsets[glyphID];
2889     length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
2890
2891     d = malloc(sizeof(GlyphData)); assert(d != 0);
2892
2893     if (length) {
2894         d->ptr = malloc((length + 1) & ~1); assert(d->ptr != 0);
2895         memcpy(d->ptr, ptr, length);
2896         if (GetInt16(ptr, 0, 1) >= 0) {
2897             d->compflag = 0;
2898         } else {
2899             d->compflag = 1;
2900         }
2901     } else {
2902         d->ptr = NULL;
2903         d->compflag = 0;
2904     }
2905
2906     d->glyphID = glyphID;
2907     d->nbytes = (length + 1) & ~1;
2908
2909     /* now calculate npoints and ncontours */
2910     n = GetTTGlyphPoints(ttf, glyphID, &cp);
2911     if (n != -1) {
2912         m = 0;
2913         for (i = 0; i < n; i++) {
2914             if (cp[i].flags & 0x8000) m++;
2915         }
2916         d->npoints = n;
2917         d->ncontours = m;
2918         free(cp);
2919     } else {
2920         d->npoints = 0;
2921         d->ncontours = 0;
2922     }
2923
2924     /* get adwance width and left sidebearing */
2925     if (glyphID < ttf->numberOfHMetrics) {
2926         d->aw = GetUInt16(hmtx, 4 * glyphID, 1);
2927         d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1);
2928     } else {
2929         d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1);
2930         d->lsb  = GetInt16(hmtx + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1);
2931     }
2932
2933     return d;
2934 }
2935
2936 int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr)
2937 {
2938     guint8 *table = getTable(ttf, O_name);
2939     guint16 n = GetUInt16(table, 2, 1);
2940     NameRecord *rec;
2941     guint16 i;
2942
2943     *nr = NULL;
2944     if (n == 0) return 0;
2945
2946     rec = calloc(n, sizeof(NameRecord));
2947
2948     for (i = 0; i < n; i++) {
2949         rec[i].platformID = GetUInt16(table + 6, 12 * i, 1);
2950         rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1);
2951         rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1);
2952         rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1);
2953         rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1);
2954         if (rec[i].slen) {
2955             rec[i].sptr = (guint8 *) malloc(rec[i].slen); assert(rec[i].sptr != 0);
2956             memcpy(rec[i].sptr, table + GetUInt16(table, 4, 1) + GetUInt16(table + 6, 10 + 12 * i, 1), rec[i].slen);
2957         } else {
2958             rec[i].sptr = NULL;
2959         }
2960     }
2961
2962     *nr = rec;
2963     return n;
2964 }
2965
2966 void DisposeNameRecords(NameRecord* nr, int n)
2967 {
2968     int i;
2969     for (i = 0; i < n; i++) {
2970         if (nr[i].sptr) free(nr[i].sptr);
2971     }
2972     free(nr);
2973 }
2974
2975 // int ExtractSimpleGlyphMetrics(guint8 *table, int numberOfMetrics, int nglyphs, int UPEm
2976
2977 TTFullSimpleGlyphMetrics *ReadGlyphMetrics(guint8 *hmtx, guint8 *vmtx, int hcount, int vcount, int gcount, int UPEm, guint16 *glyphArray, int nGlyphs)
2978 {
2979     TTFullSimpleGlyphMetrics *res;
2980     guint16 glyphID;
2981     int i;
2982
2983     if (!nGlyphs || !glyphArray) return NULL;        /* invalid parameters */
2984
2985     //printf("ReadGlyphMetrics: hmtx: %x, vmtx: %x, hcount: %d, vcount: %d\n", hmtx, vmtx, hcount, vcount);
2986
2987     res = calloc(nGlyphs, sizeof(TTFullSimpleGlyphMetrics)); assert(res != 0);
2988     for (i = 0; i < nGlyphs; i++) {
2989         glyphID = glyphArray[i];
2990
2991         res[i].aw = res[i].ah = res[i].lsb = res[i].tsb = 0;
2992
2993         /* horizontal metrics */
2994         if (hmtx != 0 && hcount > 0) {
2995
2996             if (glyphID < hcount) {
2997                 res[i].aw = XUnits(UPEm, GetUInt16(hmtx, 4 * glyphID, 1));
2998                 res[i].lsb  = XUnits(UPEm, GetInt16(hmtx, 4 * glyphID + 2, 1));
2999             } else {
3000                 res[i].aw = XUnits(UPEm, GetUInt16(hmtx, 4 * (hcount - 1), 1));
3001                 if( glyphID-hcount < gcount ) {
3002                     res[i].lsb = XUnits(UPEm, GetInt16(hmtx + hcount * 4, (glyphID - hcount) * 2, 1));
3003                 } else {                              /* font is broken */
3004                     res[i].lsb = XUnits(UPEm, GetInt16(hmtx, 4*(hcount-1) + 2, 1));
3005                 }
3006             }
3007         }
3008
3009         /* vertical metrics */
3010         if (vmtx != 0 && vcount > 0) {
3011
3012             if (glyphID < vcount) {
3013                 res[i].ah = XUnits(UPEm, GetUInt16(vmtx, 4 * glyphID, 1));
3014                 res[i].tsb  = XUnits(UPEm, GetInt16(vmtx, 4 * glyphID + 2, 1));
3015             } else {
3016                 res[i].ah = XUnits(UPEm, GetUInt16(vmtx, 4 * (vcount - 1), 1));
3017                 if( glyphID-hcount < gcount ) {
3018                     res[i].tsb = XUnits(UPEm, GetInt16(vmtx + vcount * 4, (glyphID - vcount) * 2, 1));
3019                 } else {                              /* font is broken */
3020                     res[i].tsb = XUnits(UPEm, GetInt16(vmtx, 4*(vcount-1) + 2, 1));
3021                 }
3022             }
3023         }
3024     }
3025
3026     return res;
3027 }
3028
3029 void ReadSingleGlyphMetrics(guint8 *hmtx, guint8 *vmtx, int hcount, int vcount, int gcount, int UPEm, guint16 glyphID, TTFullSimpleGlyphMetrics *metrics)
3030 {
3031
3032     memset(metrics, 0, sizeof(TTFullSimpleGlyphMetrics));
3033
3034     /* horizontal metrics */
3035     if (hmtx != 0 && hcount > 0) {
3036         if (glyphID < hcount) {
3037             metrics->aw = XUnits(UPEm, GetUInt16(hmtx, 4 * glyphID, 1));
3038             metrics->lsb  = XUnits(UPEm, GetInt16(hmtx, 4 * glyphID + 2, 1));
3039         } else {
3040             metrics->aw = XUnits(UPEm, GetUInt16(hmtx, 4 * (hcount - 1), 1));
3041             if( glyphID-hcount < gcount ) {
3042                 metrics->lsb = XUnits(UPEm, GetInt16(hmtx + hcount * 4, (glyphID - hcount) * 2, 1));
3043             } else {                              /* font is broken */
3044                 metrics->lsb = XUnits(UPEm, GetInt16(hmtx, 4*(hcount-1) + 2, 1));
3045             }
3046         }
3047     }
3048
3049     /* vertical metrics */
3050     if (vmtx != 0 && vcount > 0) {
3051         if (glyphID < vcount) {
3052             metrics->ah = XUnits(UPEm, GetUInt16(vmtx, 4 * glyphID, 1));
3053             metrics->tsb  = XUnits(UPEm, GetInt16(vmtx, 4 * glyphID + 2, 1));
3054         } else {
3055             metrics->ah = XUnits(UPEm, GetUInt16(vmtx, 4 * (vcount - 1), 1));
3056             if( glyphID-hcount < gcount ) {
3057                 metrics->tsb = XUnits(UPEm, GetInt16(vmtx + vcount * 4, (glyphID - vcount) * 2, 1));
3058             } else {                              /* font is broken */
3059                 metrics->tsb = XUnits(UPEm, GetInt16(vmtx, 4*(vcount-1) + 2, 1));
3060             }
3061         }
3062     }
3063 }
3064
3065
3066
3067
3068
3069 guint32 GetKernSubtableLength(guint8 *kern)
3070 {
3071     guint32 r = 0;
3072
3073     if (kern != NULL) {
3074         r = GetUInt16(kern, 2, 1);
3075     }
3076
3077     return r;
3078 }
3079
3080 void KernGlyphPair(int kerntype, guint32 nkern, guint8 **kern, int unitsPerEm, int wmode, guint32 a, guint32 b, int *x, int *y)
3081 {
3082     if (x == NULL || y == NULL) return;
3083     *x  = *y = 0;
3084
3085     if (nkern == 0 || kern == NULL) return;
3086
3087     switch (kerntype) {
3088       case KT_APPLE_NEW: KernGlyphPairPrim1(nkern, kern, unitsPerEm, wmode, a, b, x, y);  return;
3089       case KT_MICROSOFT: KernGlyphPairPrim2(nkern, kern, unitsPerEm, wmode, a, b, x, y);  return;
3090     }
3091 }
3092
3093 #ifdef TEST1
3094 /* This example creates a subset of a TrueType font with two encoded characters */
3095 int main(int ac, char **av)
3096 {
3097     TrueTypeFont *fnt;
3098     int r;
3099
3100     /* Array of Unicode source characters */
3101     guint16 chars[2];
3102
3103     /* Encoding vector maps character encoding to the ordinal number
3104      * of the glyph in the output file */
3105     guint8 encoding[2];
3106
3107     /* This array is for glyph IDs that  source characters map to */
3108     guint16 g[2];
3109
3110
3111     if (ac < 2) return 0;
3112
3113     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3114         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3115         return 0;
3116     }
3117
3118
3119     /* We want to create the output file that only contains two Unicode characters:
3120      * L'a' and L'A' */
3121     
3122     chars[0] = L'a';
3123     chars[1] = L'A';
3124
3125     /* Figure out what glyphs do these characters map in our font */
3126     MapString(fnt, chars, 2, g);
3127
3128     /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the
3129      * newly generated font */
3130     encoding[0] = chars[0];
3131     encoding[1] = chars[1];
3132     
3133
3134     /* Generate a subset */
3135     CreateT3FromTTGlyphs(fnt, stdout, 0, g, encoding, 2, 0);
3136
3137     /* Now call the dtor for the font */
3138     CloseTTFont(fnt);
3139     return 0;
3140 }
3141 #endif
3142
3143 #ifdef TEST2
3144 /* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */
3145 int main(int ac, char **av)
3146 {
3147     TrueTypeFont *fnt;
3148     int i, r;
3149
3150     /* Array of Unicode source characters */
3151     guint16 glyphs[224];
3152
3153     /* Encoding vector maps character encoding to the ordinal number
3154      * of the glyph in the output file */
3155     guint8 encoding[224];
3156
3157
3158     
3159     for (i=0; i<224; i++) {
3160         glyphs[i] = i;
3161         encoding[i] = 32 + i;
3162     }
3163
3164     if (ac < 2) return 0;
3165
3166     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3167         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3168         return 0;
3169     }
3170
3171
3172     /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the
3173      * newly generated font */
3174
3175     /* Generate a subset */
3176     CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 224, 0);
3177
3178     /* Now call the dtor for the font */
3179     CloseTTFont(fnt);
3180     return 0;
3181 }
3182 #endif
3183
3184 #ifdef TEST3
3185 /* Glyph metrics example */
3186 int main(int ac, char **av)
3187 {
3188     TrueTypeFont *fnt;
3189     int i, r;
3190     guint16 glyphs[224];
3191     TTSimpleGlyphMetrics *m;
3192
3193     for (i=0; i<224; i++) {
3194         glyphs[i] = i;
3195     }
3196
3197     if (ac < 2) return 0;
3198
3199     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3200         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3201         return 0;
3202     }
3203
3204     if ((m = GetTTSimpleGlyphMetrics(fnt, glyphs, 224, 0)) == 0) {
3205         printf("Requested metrics is not available\n");
3206     } else {
3207         for (i=0; i<224; i++) {
3208             printf("%d. advWid: %5d, LSBear: %5d\n", i, m[i].adv, m[i].sb);
3209         }
3210     }
3211
3212     /* Now call the dtor for the font */
3213     free(m);
3214     CloseTTFont(fnt);
3215     return 0;
3216 }
3217 #endif
3218
3219 #ifdef TEST4
3220 int main(int ac, char **av)
3221 {
3222     TrueTypeFont *fnt;
3223     TTGlobalFontInfo info;
3224     int i, r;
3225
3226
3227     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3228         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3229         return 0;
3230     }
3231
3232     printf("Font file: %s\n", av[1]);
3233
3234 #ifdef PRINT_KERN
3235     switch (fnt->kerntype) {
3236       case KT_MICROSOFT:
3237         printf("\tkern: MICROSOFT, ntables: %d.", fnt->nkern);
3238         if (fnt->nkern) {
3239             printf(" [");
3240             for (i=0; i<fnt->nkern; i++) {
3241                 printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1));
3242             }
3243             printf("]");
3244         }
3245         printf("\n");
3246         break;
3247
3248       case KT_APPLE_NEW:
3249         printf("\tkern: APPLE_NEW, ntables: %d.", fnt->nkern);
3250         if (fnt->nkern) {
3251             printf(" [");
3252             for (i=0; i<fnt->nkern; i++) {
3253                 printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1));
3254             }
3255             printf("]");
3256         }
3257         printf("\n");
3258         break;
3259
3260       case KT_NONE:
3261         printf("\tkern: none.\n");
3262         break;
3263
3264       default:
3265         printf("\tkern: unrecoginzed.\n");
3266         break;
3267     }
3268     printf("\n");
3269 #endif
3270
3271     GetTTGlobalFontInfo(fnt, &info);
3272     printf("\tfamily name: `%s`\n", info.family);
3273     printf("\tsubfamily name: `%s`\n", info.subfamily);
3274     printf("\tpostscript name: `%s`\n", info.psname);
3275     printf("\tweight: %d\n", info.weight);
3276     printf("\twidth: %d\n", info.width);
3277     printf("\tpitch: %d\n", info.pitch);
3278     printf("\titalic angle: %d\n", info.italicAngle);
3279     printf("\tbouding box: [%d %d %d %d]\n", info.xMin, info.yMin, info.xMax, info.yMax);
3280     printf("\tascender: %d\n", info.ascender);
3281     printf("\tdescender: %d\n", info.descender);
3282     printf("\tlinegap: %d\n", info.linegap);
3283     printf("\tvascent: %d\n", info.vascent);
3284     printf("\tvdescent: %d\n", info.vdescent);
3285     printf("\ttypoAscender: %d\n", info.typoAscender);
3286     printf("\ttypoDescender: %d\n", info.typoDescender);
3287     printf("\ttypoLineGap: %d\n", info.typoLineGap);
3288     printf("\twinAscent: %d\n", info.winAscent);
3289     printf("\twinDescent: %d\n", info.winDescent);
3290     printf("\tUnicode ranges:\n");
3291     for (i = 0; i < 32; i++) {
3292         if ((info.ur1 >> i) & 1) {
3293             printf("\t\t\t%s\n", UnicodeRangeName(i));
3294         }
3295     }
3296     for (i = 0; i < 32; i++) {
3297         if ((info.ur2 >> i) & 1) {
3298             printf("\t\t\t%s\n", UnicodeRangeName(i+32));
3299         }
3300     }
3301     for (i = 0; i < 32; i++) {
3302         if ((info.ur3 >> i) & 1) {
3303             printf("\t\t\t%s\n", UnicodeRangeName(i+64));
3304         }
3305     }
3306     for (i = 0; i < 32; i++) {
3307         if ((info.ur4 >> i) & 1) {
3308             printf("\t\t\t%s\n", UnicodeRangeName(i+96));
3309         }
3310     }
3311
3312     CloseTTFont(fnt);
3313     return 0;
3314 }
3315 #endif
3316
3317 #ifdef TEST5
3318 /* Kerning example */
3319 int main(int ac, char **av)
3320 {
3321     TrueTypeFont *fnt;
3322     guint16 g[224];
3323     KernData d[223];
3324     int r, i, k = 0;
3325
3326     g[k++] = 57;
3327     g[k++] = 36;
3328     g[k++] = 57;
3329     g[k++] = 98;
3330     g[k++] = 11;
3331     g[k++] = 144;
3332     g[k++] = 41;
3333     g[k++] = 171;
3334     g[k++] = 51;
3335     g[k++] = 15;
3336
3337     if (ac < 2) return 0;
3338
3339     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3340         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3341         return 0;
3342     }
3343
3344     KernGlyphs(fnt, g, k, 0, d);
3345
3346     for (i = 0; i < k-1; i++) {
3347         printf("%3d %3d: [%3d %3d]\n", g[i], g[i+1], d[i].x, d[i].y);
3348
3349     }
3350
3351     for (i=0; i<k-1; i++) {
3352         int x, y;
3353         KernGlyphPair(fnt->kerntype, fnt->nkern, fnt->kerntables, fnt->unitsPerEm, 0, g[i], g[i+1], &x, &y);
3354         printf("KernGlyphPair (wmode: 0) :  %3d %3d: [%3d %3d]\n", g[i], g[i+1], x, y);
3355         KernGlyphPair(fnt->kerntype, fnt->nkern, fnt->kerntables, fnt->unitsPerEm, 1, g[i], g[i+1], &x, &y);
3356         printf("KernGlyphPair (wmode: 1) :  %3d %3d: [%3d %3d]\n", g[i], g[i+1], x, y);
3357     }
3358
3359     CloseTTFont(fnt);
3360     return 0;
3361 }
3362 #endif
3363
3364
3365
3366 #ifdef TEST6
3367 /* This example extracts a single glyph from a font */
3368 int main(int ac, char **av)
3369 {
3370     TrueTypeFont *fnt;
3371     int r, i;
3372
3373     guint16 glyphs[256];
3374     guint8 encoding[256];
3375
3376     for (i=0; i<256; i++) {
3377         glyphs[i] = 512 + i;
3378         encoding[i] = i;
3379     }
3380
3381 #if 0
3382     i=0;
3383     glyphs[i++] = 2001;
3384     glyphs[i++] = 2002;
3385     glyphs[i++] = 2003;
3386     glyphs[i++] = 2004;
3387     glyphs[i++] = 2005;
3388     glyphs[i++] = 2006;
3389     glyphs[i++] = 2007;
3390     glyphs[i++] = 2008;
3391     glyphs[i++] = 2009;
3392     glyphs[i++] = 2010;
3393     glyphs[i++] = 2011;
3394     glyphs[i++] = 2012;
3395     glyphs[i++] = 2013;
3396     glyphs[i++] = 2014;
3397     glyphs[i++] = 2015;
3398     glyphs[i++] = 2016;
3399     glyphs[i++] = 2017;
3400     glyphs[i++] = 2018;
3401     glyphs[i++] = 2019;
3402     glyphs[i++] = 2020;
3403
3404
3405     r = 97;
3406     i = 0;
3407     encoding[i++] = r++;
3408     encoding[i++] = r++;
3409     encoding[i++] = r++;
3410     encoding[i++] = r++;
3411     encoding[i++] = r++;
3412     encoding[i++] = r++;
3413     encoding[i++] = r++;
3414     encoding[i++] = r++;
3415     encoding[i++] = r++;
3416     encoding[i++] = r++;
3417     encoding[i++] = r++;
3418     encoding[i++] = r++;
3419     encoding[i++] = r++;
3420     encoding[i++] = r++;
3421     encoding[i++] = r++;
3422     encoding[i++] = r++;
3423     encoding[i++] = r++;
3424     encoding[i++] = r++;
3425     encoding[i++] = r++;
3426     encoding[i++] = r++;
3427 #endif
3428     
3429     if (ac < 2) return 0;
3430
3431     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3432         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3433         return 0;
3434     }
3435
3436     /* Generate a subset */
3437     CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 256, 0);
3438
3439     fprintf(stderr, "UnitsPerEm: %d.\n", fnt->unitsPerEm);
3440
3441     /* Now call the dtor for the font */
3442     CloseTTFont(fnt);
3443     return 0;
3444 }
3445 #endif
3446
3447 #ifdef TEST7
3448 /* NameRecord extraction example */
3449 int main(int ac, char **av)
3450 {
3451     TrueTypeFont *fnt;
3452     int r, i, j,  n;
3453     NameRecord *nr;
3454
3455     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3456         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3457         return 0;
3458     }
3459
3460     if ((n = GetTTNameRecords(fnt, &nr)) == 0) {
3461         fprintf(stderr, "No name records in the font.\n");
3462         return 0;
3463     }
3464
3465     printf("Number of name records: %d.\n", n);
3466     for (i = 0; i < n; i++) {
3467         printf("%d %d %04X %d [", nr[i].platformID, nr[i].encodingID, nr[i].languageID, nr[i].nameID);
3468         for (j=0; j<nr[i].slen; j++) {
3469             printf("%c", isprint(nr[i].sptr[j]) ? nr[i].sptr[j] : '.');
3470         }
3471         printf("]\n");
3472     }
3473
3474     
3475     DisposeNameRecords(nr, n);
3476     CloseTTFont(fnt);
3477     return 0;
3478 }
3479 #endif
3480
3481 #ifdef TEST8
3482 /* TrueType -> TrueType subsetting */
3483 int main(int ac, char **av)
3484 {
3485     TrueTypeFont *fnt;
3486     guint16 glyphArray[] = { 0,  98,  99,  22,  24, 25, 26,  27,  28,  29, 30, 31, 1270, 1289, 34};
3487     guint8 encoding[]     = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3488     int r;
3489
3490     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3491         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3492         return 0;
3493     }
3494
3495     CreateTTFromTTGlyphs(fnt, "subfont.ttf", glyphArray, encoding, 15, 0, 0, TTCF_AutoName | TTCF_IncludeOS2);
3496
3497     CloseTTFont(fnt);
3498
3499     return 0;
3500 }
3501 #endif
3502
3503 #ifdef TEST9
3504 /* TrueType -> Type42 subsetting */
3505 int main(int ac, char **av)
3506 {
3507     TrueTypeFont *fnt;
3508     /*
3509       guint16 glyphArray[] = { 0,  20,  21,  22,  24, 25, 26,  27,  28,  29, 30, 31, 32, 33, 34};
3510       guint8 encoding[]     = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3511     guint16 glyphArray[] = { 0,  6711,  6724,  11133,  11144, 14360, 26,  27,  28,  29, 30, 31, 1270, 1289, 34};
3512     guint8 encoding[]     = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3513     */
3514     guint16 glyphArray[1000];
3515     guint8 encoding[1000];
3516     int r, i;
3517
3518     for (i=0;i<1000;i++) {
3519         glyphArray[i]=2000 + i;
3520         encoding[i] =i;
3521     }
3522     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3523         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3524         return 0;
3525     }
3526
3527     CreateT42FromTTGlyphs(fnt, stdout, "testfont", glyphArray, encoding, 1000);
3528
3529     CloseTTFont(fnt);
3530
3531     return 0;
3532 }
3533 #endif
3534
3535 #ifdef TEST10
3536 /* Component glyph test */
3537 int main(int ac, char **av)
3538 {
3539     TrueTypeFont *fnt;
3540     int r, i;
3541     list glyphlist = listNewEmpty();
3542
3543     if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3544         fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3545         return 0;
3546     }
3547
3548     for (i = 0; i < fnt->nglyphs; i++) {
3549         r = GetTTGlyphComponents(fnt, i, glyphlist);
3550         if (r > 1) {
3551             printf("%d -> ", i);
3552             listToFirst(glyphlist);
3553             do {
3554                 printf("%d ", (int) listCurrent(glyphlist));
3555             } while (listNext(glyphlist));
3556             printf("\n");
3557         } else {
3558             printf("%d: single glyph.\n", i);
3559         }
3560         listClear(glyphlist);
3561     }
3562     
3563     CloseTTFont(fnt);
3564     listDispose(glyphlist);
3565
3566     return 0;
3567 }
3568 #endif
3569
3570