xref: /aoo42x/main/vcl/source/fontsubset/ttcr.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 /*
29  * TrueTypeCreator method implementation
30  *
31  * @author: Alexander Gelfenbain
32  *
33  */
34 
35 #if OSL_DEBUG_LEVEL == 0
36 #  ifndef NDEBUG
37 #    define NDEBUG
38 #  endif
39 #endif
40 #include <assert.h>
41 
42 #include "ttcr.hxx"
43 #include "list.h"
44 #include "string.h"
45 
46 
47 
48 namespace vcl
49 {
50 
51 /*
52  * Private Data Types
53  */
54 
55     struct _TrueTypeCreator {
56         sal_uInt32 tag;                         /**< TrueType file tag */
57         list   tables;                      /**< List of table tags and pointers */
58     };
59 
60 /* These must be #defined so that they can be used in initializers */
61 #define T_maxp  0x6D617870
62 #define T_glyf  0x676C7966
63 #define T_head  0x68656164
64 #define T_loca  0x6C6F6361
65 #define T_name  0x6E616D65
66 #define T_hhea  0x68686561
67 #define T_hmtx  0x686D7478
68 #define T_cmap  0x636D6170
69 #define T_vhea  0x76686561
70 #define T_vmtx  0x766D7478
71 #define T_OS2   0x4F532F32
72 #define T_post  0x706F7374
73 #define T_kern  0x6B65726E
74 #define T_cvt   0x63767420
75 
76 typedef struct {
77     sal_uInt32 tag;
78     sal_uInt32 length;
79     sal_uInt8  *data;
80 } TableEntry;
81 
82 /*
83  * this is a duplicate code from sft.c but it is left here for performance reasons
84  */
85 #ifdef __GNUC__
86 #define _inline static __inline__
87 #else
88 #define _inline static
89 #endif
90 
91 _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) {
92     return (a << 24) | (b << 16) | (c << 8) | d;
93 }
94 
95 /*- Data access macros for data stored in big-endian or little-endian format */
96 _inline sal_Int16 GetInt16( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
97 {
98     sal_Int16 t;
99     assert(ptr != 0);
100 
101     if (bigendian) {
102         t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
103     } else {
104         t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
105     }
106 
107     return t;
108 }
109 
110 _inline sal_uInt16 GetUInt16( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
111 {
112     sal_uInt16 t;
113     assert(ptr != 0);
114 
115     if (bigendian) {
116         t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
117     } else {
118         t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
119     }
120 
121     return t;
122 }
123 
124 _inline sal_Int32 GetInt32( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
125 {
126     sal_Int32 t;
127     assert(ptr != 0);
128 
129     if (bigendian) {
130         t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
131             (ptr+offset)[2] << 8  | (ptr+offset)[3];
132     } else {
133         t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
134             (ptr+offset)[1] << 8  | (ptr+offset)[0];
135     }
136 
137     return t;
138 }
139 
140 _inline sal_uInt32 GetUInt32( const sal_uInt8* ptr, sal_uInt32 offset, int bigendian)
141 {
142     sal_uInt32 t;
143     assert(ptr != 0);
144 
145 
146     if (bigendian) {
147         t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
148             (ptr+offset)[2] << 8  | (ptr+offset)[3];
149     } else {
150         t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
151             (ptr+offset)[1] << 8  | (ptr+offset)[0];
152     }
153 
154     return t;
155 }
156 
157 
158 _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
159 {
160     assert(ptr != 0);
161 
162     if (bigendian) {
163         ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
164         ptr[offset+1] = (sal_uInt8)(val & 0xFF);
165     } else {
166         ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
167         ptr[offset] = (sal_uInt8)(val & 0xFF);
168     }
169 }
170 
171 _inline void PutUInt16(sal_uInt16 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
172 {
173     assert(ptr != 0);
174 
175     if (bigendian) {
176         ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
177         ptr[offset+1] = (sal_uInt8)(val & 0xFF);
178     } else {
179         ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
180         ptr[offset] = (sal_uInt8)(val & 0xFF);
181     }
182 }
183 
184 _inline void PutUInt32(sal_uInt32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
185 {
186     assert(ptr != 0);
187 
188     if (bigendian) {
189         ptr[offset]   = (sal_uInt8)((val >> 24) & 0xFF);
190         ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF);
191         ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF);
192         ptr[offset+3] = (sal_uInt8)(val & 0xFF);
193     } else {
194         ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF);
195         ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF);
196         ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
197         ptr[offset]   = (sal_uInt8)(val & 0xFF);
198     }
199 
200 }
201 
202 
203 _inline void PutInt32(sal_Int32 val, sal_uInt8 *ptr, sal_uInt32 offset, int bigendian)
204 {
205     assert(ptr != 0);
206 
207     if (bigendian) {
208         ptr[offset]   = (sal_uInt8)((val >> 24) & 0xFF);
209         ptr[offset+1] = (sal_uInt8)((val >> 16) & 0xFF);
210         ptr[offset+2] = (sal_uInt8)((val >> 8) & 0xFF);
211         ptr[offset+3] = (sal_uInt8)(val & 0xFF);
212     } else {
213         ptr[offset+3] = (sal_uInt8)((val >> 24) & 0xFF);
214         ptr[offset+2] = (sal_uInt8)((val >> 16) & 0xFF);
215         ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
216         ptr[offset]   = (sal_uInt8)(val & 0xFF);
217     }
218 
219 }
220 
221 static int TableEntryCompareF(const void *l, const void *r)
222 {
223     return ((const TableEntry *) l)->tag - ((const TableEntry *) r)->tag;
224 }
225 
226 static int NameRecordCompareF(const void *l, const void *r)
227 {
228     NameRecord *ll = (NameRecord *) l;
229     NameRecord *rr = (NameRecord *) r;
230 
231     if (ll->platformID != rr->platformID) {
232         return ll->platformID - rr->platformID;
233     } else if (ll->encodingID != rr->encodingID) {
234         return ll->encodingID - rr->encodingID;
235     } else if (ll->languageID != rr->languageID) {
236         return ll->languageID - rr->languageID;
237     } else if (ll->nameID != rr->nameID) {
238         return ll->nameID - rr->nameID;
239     }
240     return 0;
241 }
242 
243 
244 static sal_uInt32 CheckSum(sal_uInt32 *ptr, sal_uInt32 length)
245 {
246     sal_uInt32 sum = 0;
247     sal_uInt32 *endptr = ptr + ((length + 3) & (sal_uInt32) ~3) / 4;
248 
249     while (ptr < endptr) sum += *ptr++;
250 
251     return sum;
252 }
253 
254 _inline void *smalloc(sal_uInt32 size)
255 {
256     void *res = malloc(size);
257     assert(res != 0);
258     return res;
259 }
260 
261 _inline void *scalloc(sal_uInt32 n, sal_uInt32 size)
262 {
263     void *res = calloc(n, size);
264     assert(res != 0);
265     return res;
266 }
267 
268 /*
269  * Public functions
270  */
271 
272 void TrueTypeCreatorNewEmpty(sal_uInt32 tag, TrueTypeCreator **_this)
273 {
274     TrueTypeCreator* ptr = (TrueTypeCreator*)smalloc(sizeof(TrueTypeCreator));
275 
276     ptr->tables = listNewEmpty();
277     listSetElementDtor(ptr->tables, (list_destructor)TrueTypeTableDispose);
278 
279     ptr->tag = tag;
280 
281     *_this = ptr;
282 }
283 
284 int AddTable(TrueTypeCreator *_this, TrueTypeTable *table)
285 {
286     if (table != 0) {
287         listAppend(_this->tables, table);
288     }
289     return SF_OK;
290 }
291 
292 void RemoveTable(TrueTypeCreator *_this, sal_uInt32 tag)
293 {
294     int done = 0;
295 
296     if (listCount(_this->tables)) {
297         listToFirst(_this->tables);
298         do {
299             if (((TrueTypeTable *) listCurrent(_this->tables))->tag == tag) {
300                 listRemove(_this->tables);
301             } else {
302                 if (listNext(_this->tables)) {
303                     done = 1;
304                 }
305             }
306         } while (!done);
307     }
308 }
309 
310 static void ProcessTables(TrueTypeCreator *);
311 
312 int StreamToMemory(TrueTypeCreator *_this, sal_uInt8 **ptr, sal_uInt32 *length)
313 {
314     sal_uInt16 numTables, searchRange=1, entrySelector=0, rangeShift;
315     sal_uInt32 s, offset, checkSumAdjustment = 0;
316     sal_uInt32 *p;
317     int i=0, n;
318     sal_uInt8 *head = NULL;     /* saved pointer to the head table data for checkSumAdjustment calculation */
319 
320     if ((n = listCount(_this->tables)) == 0) return SF_TTFORMAT;
321 
322     ProcessTables(_this);
323 
324     /* ProcessTables() adds 'loca' and 'hmtx' */
325 
326     n = listCount(_this->tables);
327     numTables = (sal_uInt16) n;
328 
329 
330     TableEntry* te = (TableEntry*)scalloc(n, sizeof(TableEntry));
331 
332     listToFirst(_this->tables);
333     for (i = 0; i < n; i++) {
334         GetRawData((TrueTypeTable *) listCurrent(_this->tables), &te[i].data, &te[i].length, &te[i].tag);
335         listNext(_this->tables);
336     }
337 
338     qsort(te, n, sizeof(TableEntry), TableEntryCompareF);
339 
340     do {
341         searchRange *= 2;
342         entrySelector++;
343     } while (searchRange <= numTables);
344 
345     searchRange *= 8;
346     entrySelector--;
347     rangeShift = numTables * 16 - searchRange;
348 
349     s = offset = 12 + 16 * n;
350 
351     for (i = 0; i < n; i++) {
352         s += (te[i].length + 3) & (sal_uInt32) ~3;
353         /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */
354     }
355 
356     sal_uInt8* ttf = (sal_uInt8*)smalloc(s);
357 
358     /* Offset Table */
359     PutUInt32(_this->tag, ttf, 0, 1);
360     PutUInt16(numTables, ttf, 4, 1);
361     PutUInt16(searchRange, ttf, 6, 1);
362     PutUInt16(entrySelector, ttf, 8, 1);
363     PutUInt16(rangeShift, ttf, 10, 1);
364 
365     /* Table Directory */
366     for (i = 0; i < n; i++) {
367         PutUInt32(te[i].tag, ttf + 12, 16 * i, 1);
368         PutUInt32(CheckSum((sal_uInt32 *) te[i].data, te[i].length), ttf + 12, 16 * i + 4, 1);
369         PutUInt32(offset, ttf + 12, 16 * i + 8, 1);
370         PutUInt32(te[i].length, ttf + 12, 16 * i + 12, 1);
371 
372         if (te[i].tag == T_head) {
373             head = ttf + offset;
374         }
375 
376         memcpy(ttf+offset, te[i].data, (te[i].length + 3) & (sal_uInt32) ~3 );
377         offset += (te[i].length + 3) & (sal_uInt32) ~3;
378         /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */
379     }
380 
381     free(te);
382 
383     p = (sal_uInt32 *) ttf;
384     for (i = 0; i < (int)s / 4; i++) checkSumAdjustment += p[i];
385     PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8, 1);
386 
387     *ptr = ttf;
388     *length = s;
389 
390     return SF_OK;
391 }
392 
393 int StreamToFile(TrueTypeCreator *_this, const char* fname)
394 {
395     sal_uInt8 *ptr;
396     sal_uInt32 length;
397     int r;
398     FILE* fd;
399 
400     if ((r = StreamToMemory(_this, &ptr, &length)) != SF_OK) return r;
401     if (!fname) return SF_BADFILE;
402     if ((fd = fopen(fname, "wb")) == NULL) return SF_BADFILE;
403 
404     if (fwrite(ptr, 1, length, fd) != length) {
405         r = SF_FILEIO;
406     } else {
407         r = SF_OK;
408     }
409 
410     fclose(fd);
411     free(ptr);
412     return r;
413 }
414 
415 
416 
417 /*
418  * TrueTypeTable private methods
419  */
420 
421 #define TABLESIZE_head 54
422 #define TABLESIZE_hhea 36
423 #define TABLESIZE_maxp 32
424 
425 
426 
427 /*    Table         data points to
428  * --------------------------------------------
429  *    generic       tdata_generic struct
430  *    'head'        TABLESIZE_head bytes of memory
431  *    'hhea'        TABLESIZE_hhea bytes of memory
432  *    'loca'        tdata_loca struct
433  *    'maxp'        TABLESIZE_maxp bytes of memory
434  *    'glyf'        list of GlyphData structs (defined in sft.h)
435  *    'name'        list of NameRecord structs (defined in sft.h)
436  *    'post'        tdata_post struct
437  *
438  */
439 
440 
441 #define CMAP_SUBTABLE_INIT 10
442 #define CMAP_SUBTABLE_INCR 10
443 #define CMAP_PAIR_INIT 500
444 #define CMAP_PAIR_INCR 500
445 
446 typedef struct {
447     sal_uInt32  id;                         /* subtable ID (platform/encoding ID)    */
448     sal_uInt32  n;                          /* number of used translation pairs      */
449     sal_uInt32  m;                          /* number of allocated translation pairs */
450     sal_uInt32 *xc;                         /* character array                       */
451     sal_uInt32 *xg;                         /* glyph array                           */
452 } CmapSubTable;
453 
454 typedef struct {
455     sal_uInt32 n;                           /* number of used CMAP sub-tables       */
456     sal_uInt32 m;                           /* number of allocated CMAP sub-tables  */
457     CmapSubTable *s;                    /* sotred array of sub-tables           */
458 } table_cmap;
459 
460 typedef struct {
461     sal_uInt32 tag;
462     sal_uInt32 nbytes;
463     sal_uInt8 *ptr;
464 } tdata_generic;
465 
466 typedef struct {
467     sal_uInt32 nbytes;                      /* number of bytes in loca table */
468     sal_uInt8 *ptr;                          /* pointer to the data */
469 } tdata_loca;
470 
471 typedef struct {
472     sal_uInt32 format;
473     sal_uInt32 italicAngle;
474     sal_Int16  underlinePosition;
475     sal_Int16  underlineThickness;
476     sal_uInt32 isFixedPitch;
477     void   *ptr;                        /* format-specific pointer */
478 } tdata_post;
479 
480 
481 /* allocate memory for a TT table */
482 static sal_uInt8 *ttmalloc(sal_uInt32 nbytes)
483 {
484     sal_uInt32 n;
485 
486     n = (nbytes + 3) & (sal_uInt32) ~3;
487     sal_uInt8* res = (sal_uInt8*)malloc(n);
488     assert(res != 0);
489     memset(res, 0, n);
490 
491     return res;
492 }
493 
494 static void FreeGlyphData(void *ptr)
495 {
496     GlyphData *p = (GlyphData *) ptr;
497     if (p->ptr) free(p->ptr);
498     free(p);
499 }
500 
501 static void TrueTypeTableDispose_generic(TrueTypeTable *_this)
502 {
503     if (_this) {
504         if (_this->data) {
505             tdata_generic *pdata = (tdata_generic *) _this->data;
506             if (pdata->nbytes) free(pdata->ptr);
507             free(_this->data);
508         }
509         free(_this);
510     }
511 }
512 
513 static void TrueTypeTableDispose_head(TrueTypeTable *_this)
514 {
515     if (_this) {
516         if (_this->data) free(_this->data);
517         free(_this);
518     }
519 }
520 
521 static void TrueTypeTableDispose_hhea(TrueTypeTable *_this)
522 {
523     if (_this) {
524         if (_this->data) free(_this->data);
525         free(_this);
526     }
527 }
528 
529 static void TrueTypeTableDispose_loca(TrueTypeTable *_this)
530 {
531     if (_this) {
532         if (_this->data) {
533             tdata_loca *p = (tdata_loca *) _this->data;
534             if (p->ptr) free(p->ptr);
535             free(_this->data);
536         }
537         free(_this);
538     }
539 }
540 
541 static void TrueTypeTableDispose_maxp(TrueTypeTable *_this)
542 {
543     if (_this) {
544         if (_this->data) free(_this->data);
545         free(_this);
546     }
547 }
548 
549 static void TrueTypeTableDispose_glyf(TrueTypeTable *_this)
550 {
551     if (_this) {
552         if (_this->data) listDispose((list) _this->data);
553         free(_this);
554     }
555 }
556 
557 static void TrueTypeTableDispose_cmap(TrueTypeTable *_this)
558 {
559     table_cmap *t;
560     CmapSubTable *s;
561     sal_uInt32 i;
562 
563     if (_this) {
564         t = (table_cmap *) _this->data;
565         if (t) {
566             s = t->s;
567             if (s) {
568                 for (i = 0; i < t->m; i++) {
569                     if (s[i].xc) free(s[i].xc);
570                     if (s[i].xg) free(s[i].xg);
571                 }
572                 free(s);
573             }
574             free(t);
575         }
576         free(_this);
577     }
578 }
579 
580 static void TrueTypeTableDispose_name(TrueTypeTable *_this)
581 {
582     if (_this) {
583         if (_this->data) listDispose((list) _this->data);
584         free(_this);
585     }
586 }
587 
588 static void TrueTypeTableDispose_post(TrueTypeTable *_this)
589 {
590     if (_this) {
591         tdata_post *p = (tdata_post *) _this->data;
592         if (p) {
593             if (p->format == 0x00030000) {
594                 /* do nothing */
595             } else {
596                 fprintf(stderr, "Unsupported format of a 'post' table: %08X.\n", (int)p->format);
597             }
598             free(p);
599         }
600         free(_this);
601     }
602 }
603 
604 /* destructor vtable */
605 
606 static struct {
607     sal_uInt32 tag;
608     void (*f)(TrueTypeTable *);
609 } vtable1[] =
610 {
611     {0,      TrueTypeTableDispose_generic},
612     {T_head, TrueTypeTableDispose_head},
613     {T_hhea, TrueTypeTableDispose_hhea},
614     {T_loca, TrueTypeTableDispose_loca},
615     {T_maxp, TrueTypeTableDispose_maxp},
616     {T_glyf, TrueTypeTableDispose_glyf},
617     {T_cmap, TrueTypeTableDispose_cmap},
618     {T_name, TrueTypeTableDispose_name},
619     {T_post, TrueTypeTableDispose_post}
620 
621 };
622 
623 static int GetRawData_generic(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
624 {
625     assert(_this != 0);
626     assert(_this->data != 0);
627 
628     *ptr = ((tdata_generic *) _this->data)->ptr;
629     *len = ((tdata_generic *) _this->data)->nbytes;
630     *tag = ((tdata_generic *) _this->data)->tag;
631 
632     return TTCR_OK;
633 }
634 
635 
636 static int GetRawData_head(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
637 {
638     *len = TABLESIZE_head;
639     *ptr = (sal_uInt8 *) _this->data;
640     *tag = T_head;
641 
642     return TTCR_OK;
643 }
644 
645 static int GetRawData_hhea(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
646 {
647     *len = TABLESIZE_hhea;
648     *ptr = (sal_uInt8 *) _this->data;
649     *tag = T_hhea;
650 
651     return TTCR_OK;
652 }
653 
654 static int GetRawData_loca(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
655 {
656     tdata_loca *p;
657 
658     assert(_this->data != 0);
659 
660     p = (tdata_loca *) _this->data;
661 
662     if (p->nbytes == 0) return TTCR_ZEROGLYPHS;
663 
664     *ptr = p->ptr;
665     *len = p->nbytes;
666     *tag = T_loca;
667 
668     return TTCR_OK;
669 }
670 
671 static int GetRawData_maxp(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
672 {
673     *len = TABLESIZE_maxp;
674     *ptr = (sal_uInt8 *) _this->data;
675     *tag = T_maxp;
676 
677     return TTCR_OK;
678 }
679 
680 static int GetRawData_glyf(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
681 {
682     sal_uInt32 n, nbytes = 0;
683     list l = (list) _this->data;
684     /* sal_uInt16 curID = 0;    */               /* to check if glyph IDs are sequential and start from zero */
685     sal_uInt8 *p;
686 
687     *ptr = 0;
688     *len = 0;
689     *tag = 0;
690 
691     if (listCount(l) == 0) return TTCR_ZEROGLYPHS;
692 
693     listToFirst(l);
694     do {
695         /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */
696         nbytes += ((GlyphData *) listCurrent(l))->nbytes;
697     } while (listNext(l));
698 
699     p = _this->rawdata = ttmalloc(nbytes);
700 
701     listToFirst(l);
702     do {
703         n = ((GlyphData *) listCurrent(l))->nbytes;
704         if (n != 0) {
705             memcpy(p, ((GlyphData *) listCurrent(l))->ptr, n);
706             p += n;
707         }
708     } while (listNext(l));
709 
710     *len = nbytes;
711     *ptr = _this->rawdata;
712     *tag = T_glyf;
713 
714     return TTCR_OK;
715 }
716 
717 /* cmap packers */
718 static sal_uInt8 *PackCmapType0(CmapSubTable *s, sal_uInt32 *length)
719 {
720     sal_uInt8* ptr = (sal_uInt8*)smalloc(262);
721     sal_uInt8 *p = ptr + 6;
722     sal_uInt32 i, j;
723     sal_uInt16 g;
724 
725     PutUInt16(0, ptr, 0, 1);
726     PutUInt16(262, ptr, 2, 1);
727     PutUInt16(0, ptr, 4, 1);
728 
729     for (i = 0; i < 256; i++) {
730         g = 0;
731         for (j = 0; j < s->n; j++) {
732             if (s->xc[j] == i) {
733                 g = (sal_uInt16) s->xg[j];
734             }
735         }
736         p[i] = (sal_uInt8) g;
737     }
738     *length = 262;
739     return ptr;
740 }
741 
742 static sal_uInt8 *PackCmapType6(CmapSubTable *s, sal_uInt32 *length)
743 {
744     sal_uInt8* ptr = (sal_uInt8*)smalloc(s->n*2 + 10);
745     sal_uInt8 *p = ptr + 10;
746     sal_uInt32 i, j;
747     sal_uInt16 g;
748 
749     PutUInt16(6, ptr, 0, 1);
750     PutUInt16((sal_uInt16)(s->n*2+10), ptr, 2, 1);
751     PutUInt16(0, ptr, 4, 1);
752     PutUInt16(0, ptr, 6, 1);
753     PutUInt16((sal_uInt16)(s->n), ptr, 8, 1 );
754 
755     for (i = 0; i < s->n; i++) {
756         g = 0;
757         for (j = 0; j < s->n; j++) {
758             if (s->xc[j] == i) {
759                 g = (sal_uInt16) s->xg[j];
760             }
761         }
762         PutUInt16( g, p, 2*i, 1 );
763     }
764     *length = s->n*2+10;
765     return ptr;
766 }
767 
768 
769 
770 /* XXX it only handles Format 0 encoding tables */
771 static sal_uInt8 *PackCmap(CmapSubTable *s, sal_uInt32 *length)
772 {
773     if( s->xg[s->n-1] > 0xff )
774         return PackCmapType6(s, length);
775     else
776         return PackCmapType0(s, length);
777 }
778 
779 static int GetRawData_cmap(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
780 {
781     table_cmap *t;
782     sal_uInt32 i;
783     sal_uInt32 tlen = 0;
784     sal_uInt32 l;
785     sal_uInt32 cmapsize;
786     sal_uInt8 *cmap;
787     sal_uInt32 coffset;
788 
789     assert(_this != 0);
790     t = (table_cmap *) _this->data;
791     assert(t != 0);
792     assert(t->n != 0);
793 
794     sal_uInt8** subtables = (sal_uInt8**)scalloc(t->n, sizeof(sal_uInt8 *));
795     sal_uInt32* sizes = (sal_uInt32*)scalloc(t->n, sizeof(sal_uInt32));
796 
797     for (i = 0; i < t->n; i++) {
798         subtables[i] = PackCmap(t->s+i, &l);
799         sizes[i] = l;
800         tlen += l;
801     }
802 
803     cmapsize = tlen + 4 + 8 * t->n;
804     _this->rawdata = cmap = ttmalloc(cmapsize);
805 
806     PutUInt16(0, cmap, 0, 1);
807     PutUInt16((sal_uInt16)t->n, cmap, 2, 1);
808     coffset = 4 + t->n * 8;
809 
810     for (i = 0; i < t->n; i++) {
811         PutUInt16((sal_uInt16)(t->s[i].id >> 16), cmap + 4, i * 8, 1);
812         PutUInt16((sal_uInt16)(t->s[i].id & 0xFF), cmap + 4, 2 + i * 8, 1);
813         PutUInt32(coffset, cmap + 4, 4 + i * 8, 1);
814         memcpy(cmap + coffset, subtables[i], sizes[i]);
815         free(subtables[i]);
816         coffset += sizes[i];
817     }
818 
819     free(subtables);
820     free(sizes);
821 
822     *ptr = cmap;
823     *len = cmapsize;
824     *tag = T_cmap;
825 
826     return TTCR_OK;
827 }
828 
829 
830 static int GetRawData_name(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
831 {
832     list l;
833     sal_Int16 i=0, n;                          /* number of Name Records */
834     int stringLen = 0;
835     sal_uInt8 *p1, *p2;
836 
837     *ptr = 0;
838     *len = 0;
839     *tag = 0;
840 
841     assert(_this != 0);
842     l = (list) _this->data;
843     assert(l != 0);
844 
845     if ((n = (sal_Int16)listCount(l)) == 0) return TTCR_NONAMES;
846 
847     NameRecord* nr = (NameRecord*)scalloc(n, sizeof(NameRecord));
848 
849     listToFirst(l);
850 
851     do {
852         memcpy(nr+i, listCurrent(l), sizeof(NameRecord));
853         stringLen += nr[i].slen;
854         i++;
855     } while (listNext(l));
856 
857     if (stringLen > 65535) {
858         free(nr);
859         return TTCR_NAMETOOLONG;
860     }
861 
862     qsort(nr, n, sizeof(NameRecord), NameRecordCompareF);
863 
864     int nameLen = stringLen + 12 * n + 6;
865     sal_uInt8* name = (sal_uInt8*)ttmalloc(nameLen);
866 
867     PutUInt16(0, name, 0, 1);
868     PutUInt16(n, name, 2, 1);
869     PutUInt16((sal_uInt16)(6 + 12 * n), name, 4, 1);
870 
871     p1 = name + 6;
872     p2 = p1 + 12 * n;
873 
874     for (i = 0; i < n; i++) {
875         PutUInt16(nr[i].platformID, p1, 0, 1);
876         PutUInt16(nr[i].encodingID, p1, 2, 1);
877         PutUInt16(nr[i].languageID, p1, 4, 1);
878         PutUInt16(nr[i].nameID, p1, 6, 1);
879         PutUInt16(nr[i].slen, p1, 8, 1);
880         PutUInt16((sal_uInt16)(p2 - (name + 6 + 12 * n)), p1, 10, 1);
881         memcpy(p2, nr[i].sptr, nr[i].slen);
882         /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */
883         p2 += nr[i].slen;
884         p1 += 12;
885     }
886 
887     free(nr);
888     _this->rawdata = name;
889 
890     *ptr = name;
891     *len = (sal_uInt16)nameLen;
892     *tag = T_name;
893 
894     /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */
895 
896     return TTCR_OK;
897 }
898 
899 static int GetRawData_post(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
900 {
901     tdata_post *p = (tdata_post *) _this->data;
902     sal_uInt8 *post = 0;
903     sal_uInt32 postLen = 0;
904     int ret;
905 
906     if (_this->rawdata) free(_this->rawdata);
907 
908     if (p->format == 0x00030000) {
909         postLen = 32;
910         post = ttmalloc(postLen);
911         PutUInt32(0x00030000, post, 0, 1);
912         PutUInt32(p->italicAngle, post, 4, 1);
913         PutUInt16(p->underlinePosition, post, 8, 1);
914         PutUInt16(p->underlineThickness, post, 10, 1);
915         PutUInt16((sal_uInt16)p->isFixedPitch, post, 12, 1);
916         ret = TTCR_OK;
917     } else {
918         fprintf(stderr, "Unrecognized format of a post table: %08X.\n", (int)p->format);
919         ret = TTCR_POSTFORMAT;
920     }
921 
922     *ptr = _this->rawdata = post;
923     *len = postLen;
924     *tag = T_post;
925 
926     return ret;
927 }
928 
929 
930 
931 
932 
933 static struct {
934     sal_uInt32 tag;
935     int (*f)(TrueTypeTable *, sal_uInt8 **, sal_uInt32 *, sal_uInt32 *);
936 } vtable2[] =
937 {
938     {0,      GetRawData_generic},
939     {T_head, GetRawData_head},
940     {T_hhea, GetRawData_hhea},
941     {T_loca, GetRawData_loca},
942     {T_maxp, GetRawData_maxp},
943     {T_glyf, GetRawData_glyf},
944     {T_cmap, GetRawData_cmap},
945     {T_name, GetRawData_name},
946     {T_post, GetRawData_post}
947 
948 
949 };
950 
951 /*
952  * TrueTypeTable public methods
953  */
954 
955 /* Note: Type42 fonts only need these tables:
956  *        head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm
957  *
958  * Microsoft required tables
959  *        cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2
960  *
961  * Apple required tables
962  *        cmap, glyf, head, hhea, hmtx, loca, maxp, name, post
963  *
964  */
965 
966 TrueTypeTable *TrueTypeTableNew(sal_uInt32 tag,
967                                 sal_uInt32 nbytes,
968                                 const sal_uInt8* ptr)
969 {
970     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
971     tdata_generic* pdata = (tdata_generic*)smalloc(sizeof(tdata_generic));
972     pdata->nbytes = nbytes;
973     pdata->tag = tag;
974     if (nbytes) {
975         pdata->ptr = ttmalloc(nbytes);
976         memcpy(pdata->ptr, ptr, nbytes);
977     } else {
978         pdata->ptr = 0;
979     }
980 
981     table->tag = 0;
982     table->data = pdata;
983     table->rawdata = 0;
984 
985     return table;
986 }
987 
988 TrueTypeTable *TrueTypeTableNew_head(sal_uInt32 fontRevision,
989                                      sal_uInt16 flags,
990                                      sal_uInt16 unitsPerEm,
991                                      const sal_uInt8* created,
992                                      sal_uInt16 macStyle,
993                                      sal_uInt16 lowestRecPPEM,
994                                      sal_Int16  fontDirectionHint)
995 {
996     assert(created != 0);
997 
998     TrueTypeTable* table  = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
999     sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_head);
1000 
1001 
1002     PutUInt32(0x00010000, ptr, 0, 1);             /* version */
1003     PutUInt32(fontRevision, ptr, 4, 1);
1004     PutUInt32(0x5F0F3CF5, ptr, 12, 1);            /* magic number */
1005     PutUInt16(flags, ptr, 16, 1);
1006     PutUInt16(unitsPerEm, ptr, 18, 1);
1007     memcpy(ptr+20, created, 8);                   /* Created Long Date */
1008     memset(ptr+28, 0, 8);                         /* Modified Long Date */
1009     PutUInt16(macStyle, ptr, 44, 1);
1010     PutUInt16(lowestRecPPEM, ptr, 46, 1);
1011     PutUInt16(fontDirectionHint, ptr, 48, 1);
1012     PutUInt16(0, ptr, 52, 1);                     /* glyph data format: 0 */
1013 
1014     table->data = (void *) ptr;
1015     table->tag = T_head;
1016     table->rawdata = 0;
1017 
1018     return table;
1019 }
1020 
1021 TrueTypeTable *TrueTypeTableNew_hhea(sal_Int16  ascender,
1022                                      sal_Int16  descender,
1023                                      sal_Int16  linegap,
1024                                      sal_Int16  caretSlopeRise,
1025                                      sal_Int16  caretSlopeRun)
1026 {
1027     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1028     sal_uInt8* ptr = (sal_uInt8*)ttmalloc(TABLESIZE_hhea);
1029 
1030     PutUInt32(0x00010000, ptr, 0, 1);             /* version */
1031     PutUInt16(ascender, ptr, 4, 1);
1032     PutUInt16(descender, ptr, 6, 1);
1033     PutUInt16(linegap, ptr, 8, 1);
1034     PutUInt16(caretSlopeRise, ptr, 18, 1);
1035     PutUInt16(caretSlopeRun, ptr, 20, 1);
1036     PutUInt16(0, ptr, 22, 1);                     /* reserved 1 */
1037     PutUInt16(0, ptr, 24, 1);                     /* reserved 2 */
1038     PutUInt16(0, ptr, 26, 1);                     /* reserved 3 */
1039     PutUInt16(0, ptr, 28, 1);                     /* reserved 4 */
1040     PutUInt16(0, ptr, 30, 1);                     /* reserved 5 */
1041     PutUInt16(0, ptr, 32, 1);                     /* metricDataFormat */
1042 
1043     table->data = (void *) ptr;
1044     table->tag = T_hhea;
1045     table->rawdata = 0;
1046 
1047     return table;
1048 }
1049 
1050 TrueTypeTable *TrueTypeTableNew_loca(void)
1051 {
1052     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1053     table->data = smalloc(sizeof(tdata_loca));
1054 
1055     ((tdata_loca *)table->data)->nbytes = 0;
1056     ((tdata_loca *)table->data)->ptr = 0;
1057 
1058     table->tag = T_loca;
1059     table->rawdata = 0;
1060 
1061     return table;
1062 }
1063 
1064 TrueTypeTable *TrueTypeTableNew_maxp( const sal_uInt8* maxp, int size)
1065 {
1066     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1067     table->data = ttmalloc(TABLESIZE_maxp);
1068 
1069     if (maxp && size == TABLESIZE_maxp) {
1070         memcpy(table->data, maxp, TABLESIZE_maxp);
1071     }
1072 
1073     table->tag = T_maxp;
1074     table->rawdata = 0;
1075 
1076     return table;
1077 }
1078 
1079 TrueTypeTable *TrueTypeTableNew_glyf(void)
1080 {
1081     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1082     list l = listNewEmpty();
1083 
1084     assert(l != 0);
1085 
1086     listSetElementDtor(l, (list_destructor)FreeGlyphData);
1087 
1088     table->data = l;
1089     table->rawdata = 0;
1090     table->tag = T_glyf;
1091 
1092     return table;
1093 }
1094 
1095 TrueTypeTable *TrueTypeTableNew_cmap(void)
1096 {
1097     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1098     table_cmap* cmap = (table_cmap*)smalloc(sizeof(table_cmap));
1099 
1100     cmap->n = 0;
1101     cmap->m = CMAP_SUBTABLE_INIT;
1102     cmap->s = (CmapSubTable *) scalloc(CMAP_SUBTABLE_INIT, sizeof(CmapSubTable));
1103     memset(cmap->s, 0, sizeof(CmapSubTable) * CMAP_SUBTABLE_INIT);
1104 
1105     table->data = (table_cmap *) cmap;
1106 
1107     table->rawdata = 0;
1108     table->tag = T_cmap;
1109 
1110     return table;
1111 }
1112 
1113 static void DisposeNameRecord(void *ptr)
1114 {
1115     if (ptr != 0) {
1116         NameRecord *nr = (NameRecord *) ptr;
1117         if (nr->sptr) free(nr->sptr);
1118         free(ptr);
1119     }
1120 }
1121 
1122 static NameRecord* NameRecordNewCopy(NameRecord *nr)
1123 {
1124     NameRecord* p = (NameRecord*)smalloc(sizeof(NameRecord));
1125 
1126     memcpy(p, nr, sizeof(NameRecord));
1127 
1128     if (p->slen) {
1129         p->sptr = (sal_uInt8*)smalloc(p->slen);
1130         memcpy(p->sptr, nr->sptr, p->slen);
1131     }
1132 
1133     return p;
1134 }
1135 
1136 TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr)
1137 {
1138     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1139     list l = listNewEmpty();
1140 
1141     assert(l != 0);
1142 
1143     listSetElementDtor(l, (list_destructor)DisposeNameRecord);
1144 
1145     if (n != 0) {
1146         int i;
1147         for (i = 0; i < n; i++) {
1148             listAppend(l, NameRecordNewCopy(nr+i));
1149         }
1150     }
1151 
1152     table->data = l;
1153     table->rawdata = 0;
1154     table->tag = T_name;
1155 
1156     return table;
1157 }
1158 
1159 TrueTypeTable *TrueTypeTableNew_post(sal_uInt32 format,
1160                                      sal_uInt32 italicAngle,
1161                                      sal_Int16 underlinePosition,
1162                                      sal_Int16 underlineThickness,
1163                                      sal_uInt32 isFixedPitch)
1164 {
1165     assert(format == 0x00030000);                 /* Only format 3.0 is supported at this time */
1166     TrueTypeTable* table = (TrueTypeTable*)smalloc(sizeof(TrueTypeTable));
1167     tdata_post* post = (tdata_post*)smalloc(sizeof(tdata_post));
1168 
1169     post->format = format;
1170     post->italicAngle = italicAngle;
1171     post->underlinePosition = underlinePosition;
1172     post->underlineThickness = underlineThickness;
1173     post->isFixedPitch = isFixedPitch;
1174     post->ptr = 0;
1175 
1176     table->data = post;
1177     table->rawdata = 0;
1178     table->tag = T_post;
1179 
1180     return table;
1181 }
1182 
1183 int GetRawData(TrueTypeTable *_this, sal_uInt8 **ptr, sal_uInt32 *len, sal_uInt32 *tag)
1184 {
1185     /* XXX do a binary search */
1186     unsigned int i;
1187 
1188     assert(_this != 0);
1189     assert(ptr != 0);
1190     assert(len != 0);
1191     assert(tag != 0);
1192 
1193     *ptr = 0; *len = 0; *tag = 0;
1194 
1195     if (_this->rawdata) {
1196         free(_this->rawdata);
1197         _this->rawdata = 0;
1198     }
1199 
1200     for(i=0; i < sizeof(vtable2)/sizeof(*vtable2); i++) {
1201         if (_this->tag == vtable2[i].tag) {
1202             return vtable2[i].f(_this, ptr, len, tag);
1203         }
1204     }
1205 
1206     assert(!"Unknwon TrueType table.\n");
1207     return TTCR_UNKNOWN;
1208 }
1209 
1210 void cmapAdd(TrueTypeTable *table, sal_uInt32 id, sal_uInt32 c, sal_uInt32 g)
1211 {
1212     sal_uInt32 i, found;
1213     table_cmap *t;
1214     CmapSubTable *s;
1215 
1216     assert(table != 0);
1217     assert(table->tag == T_cmap);
1218     t = (table_cmap *) table->data; assert(t != 0);
1219     s = t->s; assert(s != 0);
1220 
1221     found = 0;
1222 
1223     for (i = 0; i < t->n; i++) {
1224         if (s[i].id == id) {
1225             found = 1;
1226             break;
1227         }
1228     }
1229 
1230     if (!found) {
1231         if (t->n == t->m) {
1232             CmapSubTable* tmp = (CmapSubTable*)scalloc(t->m + CMAP_SUBTABLE_INCR, sizeof(CmapSubTable));
1233             memset(tmp, 0, t->m + CMAP_SUBTABLE_INCR * sizeof(CmapSubTable));
1234             memcpy(tmp, s, sizeof(CmapSubTable) * t->m);
1235             t->m += CMAP_SUBTABLE_INCR;
1236             free(s);
1237             s = tmp;
1238             t->s = s;
1239         }
1240 
1241         for (i = 0; i < t->n; i++) {
1242             if (s[i].id > id) break;
1243         }
1244 
1245         if (i < t->n) {
1246             memmove(s+i+1, s+i, t->n-i);
1247         }
1248 
1249         t->n++;
1250 
1251         s[i].id = id;
1252         s[i].n = 0;
1253         s[i].m = CMAP_PAIR_INIT;
1254         s[i].xc = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32));
1255         s[i].xg = (sal_uInt32*)scalloc(CMAP_PAIR_INIT, sizeof(sal_uInt32));
1256     }
1257 
1258     if (s[i].n == s[i].m) {
1259         sal_uInt32* tmp1 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32));
1260         sal_uInt32* tmp2 = (sal_uInt32*)scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(sal_uInt32));
1261         assert(tmp1 != 0);
1262         assert(tmp2 != 0);
1263         memcpy(tmp1, s[i].xc, sizeof(sal_uInt32) * s[i].m);
1264         memcpy(tmp2, s[i].xg, sizeof(sal_uInt32) * s[i].m);
1265         s[i].m += CMAP_PAIR_INCR;
1266         free(s[i].xc);
1267         free(s[i].xg);
1268         s[i].xc = tmp1;
1269         s[i].xg = tmp2;
1270     }
1271 
1272     s[i].xc[s[i].n] = c;
1273     s[i].xg[s[i].n] = g;
1274     s[i].n++;
1275 }
1276 
1277 sal_uInt32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, TrueTypeFont *fnt)
1278 {
1279     list l;
1280     sal_uInt32 currentID;
1281     int ret, n, ncomponents;
1282     GlyphData *gd;
1283 
1284     assert(table != 0);
1285     assert(table->tag == T_glyf);
1286 
1287     if (!glyphdata) return (sal_uInt32)~0;
1288 
1289     std::vector< sal_uInt32 > glyphlist;
1290 
1291     ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist);
1292 
1293     l = (list) table->data;
1294     if (listCount(l) > 0) {
1295         listToLast(l);
1296         ret = n = ((GlyphData *) listCurrent(l))->newID + 1;
1297     } else {
1298         ret = n = 0;
1299     }
1300     glyphdata->newID = n++;
1301     listAppend(l, glyphdata);
1302 
1303     if (ncomponents > 1 && glyphlist.size() > 1 )
1304     {
1305         std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
1306         ++it;
1307         /* glyphData->glyphID is always the first glyph on the list */
1308         do
1309         {
1310             int found = 0;
1311             currentID = *it;
1312             /* XXX expensive! should be rewritten with sorted arrays! */
1313             listToFirst(l);
1314             do {
1315                 if (((GlyphData *) listCurrent(l))->glyphID == currentID) {
1316                     found = 1;
1317                     break;
1318                 }
1319             } while (listNext(l));
1320 
1321             if (!found) {
1322                 gd = GetTTRawGlyphData(fnt, currentID);
1323                 gd->newID = n++;
1324                 listAppend(l, gd);
1325             }
1326         } while( ++it !=  glyphlist.end() );
1327     }
1328 
1329     return ret;
1330 }
1331 
1332 sal_uInt32 glyfCount(const TrueTypeTable *table)
1333 {
1334     assert(table != 0);
1335     assert(table->tag == T_glyf);
1336     return listCount((list) table->data);
1337 }
1338 
1339 
1340 void nameAdd(TrueTypeTable *table, NameRecord *nr)
1341 {
1342     list l;
1343 
1344     assert(table != 0);
1345     assert(table->tag == T_name);
1346 
1347     l = (list) table->data;
1348 
1349     listAppend(l, NameRecordNewCopy(nr));
1350 }
1351 
1352 static TrueTypeTable *FindTable(TrueTypeCreator *tt, sal_uInt32 tag)
1353 {
1354     if (listIsEmpty(tt->tables)) return 0;
1355 
1356     listToFirst(tt->tables);
1357 
1358     do {
1359         if (((TrueTypeTable *) listCurrent(tt->tables))->tag == tag) {
1360             return (TrueTypeTable*)listCurrent(tt->tables);
1361         }
1362     } while (listNext(tt->tables));
1363 
1364     return 0;
1365 }
1366 
1367 /* This function processes all the tables and synchronizes them before creating
1368  * the output TrueType stream.
1369  *
1370  * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' ***
1371  *
1372  * It does:
1373  *
1374  * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables.
1375  * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table.
1376  * - Stores indexToLocFormat in 'head'
1377  * - updates 'maxp' table
1378  * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics
1379  *   in 'hhea' table
1380  *
1381  */
1382 static void ProcessTables(TrueTypeCreator *tt)
1383 {
1384     TrueTypeTable *glyf, *loca, *head, *maxp, *hhea;
1385     list glyphlist;
1386     sal_uInt32 nGlyphs, locaLen = 0, glyfLen = 0;
1387     sal_Int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0;
1388     sal_uInt32 i = 0;
1389     sal_Int16 indexToLocFormat;
1390     sal_uInt8 *hmtxPtr, *hheaPtr;
1391     sal_uInt32 hmtxSize;
1392     sal_uInt8 *p1, *p2;
1393     sal_uInt16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0;
1394     int nlsb = 0;
1395     sal_uInt32 *gid;                        /* array of old glyphIDs */
1396 
1397     glyf = FindTable(tt, T_glyf);
1398     glyphlist = (list) glyf->data;
1399     nGlyphs = listCount(glyphlist);
1400     assert(nGlyphs != 0);
1401     gid = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32));
1402 
1403     RemoveTable(tt, T_loca);
1404     RemoveTable(tt, T_hmtx);
1405 
1406     /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */
1407 
1408     listToFirst(glyphlist);
1409     do {
1410         GlyphData *gd = (GlyphData *) listCurrent(glyphlist);
1411         sal_Int16 z;
1412         glyfLen += gd->nbytes;
1413         /* XXX if (gd->nbytes & 1) glyfLen++; */
1414 
1415 
1416         assert(gd->newID == i);
1417         gid[i++] = gd->glyphID;
1418         /* gd->glyphID = i++; */
1419 
1420         /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */
1421 
1422         if (gd->nbytes != 0) {
1423             z = GetInt16(gd->ptr, 2, 1);
1424             if (z < xMin) xMin = z;
1425 
1426             z = GetInt16(gd->ptr, 4, 1);
1427             if (z < yMin) yMin = z;
1428 
1429             z = GetInt16(gd->ptr, 6, 1);
1430             if (z > xMax) xMax = z;
1431 
1432             z = GetInt16(gd->ptr, 8, 1);
1433             if (z > yMax) yMax = z;
1434         }
1435 
1436         if (gd->compflag == 0) {                            /* non-composite glyph */
1437             if (gd->npoints > maxPoints) maxPoints = gd->npoints;
1438             if (gd->ncontours > maxContours) maxContours = gd->ncontours;
1439         } else {                                            /* composite glyph */
1440             if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints;
1441             if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours;
1442         }
1443 
1444     } while (listNext(glyphlist));
1445 
1446     indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0;
1447     locaLen = indexToLocFormat ?  (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1;
1448 
1449     sal_uInt8* glyfPtr = ttmalloc(glyfLen);
1450     sal_uInt8* locaPtr = ttmalloc(locaLen);
1451     TTSimpleGlyphMetrics* met = (TTSimpleGlyphMetrics*)scalloc(nGlyphs, sizeof(TTSimpleGlyphMetrics));
1452     i = 0;
1453 
1454     listToFirst(glyphlist);
1455     p1 = glyfPtr;
1456     p2 = locaPtr;
1457     do {
1458         GlyphData *gd = (GlyphData *) listCurrent(glyphlist);
1459 
1460         if (gd->compflag) {                       /* re-number all components */
1461             sal_uInt16 flags, index;
1462             sal_uInt8 *ptr = gd->ptr + 10;
1463             do {
1464                 sal_uInt32 j;
1465                 flags = GetUInt16(ptr, 0, 1);
1466                 index = GetUInt16(ptr, 2, 1);
1467                 /* XXX use the sorted array of old to new glyphID mapping and do a binary search */
1468                 for (j = 0; j < nGlyphs; j++) {
1469                     if (gid[j] == index) {
1470                         break;
1471                     }
1472                 }
1473                 /* printf("X: %d -> %d.\n", index, j); */
1474 
1475                 PutUInt16((sal_uInt16) j, ptr, 2, 1);
1476 
1477                 ptr += 4;
1478 
1479                 if (flags & ARG_1_AND_2_ARE_WORDS) {
1480                     ptr += 4;
1481                 } else {
1482                     ptr += 2;
1483                 }
1484 
1485                 if (flags & WE_HAVE_A_SCALE) {
1486                     ptr += 2;
1487                 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
1488                     ptr += 4;
1489                 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
1490                     ptr += 8;
1491                 }
1492             } while (flags & MORE_COMPONENTS);
1493         }
1494 
1495         if (gd->nbytes != 0) {
1496             memcpy(p1, gd->ptr, gd->nbytes);
1497         }
1498         if (indexToLocFormat == 1) {
1499             PutUInt32(p1 - glyfPtr, p2, 0, 1);
1500             p2 += 4;
1501         } else {
1502             PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1);
1503             p2 += 2;
1504         }
1505         p1 += gd->nbytes;
1506 
1507         /* fill the array of metrics */
1508         met[i].adv = gd->aw;
1509         met[i].sb  = gd->lsb;
1510         i++;
1511     } while (listNext(glyphlist));
1512 
1513     free(gid);
1514 
1515     if (indexToLocFormat == 1) {
1516         PutUInt32(p1 - glyfPtr, p2, 0, 1);
1517     } else {
1518         PutUInt16((sal_uInt16)((p1 - glyfPtr) >> 1), p2, 0, 1);
1519     }
1520 
1521     glyf->rawdata = glyfPtr;
1522 
1523     loca = TrueTypeTableNew_loca(); assert(loca != 0);
1524     ((tdata_loca *) loca->data)->ptr = locaPtr;
1525     ((tdata_loca *) loca->data)->nbytes = locaLen;
1526 
1527     AddTable(tt, loca);
1528 
1529     head = FindTable(tt, T_head);
1530     sal_uInt8* const pHeadData = (sal_uInt8*)head->data;
1531     PutInt16(xMin, pHeadData, 36, 1);
1532     PutInt16(yMin, pHeadData, 38, 1);
1533     PutInt16(xMax, pHeadData, 40, 1);
1534     PutInt16(yMax, pHeadData, 42, 1);
1535     PutInt16(indexToLocFormat, pHeadData,  50, 1);
1536 
1537     maxp = FindTable(tt, T_maxp);
1538 
1539     sal_uInt8* const pMaxpData = (sal_uInt8*)maxp->data;
1540     PutUInt16((sal_uInt16)nGlyphs, pMaxpData, 4, 1);
1541     PutUInt16(maxPoints, pMaxpData, 6, 1);
1542     PutUInt16(maxContours, pMaxpData, 8, 1);
1543     PutUInt16(maxCompositePoints, pMaxpData, 10, 1);
1544     PutUInt16(maxCompositeContours, pMaxpData, 12, 1);
1545 
1546 #if 0
1547     /* XXX do not overwrite the existing data. Fix: re-calculate these numbers here */
1548     PutUInt16(2, maxp->data, 14, 1);                        /* maxZones is always 2       */
1549     PutUInt16(0, maxp->data, 16, 1);                        /* maxTwilightPoints          */
1550     PutUInt16(0, maxp->data, 18, 1);                        /* maxStorage                 */
1551     PutUInt16(0, maxp->data, 20, 1);                        /* maxFunctionDefs            */
1552     PutUint16(0, maxp->data, 22, 1);                        /* maxInstructionDefs         */
1553     PutUint16(0, maxp->data, 24, 1);                        /* maxStackElements           */
1554     PutUint16(0, maxp->data, 26, 1);                        /* maxSizeOfInstructions      */
1555     PutUint16(0, maxp->data, 28, 1);                        /* maxComponentElements       */
1556     PutUint16(0, maxp->data, 30, 1);                        /* maxComponentDepth          */
1557 #endif
1558 
1559     /*
1560      * Generate an htmx table and update hhea table
1561      */
1562     hhea = FindTable(tt, T_hhea); assert(hhea != 0);
1563     hheaPtr = (sal_uInt8 *) hhea->data;
1564     if (nGlyphs > 2) {
1565         for (i = nGlyphs - 1; i > 0; i--) {
1566             if (met[i].adv != met[i-1].adv) break;
1567         }
1568         nlsb = nGlyphs - 1 - i;
1569     }
1570     hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2;
1571     hmtxPtr = ttmalloc(hmtxSize);
1572     p1 = hmtxPtr;
1573 
1574     for (i = 0; i < nGlyphs; i++) {
1575         if (i < nGlyphs - nlsb) {
1576             PutUInt16(met[i].adv, p1, 0, 1);
1577             PutUInt16(met[i].sb, p1, 2, 1);
1578             p1 += 4;
1579         } else {
1580             PutUInt16(met[i].sb, p1, 0, 1);
1581             p1 += 2;
1582         }
1583     }
1584 
1585     AddTable(tt, TrueTypeTableNew(T_hmtx, hmtxSize, hmtxPtr));
1586     PutUInt16((sal_uInt16)(nGlyphs - nlsb), hheaPtr, 34, 1);
1587     free(hmtxPtr);
1588     free(met);
1589 }
1590 
1591 } // namespace vcl
1592 
1593 extern "C"
1594 {
1595     /**
1596      * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it.
1597      */
1598      void TrueTypeCreatorDispose(vcl::TrueTypeCreator *_this)
1599     {
1600         listDispose(_this->tables);
1601         free(_this);
1602     }
1603 
1604 
1605     /**
1606      * Destructor for the TrueTypeTable object.
1607      */
1608      void TrueTypeTableDispose(vcl::TrueTypeTable *_this)
1609     {
1610         /* XXX do a binary search */
1611         unsigned int i;
1612 
1613         assert(_this != 0);
1614 
1615         if (_this->rawdata) free(_this->rawdata);
1616 
1617         for(i=0; i < sizeof(vcl::vtable1)/sizeof(*vcl::vtable1); i++) {
1618             if (_this->tag == vcl::vtable1[i].tag) {
1619                 vcl::vtable1[i].f(_this);
1620                 return;
1621             }
1622         }
1623         assert(!"Unknown TrueType table.\n");
1624     }
1625 }
1626 
1627 
1628 #ifdef TEST_TTCR
1629 int main(void)
1630 {
1631     TrueTypeCreator *ttcr;
1632     sal_uInt8 *t1, *t2, *t3, *t4, *t5, *t6, *t7;
1633 
1634     TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr);
1635 
1636     t1 = malloc(1000); memset(t1, 'a', 1000);
1637     t2 = malloc(2000); memset(t2, 'b', 2000);
1638     t3 = malloc(3000); memset(t3, 'c', 3000);
1639     t4 = malloc(4000); memset(t4, 'd', 4000);
1640     t5 = malloc(5000); memset(t5, 'e', 5000);
1641     t6 = malloc(6000); memset(t6, 'f', 6000);
1642     t7 = malloc(7000); memset(t7, 'g', 7000);
1643 
1644     AddTable(ttcr, TrueTypeTableNew(0x6D617870, 1000, t1));
1645     AddTable(ttcr, TrueTypeTableNew(0x4F532F32, 2000, t2));
1646     AddTable(ttcr, TrueTypeTableNew(0x636D6170, 3000, t3));
1647     AddTable(ttcr, TrueTypeTableNew(0x6C6F6361, 4000, t4));
1648     AddTable(ttcr, TrueTypeTableNew(0x68686561, 5000, t5));
1649     AddTable(ttcr, TrueTypeTableNew(0x676C7966, 6000, t6));
1650     AddTable(ttcr, TrueTypeTableNew(0x6B65726E, 7000, t7));
1651 
1652     free(t1);
1653     free(t2);
1654     free(t3);
1655     free(t4);
1656     free(t5);
1657     free(t6);
1658     free(t7);
1659 
1660 
1661     StreamToFile(ttcr, "ttcrout.ttf");
1662 
1663     TrueTypeCreatorDispose(ttcr);
1664     return 0;
1665 }
1666 #endif
1667