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 : : /*
31 : : * Sun Font Tools
32 : : *
33 : : * Author: Alexander Gelfenbain
34 : : *
35 : : */
36 : :
37 : : #include <assert.h>
38 : :
39 : : #include <stdlib.h>
40 : : #include <string.h>
41 : : #include <fcntl.h>
42 : : #ifdef UNX
43 : : #include <sys/mman.h>
44 : : #include <sys/stat.h>
45 : : #endif
46 : : #include "sft.hxx"
47 : : #include "gsub.h"
48 : : #if ! (defined(NO_TTCR) && defined(NO_TYPE42))
49 : : #include "ttcr.hxx"
50 : : #endif
51 : : #ifndef NO_MAPPERS /* include MapChar() and MapString() */
52 : : #include "xlat.hxx"
53 : : #endif
54 : : #ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */
55 : : #include <rtl/crc.h>
56 : : #endif
57 : :
58 : : #include <osl/endian.h>
59 : : #include <algorithm>
60 : :
61 : : namespace vcl
62 : : {
63 : :
64 : : /*- module identification */
65 : :
66 : : static const char *modname = "SunTypeTools-TT";
67 : : static const char *modver = "1.0";
68 : : static const char *modextra = "gelf";
69 : :
70 : : /*- private functions, constants and data types */ /*FOLD00*/
71 : :
72 : : enum PathSegmentType {
73 : : PS_NOOP = 0,
74 : : PS_MOVETO = 1,
75 : : PS_LINETO = 2,
76 : : PS_CURVETO = 3,
77 : : PS_CLOSEPATH = 4
78 : : };
79 : :
80 : : struct PSPathElement
81 : : {
82 : : PathSegmentType type;
83 : : int x1, y1;
84 : : int x2, y2;
85 : : int x3, y3;
86 : :
87 : 0 : PSPathElement( PathSegmentType i_eType ) : type( i_eType ),
88 : : x1( 0 ), y1( 0 ),
89 : : x2( 0 ), y2( 0 ),
90 : 0 : x3( 0 ), y3( 0 )
91 : : {
92 : 0 : }
93 : : };
94 : :
95 : : /*- In horizontal writing mode right sidebearing is calculated using this formula
96 : : *- rsb = aw - (lsb + xMax - xMin) -*/
97 : : typedef struct {
98 : : sal_Int16 xMin;
99 : : sal_Int16 yMin;
100 : : sal_Int16 xMax;
101 : : sal_Int16 yMax;
102 : : sal_uInt16 aw; /*- Advance Width (horizontal writing mode) */
103 : : sal_Int16 lsb; /*- Left sidebearing (horizontal writing mode) */
104 : : sal_uInt16 ah; /*- advance height (vertical writing mode) */
105 : : sal_Int16 tsb; /*- top sidebearing (vertical writing mode) */
106 : : } TTGlyphMetrics;
107 : :
108 : : #define HFORMAT_LINELEN 64
109 : :
110 : : typedef struct {
111 : : FILE *o;
112 : : char buffer[HFORMAT_LINELEN];
113 : : size_t bufpos;
114 : : int total;
115 : : } HexFmt;
116 : :
117 : : typedef struct {
118 : : sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */
119 : : sal_uInt32 *offs; /* array of nGlyphs offsets */
120 : : } GlyphOffsets;
121 : :
122 : : /* private tags */
123 : : static const sal_uInt32 TTFontClassTag = 0x74746663; /* 'ttfc' */
124 : :
125 : : static const sal_uInt32 T_true = 0x74727565; /* 'true' */
126 : : static const sal_uInt32 T_ttcf = 0x74746366; /* 'ttcf' */
127 : : static const sal_uInt32 T_otto = 0x4f54544f; /* 'OTTO' */
128 : :
129 : : /* standard TrueType table tags */
130 : : #define T_maxp 0x6D617870
131 : : #define T_glyf 0x676C7966
132 : : #define T_head 0x68656164
133 : : #define T_loca 0x6C6F6361
134 : : #define T_name 0x6E616D65
135 : : #define T_hhea 0x68686561
136 : : #define T_hmtx 0x686D7478
137 : : #define T_cmap 0x636D6170
138 : : #define T_vhea 0x76686561
139 : : #define T_vmtx 0x766D7478
140 : : #define T_OS2 0x4F532F32
141 : : #define T_post 0x706F7374
142 : : #define T_kern 0x6B65726E
143 : : #define T_cvt 0x63767420
144 : : #define T_prep 0x70726570
145 : : #define T_fpgm 0x6670676D
146 : : #define T_gsub 0x47535542
147 : : #define T_CFF 0x43464620
148 : :
149 : : #define LAST_URANGE_BIT 69
150 : : const char *ulcodes[LAST_URANGE_BIT+2] = {
151 : : /* 0 */ "Basic Latin",
152 : : /* 1 */ "Latin-1 Supplement",
153 : : /* 2 */ "Latin Extended-A",
154 : : /* 3 */ "Latin Extended-B",
155 : : /* 4 */ "IPA Extensions",
156 : : /* 5 */ "Spacing Modifier Letters",
157 : : /* 6 */ "Combining Diacritical Marks",
158 : : /* 7 */ "Basic Greek",
159 : : /* 8 */ "Greek Symbols And Coptic",
160 : : /* 9 */ "Cyrillic",
161 : : /* 10 */ "Armenian",
162 : : /* 11 */ "Basic Hebrew",
163 : : /* 12 */ "Hebrew Extended (A and B blocks combined)",
164 : : /* 13 */ "Basic Arabic",
165 : : /* 14 */ "Arabic Extended",
166 : : /* 15 */ "Devanagari",
167 : : /* 16 */ "Bengali",
168 : : /* 17 */ "Gurmukhi",
169 : : /* 18 */ "Gujarati",
170 : : /* 19 */ "Oriya",
171 : : /* 20 */ "Tamil",
172 : : /* 21 */ "Telugu",
173 : : /* 22 */ "Kannada",
174 : : /* 23 */ "Malayalam",
175 : : /* 24 */ "Thai",
176 : : /* 25 */ "Lao",
177 : : /* 26 */ "Basic Georgian",
178 : : /* 27 */ "Georgian Extended",
179 : : /* 28 */ "Hangul Jamo",
180 : : /* 29 */ "Latin Extended Additional",
181 : : /* 30 */ "Greek Extended",
182 : : /* 31 */ "General Punctuation",
183 : : /* 32 */ "Superscripts And Subscripts",
184 : : /* 33 */ "Currency Symbols",
185 : : /* 34 */ "Combining Diacritical Marks For Symbols",
186 : : /* 35 */ "Letterlike Symbols",
187 : : /* 36 */ "Number Forms",
188 : : /* 37 */ "Arrows",
189 : : /* 38 */ "Mathematical Operators",
190 : : /* 39 */ "Miscellaneous Technical",
191 : : /* 40 */ "Control Pictures",
192 : : /* 41 */ "Optical Character Recognition",
193 : : /* 42 */ "Enclosed Alphanumerics",
194 : : /* 43 */ "Box Drawing",
195 : : /* 44 */ "Block Elements",
196 : : /* 45 */ "Geometric Shapes",
197 : : /* 46 */ "Miscellaneous Symbols",
198 : : /* 47 */ "Dingbats",
199 : : /* 48 */ "CJK Symbols And Punctuation",
200 : : /* 49 */ "Hiragana",
201 : : /* 50 */ "Katakana",
202 : : /* 51 */ "Bopomofo",
203 : : /* 52 */ "Hangul Compatibility Jamo",
204 : : /* 53 */ "CJK Miscellaneous",
205 : : /* 54 */ "Enclosed CJK Letters And Months",
206 : : /* 55 */ "CJK Compatibility",
207 : : /* 56 */ "Hangul",
208 : : /* 57 */ "Reserved for Unicode SubRanges",
209 : : /* 58 */ "Reserved for Unicode SubRanges",
210 : : /* 59 */ "CJK Unified Ideographs",
211 : : /* 60 */ "Private Use Area",
212 : : /* 61 */ "CJK Compatibility Ideographs",
213 : : /* 62 */ "Alphabetic Presentation Forms",
214 : : /* 63 */ "Arabic Presentation Forms-A",
215 : : /* 64 */ "Combining Half Marks",
216 : : /* 65 */ "CJK Compatibility Forms",
217 : : /* 66 */ "Small Form Variants",
218 : : /* 67 */ "Arabic Presentation Forms-B",
219 : : /* 68 */ "Halfwidth And Fullwidth Forms",
220 : : /* 69 */ "Specials",
221 : : /*70-127*/ "Reserved for Unicode SubRanges"
222 : : };
223 : :
224 : :
225 : :
226 : : /*- inline functions */ /*FOLD01*/
227 : : #ifdef __GNUC__
228 : : #define _inline static __inline__
229 : : #else
230 : : #define _inline static
231 : : #endif
232 : :
233 : 0 : _inline void *smalloc(size_t size)
234 : : {
235 : 0 : void *res = malloc(size);
236 : : assert(res != 0);
237 : 0 : return res;
238 : : }
239 : :
240 : 0 : _inline void *scalloc(size_t n, size_t size)
241 : : {
242 : 0 : void *res = calloc(n, size);
243 : : assert(res != 0);
244 : 0 : return res;
245 : : }
246 : :
247 : : _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) {
248 : : return (a << 24) | (b << 16) | (c << 8) | d;
249 : : }
250 : :
251 : : /*- Data access macros for data stored in big-endian or little-endian format */
252 : 104676 : _inline sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset, int bigendian)
253 : : {
254 : : sal_Int16 t;
255 : : assert(ptr != 0);
256 : :
257 [ + - ]: 104676 : if (bigendian) {
258 : 104676 : t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
259 : : } else {
260 : 0 : t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
261 : : }
262 : :
263 : 104676 : return t;
264 : : }
265 : :
266 : 5180616 : _inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset, int bigendian)
267 : : {
268 : : sal_uInt16 t;
269 : : assert(ptr != 0);
270 : :
271 [ + - ]: 5180616 : if (bigendian) {
272 : 5180616 : t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
273 : : } else {
274 : 0 : t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
275 : : }
276 : :
277 : 5180616 : return t;
278 : : }
279 : :
280 : 17310 : _inline sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset, int bigendian)
281 : : {
282 : : sal_Int32 t;
283 : : assert(ptr != 0);
284 : :
285 [ + - ]: 17310 : if (bigendian) {
286 : 34620 : t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
287 : 17310 : (ptr+offset)[2] << 8 | (ptr+offset)[3];
288 : : } else {
289 : 0 : t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
290 : 0 : (ptr+offset)[1] << 8 | (ptr+offset)[0];
291 : : }
292 : :
293 : 17310 : return t;
294 : : }
295 : :
296 : 36543258 : _inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset, int bigendian)
297 : : {
298 : : sal_uInt32 t;
299 : : assert(ptr != 0);
300 : :
301 : :
302 [ + - ]: 36543258 : if (bigendian) {
303 : 73086516 : t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
304 : 36543258 : (ptr+offset)[2] << 8 | (ptr+offset)[3];
305 : : } else {
306 : 0 : t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
307 : 0 : (ptr+offset)[1] << 8 | (ptr+offset)[0];
308 : : }
309 : :
310 : 36543258 : return t;
311 : : }
312 : :
313 : : _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, size_t offset, int bigendian)
314 : : {
315 : : assert(ptr != 0);
316 : :
317 : : if (bigendian) {
318 : : ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
319 : : ptr[offset+1] = (sal_uInt8)(val & 0xFF);
320 : : } else {
321 : : ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
322 : : ptr[offset] = (sal_uInt8)(val & 0xFF);
323 : : }
324 : :
325 : : }
326 : :
327 : : #if defined(OSL_BIGENDIAN)
328 : : #define Int16FromMOTA(a) (a)
329 : : #define Int32FromMOTA(a) (a)
330 : : #else
331 : 0 : static sal_uInt16 Int16FromMOTA(sal_uInt16 a) {
332 : 0 : return (sal_uInt16) (((sal_uInt8)((a) >> 8)) | ((sal_uInt8)(a) << 8));
333 : : }
334 : 0 : static sal_uInt32 Int32FromMOTA(sal_uInt32 a) {
335 : 0 : return ((a>>24)&0xFF) | (((a>>8)&0xFF00) | ((a&0xFF00)<<8) | ((a&0xFF)<<24));
336 : : }
337 : : #endif
338 : :
339 : 0 : _inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b)
340 : : {
341 : : unsigned int a1, b1;
342 : : unsigned int a2, b2;
343 : : F16Dot16 res;
344 : : int sign;
345 : :
346 : 0 : sign = (a & 0x80000000) ^ (b & 0x80000000);
347 [ # # ]: 0 : if (a < 0) a = -a;
348 [ # # ]: 0 : if (b < 0) b = -b;
349 : :
350 : 0 : a1 = a >> 16;
351 : 0 : b1 = a & 0xFFFF;
352 : 0 : a2 = b >> 16;
353 : 0 : b2 = b & 0xFFFF;
354 : :
355 : 0 : res = a1 * a2;
356 : :
357 : : /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */
358 : :
359 : 0 : res <<= 16;
360 : 0 : res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16);
361 : :
362 [ # # ]: 0 : return sign ? -res : res;
363 : : }
364 : :
365 : :
366 : 0 : _inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b)
367 : : {
368 : : unsigned int f, r;
369 : : F16Dot16 res;
370 : : int sign;
371 : :
372 : 0 : sign = (a & 0x80000000) ^ (b & 0x80000000);
373 [ # # ]: 0 : if (a < 0) a = -a;
374 [ # # ]: 0 : if (b < 0) b = -b;
375 : :
376 : 0 : f = a / b;
377 : 0 : r = a % b;
378 : :
379 : : /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */
380 : :
381 [ # # ]: 0 : while (r > 0xFFFF) {
382 : 0 : r >>= 1;
383 : 0 : b >>= 1;
384 : : }
385 : :
386 : 0 : res = (f << 16) + (r << 16) / b;
387 : :
388 [ # # ]: 0 : return sign ? -res : res;
389 : : }
390 : :
391 : : /*- returns a * b / c -*/
392 : : /* XXX provide a real implementation that preserves accuracy */
393 : 0 : _inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c)
394 : : {
395 : : F16Dot16 res;
396 : :
397 : 0 : res = fixedMul(a, b);
398 : 0 : return fixedDiv(res, c);
399 : : }
400 : :
401 : : /*- Translate units from TT to PS (standard 1/1000) -*/
402 : 104676 : _inline int XUnits(int unitsPerEm, int n)
403 : : {
404 : 104676 : return (n * 1000) / unitsPerEm;
405 : : }
406 : :
407 : : _inline const char *UnicodeRangeName(sal_uInt16 bit)
408 : : {
409 : : if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1;
410 : :
411 : : return ulcodes[bit];
412 : : }
413 : :
414 : 181347 : _inline const sal_uInt8* getTable( TrueTypeFont *ttf, sal_uInt32 ord)
415 : : {
416 : 181347 : return (sal_uInt8*)ttf->tables[ord];
417 : : }
418 : :
419 : 51522 : _inline sal_uInt32 getTableSize(TrueTypeFont *ttf, sal_uInt32 ord)
420 : : {
421 : 51522 : return ttf->tlens[ord];
422 : : }
423 : :
424 : : #ifndef NO_TYPE42
425 : : /* Hex Formatter functions */
426 : : static char HexChars[] = "0123456789ABCDEF";
427 : :
428 : 0 : static HexFmt *HexFmtNew(FILE *outf)
429 : : {
430 : 0 : HexFmt* res = (HexFmt*)smalloc(sizeof(HexFmt));
431 : 0 : res->bufpos = res->total = 0;
432 : 0 : res->o = outf;
433 : 0 : return res;
434 : : }
435 : :
436 : 0 : static bool HexFmtFlush(HexFmt *_this)
437 : : {
438 : 0 : bool bRet = true;
439 [ # # ]: 0 : if (_this->bufpos) {
440 : 0 : size_t nWritten = fwrite(_this->buffer, 1, _this->bufpos, _this->o);
441 : 0 : bRet = nWritten == _this->bufpos;
442 : 0 : _this->bufpos = 0;
443 : : }
444 : 0 : return bRet;
445 : : }
446 : :
447 : 0 : _inline void HexFmtOpenString(HexFmt *_this)
448 : : {
449 : 0 : fputs("<\n", _this->o);
450 : 0 : }
451 : :
452 : 0 : _inline void HexFmtCloseString(HexFmt *_this)
453 : : {
454 : 0 : HexFmtFlush(_this);
455 : 0 : fputs("00\n>\n", _this->o);
456 : 0 : }
457 : :
458 : 0 : _inline void HexFmtDispose(HexFmt *_this)
459 : : {
460 : 0 : HexFmtFlush(_this);
461 : 0 : free(_this);
462 : 0 : }
463 : :
464 : 0 : static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size)
465 : : {
466 : : sal_uInt8 Ch;
467 : : sal_uInt32 i;
468 : :
469 [ # # ]: 0 : if (_this->total + size > 65534) {
470 : 0 : HexFmtFlush(_this);
471 : 0 : HexFmtCloseString(_this);
472 : 0 : _this->total = 0;
473 : 0 : HexFmtOpenString(_this);
474 : : }
475 [ # # ]: 0 : for (i=0; i<size; i++) {
476 : 0 : Ch = ((sal_uInt8 *) ptr)[i];
477 : 0 : _this->buffer[_this->bufpos++] = HexChars[Ch >> 4];
478 : 0 : _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF];
479 [ # # ]: 0 : if (_this->bufpos == HFORMAT_LINELEN) {
480 : 0 : HexFmtFlush(_this);
481 : 0 : fputc('\n', _this->o);
482 : : }
483 : :
484 : : }
485 : 0 : _this->total += size;
486 : 0 : }
487 : : #endif
488 : :
489 : :
490 : :
491 : : /* Outline Extraction functions */ /*FOLD01*/
492 : :
493 : : /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
494 : 0 : static void GetMetrics(TrueTypeFont *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics)
495 : : {
496 : 0 : const sal_uInt8* table = getTable( ttf, O_hmtx );
497 : :
498 : 0 : metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0;
499 [ # # ][ # # ]: 0 : if (!table || !ttf->numberOfHMetrics) return;
500 : :
501 [ # # ]: 0 : if (glyphID < ttf->numberOfHMetrics) {
502 : 0 : metrics->aw = GetUInt16(table, 4 * glyphID, 1);
503 : 0 : metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1);
504 : : } else {
505 : 0 : metrics->aw = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1);
506 : 0 : metrics->lsb = GetInt16(table + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1);
507 : : }
508 : :
509 : 0 : table = getTable(ttf, O_vmtx);
510 [ # # ][ # # ]: 0 : if( !table || !ttf->numOfLongVerMetrics )
511 : 0 : return;
512 : :
513 [ # # ]: 0 : if (glyphID < ttf->numOfLongVerMetrics) {
514 : 0 : metrics->ah = GetUInt16(table, 4 * glyphID, 1);
515 : 0 : metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1);
516 : : } else {
517 : 0 : metrics->ah = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1);
518 : 0 : metrics->tsb = GetInt16(table + ttf->numOfLongVerMetrics * 4, (glyphID - ttf->numOfLongVerMetrics) * 2, 1);
519 : : }
520 : : }
521 : :
522 : : static int GetTTGlyphOutline(TrueTypeFont *, sal_uInt32 , ControlPoint **, TTGlyphMetrics *, std::vector< sal_uInt32 >* );
523 : :
524 : : /* returns the number of control points, allocates the pointArray */
525 : 0 : static int GetSimpleTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/
526 : : {
527 : 0 : const sal_uInt8* table = getTable( ttf, O_glyf );
528 : : sal_uInt8 flag, n;
529 : 0 : sal_uInt16 t, lastPoint=0;
530 : : int i, j, z;
531 : :
532 : 0 : *pointArray = 0;
533 : :
534 : : /* printf("GetSimpleTTOutline(%d)\n", glyphID); */
535 : :
536 [ # # ]: 0 : if( glyphID >= ttf->nglyphs ) /*- glyph is not present in the font */
537 : 0 : return 0;
538 : 0 : const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
539 : 0 : const sal_Int16 numberOfContours = GetInt16(ptr, 0, 1);
540 [ # # ]: 0 : if( numberOfContours <= 0 ) /*- glyph is not simple */
541 : 0 : return 0;
542 : :
543 [ # # ]: 0 : if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
544 : 0 : metrics->xMin = GetInt16(ptr, 2, 1);
545 : 0 : metrics->yMin = GetInt16(ptr, 4, 1);
546 : 0 : metrics->xMax = GetInt16(ptr, 6, 1);
547 : 0 : metrics->yMax = GetInt16(ptr, 8, 1);
548 : 0 : GetMetrics(ttf, glyphID, metrics);
549 : : }
550 : :
551 : : /* determine the last point and be extra safe about it. But probably this code is not needed */
552 : :
553 [ # # ]: 0 : for (i=0; i<numberOfContours; i++) {
554 [ # # ]: 0 : if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t;
555 : : }
556 : :
557 : 0 : sal_uInt16 instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1);
558 : 0 : const sal_uInt8* p = ptr + 10 + 2 * numberOfContours + 2 + instLen;
559 : 0 : ControlPoint* pa = (ControlPoint*)calloc(lastPoint+1, sizeof(ControlPoint));
560 : :
561 : 0 : i = 0;
562 [ # # ]: 0 : while (i <= lastPoint) {
563 : 0 : pa[i++].flags = (sal_uInt32) (flag = *p++);
564 [ # # ]: 0 : if (flag & 8) { /*- repeat flag */
565 : 0 : n = *p++;
566 [ # # ]: 0 : for (j=0; j<n; j++) {
567 [ # # ]: 0 : if (i > lastPoint) { /*- if the font is really broken */
568 : 0 : free(pa);
569 : 0 : return 0;
570 : : }
571 : 0 : pa[i++].flags = flag;
572 : : }
573 : : }
574 : : }
575 : :
576 : : /*- Process the X coordinate */
577 : 0 : z = 0;
578 [ # # ]: 0 : for (i = 0; i <= lastPoint; i++) {
579 [ # # ]: 0 : if (pa[i].flags & 0x02) {
580 [ # # ]: 0 : if (pa[i].flags & 0x10) {
581 : 0 : z += (int) (*p++);
582 : : } else {
583 : 0 : z -= (int) (*p++);
584 : : }
585 [ # # ]: 0 : } else if ( !(pa[i].flags & 0x10)) {
586 : 0 : z += GetInt16(p, 0, 1);
587 : 0 : p += 2;
588 : : }
589 : 0 : pa[i].x = (sal_Int16)z;
590 : : }
591 : :
592 : : /*- Process the Y coordinate */
593 : 0 : z = 0;
594 [ # # ]: 0 : for (i = 0; i <= lastPoint; i++) {
595 [ # # ]: 0 : if (pa[i].flags & 0x04) {
596 [ # # ]: 0 : if (pa[i].flags & 0x20) {
597 : 0 : z += *p++;
598 : : } else {
599 : 0 : z -= *p++;
600 : : }
601 [ # # ]: 0 : } else if ( !(pa[i].flags & 0x20)) {
602 : 0 : z += GetInt16(p, 0, 1);
603 : 0 : p += 2;
604 : : }
605 : 0 : pa[i].y = (sal_Int16)z;
606 : : }
607 : :
608 [ # # ]: 0 : for (i=0; i<numberOfContours; i++) {
609 : 0 : pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000; /*- set the end contour flag */
610 : : }
611 : :
612 : 0 : *pointArray = pa;
613 : 0 : return lastPoint + 1;
614 : : }
615 : :
616 : 0 : static int GetCompoundTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >& glyphlist) /*FOLD02*/
617 : : {
618 : : sal_uInt16 flags, index;
619 : : sal_Int16 e, f, numberOfContours;
620 : 0 : const sal_uInt8* table = getTable( ttf, O_glyf );
621 [ # # ]: 0 : std::vector<ControlPoint> myPoints;
622 : : ControlPoint *nextComponent, *pa;
623 : : int i, np;
624 : 0 : F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3;
625 : :
626 : 0 : *pointArray = 0;
627 : : /* printf("GetCompoundTTOutline(%d)\n", glyphID); */
628 : :
629 [ # # ]: 0 : if (glyphID >= ttf->nglyphs) /*- incorrect glyphID */
630 : 0 : return 0;
631 : :
632 : 0 : const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
633 [ # # ]: 0 : if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) /*- glyph is not compound */
634 : 0 : return 0;
635 : :
636 [ # # ]: 0 : if (metrics) {
637 : 0 : metrics->xMin = GetInt16(ptr, 2, 1);
638 : 0 : metrics->yMin = GetInt16(ptr, 4, 1);
639 : 0 : metrics->xMax = GetInt16(ptr, 6, 1);
640 : 0 : metrics->yMax = GetInt16(ptr, 8, 1);
641 : 0 : GetMetrics(ttf, glyphID, metrics);
642 : : }
643 : :
644 : 0 : ptr += 10;
645 : :
646 [ # # ]: 0 : do {
647 : 0 : flags = GetUInt16(ptr, 0, 1);
648 : : /* printf("flags: 0x%X\n", flags); */
649 : 0 : index = GetUInt16(ptr, 2, 1);
650 : 0 : ptr += 4;
651 : :
652 [ # # ][ # # ]: 0 : if( std::find( glyphlist.begin(), glyphlist.end(), index ) != glyphlist.end() )
653 : : {
654 : : #if OSL_DEBUG_LEVEL > 1
655 : : fprintf(stderr, "Endless loop found in a compound glyph.\n");
656 : : fprintf(stderr, "%d -> ", index);
657 : : fprintf(stderr," [");
658 : : for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
659 : : it != glyphlist.end(); ++it )
660 : : {
661 : : fprintf( stderr,"%d ", (int) *it );
662 : : }
663 : : fprintf(stderr,"]\n");
664 : : /**/
665 : : #endif
666 : : }
667 : :
668 [ # # ]: 0 : glyphlist.push_back( index );
669 : :
670 [ # # ]: 0 : if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, 0, &glyphlist)) == 0)
671 : : {
672 : : /* XXX that probably indicates a corrupted font */
673 : : #if OSL_DEBUG_LEVEL > 1
674 : : fprintf(stderr, "An empty compound!\n");
675 : : /* assert(!"An empty compound"); */
676 : : #endif
677 : : }
678 : :
679 [ # # ]: 0 : if( ! glyphlist.empty() )
680 [ # # ]: 0 : glyphlist.pop_back();
681 : :
682 [ # # ]: 0 : if (flags & USE_MY_METRICS) {
683 [ # # ]: 0 : if (metrics) GetMetrics(ttf, index, metrics);
684 : : }
685 : :
686 [ # # ]: 0 : if (flags & ARG_1_AND_2_ARE_WORDS) {
687 : 0 : e = GetInt16(ptr, 0, 1);
688 : 0 : f = GetInt16(ptr, 2, 1);
689 : : /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
690 : 0 : ptr += 4;
691 : : } else {
692 [ # # ]: 0 : if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */
693 : 0 : e = (sal_Int8) *ptr++;
694 : 0 : f = (sal_Int8) *ptr++;
695 : : /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
696 : : } else { /* args are unsigned */
697 : : /* printf("!ARGS_ARE_XY_VALUES\n"); */
698 : 0 : e = *ptr++;
699 : 0 : f = *ptr++;
700 : : }
701 : :
702 : : }
703 : :
704 : 0 : a = d = 0x10000;
705 : 0 : b = c = 0;
706 : :
707 [ # # ]: 0 : if (flags & WE_HAVE_A_SCALE) {
708 : 0 : a = GetInt16(ptr, 0, 1) << 2;
709 : 0 : d = a;
710 : 0 : ptr += 2;
711 [ # # ]: 0 : } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
712 : 0 : a = GetInt16(ptr, 0, 1) << 2;
713 : 0 : d = GetInt16(ptr, 2, 1) << 2;
714 : 0 : ptr += 4;
715 [ # # ]: 0 : } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
716 : 0 : a = GetInt16(ptr, 0, 1) << 2;
717 : 0 : b = GetInt16(ptr, 2, 1) << 2;
718 : 0 : c = GetInt16(ptr, 4, 1) << 2;
719 : 0 : d = GetInt16(ptr, 6, 1) << 2;
720 : 0 : ptr += 8;
721 : : }
722 : :
723 : 0 : abs1 = (a < 0) ? -a : a;
724 : 0 : abs2 = (b < 0) ? -b : b;
725 [ # # ]: 0 : m = (abs1 > abs2) ? abs1 : abs2;
726 : 0 : abs3 = abs1 - abs2;
727 [ # # ]: 0 : if (abs3 < 0) abs3 = -abs3;
728 [ # # ]: 0 : if (abs3 <= 33) m *= 2;
729 : :
730 : 0 : abs1 = (c < 0) ? -c : c;
731 : 0 : abs2 = (d < 0) ? -d : d;
732 [ # # ]: 0 : n = (abs1 > abs2) ? abs1 : abs2;
733 : 0 : abs3 = abs1 - abs2;
734 [ # # ]: 0 : if (abs3 < 0) abs3 = -abs3;
735 [ # # ]: 0 : if (abs3 <= 33) n *= 2;
736 : :
737 : : if (!ARGS_ARE_XY_VALUES) { /* match the points */
738 : : assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n");
739 : : }
740 : :
741 [ # # ]: 0 : for (i=0; i<np; i++) {
742 : : F16Dot16 t;
743 : : ControlPoint cp;
744 : 0 : cp.flags = nextComponent[i].flags;
745 : 0 : t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16);
746 : 0 : cp.x = (sal_Int16)(fixedMul(t, m) >> 16);
747 : 0 : t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16);
748 : 0 : cp.y = (sal_Int16)(fixedMul(t, n) >> 16);
749 : :
750 [ # # ]: 0 : myPoints.push_back( cp );
751 : : }
752 : :
753 : 0 : free(nextComponent);
754 : :
755 : : } while (flags & MORE_COMPONENTS);
756 : :
757 : :
758 : :
759 : 0 : np = myPoints.size();
760 : :
761 : 0 : pa = (ControlPoint*)calloc(np, sizeof(ControlPoint));
762 : : assert(pa != 0);
763 : :
764 : 0 : memcpy( pa, &myPoints[0], np*sizeof(ControlPoint) );
765 : :
766 : 0 : *pointArray = pa;
767 : 0 : return np;
768 : : }
769 : :
770 : : /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect,
771 : : * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
772 : : *
773 : : * NOTE: glyphlist is the stack of glyphs traversed while constructing
774 : : * a composite glyph. This is a safequard against endless recursion
775 : : * in corrupted fonts.
776 : : */
777 : 0 : static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >* glyphlist)
778 : : {
779 : 0 : const sal_uInt8 *table = getTable( ttf, O_glyf );
780 : : sal_Int16 numberOfContours;
781 : : int res;
782 : 0 : *pointArray = 0;
783 : :
784 [ # # ]: 0 : if (metrics) {
785 : 0 : memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeroes */
786 : : }
787 : :
788 [ # # ]: 0 : if (glyphID >= ttf->nglyphs) return -1; /**/
789 : :
790 : 0 : const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
791 : 0 : int length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
792 : :
793 [ # # ]: 0 : if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */
794 [ # # ]: 0 : if (metrics) GetMetrics(ttf, glyphID, metrics);
795 : 0 : return 0;
796 : : }
797 : :
798 : 0 : numberOfContours = GetInt16(ptr, 0, 1);
799 : :
800 [ # # ]: 0 : if (numberOfContours >= 0)
801 : : {
802 : 0 : res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics);
803 : : }
804 : : else
805 : : {
806 [ # # ]: 0 : std::vector< sal_uInt32 > aPrivList;
807 [ # # ]: 0 : aPrivList.push_back( glyphID );
808 [ # # ][ # # ]: 0 : res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist ? *glyphlist : aPrivList );
809 : : }
810 : :
811 : 0 : return res;
812 : : }
813 : :
814 : : #ifndef NO_TYPE3
815 : :
816 : : /*- returns the number of items in the path -*/
817 : :
818 : 0 : static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path)
819 : : {
820 [ # # ]: 0 : std::vector< PSPathElement > aPathList;
821 : 0 : int nPathCount = 0;
822 : 0 : PSPathElement p( PS_NOOP );
823 : :
824 : 0 : int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury;
825 : 0 : int lastOff = 0; /*- last point was off-contour */
826 : 0 : int scflag = 1; /*- start contour flag */
827 : 0 : int ecflag = 0; /*- end contour flag */
828 : 0 : int cp = 0; /*- current point */
829 : 0 : int StartContour = 0, EndContour = 1;
830 : :
831 : 0 : *path = 0;
832 : :
833 : : /* if (srcCount > 0) for(;;) */
834 [ # # ]: 0 : while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */
835 [ # # ]: 0 : if (scflag) {
836 : 0 : int l = cp;
837 : 0 : StartContour = cp;
838 [ # # ]: 0 : while (!(srcA[l].flags & 0x8000)) l++;
839 : 0 : EndContour = l;
840 [ # # ]: 0 : if (StartContour == EndContour) {
841 [ # # ]: 0 : if (cp + 1 < srcCount) {
842 : 0 : cp++;
843 : 0 : continue;
844 : : } else {
845 : 0 : break;
846 : : }
847 : : }
848 : 0 : p = PSPathElement(PS_MOVETO);
849 [ # # ]: 0 : if (!(srcA[cp].flags & 1)) {
850 [ # # ]: 0 : if (!(srcA[EndContour].flags & 1)) {
851 : 0 : p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2;
852 : 0 : p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2;
853 : : } else {
854 : 0 : p.x1 = x0 = srcA[EndContour].x;
855 : 0 : p.y1 = y0 = srcA[EndContour].y;
856 : : }
857 : : } else {
858 : 0 : p.x1 = x0 = srcA[cp].x;
859 : 0 : p.y1 = y0 = srcA[cp].y;
860 : 0 : cp++;
861 : : }
862 [ # # ]: 0 : aPathList.push_back( p );
863 : 0 : lastOff = 0;
864 : 0 : scflag = 0;
865 : : }
866 : :
867 : 0 : curx = srcA[cp].x;
868 : 0 : cury = srcA[cp].y;
869 : :
870 [ # # ]: 0 : if (srcA[cp].flags & 1)
871 : : {
872 [ # # ]: 0 : if (lastOff)
873 : : {
874 : 0 : p = PSPathElement(PS_CURVETO);
875 : 0 : p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
876 : 0 : p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
877 : 0 : p.x2 = x1 + (curx - x1 + 1) / 3;
878 : 0 : p.y2 = y1 + (cury - y1 + 1) / 3;
879 : 0 : p.x3 = curx;
880 : 0 : p.y3 = cury;
881 [ # # ]: 0 : aPathList.push_back( p );
882 : : }
883 : : else
884 : : {
885 [ # # ][ # # ]: 0 : if (!(x0 == curx && y0 == cury))
886 : : { /* eliminate empty lines */
887 : 0 : p = PSPathElement(PS_LINETO);
888 : 0 : p.x1 = curx;
889 : 0 : p.y1 = cury;
890 [ # # ]: 0 : aPathList.push_back( p );
891 : : }
892 : : }
893 : 0 : x0 = curx; y0 = cury; lastOff = 0;
894 : : }
895 : : else
896 : : {
897 [ # # ]: 0 : if (lastOff)
898 : : {
899 : 0 : x2 = (x1 + curx + 1) / 2;
900 : 0 : y2 = (y1 + cury + 1) / 2;
901 : 0 : p = PSPathElement(PS_CURVETO);
902 : 0 : p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
903 : 0 : p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
904 : 0 : p.x2 = x1 + (x2 - x1 + 1) / 3;
905 : 0 : p.y2 = y1 + (y2 - y1 + 1) / 3;
906 : 0 : p.x3 = x2;
907 : 0 : p.y3 = y2;
908 [ # # ]: 0 : aPathList.push_back( p );
909 : 0 : x0 = x2; y0 = y2;
910 : 0 : x1 = curx; y1 = cury;
911 : : } else {
912 : 0 : x1 = curx; y1 = cury;
913 : : }
914 : 0 : lastOff = true;
915 : : }
916 : :
917 [ # # ]: 0 : if (ecflag) {
918 [ # # ]: 0 : aPathList.push_back( PSPathElement(PS_CLOSEPATH) );
919 : 0 : scflag = 1;
920 : 0 : ecflag = 0;
921 : 0 : cp = EndContour + 1;
922 [ # # ]: 0 : if (cp >= srcCount) break;
923 : 0 : continue;
924 : : }
925 : :
926 : :
927 [ # # ]: 0 : if (cp == EndContour) {
928 : 0 : cp = StartContour;
929 : 0 : ecflag = true;
930 : : } else {
931 : 0 : cp++;
932 : : }
933 : : }
934 : :
935 [ # # ]: 0 : if( (nPathCount = (int)aPathList.size()) > 0)
936 : : {
937 : 0 : *path = (PSPathElement*)calloc(nPathCount, sizeof(PSPathElement));
938 : : assert(*path != 0);
939 : 0 : memcpy( *path, &aPathList[0], nPathCount * sizeof(PSPathElement) );
940 : : }
941 : :
942 : 0 : return nPathCount;
943 : : }
944 : :
945 : : #endif
946 : :
947 : : /*- Extracts a string from the name table and allocates memory for it -*/
948 : :
949 : 25965 : static char *nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result )
950 : : {
951 : : char *res;
952 : 25965 : const sal_uInt8* ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1);
953 : 25965 : int len = GetUInt16(name+6, 12 * n + 8, 1);
954 : :
955 : : // sanity check
956 [ - + ][ + - ]: 25965 : if( (len <= 0) || ((ptr+len) > (name+nTableSize)) )
957 : : {
958 [ # # ]: 0 : if( ucs2result )
959 : 0 : *ucs2result = NULL;
960 : 0 : return NULL;
961 : : }
962 : :
963 [ + + ]: 25965 : if( ucs2result )
964 : 17310 : *ucs2result = NULL;
965 [ + + ]: 25965 : if (dbFlag) {
966 : 17310 : res = (char*)malloc(1 + len/2);
967 : : assert(res != 0);
968 [ + + ]: 294065 : for (int i = 0; i < len/2; i++)
969 : 276755 : res[i] = *(ptr + i * 2 + 1);
970 : 17310 : res[len/2] = 0;
971 [ + + ]: 17310 : if( ucs2result )
972 : : {
973 : 8655 : *ucs2result = (sal_uInt16*)malloc( len+2 );
974 [ + + ]: 133902 : for (int i = 0; i < len/2; i++ )
975 : 125247 : (*ucs2result)[i] = GetUInt16( ptr, 2*i, 1 );
976 : 8655 : (*ucs2result)[len/2] = 0;
977 : : }
978 : : } else {
979 : 8655 : res = (char*)malloc(1 + len);
980 : : assert(res != 0);
981 : 8655 : memcpy(res, ptr, len);
982 : 8655 : res[len] = 0;
983 : : }
984 : :
985 : 25965 : return res;
986 : : }
987 : :
988 : 34620 : static int findname( const sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID,
989 : : sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID )
990 : : {
991 : 34620 : int l = 0, r = n-1, i;
992 : : sal_uInt32 t1, t2;
993 : : sal_uInt32 m1, m2;
994 : :
995 [ - + ]: 34620 : if (n == 0) return -1;
996 : :
997 : 34620 : m1 = (platformID << 16) | encodingID;
998 : 34620 : m2 = (languageID << 16) | nameID;
999 : :
1000 [ + + ]: 146208 : do {
1001 : 146208 : i = (l + r) >> 1;
1002 : 146208 : t1 = GetUInt32(name + 6, i * 12 + 0, 1);
1003 : 146208 : t2 = GetUInt32(name + 6, i * 12 + 4, 1);
1004 : :
1005 [ + + ][ + + ]: 146208 : if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1;
[ + + ]
1006 [ + + ][ + + ]: 146208 : if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1;
[ + + ]
1007 : : } while (l <= r);
1008 : :
1009 [ + + ]: 34620 : if (l - r == 2) {
1010 : 25965 : return l - 1;
1011 : : }
1012 : :
1013 : 34620 : return -1;
1014 : : }
1015 : :
1016 : : /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables.
1017 : : * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
1018 : : *
1019 : : * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
1020 : : * and does not have (3, 1, 1033)
1021 : : * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
1022 : : * require a change in algorithm
1023 : : *
1024 : : * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID,
1025 : : * but (1, 0, 1042) strings usable
1026 : : * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
1027 : : */
1028 : :
1029 : 8655 : static void GetNames(TrueTypeFont *t)
1030 : : {
1031 : 8655 : const sal_uInt8* table = getTable( t, O_name );
1032 : 8655 : int nTableSize = getTableSize(t, O_name);
1033 : :
1034 [ - + ]: 8655 : if (nTableSize < 4)
1035 : : {
1036 : : #if OSL_DEBUG_LEVEL > 1
1037 : : fprintf(stderr, "O_name table too small\n");
1038 : : #endif
1039 : 8655 : return;
1040 : : }
1041 : :
1042 : 8655 : sal_uInt16 n = GetUInt16(table, 2, 1);
1043 : : int i, r;
1044 : 8655 : sal_Bool bPSNameOK = sal_True;
1045 : :
1046 : : /* #129743# simple sanity check for name table entry count */
1047 [ - + ]: 8655 : if( nTableSize <= n * 12 + 6 )
1048 : 0 : n = 0;
1049 : :
1050 : : /* PostScript name: preferred Microsoft */
1051 : 8655 : t->psname = NULL;
1052 [ + - ]: 8655 : if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1)
1053 : 8655 : t->psname = nameExtract(table, nTableSize, r, 1, NULL);
1054 [ - + ][ # # ]: 8655 : if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1)
[ - + ]
1055 : 0 : t->psname = nameExtract(table, nTableSize, r, 0, NULL);
1056 [ - + ][ # # ]: 8655 : if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1)
[ - + ]
1057 : : {
1058 : : // some symbol fonts like Marlett have a 3,0 name!
1059 : 0 : t->psname = nameExtract(table, nTableSize, r, 1, NULL);
1060 : : }
1061 : : // for embedded font in Ghostscript PDFs
1062 [ - + ][ # # ]: 8655 : if ( ! t->psname && (r = findname(table, n, 2, 2, 0, 6)) != -1)
[ - + ]
1063 : : {
1064 : 0 : t->psname = nameExtract(table, nTableSize, r, 0, NULL);
1065 : : }
1066 [ - + ]: 8655 : if ( ! t->psname )
1067 : : {
1068 [ # # ]: 0 : if ( t->fname )
1069 : : {
1070 : 0 : char* pReverse = t->fname + strlen(t->fname);
1071 : : /* take only last token of filename */
1072 [ # # ][ # # ]: 0 : while(pReverse != t->fname && *pReverse != '/') pReverse--;
[ # # ]
1073 [ # # ]: 0 : if(*pReverse == '/') pReverse++;
1074 : 0 : t->psname = strdup(pReverse);
1075 : : assert(t->psname != 0);
1076 [ # # ]: 0 : for (i=strlen(t->psname) - 1; i > 0; i--)
1077 : : {
1078 : : /*- Remove the suffix -*/
1079 [ # # ]: 0 : if (t->psname[i] == '.' ) {
1080 : 0 : t->psname[i] = 0;
1081 : 0 : break;
1082 : : }
1083 : : }
1084 : : }
1085 : : else
1086 : 0 : t->psname = strdup( "Unknown" );
1087 : : }
1088 : :
1089 : : /* Font family and subfamily names: preferred Apple */
1090 : 8655 : t->family = NULL;
1091 [ - + ]: 8655 : if ((r = findname(table, n, 0, 0, 0, 1)) != -1)
1092 : 0 : t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1093 [ + - ][ + - ]: 8655 : if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1)
[ + - ]
1094 : 8655 : t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1095 [ - + ][ # # ]: 8655 : if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1)
[ - + ]
1096 : 0 : t->family = nameExtract(table, nTableSize, r, 0, NULL);
1097 [ - + ][ # # ]: 8655 : if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1)
[ - + ]
1098 : 0 : t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1099 [ - + ][ # # ]: 8655 : if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1)
[ - + ]
1100 : 0 : t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1101 [ - + ]: 8655 : if ( ! t->family )
1102 : : {
1103 : 0 : t->family = strdup(t->psname);
1104 : : assert(t->family != 0);
1105 : : }
1106 : :
1107 : 8655 : t->subfamily = NULL;
1108 : 8655 : t->usubfamily = NULL;
1109 [ + - ]: 8655 : if ((r = findname(table, n, 1, 0, 0, 2)) != -1)
1110 : 8655 : t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily);
1111 [ - + ][ # # ]: 8655 : if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1)
[ - + ]
1112 : 0 : t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily);
1113 [ - + ]: 8655 : if ( ! t->subfamily )
1114 : : {
1115 : 0 : t->subfamily = strdup("");
1116 : : }
1117 : :
1118 : : /* #i60349# sanity check psname
1119 : : * psname parctically has to be 7bit ascii and should not contains spaces
1120 : : * there is a class of broken fonts which do not fullfill that at all, so let's try
1121 : : * if the family name is 7bit ascii and take it instead if so
1122 : : */
1123 : : /* check psname */
1124 [ + + ][ + - ]: 160163 : for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ )
[ + + ]
1125 [ + - ][ - + ]: 151508 : if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) )
1126 : 0 : bPSNameOK = sal_False;
1127 [ - + ]: 8655 : if( bPSNameOK == sal_False )
1128 : : {
1129 : 0 : sal_Bool bReplace = sal_True;
1130 : : /* check if family is a suitable replacement */
1131 [ # # ][ # # ]: 0 : if( t->ufamily && t->family )
1132 : : {
1133 [ # # ][ # # ]: 0 : for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ )
[ # # ]
1134 [ # # ][ # # ]: 0 : if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 )
1135 : 0 : bReplace = sal_False;
1136 [ # # ]: 0 : if( bReplace )
1137 : : {
1138 : 0 : free( t->psname );
1139 : 0 : t->psname = strdup( t->family );
1140 : : }
1141 : : }
1142 : : }
1143 : : }
1144 : :
1145 : : enum cmapType {
1146 : : CMAP_NOT_USABLE = -1,
1147 : : CMAP_MS_Symbol = 10,
1148 : : CMAP_MS_Unicode = 11,
1149 : : CMAP_MS_ShiftJIS = 12,
1150 : : CMAP_MS_Big5 = 13,
1151 : : CMAP_MS_PRC = 14,
1152 : : CMAP_MS_Wansung = 15,
1153 : : CMAP_MS_Johab = 16
1154 : : };
1155 : :
1156 : : #define MISSING_GLYPH_INDEX 0
1157 : :
1158 : : /*
1159 : : * getGlyph[0246]() functions and freinds are implemented by:
1160 : : * @author Manpreet Singh
1161 : : * getGlyph12() function and friends by:
1162 : : * @author HDU
1163 : : */
1164 : 0 : static sal_uInt32 getGlyph0(const sal_uInt8* cmap, sal_uInt32 c) {
1165 [ # # ]: 0 : if (c <= 255) {
1166 : 0 : return *(cmap + 6 + c);
1167 : : } else {
1168 : 0 : return MISSING_GLYPH_INDEX;
1169 : : }
1170 : : }
1171 : :
1172 : : typedef struct _subHeader2 {
1173 : : sal_uInt16 firstCode;
1174 : : sal_uInt16 entryCount;
1175 : : sal_uInt16 idDelta;
1176 : : sal_uInt16 idRangeOffset;
1177 : : } subHeader2;
1178 : :
1179 : 0 : static sal_uInt32 getGlyph2(const sal_uInt8 *cmap, sal_uInt32 c) {
1180 : 0 : sal_uInt16 *CMAP2 = (sal_uInt16 *) cmap;
1181 : : sal_uInt8 theHighByte;
1182 : :
1183 : : sal_uInt8 theLowByte;
1184 : : subHeader2* subHeader2s;
1185 : : sal_uInt16* subHeader2Keys;
1186 : : sal_uInt16 firstCode;
1187 : : int k;
1188 : : sal_uInt32 ToReturn;
1189 : :
1190 : 0 : theHighByte = (sal_uInt8)((c >> 8) & 0x00ff);
1191 : 0 : theLowByte = (sal_uInt8)(c & 0x00ff);
1192 : 0 : subHeader2Keys = CMAP2 + 3;
1193 : 0 : subHeader2s = (subHeader2 *)(subHeader2Keys + 256);
1194 : 0 : k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8;
1195 : :
1196 [ # # ]: 0 : if(k == 0) {
1197 : 0 : firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
1198 [ # # ][ # # ]: 0 : if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
[ # # ]
1199 : : return *((&(subHeader2s[0].idRangeOffset))
1200 : 0 : + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */
1201 : 0 : + theLowByte /* + to_look */
1202 : 0 : - Int16FromMOTA(subHeader2s[0].firstCode)
1203 : 0 : );
1204 : : } else {
1205 : 0 : return MISSING_GLYPH_INDEX;
1206 : : }
1207 [ # # ]: 0 : } else if (k > 0) {
1208 : 0 : firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
1209 [ # # ][ # # ]: 0 : if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
[ # # ]
1210 : 0 : ToReturn = *((&(subHeader2s[k].idRangeOffset))
1211 : 0 : + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2)
1212 : 0 : + theLowByte - firstCode);
1213 [ # # ]: 0 : if(ToReturn == 0) {
1214 : 0 : return MISSING_GLYPH_INDEX;
1215 : : } else {
1216 : 0 : ToReturn += Int16FromMOTA(subHeader2s[k].idDelta);
1217 : 0 : return (ToReturn & 0xFFFF);
1218 : : }
1219 : : } else {
1220 : 0 : return MISSING_GLYPH_INDEX;
1221 : : }
1222 : : } else {
1223 : 0 : return MISSING_GLYPH_INDEX;
1224 : : }
1225 : : }
1226 : :
1227 : 0 : static sal_uInt32 getGlyph6(const sal_uInt8 *cmap, sal_uInt32 c) {
1228 : : sal_uInt16 firstCode, lastCode, count;
1229 : 0 : sal_uInt16 *CMAP6 = (sal_uInt16 *) cmap;
1230 : :
1231 : 0 : firstCode = Int16FromMOTA(*(CMAP6 + 3));
1232 : 0 : count = Int16FromMOTA(*(CMAP6 + 4));
1233 : 0 : lastCode = firstCode + count - 1;
1234 [ # # ][ # # ]: 0 : if (c < firstCode || c > lastCode) {
1235 : 0 : return MISSING_GLYPH_INDEX;
1236 : : } else {
1237 : 0 : return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode));
1238 : : }
1239 : : }
1240 : :
1241 : 0 : static sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch) {
1242 : 0 : signed int low, mid, high, lastfound = 0xffff;
1243 : : sal_uInt16 res;
1244 [ # # ][ # # ]: 0 : if(length == (sal_uInt16)0 || length == (sal_uInt16)0xFFFF) {
1245 : 0 : return (sal_uInt16)0xFFFF;
1246 : : }
1247 : 0 : low = 0;
1248 : 0 : high = length - 1;
1249 [ # # ]: 0 : while(high >= low) {
1250 : 0 : mid = (high + low)/2;
1251 : 0 : res = Int16FromMOTA(*(ar+mid));
1252 [ # # ]: 0 : if(res >= toSearch) {
1253 : 0 : lastfound = mid;
1254 : 0 : high = --mid;
1255 : : } else {
1256 : 0 : low = ++mid;
1257 : : }
1258 : : }
1259 : 0 : return (sal_uInt16)lastfound;
1260 : : }
1261 : :
1262 : :
1263 : 0 : static sal_uInt32 getGlyph4(const sal_uInt8 *cmap, sal_uInt32 c) {
1264 : : sal_uInt16 i;
1265 : : int ToReturn;
1266 : : sal_uInt16 segCount;
1267 : : sal_uInt16 * startCode;
1268 : : sal_uInt16 * endCode;
1269 : : sal_uInt16 * idDelta;
1270 : : /* sal_uInt16 * glyphIdArray; */
1271 : : sal_uInt16 * idRangeOffset;
1272 : : /*sal_uInt16 * glyphIndexArray;*/
1273 : 0 : sal_uInt16 *CMAP4 = (sal_uInt16 *) cmap;
1274 : : /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */
1275 : :
1276 : 0 : segCount = Int16FromMOTA(*(CMAP4 + 3))/2;
1277 : 0 : endCode = CMAP4 + 7;
1278 : 0 : i = GEbinsearch(endCode, segCount, (sal_uInt16)c);
1279 : :
1280 [ # # ]: 0 : if (i == (sal_uInt16) 0xFFFF) {
1281 : 0 : return MISSING_GLYPH_INDEX;
1282 : : }
1283 : 0 : startCode = endCode + segCount + 1;
1284 : :
1285 [ # # ]: 0 : if(Int16FromMOTA(startCode[i]) > c) {
1286 : 0 : return MISSING_GLYPH_INDEX;
1287 : : }
1288 : 0 : idDelta = startCode + segCount;
1289 : 0 : idRangeOffset = idDelta + segCount;
1290 : : /*glyphIndexArray = idRangeOffset + segCount;*/
1291 : :
1292 [ # # ]: 0 : if(Int16FromMOTA(idRangeOffset[i]) != 0) {
1293 : 0 : c = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i])))));
1294 : : }
1295 : :
1296 : 0 : ToReturn = (Int16FromMOTA(idDelta[i]) + c) & 0xFFFF;
1297 : 0 : return ToReturn;
1298 : : }
1299 : :
1300 : 0 : static sal_uInt32 getGlyph12(const sal_uInt8 *pCmap, sal_uInt32 cChar) {
1301 : 0 : const sal_uInt32* pCMAP12 = (const sal_uInt32*)pCmap;
1302 : 0 : int nLength = Int32FromMOTA( pCMAP12[1] );
1303 : 0 : int nGroups = Int32FromMOTA( pCMAP12[3] );
1304 : 0 : int nLower = 0;
1305 : 0 : int nUpper = nGroups;
1306 : :
1307 [ # # ]: 0 : if( nUpper > (nLength-16)/12 )
1308 : 0 : nUpper = (nLength-16)/12;
1309 : :
1310 : : /* binary search in "segmented coverage" subtable */
1311 [ # # ]: 0 : while( nLower < nUpper ) {
1312 : 0 : int nIndex = (nLower + nUpper) / 2;
1313 : 0 : const sal_uInt32* pEntry = &pCMAP12[ 4 + 3*nIndex ];
1314 : 0 : sal_uInt32 cStart = Int32FromMOTA( pEntry[0] );
1315 : 0 : sal_uInt32 cLast = Int32FromMOTA( pEntry[1] );
1316 [ # # ]: 0 : if( cChar < cStart )
1317 : 0 : nUpper = nIndex;
1318 [ # # ]: 0 : else if( cChar > cLast )
1319 : 0 : nLower = nIndex + 1;
1320 : : else { /* found matching entry! */
1321 : 0 : sal_uInt32 nGlyph = Int32FromMOTA( pEntry[2] );
1322 : 0 : nGlyph += cChar - cStart;
1323 : 0 : return nGlyph;
1324 : : }
1325 : : }
1326 : :
1327 : 0 : return MISSING_GLYPH_INDEX;
1328 : : }
1329 : :
1330 : :
1331 : 8655 : static void FindCmap(TrueTypeFont *ttf)
1332 : : {
1333 : 8655 : const sal_uInt8* table = getTable(ttf, O_cmap);
1334 : 8655 : sal_uInt32 table_size = getTableSize(ttf, O_cmap);
1335 : 8655 : sal_uInt16 ncmaps = GetUInt16(table, 2, 1);
1336 : : unsigned int i;
1337 : 8655 : sal_uInt32 AppleUni = 0; // Apple Unicode
1338 : 8655 : sal_uInt32 ThreeZero = 0; /* MS Symbol */
1339 : 8655 : sal_uInt32 ThreeOne = 0; /* MS UCS-2 */
1340 : 8655 : sal_uInt32 ThreeTwo = 0; /* MS ShiftJIS */
1341 : 8655 : sal_uInt32 ThreeThree = 0; /* MS Big5 */
1342 : 8655 : sal_uInt32 ThreeFour = 0; /* MS PRC */
1343 : 8655 : sal_uInt32 ThreeFive = 0; /* MS Wansung */
1344 : 8655 : sal_uInt32 ThreeSix = 0; /* MS Johab */
1345 : :
1346 [ + + ]: 40016 : for (i = 0; i < ncmaps; i++) {
1347 : : sal_uInt32 offset;
1348 : : sal_uInt16 pID, eID;
1349 : :
1350 : : /* sanity check, cmap entry must lie within table */
1351 [ - + ]: 31361 : if( i*8+4 > table_size )
1352 : 0 : break;
1353 : :
1354 : 31361 : pID = GetUInt16(table, 4 + i * 8, 1);
1355 : 31361 : eID = GetUInt16(table, 6 + i * 8, 1);
1356 : 31361 : offset = GetUInt32(table, 8 + i * 8, 1);
1357 : :
1358 : : /* sanity check, cmap must lie within file */
1359 [ - + ]: 31361 : if( (table - ttf->ptr) + offset > (sal_uInt32)ttf->fsize )
1360 : 0 : continue;
1361 : :
1362 : : /* Unicode tables in Apple fonts */
1363 [ + + ]: 31361 : if (pID == 0) {
1364 : 11295 : AppleUni = offset;
1365 : : }
1366 : :
1367 [ + + ]: 31361 : if (pID == 3) {
1368 [ - + - + : 11839 : switch (eID) {
- - - - ]
1369 : 0 : case 0: ThreeZero = offset; break;
1370 : : case 10: // UCS-4
1371 : 11635 : case 1: ThreeOne = offset; break;
1372 : 0 : case 2: ThreeTwo = offset; break;
1373 : 204 : case 3: ThreeThree = offset; break;
1374 : 0 : case 4: ThreeFour = offset; break;
1375 : 0 : case 5: ThreeFive = offset; break;
1376 : 11839 : case 6: ThreeSix = offset; break;
1377 : : }
1378 : : }
1379 : : }
1380 : :
1381 : : // fall back to AppleUnicode if there are no ThreeOne/Threezero tables
1382 [ + + ][ + - ]: 8655 : if( AppleUni && !ThreeZero && !ThreeOne)
[ - + ]
1383 : 0 : ThreeOne = AppleUni;
1384 : :
1385 [ + - ]: 8655 : if (ThreeOne) {
1386 : 8655 : ttf->cmapType = CMAP_MS_Unicode;
1387 : 8655 : ttf->cmap = table + ThreeOne;
1388 [ # # ]: 0 : } else if (ThreeTwo) {
1389 : 0 : ttf->cmapType = CMAP_MS_ShiftJIS;
1390 : 0 : ttf->cmap = table + ThreeTwo;
1391 [ # # ]: 0 : } else if (ThreeThree) {
1392 : 0 : ttf->cmapType = CMAP_MS_Big5;
1393 : 0 : ttf->cmap = table + ThreeThree;
1394 [ # # ]: 0 : } else if (ThreeFour) {
1395 : 0 : ttf->cmapType = CMAP_MS_PRC;
1396 : 0 : ttf->cmap = table + ThreeFour;
1397 [ # # ]: 0 : } else if (ThreeFive) {
1398 : 0 : ttf->cmapType = CMAP_MS_Wansung;
1399 : 0 : ttf->cmap = table + ThreeFive;
1400 [ # # ]: 0 : } else if (ThreeSix) {
1401 : 0 : ttf->cmapType = CMAP_MS_Johab;
1402 : 0 : ttf->cmap = table + ThreeSix;
1403 [ # # ]: 0 : } else if (ThreeZero) {
1404 : 0 : ttf->cmapType = CMAP_MS_Symbol;
1405 : 0 : ttf->cmap = table + ThreeZero;
1406 : : } else {
1407 : 0 : ttf->cmapType = CMAP_NOT_USABLE;
1408 : 0 : ttf->cmap = 0;
1409 : : }
1410 : :
1411 [ + - ]: 8655 : if (ttf->cmapType != CMAP_NOT_USABLE) {
1412 [ - - + - : 8655 : switch (GetUInt16(ttf->cmap, 0, 1)) {
+ - ]
1413 : 0 : case 0: ttf->mapper = getGlyph0; break;
1414 : 0 : case 2: ttf->mapper = getGlyph2; break;
1415 : 5675 : case 4: ttf->mapper = getGlyph4; break;
1416 : 0 : case 6: ttf->mapper = getGlyph6; break;
1417 : 2980 : case 12: ttf->mapper= getGlyph12; break;
1418 : : default:
1419 : : #if OSL_DEBUG_LEVEL > 1
1420 : : /*- if the cmap table is really broken */
1421 : : printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1));
1422 : : #endif
1423 : 0 : ttf->cmapType = CMAP_NOT_USABLE;
1424 : 0 : ttf->cmap = 0;
1425 : 8655 : ttf->mapper = 0;
1426 : : }
1427 : : }
1428 : 8655 : }
1429 : :
1430 : 8655 : static void GetKern(TrueTypeFont *ttf)
1431 : : {
1432 : 8655 : const sal_uInt8* table = getTable(ttf, O_kern);
1433 : : const sal_uInt8 *ptr;
1434 : :
1435 [ + + ]: 8655 : if( !table )
1436 : 4591 : goto badtable;
1437 : :
1438 [ + - ]: 4064 : if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with sal_uInt16 version and nTables fields */
1439 : 4064 : ttf->nkern = GetUInt16(table, 2, 1);
1440 : 4064 : ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8 *));
1441 : : assert(ttf->kerntables != 0);
1442 : 4064 : ttf->kerntype = KT_MICROSOFT;
1443 : 4064 : ptr = table + 4;
1444 [ + + ]: 8518 : for( unsigned i = 0; i < ttf->nkern; ++i) {
1445 : 4454 : ttf->kerntables[i] = ptr;
1446 : 4454 : ptr += GetUInt16(ptr, 2, 1);
1447 : : /* sanity check */
1448 [ - + ]: 4454 : if( ptr > ttf->ptr+ttf->fsize )
1449 : : {
1450 : 0 : free( ttf->kerntables );
1451 : 0 : goto badtable;
1452 : : }
1453 : : }
1454 : 4064 : return;
1455 : : }
1456 : :
1457 [ # # ]: 0 : if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */
1458 : 0 : ttf->nkern = GetUInt32(table, 4, 1);
1459 : 0 : ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8 *));
1460 : : assert(ttf->kerntables != 0);
1461 : 0 : ttf->kerntype = KT_APPLE_NEW;
1462 : 0 : ptr = table + 8;
1463 [ # # ]: 0 : for( unsigned i = 0; i < ttf->nkern; ++i) {
1464 : 0 : ttf->kerntables[i] = ptr;
1465 : 0 : ptr += GetUInt32(ptr, 0, 1);
1466 : : /* sanity check; there are some fonts that are broken in this regard */
1467 [ # # ]: 0 : if( ptr > ttf->ptr+ttf->fsize )
1468 : : {
1469 : 0 : free( ttf->kerntables );
1470 : 0 : goto badtable;
1471 : : }
1472 : : }
1473 : 0 : return;
1474 : : }
1475 : :
1476 : : badtable:
1477 : 4591 : ttf->kerntype = KT_NONE;
1478 : 4591 : ttf->kerntables = 0;
1479 : :
1480 : 8655 : return;
1481 : : }
1482 : :
1483 : : /*- Public functions */ /*FOLD00*/
1484 : :
1485 : 8194 : int CountTTCFonts(const char* fname)
1486 : : {
1487 : 8194 : int nFonts = 0;
1488 : : sal_uInt8 buffer[12];
1489 [ + - ]: 8194 : FILE* fd = fopen(fname, "rb");
1490 [ + - ]: 8194 : if( fd ) {
1491 [ + - ][ + - ]: 8194 : if (fread(buffer, 1, 12, fd) == 12) {
1492 [ + + ]: 8194 : if(GetUInt32(buffer, 0, 1) == T_ttcf )
1493 : 136 : nFonts = GetUInt32(buffer, 8, 1);
1494 : : }
1495 [ + - ]: 8194 : fclose(fd);
1496 : : }
1497 : 8194 : return nFonts;
1498 : : }
1499 : :
1500 : 8655 : static void allocTrueTypeFont( TrueTypeFont** ttf )
1501 : : {
1502 : 8655 : *ttf = (TrueTypeFont*)calloc(1,sizeof(TrueTypeFont));
1503 [ + - ]: 8655 : if( *ttf != NULL )
1504 : : {
1505 : 8655 : (*ttf)->tag = 0;
1506 : 8655 : (*ttf)->fname = 0;
1507 : 8655 : (*ttf)->fsize = -1;
1508 : 8655 : (*ttf)->ptr = 0;
1509 : 8655 : (*ttf)->nglyphs = 0xFFFFFFFF;
1510 : 8655 : (*ttf)->pGSubstitution = 0;
1511 : : }
1512 : 8655 : }
1513 : :
1514 : : /* forward declariotn for the two entry points to use*/
1515 : : static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t );
1516 : :
1517 : : #if !defined(WIN32)
1518 : 8655 : int OpenTTFontFile( const char* fname, sal_uInt32 facenum, TrueTypeFont** ttf )
1519 : : {
1520 : 8655 : int ret, fd = -1;
1521 : : struct stat st;
1522 : :
1523 [ + - ][ - + ]: 8655 : if (!fname || !*fname) return SF_BADFILE;
1524 : :
1525 : 8655 : allocTrueTypeFont( ttf );
1526 [ - + ]: 8655 : if( ! *ttf )
1527 : 0 : return SF_MEMORY;
1528 : :
1529 : 8655 : (*ttf)->fname = strdup(fname);
1530 [ - + ]: 8655 : if( ! (*ttf)->fname )
1531 : : {
1532 : 0 : ret = SF_MEMORY;
1533 : 0 : goto cleanup;
1534 : : }
1535 : :
1536 [ + - ]: 8655 : fd = open(fname, O_RDONLY);
1537 : :
1538 [ - + ]: 8655 : if (fd == -1) {
1539 : 0 : ret = SF_BADFILE;
1540 : 0 : goto cleanup;
1541 : : }
1542 : :
1543 [ - + ]: 8655 : if (fstat(fd, &st) == -1) {
1544 : 0 : ret = SF_FILEIO;
1545 : 0 : goto cleanup;
1546 : : }
1547 : :
1548 : 8655 : (*ttf)->fsize = st.st_size;
1549 : :
1550 : : /* On Mac OS, most likely will happen if a Mac user renames a font file
1551 : : * to be .ttf when its really a Mac resource-based font.
1552 : : * Size will be 0, but fonts smaller than 4 bytes would be broken anyway.
1553 : : */
1554 [ - + ]: 8655 : if ((*ttf)->fsize == 0) {
1555 : 0 : ret = SF_BADFILE;
1556 : 0 : goto cleanup;
1557 : : }
1558 : :
1559 [ - + ]: 8655 : if (((*ttf)->ptr = (sal_uInt8 *) mmap(0, (*ttf)->fsize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
1560 : 0 : ret = SF_MEMORY;
1561 : 0 : goto cleanup;
1562 : : }
1563 [ + - ]: 8655 : close(fd);
1564 : :
1565 [ + - ]: 8655 : return doOpenTTFont( facenum, *ttf );
1566 : :
1567 : : cleanup:
1568 [ # # ][ # # ]: 0 : if (fd != -1) close(fd);
1569 : : /*- t and t->fname have been allocated! */
1570 : 0 : free((*ttf)->fname);
1571 : 0 : free(*ttf);
1572 : 0 : *ttf = NULL;
1573 : 8655 : return ret;
1574 : : }
1575 : : #endif
1576 : :
1577 : 0 : int OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf)
1578 : : {
1579 : 0 : allocTrueTypeFont( ttf );
1580 [ # # ]: 0 : if( *ttf == NULL )
1581 : 0 : return SF_MEMORY;
1582 : :
1583 : 0 : (*ttf)->fname = NULL;
1584 : 0 : (*ttf)->fsize = nLen;
1585 : 0 : (*ttf)->ptr = (sal_uInt8*)pBuffer;
1586 : :
1587 : 0 : return doOpenTTFont( facenum, *ttf );
1588 : : }
1589 : :
1590 : 8655 : static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
1591 : : {
1592 : : int i;
1593 : : sal_uInt32 length, tag;
1594 : 8655 : sal_uInt32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */
1595 : : int indexfmt;
1596 : :
1597 : 8655 : sal_uInt32 version = GetInt32(t->ptr, 0, 1);
1598 : :
1599 [ - + ][ + + ]: 8655 : if ((version == 0x00010000) || (version == T_true)) {
1600 : 7771 : tdoffset = 0;
1601 [ + + ]: 884 : } else if (version == T_otto) { /* PS-OpenType font */
1602 : 408 : tdoffset = 0;
1603 [ + - ]: 476 : } else if (version == T_ttcf) { /* TrueType collection */
1604 [ - + ]: 476 : if (GetUInt32(t->ptr, 4, 1) != 0x00010000) {
1605 : 0 : CloseTTFont(t);
1606 : 0 : return SF_TTFORMAT;
1607 : : }
1608 [ - + ]: 476 : if (facenum >= GetUInt32(t->ptr, 8, 1)) {
1609 : 0 : CloseTTFont(t);
1610 : 0 : return SF_FONTNO;
1611 : : }
1612 : 476 : tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1);
1613 : : } else {
1614 : 0 : CloseTTFont(t);
1615 : 0 : return SF_TTFORMAT;
1616 : : }
1617 : :
1618 : : /* magic number */
1619 : 8655 : t->tag = TTFontClassTag;
1620 : :
1621 : 8655 : t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1);
1622 [ - + ]: 8655 : if( t->ntables >= 128 )
1623 : 0 : return SF_TTFORMAT;
1624 : :
1625 : 8655 : t->tables = (const sal_uInt8**)calloc(NUM_TAGS, sizeof(sal_uInt8 *));
1626 : : assert(t->tables != 0);
1627 : 8655 : t->tlens = (sal_uInt32*)calloc(NUM_TAGS, sizeof(sal_uInt32));
1628 : : assert(t->tlens != 0);
1629 : :
1630 : : /* parse the tables */
1631 [ + + ]: 171703 : for (i=0; i<(int)t->ntables; i++) {
1632 : : int nIndex;
1633 : 163048 : tag = GetUInt32(t->ptr + tdoffset + 12, 16 * i, 1);
1634 [ + + + + : 163048 : switch( tag ) {
+ + + + +
+ + + + +
+ + + +
+ ]
1635 : 8655 : case T_maxp: nIndex = O_maxp; break;
1636 : 8247 : case T_glyf: nIndex = O_glyf; break;
1637 : 8655 : case T_head: nIndex = O_head; break;
1638 : 8247 : case T_loca: nIndex = O_loca; break;
1639 : 8655 : case T_name: nIndex = O_name; break;
1640 : 8655 : case T_hhea: nIndex = O_hhea; break;
1641 : 8655 : case T_hmtx: nIndex = O_hmtx; break;
1642 : 8655 : case T_cmap: nIndex = O_cmap; break;
1643 : 408 : case T_vhea: nIndex = O_vhea; break;
1644 : 408 : case T_vmtx: nIndex = O_vmtx; break;
1645 : 8655 : case T_OS2 : nIndex = O_OS2; break;
1646 : 8655 : case T_post: nIndex = O_post; break;
1647 : 4064 : case T_kern: nIndex = O_kern; break;
1648 : 7907 : case T_cvt : nIndex = O_cvt; break;
1649 : 7703 : case T_prep: nIndex = O_prep; break;
1650 : 7635 : case T_fpgm: nIndex = O_fpgm; break;
1651 : 8169 : case T_gsub: nIndex = O_gsub; break;
1652 : 408 : case T_CFF: nIndex = O_CFF; break;
1653 : 40612 : default: nIndex = -1; break;
1654 : : }
1655 [ + + ]: 163048 : if( nIndex >= 0 ) {
1656 : 122436 : sal_uInt32 nTableOffset = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1);
1657 : 122436 : length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1);
1658 : 122436 : t->tables[nIndex] = t->ptr + nTableOffset;
1659 : 122436 : t->tlens[nIndex] = length;
1660 : : }
1661 : : }
1662 : :
1663 : : /* Fixup offsets when only a TTC extract was provided */
1664 [ - + ]: 8655 : if( facenum == (sal_uInt32)~0 ) {
1665 : 0 : sal_uInt8* pHead = (sal_uInt8*)t->tables[O_head];
1666 [ # # ]: 0 : if( !pHead )
1667 : 0 : return SF_TTFORMAT;
1668 : : /* limit Head candidate to TTC extract's limits */
1669 [ # # ]: 0 : if( pHead > t->ptr + (t->fsize - 54) )
1670 : 0 : pHead = t->ptr + (t->fsize - 54);
1671 : : /* TODO: find better method than searching head table's magic */
1672 : 0 : sal_uInt8* p = NULL;
1673 [ # # ]: 0 : for( p = pHead + 12; p > t->ptr; --p ) {
1674 [ # # ][ # # ]: 0 : if( p[0]==0x5F && p[1]==0x0F && p[2]==0x3C && p[3]==0xF5 ) {
[ # # ][ # # ]
1675 : 0 : int nDelta = (pHead + 12) - p;
1676 [ # # ]: 0 : if( nDelta )
1677 [ # # ]: 0 : for( int j = 0; j < NUM_TAGS; ++j )
1678 [ # # ]: 0 : if( t->tables[j] )
1679 : 0 : *(char**)&t->tables[j] -= nDelta;
1680 : 0 : break;
1681 : : }
1682 : : }
1683 [ # # ]: 0 : if( p <= t->ptr )
1684 : 0 : return SF_TTFORMAT;
1685 : : }
1686 : :
1687 : : /* Check the table offsets after TTC correction */
1688 [ + + ]: 164445 : for (i=0; i<NUM_TAGS; i++) {
1689 : : /* sanity check: table must lay completely within the file
1690 : : * at this point one could check the checksum of all contained
1691 : : * tables, but this would be quite time intensive.
1692 : : * Try to fix tables, so we can cope with minor problems.
1693 : : */
1694 : :
1695 [ + + ]: 155790 : if( (sal_uInt8*)t->tables[i] < t->ptr )
1696 : : {
1697 : : #if OSL_DEBUG_LEVEL > 1
1698 : : if( t->tables[i] )
1699 : : fprintf( stderr, "font file %s has bad table offset %" SAL_PRI_PTRDIFFT "d (tagnum=%d)\n", t->fname, (sal_uInt8*)t->tables[i]-t->ptr, i );
1700 : : #endif
1701 : 33354 : t->tlens[i] = 0;
1702 : 33354 : t->tables[i] = NULL;
1703 : : }
1704 [ - + ]: 122436 : else if( (sal_uInt8*)t->tables[i] + t->tlens[i] > t->ptr + t->fsize )
1705 : : {
1706 : 0 : int nMaxLen = (t->ptr + t->fsize) - (sal_uInt8*)t->tables[i];
1707 [ # # ]: 0 : if( nMaxLen < 0 )
1708 : 0 : nMaxLen = 0;
1709 : 0 : t->tlens[i] = nMaxLen;
1710 : : #if OSL_DEBUG_LEVEL > 1
1711 : : fprintf( stderr, "font file %s has too big table (tagnum=%d)\n", t->fname, i );
1712 : : #endif
1713 : : }
1714 : : }
1715 : :
1716 : : /* At this point TrueTypeFont is constructed, now need to verify the font format
1717 : : and read the basic font properties */
1718 : :
1719 : : /* The following tables are absolutely required:
1720 : : * maxp, head, name, cmap
1721 : : */
1722 : :
1723 [ + - ][ + - ]: 8655 : if( !(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_name) && getTable(t, O_cmap)) ) {
[ + - ][ - + ]
[ - + ]
1724 : 0 : CloseTTFont(t);
1725 : 0 : return SF_TTFORMAT;
1726 : : }
1727 : :
1728 : 8655 : const sal_uInt8* table = getTable(t, O_maxp);
1729 : 8655 : t->nglyphs = GetUInt16(table, 4, 1);
1730 : :
1731 : 8655 : table = getTable(t, O_head);
1732 : 8655 : t->unitsPerEm = GetUInt16(table, 18, 1);
1733 : 8655 : indexfmt = GetInt16(table, 50, 1);
1734 : :
1735 [ + - ][ - + ]: 8655 : if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) {
[ + + ]
1736 : 0 : CloseTTFont(t);
1737 : 0 : return SF_TTFORMAT;
1738 : : }
1739 : :
1740 [ + + ][ + - ]: 8655 : if( getTable(t, O_glyf) && getTable(t, O_loca) ) /* TTF or TTF-OpenType */
[ + + ]
1741 : : {
1742 [ + + ]: 8247 : int k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1;
1743 [ - + ]: 8247 : if( k < (int)t->nglyphs ) /* Hack for broken Chinese fonts */
1744 : 0 : t->nglyphs = k;
1745 : :
1746 : 8247 : table = getTable(t, O_loca);
1747 : 8247 : t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32));
1748 : : assert(t->goffsets != 0);
1749 : :
1750 [ + + ]: 37655173 : for( i = 0; i <= (int)t->nglyphs; ++i )
1751 [ + + ]: 37646926 : t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : (sal_uInt32)GetUInt16(table, i << 1, 1) << 1;
1752 [ + - ]: 408 : } else if( getTable(t, O_CFF) ) { /* PS-OpenType */
1753 : 408 : t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32));
1754 : : /* TODO: implement to get subsetting */
1755 : : assert(t->goffsets != 0);
1756 : : } else {
1757 : 0 : CloseTTFont(t);
1758 : 0 : return SF_TTFORMAT;
1759 : : }
1760 : :
1761 : 8655 : table = getTable(t, O_hhea);
1762 [ + - ]: 8655 : t->numberOfHMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0;
1763 : :
1764 : 8655 : table = getTable(t, O_vhea);
1765 [ + + ]: 8655 : t->numOfLongVerMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0;
1766 : :
1767 : 8655 : GetNames(t);
1768 : 8655 : FindCmap(t);
1769 : 8655 : GetKern(t);
1770 : 8655 : ReadGSUB( t, 0, 0 );
1771 : :
1772 : 8655 : return SF_OK;
1773 : : }
1774 : :
1775 : 8655 : void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/
1776 : : {
1777 : : #if !defined(WIN32)
1778 [ + - ]: 8655 : if( ttf->fname )
1779 : 8655 : munmap((char *) ttf->ptr, ttf->fsize);
1780 : : #endif
1781 : 8655 : free(ttf->fname);
1782 : 8655 : free(ttf->goffsets);
1783 : 8655 : free(ttf->psname);
1784 : 8655 : free(ttf->family);
1785 [ + - ]: 8655 : if( ttf->ufamily )
1786 : 8655 : free( ttf->ufamily );
1787 : 8655 : free(ttf->subfamily);
1788 [ - + ]: 8655 : if( ttf->usubfamily )
1789 : 0 : free( ttf->usubfamily );
1790 : 8655 : free(ttf->tables);
1791 : 8655 : free(ttf->tlens);
1792 : 8655 : free(ttf->kerntables);
1793 : :
1794 : 8655 : ReleaseGSUB(ttf);
1795 : :
1796 : 8655 : free(ttf);
1797 : 8655 : return;
1798 : : }
1799 : :
1800 : 0 : int GetTTGlyphPoints(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray)
1801 : : {
1802 : 0 : return GetTTGlyphOutline(ttf, glyphID, pointArray, 0, 0);
1803 : : }
1804 : :
1805 : 0 : int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal_uInt32 >& glyphlist)
1806 : : {
1807 : 0 : int n = 1;
1808 : :
1809 [ # # ]: 0 : if( glyphID >= ttf->nglyphs )
1810 : 0 : return 0;
1811 : :
1812 : 0 : const sal_uInt8* glyf = getTable(ttf, O_glyf);
1813 : 0 : const sal_uInt8* ptr = glyf + ttf->goffsets[glyphID];
1814 : :
1815 : 0 : glyphlist.push_back( glyphID );
1816 : :
1817 [ # # ]: 0 : if (GetInt16(ptr, 0, 1) == -1) {
1818 : : sal_uInt16 flags, index;
1819 : 0 : ptr += 10;
1820 [ # # ]: 0 : do {
1821 : 0 : flags = GetUInt16(ptr, 0, 1);
1822 : 0 : index = GetUInt16(ptr, 2, 1);
1823 : :
1824 : 0 : ptr += 4;
1825 : 0 : n += GetTTGlyphComponents(ttf, index, glyphlist);
1826 : :
1827 [ # # ]: 0 : if (flags & ARG_1_AND_2_ARE_WORDS) {
1828 : 0 : ptr += 4;
1829 : : } else {
1830 : 0 : ptr += 2;
1831 : : }
1832 : :
1833 [ # # ]: 0 : if (flags & WE_HAVE_A_SCALE) {
1834 : 0 : ptr += 2;
1835 [ # # ]: 0 : } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
1836 : 0 : ptr += 4;
1837 [ # # ]: 0 : } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
1838 : 0 : ptr += 8;
1839 : : }
1840 : : } while (flags & MORE_COMPONENTS);
1841 : : }
1842 : :
1843 : 0 : return n;
1844 : : }
1845 : :
1846 : : #ifndef NO_TYPE3
1847 : 0 : int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/
1848 : : sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs,
1849 : : int wmode)
1850 : : {
1851 : : ControlPoint *pa;
1852 : : PSPathElement *path;
1853 : : int i, j, r, n;
1854 : 0 : const sal_uInt8* table = getTable(ttf, O_head);
1855 : : TTGlyphMetrics metrics;
1856 : 0 : int UPEm = ttf->unitsPerEm;
1857 : :
1858 : 0 : const char *h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n";
1859 : 0 : const char *h02 = "%% Creator: %s %s %s\n";
1860 : 0 : const char *h09 = "%% Original font name: %s\n";
1861 : :
1862 : : const char *h10 =
1863 : : "30 dict begin\n"
1864 : : "/PaintType 0 def\n"
1865 : : "/FontType 3 def\n"
1866 : 0 : "/StrokeWidth 0 def\n";
1867 : :
1868 : 0 : const char *h11 = "/FontName (%s) cvn def\n";
1869 : :
1870 : : /*
1871 : : const char *h12 = "%/UniqueID %d def\n";
1872 : : */
1873 : 0 : const char *h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n";
1874 : 0 : const char *h14 = "/FontBBox [%d %d %d %d] def\n";
1875 : :
1876 : : const char *h15=
1877 : : "/Encoding 256 array def\n"
1878 : 0 : " 0 1 255 {Encoding exch /.notdef put} for\n";
1879 : :
1880 : 0 : const char *h16 = " Encoding %d /glyph%d put\n";
1881 : 0 : const char *h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n";
1882 : :
1883 : 0 : const char *h30 = "/CharProcs %d dict def\n";
1884 : 0 : const char *h31 = " CharProcs begin\n";
1885 : 0 : const char *h32 = " /.notdef {} def\n";
1886 : 0 : const char *h33 = " /glyph%d {\n";
1887 : 0 : const char *h34 = " } bind def\n";
1888 : 0 : const char *h35 = " end\n";
1889 : :
1890 : : const char *h40 =
1891 : : "/BuildGlyph {\n"
1892 : : " exch /CharProcs get exch\n"
1893 : : " 2 copy known not\n"
1894 : : " {pop /.notdef} if\n"
1895 : : " get exec\n"
1896 : : "} bind def\n"
1897 : : "/BuildChar {\n"
1898 : : " 1 index /Encoding get exch get\n"
1899 : : " 1 index /BuildGlyph get exec\n"
1900 : : "} bind def\n"
1901 : 0 : "currentdict end\n";
1902 : :
1903 : 0 : const char *h41 = "(%s) cvn exch definefont pop\n";
1904 : :
1905 : :
1906 [ # # ][ # # ]: 0 : if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM;
1907 [ # # ]: 0 : if (!glyphArray) return SF_BADARG;
1908 [ # # ]: 0 : if (!fname) fname = ttf->psname;
1909 : :
1910 [ # # ]: 0 : fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1));
1911 [ # # ]: 0 : fprintf(outf, h02, modname, modver, modextra);
1912 [ # # ]: 0 : fprintf(outf, h09, ttf->psname);
1913 : :
1914 [ # # ]: 0 : fprintf(outf, "%s", h10);
1915 [ # # ]: 0 : fprintf(outf, h11, fname);
1916 : : /* fprintf(outf, h12, 4000000); */
1917 : :
1918 : : /* XUID generation:
1919 : : * 103 0 0 C1 C2 C3 C4
1920 : : * C1 - CRC-32 of the entire source TrueType font
1921 : : * C2 - number of glyphs in the subset
1922 : : * C3 - CRC-32 of the glyph array
1923 : : * C4 - CRC-32 of the encoding array
1924 : : *
1925 : : * All CRC-32 numbers are presented as hexadecimal numbers
1926 : : */
1927 : :
1928 [ # # ]: 0 : fprintf(outf, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs));
1929 [ # # ]: 0 : fprintf(outf, "%s", h13);
1930 [ # # ]: 0 : fprintf(outf, h14, XUnits(UPEm, GetInt16(table, 36, 1)), XUnits(UPEm, GetInt16(table, 38, 1)), XUnits(UPEm, GetInt16(table, 40, 1)), XUnits(UPEm, GetInt16(table, 42, 1)));
1931 [ # # ]: 0 : fprintf(outf, "%s", h15);
1932 : :
1933 [ # # ]: 0 : for (i = 0; i < nGlyphs; i++) {
1934 [ # # ]: 0 : fprintf(outf, h16, encoding[i], i);
1935 : : }
1936 : :
1937 [ # # ]: 0 : fprintf(outf, h30, nGlyphs+1);
1938 [ # # ]: 0 : fprintf(outf, "%s", h31);
1939 [ # # ]: 0 : fprintf(outf, "%s", h32);
1940 : :
1941 [ # # ]: 0 : for (i = 0; i < nGlyphs; i++) {
1942 [ # # ]: 0 : fprintf(outf, h33, i);
1943 [ # # ][ # # ]: 0 : r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0);
1944 : :
1945 [ # # ]: 0 : if (r > 0) {
1946 [ # # ]: 0 : n = BSplineToPSPath(pa, r, &path);
1947 : : } else {
1948 : 0 : n = 0; /* glyph might have zero contours but valid metrics ??? */
1949 : 0 : path = 0;
1950 [ # # ]: 0 : if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */
1951 : 0 : continue;
1952 : : }
1953 : : }
1954 : : fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n",
1955 : 0 : wmode == 0 ? XUnits(UPEm, metrics.aw) : 0,
1956 : 0 : wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah),
1957 : : XUnits(UPEm, metrics.xMin),
1958 : : XUnits(UPEm, metrics.yMin),
1959 : : XUnits(UPEm, metrics.xMax),
1960 [ # # ][ # # ]: 0 : XUnits(UPEm, metrics.yMax));
[ # # ]
1961 : :
1962 [ # # ]: 0 : for (j = 0; j < n; j++)
1963 : : {
1964 [ # # # # : 0 : switch (path[j].type)
# # ]
1965 : : {
1966 : : case PS_MOVETO:
1967 [ # # ]: 0 : fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
1968 : 0 : break;
1969 : :
1970 : : case PS_LINETO:
1971 [ # # ]: 0 : fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
1972 : 0 : break;
1973 : :
1974 : : case PS_CURVETO:
1975 [ # # ]: 0 : fprintf(outf, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3));
1976 : 0 : break;
1977 : :
1978 : : case PS_CLOSEPATH:
1979 [ # # ]: 0 : fprintf(outf, "\tclosepath\n");
1980 : 0 : break;
1981 : : case PS_NOOP:
1982 : 0 : break;
1983 : : }
1984 : : }
1985 [ # # ][ # # ]: 0 : if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */
1986 : :
1987 [ # # ]: 0 : fprintf(outf, "%s", h34);
1988 : :
1989 : 0 : free(pa);
1990 : 0 : free(path);
1991 : : }
1992 [ # # ]: 0 : fprintf(outf, "%s", h35);
1993 : :
1994 [ # # ]: 0 : fprintf(outf, "%s", h40);
1995 [ # # ]: 0 : fprintf(outf, h41, fname);
1996 : :
1997 : 0 : return SF_OK;
1998 : : }
1999 : : #endif
2000 : :
2001 : : #ifndef NO_TTCR
2002 : 0 : int CreateTTFromTTGlyphs(TrueTypeFont *ttf,
2003 : : const char *fname,
2004 : : sal_uInt16 *glyphArray,
2005 : : sal_uInt8 *encoding,
2006 : : int nGlyphs,
2007 : : int nNameRecs,
2008 : : NameRecord *nr,
2009 : : sal_uInt32 flags)
2010 : : {
2011 : : TrueTypeCreator *ttcr;
2012 : 0 : TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0, *cmap=0, *name=0, *post = 0, *os2 = 0;
2013 : : int i;
2014 : : int res;
2015 : :
2016 [ # # ]: 0 : TrueTypeCreatorNewEmpty(T_true, &ttcr);
2017 : :
2018 : : /** name **/
2019 : :
2020 [ # # ]: 0 : if (flags & TTCF_AutoName) {
2021 : : /* not implemented yet
2022 : : NameRecord *names;
2023 : : NameRecord newname;
2024 : : int n = GetTTNameRecords(ttf, &names);
2025 : : int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
2026 : : sal_uInt8 *cp1;
2027 : : sal_uInt8 suffix[32];
2028 : : sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2);
2029 : : sal_uInt32 c2 = crc32(encoding, nGlyphs);
2030 : : int len;
2031 : : snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs);
2032 : :
2033 : : name = TrueTypeTableNew_name(0, 0);
2034 : : for (i = 0; i < n; i++) {
2035 : : if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) {
2036 : :
2037 : : memcpy(newname, names+i, sizeof(NameRecord));
2038 : : newname.slen = name[i].slen + strlen(suffix);
2039 : : */
2040 : 0 : const sal_uInt8 ptr[] = {0,'T',0,'r',0,'u',0,'e',0,'T',0,'y',0,'p',0,'e',0,'S',0,'u',0,'b',0,'s',0,'e',0,'t'};
2041 : 0 : NameRecord n1 = {1, 0, 0, 6, 14, (sal_uInt8*)"TrueTypeSubset"};
2042 : 0 : NameRecord n2 = {3, 1, 1033, 6, 28, 0};
2043 : 0 : n2.sptr = (sal_uInt8 *) ptr;
2044 [ # # ]: 0 : name = TrueTypeTableNew_name(0, 0);
2045 [ # # ]: 0 : nameAdd(name, &n1);
2046 [ # # ]: 0 : nameAdd(name, &n2);
2047 : : } else {
2048 [ # # ]: 0 : if (nNameRecs == 0) {
2049 : : NameRecord *names;
2050 : 0 : int n = GetTTNameRecords(ttf, &names);
2051 [ # # ]: 0 : name = TrueTypeTableNew_name(n, names);
2052 : 0 : DisposeNameRecords(names, n);
2053 : : } else {
2054 [ # # ]: 0 : name = TrueTypeTableNew_name(nNameRecs, nr);
2055 : : }
2056 : : }
2057 : :
2058 : : /** maxp **/
2059 [ # # ]: 0 : maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
2060 : :
2061 : : /** hhea **/
2062 : 0 : const sal_uInt8* p = getTable(ttf, O_hhea);
2063 [ # # ]: 0 : if (p) {
2064 [ # # ]: 0 : hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
2065 : : } else {
2066 [ # # ]: 0 : hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2067 : : }
2068 : :
2069 : : /** head **/
2070 : :
2071 : 0 : p = getTable(ttf, O_head);
2072 : : assert(p != 0);
2073 : : head = TrueTypeTableNew_head(GetUInt32(p, 4, 1),
2074 : 0 : GetUInt16(p, 16, 1),
2075 : 0 : GetUInt16(p, 18, 1),
2076 : : p+20,
2077 : 0 : GetUInt16(p, 44, 1),
2078 : 0 : GetUInt16(p, 46, 1),
2079 [ # # ]: 0 : GetInt16(p, 48, 1));
2080 : :
2081 : :
2082 : : /** glyf **/
2083 : :
2084 [ # # ]: 0 : glyf = TrueTypeTableNew_glyf();
2085 : 0 : sal_uInt32* gID = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32));
2086 : :
2087 [ # # ]: 0 : for (i = 0; i < nGlyphs; i++) {
2088 [ # # ][ # # ]: 0 : gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
2089 : : }
2090 : :
2091 : : /** cmap **/
2092 [ # # ]: 0 : cmap = TrueTypeTableNew_cmap();
2093 : :
2094 [ # # ]: 0 : for (i=0; i < nGlyphs; i++) {
2095 [ # # ]: 0 : cmapAdd(cmap, 0x010000, encoding[i], gID[i]);
2096 : : }
2097 : :
2098 : : /** cvt **/
2099 [ # # ]: 0 : if ((p = getTable(ttf, O_cvt)) != 0) {
2100 [ # # ]: 0 : cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
2101 : : }
2102 : :
2103 : : /** prep **/
2104 [ # # ]: 0 : if ((p = getTable(ttf, O_prep)) != 0) {
2105 [ # # ]: 0 : prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
2106 : : }
2107 : :
2108 : : /** fpgm **/
2109 [ # # ]: 0 : if ((p = getTable(ttf, O_fpgm)) != 0) {
2110 [ # # ]: 0 : fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
2111 : : }
2112 : :
2113 : : /** post **/
2114 [ # # ]: 0 : if ((p = getTable(ttf, O_post)) != 0) {
2115 : : post = TrueTypeTableNew_post(0x00030000,
2116 : : GetUInt32(p, 4, 1),
2117 : 0 : GetUInt16(p, 8, 1),
2118 : 0 : GetUInt16(p, 10, 1),
2119 [ # # ]: 0 : GetUInt16(p, 12, 1));
2120 : : } else {
2121 [ # # ]: 0 : post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
2122 : : }
2123 : :
2124 [ # # ]: 0 : if (flags & TTCF_IncludeOS2) {
2125 [ # # ]: 0 : if ((p = getTable(ttf, O_OS2)) != 0) {
2126 [ # # ]: 0 : os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p);
2127 : : }
2128 : : }
2129 : :
2130 [ # # ][ # # ]: 0 : AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea);
[ # # ]
2131 [ # # ][ # # ]: 0 : AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap);
[ # # ]
2132 [ # # ][ # # ]: 0 : AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm);
[ # # ]
2133 [ # # ][ # # ]: 0 : AddTable(ttcr, post); AddTable(ttcr, os2);
2134 : :
2135 [ # # ]: 0 : if ((res = StreamToFile(ttcr, fname)) != SF_OK) {
2136 : : #if OSL_DEBUG_LEVEL > 1
2137 : : fprintf(stderr, "StreamToFile: error code: %d.\n", res);
2138 : : #endif
2139 : : }
2140 : :
2141 [ # # ]: 0 : TrueTypeCreatorDispose(ttcr);
2142 : 0 : free(gID);
2143 : :
2144 : 0 : return res;
2145 : : }
2146 : : #endif
2147 : :
2148 : :
2149 : : #ifndef NO_TYPE42
2150 : 0 : static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP)
2151 : : {
2152 : 0 : GlyphOffsets* res = (GlyphOffsets*)smalloc(sizeof(GlyphOffsets));
2153 : 0 : sal_uInt8 *loca = NULL;
2154 : 0 : sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1);
2155 : 0 : sal_uInt32 locaLen = 0;
2156 : 0 : sal_Int16 indexToLocFormat = 0;
2157 : :
2158 [ # # ]: 0 : for (i = 0; i < numTables; i++) {
2159 : 0 : sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1);
2160 : 0 : sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1);
2161 : 0 : sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1);
2162 : :
2163 [ # # ]: 0 : if (tag == T_loca) {
2164 : 0 : loca = sfntP + off;
2165 : 0 : locaLen = len;
2166 [ # # ]: 0 : } else if (tag == T_head) {
2167 : 0 : indexToLocFormat = GetInt16(sfntP + off, 50, 1);
2168 : : }
2169 : : }
2170 : :
2171 [ # # ]: 0 : res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2);
2172 : : assert(res->nGlyphs != 0);
2173 : 0 : res->offs = (sal_uInt32*)scalloc(res->nGlyphs, sizeof(sal_uInt32));
2174 : :
2175 [ # # ]: 0 : for (i = 0; i < res->nGlyphs; i++) {
2176 [ # # ]: 0 : if (indexToLocFormat == 1) {
2177 : 0 : res->offs[i] = GetUInt32(loca, i * 4, 1);
2178 : : } else {
2179 : 0 : res->offs[i] = GetUInt16(loca, i * 2, 1) << 1;
2180 : : }
2181 : : }
2182 : 0 : return res;
2183 : : }
2184 : :
2185 : 0 : static void GlyphOffsetsDispose(GlyphOffsets *_this)
2186 : : {
2187 [ # # ]: 0 : if (_this) {
2188 : 0 : free(_this->offs);
2189 : 0 : free(_this);
2190 : : }
2191 : 0 : }
2192 : :
2193 : 0 : static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP)
2194 : : {
2195 : 0 : HexFmt *h = HexFmtNew(outf);
2196 : 0 : sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1);
2197 : 0 : GlyphOffsets *go = GlyphOffsetsNew(sfntP);
2198 : 0 : sal_uInt8 pad[] = {0,0,0,0}; /* zeroes */
2199 : :
2200 : : assert(numTables <= 9); /* Type42 has 9 required tables */
2201 : :
2202 : 0 : sal_uInt32* offs = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32));
2203 : : // sal_uInt32* lens = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32));
2204 : :
2205 [ # # ]: 0 : fputs("/sfnts [", outf);
2206 [ # # ]: 0 : HexFmtOpenString(h);
2207 [ # # ]: 0 : HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */
2208 [ # # ]: 0 : HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */
2209 : :
2210 [ # # ]: 0 : for (i=0; i<numTables; i++) {
2211 : 0 : sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1);
2212 : 0 : sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1);
2213 : 0 : sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1);
2214 : :
2215 [ # # ]: 0 : if (tag != T_glyf) {
2216 [ # # ]: 0 : HexFmtBlockWrite(h, sfntP + off, len);
2217 : : } else {
2218 : 0 : sal_uInt8 *glyf = sfntP + off;
2219 : : sal_uInt32 o, l, j;
2220 [ # # ]: 0 : for (j = 0; j < go->nGlyphs - 1; j++) {
2221 : 0 : o = go->offs[j];
2222 : 0 : l = go->offs[j + 1] - o;
2223 [ # # ]: 0 : HexFmtBlockWrite(h, glyf + o, l);
2224 : : }
2225 : : }
2226 [ # # ]: 0 : HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3);
2227 : : }
2228 [ # # ]: 0 : HexFmtCloseString(h);
2229 [ # # ]: 0 : fputs("] def\n", outf);
2230 : 0 : GlyphOffsetsDispose(go);
2231 [ # # ]: 0 : HexFmtDispose(h);
2232 : 0 : free(offs);
2233 : : // free(lens);
2234 : 0 : }
2235 : :
2236 : 0 : int CreateT42FromTTGlyphs(TrueTypeFont *ttf,
2237 : : FILE *outf,
2238 : : const char *psname,
2239 : : sal_uInt16 *glyphArray,
2240 : : sal_uInt8 *encoding,
2241 : : int nGlyphs)
2242 : : {
2243 : : TrueTypeCreator *ttcr;
2244 : 0 : TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0;
2245 : : int i;
2246 : : int res;
2247 : :
2248 : : sal_uInt32 ver, rev;
2249 : :
2250 : : sal_uInt8 *sfntP;
2251 : : sal_uInt32 sfntLen;
2252 : 0 : int UPEm = ttf->unitsPerEm;
2253 : :
2254 [ # # ]: 0 : if (nGlyphs >= 256) return SF_GLYPHNUM;
2255 : :
2256 : : assert(psname != 0);
2257 : :
2258 [ # # ]: 0 : TrueTypeCreatorNewEmpty(T_true, &ttcr);
2259 : :
2260 : : /* head */
2261 : 0 : const sal_uInt8* p = getTable(ttf, O_head);
2262 : 0 : const sal_uInt8* headP = p;
2263 : : assert(p != 0);
2264 [ # # ]: 0 : head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), GetUInt16(p, 16, 1), GetUInt16(p, 18, 1), p+20, GetUInt16(p, 44, 1), GetUInt16(p, 46, 1), GetInt16(p, 48, 1));
2265 : 0 : ver = GetUInt32(p, 0, 1);
2266 : 0 : rev = GetUInt32(p, 4, 1);
2267 : :
2268 : : /** hhea **/
2269 : 0 : p = getTable(ttf, O_hhea);
2270 [ # # ]: 0 : if (p) {
2271 [ # # ]: 0 : hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
2272 : : } else {
2273 [ # # ]: 0 : hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2274 : : }
2275 : :
2276 : : /** maxp **/
2277 [ # # ]: 0 : maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
2278 : :
2279 : : /** cvt **/
2280 [ # # ]: 0 : if ((p = getTable(ttf, O_cvt)) != 0) {
2281 [ # # ]: 0 : cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
2282 : : }
2283 : :
2284 : : /** prep **/
2285 [ # # ]: 0 : if ((p = getTable(ttf, O_prep)) != 0) {
2286 [ # # ]: 0 : prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
2287 : : }
2288 : :
2289 : : /** fpgm **/
2290 [ # # ]: 0 : if ((p = getTable(ttf, O_fpgm)) != 0) {
2291 [ # # ]: 0 : fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
2292 : : }
2293 : :
2294 : : /** glyf **/
2295 [ # # ]: 0 : glyf = TrueTypeTableNew_glyf();
2296 : 0 : sal_uInt16* gID = (sal_uInt16*)scalloc(nGlyphs, sizeof(sal_uInt32));
2297 : :
2298 [ # # ]: 0 : for (i = 0; i < nGlyphs; i++) {
2299 [ # # ][ # # ]: 0 : gID[i] = (sal_uInt16)glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
2300 : : }
2301 : :
2302 [ # # ][ # # ]: 0 : AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt);
[ # # ][ # # ]
2303 [ # # ][ # # ]: 0 : AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm);
[ # # ]
2304 : :
2305 [ # # ][ # # ]: 0 : if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) {
2306 [ # # ]: 0 : TrueTypeCreatorDispose(ttcr);
2307 : 0 : free(gID);
2308 : 0 : return res;
2309 : : }
2310 : :
2311 [ # # ]: 0 : fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver>>16), (int)(ver & 0xFFFF), (int)(rev>>16), (int)(rev & 0xFFFF));
2312 [ # # ]: 0 : fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra);
2313 [ # # ]: 0 : fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname);
2314 [ # # ]: 0 : fprintf(outf, "%%- Original font name: %s\n", ttf->psname);
2315 [ # # ]: 0 : fprintf(outf, "%%- Original font family: %s\n", ttf->family);
2316 [ # # ]: 0 : fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily);
2317 [ # # ]: 0 : fprintf(outf, "11 dict begin\n");
2318 [ # # ]: 0 : fprintf(outf, "/FontName (%s) cvn def\n", psname);
2319 [ # # ]: 0 : fprintf(outf, "/PaintType 0 def\n");
2320 [ # # ]: 0 : fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n");
2321 [ # # ]: 0 : fprintf(outf, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, 36, 1)), XUnits(UPEm, GetInt16(headP, 38, 1)), XUnits(UPEm, GetInt16(headP, 40, 1)), XUnits(UPEm, GetInt16(headP, 42, 1)));
2322 [ # # ]: 0 : fprintf(outf, "/FontType 42 def\n");
2323 [ # # ]: 0 : fprintf(outf, "/Encoding 256 array def\n");
2324 [ # # ]: 0 : fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n");
2325 : :
2326 [ # # ]: 0 : for (i = 1; i<nGlyphs; i++) {
2327 [ # # ]: 0 : fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]);
2328 : : }
2329 [ # # ]: 0 : fprintf(outf, "/XUID [103 0 1 16#%08X %d 16#%08X 16#%08X] def\n", (unsigned int)rtl_crc32(0, ttf->ptr, ttf->fsize), (unsigned int)nGlyphs, (unsigned int)rtl_crc32(0, glyphArray, nGlyphs * 2), (unsigned int)rtl_crc32(0, encoding, nGlyphs));
2330 : :
2331 [ # # ]: 0 : DumpSfnts(outf, sfntP);
2332 : :
2333 : : /* dump charstrings */
2334 [ # # ]: 0 : fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs);
2335 [ # # ]: 0 : fprintf(outf, "/.notdef 0 def\n");
2336 [ # # ][ # # ]: 0 : for (i = 1; i < (int)glyfCount(glyf); i++) {
2337 [ # # ]: 0 : fprintf(outf,"/glyph%d %d def\n", i, i);
2338 : : }
2339 [ # # ]: 0 : fprintf(outf, "end readonly def\n");
2340 : :
2341 [ # # ]: 0 : fprintf(outf, "FontName currentdict end definefont pop\n");
2342 [ # # ]: 0 : TrueTypeCreatorDispose(ttcr);
2343 : 0 : free(gID);
2344 : 0 : free(sfntP);
2345 : 0 : return SF_OK;
2346 : : }
2347 : : #endif
2348 : :
2349 : :
2350 : : #ifndef NO_MAPPERS
2351 : 0 : int MapString(TrueTypeFont *ttf, sal_uInt16 *str, int nchars, sal_uInt16 *glyphArray, int bvertical)
2352 : : {
2353 : : int i;
2354 : : sal_uInt16 *cp;
2355 : :
2356 [ # # ]: 0 : if (ttf->cmapType == CMAP_NOT_USABLE ) return -1;
2357 [ # # ]: 0 : if (!nchars) return 0;
2358 : :
2359 [ # # ]: 0 : if (glyphArray == 0) {
2360 : 0 : cp = str;
2361 : : } else {
2362 : 0 : cp = glyphArray;
2363 : : }
2364 : :
2365 [ # # # # : 0 : switch (ttf->cmapType) {
# # # # ]
2366 : : case CMAP_MS_Symbol:
2367 [ # # ]: 0 : if( ttf->mapper == getGlyph0 ) {
2368 : : sal_uInt16 aChar;
2369 [ # # ]: 0 : for( i = 0; i < nchars; i++ ) {
2370 : 0 : aChar = str[i];
2371 [ # # ]: 0 : if( ( aChar & 0xf000 ) == 0xf000 )
2372 : 0 : aChar &= 0x00ff;
2373 : 0 : cp[i] = aChar;
2374 : : }
2375 : : }
2376 [ # # ]: 0 : else if( glyphArray )
2377 : 0 : memcpy(glyphArray, str, nchars * 2);
2378 : 0 : break;
2379 : :
2380 : : case CMAP_MS_Unicode:
2381 [ # # ]: 0 : if (glyphArray != 0) {
2382 : 0 : memcpy(glyphArray, str, nchars * 2);
2383 : : }
2384 : 0 : break;
2385 : :
2386 : 0 : case CMAP_MS_ShiftJIS: TranslateString12(str, cp, nchars); break;
2387 : 0 : case CMAP_MS_Big5: TranslateString13(str, cp, nchars); break;
2388 : 0 : case CMAP_MS_PRC: TranslateString14(str, cp, nchars); break;
2389 : 0 : case CMAP_MS_Wansung: TranslateString15(str, cp, nchars); break;
2390 : 0 : case CMAP_MS_Johab: TranslateString16(str, cp, nchars); break;
2391 : : }
2392 : :
2393 [ # # ]: 0 : for (i = 0; i < nchars; i++) {
2394 : 0 : cp[i] = (sal_uInt16)ttf->mapper(ttf->cmap, cp[i]);
2395 [ # # ][ # # ]: 0 : if (cp[i]!=0 && bvertical!=0)
2396 : 0 : cp[i] = (sal_uInt16)UseGSUB(ttf,cp[i],bvertical);
2397 : : }
2398 : 0 : return nchars;
2399 : : }
2400 : :
2401 : 0 : sal_uInt16 MapChar(TrueTypeFont *ttf, sal_uInt16 ch, int bvertical)
2402 : : {
2403 [ # # # # : 0 : switch (ttf->cmapType) {
# # # # ]
2404 : : case CMAP_MS_Symbol:
2405 : :
2406 [ # # ][ # # ]: 0 : if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 )
2407 : 0 : ch &= 0x00ff;
2408 : 0 : return (sal_uInt16)ttf->mapper(ttf->cmap, ch );
2409 : :
2410 : 0 : case CMAP_MS_Unicode: break;
2411 : 0 : case CMAP_MS_ShiftJIS: ch = TranslateChar12(ch); break;
2412 : 0 : case CMAP_MS_Big5: ch = TranslateChar13(ch); break;
2413 : 0 : case CMAP_MS_PRC: ch = TranslateChar14(ch); break;
2414 : 0 : case CMAP_MS_Wansung: ch = TranslateChar15(ch); break;
2415 : 0 : case CMAP_MS_Johab: ch = TranslateChar16(ch); break;
2416 : 0 : default: return 0;
2417 : : }
2418 : 0 : ch = (sal_uInt16)ttf->mapper(ttf->cmap, ch);
2419 [ # # ][ # # ]: 0 : if (ch!=0 && bvertical!=0)
2420 : 0 : ch = (sal_uInt16)UseGSUB(ttf,ch,bvertical);
2421 : 0 : return ch;
2422 : : }
2423 : :
2424 : 8655 : int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical)
2425 : : {
2426 : 8655 : int nRet = 0;
2427 [ + - ]: 8655 : if( bvertical)
2428 : 8655 : nRet = HasVerticalGSUB( ttf);
2429 : 8655 : return nRet;
2430 : : }
2431 : :
2432 : : #endif
2433 : :
2434 : 0 : int GetTTGlyphCount( TrueTypeFont* ttf )
2435 : : {
2436 : 0 : return ttf->nglyphs;
2437 : : }
2438 : :
2439 : 0 : bool GetSfntTable( TrueTypeFont* ttf, int nSubtableIndex,
2440 : : const sal_uInt8** ppRawBytes, int* pRawLength )
2441 : : {
2442 [ # # ][ # # ]: 0 : if( (nSubtableIndex < 0) || (nSubtableIndex >= NUM_TAGS) )
2443 : 0 : return false;
2444 : 0 : *pRawLength = ttf->tlens[ nSubtableIndex ];
2445 : 0 : *ppRawBytes = ttf->tables[ nSubtableIndex ];
2446 [ # # ][ # # ]: 0 : bool bOk = (*pRawLength > 0) && (ppRawBytes != NULL);
2447 : 0 : return bOk;
2448 : : }
2449 : :
2450 : 0 : TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *glyphArray, int nGlyphs, int mode)
2451 : : {
2452 : : const sal_uInt8* pTable;
2453 : : sal_uInt32 n;
2454 : : int nTableSize;
2455 : :
2456 [ # # ]: 0 : if (mode == 0) {
2457 : 0 : n = ttf->numberOfHMetrics;
2458 : 0 : pTable = getTable( ttf, O_hmtx );
2459 : 0 : nTableSize = getTableSize( ttf, O_hmtx );
2460 : : } else {
2461 : 0 : n = ttf->numOfLongVerMetrics;
2462 : 0 : pTable = getTable( ttf, O_vmtx );
2463 : 0 : nTableSize = getTableSize( ttf, O_vmtx );
2464 : : }
2465 : :
2466 [ # # ][ # # ]: 0 : if (!nGlyphs || !glyphArray) return 0; /* invalid parameters */
2467 [ # # ][ # # ]: 0 : if (!n || !pTable) return 0; /* the font does not contain the requested metrics */
2468 : :
2469 : 0 : TTSimpleGlyphMetrics* res = (TTSimpleGlyphMetrics*)calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics));
2470 : : assert(res != 0);
2471 : :
2472 : 0 : const int UPEm = ttf->unitsPerEm;
2473 [ # # ]: 0 : for( int i = 0; i < nGlyphs; ++i) {
2474 : : int nAdvOffset, nLsbOffset;
2475 : 0 : sal_uInt16 glyphID = glyphArray[i];
2476 : :
2477 [ # # ]: 0 : if (glyphID < n) {
2478 : 0 : nAdvOffset = 4 * glyphID;
2479 : 0 : nLsbOffset = nAdvOffset + 2;
2480 : : } else {
2481 : 0 : nAdvOffset = 4 * (n - 1);
2482 [ # # ]: 0 : if( glyphID < ttf->nglyphs )
2483 : 0 : nLsbOffset = 4 * n + 2 * (glyphID - n);
2484 : : else /* font is broken -> use lsb of last hmetrics */
2485 : 0 : nLsbOffset = nAdvOffset + 2;
2486 : : }
2487 : :
2488 [ # # ]: 0 : if( nAdvOffset >= nTableSize)
2489 : 0 : res[i].adv = 0; /* better than a crash for buggy fonts */
2490 : : else
2491 : 0 : res[i].adv = static_cast<sal_uInt16>(
2492 : 0 : XUnits( UPEm, GetUInt16( pTable, nAdvOffset, 1) ) );
2493 : :
2494 [ # # ]: 0 : if( nLsbOffset >= nTableSize)
2495 : 0 : res[i].sb = 0; /* better than a crash for buggy fonts */
2496 : : else
2497 : 0 : res[i].sb = static_cast<sal_Int16>(
2498 : 0 : XUnits( UPEm, GetInt16( pTable, nLsbOffset, 1) ) );
2499 : : }
2500 : :
2501 : 0 : return res;
2502 : : }
2503 : :
2504 : : #ifndef NO_MAPPERS
2505 : 0 : TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firstChar, int nChars, int mode)
2506 : : {
2507 : 0 : TTSimpleGlyphMetrics *res = 0;
2508 : : int i, n;
2509 : :
2510 : 0 : sal_uInt16* str = (sal_uInt16*)malloc(nChars * 2);
2511 : : assert(str != 0);
2512 : :
2513 [ # # ]: 0 : for (i=0; i<nChars; i++) str[i] = (sal_uInt16)(firstChar + i);
2514 [ # # ]: 0 : if ((n = MapString(ttf, str, nChars, 0, mode)) != -1) {
2515 : 0 : res = GetTTSimpleGlyphMetrics(ttf, str, n, mode);
2516 : : }
2517 : :
2518 : 0 : free(str);
2519 : :
2520 : 0 : return res;
2521 : : }
2522 : : #endif
2523 : :
2524 : 8655 : void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info)
2525 : : {
2526 : 8655 : int UPEm = ttf->unitsPerEm;
2527 : :
2528 : 8655 : memset(info, 0, sizeof(TTGlobalFontInfo));
2529 : :
2530 : 8655 : info->family = ttf->family;
2531 : 8655 : info->ufamily = ttf->ufamily;
2532 : 8655 : info->subfamily = ttf->subfamily;
2533 : 8655 : info->usubfamily = ttf->usubfamily;
2534 : 8655 : info->psname = ttf->psname;
2535 : 8655 : info->symbolEncoded = (ttf->cmapType == CMAP_MS_Symbol);
2536 : :
2537 : 8655 : const sal_uInt8* table = getTable(ttf, O_OS2);
2538 [ + - ]: 8655 : if (table) {
2539 : 8655 : info->weight = GetUInt16(table, 4, 1);
2540 : 8655 : info->width = GetUInt16(table, 6, 1);
2541 : :
2542 : : /* There are 3 different versions of OS/2 table: original (68 bytes long),
2543 : : * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,)
2544 : : * Apple's documentation recommends looking at the table length.
2545 : : */
2546 [ + - ]: 8655 : if (getTableSize(ttf, O_OS2) > 68) {
2547 : 8655 : info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1));
2548 : 8655 : info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1));
2549 : 8655 : info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1));
2550 : 8655 : info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1));
2551 : 8655 : info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1));
2552 : : /* sanity check; some fonts treat winDescent as signed
2553 : : * violating the standard */
2554 [ - + ]: 8655 : if( info->winDescent > 5*UPEm )
2555 : 0 : info->winDescent = XUnits(UPEm, GetInt16(table, 76,1));
2556 : : }
2557 [ + - ]: 8655 : if (ttf->cmapType == CMAP_MS_Unicode) {
2558 : 8655 : info->rangeFlag = 1;
2559 : 8655 : info->ur1 = GetUInt32(table, 42, 1);
2560 : 8655 : info->ur2 = GetUInt32(table, 46, 1);
2561 : 8655 : info->ur3 = GetUInt32(table, 50, 1);
2562 : 8655 : info->ur4 = GetUInt32(table, 54, 1);
2563 : : }
2564 : 8655 : memcpy(info->panose, table + 32, 10);
2565 : 8655 : info->typeFlags = GetUInt16( table, 8, 1 );
2566 [ + + ]: 8655 : if( getTable(ttf, O_CFF) )
2567 : 408 : info->typeFlags |= TYPEFLAG_PS_OPENTYPE;
2568 : : }
2569 : :
2570 : 8655 : table = getTable(ttf, O_post);
2571 [ + - ][ + - ]: 8655 : if (table && getTableSize(ttf, O_post) >= 12+sizeof(sal_uInt32)) {
[ + - ]
2572 : 8655 : info->pitch = GetUInt32(table, 12, 1);
2573 : 8655 : info->italicAngle = GetInt32(table, 4, 1);
2574 : : }
2575 : :
2576 : 8655 : table = getTable(ttf, O_head); /* 'head' tables is always there */
2577 : 8655 : info->xMin = XUnits(UPEm, GetInt16(table, 36, 1));
2578 : 8655 : info->yMin = XUnits(UPEm, GetInt16(table, 38, 1));
2579 : 8655 : info->xMax = XUnits(UPEm, GetInt16(table, 40, 1));
2580 : 8655 : info->yMax = XUnits(UPEm, GetInt16(table, 42, 1));
2581 : 8655 : info->macStyle = GetInt16(table, 44, 1);
2582 : :
2583 : 8655 : table = getTable(ttf, O_hhea);
2584 [ + - ]: 8655 : if (table) {
2585 : 8655 : info->ascender = XUnits(UPEm, GetInt16(table, 4, 1));
2586 : 8655 : info->descender = XUnits(UPEm, GetInt16(table, 6, 1));
2587 : 8655 : info->linegap = XUnits(UPEm, GetInt16(table, 8, 1));
2588 : : }
2589 : :
2590 : 8655 : table = getTable(ttf, O_vhea);
2591 [ + + ]: 8655 : if (table) {
2592 : 408 : info->vascent = XUnits(UPEm, GetInt16(table, 4, 1));
2593 : 408 : info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1));
2594 : : }
2595 : 8655 : }
2596 : :
2597 : 0 : GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, sal_uInt32 glyphID)
2598 : : {
2599 : 0 : const sal_uInt8* glyf = getTable(ttf, O_glyf);
2600 : 0 : const sal_uInt8* hmtx = getTable(ttf, O_hmtx);
2601 : : int n;
2602 : :
2603 [ # # ]: 0 : if( glyphID >= ttf->nglyphs )
2604 : 0 : return 0;
2605 : :
2606 : : /* #127161# check the glyph offsets */
2607 : 0 : sal_uInt32 length = getTableSize( ttf, O_glyf );
2608 [ # # ]: 0 : if( length < ttf->goffsets[ glyphID+1 ] )
2609 : 0 : return 0;
2610 : :
2611 : 0 : length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
2612 : :
2613 : 0 : GlyphData* d = (GlyphData*)malloc(sizeof(GlyphData)); assert(d != 0);
2614 : :
2615 [ # # ]: 0 : if (length > 0) {
2616 : 0 : const sal_uInt8* srcptr = glyf + ttf->goffsets[glyphID];
2617 : 0 : d->ptr = (sal_uInt8*)malloc((length + 1) & ~1); assert(d->ptr != 0);
2618 : 0 : memcpy( d->ptr, srcptr, length );
2619 : 0 : d->compflag = (GetInt16( srcptr, 0, 1 ) < 0);
2620 : : } else {
2621 : 0 : d->ptr = 0;
2622 : 0 : d->compflag = 0;
2623 : : }
2624 : :
2625 : 0 : d->glyphID = glyphID;
2626 : 0 : d->nbytes = (sal_uInt16)((length + 1) & ~1);
2627 : :
2628 : : /* now calculate npoints and ncontours */
2629 : : ControlPoint *cp;
2630 [ # # ]: 0 : n = GetTTGlyphPoints(ttf, glyphID, &cp);
2631 [ # # ]: 0 : if (n != -1)
2632 : : {
2633 : 0 : int m = 0;
2634 [ # # ]: 0 : for (int i = 0; i < n; i++)
2635 : : {
2636 [ # # ]: 0 : if (cp[i].flags & 0x8000)
2637 : 0 : m++;
2638 : : }
2639 : 0 : d->npoints = (sal_uInt16)n;
2640 : 0 : d->ncontours = (sal_uInt16)m;
2641 : 0 : free(cp);
2642 : : } else {
2643 : 0 : d->npoints = 0;
2644 : 0 : d->ncontours = 0;
2645 : : }
2646 : :
2647 : : /* get advance width and left sidebearing */
2648 [ # # ]: 0 : if (glyphID < ttf->numberOfHMetrics) {
2649 : 0 : d->aw = GetUInt16(hmtx, 4 * glyphID, 1);
2650 : 0 : d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1);
2651 : : } else {
2652 : 0 : d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1);
2653 : 0 : d->lsb = GetInt16(hmtx + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1);
2654 : : }
2655 : :
2656 : 0 : return d;
2657 : : }
2658 : :
2659 : 8655 : int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr)
2660 : : {
2661 : 8655 : const sal_uInt8* table = getTable(ttf, O_name);
2662 : 8655 : int nTableSize = getTableSize(ttf, O_name );
2663 : :
2664 [ - + ]: 8655 : if (nTableSize < 6)
2665 : : {
2666 : : #if OSL_DEBUG_LEVEL > 1
2667 : : fprintf(stderr, "O_name table too small\n");
2668 : : #endif
2669 : 0 : return 0;
2670 : : }
2671 : :
2672 : 8655 : sal_uInt16 n = GetUInt16(table, 2, 1);
2673 : 8655 : int nStrBase = GetUInt16(table, 4, 1);
2674 : : int i;
2675 : :
2676 : 8655 : *nr = 0;
2677 [ - + ]: 8655 : if (n == 0) return 0;
2678 : :
2679 : 8655 : NameRecord* rec = (NameRecord*)calloc(n, sizeof(NameRecord));
2680 : :
2681 [ + + ]: 490683 : for (i = 0; i < n; i++) {
2682 : 482028 : int nStrOffset = GetUInt16(table + 6, 10 + 12 * i, 1);
2683 : 482028 : rec[i].platformID = GetUInt16(table + 6, 12 * i, 1);
2684 : 482028 : rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1);
2685 : 482028 : rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1);
2686 : 482028 : rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1);
2687 : 482028 : rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1);
2688 [ + - ]: 482028 : if (rec[i].slen) {
2689 [ + + ]: 482028 : if( nStrBase+nStrOffset+rec[i].slen >= nTableSize ) {
2690 : 2550 : rec[i].sptr = 0;
2691 : 2550 : rec[i].slen = 0;
2692 : 2550 : continue;
2693 : : }
2694 : :
2695 : 479478 : const sal_uInt8* rec_string = table + nStrBase + nStrOffset;
2696 : : // sanity check
2697 [ + - ][ + - ]: 479478 : if( rec_string > (sal_uInt8*)ttf->ptr && rec_string < ((sal_uInt8*)ttf->ptr + ttf->fsize - rec[i].slen ) )
2698 : : {
2699 : 479478 : rec[i].sptr = (sal_uInt8 *) malloc(rec[i].slen); assert(rec[i].sptr != 0);
2700 : 479478 : memcpy(rec[i].sptr, rec_string, rec[i].slen);
2701 : : }
2702 : : else
2703 : : {
2704 : 0 : rec[i].sptr = 0;
2705 : 479478 : rec[i].slen = 0;
2706 : : }
2707 : : } else {
2708 : 0 : rec[i].sptr = 0;
2709 : : }
2710 : : // some fonts have 3.0 names => fix them to 3.1
2711 [ + + ][ - + ]: 479478 : if( (rec[i].platformID == 3) && (rec[i].encodingID == 0) )
2712 : 0 : rec[i].encodingID = 1;
2713 : : }
2714 : :
2715 : 8655 : *nr = rec;
2716 : 8655 : return n;
2717 : : }
2718 : :
2719 : 8655 : void DisposeNameRecords(NameRecord* nr, int n)
2720 : : {
2721 : : int i;
2722 [ + + ]: 490683 : for (i = 0; i < n; i++) {
2723 [ + + ]: 482028 : if (nr[i].sptr) free(nr[i].sptr);
2724 : : }
2725 : 8655 : free(nr);
2726 : 8655 : }
2727 : :
2728 : 2 : bool getTTCoverage(
2729 : : boost::dynamic_bitset<sal_uInt32> &rUnicodeRange,
2730 : : boost::dynamic_bitset<sal_uInt32> &rCodePageRange,
2731 : : const unsigned char* pTable, size_t nLength)
2732 : : {
2733 : 2 : bool bRet = false;
2734 : 2 : sal_uInt16 nVersion = GetUInt16(pTable, 0, 1);
2735 : : // parse OS/2 header
2736 [ + - ][ + - ]: 2 : if ( nVersion >= 0x0001 && nLength >= 58 )
2737 : : {
2738 : 2 : rUnicodeRange.append(GetUInt32(pTable, 42, 1));
2739 : 2 : rUnicodeRange.append(GetUInt32(pTable, 46, 1));
2740 : 2 : rUnicodeRange.append(GetUInt32(pTable, 50, 1));
2741 : 2 : rUnicodeRange.append(GetUInt32(pTable, 54, 1));
2742 : 2 : bRet = true;
2743 [ + - ]: 2 : if (nLength >= 86)
2744 : : {
2745 : 2 : rCodePageRange.append(GetUInt32(pTable, 78, 1));
2746 : 2 : rCodePageRange.append(GetUInt32(pTable, 82, 1));
2747 : : }
2748 : : }
2749 : 2 : return bRet;
2750 : : }
2751 : :
2752 : 2 : void getTTScripts(std::vector< sal_uInt32 > &rScriptTags, const unsigned char* pTable, size_t nLength)
2753 : : {
2754 [ - + ]: 2 : if (nLength < 6)
2755 : 2 : return;
2756 : :
2757 : : // parse GSUB/GPOS header
2758 : 2 : const sal_uInt16 nOfsScriptList = GetUInt16(pTable, 4, 1);
2759 : :
2760 : : // parse Script Table
2761 : 2 : const sal_uInt16 nCntScript = GetUInt16(pTable, nOfsScriptList, 1);
2762 : 2 : sal_uInt32 nCurrentPos = nOfsScriptList+2;
2763 [ + + ][ + - ]: 10 : for( sal_uInt16 nScriptIndex = 0;
[ + + ]
2764 : : nScriptIndex < nCntScript && nLength >= 6; ++nScriptIndex,
2765 : : nLength-=6 )
2766 : : {
2767 : 8 : sal_uInt32 nTag = GetUInt32(pTable, nCurrentPos, 1);
2768 : 8 : nCurrentPos+=6;
2769 [ + - ]: 8 : rScriptTags.push_back(nTag); // e.g. hani/arab/kana/hang
2770 : : }
2771 : :
2772 : 2 : std::sort(rScriptTags.begin(), rScriptTags.end());
2773 : 2 : rScriptTags.erase(std::unique(rScriptTags.begin(), rScriptTags.end()), rScriptTags.end());
2774 : : }
2775 : :
2776 : : } // namespace vcl
2777 : :
2778 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|