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