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