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