1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
24 * Author: Alexander Gelfenbain
39 #if ! (defined(NO_TTCR) && defined(NO_TYPE42))
42 #ifndef NO_MAPPERS /* include MapChar() and MapString() */
45 #ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */
49 #include <osl/endian.h>
55 /*- module identification */
57 static const char *modname
= "SunTypeTools-TT";
58 static const char *modver
= "1.0";
59 static const char *modextra
= "gelf";
61 /*- private functions, constants and data types */ /*FOLD00*/
63 enum PathSegmentType
{
78 PSPathElement( PathSegmentType i_eType
) : type( i_eType
),
86 /*- In horizontal writing mode right sidebearing is calculated using this formula
87 *- rsb = aw - (lsb + xMax - xMin) -*/
93 sal_uInt16 aw
; /*- Advance Width (horizontal writing mode) */
94 sal_Int16 lsb
; /*- Left sidebearing (horizontal writing mode) */
95 sal_uInt16 ah
; /*- advance height (vertical writing mode) */
96 sal_Int16 tsb
; /*- top sidebearing (vertical writing mode) */
99 #define HFORMAT_LINELEN 64
103 char buffer
[HFORMAT_LINELEN
];
109 sal_uInt32 nGlyphs
; /* number of glyphs in the font + 1 */
110 sal_uInt32
*offs
; /* array of nGlyphs offsets */
114 static const sal_uInt32 TTFontClassTag
= 0x74746663; /* 'ttfc' */
116 static const sal_uInt32 T_true
= 0x74727565; /* 'true' */
117 static const sal_uInt32 T_ttcf
= 0x74746366; /* 'ttcf' */
118 static const sal_uInt32 T_otto
= 0x4f54544f; /* 'OTTO' */
120 /* standard TrueType table tags */
121 #define T_maxp 0x6D617870
122 #define T_glyf 0x676C7966
123 #define T_head 0x68656164
124 #define T_loca 0x6C6F6361
125 #define T_name 0x6E616D65
126 #define T_hhea 0x68686561
127 #define T_hmtx 0x686D7478
128 #define T_cmap 0x636D6170
129 #define T_vhea 0x76686561
130 #define T_vmtx 0x766D7478
131 #define T_OS2 0x4F532F32
132 #define T_post 0x706F7374
133 #define T_kern 0x6B65726E
134 #define T_cvt 0x63767420
135 #define T_prep 0x70726570
136 #define T_fpgm 0x6670676D
137 #define T_gsub 0x47535542
138 #define T_CFF 0x43464620
140 #define LAST_URANGE_BIT 69
141 const char *ulcodes
[LAST_URANGE_BIT
+2] = {
142 /* 0 */ "Basic Latin",
143 /* 1 */ "Latin-1 Supplement",
144 /* 2 */ "Latin Extended-A",
145 /* 3 */ "Latin Extended-B",
146 /* 4 */ "IPA Extensions",
147 /* 5 */ "Spacing Modifier Letters",
148 /* 6 */ "Combining Diacritical Marks",
149 /* 7 */ "Basic Greek",
150 /* 8 */ "Greek Symbols And Coptic",
153 /* 11 */ "Basic Hebrew",
154 /* 12 */ "Hebrew Extended (A and B blocks combined)",
155 /* 13 */ "Basic Arabic",
156 /* 14 */ "Arabic Extended",
157 /* 15 */ "Devanagari",
165 /* 23 */ "Malayalam",
168 /* 26 */ "Basic Georgian",
169 /* 27 */ "Georgian Extended",
170 /* 28 */ "Hangul Jamo",
171 /* 29 */ "Latin Extended Additional",
172 /* 30 */ "Greek Extended",
173 /* 31 */ "General Punctuation",
174 /* 32 */ "Superscripts And Subscripts",
175 /* 33 */ "Currency Symbols",
176 /* 34 */ "Combining Diacritical Marks For Symbols",
177 /* 35 */ "Letterlike Symbols",
178 /* 36 */ "Number Forms",
180 /* 38 */ "Mathematical Operators",
181 /* 39 */ "Miscellaneous Technical",
182 /* 40 */ "Control Pictures",
183 /* 41 */ "Optical Character Recognition",
184 /* 42 */ "Enclosed Alphanumerics",
185 /* 43 */ "Box Drawing",
186 /* 44 */ "Block Elements",
187 /* 45 */ "Geometric Shapes",
188 /* 46 */ "Miscellaneous Symbols",
190 /* 48 */ "CJK Symbols And Punctuation",
194 /* 52 */ "Hangul Compatibility Jamo",
195 /* 53 */ "CJK Miscellaneous",
196 /* 54 */ "Enclosed CJK Letters And Months",
197 /* 55 */ "CJK Compatibility",
199 /* 57 */ "Reserved for Unicode SubRanges",
200 /* 58 */ "Reserved for Unicode SubRanges",
201 /* 59 */ "CJK Unified Ideographs",
202 /* 60 */ "Private Use Area",
203 /* 61 */ "CJK Compatibility Ideographs",
204 /* 62 */ "Alphabetic Presentation Forms",
205 /* 63 */ "Arabic Presentation Forms-A",
206 /* 64 */ "Combining Half Marks",
207 /* 65 */ "CJK Compatibility Forms",
208 /* 66 */ "Small Form Variants",
209 /* 67 */ "Arabic Presentation Forms-B",
210 /* 68 */ "Halfwidth And Fullwidth Forms",
212 /*70-127*/ "Reserved for Unicode SubRanges"
217 /*- inline functions */ /*FOLD01*/
219 #define _inline static __inline__
221 #define _inline static
224 _inline
void *smalloc(size_t size
)
226 void *res
= malloc(size
);
231 _inline
void *scalloc(size_t n
, size_t size
)
233 void *res
= calloc(n
, size
);
238 _inline sal_uInt32
mkTag(sal_uInt8 a
, sal_uInt8 b
, sal_uInt8 c
, sal_uInt8 d
) {
239 return (a
<< 24) | (b
<< 16) | (c
<< 8) | d
;
242 /*- Data access macros for data stored in big-endian or little-endian format */
243 _inline sal_Int16
GetInt16(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
249 t
= (ptr
+offset
)[0] << 8 | (ptr
+offset
)[1];
251 t
= (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
257 _inline sal_uInt16
GetUInt16(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
263 t
= (ptr
+offset
)[0] << 8 | (ptr
+offset
)[1];
265 t
= (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
271 _inline sal_Int32
GetInt32(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
277 t
= (ptr
+offset
)[0] << 24 | (ptr
+offset
)[1] << 16 |
278 (ptr
+offset
)[2] << 8 | (ptr
+offset
)[3];
280 t
= (ptr
+offset
)[3] << 24 | (ptr
+offset
)[2] << 16 |
281 (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
287 _inline sal_uInt32
GetUInt32(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
294 t
= (ptr
+offset
)[0] << 24 | (ptr
+offset
)[1] << 16 |
295 (ptr
+offset
)[2] << 8 | (ptr
+offset
)[3];
297 t
= (ptr
+offset
)[3] << 24 | (ptr
+offset
)[2] << 16 |
298 (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
304 _inline
void PutInt16(sal_Int16 val
, sal_uInt8
*ptr
, size_t offset
, int bigendian
)
309 ptr
[offset
] = (sal_uInt8
)((val
>> 8) & 0xFF);
310 ptr
[offset
+1] = (sal_uInt8
)(val
& 0xFF);
312 ptr
[offset
+1] = (sal_uInt8
)((val
>> 8) & 0xFF);
313 ptr
[offset
] = (sal_uInt8
)(val
& 0xFF);
318 #if defined(OSL_BIGENDIAN)
319 #define Int16FromMOTA(a) (a)
320 #define Int32FromMOTA(a) (a)
322 static sal_uInt16
Int16FromMOTA(sal_uInt16 a
) {
323 return (sal_uInt16
) (((sal_uInt8
)((a
) >> 8)) | ((sal_uInt8
)(a
) << 8));
325 static sal_uInt32
Int32FromMOTA(sal_uInt32 a
) {
326 return ((a
>>24)&0xFF) | (((a
>>8)&0xFF00) | ((a
&0xFF00)<<8) | ((a
&0xFF)<<24));
330 _inline F16Dot16
fixedMul(F16Dot16 a
, F16Dot16 b
)
337 sign
= (a
& 0x80000000) ^ (b
& 0x80000000);
348 /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */
351 res
+= a1
* b2
+ b1
* a2
+ ((b1
* b2
) >> 16);
353 return sign
? -res
: res
;
357 _inline F16Dot16
fixedDiv(F16Dot16 a
, F16Dot16 b
)
363 sign
= (a
& 0x80000000) ^ (b
& 0x80000000);
370 /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */
377 res
= (f
<< 16) + (r
<< 16) / b
;
379 return sign
? -res
: res
;
382 /*- returns a * b / c -*/
383 /* XXX provide a real implementation that preserves accuracy */
384 _inline F16Dot16
fixedMulDiv(F16Dot16 a
, F16Dot16 b
, F16Dot16 c
)
388 res
= fixedMul(a
, b
);
389 return fixedDiv(res
, c
);
392 /*- Translate units from TT to PS (standard 1/1000) -*/
393 _inline
int XUnits(int unitsPerEm
, int n
)
395 return (n
* 1000) / unitsPerEm
;
398 _inline
const char *UnicodeRangeName(sal_uInt16 bit
)
400 if (bit
> LAST_URANGE_BIT
) bit
= LAST_URANGE_BIT
+1;
405 _inline
const sal_uInt8
* getTable( TrueTypeFont
*ttf
, sal_uInt32 ord
)
407 return (sal_uInt8
*)ttf
->tables
[ord
];
410 _inline sal_uInt32
getTableSize(TrueTypeFont
*ttf
, sal_uInt32 ord
)
412 return ttf
->tlens
[ord
];
416 /* Hex Formatter functions */
417 static char HexChars
[] = "0123456789ABCDEF";
419 static HexFmt
*HexFmtNew(FILE *outf
)
421 HexFmt
* res
= (HexFmt
*)smalloc(sizeof(HexFmt
));
422 res
->bufpos
= res
->total
= 0;
427 static bool HexFmtFlush(HexFmt
*_this
)
431 size_t nWritten
= fwrite(_this
->buffer
, 1, _this
->bufpos
, _this
->o
);
432 bRet
= nWritten
== _this
->bufpos
;
438 _inline
void HexFmtOpenString(HexFmt
*_this
)
440 fputs("<\n", _this
->o
);
443 _inline
void HexFmtCloseString(HexFmt
*_this
)
446 fputs("00\n>\n", _this
->o
);
449 _inline
void HexFmtDispose(HexFmt
*_this
)
455 static void HexFmtBlockWrite(HexFmt
*_this
, const void *ptr
, sal_uInt32 size
)
460 if (_this
->total
+ size
> 65534) {
462 HexFmtCloseString(_this
);
464 HexFmtOpenString(_this
);
466 for (i
=0; i
<size
; i
++) {
467 Ch
= ((sal_uInt8
*) ptr
)[i
];
468 _this
->buffer
[_this
->bufpos
++] = HexChars
[Ch
>> 4];
469 _this
->buffer
[_this
->bufpos
++] = HexChars
[Ch
& 0xF];
470 if (_this
->bufpos
== HFORMAT_LINELEN
) {
472 fputc('\n', _this
->o
);
476 _this
->total
+= size
;
482 /* Outline Extraction functions */ /*FOLD01*/
484 /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
485 static void GetMetrics(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, TTGlyphMetrics
*metrics
)
487 const sal_uInt8
* table
= getTable( ttf
, O_hmtx
);
489 metrics
->aw
= metrics
->lsb
= metrics
->ah
= metrics
->tsb
= 0;
490 if (!table
|| !ttf
->numberOfHMetrics
) return;
492 if (glyphID
< ttf
->numberOfHMetrics
) {
493 metrics
->aw
= GetUInt16(table
, 4 * glyphID
, 1);
494 metrics
->lsb
= GetInt16(table
, 4 * glyphID
+ 2, 1);
496 metrics
->aw
= GetUInt16(table
, 4 * (ttf
->numberOfHMetrics
- 1), 1);
497 metrics
->lsb
= GetInt16(table
+ ttf
->numberOfHMetrics
* 4, (glyphID
- ttf
->numberOfHMetrics
) * 2, 1);
500 table
= getTable(ttf
, O_vmtx
);
501 if( !table
|| !ttf
->numOfLongVerMetrics
)
504 if (glyphID
< ttf
->numOfLongVerMetrics
) {
505 metrics
->ah
= GetUInt16(table
, 4 * glyphID
, 1);
506 metrics
->tsb
= GetInt16(table
, 4 * glyphID
+ 2, 1);
508 metrics
->ah
= GetUInt16(table
, 4 * (ttf
->numOfLongVerMetrics
- 1), 1);
509 metrics
->tsb
= GetInt16(table
+ ttf
->numOfLongVerMetrics
* 4, (glyphID
- ttf
->numOfLongVerMetrics
) * 2, 1);
513 static int GetTTGlyphOutline(TrueTypeFont
*, sal_uInt32
, ControlPoint
**, TTGlyphMetrics
*, std::vector
< sal_uInt32
>* );
515 /* returns the number of control points, allocates the pointArray */
516 static int GetSimpleTTOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
) /*FOLD02*/
518 const sal_uInt8
* table
= getTable( ttf
, O_glyf
);
520 sal_uInt16 t
, lastPoint
=0;
525 /* printf("GetSimpleTTOutline(%d)\n", glyphID); */
527 if( glyphID
>= ttf
->nglyphs
) /*- glyph is not present in the font */
529 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
530 const sal_Int16 numberOfContours
= GetInt16(ptr
, 0, 1);
531 if( numberOfContours
<= 0 ) /*- glyph is not simple */
534 if (metrics
) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
535 metrics
->xMin
= GetInt16(ptr
, 2, 1);
536 metrics
->yMin
= GetInt16(ptr
, 4, 1);
537 metrics
->xMax
= GetInt16(ptr
, 6, 1);
538 metrics
->yMax
= GetInt16(ptr
, 8, 1);
539 GetMetrics(ttf
, glyphID
, metrics
);
542 /* determine the last point and be extra safe about it. But probably this code is not needed */
544 for (i
=0; i
<numberOfContours
; i
++) {
545 if ((t
= GetUInt16(ptr
, 10+i
*2, 1)) > lastPoint
) lastPoint
= t
;
548 sal_uInt16 instLen
= GetUInt16(ptr
, 10 + numberOfContours
*2, 1);
549 const sal_uInt8
* p
= ptr
+ 10 + 2 * numberOfContours
+ 2 + instLen
;
550 ControlPoint
* pa
= (ControlPoint
*)calloc(lastPoint
+1, sizeof(ControlPoint
));
553 while (i
<= lastPoint
) {
554 pa
[i
++].flags
= (sal_uInt32
) (flag
= *p
++);
555 if (flag
& 8) { /*- repeat flag */
557 for (j
=0; j
<n
; j
++) {
558 if (i
> lastPoint
) { /*- if the font is really broken */
562 pa
[i
++].flags
= flag
;
567 /*- Process the X coordinate */
569 for (i
= 0; i
<= lastPoint
; i
++) {
570 if (pa
[i
].flags
& 0x02) {
571 if (pa
[i
].flags
& 0x10) {
576 } else if ( !(pa
[i
].flags
& 0x10)) {
577 z
+= GetInt16(p
, 0, 1);
580 pa
[i
].x
= (sal_Int16
)z
;
583 /*- Process the Y coordinate */
585 for (i
= 0; i
<= lastPoint
; i
++) {
586 if (pa
[i
].flags
& 0x04) {
587 if (pa
[i
].flags
& 0x20) {
592 } else if ( !(pa
[i
].flags
& 0x20)) {
593 z
+= GetInt16(p
, 0, 1);
596 pa
[i
].y
= (sal_Int16
)z
;
599 for (i
=0; i
<numberOfContours
; i
++) {
600 pa
[GetUInt16(ptr
, 10 + i
* 2, 1)].flags
|= 0x00008000; /*- set the end contour flag */
604 return lastPoint
+ 1;
607 static int GetCompoundTTOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
, std::vector
< sal_uInt32
>& glyphlist
) /*FOLD02*/
609 sal_uInt16 flags
, index
;
610 sal_Int16 e
, f
, numberOfContours
;
611 const sal_uInt8
* table
= getTable( ttf
, O_glyf
);
612 std::vector
<ControlPoint
> myPoints
;
613 ControlPoint
*nextComponent
, *pa
;
615 F16Dot16 a
= 0x10000, b
= 0, c
= 0, d
= 0x10000, m
, n
, abs1
, abs2
, abs3
;
618 /* printf("GetCompoundTTOutline(%d)\n", glyphID); */
620 if (glyphID
>= ttf
->nglyphs
) /*- incorrect glyphID */
623 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
624 if ((numberOfContours
= GetInt16(ptr
, 0, 1)) != -1) /*- glyph is not compound */
628 metrics
->xMin
= GetInt16(ptr
, 2, 1);
629 metrics
->yMin
= GetInt16(ptr
, 4, 1);
630 metrics
->xMax
= GetInt16(ptr
, 6, 1);
631 metrics
->yMax
= GetInt16(ptr
, 8, 1);
632 GetMetrics(ttf
, glyphID
, metrics
);
638 flags
= GetUInt16(ptr
, 0, 1);
639 /* printf("flags: 0x%X\n", flags); */
640 index
= GetUInt16(ptr
, 2, 1);
643 if( std::find( glyphlist
.begin(), glyphlist
.end(), index
) != glyphlist
.end() )
645 #if OSL_DEBUG_LEVEL > 1
646 fprintf(stderr
, "Endless loop found in a compound glyph.\n");
647 fprintf(stderr
, "%d -> ", index
);
648 fprintf(stderr
," [");
649 for( std::vector
< sal_uInt32
>::const_iterator it
= glyphlist
.begin();
650 it
!= glyphlist
.end(); ++it
)
652 fprintf( stderr
,"%d ", (int) *it
);
654 fprintf(stderr
,"]\n");
659 glyphlist
.push_back( index
);
661 if ((np
= GetTTGlyphOutline(ttf
, index
, &nextComponent
, 0, &glyphlist
)) == 0)
663 /* XXX that probably indicates a corrupted font */
664 #if OSL_DEBUG_LEVEL > 1
665 fprintf(stderr
, "An empty compound!\n");
666 /* assert(!"An empty compound"); */
670 if( ! glyphlist
.empty() )
671 glyphlist
.pop_back();
673 if (flags
& USE_MY_METRICS
) {
674 if (metrics
) GetMetrics(ttf
, index
, metrics
);
677 if (flags
& ARG_1_AND_2_ARE_WORDS
) {
678 e
= GetInt16(ptr
, 0, 1);
679 f
= GetInt16(ptr
, 2, 1);
680 /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
683 if (flags
& ARGS_ARE_XY_VALUES
) { /* args are signed */
684 e
= (sal_Int8
) *ptr
++;
685 f
= (sal_Int8
) *ptr
++;
686 /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
687 } else { /* args are unsigned */
688 /* printf("!ARGS_ARE_XY_VALUES\n"); */
698 if (flags
& WE_HAVE_A_SCALE
) {
699 a
= GetInt16(ptr
, 0, 1) << 2;
702 } else if (flags
& WE_HAVE_AN_X_AND_Y_SCALE
) {
703 a
= GetInt16(ptr
, 0, 1) << 2;
704 d
= GetInt16(ptr
, 2, 1) << 2;
706 } else if (flags
& WE_HAVE_A_TWO_BY_TWO
) {
707 a
= GetInt16(ptr
, 0, 1) << 2;
708 b
= GetInt16(ptr
, 2, 1) << 2;
709 c
= GetInt16(ptr
, 4, 1) << 2;
710 d
= GetInt16(ptr
, 6, 1) << 2;
714 abs1
= (a
< 0) ? -a
: a
;
715 abs2
= (b
< 0) ? -b
: b
;
716 m
= (abs1
> abs2
) ? abs1
: abs2
;
718 if (abs3
< 0) abs3
= -abs3
;
719 if (abs3
<= 33) m
*= 2;
721 abs1
= (c
< 0) ? -c
: c
;
722 abs2
= (d
< 0) ? -d
: d
;
723 n
= (abs1
> abs2
) ? abs1
: abs2
;
725 if (abs3
< 0) abs3
= -abs3
;
726 if (abs3
<= 33) n
*= 2;
728 if (!ARGS_ARE_XY_VALUES
) { /* match the points */
729 assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n");
732 for (i
=0; i
<np
; i
++) {
735 cp
.flags
= nextComponent
[i
].flags
;
736 t
= fixedMulDiv(a
, nextComponent
[i
].x
<< 16, m
) + fixedMulDiv(c
, nextComponent
[i
].y
<< 16, m
) + (e
<< 16);
737 cp
.x
= (sal_Int16
)(fixedMul(t
, m
) >> 16);
738 t
= fixedMulDiv(b
, nextComponent
[i
].x
<< 16, n
) + fixedMulDiv(d
, nextComponent
[i
].y
<< 16, n
) + (f
<< 16);
739 cp
.y
= (sal_Int16
)(fixedMul(t
, n
) >> 16);
741 myPoints
.push_back( cp
);
746 } while (flags
& MORE_COMPONENTS
);
748 // #i123417# some fonts like IFAOGrec have no outline points in some compound glyphs
749 // so this unlikely but possible scenario should be handled gracefully
750 if( myPoints
.empty() )
753 np
= myPoints
.size();
755 pa
= (ControlPoint
*)calloc(np
, sizeof(ControlPoint
));
759 memcpy( pa
, &myPoints
[0], np
*sizeof(ControlPoint
) );
765 /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect,
766 * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
768 * NOTE: glyphlist is the stack of glyphs traversed while constructing
769 * a composite glyph. This is a safequard against endless recursion
770 * in corrupted fonts.
772 static int GetTTGlyphOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
, std::vector
< sal_uInt32
>* glyphlist
)
774 const sal_uInt8
*table
= getTable( ttf
, O_glyf
);
775 sal_Int16 numberOfContours
;
780 memset(metrics
, 0, sizeof(TTGlyphMetrics
)); /*- metrics is initialized to all zeroes */
783 if (glyphID
>= ttf
->nglyphs
) return -1; /**/
785 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
786 int length
= ttf
->goffsets
[glyphID
+1] - ttf
->goffsets
[glyphID
];
788 if (length
== 0) { /*- empty glyphs still have hmtx and vmtx metrics values */
789 if (metrics
) GetMetrics(ttf
, glyphID
, metrics
);
793 numberOfContours
= GetInt16(ptr
, 0, 1);
795 if (numberOfContours
>= 0)
797 res
=GetSimpleTTOutline(ttf
, glyphID
, pointArray
, metrics
);
801 std::vector
< sal_uInt32
> aPrivList
;
802 aPrivList
.push_back( glyphID
);
803 res
= GetCompoundTTOutline(ttf
, glyphID
, pointArray
, metrics
, glyphlist
? *glyphlist
: aPrivList
);
811 /*- returns the number of items in the path -*/
813 static int BSplineToPSPath(ControlPoint
*srcA
, int srcCount
, PSPathElement
**path
)
815 std::vector
< PSPathElement
> aPathList
;
817 PSPathElement
p( PS_NOOP
);
819 int x0
= 0, y0
= 0, x1
= 0, y1
= 0, x2
, y2
, curx
, cury
;
820 int lastOff
= 0; /*- last point was off-contour */
821 int scflag
= 1; /*- start contour flag */
822 int ecflag
= 0; /*- end contour flag */
823 int cp
= 0; /*- current point */
824 int StartContour
= 0, EndContour
= 1;
828 /* if (srcCount > 0) for(;;) */
829 while (srcCount
> 0) { /*- srcCount does not get changed inside the loop. */
833 while (!(srcA
[l
].flags
& 0x8000)) l
++;
835 if (StartContour
== EndContour
) {
836 if (cp
+ 1 < srcCount
) {
843 p
= PSPathElement(PS_MOVETO
);
844 if (!(srcA
[cp
].flags
& 1)) {
845 if (!(srcA
[EndContour
].flags
& 1)) {
846 p
.x1
= x0
= (srcA
[cp
].x
+ srcA
[EndContour
].x
+ 1) / 2;
847 p
.y1
= y0
= (srcA
[cp
].y
+ srcA
[EndContour
].y
+ 1) / 2;
849 p
.x1
= x0
= srcA
[EndContour
].x
;
850 p
.y1
= y0
= srcA
[EndContour
].y
;
853 p
.x1
= x0
= srcA
[cp
].x
;
854 p
.y1
= y0
= srcA
[cp
].y
;
857 aPathList
.push_back( p
);
865 if (srcA
[cp
].flags
& 1)
869 p
= PSPathElement(PS_CURVETO
);
870 p
.x1
= x0
+ (2 * (x1
- x0
) + 1) / 3;
871 p
.y1
= y0
+ (2 * (y1
- y0
) + 1) / 3;
872 p
.x2
= x1
+ (curx
- x1
+ 1) / 3;
873 p
.y2
= y1
+ (cury
- y1
+ 1) / 3;
876 aPathList
.push_back( p
);
880 if (!(x0
== curx
&& y0
== cury
))
881 { /* eliminate empty lines */
882 p
= PSPathElement(PS_LINETO
);
885 aPathList
.push_back( p
);
888 x0
= curx
; y0
= cury
; lastOff
= 0;
894 x2
= (x1
+ curx
+ 1) / 2;
895 y2
= (y1
+ cury
+ 1) / 2;
896 p
= PSPathElement(PS_CURVETO
);
897 p
.x1
= x0
+ (2 * (x1
- x0
) + 1) / 3;
898 p
.y1
= y0
+ (2 * (y1
- y0
) + 1) / 3;
899 p
.x2
= x1
+ (x2
- x1
+ 1) / 3;
900 p
.y2
= y1
+ (y2
- y1
+ 1) / 3;
903 aPathList
.push_back( p
);
905 x1
= curx
; y1
= cury
;
907 x1
= curx
; y1
= cury
;
913 aPathList
.push_back( PSPathElement(PS_CLOSEPATH
) );
917 if (cp
>= srcCount
) break;
922 if (cp
== EndContour
) {
930 if( (nPathCount
= (int)aPathList
.size()) > 0)
932 *path
= (PSPathElement
*)calloc(nPathCount
, sizeof(PSPathElement
));
934 memcpy( *path
, &aPathList
[0], nPathCount
* sizeof(PSPathElement
) );
942 /*- Extracts a string from the name table and allocates memory for it -*/
944 static char *nameExtract( const sal_uInt8
* name
, int nTableSize
, int n
, int dbFlag
, sal_uInt16
** ucs2result
)
947 const sal_uInt8
* ptr
= name
+ GetUInt16(name
, 4, 1) + GetUInt16(name
+ 6, 12 * n
+ 10, 1);
948 int len
= GetUInt16(name
+6, 12 * n
+ 8, 1);
951 if( (len
<= 0) || ((ptr
+len
) > (name
+nTableSize
)) )
961 res
= (char*)malloc(1 + len
/2);
963 for (int i
= 0; i
< len
/2; i
++)
964 res
[i
] = *(ptr
+ i
* 2 + 1);
968 *ucs2result
= (sal_uInt16
*)malloc( len
+2 );
969 for (int i
= 0; i
< len
/2; i
++ )
970 (*ucs2result
)[i
] = GetUInt16( ptr
, 2*i
, 1 );
971 (*ucs2result
)[len
/2] = 0;
974 res
= (char*)malloc(1 + len
);
976 memcpy(res
, ptr
, len
);
983 static int findname( const sal_uInt8
*name
, sal_uInt16 n
, sal_uInt16 platformID
,
984 sal_uInt16 encodingID
, sal_uInt16 languageID
, sal_uInt16 nameID
)
986 int l
= 0, r
= n
-1, i
;
990 if (n
== 0) return -1;
992 m1
= (platformID
<< 16) | encodingID
;
993 m2
= (languageID
<< 16) | nameID
;
997 t1
= GetUInt32(name
+ 6, i
* 12 + 0, 1);
998 t2
= GetUInt32(name
+ 6, i
* 12 + 4, 1);
1000 if (! ((m1
< t1
) || ((m1
== t1
) && (m2
< t2
)))) l
= i
+ 1;
1001 if (! ((m1
> t1
) || ((m1
== t1
) && (m2
> t2
)))) r
= i
- 1;
1011 /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables.
1012 * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
1014 * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
1015 * and does not have (3, 1, 1033)
1016 * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
1017 * require a change in algorithm
1019 * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID,
1020 * but (1, 0, 1042) strings usable
1021 * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
1024 static void GetNames(TrueTypeFont
*t
)
1026 const sal_uInt8
* table
= getTable( t
, O_name
);
1027 int nTableSize
= getTableSize(t
, O_name
);
1031 #if OSL_DEBUG_LEVEL > 1
1032 fprintf(stderr
, "O_name table too small\n");
1037 sal_uInt16 n
= GetUInt16(table
, 2, 1);
1039 sal_Bool bPSNameOK
= sal_True
;
1041 /* #129743# simple sanity check for name table entry count */
1042 if( nTableSize
<= n
* 12 + 6 )
1045 /* PostScript name: preferred Microsoft */
1047 if ((r
= findname(table
, n
, 3, 1, 0x0409, 6)) != -1)
1048 t
->psname
= nameExtract(table
, nTableSize
, r
, 1, NULL
);
1049 if ( ! t
->psname
&& (r
= findname(table
, n
, 1, 0, 0, 6)) != -1)
1050 t
->psname
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
1051 if ( ! t
->psname
&& (r
= findname(table
, n
, 3, 0, 0x0409, 6)) != -1)
1053 // some symbol fonts like Marlett have a 3,0 name!
1054 t
->psname
= nameExtract(table
, nTableSize
, r
, 1, NULL
);
1056 // for embedded font in Ghostscript PDFs
1057 if ( ! t
->psname
&& (r
= findname(table
, n
, 2, 2, 0, 6)) != -1)
1059 t
->psname
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
1065 char* pReverse
= t
->fname
+ strlen(t
->fname
);
1066 /* take only last token of filename */
1067 while(pReverse
!= t
->fname
&& *pReverse
!= '/') pReverse
--;
1068 if(*pReverse
== '/') pReverse
++;
1069 t
->psname
= strdup(pReverse
);
1070 assert(t
->psname
!= 0);
1071 for (i
=strlen(t
->psname
) - 1; i
> 0; i
--)
1073 /*- Remove the suffix -*/
1074 if (t
->psname
[i
] == '.' ) {
1081 t
->psname
= strdup( "Unknown" );
1084 /* Font family and subfamily names: preferred Apple */
1086 if ((r
= findname(table
, n
, 0, 0, 0, 1)) != -1)
1087 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1088 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 1, 0x0409, 1)) != -1)
1089 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1090 if ( ! t
->family
&& (r
= findname(table
, n
, 1, 0, 0, 1)) != -1)
1091 t
->family
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
1092 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 1, 0x0411, 1)) != -1)
1093 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1094 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 0, 0x0409, 1)) != -1)
1095 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1098 t
->family
= strdup(t
->psname
);
1099 assert(t
->family
!= 0);
1102 t
->subfamily
= NULL
;
1103 t
->usubfamily
= NULL
;
1104 if ((r
= findname(table
, n
, 1, 0, 0, 2)) != -1)
1105 t
->subfamily
= nameExtract(table
, nTableSize
, r
, 0, &t
->usubfamily
);
1106 if ( ! t
->subfamily
&& (r
= findname(table
, n
, 3, 1, 0x0409, 2)) != -1)
1107 t
->subfamily
= nameExtract(table
, nTableSize
, r
, 1, &t
->usubfamily
);
1108 if ( ! t
->subfamily
)
1110 t
->subfamily
= strdup("");
1113 /* #i60349# sanity check psname
1114 * psname parctically has to be 7bit ascii and should not contains spaces
1115 * there is a class of broken fonts which do not fullfill that at all, so let's try
1116 * if the family name is 7bit ascii and take it instead if so
1119 for( i
= 0; t
->psname
[i
] != 0 && bPSNameOK
; i
++ )
1120 if( t
->psname
[ i
] < 33 || (t
->psname
[ i
] & 0x80) )
1121 bPSNameOK
= sal_False
;
1122 if( bPSNameOK
== sal_False
)
1124 sal_Bool bReplace
= sal_True
;
1125 /* check if family is a suitable replacement */
1126 if( t
->ufamily
&& t
->family
)
1128 for( i
= 0; t
->ufamily
[ i
] != 0 && bReplace
; i
++ )
1129 if( t
->ufamily
[ i
] < 33 || t
->ufamily
[ i
] > 127 )
1130 bReplace
= sal_False
;
1134 t
->psname
= strdup( t
->family
);
1141 CMAP_NOT_USABLE
= -1,
1142 CMAP_MS_Symbol
= 10,
1143 CMAP_MS_Unicode
= 11,
1144 CMAP_MS_ShiftJIS
= 12,
1147 CMAP_MS_Wansung
= 15,
1151 #define MISSING_GLYPH_INDEX 0
1154 * getGlyph[0246]() functions and friends are implemented by:
1155 * @author Manpreet Singh
1156 * getGlyph12() function and friends by:
1159 static sal_uInt32
getGlyph0(const sal_uInt8
* cmap
, sal_uInt32 c
) {
1161 return *(cmap
+ 6 + c
);
1163 return MISSING_GLYPH_INDEX
;
1167 typedef struct _subHeader2
{
1168 sal_uInt16 firstCode
;
1169 sal_uInt16 entryCount
;
1171 sal_uInt16 idRangeOffset
;
1174 static sal_uInt32
getGlyph2(const sal_uInt8
*cmap
, sal_uInt32 c
) {
1175 sal_uInt16
*CMAP2
= (sal_uInt16
*) cmap
;
1176 sal_uInt8 theHighByte
;
1178 sal_uInt8 theLowByte
;
1179 subHeader2
* subHeader2s
;
1180 sal_uInt16
* subHeader2Keys
;
1181 sal_uInt16 firstCode
;
1183 sal_uInt32 ToReturn
;
1185 theHighByte
= (sal_uInt8
)((c
>> 8) & 0x00ff);
1186 theLowByte
= (sal_uInt8
)(c
& 0x00ff);
1187 subHeader2Keys
= CMAP2
+ 3;
1188 subHeader2s
= (subHeader2
*)(subHeader2Keys
+ 256);
1189 k
= Int16FromMOTA(subHeader2Keys
[theHighByte
]) / 8;
1192 firstCode
= Int16FromMOTA(subHeader2s
[k
].firstCode
);
1193 if(theLowByte
>= firstCode
&& theLowByte
< (firstCode
+ Int16FromMOTA(subHeader2s
[k
].entryCount
))) {
1194 return *((&(subHeader2s
[0].idRangeOffset
))
1195 + (Int16FromMOTA(subHeader2s
[0].idRangeOffset
)/2) /* + offset */
1196 + theLowByte
/* + to_look */
1197 - Int16FromMOTA(subHeader2s
[0].firstCode
)
1200 return MISSING_GLYPH_INDEX
;
1203 firstCode
= Int16FromMOTA(subHeader2s
[k
].firstCode
);
1204 if(theLowByte
>= firstCode
&& theLowByte
< (firstCode
+ Int16FromMOTA(subHeader2s
[k
].entryCount
))) {
1205 ToReturn
= *((&(subHeader2s
[k
].idRangeOffset
))
1206 + (Int16FromMOTA(subHeader2s
[k
].idRangeOffset
)/2)
1207 + theLowByte
- firstCode
);
1209 return MISSING_GLYPH_INDEX
;
1211 ToReturn
+= Int16FromMOTA(subHeader2s
[k
].idDelta
);
1212 return (ToReturn
& 0xFFFF);
1215 return MISSING_GLYPH_INDEX
;
1218 return MISSING_GLYPH_INDEX
;
1222 static sal_uInt32
getGlyph6(const sal_uInt8
*cmap
, sal_uInt32 c
) {
1223 sal_uInt16 firstCode
, lastCode
, count
;
1224 sal_uInt16
*CMAP6
= (sal_uInt16
*) cmap
;
1226 firstCode
= Int16FromMOTA(*(CMAP6
+ 3));
1227 count
= Int16FromMOTA(*(CMAP6
+ 4));
1228 lastCode
= firstCode
+ count
- 1;
1229 if (c
< firstCode
|| c
> lastCode
) {
1230 return MISSING_GLYPH_INDEX
;
1232 return *((CMAP6
+ 5)/*glyphIdArray*/ + (c
- firstCode
));
1236 static sal_uInt16
GEbinsearch(sal_uInt16
*ar
, sal_uInt16 length
, sal_uInt16 toSearch
) {
1237 signed int low
, mid
, high
, lastfound
= 0xffff;
1239 if(length
== (sal_uInt16
)0 || length
== (sal_uInt16
)0xFFFF) {
1240 return (sal_uInt16
)0xFFFF;
1244 while(high
>= low
) {
1245 mid
= (high
+ low
)/2;
1246 res
= Int16FromMOTA(*(ar
+mid
));
1247 if(res
>= toSearch
) {
1254 return (sal_uInt16
)lastfound
;
1258 static sal_uInt32
getGlyph4(const sal_uInt8
*cmap
, sal_uInt32 c
) {
1261 sal_uInt16 segCount
;
1262 sal_uInt16
* startCode
;
1263 sal_uInt16
* endCode
;
1264 sal_uInt16
* idDelta
;
1265 /* sal_uInt16 * glyphIdArray; */
1266 sal_uInt16
* idRangeOffset
;
1267 /*sal_uInt16 * glyphIndexArray;*/
1268 sal_uInt16
*CMAP4
= (sal_uInt16
*) cmap
;
1269 /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */
1271 segCount
= Int16FromMOTA(*(CMAP4
+ 3))/2;
1272 endCode
= CMAP4
+ 7;
1273 i
= GEbinsearch(endCode
, segCount
, (sal_uInt16
)c
);
1275 if (i
== (sal_uInt16
) 0xFFFF) {
1276 return MISSING_GLYPH_INDEX
;
1278 startCode
= endCode
+ segCount
+ 1;
1280 if(Int16FromMOTA(startCode
[i
]) > c
) {
1281 return MISSING_GLYPH_INDEX
;
1283 idDelta
= startCode
+ segCount
;
1284 idRangeOffset
= idDelta
+ segCount
;
1285 /*glyphIndexArray = idRangeOffset + segCount;*/
1287 if(Int16FromMOTA(idRangeOffset
[i
]) != 0) {
1288 c
= Int16FromMOTA(*(&(idRangeOffset
[i
]) + (Int16FromMOTA(idRangeOffset
[i
])/2 + (c
- Int16FromMOTA(startCode
[i
])))));
1291 ToReturn
= (Int16FromMOTA(idDelta
[i
]) + c
) & 0xFFFF;
1295 static sal_uInt32
getGlyph12(const sal_uInt8
*pCmap
, sal_uInt32 cChar
) {
1296 const sal_uInt32
* pCMAP12
= (const sal_uInt32
*)pCmap
;
1297 int nLength
= Int32FromMOTA( pCMAP12
[1] );
1298 int nGroups
= Int32FromMOTA( pCMAP12
[3] );
1300 int nUpper
= nGroups
;
1302 if( nUpper
> (nLength
-16)/12 )
1303 nUpper
= (nLength
-16)/12;
1305 /* binary search in "segmented coverage" subtable */
1306 while( nLower
< nUpper
) {
1307 int nIndex
= (nLower
+ nUpper
) / 2;
1308 const sal_uInt32
* pEntry
= &pCMAP12
[ 4 + 3*nIndex
];
1309 sal_uInt32 cStart
= Int32FromMOTA( pEntry
[0] );
1310 sal_uInt32 cLast
= Int32FromMOTA( pEntry
[1] );
1311 if( cChar
< cStart
)
1313 else if( cChar
> cLast
)
1314 nLower
= nIndex
+ 1;
1315 else { /* found matching entry! */
1316 sal_uInt32 nGlyph
= Int32FromMOTA( pEntry
[2] );
1317 nGlyph
+= cChar
- cStart
;
1322 return MISSING_GLYPH_INDEX
;
1326 static void FindCmap(TrueTypeFont
*ttf
)
1328 const sal_uInt8
* table
= getTable(ttf
, O_cmap
);
1329 sal_uInt32 table_size
= getTableSize(ttf
, O_cmap
);
1330 sal_uInt16 ncmaps
= GetUInt16(table
, 2, 1);
1332 sal_uInt32 AppleUni
= 0; // Apple Unicode
1333 sal_uInt32 ThreeZero
= 0; /* MS Symbol */
1334 sal_uInt32 ThreeOne
= 0; /* MS UCS-2 */
1335 sal_uInt32 ThreeTwo
= 0; /* MS ShiftJIS */
1336 sal_uInt32 ThreeThree
= 0; /* MS Big5 */
1337 sal_uInt32 ThreeFour
= 0; /* MS PRC */
1338 sal_uInt32 ThreeFive
= 0; /* MS Wansung */
1339 sal_uInt32 ThreeSix
= 0; /* MS Johab */
1341 for (i
= 0; i
< ncmaps
; i
++) {
1343 sal_uInt16 pID
, eID
;
1345 /* sanity check, cmap entry must lie within table */
1346 if( i
*8+4 > table_size
)
1349 pID
= GetUInt16(table
, 4 + i
* 8, 1);
1350 eID
= GetUInt16(table
, 6 + i
* 8, 1);
1351 offset
= GetUInt32(table
, 8 + i
* 8, 1);
1353 /* sanity check, cmap must lie within file */
1354 if( (table
- ttf
->ptr
) + offset
> (sal_uInt32
)ttf
->fsize
)
1357 /* Unicode tables in Apple fonts */
1364 case 0: ThreeZero
= offset
; break;
1366 case 1: ThreeOne
= offset
; break;
1367 case 2: ThreeTwo
= offset
; break;
1368 case 3: ThreeThree
= offset
; break;
1369 case 4: ThreeFour
= offset
; break;
1370 case 5: ThreeFive
= offset
; break;
1371 case 6: ThreeSix
= offset
; break;
1376 // fall back to AppleUnicode if there are no ThreeOne/Threezero tables
1377 if( AppleUni
&& !ThreeZero
&& !ThreeOne
)
1378 ThreeOne
= AppleUni
;
1381 ttf
->cmapType
= CMAP_MS_Unicode
;
1382 ttf
->cmap
= table
+ ThreeOne
;
1383 } else if (ThreeTwo
) {
1384 ttf
->cmapType
= CMAP_MS_ShiftJIS
;
1385 ttf
->cmap
= table
+ ThreeTwo
;
1386 } else if (ThreeThree
) {
1387 ttf
->cmapType
= CMAP_MS_Big5
;
1388 ttf
->cmap
= table
+ ThreeThree
;
1389 } else if (ThreeFour
) {
1390 ttf
->cmapType
= CMAP_MS_PRC
;
1391 ttf
->cmap
= table
+ ThreeFour
;
1392 } else if (ThreeFive
) {
1393 ttf
->cmapType
= CMAP_MS_Wansung
;
1394 ttf
->cmap
= table
+ ThreeFive
;
1395 } else if (ThreeSix
) {
1396 ttf
->cmapType
= CMAP_MS_Johab
;
1397 ttf
->cmap
= table
+ ThreeSix
;
1398 } else if (ThreeZero
) {
1399 ttf
->cmapType
= CMAP_MS_Symbol
;
1400 ttf
->cmap
= table
+ ThreeZero
;
1402 ttf
->cmapType
= CMAP_NOT_USABLE
;
1406 if (ttf
->cmapType
!= CMAP_NOT_USABLE
) {
1407 switch (GetUInt16(ttf
->cmap
, 0, 1)) {
1408 case 0: ttf
->mapper
= getGlyph0
; break;
1409 case 2: ttf
->mapper
= getGlyph2
; break;
1410 case 4: ttf
->mapper
= getGlyph4
; break;
1411 case 6: ttf
->mapper
= getGlyph6
; break;
1412 case 12: ttf
->mapper
= getGlyph12
; break;
1414 #if OSL_DEBUG_LEVEL > 1
1415 /*- if the cmap table is really broken */
1416 printf("%s: %d is not a recognized cmap format.\n", ttf
->fname
, GetUInt16(ttf
->cmap
, 0, 1));
1418 ttf
->cmapType
= CMAP_NOT_USABLE
;
1425 static void GetKern(TrueTypeFont
*ttf
)
1427 const sal_uInt8
* table
= getTable(ttf
, O_kern
);
1428 const sal_uInt8
*ptr
;
1433 if (GetUInt16(table
, 0, 1) == 0) { /* Traditional Microsoft style table with sal_uInt16 version and nTables fields */
1434 ttf
->nkern
= GetUInt16(table
, 2, 1);
1435 ttf
->kerntables
= (const sal_uInt8
**)calloc(ttf
->nkern
, sizeof(sal_uInt8
*));
1436 assert(ttf
->kerntables
!= 0);
1437 ttf
->kerntype
= KT_MICROSOFT
;
1439 for( unsigned i
= 0; i
< ttf
->nkern
; ++i
) {
1440 ttf
->kerntables
[i
] = ptr
;
1441 ptr
+= GetUInt16(ptr
, 2, 1);
1443 if( ptr
> ttf
->ptr
+ttf
->fsize
)
1445 free( ttf
->kerntables
);
1452 if (GetUInt32(table
, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */
1453 ttf
->nkern
= GetUInt32(table
, 4, 1);
1454 ttf
->kerntables
= (const sal_uInt8
**)calloc(ttf
->nkern
, sizeof(sal_uInt8
*));
1455 assert(ttf
->kerntables
!= 0);
1456 ttf
->kerntype
= KT_APPLE_NEW
;
1458 for( unsigned i
= 0; i
< ttf
->nkern
; ++i
) {
1459 ttf
->kerntables
[i
] = ptr
;
1460 ptr
+= GetUInt32(ptr
, 0, 1);
1461 /* sanity check; there are some fonts that are broken in this regard */
1462 if( ptr
> ttf
->ptr
+ttf
->fsize
)
1464 free( ttf
->kerntables
);
1472 ttf
->kerntype
= KT_NONE
;
1473 ttf
->kerntables
= 0;
1478 /*- Public functions */ /*FOLD00*/
1480 int CountTTCFonts(const char* fname
)
1483 sal_uInt8 buffer
[12];
1484 FILE* fd
= fopen(fname
, "rb");
1486 if (fread(buffer
, 1, 12, fd
) == 12) {
1487 if(GetUInt32(buffer
, 0, 1) == T_ttcf
)
1488 nFonts
= GetUInt32(buffer
, 8, 1);
1495 static void allocTrueTypeFont( TrueTypeFont
** ttf
)
1497 *ttf
= (TrueTypeFont
*)calloc(1,sizeof(TrueTypeFont
));
1504 (*ttf
)->nglyphs
= 0xFFFFFFFF;
1505 (*ttf
)->pGSubstitution
= 0;
1509 /* forward declariotn for the two entry points to use*/
1510 static int doOpenTTFont( sal_uInt32 facenum
, TrueTypeFont
* t
);
1513 int OpenTTFontFile( const char* fname
, sal_uInt32 facenum
, TrueTypeFont
** ttf
)
1518 if (!fname
|| !*fname
) return SF_BADFILE
;
1520 allocTrueTypeFont( ttf
);
1524 (*ttf
)->fname
= strdup(fname
);
1525 if( ! (*ttf
)->fname
)
1531 fd
= open(fname
, O_RDONLY
);
1538 if (fstat(fd
, &st
) == -1) {
1543 (*ttf
)->fsize
= st
.st_size
;
1545 /* On Mac OS, most likely will happen if a Mac user renames a font file
1546 * to be .ttf when its really a Mac resource-based font.
1547 * Size will be 0, but fonts smaller than 4 bytes would be broken anyway.
1549 if ((*ttf
)->fsize
== 0) {
1554 if (((*ttf
)->ptr
= (sal_uInt8
*) mmap(0, (*ttf
)->fsize
, PROT_READ
, MAP_SHARED
, fd
, 0)) == MAP_FAILED
) {
1560 return doOpenTTFont( facenum
, *ttf
);
1563 if (fd
!= -1) close(fd
);
1564 /*- t and t->fname have been allocated! */
1565 free((*ttf
)->fname
);
1572 int OpenTTFontBuffer(const void* pBuffer
, sal_uInt32 nLen
, sal_uInt32 facenum
, TrueTypeFont
** ttf
)
1574 allocTrueTypeFont( ttf
);
1578 (*ttf
)->fname
= NULL
;
1579 (*ttf
)->fsize
= nLen
;
1580 (*ttf
)->ptr
= (sal_uInt8
*)pBuffer
;
1582 return doOpenTTFont( facenum
, *ttf
);
1585 static int doOpenTTFont( sal_uInt32 facenum
, TrueTypeFont
* t
)
1588 sal_uInt32 length
, tag
;
1589 sal_uInt32 tdoffset
= 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */
1592 sal_uInt32 version
= GetInt32(t
->ptr
, 0, 1);
1594 if ((version
== 0x00010000) || (version
== T_true
)) {
1596 } else if (version
== T_otto
) { /* PS-OpenType font */
1598 } else if (version
== T_ttcf
) { /* TrueType collection */
1599 if (GetUInt32(t
->ptr
, 4, 1) != 0x00010000) {
1603 if (facenum
>= GetUInt32(t
->ptr
, 8, 1)) {
1607 tdoffset
= GetUInt32(t
->ptr
, 12 + 4 * facenum
, 1);
1614 t
->tag
= TTFontClassTag
;
1616 t
->ntables
= GetUInt16(t
->ptr
+ tdoffset
, 4, 1);
1617 if( t
->ntables
>= 128 )
1620 t
->tables
= (const sal_uInt8
**)calloc(NUM_TAGS
, sizeof(sal_uInt8
*));
1621 assert(t
->tables
!= 0);
1622 t
->tlens
= (sal_uInt32
*)calloc(NUM_TAGS
, sizeof(sal_uInt32
));
1623 assert(t
->tlens
!= 0);
1625 /* parse the tables */
1626 for (i
=0; i
<(int)t
->ntables
; i
++) {
1628 tag
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
, 1);
1630 case T_maxp
: nIndex
= O_maxp
; break;
1631 case T_glyf
: nIndex
= O_glyf
; break;
1632 case T_head
: nIndex
= O_head
; break;
1633 case T_loca
: nIndex
= O_loca
; break;
1634 case T_name
: nIndex
= O_name
; break;
1635 case T_hhea
: nIndex
= O_hhea
; break;
1636 case T_hmtx
: nIndex
= O_hmtx
; break;
1637 case T_cmap
: nIndex
= O_cmap
; break;
1638 case T_vhea
: nIndex
= O_vhea
; break;
1639 case T_vmtx
: nIndex
= O_vmtx
; break;
1640 case T_OS2
: nIndex
= O_OS2
; break;
1641 case T_post
: nIndex
= O_post
; break;
1642 case T_kern
: nIndex
= O_kern
; break;
1643 case T_cvt
: nIndex
= O_cvt
; break;
1644 case T_prep
: nIndex
= O_prep
; break;
1645 case T_fpgm
: nIndex
= O_fpgm
; break;
1646 case T_gsub
: nIndex
= O_gsub
; break;
1647 case T_CFF
: nIndex
= O_CFF
; break;
1648 default: nIndex
= -1; break;
1651 sal_uInt32 nTableOffset
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
+ 8, 1);
1652 length
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
+ 12, 1);
1653 t
->tables
[nIndex
] = t
->ptr
+ nTableOffset
;
1654 t
->tlens
[nIndex
] = length
;
1658 /* Fixup offsets when only a TTC extract was provided */
1659 if( facenum
== (sal_uInt32
)~0 ) {
1660 sal_uInt8
* pHead
= (sal_uInt8
*)t
->tables
[O_head
];
1663 /* limit Head candidate to TTC extract's limits */
1664 if( pHead
> t
->ptr
+ (t
->fsize
- 54) )
1665 pHead
= t
->ptr
+ (t
->fsize
- 54);
1666 /* TODO: find better method than searching head table's magic */
1667 sal_uInt8
* p
= NULL
;
1668 for( p
= pHead
+ 12; p
> t
->ptr
; --p
) {
1669 if( p
[0]==0x5F && p
[1]==0x0F && p
[2]==0x3C && p
[3]==0xF5 ) {
1670 int nDelta
= (pHead
+ 12) - p
;
1672 for( int j
= 0; j
< NUM_TAGS
; ++j
)
1674 *(char**)&t
->tables
[j
] -= nDelta
;
1682 /* Check the table offsets after TTC correction */
1683 for (i
=0; i
<NUM_TAGS
; i
++) {
1684 /* sanity check: table must lay completely within the file
1685 * at this point one could check the checksum of all contained
1686 * tables, but this would be quite time intensive.
1687 * Try to fix tables, so we can cope with minor problems.
1690 if( (sal_uInt8
*)t
->tables
[i
] < t
->ptr
)
1692 #if OSL_DEBUG_LEVEL > 1
1694 fprintf( stderr
, "font file %s has bad table offset %" SAL_PRI_PTRDIFFT
"d (tagnum=%d)\n", t
->fname
, (sal_uInt8
*)t
->tables
[i
]-t
->ptr
, i
);
1697 t
->tables
[i
] = NULL
;
1699 else if( (sal_uInt8
*)t
->tables
[i
] + t
->tlens
[i
] > t
->ptr
+ t
->fsize
)
1701 int nMaxLen
= (t
->ptr
+ t
->fsize
) - (sal_uInt8
*)t
->tables
[i
];
1704 t
->tlens
[i
] = nMaxLen
;
1705 #if OSL_DEBUG_LEVEL > 1
1706 fprintf( stderr
, "font file %s has too big table (tagnum=%d)\n", t
->fname
, i
);
1711 /* At this point TrueTypeFont is constructed, now need to verify the font format
1712 and read the basic font properties */
1714 /* The following tables are absolutely required:
1715 * maxp, head, name, cmap
1718 if( !(getTable(t
, O_maxp
) && getTable(t
, O_head
) && getTable(t
, O_name
) && getTable(t
, O_cmap
)) ) {
1723 const sal_uInt8
* table
= getTable(t
, O_maxp
);
1724 t
->nglyphs
= GetUInt16(table
, 4, 1);
1726 table
= getTable(t
, O_head
);
1727 t
->unitsPerEm
= GetUInt16(table
, 18, 1);
1728 indexfmt
= GetInt16(table
, 50, 1);
1730 if( ((indexfmt
!= 0) && (indexfmt
!= 1)) || (t
->unitsPerEm
<= 0) ) {
1735 if( getTable(t
, O_glyf
) && getTable(t
, O_loca
) ) /* TTF or TTF-OpenType */
1737 int k
= (getTableSize(t
, O_loca
) / (indexfmt
? 4 : 2)) - 1;
1738 if( k
< (int)t
->nglyphs
) /* Hack for broken Chinese fonts */
1741 table
= getTable(t
, O_loca
);
1742 t
->goffsets
= (sal_uInt32
*) calloc(1+t
->nglyphs
, sizeof(sal_uInt32
));
1743 assert(t
->goffsets
!= 0);
1745 for( i
= 0; i
<= (int)t
->nglyphs
; ++i
)
1746 t
->goffsets
[i
] = indexfmt
? GetUInt32(table
, i
<< 2, 1) : (sal_uInt32
)GetUInt16(table
, i
<< 1, 1) << 1;
1747 } else if( getTable(t
, O_CFF
) ) { /* PS-OpenType */
1748 t
->goffsets
= (sal_uInt32
*) calloc(1+t
->nglyphs
, sizeof(sal_uInt32
));
1749 /* TODO: implement to get subsetting */
1750 assert(t
->goffsets
!= 0);
1756 table
= getTable(t
, O_hhea
);
1757 t
->numberOfHMetrics
= (table
!= 0) ? GetUInt16(table
, 34, 1) : 0;
1759 table
= getTable(t
, O_vhea
);
1760 t
->numOfLongVerMetrics
= (table
!= 0) ? GetUInt16(table
, 34, 1) : 0;
1765 ReadGSUB( t
, 0, 0 );
1770 void CloseTTFont(TrueTypeFont
*ttf
) /*FOLD01*/
1774 munmap((char *) ttf
->ptr
, ttf
->fsize
);
1777 free(ttf
->goffsets
);
1781 free( ttf
->ufamily
);
1782 free(ttf
->subfamily
);
1783 if( ttf
->usubfamily
)
1784 free( ttf
->usubfamily
);
1787 free(ttf
->kerntables
);
1795 int GetTTGlyphPoints(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
)
1797 return GetTTGlyphOutline(ttf
, glyphID
, pointArray
, 0, 0);
1800 int GetTTGlyphComponents(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, std::vector
< sal_uInt32
>& glyphlist
)
1804 if( glyphID
>= ttf
->nglyphs
)
1807 const sal_uInt8
* glyf
= getTable(ttf
, O_glyf
);
1808 const sal_uInt8
* ptr
= glyf
+ ttf
->goffsets
[glyphID
];
1810 glyphlist
.push_back( glyphID
);
1812 if (GetInt16(ptr
, 0, 1) == -1) {
1813 sal_uInt16 flags
, index
;
1816 flags
= GetUInt16(ptr
, 0, 1);
1817 index
= GetUInt16(ptr
, 2, 1);
1820 n
+= GetTTGlyphComponents(ttf
, index
, glyphlist
);
1822 if (flags
& ARG_1_AND_2_ARE_WORDS
) {
1828 if (flags
& WE_HAVE_A_SCALE
) {
1830 } else if (flags
& WE_HAVE_AN_X_AND_Y_SCALE
) {
1832 } else if (flags
& WE_HAVE_A_TWO_BY_TWO
) {
1835 } while (flags
& MORE_COMPONENTS
);
1842 int CreateT3FromTTGlyphs(TrueTypeFont
*ttf
, FILE *outf
, const char *fname
, /*FOLD00*/
1843 sal_uInt16
*glyphArray
, sal_uInt8
*encoding
, int nGlyphs
,
1847 PSPathElement
*path
;
1849 const sal_uInt8
* table
= getTable(ttf
, O_head
);
1850 TTGlyphMetrics metrics
;
1851 int UPEm
= ttf
->unitsPerEm
;
1853 const char *h01
= "%%!PS-AdobeFont-%d.%d-%d.%d\n";
1854 const char *h02
= "%% Creator: %s %s %s\n";
1855 const char *h09
= "%% Original font name: %s\n";
1859 "/PaintType 0 def\n"
1861 "/StrokeWidth 0 def\n";
1863 const char *h11
= "/FontName (%s) cvn def\n";
1866 const char *h12 = "%/UniqueID %d def\n";
1868 const char *h13
= "/FontMatrix [.001 0 0 .001 0 0] def\n";
1869 const char *h14
= "/FontBBox [%d %d %d %d] def\n";
1872 "/Encoding 256 array def\n"
1873 " 0 1 255 {Encoding exch /.notdef put} for\n";
1875 const char *h16
= " Encoding %d /glyph%d put\n";
1876 const char *h17
= "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n";
1878 const char *h30
= "/CharProcs %d dict def\n";
1879 const char *h31
= " CharProcs begin\n";
1880 const char *h32
= " /.notdef {} def\n";
1881 const char *h33
= " /glyph%d {\n";
1882 const char *h34
= " } bind def\n";
1883 const char *h35
= " end\n";
1887 " exch /CharProcs get exch\n"
1888 " 2 copy known not\n"
1889 " {pop /.notdef} if\n"
1893 " 1 index /Encoding get exch get\n"
1894 " 1 index /BuildGlyph get exec\n"
1896 "currentdict end\n";
1898 const char *h41
= "(%s) cvn exch definefont pop\n";
1901 if (!((nGlyphs
> 0) && (nGlyphs
<= 256))) return SF_GLYPHNUM
;
1902 if (!glyphArray
) return SF_BADARG
;
1903 if (!fname
) fname
= ttf
->psname
;
1905 fprintf(outf
, h01
, GetInt16(table
, 0, 1), GetUInt16(table
, 2, 1), GetInt16(table
, 4, 1), GetUInt16(table
, 6, 1));
1906 fprintf(outf
, h02
, modname
, modver
, modextra
);
1907 fprintf(outf
, h09
, ttf
->psname
);
1909 fprintf(outf
, "%s", h10
);
1910 fprintf(outf
, h11
, fname
);
1911 /* fprintf(outf, h12, 4000000); */
1914 * 103 0 0 C1 C2 C3 C4
1915 * C1 - CRC-32 of the entire source TrueType font
1916 * C2 - number of glyphs in the subset
1917 * C3 - CRC-32 of the glyph array
1918 * C4 - CRC-32 of the encoding array
1920 * All CRC-32 numbers are presented as hexadecimal numbers
1923 fprintf(outf
, h17
, rtl_crc32(0, ttf
->ptr
, ttf
->fsize
), nGlyphs
, rtl_crc32(0, glyphArray
, nGlyphs
* 2), rtl_crc32(0, encoding
, nGlyphs
));
1924 fprintf(outf
, "%s", h13
);
1925 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)));
1926 fprintf(outf
, "%s", h15
);
1928 for (i
= 0; i
< nGlyphs
; i
++) {
1929 fprintf(outf
, h16
, encoding
[i
], i
);
1932 fprintf(outf
, h30
, nGlyphs
+1);
1933 fprintf(outf
, "%s", h31
);
1934 fprintf(outf
, "%s", h32
);
1936 for (i
= 0; i
< nGlyphs
; i
++) {
1937 fprintf(outf
, h33
, i
);
1938 r
= GetTTGlyphOutline(ttf
, glyphArray
[i
] < ttf
->nglyphs
? glyphArray
[i
] : 0, &pa
, &metrics
, 0);
1941 n
= BSplineToPSPath(pa
, r
, &path
);
1943 n
= 0; /* glyph might have zero contours but valid metrics ??? */
1945 if (r
< 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */
1949 fprintf(outf
, "\t%d %d %d %d %d %d setcachedevice\n",
1950 wmode
== 0 ? XUnits(UPEm
, metrics
.aw
) : 0,
1951 wmode
== 0 ? 0 : -XUnits(UPEm
, metrics
.ah
),
1952 XUnits(UPEm
, metrics
.xMin
),
1953 XUnits(UPEm
, metrics
.yMin
),
1954 XUnits(UPEm
, metrics
.xMax
),
1955 XUnits(UPEm
, metrics
.yMax
));
1957 for (j
= 0; j
< n
; j
++)
1959 switch (path
[j
].type
)
1962 fprintf(outf
, "\t%d %d moveto\n", XUnits(UPEm
, path
[j
].x1
), XUnits(UPEm
, path
[j
].y1
));
1966 fprintf(outf
, "\t%d %d lineto\n", XUnits(UPEm
, path
[j
].x1
), XUnits(UPEm
, path
[j
].y1
));
1970 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
));
1974 fprintf(outf
, "\tclosepath\n");
1980 if (n
> 0) fprintf(outf
, "\tfill\n"); /* if glyph is not a whitespace character */
1982 fprintf(outf
, "%s", h34
);
1987 fprintf(outf
, "%s", h35
);
1989 fprintf(outf
, "%s", h40
);
1990 fprintf(outf
, h41
, fname
);
1997 int CreateTTFromTTGlyphs(TrueTypeFont
*ttf
,
1999 sal_uInt16
*glyphArray
,
2000 sal_uInt8
*encoding
,
2006 TrueTypeCreator
*ttcr
;
2007 TrueTypeTable
*head
=0, *hhea
=0, *maxp
=0, *cvt
=0, *prep
=0, *glyf
=0, *fpgm
=0, *cmap
=0, *name
=0, *post
= 0, *os2
= 0;
2011 TrueTypeCreatorNewEmpty(T_true
, &ttcr
);
2015 if (flags
& TTCF_AutoName
) {
2016 /* not implemented yet
2019 int n = GetTTNameRecords(ttf, &names);
2020 int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
2022 sal_uInt8 suffix[32];
2023 sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2);
2024 sal_uInt32 c2 = crc32(encoding, nGlyphs);
2026 snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs);
2028 name = TrueTypeTableNew_name(0, 0);
2029 for (i = 0; i < n; i++) {
2030 if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) {
2032 memcpy(newname, names+i, sizeof(NameRecord));
2033 newname.slen = name[i].slen + strlen(suffix);
2035 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'};
2036 NameRecord n1
= {1, 0, 0, 6, 14, (sal_uInt8
*)"TrueTypeSubset"};
2037 NameRecord n2
= {3, 1, 1033, 6, 28, 0};
2038 n2
.sptr
= (sal_uInt8
*) ptr
;
2039 name
= TrueTypeTableNew_name(0, 0);
2043 if (nNameRecs
== 0) {
2045 int n
= GetTTNameRecords(ttf
, &names
);
2046 name
= TrueTypeTableNew_name(n
, names
);
2047 DisposeNameRecords(names
, n
);
2049 name
= TrueTypeTableNew_name(nNameRecs
, nr
);
2054 maxp
= TrueTypeTableNew_maxp(getTable(ttf
, O_maxp
), getTableSize(ttf
, O_maxp
));
2057 const sal_uInt8
* p
= getTable(ttf
, O_hhea
);
2059 hhea
= TrueTypeTableNew_hhea(GetUInt16(p
, 4, 1), GetUInt16(p
, 6, 1), GetUInt16(p
, 8, 1), GetUInt16(p
, 18, 1), GetUInt16(p
, 20, 1));
2061 hhea
= TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2066 p
= getTable(ttf
, O_head
);
2068 head
= TrueTypeTableNew_head(GetUInt32(p
, 4, 1),
2069 GetUInt16(p
, 16, 1),
2070 GetUInt16(p
, 18, 1),
2072 GetUInt16(p
, 44, 1),
2073 GetUInt16(p
, 46, 1),
2074 GetInt16(p
, 48, 1));
2079 glyf
= TrueTypeTableNew_glyf();
2080 sal_uInt32
* gID
= (sal_uInt32
*)scalloc(nGlyphs
, sizeof(sal_uInt32
));
2082 for (i
= 0; i
< nGlyphs
; i
++) {
2083 gID
[i
] = glyfAdd(glyf
, GetTTRawGlyphData(ttf
, glyphArray
[i
]), ttf
);
2087 cmap
= TrueTypeTableNew_cmap();
2089 for (i
=0; i
< nGlyphs
; i
++) {
2090 cmapAdd(cmap
, 0x010000, encoding
[i
], gID
[i
]);
2094 if ((p
= getTable(ttf
, O_cvt
)) != 0) {
2095 cvt
= TrueTypeTableNew(T_cvt
, getTableSize(ttf
, O_cvt
), p
);
2099 if ((p
= getTable(ttf
, O_prep
)) != 0) {
2100 prep
= TrueTypeTableNew(T_prep
, getTableSize(ttf
, O_prep
), p
);
2104 if ((p
= getTable(ttf
, O_fpgm
)) != 0) {
2105 fpgm
= TrueTypeTableNew(T_fpgm
, getTableSize(ttf
, O_fpgm
), p
);
2109 if ((p
= getTable(ttf
, O_post
)) != 0) {
2110 post
= TrueTypeTableNew_post(0x00030000,
2113 GetUInt16(p
, 10, 1),
2114 GetUInt16(p
, 12, 1));
2116 post
= TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
2119 if (flags
& TTCF_IncludeOS2
) {
2120 if ((p
= getTable(ttf
, O_OS2
)) != 0) {
2121 os2
= TrueTypeTableNew(T_OS2
, getTableSize(ttf
, O_OS2
), p
);
2125 AddTable(ttcr
, name
); AddTable(ttcr
, maxp
); AddTable(ttcr
, hhea
);
2126 AddTable(ttcr
, head
); AddTable(ttcr
, glyf
); AddTable(ttcr
, cmap
);
2127 AddTable(ttcr
, cvt
); AddTable(ttcr
, prep
); AddTable(ttcr
, fpgm
);
2128 AddTable(ttcr
, post
); AddTable(ttcr
, os2
);
2130 if ((res
= StreamToFile(ttcr
, fname
)) != SF_OK
) {
2131 #if OSL_DEBUG_LEVEL > 1
2132 fprintf(stderr
, "StreamToFile: error code: %d.\n", res
);
2136 TrueTypeCreatorDispose(ttcr
);
2145 static GlyphOffsets
*GlyphOffsetsNew(sal_uInt8
*sfntP
)
2147 GlyphOffsets
* res
= (GlyphOffsets
*)smalloc(sizeof(GlyphOffsets
));
2148 sal_uInt8
*loca
= NULL
;
2149 sal_uInt16 i
, numTables
= GetUInt16(sfntP
, 4, 1);
2150 sal_uInt32 locaLen
= 0;
2151 sal_Int16 indexToLocFormat
= 0;
2153 for (i
= 0; i
< numTables
; i
++) {
2154 sal_uInt32 tag
= GetUInt32(sfntP
+ 12, 16 * i
, 1);
2155 sal_uInt32 off
= GetUInt32(sfntP
+ 12, 16 * i
+ 8, 1);
2156 sal_uInt32 len
= GetUInt32(sfntP
+ 12, 16 * i
+ 12, 1);
2158 if (tag
== T_loca
) {
2161 } else if (tag
== T_head
) {
2162 indexToLocFormat
= GetInt16(sfntP
+ off
, 50, 1);
2166 res
->nGlyphs
= locaLen
/ ((indexToLocFormat
== 1) ? 4 : 2);
2167 assert(res
->nGlyphs
!= 0);
2168 res
->offs
= (sal_uInt32
*)scalloc(res
->nGlyphs
, sizeof(sal_uInt32
));
2170 for (i
= 0; i
< res
->nGlyphs
; i
++) {
2171 if (indexToLocFormat
== 1) {
2172 res
->offs
[i
] = GetUInt32(loca
, i
* 4, 1);
2174 res
->offs
[i
] = GetUInt16(loca
, i
* 2, 1) << 1;
2180 static void GlyphOffsetsDispose(GlyphOffsets
*_this
)
2188 static void DumpSfnts(FILE *outf
, sal_uInt8
*sfntP
)
2190 HexFmt
*h
= HexFmtNew(outf
);
2191 sal_uInt16 i
, numTables
= GetUInt16(sfntP
, 4, 1);
2192 GlyphOffsets
*go
= GlyphOffsetsNew(sfntP
);
2193 sal_uInt8 pad
[] = {0,0,0,0}; /* zeroes */
2195 assert(numTables
<= 9); /* Type42 has 9 required tables */
2197 sal_uInt32
* offs
= (sal_uInt32
*)scalloc(numTables
, sizeof(sal_uInt32
));
2198 // sal_uInt32* lens = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32));
2200 fputs("/sfnts [", outf
);
2201 HexFmtOpenString(h
);
2202 HexFmtBlockWrite(h
, sfntP
, 12); /* stream out the Offset Table */
2203 HexFmtBlockWrite(h
, sfntP
+12, 16 * numTables
); /* stream out the Table Directory */
2205 for (i
=0; i
<numTables
; i
++) {
2206 sal_uInt32 tag
= GetUInt32(sfntP
+ 12, 16 * i
, 1);
2207 sal_uInt32 off
= GetUInt32(sfntP
+ 12, 16 * i
+ 8, 1);
2208 sal_uInt32 len
= GetUInt32(sfntP
+ 12, 16 * i
+ 12, 1);
2210 if (tag
!= T_glyf
) {
2211 HexFmtBlockWrite(h
, sfntP
+ off
, len
);
2213 sal_uInt8
*glyf
= sfntP
+ off
;
2215 for (j
= 0; j
< go
->nGlyphs
- 1; j
++) {
2217 l
= go
->offs
[j
+ 1] - o
;
2218 HexFmtBlockWrite(h
, glyf
+ o
, l
);
2221 HexFmtBlockWrite(h
, pad
, (4 - (len
& 3)) & 3);
2223 HexFmtCloseString(h
);
2224 fputs("] def\n", outf
);
2225 GlyphOffsetsDispose(go
);
2231 int CreateT42FromTTGlyphs(TrueTypeFont
*ttf
,
2234 sal_uInt16
*glyphArray
,
2235 sal_uInt8
*encoding
,
2238 TrueTypeCreator
*ttcr
;
2239 TrueTypeTable
*head
=0, *hhea
=0, *maxp
=0, *cvt
=0, *prep
=0, *glyf
=0, *fpgm
=0;
2243 sal_uInt32 ver
, rev
;
2247 int UPEm
= ttf
->unitsPerEm
;
2249 if (nGlyphs
>= 256) return SF_GLYPHNUM
;
2251 assert(psname
!= 0);
2253 TrueTypeCreatorNewEmpty(T_true
, &ttcr
);
2256 const sal_uInt8
* p
= getTable(ttf
, O_head
);
2257 const sal_uInt8
* headP
= p
;
2259 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));
2260 ver
= GetUInt32(p
, 0, 1);
2261 rev
= GetUInt32(p
, 4, 1);
2264 p
= getTable(ttf
, O_hhea
);
2266 hhea
= TrueTypeTableNew_hhea(GetUInt16(p
, 4, 1), GetUInt16(p
, 6, 1), GetUInt16(p
, 8, 1), GetUInt16(p
, 18, 1), GetUInt16(p
, 20, 1));
2268 hhea
= TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2272 maxp
= TrueTypeTableNew_maxp(getTable(ttf
, O_maxp
), getTableSize(ttf
, O_maxp
));
2275 if ((p
= getTable(ttf
, O_cvt
)) != 0) {
2276 cvt
= TrueTypeTableNew(T_cvt
, getTableSize(ttf
, O_cvt
), p
);
2280 if ((p
= getTable(ttf
, O_prep
)) != 0) {
2281 prep
= TrueTypeTableNew(T_prep
, getTableSize(ttf
, O_prep
), p
);
2285 if ((p
= getTable(ttf
, O_fpgm
)) != 0) {
2286 fpgm
= TrueTypeTableNew(T_fpgm
, getTableSize(ttf
, O_fpgm
), p
);
2290 glyf
= TrueTypeTableNew_glyf();
2291 sal_uInt16
* gID
= (sal_uInt16
*)scalloc(nGlyphs
, sizeof(sal_uInt32
));
2293 for (i
= 0; i
< nGlyphs
; i
++) {
2294 gID
[i
] = (sal_uInt16
)glyfAdd(glyf
, GetTTRawGlyphData(ttf
, glyphArray
[i
]), ttf
);
2297 AddTable(ttcr
, head
); AddTable(ttcr
, hhea
); AddTable(ttcr
, maxp
); AddTable(ttcr
, cvt
);
2298 AddTable(ttcr
, prep
); AddTable(ttcr
, glyf
); AddTable(ttcr
, fpgm
);
2300 if ((res
= StreamToMemory(ttcr
, &sfntP
, &sfntLen
)) != SF_OK
) {
2301 TrueTypeCreatorDispose(ttcr
);
2306 fprintf(outf
, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver
>>16), (int)(ver
& 0xFFFF), (int)(rev
>>16), (int)(rev
& 0xFFFF));
2307 fprintf(outf
, "%%%%Creator: %s %s %s\n", modname
, modver
, modextra
);
2308 fprintf(outf
, "%%- Font subset generated from a source font file: '%s'\n", ttf
->fname
);
2309 fprintf(outf
, "%%- Original font name: %s\n", ttf
->psname
);
2310 fprintf(outf
, "%%- Original font family: %s\n", ttf
->family
);
2311 fprintf(outf
, "%%- Original font sub-family: %s\n", ttf
->subfamily
);
2312 fprintf(outf
, "11 dict begin\n");
2313 fprintf(outf
, "/FontName (%s) cvn def\n", psname
);
2314 fprintf(outf
, "/PaintType 0 def\n");
2315 fprintf(outf
, "/FontMatrix [1 0 0 1 0 0] def\n");
2316 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)));
2317 fprintf(outf
, "/FontType 42 def\n");
2318 fprintf(outf
, "/Encoding 256 array def\n");
2319 fprintf(outf
, " 0 1 255 {Encoding exch /.notdef put} for\n");
2321 for (i
= 1; i
<nGlyphs
; i
++) {
2322 fprintf(outf
, "Encoding %d /glyph%d put\n", encoding
[i
], gID
[i
]);
2324 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
));
2326 DumpSfnts(outf
, sfntP
);
2328 /* dump charstrings */
2329 fprintf(outf
, "/CharStrings %d dict dup begin\n", nGlyphs
);
2330 fprintf(outf
, "/.notdef 0 def\n");
2331 for (i
= 1; i
< (int)glyfCount(glyf
); i
++) {
2332 fprintf(outf
,"/glyph%d %d def\n", i
, i
);
2334 fprintf(outf
, "end readonly def\n");
2336 fprintf(outf
, "FontName currentdict end definefont pop\n");
2337 TrueTypeCreatorDispose(ttcr
);
2346 int MapString(TrueTypeFont
*ttf
, sal_uInt16
*str
, int nchars
, sal_uInt16
*glyphArray
, int bvertical
)
2351 if (ttf
->cmapType
== CMAP_NOT_USABLE
) return -1;
2352 if (!nchars
) return 0;
2354 if (glyphArray
== 0) {
2360 switch (ttf
->cmapType
) {
2361 case CMAP_MS_Symbol
:
2362 if( ttf
->mapper
== getGlyph0
) {
2364 for( i
= 0; i
< nchars
; i
++ ) {
2366 if( ( aChar
& 0xf000 ) == 0xf000 )
2371 else if( glyphArray
)
2372 memcpy(glyphArray
, str
, nchars
* 2);
2375 case CMAP_MS_Unicode
:
2376 if (glyphArray
!= 0) {
2377 memcpy(glyphArray
, str
, nchars
* 2);
2381 case CMAP_MS_ShiftJIS
: TranslateString12(str
, cp
, nchars
); break;
2382 case CMAP_MS_Big5
: TranslateString13(str
, cp
, nchars
); break;
2383 case CMAP_MS_PRC
: TranslateString14(str
, cp
, nchars
); break;
2384 case CMAP_MS_Wansung
: TranslateString15(str
, cp
, nchars
); break;
2385 case CMAP_MS_Johab
: TranslateString16(str
, cp
, nchars
); break;
2388 for (i
= 0; i
< nchars
; i
++) {
2389 cp
[i
] = (sal_uInt16
)ttf
->mapper(ttf
->cmap
, cp
[i
]);
2390 if (cp
[i
]!=0 && bvertical
!=0)
2391 cp
[i
] = (sal_uInt16
)UseGSUB(ttf
,cp
[i
],bvertical
);
2396 sal_uInt16
MapChar(TrueTypeFont
*ttf
, sal_uInt16 ch
, int bvertical
)
2398 switch (ttf
->cmapType
) {
2399 case CMAP_MS_Symbol
:
2401 if( ttf
->mapper
== getGlyph0
&& ( ch
& 0xf000 ) == 0xf000 )
2403 return (sal_uInt16
)ttf
->mapper(ttf
->cmap
, ch
);
2405 case CMAP_MS_Unicode
: break;
2406 case CMAP_MS_ShiftJIS
: ch
= TranslateChar12(ch
); break;
2407 case CMAP_MS_Big5
: ch
= TranslateChar13(ch
); break;
2408 case CMAP_MS_PRC
: ch
= TranslateChar14(ch
); break;
2409 case CMAP_MS_Wansung
: ch
= TranslateChar15(ch
); break;
2410 case CMAP_MS_Johab
: ch
= TranslateChar16(ch
); break;
2413 ch
= (sal_uInt16
)ttf
->mapper(ttf
->cmap
, ch
);
2414 if (ch
!=0 && bvertical
!=0)
2415 ch
= (sal_uInt16
)UseGSUB(ttf
,ch
,bvertical
);
2419 int DoesVerticalSubstitution( TrueTypeFont
*ttf
, int bvertical
)
2423 nRet
= HasVerticalGSUB( ttf
);
2429 int GetTTGlyphCount( TrueTypeFont
* ttf
)
2431 return ttf
->nglyphs
;
2434 bool GetSfntTable( TrueTypeFont
* ttf
, int nSubtableIndex
,
2435 const sal_uInt8
** ppRawBytes
, int* pRawLength
)
2437 if( (nSubtableIndex
< 0) || (nSubtableIndex
>= NUM_TAGS
) )
2439 *pRawLength
= ttf
->tlens
[ nSubtableIndex
];
2440 *ppRawBytes
= ttf
->tables
[ nSubtableIndex
];
2441 bool bOk
= (*pRawLength
> 0) && (*ppRawBytes
!= NULL
);
2445 TTSimpleGlyphMetrics
*GetTTSimpleGlyphMetrics(TrueTypeFont
*ttf
, sal_uInt16
*glyphArray
, int nGlyphs
, int mode
)
2447 const sal_uInt8
* pTable
;
2452 n
= ttf
->numberOfHMetrics
;
2453 pTable
= getTable( ttf
, O_hmtx
);
2454 nTableSize
= getTableSize( ttf
, O_hmtx
);
2456 n
= ttf
->numOfLongVerMetrics
;
2457 pTable
= getTable( ttf
, O_vmtx
);
2458 nTableSize
= getTableSize( ttf
, O_vmtx
);
2461 if (!nGlyphs
|| !glyphArray
) return 0; /* invalid parameters */
2462 if (!n
|| !pTable
) return 0; /* the font does not contain the requested metrics */
2464 TTSimpleGlyphMetrics
* res
= (TTSimpleGlyphMetrics
*)calloc(nGlyphs
, sizeof(TTSimpleGlyphMetrics
));
2467 const int UPEm
= ttf
->unitsPerEm
;
2468 for( int i
= 0; i
< nGlyphs
; ++i
) {
2469 int nAdvOffset
, nLsbOffset
;
2470 sal_uInt16 glyphID
= glyphArray
[i
];
2473 nAdvOffset
= 4 * glyphID
;
2474 nLsbOffset
= nAdvOffset
+ 2;
2476 nAdvOffset
= 4 * (n
- 1);
2477 if( glyphID
< ttf
->nglyphs
)
2478 nLsbOffset
= 4 * n
+ 2 * (glyphID
- n
);
2479 else /* font is broken -> use lsb of last hmetrics */
2480 nLsbOffset
= nAdvOffset
+ 2;
2483 if( nAdvOffset
>= nTableSize
)
2484 res
[i
].adv
= 0; /* better than a crash for buggy fonts */
2486 res
[i
].adv
= static_cast<sal_uInt16
>(
2487 XUnits( UPEm
, GetUInt16( pTable
, nAdvOffset
, 1) ) );
2489 if( nLsbOffset
>= nTableSize
)
2490 res
[i
].sb
= 0; /* better than a crash for buggy fonts */
2492 res
[i
].sb
= static_cast<sal_Int16
>(
2493 XUnits( UPEm
, GetInt16( pTable
, nLsbOffset
, 1) ) );
2500 TTSimpleGlyphMetrics
*GetTTSimpleCharMetrics(TrueTypeFont
* ttf
, sal_uInt16 firstChar
, int nChars
, int mode
)
2502 TTSimpleGlyphMetrics
*res
= 0;
2505 sal_uInt16
* str
= (sal_uInt16
*)malloc(nChars
* 2);
2508 for (i
=0; i
<nChars
; i
++) str
[i
] = (sal_uInt16
)(firstChar
+ i
);
2509 if ((n
= MapString(ttf
, str
, nChars
, 0, mode
)) != -1) {
2510 res
= GetTTSimpleGlyphMetrics(ttf
, str
, n
, mode
);
2519 void GetTTGlobalFontInfo(TrueTypeFont
*ttf
, TTGlobalFontInfo
*info
)
2521 int UPEm
= ttf
->unitsPerEm
;
2523 memset(info
, 0, sizeof(TTGlobalFontInfo
));
2525 info
->family
= ttf
->family
;
2526 info
->ufamily
= ttf
->ufamily
;
2527 info
->subfamily
= ttf
->subfamily
;
2528 info
->usubfamily
= ttf
->usubfamily
;
2529 info
->psname
= ttf
->psname
;
2530 info
->symbolEncoded
= (ttf
->cmapType
== CMAP_MS_Symbol
);
2532 const sal_uInt8
* table
= getTable(ttf
, O_OS2
);
2534 info
->weight
= GetUInt16(table
, 4, 1);
2535 info
->width
= GetUInt16(table
, 6, 1);
2537 /* There are 3 different versions of OS/2 table: original (68 bytes long),
2538 * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,)
2539 * Apple's documentation recommends looking at the table length.
2541 if (getTableSize(ttf
, O_OS2
) > 68) {
2542 info
->typoAscender
= XUnits(UPEm
,GetInt16(table
, 68, 1));
2543 info
->typoDescender
= XUnits(UPEm
, GetInt16(table
, 70, 1));
2544 info
->typoLineGap
= XUnits(UPEm
, GetInt16(table
, 72, 1));
2545 info
->winAscent
= XUnits(UPEm
, GetUInt16(table
, 74, 1));
2546 info
->winDescent
= XUnits(UPEm
, GetUInt16(table
, 76, 1));
2547 /* sanity check; some fonts treat winDescent as signed
2548 * violating the standard */
2549 if( info
->winDescent
> 5*UPEm
)
2550 info
->winDescent
= XUnits(UPEm
, GetInt16(table
, 76,1));
2552 if (ttf
->cmapType
== CMAP_MS_Unicode
) {
2553 info
->rangeFlag
= 1;
2554 info
->ur1
= GetUInt32(table
, 42, 1);
2555 info
->ur2
= GetUInt32(table
, 46, 1);
2556 info
->ur3
= GetUInt32(table
, 50, 1);
2557 info
->ur4
= GetUInt32(table
, 54, 1);
2559 memcpy(info
->panose
, table
+ 32, 10);
2560 info
->typeFlags
= GetUInt16( table
, 8, 1 );
2561 if( getTable(ttf
, O_CFF
) )
2562 info
->typeFlags
|= TYPEFLAG_PS_OPENTYPE
;
2565 table
= getTable(ttf
, O_post
);
2566 if (table
&& getTableSize(ttf
, O_post
) >= 12+sizeof(sal_uInt32
)) {
2567 info
->pitch
= GetUInt32(table
, 12, 1);
2568 info
->italicAngle
= GetInt32(table
, 4, 1);
2571 table
= getTable(ttf
, O_head
); /* 'head' tables is always there */
2572 info
->xMin
= XUnits(UPEm
, GetInt16(table
, 36, 1));
2573 info
->yMin
= XUnits(UPEm
, GetInt16(table
, 38, 1));
2574 info
->xMax
= XUnits(UPEm
, GetInt16(table
, 40, 1));
2575 info
->yMax
= XUnits(UPEm
, GetInt16(table
, 42, 1));
2576 info
->macStyle
= GetInt16(table
, 44, 1);
2578 table
= getTable(ttf
, O_hhea
);
2580 info
->ascender
= XUnits(UPEm
, GetInt16(table
, 4, 1));
2581 info
->descender
= XUnits(UPEm
, GetInt16(table
, 6, 1));
2582 info
->linegap
= XUnits(UPEm
, GetInt16(table
, 8, 1));
2585 table
= getTable(ttf
, O_vhea
);
2587 info
->vascent
= XUnits(UPEm
, GetInt16(table
, 4, 1));
2588 info
->vdescent
= XUnits(UPEm
, GetInt16(table
, 6, 1));
2592 GlyphData
*GetTTRawGlyphData(TrueTypeFont
*ttf
, sal_uInt32 glyphID
)
2594 const sal_uInt8
* glyf
= getTable(ttf
, O_glyf
);
2595 const sal_uInt8
* hmtx
= getTable(ttf
, O_hmtx
);
2598 if( glyphID
>= ttf
->nglyphs
)
2601 /* #127161# check the glyph offsets */
2602 sal_uInt32 length
= getTableSize( ttf
, O_glyf
);
2603 if( length
< ttf
->goffsets
[ glyphID
+1 ] )
2606 length
= ttf
->goffsets
[glyphID
+1] - ttf
->goffsets
[glyphID
];
2608 GlyphData
* d
= (GlyphData
*)malloc(sizeof(GlyphData
)); assert(d
!= 0);
2611 const sal_uInt8
* srcptr
= glyf
+ ttf
->goffsets
[glyphID
];
2612 d
->ptr
= (sal_uInt8
*)malloc((length
+ 1) & ~1); assert(d
->ptr
!= 0);
2613 memcpy( d
->ptr
, srcptr
, length
);
2614 d
->compflag
= (GetInt16( srcptr
, 0, 1 ) < 0);
2620 d
->glyphID
= glyphID
;
2621 d
->nbytes
= (sal_uInt16
)((length
+ 1) & ~1);
2623 /* now calculate npoints and ncontours */
2625 n
= GetTTGlyphPoints(ttf
, glyphID
, &cp
);
2629 for (int i
= 0; i
< n
; i
++)
2631 if (cp
[i
].flags
& 0x8000)
2634 d
->npoints
= (sal_uInt16
)n
;
2635 d
->ncontours
= (sal_uInt16
)m
;
2642 /* get advance width and left sidebearing */
2643 if (glyphID
< ttf
->numberOfHMetrics
) {
2644 d
->aw
= GetUInt16(hmtx
, 4 * glyphID
, 1);
2645 d
->lsb
= GetInt16(hmtx
, 4 * glyphID
+ 2, 1);
2647 d
->aw
= GetUInt16(hmtx
, 4 * (ttf
->numberOfHMetrics
- 1), 1);
2648 d
->lsb
= GetInt16(hmtx
+ ttf
->numberOfHMetrics
* 4, (glyphID
- ttf
->numberOfHMetrics
) * 2, 1);
2654 int GetTTNameRecords(TrueTypeFont
*ttf
, NameRecord
**nr
)
2656 const sal_uInt8
* table
= getTable(ttf
, O_name
);
2657 int nTableSize
= getTableSize(ttf
, O_name
);
2661 #if OSL_DEBUG_LEVEL > 1
2662 fprintf(stderr
, "O_name table too small\n");
2667 sal_uInt16 n
= GetUInt16(table
, 2, 1);
2668 int nStrBase
= GetUInt16(table
, 4, 1);
2672 if (n
== 0) return 0;
2674 NameRecord
* rec
= (NameRecord
*)calloc(n
, sizeof(NameRecord
));
2676 for (i
= 0; i
< n
; i
++) {
2677 int nStrOffset
= GetUInt16(table
+ 6, 10 + 12 * i
, 1);
2678 rec
[i
].platformID
= GetUInt16(table
+ 6, 12 * i
, 1);
2679 rec
[i
].encodingID
= GetUInt16(table
+ 6, 2 + 12 * i
, 1);
2680 rec
[i
].languageID
= GetUInt16(table
+ 6, 4 + 12 * i
, 1);
2681 rec
[i
].nameID
= GetUInt16(table
+ 6, 6 + 12 * i
, 1);
2682 rec
[i
].slen
= GetUInt16(table
+ 6, 8 + 12 * i
, 1);
2684 if( nStrBase
+nStrOffset
+rec
[i
].slen
>= nTableSize
) {
2690 const sal_uInt8
* rec_string
= table
+ nStrBase
+ nStrOffset
;
2692 if( rec_string
> (sal_uInt8
*)ttf
->ptr
&& rec_string
< ((sal_uInt8
*)ttf
->ptr
+ ttf
->fsize
- rec
[i
].slen
) )
2694 rec
[i
].sptr
= (sal_uInt8
*) malloc(rec
[i
].slen
); assert(rec
[i
].sptr
!= 0);
2695 memcpy(rec
[i
].sptr
, rec_string
, rec
[i
].slen
);
2705 // some fonts have 3.0 names => fix them to 3.1
2706 if( (rec
[i
].platformID
== 3) && (rec
[i
].encodingID
== 0) )
2707 rec
[i
].encodingID
= 1;
2714 void DisposeNameRecords(NameRecord
* nr
, int n
)
2717 for (i
= 0; i
< n
; i
++) {
2718 if (nr
[i
].sptr
) free(nr
[i
].sptr
);
2724 boost::dynamic_bitset
<sal_uInt32
> &rUnicodeRange
,
2725 boost::dynamic_bitset
<sal_uInt32
> &rCodePageRange
,
2726 const unsigned char* pTable
, size_t nLength
)
2729 sal_uInt16 nVersion
= GetUInt16(pTable
, 0, 1);
2730 // parse OS/2 header
2731 if ( nVersion
>= 0x0001 && nLength
>= 58 )
2733 rUnicodeRange
.append(GetUInt32(pTable
, 42, 1));
2734 rUnicodeRange
.append(GetUInt32(pTable
, 46, 1));
2735 rUnicodeRange
.append(GetUInt32(pTable
, 50, 1));
2736 rUnicodeRange
.append(GetUInt32(pTable
, 54, 1));
2740 rCodePageRange
.append(GetUInt32(pTable
, 78, 1));
2741 rCodePageRange
.append(GetUInt32(pTable
, 82, 1));
2747 void getTTScripts(std::vector
< sal_uInt32
> &rScriptTags
, const unsigned char* pTable
, size_t nLength
)
2752 // parse GSUB/GPOS header
2753 const sal_uInt16 nOfsScriptList
= GetUInt16(pTable
, 4, 1);
2755 // parse Script Table
2756 const sal_uInt16 nCntScript
= GetUInt16(pTable
, nOfsScriptList
, 1);
2757 sal_uInt32 nCurrentPos
= nOfsScriptList
+2;
2758 for( sal_uInt16 nScriptIndex
= 0;
2759 nScriptIndex
< nCntScript
&& nLength
>= 6; ++nScriptIndex
,
2762 sal_uInt32 nTag
= GetUInt32(pTable
, nCurrentPos
, 1);
2764 rScriptTags
.push_back(nTag
); // e.g. hani/arab/kana/hang
2767 std::sort(rScriptTags
.begin(), rScriptTags
.end());
2768 rScriptTags
.erase(std::unique(rScriptTags
.begin(), rScriptTags
.end()), rScriptTags
.end());
2773 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */