1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 /*
28 * Sun Font Tools
29 *
30 * Author: Alexander Gelfenbain
31 *
32 */
33
34 #if OSL_DEBUG_LEVEL == 0
35 # ifndef NDEBUG
36 # define NDEBUG
37 # endif
38 #endif
39 #include <assert.h>
40
41 #include <stdlib.h>
42 #include <string.h>
43 #include <fcntl.h>
44 #ifdef UNX
45 #include <sys/mman.h>
46 #include <sys/stat.h>
47 #endif
48 #include "sft.hxx"
49 #include "gsub.h"
50 #if ! (defined(NO_TTCR) && defined(NO_TYPE42))
51 #include "ttcr.hxx"
52 #endif
53 #ifndef NO_MAPPERS /* include MapChar() and MapString() */
54 #include "xlat.hxx"
55 #endif
56 #ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */
57 #include <rtl/crc.h>
58 #endif
59
60 #include <osl/endian.h>
61 #include <algorithm>
62
63 #ifdef TEST7
64 #include <ctype.h>
65 #endif
66
67 namespace vcl
68 {
69
70 /*- module identification */
71
72 static const char *modname = "SunTypeTools-TT";
73 static const char *modver = "1.0";
74 static const char *modextra = "gelf";
75
76 /*- private functions, constants and data types */ /*FOLD00*/
77
78 enum PathSegmentType {
79 PS_NOOP = 0,
80 PS_MOVETO = 1,
81 PS_LINETO = 2,
82 PS_CURVETO = 3,
83 PS_CLOSEPATH = 4
84 };
85
86 struct PSPathElement
87 {
88 PathSegmentType type;
89 int x1, y1;
90 int x2, y2;
91 int x3, y3;
92
PSPathElementvcl::PSPathElement93 PSPathElement( PathSegmentType i_eType ) : type( i_eType ),
94 x1( 0 ), y1( 0 ),
95 x2( 0 ), y2( 0 ),
96 x3( 0 ), y3( 0 )
97 {
98 }
99 };
100
101 /*- In horizontal writing mode right sidebearing is calculated using this formula
102 *- rsb = aw - (lsb + xMax - xMin) -*/
103 typedef struct {
104 sal_Int16 xMin;
105 sal_Int16 yMin;
106 sal_Int16 xMax;
107 sal_Int16 yMax;
108 sal_uInt16 aw; /*- Advance width (horizontal writing mode) */
109 sal_Int16 lsb; /*- Left sidebearing (horizontal writing mode) */
110 sal_uInt16 ah; /*- Advance height (vertical writing mode) */
111 sal_Int16 tsb; /*- Top sidebearing (vertical writing mode) */
112 } TTGlyphMetrics;
113
114 #define HFORMAT_LINELEN 64
115
116 typedef struct {
117 FILE *o;
118 char buffer[HFORMAT_LINELEN];
119 int bufpos;
120 int total;
121 } HexFmt;
122
123 typedef struct {
124 sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */
125 sal_uInt32 *offs; /* array of nGlyphs offsets */
126 } GlyphOffsets;
127
128 /* private tags */
129 static const sal_uInt32 TTFontClassTag = 0x74746663; /* 'ttfc' */
130
131 static const sal_uInt32 T_true = 0x74727565; /* 'true' */
132 static const sal_uInt32 T_ttcf = 0x74746366; /* 'ttcf' */
133 static const sal_uInt32 T_otto = 0x4f54544f; /* 'OTTO' */
134
135 /* standard TrueType table tags */
136 #define T_maxp 0x6D617870
137 #define T_glyf 0x676C7966
138 #define T_head 0x68656164
139 #define T_loca 0x6C6F6361
140 #define T_name 0x6E616D65
141 #define T_hhea 0x68686561
142 #define T_hmtx 0x686D7478
143 #define T_cmap 0x636D6170
144 #define T_vhea 0x76686561
145 #define T_vmtx 0x766D7478
146 #define T_OS2 0x4F532F32
147 #define T_post 0x706F7374
148 #define T_kern 0x6B65726E
149 #define T_cvt 0x63767420
150 #define T_prep 0x70726570
151 #define T_fpgm 0x6670676D
152 #define T_gsub 0x47535542
153 #define T_CFF 0x43464620
154
155 #define LAST_URANGE_BIT 69
156 const char *ulcodes[LAST_URANGE_BIT+2] = {
157 /* 0 */ "Basic Latin",
158 /* 1 */ "Latin-1 Supplement",
159 /* 2 */ "Latin Extended-A",
160 /* 3 */ "Latin Extended-B",
161 /* 4 */ "IPA Extensions",
162 /* 5 */ "Spacing Modifier Letters",
163 /* 6 */ "Combining Diacritical Marks",
164 /* 7 */ "Basic Greek",
165 /* 8 */ "Greek Symbols And Coptic",
166 /* 9 */ "Cyrillic",
167 /* 10 */ "Armenian",
168 /* 11 */ "Basic Hebrew",
169 /* 12 */ "Hebrew Extended (A and B blocks combined)",
170 /* 13 */ "Basic Arabic",
171 /* 14 */ "Arabic Extended",
172 /* 15 */ "Devanagari",
173 /* 16 */ "Bengali",
174 /* 17 */ "Gurmukhi",
175 /* 18 */ "Gujarati",
176 /* 19 */ "Oriya",
177 /* 20 */ "Tamil",
178 /* 21 */ "Telugu",
179 /* 22 */ "Kannada",
180 /* 23 */ "Malayalam",
181 /* 24 */ "Thai",
182 /* 25 */ "Lao",
183 /* 26 */ "Basic Georgian",
184 /* 27 */ "Georgian Extended",
185 /* 28 */ "Hangul Jamo",
186 /* 29 */ "Latin Extended Additional",
187 /* 30 */ "Greek Extended",
188 /* 31 */ "General Punctuation",
189 /* 32 */ "Superscripts And Subscripts",
190 /* 33 */ "Currency Symbols",
191 /* 34 */ "Combining Diacritical Marks For Symbols",
192 /* 35 */ "Letterlike Symbols",
193 /* 36 */ "Number Forms",
194 /* 37 */ "Arrows",
195 /* 38 */ "Mathematical Operators",
196 /* 39 */ "Miscellaneous Technical",
197 /* 40 */ "Control Pictures",
198 /* 41 */ "Optical Character Recognition",
199 /* 42 */ "Enclosed Alphanumerics",
200 /* 43 */ "Box Drawing",
201 /* 44 */ "Block Elements",
202 /* 45 */ "Geometric Shapes",
203 /* 46 */ "Miscellaneous Symbols",
204 /* 47 */ "Dingbats",
205 /* 48 */ "CJK Symbols And Punctuation",
206 /* 49 */ "Hiragana",
207 /* 50 */ "Katakana",
208 /* 51 */ "Bopomofo",
209 /* 52 */ "Hangul Compatibility Jamo",
210 /* 53 */ "CJK Miscellaneous",
211 /* 54 */ "Enclosed CJK Letters And Months",
212 /* 55 */ "CJK Compatibility",
213 /* 56 */ "Hangul",
214 /* 57 */ "Reserved for Unicode SubRanges",
215 /* 58 */ "Reserved for Unicode SubRanges",
216 /* 59 */ "CJK Unified Ideographs",
217 /* 60 */ "Private Use Area",
218 /* 61 */ "CJK Compatibility Ideographs",
219 /* 62 */ "Alphabetic Presentation Forms",
220 /* 63 */ "Arabic Presentation Forms-A",
221 /* 64 */ "Combining Half Marks",
222 /* 65 */ "CJK Compatibility Forms",
223 /* 66 */ "Small Form Variants",
224 /* 67 */ "Arabic Presentation Forms-B",
225 /* 68 */ "Halfwidth And Fullwidth Forms",
226 /* 69 */ "Specials",
227 /*70-127*/ "Reserved for Unicode SubRanges"
228 };
229
230
231
232 /*- inline functions */ /*FOLD01*/
233 #ifdef __GNUC__
234 #define _inline static __inline__
235 #else
236 #define _inline static
237 #endif
238
smalloc(size_t size)239 _inline void *smalloc(size_t size)
240 {
241 void *res = malloc(size);
242 assert(res != 0);
243 return res;
244 }
245
scalloc(size_t n,size_t size)246 _inline void *scalloc(size_t n, size_t size)
247 {
248 void *res = calloc(n, size);
249 assert(res != 0);
250 return res;
251 }
252
mkTag(sal_uInt8 a,sal_uInt8 b,sal_uInt8 c,sal_uInt8 d)253 _inline sal_uInt32 mkTag(sal_uInt8 a, sal_uInt8 b, sal_uInt8 c, sal_uInt8 d) {
254 return (a << 24) | (b << 16) | (c << 8) | d;
255 }
256
257 /* Whether nBytes starting at nOffset lie inside a table of nSize bytes. */
fitsInTable(sal_uInt32 nOffset,sal_uInt32 nBytes,sal_uInt32 nSize)258 _inline bool fitsInTable(sal_uInt32 nOffset, sal_uInt32 nBytes, sal_uInt32 nSize)
259 {
260 return (nOffset <= nSize) && (nBytes <= nSize - nOffset);
261 }
262
263 /*- Data access macros for data stored in big-endian or little-endian format */
GetInt16(const sal_uInt8 * ptr,size_t offset,int bigendian)264 _inline sal_Int16 GetInt16(const sal_uInt8 *ptr, size_t offset, int bigendian)
265 {
266 sal_Int16 t;
267 assert(ptr != 0);
268
269 if (bigendian) {
270 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
271 } else {
272 t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
273 }
274
275 return t;
276 }
277
GetUInt16(const sal_uInt8 * ptr,size_t offset,int bigendian)278 _inline sal_uInt16 GetUInt16(const sal_uInt8 *ptr, size_t offset, int bigendian)
279 {
280 sal_uInt16 t;
281 assert(ptr != 0);
282
283 if (bigendian) {
284 t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
285 } else {
286 t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
287 }
288
289 return t;
290 }
291
GetInt32(const sal_uInt8 * ptr,size_t offset,int bigendian)292 _inline sal_Int32 GetInt32(const sal_uInt8 *ptr, size_t offset, int bigendian)
293 {
294 sal_Int32 t;
295 assert(ptr != 0);
296
297 if (bigendian) {
298 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
299 (ptr+offset)[2] << 8 | (ptr+offset)[3];
300 } else {
301 t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
302 (ptr+offset)[1] << 8 | (ptr+offset)[0];
303 }
304
305 return t;
306 }
307
GetUInt32(const sal_uInt8 * ptr,size_t offset,int bigendian)308 _inline sal_uInt32 GetUInt32(const sal_uInt8 *ptr, size_t offset, int bigendian)
309 {
310 sal_uInt32 t;
311 assert(ptr != 0);
312
313
314 if (bigendian) {
315 t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
316 (ptr+offset)[2] << 8 | (ptr+offset)[3];
317 } else {
318 t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
319 (ptr+offset)[1] << 8 | (ptr+offset)[0];
320 }
321
322 return t;
323 }
324
PutInt16(sal_Int16 val,sal_uInt8 * ptr,size_t offset,int bigendian)325 _inline void PutInt16(sal_Int16 val, sal_uInt8 *ptr, size_t offset, int bigendian)
326 {
327 assert(ptr != 0);
328
329 if (bigendian) {
330 ptr[offset] = (sal_uInt8)((val >> 8) & 0xFF);
331 ptr[offset+1] = (sal_uInt8)(val & 0xFF);
332 } else {
333 ptr[offset+1] = (sal_uInt8)((val >> 8) & 0xFF);
334 ptr[offset] = (sal_uInt8)(val & 0xFF);
335 }
336
337 }
338
339 #if defined(OSL_BIGENDIAN)
340 #define Int16FromMOTA(a) (a)
341 #define Int32FromMOTA(a) (a)
342 #else
Int16FromMOTA(sal_uInt16 a)343 static sal_uInt16 Int16FromMOTA(sal_uInt16 a) {
344 return (sal_uInt16) (((sal_uInt8)((a) >> 8)) | ((sal_uInt8)(a) << 8));
345 }
Int32FromMOTA(sal_uInt32 a)346 static sal_uInt32 Int32FromMOTA(sal_uInt32 a) {
347 return ((a>>24)&0xFF) | (((a>>8)&0xFF00) | ((a&0xFF00)<<8) | ((a&0xFF)<<24));
348 }
349 #endif
350
fixedMul(F16Dot16 a,F16Dot16 b)351 _inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b)
352 {
353 unsigned int a1, b1;
354 unsigned int a2, b2;
355 F16Dot16 res;
356 int sign;
357
358 sign = (a & 0x80000000) ^ (b & 0x80000000);
359 if (a < 0) a = -a;
360 if (b < 0) b = -b;
361
362 a1 = a >> 16;
363 b1 = a & 0xFFFF;
364 a2 = b >> 16;
365 b2 = b & 0xFFFF;
366
367 res = a1 * a2;
368
369 /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */
370
371 res <<= 16;
372 res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16);
373
374 return sign ? -res : res;
375 }
376
377
fixedDiv(F16Dot16 a,F16Dot16 b)378 _inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b)
379 {
380 unsigned int f, r;
381 F16Dot16 res;
382 int sign;
383
384 sign = (a & 0x80000000) ^ (b & 0x80000000);
385 if (a < 0) a = -a;
386 if (b < 0) b = -b;
387
388 f = a / b;
389 r = a % b;
390
391 /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */
392
393 while (r > 0xFFFF) {
394 r >>= 1;
395 b >>= 1;
396 }
397
398 res = (f << 16) + (r << 16) / b;
399
400 return sign ? -res : res;
401 }
402
403 /*- returns a * b / c -*/
404 /* XXX provide a real implementation that preserves accuracy */
fixedMulDiv(F16Dot16 a,F16Dot16 b,F16Dot16 c)405 _inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c)
406 {
407 F16Dot16 res;
408
409 res = fixedMul(a, b);
410 return fixedDiv(res, c);
411 }
412
413 /*- Translate units from TT to PS (standard 1/1000) -*/
XUnits(int unitsPerEm,int n)414 _inline int XUnits(int unitsPerEm, int n)
415 {
416 return (n * 1000) / unitsPerEm;
417 }
418
UnicodeRangeName(sal_uInt16 bit)419 _inline const char *UnicodeRangeName(sal_uInt16 bit)
420 {
421 if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1;
422
423 return ulcodes[bit];
424 }
425
getTable(TrueTypeFont * ttf,sal_uInt32 ord)426 _inline const sal_uInt8* getTable( TrueTypeFont *ttf, sal_uInt32 ord)
427 {
428 return (sal_uInt8*)ttf->tables[ord];
429 }
430
getTableSize(TrueTypeFont * ttf,sal_uInt32 ord)431 _inline sal_uInt32 getTableSize(TrueTypeFont *ttf, sal_uInt32 ord)
432 {
433 return ttf->tlens[ord];
434 }
435
436 #ifndef NO_TYPE42
437 /* Hex Formatter functions */
438 static char HexChars[] = "0123456789ABCDEF";
439
HexFmtNew(FILE * outf)440 static HexFmt *HexFmtNew(FILE *outf)
441 {
442 HexFmt* res = (HexFmt*)smalloc(sizeof(HexFmt));
443 res->bufpos = res->total = 0;
444 res->o = outf;
445 return res;
446 }
447
HexFmtFlush(HexFmt * _this)448 static void HexFmtFlush(HexFmt *_this)
449 {
450 if (_this->bufpos) {
451 fwrite(_this->buffer, 1, _this->bufpos, _this->o);
452 _this->bufpos = 0;
453 }
454 }
455
456
HexFmtOpenString(HexFmt * _this)457 _inline void HexFmtOpenString(HexFmt *_this)
458 {
459 fputs("<\n", _this->o);
460 }
461
HexFmtCloseString(HexFmt * _this)462 _inline void HexFmtCloseString(HexFmt *_this)
463 {
464 HexFmtFlush(_this);
465 fputs("00\n>\n", _this->o);
466 }
467
HexFmtDispose(HexFmt * _this)468 _inline void HexFmtDispose(HexFmt *_this)
469 {
470 HexFmtFlush(_this);
471 free(_this);
472 }
473
HexFmtBlockWrite(HexFmt * _this,const void * ptr,sal_uInt32 size)474 static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size)
475 {
476 sal_uInt8 Ch;
477 sal_uInt32 i;
478
479 if (_this->total + size > 65534) {
480 HexFmtFlush(_this);
481 HexFmtCloseString(_this);
482 _this->total = 0;
483 HexFmtOpenString(_this);
484 }
485 for (i=0; i<size; i++) {
486 Ch = ((sal_uInt8 *) ptr)[i];
487 _this->buffer[_this->bufpos++] = HexChars[Ch >> 4];
488 _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF];
489 if (_this->bufpos == HFORMAT_LINELEN) {
490 HexFmtFlush(_this);
491 fputc('\n', _this->o);
492 }
493
494 }
495 _this->total += size;
496 }
497 #endif
498
499
500
501 /* Outline Extraction functions */ /*FOLD01*/
502
503 /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
GetMetrics(TrueTypeFont * ttf,sal_uInt32 glyphID,TTGlyphMetrics * metrics)504 static void GetMetrics(TrueTypeFont *ttf, sal_uInt32 glyphID, TTGlyphMetrics *metrics)
505 {
506 const sal_uInt8* table = getTable( ttf, O_hmtx );
507
508 metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0;
509 if (!table || !ttf->numberOfHMetrics) return;
510
511 if (glyphID < ttf->numberOfHMetrics) {
512 metrics->aw = GetUInt16(table, 4 * glyphID, 1);
513 metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1);
514 } else {
515 metrics->aw = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1);
516 const sal_uInt32 nLsbOff = ttf->numberOfHMetrics * 4 + (glyphID - ttf->numberOfHMetrics) * 2;
517 if (fitsInTable(nLsbOff, 2, getTableSize(ttf, O_hmtx)))
518 metrics->lsb = GetInt16(table, nLsbOff, 1);
519 }
520
521 table = getTable(ttf, O_vmtx);
522 if( !table || !ttf->numOfLongVerMetrics )
523 return;
524
525 if (glyphID < ttf->numOfLongVerMetrics) {
526 metrics->ah = GetUInt16(table, 4 * glyphID, 1);
527 metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1);
528 } else {
529 metrics->ah = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1);
530 const sal_uInt32 nTsbOff = ttf->numOfLongVerMetrics * 4 + (glyphID - ttf->numOfLongVerMetrics) * 2;
531 if (fitsInTable(nTsbOff, 2, getTableSize(ttf, O_vmtx)))
532 metrics->tsb = GetInt16(table, nTsbOff, 1);
533 }
534 }
535
536 static int GetTTGlyphOutline(TrueTypeFont *, sal_uInt32 , ControlPoint **, TTGlyphMetrics *, std::vector< sal_uInt32 >* );
537
538 /* returns the number of control points, allocates the pointArray */
GetSimpleTTOutline(TrueTypeFont * ttf,sal_uInt32 glyphID,ControlPoint ** pointArray,TTGlyphMetrics * metrics)539 static int GetSimpleTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/
540 {
541 const sal_uInt8* table = getTable( ttf, O_glyf );
542 sal_uInt8 flag, n;
543 sal_uInt16 t, lastPoint=0;
544 int i, j, z;
545
546 *pointArray = 0;
547
548 /* printf("GetSimpleTTOutline(%d)\n", glyphID); */
549
550 if( glyphID >= ttf->nglyphs ) /*- glyph is not present in the font */
551 return 0;
552 /* goffsets were checked against glyf in doOpenTTFont() */
553 const sal_uInt32 nGlyphLen = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
554 const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
555 const sal_uInt8* const pEnd = ptr + nGlyphLen;
556 if( nGlyphLen < 10 ) /*- shorter than a glyph header */
557 return 0;
558 const sal_Int16 numberOfContours = GetInt16(ptr, 0, 1);
559 if( numberOfContours <= 0 ) /*- glyph is not simple */
560 return 0;
561 /* One end point per contour, then the two-byte instruction length. */
562 if( !fitsInTable(10, (sal_uInt32)numberOfContours * 2 + 2, nGlyphLen) )
563 return 0;
564
565 if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
566 metrics->xMin = GetInt16(ptr, 2, 1);
567 metrics->yMin = GetInt16(ptr, 4, 1);
568 metrics->xMax = GetInt16(ptr, 6, 1);
569 metrics->yMax = GetInt16(ptr, 8, 1);
570 GetMetrics(ttf, glyphID, metrics);
571 }
572
573 /* determine the last point and be extra safe about it. But probably this code is not needed */
574
575 for (i=0; i<numberOfContours; i++) {
576 if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t;
577 }
578
579 sal_uInt16 instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1);
580 const sal_uInt8* p = ptr + 10 + 2 * numberOfContours + 2 + instLen;
581 if( p > pEnd ) /*- the instructions leave the glyph */
582 return 0;
583 ControlPoint* pa = (ControlPoint*)calloc(lastPoint+1, sizeof(ControlPoint));
584 if (!pa)
585 return 0;
586
587 i = 0;
588 while (i <= lastPoint) {
589 if (p >= pEnd) {
590 free(pa);
591 return 0;
592 }
593 pa[i++].flags = (sal_uInt32) (flag = *p++);
594 if (flag & 8) { /*- repeat flag */
595 if (p >= pEnd) {
596 free(pa);
597 return 0;
598 }
599 n = *p++;
600 for (j=0; j<n; j++) {
601 if (i > lastPoint) { /*- if the font is really broken */
602 free(pa);
603 return 0;
604 }
605 pa[i++].flags = flag;
606 }
607 }
608 }
609
610 /*- Process the X coordinate */
611 z = 0;
612 for (i = 0; i <= lastPoint; i++) {
613 if (pa[i].flags & 0x02) {
614 if (p >= pEnd) {
615 free(pa);
616 return 0;
617 }
618 if (pa[i].flags & 0x10) {
619 z += (int) (*p++);
620 } else {
621 z -= (int) (*p++);
622 }
623 } else if ( !(pa[i].flags & 0x10)) {
624 if (p + 2 > pEnd) {
625 free(pa);
626 return 0;
627 }
628 z += GetInt16(p, 0, 1);
629 p += 2;
630 }
631 pa[i].x = (sal_Int16)z;
632 }
633
634 /*- Process the Y coordinate */
635 z = 0;
636 for (i = 0; i <= lastPoint; i++) {
637 if (pa[i].flags & 0x04) {
638 if (p >= pEnd) {
639 free(pa);
640 return 0;
641 }
642 if (pa[i].flags & 0x20) {
643 z += *p++;
644 } else {
645 z -= *p++;
646 }
647 } else if ( !(pa[i].flags & 0x20)) {
648 if (p + 2 > pEnd) {
649 free(pa);
650 return 0;
651 }
652 z += GetInt16(p, 0, 1);
653 p += 2;
654 }
655 pa[i].y = (sal_Int16)z;
656 }
657
658 for (i=0; i<numberOfContours; i++) {
659 pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000; /*- set the end contour flag */
660 }
661
662 *pointArray = pa;
663 return lastPoint + 1;
664 }
665
666 /* How deep a compound glyph may nest. */
667 #define MAX_COMPOUND_DEPTH 16
668
GetCompoundTTOutline(TrueTypeFont * ttf,sal_uInt32 glyphID,ControlPoint ** pointArray,TTGlyphMetrics * metrics,std::vector<sal_uInt32> & glyphlist)669 static int GetCompoundTTOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >& glyphlist) /*FOLD02*/
670 {
671 sal_uInt16 flags, index;
672 sal_Int16 e, f, numberOfContours;
673 const sal_uInt8* table = getTable( ttf, O_glyf );
674 std::vector<ControlPoint> myPoints;
675 ControlPoint *nextComponent, *pa;
676 int i, np;
677 F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3;
678
679 *pointArray = 0;
680 /* printf("GetCompoundTTOutline(%d)\n", glyphID); */
681
682 if (glyphID >= ttf->nglyphs) /*- incorrect glyphID */
683 return 0;
684
685 const sal_uInt32 nGlyphLen = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
686 const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
687 const sal_uInt8* const pEnd = ptr + nGlyphLen;
688 if (nGlyphLen < 10) /*- shorter than a glyph header */
689 return 0;
690 if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) /*- glyph is not compound */
691 return 0;
692
693 if (metrics) {
694 metrics->xMin = GetInt16(ptr, 2, 1);
695 metrics->yMin = GetInt16(ptr, 4, 1);
696 metrics->xMax = GetInt16(ptr, 6, 1);
697 metrics->yMax = GetInt16(ptr, 8, 1);
698 GetMetrics(ttf, glyphID, metrics);
699 }
700
701 ptr += 10;
702
703 do {
704 if (ptr + 4 > pEnd) /*- no room for another component */
705 break;
706 flags = GetUInt16(ptr, 0, 1);
707 /* printf("flags: 0x%X\n", flags); */
708 index = GetUInt16(ptr, 2, 1);
709 ptr += 4;
710
711 if( std::find( glyphlist.begin(), glyphlist.end(), index ) != glyphlist.end() )
712 {
713 #if OSL_DEBUG_LEVEL > 1
714 fprintf(stderr, "Endless loop found in a compound glyph.\n");
715 fprintf(stderr, "%d -> ", index);
716 fprintf(stderr," [");
717 for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
718 it != glyphlist.end(); ++it )
719 {
720 fprintf( stderr,"%d ", (int) *it );
721 }
722 fprintf(stderr,"]\n");
723 /**/
724 #endif
725 /* the component is already on the current path */
726 break;
727 }
728
729 if( glyphlist.size() >= MAX_COMPOUND_DEPTH )
730 break;
731
732 glyphlist.push_back( index );
733
734 #ifdef DEBUG2
735 fprintf(stderr,"glyphlist: += %d\n", index);
736 #endif
737
738 if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, 0, &glyphlist)) == 0)
739 {
740 /* XXX that probably indicates a corrupted font */
741 #if OSL_DEBUG_LEVEL > 1
742 fprintf(stderr, "An empty compound!\n");
743 /* assert(!"An empty compound"); */
744 #endif
745 }
746
747 #ifdef DEBUG2
748 fprintf(stderr,"%d [", (int)glyphlist.size() );
749 for( std::vector< sal_uInt32 >::const_iterator it = glyphlist.begin();
750 it != glyphlist.end(); ++it )
751 {
752 fprintf( stderr,"%d ", (int) *it );
753 }
754 fprintf(stderr, "]\n");
755 if( ! glyphlist.empty() )
756 fprintf(stderr, "glyphlist: -= %d\n", (int) glyphlist.back());
757
758 #endif
759 if( ! glyphlist.empty() )
760 glyphlist.pop_back();
761
762 if (flags & USE_MY_METRICS) {
763 if (metrics) GetMetrics(ttf, index, metrics);
764 }
765
766 if (ptr + ((flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2) > pEnd)
767 break;
768
769 if (flags & ARG_1_AND_2_ARE_WORDS) {
770 e = GetInt16(ptr, 0, 1);
771 f = GetInt16(ptr, 2, 1);
772 /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
773 ptr += 4;
774 } else {
775 if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */
776 e = (sal_Int8) *ptr++;
777 f = (sal_Int8) *ptr++;
778 /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
779 } else { /* args are unsigned */
780 /* printf("!ARGS_ARE_XY_VALUES\n"); */
781 e = *ptr++;
782 f = *ptr++;
783 }
784
785 }
786
787 a = d = 0x10000;
788 b = c = 0;
789
790 /* The transform that may follow is two, four or eight bytes. */
791 {
792 int nXformLen = 0;
793 if (flags & WE_HAVE_A_SCALE) nXformLen = 2;
794 else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) nXformLen = 4;
795 else if (flags & WE_HAVE_A_TWO_BY_TWO) nXformLen = 8;
796 if (ptr + nXformLen > pEnd)
797 break;
798 }
799
800 if (flags & WE_HAVE_A_SCALE) {
801 #ifdef DEBUG2
802 fprintf(stderr, "WE_HAVE_A_SCALE\n");
803 #endif
804 a = GetInt16(ptr, 0, 1) << 2;
805 d = a;
806 ptr += 2;
807 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
808 #ifdef DEBUG2
809 fprintf(stderr, "WE_HAVE_AN_X_AND_Y_SCALE\n");
810 #endif
811 a = GetInt16(ptr, 0, 1) << 2;
812 d = GetInt16(ptr, 2, 1) << 2;
813 ptr += 4;
814 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
815 #ifdef DEBUG2
816 fprintf(stderr, "WE_HAVE_A_TWO_BY_TWO\n");
817 #endif
818 a = GetInt16(ptr, 0, 1) << 2;
819 b = GetInt16(ptr, 2, 1) << 2;
820 c = GetInt16(ptr, 4, 1) << 2;
821 d = GetInt16(ptr, 6, 1) << 2;
822 ptr += 8;
823 }
824
825 abs1 = (a < 0) ? -a : a;
826 abs2 = (b < 0) ? -b : b;
827 m = (abs1 > abs2) ? abs1 : abs2;
828 abs3 = abs1 - abs2;
829 if (abs3 < 0) abs3 = -abs3;
830 if (abs3 <= 33) m *= 2;
831
832 abs1 = (c < 0) ? -c : c;
833 abs2 = (d < 0) ? -d : d;
834 n = (abs1 > abs2) ? abs1 : abs2;
835 abs3 = abs1 - abs2;
836 if (abs3 < 0) abs3 = -abs3;
837 if (abs3 <= 33) n *= 2;
838
839 if (!ARGS_ARE_XY_VALUES) { /* match the points */
840 assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n");
841 }
842
843 #ifdef DEBUG2
844 fprintf(stderr, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n",
845 ((double) a) / 65536,
846 ((double) b) / 65536,
847 ((double) c) / 65536,
848 ((double) d) / 65536,
849 ((double) e) / 65536,
850 ((double) f) / 65536,
851 ((double) m) / 65536,
852 ((double) n) / 65536);
853 #endif
854
855 for (i=0; i<np; i++) {
856 F16Dot16 t;
857 ControlPoint cp;
858 cp.flags = nextComponent[i].flags;
859 t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16);
860 cp.x = (sal_Int16)(fixedMul(t, m) >> 16);
861 t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16);
862 cp.y = (sal_Int16)(fixedMul(t, n) >> 16);
863
864 #ifdef DEBUG2
865 fprintf(stderr, "( %d %d ) -> ( %d %d )\n", nextComponent[i].x, nextComponent[i].y, cp.x, cp.y);
866 #endif
867
868 myPoints.push_back( cp );
869 }
870
871 free(nextComponent);
872
873 } while (flags & MORE_COMPONENTS);
874
875 // #i123417# some fonts like IFAOGrec have no outline points in some compound glyphs
876 // so this unlikely but possible scenario should be handled gracefully
877 if( myPoints.empty() )
878 return 0;
879
880 np = myPoints.size();
881
882 pa = (ControlPoint*)calloc(np, sizeof(ControlPoint));
883 assert(pa != 0);
884
885 memcpy( pa, &myPoints[0], np*sizeof(ControlPoint) );
886
887 *pointArray = pa;
888 return np;
889 }
890
891 /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect,
892 * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
893 *
894 * NOTE: glyphlist is the stack of glyphs traversed while constructing
895 * a composite glyph. This is a safeguard against endless recursion
896 * in corrupted fonts.
897 */
GetTTGlyphOutline(TrueTypeFont * ttf,sal_uInt32 glyphID,ControlPoint ** pointArray,TTGlyphMetrics * metrics,std::vector<sal_uInt32> * glyphlist)898 static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, std::vector< sal_uInt32 >* glyphlist)
899 {
900 const sal_uInt8 *table = getTable( ttf, O_glyf );
901 sal_Int16 numberOfContours;
902 int res;
903 *pointArray = 0;
904
905 if (metrics) {
906 memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeros */
907 }
908
909 if (glyphID >= ttf->nglyphs) return -1; /**/
910
911 const sal_uInt8* ptr = table + ttf->goffsets[glyphID];
912 int length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
913
914 if (length < 2) { /*- empty glyphs still have hmtx and vmtx metrics values */
915 if (metrics) GetMetrics(ttf, glyphID, metrics);
916 return 0;
917 }
918
919 numberOfContours = GetInt16(ptr, 0, 1);
920
921 if (numberOfContours >= 0)
922 {
923 res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics);
924 }
925 else
926 {
927 std::vector< sal_uInt32 > aPrivList;
928 aPrivList.push_back( glyphID );
929 res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist ? *glyphlist : aPrivList );
930 }
931
932 #ifdef DEBUG3
933 {
934 int i;
935 FILE *out = fopen("points.dat", "a");
936 assert(out != 0);
937 fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res);
938 for (i=0; i<res; i++) {
939 fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.');
940 fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-');
941 fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y);
942 }
943 fclose(out);
944 }
945 #endif
946
947 return res;
948 }
949
950 #ifndef NO_TYPE3
951
952 /*- returns the number of items in the path -*/
953
BSplineToPSPath(ControlPoint * srcA,int srcCount,PSPathElement ** path)954 static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path)
955 {
956 std::vector< PSPathElement > aPathList;
957 int nPathCount = 0;
958 PSPathElement p( PS_NOOP );
959
960 int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury;
961 int lastOff = 0; /*- last point was off-contour */
962 int scflag = 1; /*- start contour flag */
963 int ecflag = 0; /*- end contour flag */
964 int cp = 0; /*- current point */
965 int StartContour = 0, EndContour = 1;
966
967 *path = 0;
968
969 /* if (srcCount > 0) for(;;) */
970 while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */
971 if (scflag) {
972 int l = cp;
973 StartContour = cp;
974 while (!(srcA[l].flags & 0x8000)) l++;
975 EndContour = l;
976 if (StartContour == EndContour) {
977 if (cp + 1 < srcCount) {
978 cp++;
979 continue;
980 } else {
981 break;
982 }
983 }
984 p = PSPathElement(PS_MOVETO);
985 if (!(srcA[cp].flags & 1)) {
986 if (!(srcA[EndContour].flags & 1)) {
987 p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2;
988 p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2;
989 } else {
990 p.x1 = x0 = srcA[EndContour].x;
991 p.y1 = y0 = srcA[EndContour].y;
992 }
993 } else {
994 p.x1 = x0 = srcA[cp].x;
995 p.y1 = y0 = srcA[cp].y;
996 cp++;
997 }
998 aPathList.push_back( p );
999 lastOff = 0;
1000 scflag = 0;
1001 }
1002
1003 curx = srcA[cp].x;
1004 cury = srcA[cp].y;
1005
1006 if (srcA[cp].flags & 1)
1007 {
1008 if (lastOff)
1009 {
1010 p = PSPathElement(PS_CURVETO);
1011 p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
1012 p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
1013 p.x2 = x1 + (curx - x1 + 1) / 3;
1014 p.y2 = y1 + (cury - y1 + 1) / 3;
1015 p.x3 = curx;
1016 p.y3 = cury;
1017 aPathList.push_back( p );
1018 }
1019 else
1020 {
1021 if (!(x0 == curx && y0 == cury))
1022 { /* eliminate empty lines */
1023 p = PSPathElement(PS_LINETO);
1024 p.x1 = curx;
1025 p.y1 = cury;
1026 aPathList.push_back( p );
1027 }
1028 }
1029 x0 = curx; y0 = cury; lastOff = 0;
1030 }
1031 else
1032 {
1033 if (lastOff)
1034 {
1035 x2 = (x1 + curx + 1) / 2;
1036 y2 = (y1 + cury + 1) / 2;
1037 p = PSPathElement(PS_CURVETO);
1038 p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
1039 p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
1040 p.x2 = x1 + (x2 - x1 + 1) / 3;
1041 p.y2 = y1 + (y2 - y1 + 1) / 3;
1042 p.x3 = x2;
1043 p.y3 = y2;
1044 aPathList.push_back( p );
1045 x0 = x2; y0 = y2;
1046 x1 = curx; y1 = cury;
1047 } else {
1048 x1 = curx; y1 = cury;
1049 }
1050 lastOff = true;
1051 }
1052
1053 if (ecflag) {
1054 aPathList.push_back( PSPathElement(PS_CLOSEPATH) );
1055 scflag = 1;
1056 ecflag = 0;
1057 cp = EndContour + 1;
1058 if (cp >= srcCount) break;
1059 continue;
1060 }
1061
1062
1063 if (cp == EndContour) {
1064 cp = StartContour;
1065 ecflag = true;
1066 } else {
1067 cp++;
1068 }
1069 }
1070
1071 if( (nPathCount = (int)aPathList.size()) > 0)
1072 {
1073 *path = (PSPathElement*)calloc(nPathCount, sizeof(PSPathElement));
1074 assert(*path != 0);
1075 memcpy( *path, &aPathList[0], nPathCount * sizeof(PSPathElement) );
1076 }
1077
1078 return nPathCount;
1079 }
1080
1081 #endif
1082
1083 /*- Extracts a string from the name table and allocates memory for it -*/
1084
nameExtract(const sal_uInt8 * name,int nTableSize,int n,int dbFlag,sal_uInt16 ** ucs2result)1085 static char *nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result )
1086 {
1087 int i;
1088 char *res;
1089 const sal_uInt8* ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1);
1090 int len = GetUInt16(name+6, 12 * n + 8, 1);
1091
1092 // sanity check
1093 if( (len <= 0) || ((ptr+len) > (name+nTableSize)) )
1094 {
1095 if( ucs2result )
1096 *ucs2result = NULL;
1097 return NULL;
1098 }
1099
1100 if( ucs2result )
1101 *ucs2result = NULL;
1102 if (dbFlag) {
1103 res = (char*)malloc(1 + len/2);
1104 assert(res != 0);
1105 for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1);
1106 res[len/2] = 0;
1107 if( ucs2result )
1108 {
1109 *ucs2result = (sal_uInt16*)malloc( len+2 );
1110 for (i = 0; i < len/2; i++ ) (*ucs2result)[i] = GetUInt16( ptr, 2*i, 1 );
1111 (*ucs2result)[len/2] = 0;
1112 }
1113 } else {
1114 res = (char*)malloc(1 + len);
1115 assert(res != 0);
1116 memcpy(res, ptr, len);
1117 res[len] = 0;
1118 }
1119
1120 return res;
1121 }
1122
findname(const sal_uInt8 * name,sal_uInt16 n,sal_uInt16 platformID,sal_uInt16 encodingID,sal_uInt16 languageID,sal_uInt16 nameID)1123 static int findname( const sal_uInt8 *name, sal_uInt16 n, sal_uInt16 platformID,
1124 sal_uInt16 encodingID, sal_uInt16 languageID, sal_uInt16 nameID )
1125 {
1126 int l = 0, r = n-1, i;
1127 sal_uInt32 t1, t2;
1128 sal_uInt32 m1, m2;
1129
1130 if (n == 0) return -1;
1131
1132 m1 = (platformID << 16) | encodingID;
1133 m2 = (languageID << 16) | nameID;
1134
1135 do {
1136 i = (l + r) >> 1;
1137 t1 = GetUInt32(name + 6, i * 12 + 0, 1);
1138 t2 = GetUInt32(name + 6, i * 12 + 4, 1);
1139
1140 if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1;
1141 if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1;
1142 } while (l <= r);
1143
1144 if (l - r == 2) {
1145 return l - 1;
1146 }
1147
1148 return -1;
1149 }
1150
1151 /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables.
1152 * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
1153 *
1154 * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
1155 * and does not have (3, 1, 1033)
1156 * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
1157 * require a change in algorithm
1158 *
1159 * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID,
1160 * but (1, 0, 1042) strings usable
1161 * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
1162 */
1163
GetNames(TrueTypeFont * t)1164 static void GetNames(TrueTypeFont *t)
1165 {
1166 const sal_uInt8* table = getTable( t, O_name );
1167 int nTableSize = getTableSize(t, O_name);
1168
1169 if (nTableSize < 4)
1170 {
1171 #if OSL_DEBUG_LEVEL > 1
1172 fprintf(stderr, "O_name table too small\n");
1173 #endif
1174 return;
1175 }
1176
1177 sal_uInt16 n = GetUInt16(table, 2, 1);
1178 int i, r;
1179 sal_Bool bPSNameOK = sal_True;
1180
1181 /* #129743# simple sanity check for name table entry count */
1182 if( nTableSize <= n * 12 + 6 )
1183 n = 0;
1184
1185 /* PostScript name: preferred Microsoft */
1186 t->psname = NULL;
1187 if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1)
1188 t->psname = nameExtract(table, nTableSize, r, 1, NULL);
1189 if ( ! t->psname && (r = findname(table, n, 1, 0, 0, 6)) != -1)
1190 t->psname = nameExtract(table, nTableSize, r, 0, NULL);
1191 if ( ! t->psname && (r = findname(table, n, 3, 0, 0x0409, 6)) != -1)
1192 {
1193 // some symbol fonts like Marlett have a 3,0 name!
1194 t->psname = nameExtract(table, nTableSize, r, 1, NULL);
1195 }
1196 // for embedded font in Ghostscript PDFs
1197 if ( ! t->psname && (r = findname(table, n, 2, 2, 0, 6)) != -1)
1198 {
1199 t->psname = nameExtract(table, nTableSize, r, 0, NULL);
1200 }
1201 if ( ! t->psname )
1202 {
1203 if ( t->fname )
1204 {
1205 char* pReverse = t->fname + strlen(t->fname);
1206 /* take only last token of filename */
1207 while(pReverse != t->fname && *pReverse != '/') pReverse--;
1208 if(*pReverse == '/') pReverse++;
1209 t->psname = strdup(pReverse);
1210 assert(t->psname != 0);
1211 for (i=strlen(t->psname) - 1; i > 0; i--)
1212 {
1213 /*- Remove the suffix -*/
1214 if (t->psname[i] == '.' ) {
1215 t->psname[i] = 0;
1216 break;
1217 }
1218 }
1219 }
1220 else
1221 t->psname = strdup( "Unknown" );
1222 }
1223
1224 /* Font family and subfamily names: preferred Apple */
1225 t->family = NULL;
1226 if ((r = findname(table, n, 0, 0, 0, 1)) != -1)
1227 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1228 if ( ! t->family && (r = findname(table, n, 3, 1, 0x0409, 1)) != -1)
1229 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1230 if ( ! t->family && (r = findname(table, n, 1, 0, 0, 1)) != -1)
1231 t->family = nameExtract(table, nTableSize, r, 0, NULL);
1232 if ( ! t->family && (r = findname(table, n, 3, 1, 0x0411, 1)) != -1)
1233 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1234 if ( ! t->family && (r = findname(table, n, 3, 0, 0x0409, 1)) != -1)
1235 t->family = nameExtract(table, nTableSize, r, 1, &t->ufamily);
1236 if ( ! t->family )
1237 {
1238 t->family = strdup(t->psname);
1239 assert(t->family != 0);
1240 }
1241
1242 t->subfamily = NULL;
1243 t->usubfamily = NULL;
1244 if ((r = findname(table, n, 1, 0, 0, 2)) != -1)
1245 t->subfamily = nameExtract(table, nTableSize, r, 0, &t->usubfamily);
1246 if ( ! t->subfamily && (r = findname(table, n, 3, 1, 0x0409, 2)) != -1)
1247 t->subfamily = nameExtract(table, nTableSize, r, 1, &t->usubfamily);
1248 if ( ! t->subfamily )
1249 {
1250 t->subfamily = strdup("");
1251 }
1252
1253 /* #i60349# sanity check psname
1254 * psname practically has to be 7bit ascii and should not contains spaces
1255 * there is a class of broken fonts which do not fulfill that at all, so let's try
1256 * if the family name is 7bit ascii and take it instead if so
1257 */
1258 /* check psname */
1259 for( i = 0; t->psname[i] != 0 && bPSNameOK; i++ )
1260 if( t->psname[ i ] < 33 || (t->psname[ i ] & 0x80) )
1261 bPSNameOK = sal_False;
1262 if( bPSNameOK == sal_False )
1263 {
1264 sal_Bool bReplace = sal_True;
1265 /* check if family is a suitable replacement */
1266 if( t->ufamily && t->family )
1267 {
1268 for( i = 0; t->ufamily[ i ] != 0 && bReplace; i++ )
1269 if( t->ufamily[ i ] < 33 || t->ufamily[ i ] > 127 )
1270 bReplace = sal_False;
1271 if( bReplace )
1272 {
1273 free( t->psname );
1274 t->psname = strdup( t->family );
1275 }
1276 }
1277 }
1278 }
1279
1280 enum cmapType {
1281 CMAP_NOT_USABLE = -1,
1282 CMAP_MS_Symbol = 10,
1283 CMAP_MS_Unicode = 11,
1284 CMAP_MS_ShiftJIS = 12,
1285 CMAP_MS_Big5 = 13,
1286 CMAP_MS_PRC = 14,
1287 CMAP_MS_Wansung = 15,
1288 CMAP_MS_Johab = 16
1289 };
1290
1291 #define MISSING_GLYPH_INDEX 0
1292
1293 /*
1294 * getGlyph[0246]() functions and friends are implemented by:
1295 * @author Manpreet Singh
1296 * getGlyph12() function and friends by:
1297 * @author HDU
1298 */
getGlyph0(const sal_uInt8 * cmap,sal_uInt32 c)1299 static sal_uInt32 getGlyph0(const sal_uInt8* cmap, sal_uInt32 c) {
1300 if (c <= 255) {
1301 return *(cmap + 6 + c);
1302 } else {
1303 return MISSING_GLYPH_INDEX;
1304 }
1305 }
1306
1307 typedef struct _subHeader2 {
1308 sal_uInt16 firstCode;
1309 sal_uInt16 entryCount;
1310 sal_uInt16 idDelta;
1311 sal_uInt16 idRangeOffset;
1312 } subHeader2;
1313
getGlyph2(const sal_uInt8 * cmap,sal_uInt32 c)1314 static sal_uInt32 getGlyph2(const sal_uInt8 *cmap, sal_uInt32 c) {
1315 sal_uInt16 *CMAP2 = (sal_uInt16 *) cmap;
1316 sal_uInt8 theHighByte;
1317
1318 sal_uInt8 theLowByte;
1319 subHeader2* subHeader2s;
1320 sal_uInt16* subHeader2Keys;
1321 sal_uInt16 firstCode;
1322 int k;
1323 sal_uInt32 ToReturn;
1324
1325 theHighByte = (sal_uInt8)((c >> 8) & 0x00ff);
1326 theLowByte = (sal_uInt8)(c & 0x00ff);
1327 subHeader2Keys = CMAP2 + 3;
1328 subHeader2s = (subHeader2 *)(subHeader2Keys + 256);
1329 k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8;
1330
1331 if(k == 0) {
1332 firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
1333 if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
1334 return *((&(subHeader2s[0].idRangeOffset))
1335 + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */
1336 + theLowByte /* + to_look */
1337 - Int16FromMOTA(subHeader2s[0].firstCode)
1338 );
1339 } else {
1340 return MISSING_GLYPH_INDEX;
1341 }
1342 } else if (k > 0) {
1343 firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
1344 if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
1345 ToReturn = *((&(subHeader2s[k].idRangeOffset))
1346 + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2)
1347 + theLowByte - firstCode);
1348 if(ToReturn == 0) {
1349 return MISSING_GLYPH_INDEX;
1350 } else {
1351 ToReturn += Int16FromMOTA(subHeader2s[k].idDelta);
1352 return (ToReturn & 0xFFFF);
1353 }
1354 } else {
1355 return MISSING_GLYPH_INDEX;
1356 }
1357 } else {
1358 return MISSING_GLYPH_INDEX;
1359 }
1360 }
1361
getGlyph6(const sal_uInt8 * cmap,sal_uInt32 c)1362 static sal_uInt32 getGlyph6(const sal_uInt8 *cmap, sal_uInt32 c) {
1363 sal_uInt16 firstCode, lastCode, count;
1364 sal_uInt16 *CMAP6 = (sal_uInt16 *) cmap;
1365
1366 firstCode = Int16FromMOTA(*(CMAP6 + 3));
1367 count = Int16FromMOTA(*(CMAP6 + 4));
1368 lastCode = firstCode + count - 1;
1369 if (c < firstCode || c > lastCode) {
1370 return MISSING_GLYPH_INDEX;
1371 } else {
1372 return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode));
1373 }
1374 }
1375
GEbinsearch(sal_uInt16 * ar,sal_uInt16 length,sal_uInt16 toSearch)1376 static sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch) {
1377 signed int low, mid, high, lastfound = 0xffff;
1378 sal_uInt16 res;
1379 if(length == (sal_uInt16)0 || length == (sal_uInt16)0xFFFF) {
1380 return (sal_uInt16)0xFFFF;
1381 }
1382 low = 0;
1383 high = length - 1;
1384 while(high >= low) {
1385 mid = (high + low)/2;
1386 res = Int16FromMOTA(*(ar+mid));
1387 if(res >= toSearch) {
1388 lastfound = mid;
1389 high = --mid;
1390 } else {
1391 low = ++mid;
1392 }
1393 }
1394 return (sal_uInt16)lastfound;
1395 }
1396
1397
getGlyph4(const sal_uInt8 * cmap,sal_uInt32 c)1398 static sal_uInt32 getGlyph4(const sal_uInt8 *cmap, sal_uInt32 c) {
1399 sal_uInt16 i;
1400 int ToReturn;
1401 sal_uInt16 segCount;
1402 sal_uInt16 * startCode;
1403 sal_uInt16 * endCode;
1404 sal_uInt16 * idDelta;
1405 /* sal_uInt16 * glyphIdArray; */
1406 sal_uInt16 * idRangeOffset;
1407 sal_uInt16 * glyphIndexArray;
1408 sal_uInt16 *CMAP4 = (sal_uInt16 *) cmap;
1409 /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */
1410
1411 segCount = Int16FromMOTA(*(CMAP4 + 3))/2;
1412 endCode = CMAP4 + 7;
1413 i = GEbinsearch(endCode, segCount, (sal_uInt16)c);
1414
1415 if (i == (sal_uInt16) 0xFFFF) {
1416 return MISSING_GLYPH_INDEX;
1417 }
1418 startCode = endCode + segCount + 1;
1419
1420 if(Int16FromMOTA(startCode[i]) > c) {
1421 return MISSING_GLYPH_INDEX;
1422 }
1423 idDelta = startCode + segCount;
1424 idRangeOffset = idDelta + segCount;
1425 glyphIndexArray = idRangeOffset + segCount;
1426
1427 if(Int16FromMOTA(idRangeOffset[i]) != 0) {
1428 c = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i])))));
1429 }
1430
1431 ToReturn = (Int16FromMOTA(idDelta[i]) + c) & 0xFFFF;
1432 return ToReturn;
1433 }
1434
getGlyph12(const sal_uInt8 * pCmap,sal_uInt32 cChar)1435 static sal_uInt32 getGlyph12(const sal_uInt8 *pCmap, sal_uInt32 cChar) {
1436 const sal_uInt32* pCMAP12 = (const sal_uInt32*)pCmap;
1437 int nLength = Int32FromMOTA( pCMAP12[1] );
1438 int nGroups = Int32FromMOTA( pCMAP12[3] );
1439 int nLower = 0;
1440 int nUpper = nGroups;
1441
1442 if( nUpper > (nLength-16)/12 )
1443 nUpper = (nLength-16)/12;
1444
1445 /* binary search in "segmented coverage" subtable */
1446 while( nLower < nUpper ) {
1447 int nIndex = (nLower + nUpper) / 2;
1448 const sal_uInt32* pEntry = &pCMAP12[ 4 + 3*nIndex ];
1449 sal_uInt32 cStart = Int32FromMOTA( pEntry[0] );
1450 sal_uInt32 cLast = Int32FromMOTA( pEntry[1] );
1451 if( cChar < cStart )
1452 nUpper = nIndex;
1453 else if( cChar > cLast )
1454 nLower = nIndex + 1;
1455 else { /* found matching entry! */
1456 sal_uInt32 nGlyph = Int32FromMOTA( pEntry[2] );
1457 nGlyph += cChar - cStart;
1458 return nGlyph;
1459 }
1460 }
1461
1462 return MISSING_GLYPH_INDEX;
1463 }
1464
1465
1466 /* Whether the arrays the format decoders above read lie inside cmap.
1467 *
1468 * nAvail is what is left of the cmap table from the start of this subtable.
1469 */
cmapSubtableFits(const sal_uInt8 * pSub,sal_uInt32 nAvail)1470 static bool cmapSubtableFits(const sal_uInt8* pSub, sal_uInt32 nAvail)
1471 {
1472 if (nAvail < 4)
1473 return false;
1474
1475 switch (GetUInt16(pSub, 0, 1)) {
1476 case 0:
1477 /* byte encoding: a 256 entry glyph array at offset 6 */
1478 return nAvail >= 6 + 256;
1479
1480 case 2: {
1481 /* high-byte mapping: 256 sub-header keys at offset 6, the
1482 * sub-headers those keys address from offset 518, and for each
1483 * sub-header a glyph array reached through its own idRangeOffset. */
1484 if (nAvail < 518)
1485 return false;
1486 for (sal_uInt32 i = 0; i < 256; ++i) {
1487 const sal_uInt32 k = GetUInt16(pSub, 6 + 2 * i, 1) / 8;
1488 const sal_uInt32 nHdr = 518 + 8 * k;
1489 if (!fitsInTable(nHdr, 8, nAvail))
1490 return false;
1491 const sal_uInt32 nCount = GetUInt16(pSub, nHdr + 2, 1);
1492 const sal_uInt32 nRangeOff = GetUInt16(pSub, nHdr + 6, 1);
1493 if (!nCount)
1494 continue;
1495 /* the last entry this sub-header lets the decoder reach */
1496 const sal_uInt32 nLast = nHdr + 6 + (nRangeOff / 2) * 2 + (nCount - 1) * 2;
1497 if (!fitsInTable(nLast, 2, nAvail))
1498 return false;
1499 }
1500 return true;
1501 }
1502
1503 case 4: {
1504 /* segment mapping: end codes at 14, then start codes, deltas and
1505 * range offsets, one array of segCount each. */
1506 const sal_uInt32 nSegCount = GetUInt16(pSub, 6, 1) / 2;
1507 if (!fitsInTable(16, 8 * nSegCount, nAvail))
1508 return false;
1509 for (sal_uInt32 i = 0; i < nSegCount; ++i) {
1510 const sal_uInt32 nRangeOff = GetUInt16(pSub, 16 + 6 * nSegCount + 2 * i, 1);
1511 if (!nRangeOff)
1512 continue; /* answered from idDelta alone */
1513 const sal_uInt32 nEnd = GetUInt16(pSub, 14 + 2 * i, 1);
1514 const sal_uInt32 nStart = GetUInt16(pSub, 16 + 2 * nSegCount + 2 * i, 1);
1515 if (nEnd < nStart)
1516 continue; /* no character falls in this segment */
1517 /* the furthest the indirection reaches for this segment */
1518 const sal_uInt32 nLast = 16 + 6 * nSegCount + 2 * i
1519 + (nRangeOff / 2) * 2 + (nEnd - nStart) * 2;
1520 if (!fitsInTable(nLast, 2, nAvail))
1521 return false;
1522 }
1523 return true;
1524 }
1525
1526 case 6: {
1527 /* trimmed table: entryCount glyphs at offset 10 */
1528 if (nAvail < 10)
1529 return false;
1530 return fitsInTable(10, 2 * (sal_uInt32)GetUInt16(pSub, 8, 1), nAvail);
1531 }
1532
1533 case 12:
1534 /* segmented coverage: the subtable length has to lie inside cmap */
1535 return (nAvail >= 16) && (GetUInt32(pSub, 4, 1) <= nAvail);
1536
1537 default:
1538 return false;
1539 }
1540 }
1541
FindCmap(TrueTypeFont * ttf)1542 static void FindCmap(TrueTypeFont *ttf)
1543 {
1544 const sal_uInt8* table = getTable(ttf, O_cmap);
1545 sal_uInt32 table_size = getTableSize(ttf, O_cmap);
1546 sal_uInt16 ncmaps = GetUInt16(table, 2, 1);
1547 unsigned int i;
1548 sal_uInt32 AppleUni = 0; // Apple Unicode
1549 sal_uInt32 ThreeZero = 0; /* MS Symbol */
1550 sal_uInt32 ThreeOne = 0; /* MS UCS-2 */
1551 sal_uInt32 ThreeTwo = 0; /* MS ShiftJIS */
1552 sal_uInt32 ThreeThree = 0; /* MS Big5 */
1553 sal_uInt32 ThreeFour = 0; /* MS PRC */
1554 sal_uInt32 ThreeFive = 0; /* MS Wansung */
1555 sal_uInt32 ThreeSix = 0; /* MS Johab */
1556
1557 for (i = 0; i < ncmaps; i++) {
1558 sal_uInt32 offset;
1559 sal_uInt16 pID, eID;
1560
1561 /* sanity check, cmap entry must lie within table */
1562 if( !fitsInTable(4 + i * 8, 8, table_size) )
1563 break;
1564
1565 pID = GetUInt16(table, 4 + i * 8, 1);
1566 eID = GetUInt16(table, 6 + i * 8, 1);
1567 offset = GetUInt32(table, 8 + i * 8, 1);
1568
1569 /* sanity check, subtable format and length must lie within cmap */
1570 if( !fitsInTable(offset, 4, table_size) )
1571 continue;
1572
1573 /* Unicode tables in Apple fonts */
1574 if (pID == 0) {
1575 AppleUni = offset;
1576 }
1577
1578 if (pID == 3) {
1579 switch (eID) {
1580 case 0: ThreeZero = offset; break;
1581 case 10: // UCS-4
1582 case 1: ThreeOne = offset; break;
1583 case 2: ThreeTwo = offset; break;
1584 case 3: ThreeThree = offset; break;
1585 case 4: ThreeFour = offset; break;
1586 case 5: ThreeFive = offset; break;
1587 case 6: ThreeSix = offset; break;
1588 }
1589 }
1590 }
1591
1592 // fall back to AppleUnicode if there are no ThreeOne/Threezero tables
1593 if( AppleUni && !ThreeZero && !ThreeOne)
1594 ThreeOne = AppleUni;
1595
1596 if (ThreeOne) {
1597 ttf->cmapType = CMAP_MS_Unicode;
1598 ttf->cmap = table + ThreeOne;
1599 } else if (ThreeTwo) {
1600 ttf->cmapType = CMAP_MS_ShiftJIS;
1601 ttf->cmap = table + ThreeTwo;
1602 } else if (ThreeThree) {
1603 ttf->cmapType = CMAP_MS_Big5;
1604 ttf->cmap = table + ThreeThree;
1605 } else if (ThreeFour) {
1606 ttf->cmapType = CMAP_MS_PRC;
1607 ttf->cmap = table + ThreeFour;
1608 } else if (ThreeFive) {
1609 ttf->cmapType = CMAP_MS_Wansung;
1610 ttf->cmap = table + ThreeFive;
1611 } else if (ThreeSix) {
1612 ttf->cmapType = CMAP_MS_Johab;
1613 ttf->cmap = table + ThreeSix;
1614 } else if (ThreeZero) {
1615 ttf->cmapType = CMAP_MS_Symbol;
1616 ttf->cmap = table + ThreeZero;
1617 } else {
1618 ttf->cmapType = CMAP_NOT_USABLE;
1619 ttf->cmap = 0;
1620 }
1621
1622 if (ttf->cmapType != CMAP_NOT_USABLE
1623 && !cmapSubtableFits(ttf->cmap, table_size - (sal_uInt32)(ttf->cmap - table))) {
1624 ttf->cmapType = CMAP_NOT_USABLE;
1625 ttf->cmap = 0;
1626 }
1627
1628 if (ttf->cmapType != CMAP_NOT_USABLE) {
1629 switch (GetUInt16(ttf->cmap, 0, 1)) {
1630 case 0: ttf->mapper = getGlyph0; break;
1631 case 2: ttf->mapper = getGlyph2; break;
1632 case 4: ttf->mapper = getGlyph4; break;
1633 case 6: ttf->mapper = getGlyph6; break;
1634 case 12: ttf->mapper= getGlyph12; break;
1635 default:
1636 #if OSL_DEBUG_LEVEL > 1
1637 /*- if the cmap table is really broken */
1638 printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1));
1639 #endif
1640 ttf->cmapType = CMAP_NOT_USABLE;
1641 ttf->cmap = 0;
1642 ttf->mapper = 0;
1643 }
1644 }
1645 }
1646
GetKern(TrueTypeFont * ttf)1647 static void GetKern(TrueTypeFont *ttf)
1648 {
1649 const sal_uInt8* table = getTable(ttf, O_kern);
1650 const sal_uInt8 *ptr;
1651
1652 if( !table )
1653 goto badtable;
1654
1655 if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with sal_uInt16 version and nTables fields */
1656 ttf->nkern = GetUInt16(table, 2, 1);
1657 ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8 *));
1658 assert(ttf->kerntables != 0);
1659 memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *));
1660 ttf->kerntype = KT_MICROSOFT;
1661 ptr = table + 4;
1662 for( unsigned i = 0; i < ttf->nkern; ++i) {
1663 ttf->kerntables[i] = ptr;
1664 ptr += GetUInt16(ptr, 2, 1);
1665 /* sanity check */
1666 if( ptr > ttf->ptr+ttf->fsize )
1667 {
1668 free( ttf->kerntables );
1669 goto badtable;
1670 }
1671 }
1672 return;
1673 }
1674
1675 if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */
1676 ttf->nkern = GetUInt32(table, 4, 1);
1677 ttf->kerntables = (const sal_uInt8**)calloc(ttf->nkern, sizeof(sal_uInt8*));
1678 assert(ttf->kerntables != 0);
1679 memset(ttf->kerntables, 0, ttf->nkern * sizeof(sal_uInt8 *));
1680 ttf->kerntype = KT_APPLE_NEW;
1681 ptr = table + 8;
1682 for( unsigned i = 0; i < ttf->nkern; ++i) {
1683 ttf->kerntables[i] = ptr;
1684 ptr += GetUInt32(ptr, 0, 1);
1685 /* sanity check; there are some fonts that are broken in this regard */
1686 if( ptr > ttf->ptr+ttf->fsize )
1687 {
1688 free( ttf->kerntables );
1689 goto badtable;
1690 }
1691 }
1692 return;
1693 }
1694
1695 badtable:
1696 ttf->kerntype = KT_NONE;
1697 ttf->kerntables = 0;
1698
1699 return;
1700 }
1701
1702 #ifdef TEST5
1703 /* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and
1704 * that x and y elements of the kern array are initialized to zeros
1705 */
KernGlyphsPrim1(TrueTypeFont * ttf,sal_uInt16 * glyphs,int nglyphs,int wmode,KernData * kern)1706 static void KernGlyphsPrim1(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern)
1707 {
1708 (void)ttf; /* avoid warning */
1709 (void)glyphs; /* avoid warning */
1710 (void)nglyphs; /* avoid warning */
1711 (void)wmode; /* avoid warning */
1712 (void)nglyphs; /* avoid warning */
1713 (void)kern; /* avoid warning */
1714 fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n");
1715 }
1716
KernGlyphsPrim2(TrueTypeFont * ttf,sal_uInt16 * glyphs,int nglyphs,int wmode,KernData * kern)1717 static void KernGlyphsPrim2(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern)
1718 {
1719 sal_uInt32 i, j;
1720 sal_uInt32 gpair;
1721
1722 if( ! nglyphs )
1723 return;
1724
1725 for (i = 0; i < (sal_uInt32)nglyphs - 1; i++) {
1726 gpair = (glyphs[i] << 16) | glyphs[i+1];
1727 #ifdef DEBUG2
1728 /* All fonts with MS kern table that I've seen so far contain just one kern subtable.
1729 * MS kern documentation is very poor and I doubt that font developers will be using
1730 * several subtables. I expect them to be using OpenType tables instead.
1731 * According to MS documentation, format 2 subtables are not supported by Windows and OS/2.
1732 */
1733 if (ttf->nkern > 1) {
1734 fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern);
1735 }
1736 #endif
1737 for (j = 0; j < ttf->nkern; j++) {
1738 sal_uInt16 coverage = GetUInt16(ttf->kerntables[j], 4, 1);
1739 sal_uInt8 *ptr;
1740 int npairs;
1741 sal_uInt32 t;
1742 int l, r, k;
1743
1744 if (! ((coverage & 1) ^ wmode)) continue;
1745 if ((coverage & 0xFFFE) != 0) {
1746 #ifdef DEBUG2
1747 fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage);
1748 #endif
1749 continue;
1750 }
1751 ptr = ttf->kerntables[j];
1752 npairs = GetUInt16(ptr, 6, 1);
1753 ptr += 14;
1754 l = 0;
1755 r = npairs;
1756 do {
1757 k = (l + r) >> 1;
1758 t = GetUInt32(ptr, k * 6, 1);
1759 if (gpair >= t) l = k + 1;
1760 if (gpair <= t) r = k - 1;
1761 } while (l <= r);
1762 if (l - r == 2) {
1763 if (!wmode) {
1764 kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1));
1765 } else {
1766 kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1));
1767 }
1768 /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */
1769 }
1770 }
1771 }
1772 }
1773 #endif
1774
1775 /*- Public functions */ /*FOLD00*/
1776
CountTTCFonts(const char * fname)1777 int CountTTCFonts(const char* fname)
1778 {
1779 int nFonts = 0;
1780 sal_uInt8 buffer[12];
1781 FILE* fd = fopen(fname, "rb");
1782 if( fd ) {
1783 if (fread(buffer, 1, 12, fd) == 12) {
1784 if(GetUInt32(buffer, 0, 1) == T_ttcf )
1785 nFonts = GetUInt32(buffer, 8, 1);
1786 }
1787 fclose(fd);
1788 }
1789 return nFonts;
1790 }
1791
allocTrueTypeFont(TrueTypeFont ** ttf)1792 static void allocTrueTypeFont( TrueTypeFont** ttf )
1793 {
1794 *ttf = (TrueTypeFont*)calloc(1,sizeof(TrueTypeFont));
1795 if( *ttf != NULL )
1796 {
1797 (*ttf)->tag = 0;
1798 (*ttf)->fname = 0;
1799 (*ttf)->fsize = -1;
1800 (*ttf)->ptr = 0;
1801 (*ttf)->nglyphs = 0xFFFFFFFF;
1802 (*ttf)->pGSubstitution = 0;
1803 }
1804 }
1805
1806 /* forward declaration for the two entry points to use*/
1807 static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t );
1808
1809 #if !defined(WIN32) && !defined(OS2)
OpenTTFontFile(const char * fname,sal_uInt32 facenum,TrueTypeFont ** ttf)1810 int OpenTTFontFile( const char* fname, sal_uInt32 facenum, TrueTypeFont** ttf )
1811 {
1812 int ret, fd = -1;
1813 struct stat st;
1814
1815 if (!fname || !*fname) return SF_BADFILE;
1816
1817 allocTrueTypeFont( ttf );
1818 if( ! *ttf )
1819 return SF_MEMORY;
1820
1821 (*ttf)->fname = strdup(fname);
1822 if( ! (*ttf)->fname )
1823 {
1824 ret = SF_MEMORY;
1825 goto cleanup;
1826 }
1827
1828 fd = open(fname, O_RDONLY);
1829
1830 if (fd == -1) {
1831 ret = SF_BADFILE;
1832 goto cleanup;
1833 }
1834
1835 if (fstat(fd, &st) == -1) {
1836 ret = SF_FILEIO;
1837 goto cleanup;
1838 }
1839
1840 (*ttf)->fsize = st.st_size;
1841
1842 /* On Mac OS, most likely will happen if a Mac user renames a font file
1843 * to be .ttf when its really a Mac resource-based font.
1844 * Size will be 0, but fonts smaller than 4 bytes would be broken anyway.
1845 */
1846 if ((*ttf)->fsize == 0) {
1847 ret = SF_BADFILE;
1848 goto cleanup;
1849 }
1850
1851 if (((*ttf)->ptr = (sal_uInt8 *) mmap(0, (*ttf)->fsize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
1852 ret = SF_MEMORY;
1853 goto cleanup;
1854 }
1855 close(fd);
1856
1857 return doOpenTTFont( facenum, *ttf );
1858
1859 cleanup:
1860 if (fd != -1) close(fd);
1861 /*- t and t->fname have been allocated! */
1862 free((*ttf)->fname);
1863 free(*ttf);
1864 *ttf = NULL;
1865 return ret;
1866 }
1867 #endif
1868
OpenTTFontBuffer(void * pBuffer,sal_uInt32 nLen,sal_uInt32 facenum,TrueTypeFont ** ttf)1869 int OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf)
1870 {
1871 allocTrueTypeFont( ttf );
1872 if( *ttf == NULL )
1873 return SF_MEMORY;
1874
1875 (*ttf)->fname = NULL;
1876 (*ttf)->fsize = nLen;
1877 (*ttf)->ptr = (sal_uInt8*)pBuffer;
1878
1879 return doOpenTTFont( facenum, *ttf );
1880 }
1881
doOpenTTFont(sal_uInt32 facenum,TrueTypeFont * t)1882 static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t )
1883 {
1884 int i;
1885 sal_uInt32 length, tag;
1886 sal_uInt32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */
1887 int indexfmt, k;
1888
1889 /* The table directory header and the collection header are twelve bytes. */
1890 if (t->fsize < 12) {
1891 CloseTTFont(t);
1892 return SF_TTFORMAT;
1893 }
1894 const sal_uInt32 nFileSize = (sal_uInt32)t->fsize;
1895
1896 sal_uInt32 version = GetInt32(t->ptr, 0, 1);
1897
1898 if ((version == 0x00010000) || (version == T_true)) {
1899 tdoffset = 0;
1900 } else if (version == T_otto) { /* PS-OpenType font */
1901 tdoffset = 0;
1902 } else if (version == T_ttcf) { /* TrueType collection */
1903 if (GetUInt32(t->ptr, 4, 1) == 0x00000000) {
1904 CloseTTFont(t);
1905 return SF_TTFORMAT;
1906 }
1907 if (facenum >= GetUInt32(t->ptr, 8, 1)) {
1908 CloseTTFont(t);
1909 return SF_FONTNO;
1910 }
1911 if ((sal_uInt64)12 + 4 * (sal_uInt64)facenum + 4 > (sal_uInt64)nFileSize) {
1912 CloseTTFont(t);
1913 return SF_TTFORMAT;
1914 }
1915 tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1);
1916 } else {
1917 CloseTTFont(t);
1918 return SF_TTFORMAT;
1919 }
1920
1921 #ifdef DEBUG2
1922 fprintf(stderr, "tdoffset: %d\n", tdoffset);
1923 #endif
1924
1925 /* magic number */
1926 t->tag = TTFontClassTag;
1927
1928 if (!fitsInTable(tdoffset, 12, nFileSize)) {
1929 CloseTTFont(t);
1930 return SF_TTFORMAT;
1931 }
1932
1933 t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1);
1934 if( t->ntables >= 128 )
1935 return SF_TTFORMAT;
1936
1937 /* sixteen bytes per table directory entry */
1938 if (!fitsInTable(tdoffset + 12, 16 * t->ntables, nFileSize)) {
1939 CloseTTFont(t);
1940 return SF_TTFORMAT;
1941 }
1942
1943 t->tables = (const sal_uInt8**)calloc(NUM_TAGS, sizeof(sal_uInt8*));
1944 assert(t->tables != 0);
1945 t->tlens = (sal_uInt32*)calloc(NUM_TAGS, sizeof(sal_uInt32));
1946 assert(t->tlens != 0);
1947
1948 memset(t->tables, 0, NUM_TAGS * sizeof(void *));
1949 memset(t->tlens, 0, NUM_TAGS * sizeof(sal_uInt32));
1950
1951 /* parse the tables */
1952 for (i=0; i<(int)t->ntables; i++) {
1953 int nIndex;
1954 tag = GetUInt32(t->ptr + tdoffset + 12, 16 * i, 1);
1955 switch( tag ) {
1956 case T_maxp: nIndex = O_maxp; break;
1957 case T_glyf: nIndex = O_glyf; break;
1958 case T_head: nIndex = O_head; break;
1959 case T_loca: nIndex = O_loca; break;
1960 case T_name: nIndex = O_name; break;
1961 case T_hhea: nIndex = O_hhea; break;
1962 case T_hmtx: nIndex = O_hmtx; break;
1963 case T_cmap: nIndex = O_cmap; break;
1964 case T_vhea: nIndex = O_vhea; break;
1965 case T_vmtx: nIndex = O_vmtx; break;
1966 case T_OS2 : nIndex = O_OS2; break;
1967 case T_post: nIndex = O_post; break;
1968 case T_kern: nIndex = O_kern; break;
1969 case T_cvt : nIndex = O_cvt; break;
1970 case T_prep: nIndex = O_prep; break;
1971 case T_fpgm: nIndex = O_fpgm; break;
1972 case T_gsub: nIndex = O_gsub; break;
1973 case T_CFF: nIndex = O_CFF; break;
1974 default: nIndex = -1; break;
1975 }
1976 if( nIndex >= 0 ) {
1977 sal_uInt32 nTableOffset = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1);
1978 length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1);
1979 /* clamp the table to the file */
1980 if( nTableOffset > nFileSize )
1981 continue;
1982 if( length > nFileSize - nTableOffset )
1983 length = nFileSize - nTableOffset;
1984 t->tables[nIndex] = t->ptr + nTableOffset;
1985 t->tlens[nIndex] = length;
1986 }
1987 }
1988
1989 /* Fixup offsets when only a TTC extract was provided */
1990 if( facenum == (sal_uInt32)~0 ) {
1991 sal_uInt8* pHead = (sal_uInt8*)t->tables[O_head];
1992 if( !pHead )
1993 return SF_TTFORMAT;
1994 if( nFileSize < 54 )
1995 return SF_TTFORMAT;
1996 /* limit Head candidate to TTC extract's limits */
1997 if( pHead > t->ptr + (t->fsize - 54) )
1998 pHead = t->ptr + (t->fsize - 54);
1999 /* TODO: find better method than searching head table's magic */
2000 sal_uInt8* p = NULL;
2001 for( p = pHead + 12; p > t->ptr; --p ) {
2002 if( p[0]==0x5F && p[1]==0x0F && p[2]==0x3C && p[3]==0xF5 ) {
2003 int nDelta = (pHead + 12) - p, j;
2004 if( nDelta )
2005 for( j=0; j<NUM_TAGS; ++j )
2006 if( t->tables[j] )
2007 *(char**)&t->tables[j] -= nDelta;
2008 break;
2009 }
2010 }
2011 if( p <= t->ptr )
2012 return SF_TTFORMAT;
2013 }
2014
2015 /* Check the table offsets after TTC correction */
2016 for (i=0; i<NUM_TAGS; i++) {
2017 /* sanity check: table must lay completely within the file
2018 * at this point one could check the checksum of all contained
2019 * tables, but this would be quite time intensive.
2020 * Try to fix tables, so we can cope with minor problems.
2021 */
2022
2023 if( (sal_uInt8*)t->tables[i] < t->ptr )
2024 {
2025 #if OSL_DEBUG_LEVEL > 1
2026 if( t->tables[i] )
2027 fprintf( stderr, "font file %s has bad table offset %d (tagnum=%d)\n", t->fname, (sal_uInt8*)t->tables[i]-t->ptr, i );
2028 #endif
2029 t->tlens[i] = 0;
2030 t->tables[i] = NULL;
2031 }
2032 else if( (sal_uInt8*)t->tables[i] + t->tlens[i] > t->ptr + t->fsize )
2033 {
2034 int nMaxLen = (t->ptr + t->fsize) - (sal_uInt8*)t->tables[i];
2035 if( nMaxLen < 0 )
2036 nMaxLen = 0;
2037 t->tlens[i] = nMaxLen;
2038 #if OSL_DEBUG_LEVEL > 1
2039 fprintf( stderr, "font file %s has too big table (tagnum=%d)\n", t->fname, i );
2040 #endif
2041 }
2042 }
2043
2044 /* At this point TrueTypeFont is constructed, now need to verify the font format
2045 and read the basic font properties */
2046
2047 /* The following tables are absolutely required:
2048 * maxp, head, name, cmap
2049 */
2050
2051 /* Long enough for the fields read below: numGlyphs at maxp 4, unitsPerEm
2052 * at head 18, indexToLocFormat at head 50, the subtable count at cmap 2. */
2053 if( !(getTable(t, O_maxp) && getTableSize(t, O_maxp) >= 6 &&
2054 getTable(t, O_head) && getTableSize(t, O_head) >= 52 &&
2055 getTable(t, O_name) &&
2056 getTable(t, O_cmap) && getTableSize(t, O_cmap) >= 4) ) {
2057 CloseTTFont(t);
2058 return SF_TTFORMAT;
2059 }
2060
2061 const sal_uInt8* table = getTable(t, O_maxp);
2062 t->nglyphs = GetUInt16(table, 4, 1);
2063
2064 table = getTable(t, O_head);
2065 t->unitsPerEm = GetUInt16(table, 18, 1);
2066 indexfmt = GetInt16(table, 50, 1);
2067
2068 if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) {
2069 CloseTTFont(t);
2070 return SF_TTFORMAT;
2071 }
2072
2073 if( getTable(t, O_glyf) && getTable(t, O_loca) ) { /* TTF or TTF-OpenType */
2074 k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1;
2075 /* loca has to hold at least two offsets */
2076 if( k < 0 ) {
2077 CloseTTFont(t);
2078 return SF_TTFORMAT;
2079 }
2080 if( k < (int)t->nglyphs ) /* Hack for broken Chinese fonts */
2081 t->nglyphs = k;
2082
2083 table = getTable(t, O_loca);
2084 t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32));
2085 assert(t->goffsets != 0);
2086
2087 for( i = 0; i <= (int)t->nglyphs; ++i )
2088 t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : (sal_uInt32)GetUInt16(table, i << 1, 1) << 1;
2089
2090 /* Stop at the first offset outside glyf or below the one before it;
2091 * the glyphs ahead of it stay usable. */
2092 const sal_uInt32 nGlyfLen = getTableSize(t, O_glyf);
2093 for( i = 0; i <= (int)t->nglyphs; ++i ) {
2094 if( t->goffsets[i] > nGlyfLen
2095 || (i > 0 && t->goffsets[i] < t->goffsets[i-1]) ) {
2096 t->nglyphs = (i > 0) ? (sal_uInt32)(i - 1) : 0;
2097 break;
2098 }
2099 }
2100 } else if( getTable(t, O_CFF) ) { /* PS-OpenType */
2101 t->goffsets = (sal_uInt32 *) calloc(1+t->nglyphs, sizeof(sal_uInt32));
2102 /* TODO: implement to get subsetting */
2103 assert(t->goffsets != 0);
2104 } else {
2105 CloseTTFont(t);
2106 return SF_TTFORMAT;
2107 }
2108
2109 /* numberOfHMetrics is at offset 34 of a 36-byte table, and hmtx has four
2110 * bytes per long metric. Same for the vertical pair. */
2111 table = getTable(t, O_hhea);
2112 t->numberOfHMetrics = (table != 0 && getTableSize(t, O_hhea) >= 36) ? GetUInt16(table, 34, 1) : 0;
2113 if( t->numberOfHMetrics > getTableSize(t, O_hmtx) / 4 )
2114 t->numberOfHMetrics = getTableSize(t, O_hmtx) / 4;
2115
2116 table = getTable(t, O_vhea);
2117 t->numOfLongVerMetrics = (table != 0 && getTableSize(t, O_vhea) >= 36) ? GetUInt16(table, 34, 1) : 0;
2118 if( t->numOfLongVerMetrics > getTableSize(t, O_vmtx) / 4 )
2119 t->numOfLongVerMetrics = getTableSize(t, O_vmtx) / 4;
2120
2121 GetNames(t);
2122 FindCmap(t);
2123 GetKern(t);
2124 ReadGSUB( t, 0, 0 );
2125
2126 return SF_OK;
2127 }
2128
CloseTTFont(TrueTypeFont * ttf)2129 void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/
2130 {
2131 if (ttf->tag != TTFontClassTag) return;
2132
2133 #if !defined(WIN32) && !defined(OS2)
2134 if( ttf->fname )
2135 munmap((char *) ttf->ptr, ttf->fsize);
2136 #endif
2137 free(ttf->fname);
2138 free(ttf->goffsets);
2139 free(ttf->psname);
2140 free(ttf->family);
2141 if( ttf->ufamily )
2142 free( ttf->ufamily );
2143 free(ttf->subfamily);
2144 if( ttf->usubfamily )
2145 free( ttf->usubfamily );
2146 free(ttf->tables);
2147 free(ttf->tlens);
2148 free(ttf->kerntables);
2149
2150 ReleaseGSUB(ttf);
2151
2152 free(ttf);
2153 return;
2154 }
2155
GetTTGlyphPoints(TrueTypeFont * ttf,sal_uInt32 glyphID,ControlPoint ** pointArray)2156 int GetTTGlyphPoints(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint **pointArray)
2157 {
2158 return GetTTGlyphOutline(ttf, glyphID, pointArray, 0, 0);
2159 }
2160
GetTTGlyphComponents(TrueTypeFont * ttf,sal_uInt32 glyphID,std::vector<sal_uInt32> & glyphlist)2161 int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal_uInt32 >& glyphlist)
2162 {
2163 int n = 1;
2164
2165 if( glyphID >= ttf->nglyphs )
2166 return 0;
2167
2168 const sal_uInt8* glyf = getTable(ttf, O_glyf);
2169 const sal_uInt8* ptr = glyf + ttf->goffsets[glyphID];
2170
2171 glyphlist.push_back( glyphID );
2172
2173 if (GetInt16(ptr, 0, 1) == -1) {
2174 sal_uInt16 flags, index;
2175 ptr += 10;
2176 do {
2177 flags = GetUInt16(ptr, 0, 1);
2178 index = GetUInt16(ptr, 2, 1);
2179
2180 ptr += 4;
2181 n += GetTTGlyphComponents(ttf, index, glyphlist);
2182
2183 if (flags & ARG_1_AND_2_ARE_WORDS) {
2184 ptr += 4;
2185 } else {
2186 ptr += 2;
2187 }
2188
2189 if (flags & WE_HAVE_A_SCALE) {
2190 ptr += 2;
2191 } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
2192 ptr += 4;
2193 } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
2194 ptr += 8;
2195 }
2196 } while (flags & MORE_COMPONENTS);
2197 }
2198
2199 return n;
2200 }
2201
2202 #ifndef NO_TYPE3
CreateT3FromTTGlyphs(TrueTypeFont * ttf,FILE * outf,const char * fname,sal_uInt16 * glyphArray,sal_uInt8 * encoding,int nGlyphs,int wmode)2203 int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/
2204 sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs,
2205 int wmode)
2206 {
2207 ControlPoint *pa;
2208 PSPathElement *path;
2209 int i, j, r, n;
2210 const sal_uInt8* table = getTable(ttf, O_head);
2211 TTGlyphMetrics metrics;
2212 int UPEm = ttf->unitsPerEm;
2213
2214 const char * const h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n";
2215 const char * const h02 = "%% Creator: %s %s %s\n";
2216 const char * const h09 = "%% Original font name: %s\n";
2217
2218 const char * const h10 =
2219 "30 dict begin\n"
2220 "/PaintType 0 def\n"
2221 "/FontType 3 def\n"
2222 "/StrokeWidth 0 def\n";
2223
2224 const char * const h11 = "/FontName (%s) cvn def\n";
2225
2226 /*
2227 const char * const h12 = "%/UniqueID %d def\n";
2228 */
2229 const char * const h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n";
2230 const char * const h14 = "/FontBBox [%d %d %d %d] def\n";
2231
2232 const char * const h15=
2233 "/Encoding 256 array def\n"
2234 " 0 1 255 {Encoding exch /.notdef put} for\n";
2235
2236 const char * const h16 = " Encoding %d /glyph%d put\n";
2237 const char * const h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n";
2238
2239 const char * const h30 = "/CharProcs %d dict def\n";
2240 const char * const h31 = " CharProcs begin\n";
2241 const char * const h32 = " /.notdef {} def\n";
2242 const char * const h33 = " /glyph%d {\n";
2243 const char * const h34 = " } bind def\n";
2244 const char * const h35 = " end\n";
2245
2246 const char * const h40 =
2247 "/BuildGlyph {\n"
2248 " exch /CharProcs get exch\n"
2249 " 2 copy known not\n"
2250 " {pop /.notdef} if\n"
2251 " get exec\n"
2252 "} bind def\n"
2253 "/BuildChar {\n"
2254 " 1 index /Encoding get exch get\n"
2255 " 1 index /BuildGlyph get exec\n"
2256 "} bind def\n"
2257 "currentdict end\n";
2258
2259 const char * const h41 = "(%s) cvn exch definefont pop\n";
2260
2261
2262 if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM;
2263 if (!glyphArray) return SF_BADARG;
2264 if (!fname) fname = ttf->psname;
2265
2266 fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1));
2267 fprintf(outf, h02, modname, modver, modextra);
2268 fprintf(outf, h09, ttf->psname);
2269
2270 fprintf(outf, h10);
2271 fprintf(outf, h11, fname);
2272 /* fprintf(outf, h12, 4000000); */
2273
2274 /* XUID generation:
2275 * 103 0 0 C1 C2 C3 C4
2276 * C1 - CRC-32 of the entire source TrueType font
2277 * C2 - number of glyphs in the subset
2278 * C3 - CRC-32 of the glyph array
2279 * C4 - CRC-32 of the encoding array
2280 *
2281 * All CRC-32 numbers are presented as hexadecimal numbers
2282 */
2283
2284 fprintf(outf, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs));
2285 fprintf(outf, h13);
2286 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)));
2287 fprintf(outf, h15);
2288
2289 for (i = 0; i < nGlyphs; i++) {
2290 fprintf(outf, h16, encoding[i], i);
2291 }
2292
2293 fprintf(outf, h30, nGlyphs+1);
2294 fprintf(outf, h31);
2295 fprintf(outf, h32);
2296
2297 for (i = 0; i < nGlyphs; i++) {
2298 fprintf(outf, h33, i);
2299 r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0);
2300
2301 if (r > 0) {
2302 n = BSplineToPSPath(pa, r, &path);
2303 } else {
2304 n = 0; /* glyph might have zero contours but valid metrics ??? */
2305 path = 0;
2306 if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */
2307 continue;
2308 }
2309 }
2310 fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n",
2311 wmode == 0 ? XUnits(UPEm, metrics.aw) : 0,
2312 wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah),
2313 XUnits(UPEm, metrics.xMin),
2314 XUnits(UPEm, metrics.yMin),
2315 XUnits(UPEm, metrics.xMax),
2316 XUnits(UPEm, metrics.yMax));
2317
2318 for (j = 0; j < n; j++)
2319 {
2320 switch (path[j].type)
2321 {
2322 case PS_MOVETO:
2323 fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
2324 break;
2325
2326 case PS_LINETO:
2327 fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
2328 break;
2329
2330 case PS_CURVETO:
2331 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));
2332 break;
2333
2334 case PS_CLOSEPATH:
2335 fprintf(outf, "\tclosepath\n");
2336 break;
2337 case PS_NOOP:
2338 break;
2339 }
2340 }
2341 if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */
2342
2343 fprintf(outf, h34);
2344
2345 free(pa);
2346 free(path);
2347 }
2348 fprintf(outf, h35);
2349
2350 fprintf(outf, h40);
2351 fprintf(outf, h41, fname);
2352
2353 return SF_OK;
2354 }
2355 #endif
2356
2357 #ifndef NO_TTCR
CreateTTFromTTGlyphs(TrueTypeFont * ttf,const char * fname,sal_uInt16 * glyphArray,sal_uInt8 * encoding,int nGlyphs,int nNameRecs,NameRecord * nr,sal_uInt32 flags)2358 int CreateTTFromTTGlyphs(TrueTypeFont *ttf,
2359 const char *fname,
2360 sal_uInt16 *glyphArray,
2361 sal_uInt8 *encoding,
2362 int nGlyphs,
2363 int nNameRecs,
2364 NameRecord *nr,
2365 sal_uInt32 flags)
2366 {
2367 TrueTypeCreator *ttcr;
2368 TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0, *cmap=0, *name=0, *post = 0, *os2 = 0;
2369 int i;
2370 int res;
2371
2372 TrueTypeCreatorNewEmpty(T_true, &ttcr);
2373
2374 /** name **/
2375
2376 if (flags & TTCF_AutoName) {
2377 /* not implemented yet
2378 NameRecord *names;
2379 NameRecord newname;
2380 int n = GetTTNameRecords(ttf, &names);
2381 int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
2382 sal_uInt8 *cp1;
2383 sal_uInt8 suffix[32];
2384 sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2);
2385 sal_uInt32 c2 = crc32(encoding, nGlyphs);
2386 int len;
2387 snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs);
2388
2389 name = TrueTypeTableNew_name(0, 0);
2390 for (i = 0; i < n; i++) {
2391 if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) {
2392
2393 memcpy(newname, names+i, sizeof(NameRecord));
2394 newname.slen = name[i].slen + strlen(suffix);
2395 */
2396 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'};
2397 NameRecord n1 = {1, 0, 0, 6, 14, (sal_uInt8*)"TrueTypeSubset"};
2398 NameRecord n2 = {3, 1, 1033, 6, 28, 0};
2399 n2.sptr = (sal_uInt8 *) ptr;
2400 name = TrueTypeTableNew_name(0, 0);
2401 nameAdd(name, &n1);
2402 nameAdd(name, &n2);
2403 } else {
2404 if (nNameRecs == 0) {
2405 NameRecord *names;
2406 int n = GetTTNameRecords(ttf, &names);
2407 name = TrueTypeTableNew_name(n, names);
2408 DisposeNameRecords(names, n);
2409 } else {
2410 name = TrueTypeTableNew_name(nNameRecs, nr);
2411 }
2412 }
2413
2414 /** maxp **/
2415 maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
2416
2417 /** hhea **/
2418 const sal_uInt8* p = getTable(ttf, O_hhea);
2419 if (p) {
2420 hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
2421 } else {
2422 hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2423 }
2424
2425 /** head **/
2426
2427 p = getTable(ttf, O_head);
2428 assert(p != 0);
2429 head = TrueTypeTableNew_head(GetUInt32(p, 4, 1),
2430 GetUInt16(p, 16, 1),
2431 GetUInt16(p, 18, 1),
2432 p+20,
2433 GetUInt16(p, 44, 1),
2434 GetUInt16(p, 46, 1),
2435 GetInt16(p, 48, 1));
2436
2437
2438 /** glyf **/
2439
2440 glyf = TrueTypeTableNew_glyf();
2441 sal_uInt32* gID = (sal_uInt32*)scalloc(nGlyphs, sizeof(sal_uInt32));
2442
2443 for (i = 0; i < nGlyphs; i++) {
2444 gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
2445 }
2446
2447 /** cmap **/
2448 cmap = TrueTypeTableNew_cmap();
2449
2450 for (i=0; i < nGlyphs; i++) {
2451 cmapAdd(cmap, 0x010000, encoding[i], gID[i]);
2452 }
2453
2454 /** cvt **/
2455 if ((p = getTable(ttf, O_cvt)) != 0) {
2456 cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
2457 }
2458
2459 /** prep **/
2460 if ((p = getTable(ttf, O_prep)) != 0) {
2461 prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
2462 }
2463
2464 /** fpgm **/
2465 if ((p = getTable(ttf, O_fpgm)) != 0) {
2466 fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
2467 }
2468
2469 /** post **/
2470 if ((p = getTable(ttf, O_post)) != 0) {
2471 post = TrueTypeTableNew_post(0x00030000,
2472 GetUInt32(p, 4, 1),
2473 GetUInt16(p, 8, 1),
2474 GetUInt16(p, 10, 1),
2475 GetUInt16(p, 12, 1));
2476 } else {
2477 post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
2478 }
2479
2480 if (flags & TTCF_IncludeOS2) {
2481 if ((p = getTable(ttf, O_OS2)) != 0) {
2482 os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p);
2483 }
2484 }
2485
2486 AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea);
2487 AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap);
2488 AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm);
2489 AddTable(ttcr, post); AddTable(ttcr, os2);
2490
2491 if ((res = StreamToFile(ttcr, fname)) != SF_OK) {
2492 #if OSL_DEBUG_LEVEL > 1
2493 fprintf(stderr, "StreamToFile: error code: %d.\n", res);
2494 #endif
2495 }
2496
2497 TrueTypeCreatorDispose(ttcr);
2498 free(gID);
2499
2500 return res;
2501 }
2502 #endif
2503
2504
2505 #ifndef NO_TYPE42
GlyphOffsetsNew(sal_uInt8 * sfntP)2506 static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP)
2507 {
2508 GlyphOffsets* res = (GlyphOffsets*)smalloc(sizeof(GlyphOffsets));
2509 sal_uInt8 *loca = NULL;
2510 sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1);
2511 sal_uInt32 locaLen = 0;
2512 sal_Int16 indexToLocFormat = 0;
2513
2514 for (i = 0; i < numTables; i++) {
2515 sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1);
2516 sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1);
2517 sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1);
2518
2519 if (tag == T_loca) {
2520 loca = sfntP + off;
2521 locaLen = len;
2522 } else if (tag == T_head) {
2523 indexToLocFormat = GetInt16(sfntP + off, 50, 1);
2524 }
2525 }
2526
2527 res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2);
2528 assert(res->nGlyphs != 0);
2529 res->offs = (sal_uInt32*)scalloc(res->nGlyphs, sizeof(sal_uInt32));
2530
2531 for (i = 0; i < res->nGlyphs; i++) {
2532 if (indexToLocFormat == 1) {
2533 res->offs[i] = GetUInt32(loca, i * 4, 1);
2534 } else {
2535 res->offs[i] = GetUInt16(loca, i * 2, 1) << 1;
2536 }
2537 }
2538 return res;
2539 }
2540
GlyphOffsetsDispose(GlyphOffsets * _this)2541 static void GlyphOffsetsDispose(GlyphOffsets *_this)
2542 {
2543 if (_this) {
2544 free(_this->offs);
2545 free(_this);
2546 }
2547 }
2548
DumpSfnts(FILE * outf,sal_uInt8 * sfntP)2549 static void DumpSfnts(FILE *outf, sal_uInt8 *sfntP)
2550 {
2551 HexFmt *h = HexFmtNew(outf);
2552 sal_uInt16 i, numTables = GetUInt16(sfntP, 4, 1);
2553 GlyphOffsets *go = GlyphOffsetsNew(sfntP);
2554 sal_uInt8 pad[] = {0,0,0,0}; /* zeros */
2555
2556 assert(numTables <= 9); /* Type42 has 9 required tables */
2557
2558 sal_uInt32* offs = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32));
2559 // sal_uInt32* lens = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32));
2560
2561 fputs("/sfnts [", outf);
2562 HexFmtOpenString(h);
2563 HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */
2564 HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */
2565
2566 for (i=0; i<numTables; i++) {
2567 sal_uInt32 tag = GetUInt32(sfntP + 12, 16 * i, 1);
2568 sal_uInt32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1);
2569 sal_uInt32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1);
2570
2571 if (tag != T_glyf) {
2572 HexFmtBlockWrite(h, sfntP + off, len);
2573 } else {
2574 sal_uInt8 *glyf = sfntP + off;
2575 sal_uInt32 o, l, j;
2576 for (j = 0; j < go->nGlyphs - 1; j++) {
2577 o = go->offs[j];
2578 l = go->offs[j + 1] - o;
2579 HexFmtBlockWrite(h, glyf + o, l);
2580 }
2581 }
2582 HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3);
2583 }
2584 HexFmtCloseString(h);
2585 fputs("] def\n", outf);
2586 GlyphOffsetsDispose(go);
2587 HexFmtDispose(h);
2588 free(offs);
2589 // free(lens);
2590 }
2591
CreateT42FromTTGlyphs(TrueTypeFont * ttf,FILE * outf,const char * psname,sal_uInt16 * glyphArray,sal_uInt8 * encoding,int nGlyphs)2592 int CreateT42FromTTGlyphs(TrueTypeFont *ttf,
2593 FILE *outf,
2594 const char *psname,
2595 sal_uInt16 *glyphArray,
2596 sal_uInt8 *encoding,
2597 int nGlyphs)
2598 {
2599 TrueTypeCreator *ttcr;
2600 TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0;
2601 int i;
2602 int res;
2603
2604 sal_uInt32 ver, rev;
2605
2606 sal_uInt8 *sfntP;
2607 sal_uInt32 sfntLen;
2608 int UPEm = ttf->unitsPerEm;
2609
2610 if (nGlyphs >= 256) return SF_GLYPHNUM;
2611
2612 assert(psname != 0);
2613
2614 TrueTypeCreatorNewEmpty(T_true, &ttcr);
2615
2616 /* head */
2617 const sal_uInt8* p = getTable(ttf, O_head);
2618 const sal_uInt8* headP = p;
2619 assert(p != 0);
2620 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));
2621 ver = GetUInt32(p, 0, 1);
2622 rev = GetUInt32(p, 4, 1);
2623
2624 /** hhea **/
2625 p = getTable(ttf, O_hhea);
2626 if (p) {
2627 hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
2628 } else {
2629 hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2630 }
2631
2632 /** maxp **/
2633 maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
2634
2635 /** cvt **/
2636 if ((p = getTable(ttf, O_cvt)) != 0) {
2637 cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
2638 }
2639
2640 /** prep **/
2641 if ((p = getTable(ttf, O_prep)) != 0) {
2642 prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
2643 }
2644
2645 /** fpgm **/
2646 if ((p = getTable(ttf, O_fpgm)) != 0) {
2647 fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
2648 }
2649
2650 /** glyf **/
2651 glyf = TrueTypeTableNew_glyf();
2652 sal_uInt16* gID = (sal_uInt16*)scalloc(nGlyphs, sizeof(sal_uInt32));
2653
2654 for (i = 0; i < nGlyphs; i++) {
2655 gID[i] = (sal_uInt16)glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
2656 }
2657
2658 AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt);
2659 AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm);
2660
2661 if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) {
2662 TrueTypeCreatorDispose(ttcr);
2663 free(gID);
2664 return res;
2665 }
2666
2667 fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver>>16), (int)(ver & 0xFFFF), (int)(rev>>16), (int)(rev & 0xFFFF));
2668 fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra);
2669 fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname);
2670 fprintf(outf, "%%- Original font name: %s\n", ttf->psname);
2671 fprintf(outf, "%%- Original font family: %s\n", ttf->family);
2672 fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily);
2673 fprintf(outf, "11 dict begin\n");
2674 fprintf(outf, "/FontName (%s) cvn def\n", psname);
2675 fprintf(outf, "/PaintType 0 def\n");
2676 fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n");
2677 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)));
2678 fprintf(outf, "/FontType 42 def\n");
2679 fprintf(outf, "/Encoding 256 array def\n");
2680 fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n");
2681
2682 for (i = 1; i<nGlyphs; i++) {
2683 fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]);
2684 }
2685 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));
2686
2687 DumpSfnts(outf, sfntP);
2688
2689 /* dump charstrings */
2690 fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs);
2691 fprintf(outf, "/.notdef 0 def\n");
2692 for (i = 1; i < (int)glyfCount(glyf); i++) {
2693 fprintf(outf,"/glyph%d %d def\n", i, i);
2694 }
2695 fprintf(outf, "end readonly def\n");
2696
2697 fprintf(outf, "FontName currentdict end definefont pop\n");
2698 TrueTypeCreatorDispose(ttcr);
2699 free(gID);
2700 free(sfntP);
2701 return SF_OK;
2702 }
2703 #endif
2704
2705
2706 #ifndef NO_MAPPERS
MapString(TrueTypeFont * ttf,sal_uInt16 * str,int nchars,sal_uInt16 * glyphArray,int bvertical)2707 int MapString(TrueTypeFont *ttf, sal_uInt16 *str, int nchars, sal_uInt16 *glyphArray, int bvertical)
2708 {
2709 int i;
2710 sal_uInt16 *cp;
2711
2712 if (ttf->cmapType == CMAP_NOT_USABLE ) return -1;
2713 if (!nchars) return 0;
2714
2715 if (glyphArray == 0) {
2716 cp = str;
2717 } else {
2718 cp = glyphArray;
2719 }
2720
2721 switch (ttf->cmapType) {
2722 case CMAP_MS_Symbol:
2723 if( ttf->mapper == getGlyph0 ) {
2724 sal_uInt16 aChar;
2725 for( i = 0; i < nchars; i++ ) {
2726 aChar = str[i];
2727 if( ( aChar & 0xf000 ) == 0xf000 )
2728 aChar &= 0x00ff;
2729 cp[i] = aChar;
2730 }
2731 }
2732 else if( glyphArray )
2733 memcpy(glyphArray, str, nchars * 2);
2734 break;
2735
2736 case CMAP_MS_Unicode:
2737 if (glyphArray != 0) {
2738 memcpy(glyphArray, str, nchars * 2);
2739 }
2740 break;
2741
2742 case CMAP_MS_ShiftJIS: TranslateString12(str, cp, nchars); break;
2743 case CMAP_MS_Big5: TranslateString13(str, cp, nchars); break;
2744 case CMAP_MS_PRC: TranslateString14(str, cp, nchars); break;
2745 case CMAP_MS_Wansung: TranslateString15(str, cp, nchars); break;
2746 case CMAP_MS_Johab: TranslateString16(str, cp, nchars); break;
2747 }
2748
2749 for (i = 0; i < nchars; i++) {
2750 cp[i] = (sal_uInt16)ttf->mapper(ttf->cmap, cp[i]);
2751 if (cp[i]!=0 && bvertical!=0)
2752 cp[i] = (sal_uInt16)UseGSUB(ttf,cp[i],bvertical);
2753 }
2754 return nchars;
2755 }
2756
MapChar(TrueTypeFont * ttf,sal_uInt16 ch,int bvertical)2757 sal_uInt16 MapChar(TrueTypeFont *ttf, sal_uInt16 ch, int bvertical)
2758 {
2759 switch (ttf->cmapType) {
2760 case CMAP_MS_Symbol:
2761
2762 if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 )
2763 ch &= 0x00ff;
2764 return (sal_uInt16)ttf->mapper(ttf->cmap, ch );
2765
2766 case CMAP_MS_Unicode: break;
2767 case CMAP_MS_ShiftJIS: ch = TranslateChar12(ch); break;
2768 case CMAP_MS_Big5: ch = TranslateChar13(ch); break;
2769 case CMAP_MS_PRC: ch = TranslateChar14(ch); break;
2770 case CMAP_MS_Wansung: ch = TranslateChar15(ch); break;
2771 case CMAP_MS_Johab: ch = TranslateChar16(ch); break;
2772 default: return 0;
2773 }
2774 ch = (sal_uInt16)ttf->mapper(ttf->cmap, ch);
2775 if (ch!=0 && bvertical!=0)
2776 ch = (sal_uInt16)UseGSUB(ttf,ch,bvertical);
2777 return ch;
2778 }
2779
DoesVerticalSubstitution(TrueTypeFont * ttf,int bvertical)2780 int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical)
2781 {
2782 int nRet = 0;
2783 if( bvertical)
2784 nRet = HasVerticalGSUB( ttf);
2785 return nRet;
2786 }
2787
2788 #endif
2789
GetTTGlyphCount(TrueTypeFont * ttf)2790 int GetTTGlyphCount( TrueTypeFont* ttf )
2791 {
2792 return ttf->nglyphs;
2793 }
2794
GetSfntTable(TrueTypeFont * ttf,int nSubtableIndex,const sal_uInt8 ** ppRawBytes,int * pRawLength)2795 bool GetSfntTable( TrueTypeFont* ttf, int nSubtableIndex,
2796 const sal_uInt8** ppRawBytes, int* pRawLength )
2797 {
2798 if( (nSubtableIndex < 0) || (nSubtableIndex >= NUM_TAGS) )
2799 return false;
2800 *pRawLength = ttf->tlens[ nSubtableIndex ];
2801 *ppRawBytes = ttf->tables[ nSubtableIndex ];
2802 bool bOk = (*pRawLength > 0) && (ppRawBytes != NULL);
2803 return bOk;
2804 }
2805
GetTTSimpleGlyphMetrics(TrueTypeFont * ttf,sal_uInt16 * glyphArray,int nGlyphs,int mode)2806 TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *glyphArray, int nGlyphs, int mode)
2807 {
2808 const sal_uInt8* pTable;
2809 sal_uInt32 n;
2810 int nTableSize;
2811
2812 if (mode == 0) {
2813 n = ttf->numberOfHMetrics;
2814 pTable = getTable( ttf, O_hmtx );
2815 nTableSize = getTableSize( ttf, O_hmtx );
2816 } else {
2817 n = ttf->numOfLongVerMetrics;
2818 pTable = getTable( ttf, O_vmtx );
2819 nTableSize = getTableSize( ttf, O_vmtx );
2820 }
2821
2822 if (!nGlyphs || !glyphArray) return 0; /* invalid parameters */
2823 if (!n || !pTable) return 0; /* the font does not contain the requested metrics */
2824
2825 TTSimpleGlyphMetrics* res = (TTSimpleGlyphMetrics*)calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics));
2826 assert(res != 0);
2827
2828 const int UPEm = ttf->unitsPerEm;
2829 for( int i = 0; i < nGlyphs; ++i) {
2830 int nAdvOffset, nLsbOffset;
2831 sal_uInt16 glyphID = glyphArray[i];
2832
2833 if (glyphID < n) {
2834 nAdvOffset = 4 * glyphID;
2835 nLsbOffset = nAdvOffset + 2;
2836 } else {
2837 nAdvOffset = 4 * (n - 1);
2838 if( glyphID < ttf->nglyphs )
2839 nLsbOffset = 4 * n + 2 * (glyphID - n);
2840 else /* font is broken -> use lsb of last hmetrics */
2841 nLsbOffset = nAdvOffset + 2;
2842 }
2843
2844 if( nAdvOffset >= nTableSize)
2845 res[i].adv = 0; /* better than a crash for buggy fonts */
2846 else
2847 res[i].adv = static_cast<sal_uInt16>(
2848 XUnits( UPEm, GetUInt16( pTable, nAdvOffset, 1) ) );
2849
2850 if( nLsbOffset >= nTableSize)
2851 res[i].sb = 0; /* better than a crash for buggy fonts */
2852 else
2853 res[i].sb = static_cast<sal_Int16>(
2854 XUnits( UPEm, GetInt16( pTable, nLsbOffset, 1) ) );
2855 }
2856
2857 return res;
2858 }
2859
2860 #ifndef NO_MAPPERS
GetTTSimpleCharMetrics(TrueTypeFont * ttf,sal_uInt16 firstChar,int nChars,int mode)2861 TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firstChar, int nChars, int mode)
2862 {
2863 TTSimpleGlyphMetrics *res = 0;
2864 int i, n;
2865
2866 sal_uInt16* str = (sal_uInt16*)malloc(nChars * 2);
2867 assert(str != 0);
2868
2869 for (i=0; i<nChars; i++) str[i] = (sal_uInt16)(firstChar + i);
2870 if ((n = MapString(ttf, str, nChars, 0, mode)) != -1) {
2871 res = GetTTSimpleGlyphMetrics(ttf, str, n, mode);
2872 }
2873
2874 free(str);
2875
2876 return res;
2877 }
2878 #endif
2879
GetTTGlobalFontInfo(TrueTypeFont * ttf,TTGlobalFontInfo * info)2880 void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info)
2881 {
2882 int UPEm = ttf->unitsPerEm;
2883
2884 memset(info, 0, sizeof(TTGlobalFontInfo));
2885
2886 info->family = ttf->family;
2887 info->ufamily = ttf->ufamily;
2888 info->subfamily = ttf->subfamily;
2889 info->usubfamily = ttf->usubfamily;
2890 info->psname = ttf->psname;
2891 info->symbolEncoded = (ttf->cmapType == CMAP_MS_Symbol);
2892
2893 const sal_uInt8* table = getTable(ttf, O_OS2);
2894 if (table) {
2895 info->weight = GetUInt16(table, 4, 1);
2896 info->width = GetUInt16(table, 6, 1);
2897
2898 /* There are 3 different versions of OS/2 table: original (68 bytes long),
2899 * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,)
2900 * Apple's documentation recommends looking at the table length.
2901 */
2902 if (getTableSize(ttf, O_OS2) > 68) {
2903 info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1));
2904 info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1));
2905 info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1));
2906 info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1));
2907 info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1));
2908 /* sanity check; some fonts treat winDescent as signed
2909 * violating the standard */
2910 if( info->winDescent > 5*UPEm )
2911 info->winDescent = XUnits(UPEm, GetInt16(table, 76,1));
2912 }
2913 if (ttf->cmapType == CMAP_MS_Unicode) {
2914 info->rangeFlag = 1;
2915 info->ur1 = GetUInt32(table, 42, 1);
2916 info->ur2 = GetUInt32(table, 46, 1);
2917 info->ur3 = GetUInt32(table, 50, 1);
2918 info->ur4 = GetUInt32(table, 54, 1);
2919 }
2920 memcpy(info->panose, table + 32, 10);
2921 info->typeFlags = GetUInt16( table, 8, 1 );
2922 if( getTable(ttf, O_CFF) )
2923 info->typeFlags |= TYPEFLAG_PS_OPENTYPE;
2924 }
2925
2926 table = getTable(ttf, O_post);
2927 if (table && getTableSize(ttf, O_post) >= 12+sizeof(sal_uInt32)) {
2928 info->pitch = GetUInt32(table, 12, 1);
2929 info->italicAngle = GetInt32(table, 4, 1);
2930 }
2931
2932 table = getTable(ttf, O_head); /* 'head' tables is always there */
2933 info->xMin = XUnits(UPEm, GetInt16(table, 36, 1));
2934 info->yMin = XUnits(UPEm, GetInt16(table, 38, 1));
2935 info->xMax = XUnits(UPEm, GetInt16(table, 40, 1));
2936 info->yMax = XUnits(UPEm, GetInt16(table, 42, 1));
2937 info->macStyle = GetInt16(table, 44, 1);
2938
2939 table = getTable(ttf, O_hhea);
2940 if (table) {
2941 info->ascender = XUnits(UPEm, GetInt16(table, 4, 1));
2942 info->descender = XUnits(UPEm, GetInt16(table, 6, 1));
2943 info->linegap = XUnits(UPEm, GetInt16(table, 8, 1));
2944 }
2945
2946 table = getTable(ttf, O_vhea);
2947 if (table) {
2948 info->vascent = XUnits(UPEm, GetInt16(table, 4, 1));
2949 info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1));
2950 }
2951 }
2952
2953 #ifdef TEST5
KernGlyphs(TrueTypeFont * ttf,sal_uInt16 * glyphs,int nglyphs,int wmode,KernData * kern)2954 void KernGlyphs(TrueTypeFont *ttf, sal_uInt16 *glyphs, int nglyphs, int wmode, KernData *kern)
2955 {
2956 int i;
2957
2958 if (!nglyphs || !glyphs || !kern) return;
2959
2960 for (i = 0; i < nglyphs-1; i++) kern[i].x = kern[i].y = 0;
2961
2962 switch (ttf->kerntype) {
2963 case KT_APPLE_NEW: KernGlyphsPrim1(ttf, glyphs, nglyphs, wmode, kern); return;
2964 case KT_MICROSOFT: KernGlyphsPrim2(ttf, glyphs, nglyphs, wmode, kern); return;
2965 default: return;
2966 }
2967 }
2968 #endif
2969
GetTTRawGlyphData(TrueTypeFont * ttf,sal_uInt32 glyphID)2970 GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, sal_uInt32 glyphID)
2971 {
2972 const sal_uInt8* glyf = getTable(ttf, O_glyf);
2973 const sal_uInt8* hmtx = getTable(ttf, O_hmtx);
2974 int i, n, m;
2975
2976 if( glyphID >= ttf->nglyphs )
2977 return 0;
2978
2979 /* #127161# check the glyph offsets */
2980 sal_uInt32 length = getTableSize( ttf, O_glyf );
2981 if( length < ttf->goffsets[ glyphID+1 ] )
2982 return 0;
2983 if( ttf->goffsets[ glyphID+1 ] < ttf->goffsets[ glyphID ] )
2984 return 0;
2985
2986 length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
2987
2988 GlyphData* d = (GlyphData*)malloc(sizeof(GlyphData));
2989 if (d == 0)
2990 return 0;
2991
2992 if (length > 0) {
2993 const sal_uInt8* srcptr = glyf + ttf->goffsets[glyphID];
2994 d->ptr = (sal_uInt8*)malloc((length + 1) & ~1);
2995 if (d->ptr == 0) {
2996 free(d);
2997 return 0;
2998 }
2999 memcpy( d->ptr, srcptr, length );
3000 d->compflag = (GetInt16( srcptr, 0, 1 ) < 0);
3001 } else {
3002 d->ptr = 0;
3003 d->compflag = 0;
3004 }
3005
3006 d->glyphID = glyphID;
3007 d->nbytes = (sal_uInt16)((length + 1) & ~1);
3008
3009 /* now calculate npoints and ncontours */
3010 ControlPoint *cp;
3011 n = GetTTGlyphPoints(ttf, glyphID, &cp);
3012 if( n > 0) {
3013 m = 0;
3014 for (i = 0; i < n; i++) {
3015 if (cp[i].flags & 0x8000) m++;
3016 }
3017 d->npoints = (sal_uInt16)n;
3018 d->ncontours = (sal_uInt16)m;
3019 free(cp);
3020 } else {
3021 d->npoints = 0;
3022 d->ncontours = 0;
3023 }
3024
3025 /* get advance width and left sidebearing */
3026 /* the same checks GetMetrics() makes */
3027 d->aw = 0;
3028 d->lsb = 0;
3029 if (hmtx && ttf->numberOfHMetrics) {
3030 if (glyphID < ttf->numberOfHMetrics) {
3031 d->aw = GetUInt16(hmtx, 4 * glyphID, 1);
3032 d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1);
3033 } else {
3034 const sal_uInt32 nLsbOff = ttf->numberOfHMetrics * 4 + (glyphID - ttf->numberOfHMetrics) * 2;
3035 d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1);
3036 if (fitsInTable(nLsbOff, 2, getTableSize(ttf, O_hmtx)))
3037 d->lsb = GetInt16(hmtx, nLsbOff, 1);
3038 }
3039 }
3040
3041 return d;
3042 }
3043
GetTTNameRecords(TrueTypeFont * ttf,NameRecord ** nr)3044 int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr)
3045 {
3046 const sal_uInt8* table = getTable(ttf, O_name);
3047 int nTableSize = getTableSize(ttf, O_name );
3048
3049 if (nTableSize < 6)
3050 {
3051 #if OSL_DEBUG_LEVEL > 1
3052 fprintf(stderr, "O_name table too small\n");
3053 #endif
3054 return 0;
3055 }
3056
3057 sal_uInt16 n = GetUInt16(table, 2, 1);
3058 int nStrBase = GetUInt16(table, 4, 1);
3059 int i;
3060
3061 *nr = 0;
3062 if (n == 0) return 0;
3063
3064 NameRecord* rec = (NameRecord*)calloc(n, sizeof(NameRecord));
3065
3066 for (i = 0; i < n; i++) {
3067 int nStrOffset = GetUInt16(table + 6, 10 + 12 * i, 1);
3068 rec[i].platformID = GetUInt16(table + 6, 12 * i, 1);
3069 rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1);
3070 rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1);
3071 rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1);
3072 rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1);
3073 if (rec[i].slen) {
3074 if( nStrBase+nStrOffset+rec[i].slen >= nTableSize ) {
3075 rec[i].sptr = 0;
3076 rec[i].slen = 0;
3077 continue;
3078 }
3079
3080 const sal_uInt8* rec_string = table + nStrBase + nStrOffset;
3081 // sanity check
3082 if( rec_string > (sal_uInt8*)ttf->ptr && rec_string < ((sal_uInt8*)ttf->ptr + ttf->fsize - rec[i].slen ) )
3083 {
3084 rec[i].sptr = (sal_uInt8 *) malloc(rec[i].slen); assert(rec[i].sptr != 0);
3085 memcpy(rec[i].sptr, rec_string, rec[i].slen);
3086 }
3087 else
3088 {
3089 #ifdef DEBUG
3090 fprintf( stderr, "found invalid name record %d with name id %d for file %s\n",
3091 i, rec[i].nameID, ttf->fname );
3092 #endif
3093 rec[i].sptr = 0;
3094 rec[i].slen = 0;
3095 }
3096 } else {
3097 rec[i].sptr = 0;
3098 }
3099 // some fonts have 3.0 names => fix them to 3.1
3100 if( (rec[i].platformID == 3) && (rec[i].encodingID == 0) )
3101 rec[i].encodingID = 1;
3102 }
3103
3104 *nr = rec;
3105 return n;
3106 }
3107
DisposeNameRecords(NameRecord * nr,int n)3108 void DisposeNameRecords(NameRecord* nr, int n)
3109 {
3110 int i;
3111 for (i = 0; i < n; i++) {
3112 if (nr[i].sptr) free(nr[i].sptr);
3113 }
3114 free(nr);
3115 }
3116
3117 } // namespace vcl
3118
3119
3120 #ifdef TEST1
3121 /* This example creates a subset of a TrueType font with two encoded characters */
main(int ac,char ** av)3122 int main(int ac, char **av)
3123 {
3124 TrueTypeFont *fnt;
3125 int r;
3126
3127 /* Array of Unicode source characters */
3128 sal_uInt16 chars[2];
3129
3130 /* Encoding vector maps character encoding to the ordinal number
3131 * of the glyph in the output file */
3132 sal_uInt8 encoding[2];
3133
3134 /* This array is for glyph IDs that source characters map to */
3135 sal_uInt16 g[2];
3136
3137
3138 if (ac < 2) return 0;
3139
3140 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3141 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3142 return 0;
3143 }
3144
3145
3146 /* We want to create the output file that only contains two Unicode characters:
3147 * L'a' and L'A' */
3148
3149 chars[0] = L'a';
3150 chars[1] = L'A';
3151
3152 /* Figure out what glyphs do these characters map in our font */
3153 MapString(fnt, chars, 2, g);
3154
3155 /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the
3156 * newly generated font */
3157 encoding[0] = chars[0];
3158 encoding[1] = chars[1];
3159
3160
3161 /* Generate a subset */
3162 CreateT3FromTTGlyphs(fnt, stdout, 0, g, encoding, 2, 0);
3163
3164 /* Now call the dtor for the font */
3165 CloseTTFont(fnt);
3166 return 0;
3167 }
3168 #endif
3169
3170 #ifdef TEST2
3171 /* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */
main(int ac,char ** av)3172 int main(int ac, char **av)
3173 {
3174 TrueTypeFont *fnt;
3175 int i, r;
3176
3177 /* Array of Unicode source characters */
3178 sal_uInt16 glyphs[224];
3179
3180 /* Encoding vector maps character encoding to the ordinal number
3181 * of the glyph in the output file */
3182 sal_uInt8 encoding[224];
3183
3184
3185
3186 for (i=0; i<224; i++) {
3187 glyphs[i] = i;
3188 encoding[i] = 32 + i;
3189 }
3190
3191 if (ac < 2) return 0;
3192
3193 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3194 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3195 return 0;
3196 }
3197
3198
3199 /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the
3200 * newly generated font */
3201
3202 /* Generate a subset */
3203 CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 224, 0);
3204
3205 /* Now call the dtor for the font */
3206 CloseTTFont(fnt);
3207 return 0;
3208 }
3209 #endif
3210
3211 #ifdef TEST3
3212 /* Glyph metrics example */
main(int ac,char ** av)3213 int main(int ac, char **av)
3214 {
3215 TrueTypeFont *fnt;
3216 int i, r;
3217 sal_uInt16 glyphs[224];
3218 TTSimpleGlyphMetrics *m;
3219
3220 for (i=0; i<224; i++) {
3221 glyphs[i] = i;
3222 }
3223
3224 if (ac < 2) return 0;
3225
3226 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3227 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3228 return 0;
3229 }
3230
3231 if ((m = GetTTSimpleGlyphMetrics(fnt, glyphs, 224, 0)) == 0) {
3232 printf("Requested metrics is not available\n");
3233 } else {
3234 for (i=0; i<224; i++) {
3235 printf("%d. advWid: %5d, LSBear: %5d\n", i, m[i].adv, m[i].sb);
3236 }
3237 }
3238
3239 /* Now call the dtor for the font */
3240 free(m);
3241 CloseTTFont(fnt);
3242 return 0;
3243 }
3244 #endif
3245
3246 #ifdef TEST4
main(int ac,char ** av)3247 int main(int ac, char **av)
3248 {
3249 TrueTypeFont *fnt;
3250 TTGlobalFontInfo info;
3251 int i, r;
3252
3253
3254 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3255 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3256 return 0;
3257 }
3258
3259 printf("Font file: %s\n", av[1]);
3260
3261 #ifdef PRINT_KERN
3262 switch (fnt->kerntype) {
3263 case KT_MICROSOFT:
3264 printf("\tkern: MICROSOFT, ntables: %d.", fnt->nkern);
3265 if (fnt->nkern) {
3266 printf(" [");
3267 for (i=0; i<fnt->nkern; i++) {
3268 printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1));
3269 }
3270 printf("]");
3271 }
3272 printf("\n");
3273 break;
3274
3275 case KT_APPLE_NEW:
3276 printf("\tkern: APPLE_NEW, ntables: %d.", fnt->nkern);
3277 if (fnt->nkern) {
3278 printf(" [");
3279 for (i=0; i<fnt->nkern; i++) {
3280 printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1));
3281 }
3282 printf("]");
3283 }
3284 printf("\n");
3285 break;
3286
3287 case KT_NONE:
3288 printf("\tkern: none.\n");
3289 break;
3290
3291 default:
3292 printf("\tkern: unrecoginzed.\n");
3293 break;
3294 }
3295 printf("\n");
3296 #endif
3297
3298 GetTTGlobalFontInfo(fnt, &info);
3299 printf("\tfamily name: `%s`\n", info.family);
3300 printf("\tsubfamily name: `%s`\n", info.subfamily);
3301 printf("\tpostscript name: `%s`\n", info.psname);
3302 printf("\tweight: %d\n", info.weight);
3303 printf("\twidth: %d\n", info.width);
3304 printf("\tpitch: %d\n", info.pitch);
3305 printf("\titalic angle: %d\n", info.italicAngle);
3306 printf("\tbouding box: [%d %d %d %d]\n", info.xMin, info.yMin, info.xMax, info.yMax);
3307 printf("\tascender: %d\n", info.ascender);
3308 printf("\tdescender: %d\n", info.descender);
3309 printf("\tlinegap: %d\n", info.linegap);
3310 printf("\tvascent: %d\n", info.vascent);
3311 printf("\tvdescent: %d\n", info.vdescent);
3312 printf("\ttypoAscender: %d\n", info.typoAscender);
3313 printf("\ttypoDescender: %d\n", info.typoDescender);
3314 printf("\ttypoLineGap: %d\n", info.typoLineGap);
3315 printf("\twinAscent: %d\n", info.winAscent);
3316 printf("\twinDescent: %d\n", info.winDescent);
3317 printf("\tUnicode ranges:\n");
3318 for (i = 0; i < 32; i++) {
3319 if ((info.ur1 >> i) & 1) {
3320 printf("\t\t\t%s\n", UnicodeRangeName(i));
3321 }
3322 }
3323 for (i = 0; i < 32; i++) {
3324 if ((info.ur2 >> i) & 1) {
3325 printf("\t\t\t%s\n", UnicodeRangeName(i+32));
3326 }
3327 }
3328 for (i = 0; i < 32; i++) {
3329 if ((info.ur3 >> i) & 1) {
3330 printf("\t\t\t%s\n", UnicodeRangeName(i+64));
3331 }
3332 }
3333 for (i = 0; i < 32; i++) {
3334 if ((info.ur4 >> i) & 1) {
3335 printf("\t\t\t%s\n", UnicodeRangeName(i+96));
3336 }
3337 }
3338
3339 CloseTTFont(fnt);
3340 return 0;
3341 }
3342 #endif
3343
3344 #ifdef TEST5
3345 /* Kerning example */
main(int ac,char ** av)3346 int main(int ac, char **av)
3347 {
3348 TrueTypeFont *fnt;
3349 sal_uInt16 g[224];
3350 KernData d[223];
3351 int r, i, k = 0;
3352
3353 g[k++] = 11;
3354 g[k++] = 36;
3355 g[k++] = 11;
3356 g[k++] = 98;
3357 g[k++] = 11;
3358 g[k++] = 144;
3359 g[k++] = 41;
3360 g[k++] = 171;
3361 g[k++] = 51;
3362 g[k++] = 15;
3363
3364 if (ac < 2) return 0;
3365
3366 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3367 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3368 return 0;
3369 }
3370
3371 KernGlyphs(fnt, g, k, 0, d);
3372
3373 for (i = 0; i < k-1; i++) {
3374 printf("%3d %3d: [%3d %3d]\n", g[i], g[i+1], d[i].x, d[i].y);
3375 }
3376
3377 CloseTTFont(fnt);
3378 return 0;
3379 }
3380 #endif
3381
3382
3383
3384 #ifdef TEST6
3385 /* This example extracts a single glyph from a font */
main(int ac,char ** av)3386 int main(int ac, char **av)
3387 {
3388 TrueTypeFont *fnt;
3389 int r, i;
3390
3391 sal_uInt16 glyphs[256];
3392 sal_uInt8 encoding[256];
3393
3394 for (i=0; i<256; i++) {
3395 glyphs[i] = 512 + i;
3396 encoding[i] = i;
3397 }
3398
3399 #if 0
3400 i=0;
3401 glyphs[i++] = 2001;
3402 glyphs[i++] = 2002;
3403 glyphs[i++] = 2003;
3404 glyphs[i++] = 2004;
3405 glyphs[i++] = 2005;
3406 glyphs[i++] = 2006;
3407 glyphs[i++] = 2007;
3408 glyphs[i++] = 2008;
3409 glyphs[i++] = 2009;
3410 glyphs[i++] = 2010;
3411 glyphs[i++] = 2011;
3412 glyphs[i++] = 2012;
3413 glyphs[i++] = 2013;
3414 glyphs[i++] = 2014;
3415 glyphs[i++] = 2015;
3416 glyphs[i++] = 2016;
3417 glyphs[i++] = 2017;
3418 glyphs[i++] = 2018;
3419 glyphs[i++] = 2019;
3420 glyphs[i++] = 2020;
3421
3422
3423 r = 97;
3424 i = 0;
3425 encoding[i++] = r++;
3426 encoding[i++] = r++;
3427 encoding[i++] = r++;
3428 encoding[i++] = r++;
3429 encoding[i++] = r++;
3430 encoding[i++] = r++;
3431 encoding[i++] = r++;
3432 encoding[i++] = r++;
3433 encoding[i++] = r++;
3434 encoding[i++] = r++;
3435 encoding[i++] = r++;
3436 encoding[i++] = r++;
3437 encoding[i++] = r++;
3438 encoding[i++] = r++;
3439 encoding[i++] = r++;
3440 encoding[i++] = r++;
3441 encoding[i++] = r++;
3442 encoding[i++] = r++;
3443 encoding[i++] = r++;
3444 encoding[i++] = r++;
3445 #endif
3446
3447 if (ac < 2) return 0;
3448
3449 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3450 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3451 return 0;
3452 }
3453
3454 /* Generate a subset */
3455 CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 256, 0);
3456
3457 fprintf(stderr, "UnitsPerEm: %d.\n", fnt->unitsPerEm);
3458
3459 /* Now call the dtor for the font */
3460 CloseTTFont(fnt);
3461 return 0;
3462 }
3463 #endif
3464
3465 #ifdef TEST7
3466 /* NameRecord extraction example */
main(int ac,char ** av)3467 int main(int ac, char **av)
3468 {
3469 TrueTypeFont *fnt;
3470 int r, i, j, n;
3471 NameRecord *nr;
3472
3473 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3474 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3475 return 0;
3476 }
3477
3478 if ((n = GetTTNameRecords(fnt, &nr)) == 0) {
3479 fprintf(stderr, "No name records in the font.\n");
3480 return 0;
3481 }
3482
3483 printf("Number of name records: %d.\n", n);
3484 for (i = 0; i < n; i++) {
3485 printf("%d %d %04X %d [", nr[i].platformID, nr[i].encodingID, nr[i].languageID, nr[i].nameID);
3486 for (j=0; j<nr[i].slen; j++) {
3487 printf("%c", isprint(nr[i].sptr[j]) ? nr[i].sptr[j] : '.');
3488 }
3489 printf("]\n");
3490 }
3491
3492
3493 DisposeNameRecords(nr, n);
3494 CloseTTFont(fnt);
3495 return 0;
3496 }
3497 #endif
3498
3499 #ifdef TEST8
3500 /* TrueType -> TrueType subsetting */
main(int ac,char ** av)3501 int main(int ac, char **av)
3502 {
3503 TrueTypeFont *fnt;
3504 sal_uInt16 glyphArray[] = { 0, 98, 99, 22, 24, 25, 26, 27, 28, 29, 30, 31, 1270, 1289, 34};
3505 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3506 int r;
3507
3508 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3509 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3510 return 0;
3511 }
3512
3513 CreateTTFromTTGlyphs(fnt, "subfont.ttf", glyphArray, encoding, 15, 0, 0, TTCF_AutoName | TTCF_IncludeOS2);
3514
3515
3516 CloseTTFont(fnt);
3517
3518 return 0;
3519 }
3520 #endif
3521
3522 #ifdef TEST9
3523 /* TrueType -> Type42 subsetting */
main(int ac,char ** av)3524 int main(int ac, char **av)
3525 {
3526 TrueTypeFont *fnt;
3527 /*
3528 sal_uInt16 glyphArray[] = { 0, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34};
3529 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3530 */
3531 sal_uInt16 glyphArray[] = { 0, 6711, 6724, 11133, 11144, 14360, 26, 27, 28, 29, 30, 31, 1270, 1289, 34};
3532 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3533 int r;
3534
3535 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3536 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3537 return 0;
3538 }
3539
3540 CreateT42FromTTGlyphs(fnt, stdout, "testfont", glyphArray, encoding, 15);
3541
3542 CloseTTFont(fnt);
3543
3544 return 0;
3545 }
3546 #endif
3547
3548 #ifdef TEST10
3549 /* Component glyph test */
main(int ac,char ** av)3550 int main(int ac, char **av)
3551 {
3552 TrueTypeFont *fnt;
3553 int r, i;
3554 list glyphlist = listNewEmpty();
3555
3556
3557 if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
3558 fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
3559 return 0;
3560 }
3561
3562 for (i = 0; i < fnt->nglyphs; i++) {
3563 r = GetTTGlyphComponents(fnt, i, glyphlist);
3564 if (r > 1) {
3565 printf("%d -> ", i);
3566 listToFirst(glyphlist);
3567 do {
3568 printf("%d ", (int) listCurrent(glyphlist));
3569 } while (listNext(glyphlist));
3570 printf("\n");
3571 } else {
3572 printf("%d: single glyph.\n", i);
3573 }
3574 listClear(glyphlist);
3575 }
3576
3577 CloseTTFont(fnt);
3578 listDispose(glyphlist);
3579
3580 return 0;
3581 }
3582 #endif
3583
3584 /* vim: set noet sw=4 ts=4: */
3585