1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
34 * Author: Alexander Gelfenbain
38 #if OSL_DEBUG_LEVEL == 0
54 #if ! (defined(NO_TTCR) && defined(NO_TYPE42))
57 #ifndef NO_MAPPERS /* include MapChar() and MapString() */
60 #ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */
64 #include <osl/endian.h>
74 /*- module identification */
76 static const char *modname
= "SunTypeTools-TT";
77 static const char *modver
= "1.0";
78 static const char *modextra
= "gelf";
80 /*- private functions, constants and data types */ /*FOLD00*/
82 enum PathSegmentType
{
97 PSPathElement( PathSegmentType i_eType
) : type( i_eType
),
105 /*- In horisontal writing mode right sidebearing is calculated using this formula
106 *- rsb = aw - (lsb + xMax - xMin) -*/
112 sal_uInt16 aw
; /*- Advance Width (horisontal writing mode) */
113 sal_Int16 lsb
; /*- Left sidebearing (horisontal writing mode) */
114 sal_uInt16 ah
; /*- advance height (vertical writing mode) */
115 sal_Int16 tsb
; /*- top sidebearing (vertical writing mode) */
118 #define HFORMAT_LINELEN 64
122 char buffer
[HFORMAT_LINELEN
];
128 sal_uInt32 nGlyphs
; /* number of glyphs in the font + 1 */
129 sal_uInt32
*offs
; /* array of nGlyphs offsets */
133 static const sal_uInt32 TTFontClassTag
= 0x74746663; /* 'ttfc' */
135 static const sal_uInt32 T_true
= 0x74727565; /* 'true' */
136 static const sal_uInt32 T_ttcf
= 0x74746366; /* 'ttcf' */
137 static const sal_uInt32 T_otto
= 0x4f54544f; /* 'OTTO' */
139 /* standard TrueType table tags */
140 #define T_maxp 0x6D617870
141 #define T_glyf 0x676C7966
142 #define T_head 0x68656164
143 #define T_loca 0x6C6F6361
144 #define T_name 0x6E616D65
145 #define T_hhea 0x68686561
146 #define T_hmtx 0x686D7478
147 #define T_cmap 0x636D6170
148 #define T_vhea 0x76686561
149 #define T_vmtx 0x766D7478
150 #define T_OS2 0x4F532F32
151 #define T_post 0x706F7374
152 #define T_kern 0x6B65726E
153 #define T_cvt 0x63767420
154 #define T_prep 0x70726570
155 #define T_fpgm 0x6670676D
156 #define T_gsub 0x47535542
157 #define T_CFF 0x43464620
159 #define LAST_URANGE_BIT 69
160 const char *ulcodes
[LAST_URANGE_BIT
+2] = {
161 /* 0 */ "Basic Latin",
162 /* 1 */ "Latin-1 Supplement",
163 /* 2 */ "Latin Extended-A",
164 /* 3 */ "Latin Extended-B",
165 /* 4 */ "IPA Extensions",
166 /* 5 */ "Spacing Modifier Letters",
167 /* 6 */ "Combining Diacritical Marks",
168 /* 7 */ "Basic Greek",
169 /* 8 */ "Greek Symbols And Coptic",
172 /* 11 */ "Basic Hebrew",
173 /* 12 */ "Hebrew Extended (A and B blocks combined)",
174 /* 13 */ "Basic Arabic",
175 /* 14 */ "Arabic Extended",
176 /* 15 */ "Devanagari",
184 /* 23 */ "Malayalam",
187 /* 26 */ "Basic Georgian",
188 /* 27 */ "Georgian Extended",
189 /* 28 */ "Hangul Jamo",
190 /* 29 */ "Latin Extended Additional",
191 /* 30 */ "Greek Extended",
192 /* 31 */ "General Punctuation",
193 /* 32 */ "Superscripts And Subscripts",
194 /* 33 */ "Currency Symbols",
195 /* 34 */ "Combining Diacritical Marks For Symbols",
196 /* 35 */ "Letterlike Symbols",
197 /* 36 */ "Number Forms",
199 /* 38 */ "Mathematical Operators",
200 /* 39 */ "Miscellaneous Technical",
201 /* 40 */ "Control Pictures",
202 /* 41 */ "Optical Character Recognition",
203 /* 42 */ "Enclosed Alphanumerics",
204 /* 43 */ "Box Drawing",
205 /* 44 */ "Block Elements",
206 /* 45 */ "Geometric Shapes",
207 /* 46 */ "Miscellaneous Symbols",
209 /* 48 */ "CJK Symbols And Punctuation",
213 /* 52 */ "Hangul Compatibility Jamo",
214 /* 53 */ "CJK Miscellaneous",
215 /* 54 */ "Enclosed CJK Letters And Months",
216 /* 55 */ "CJK Compatibility",
218 /* 57 */ "Reserved for Unicode SubRanges",
219 /* 58 */ "Reserved for Unicode SubRanges",
220 /* 59 */ "CJK Unified Ideographs",
221 /* 60 */ "Private Use Area",
222 /* 61 */ "CJK Compatibility Ideographs",
223 /* 62 */ "Alphabetic Presentation Forms",
224 /* 63 */ "Arabic Presentation Forms-A",
225 /* 64 */ "Combining Half Marks",
226 /* 65 */ "CJK Compatibility Forms",
227 /* 66 */ "Small Form Variants",
228 /* 67 */ "Arabic Presentation Forms-B",
229 /* 68 */ "Halfwidth And Fullwidth Forms",
231 /*70-127*/ "Reserved for Unicode SubRanges"
236 /*- inline functions */ /*FOLD01*/
238 #define _inline static __inline__
240 #define _inline static
243 _inline
void *smalloc(size_t size
)
245 void *res
= malloc(size
);
250 _inline
void *scalloc(size_t n
, size_t size
)
252 void *res
= calloc(n
, size
);
257 _inline sal_uInt32
mkTag(sal_uInt8 a
, sal_uInt8 b
, sal_uInt8 c
, sal_uInt8 d
) {
258 return (a
<< 24) | (b
<< 16) | (c
<< 8) | d
;
261 /*- Data access macros for data stored in big-endian or little-endian format */
262 _inline sal_Int16
GetInt16(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
268 t
= (ptr
+offset
)[0] << 8 | (ptr
+offset
)[1];
270 t
= (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
276 _inline sal_uInt16
GetUInt16(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
282 t
= (ptr
+offset
)[0] << 8 | (ptr
+offset
)[1];
284 t
= (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
290 _inline sal_Int32
GetInt32(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
296 t
= (ptr
+offset
)[0] << 24 | (ptr
+offset
)[1] << 16 |
297 (ptr
+offset
)[2] << 8 | (ptr
+offset
)[3];
299 t
= (ptr
+offset
)[3] << 24 | (ptr
+offset
)[2] << 16 |
300 (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
306 _inline sal_uInt32
GetUInt32(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
313 t
= (ptr
+offset
)[0] << 24 | (ptr
+offset
)[1] << 16 |
314 (ptr
+offset
)[2] << 8 | (ptr
+offset
)[3];
316 t
= (ptr
+offset
)[3] << 24 | (ptr
+offset
)[2] << 16 |
317 (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
323 _inline
void PutInt16(sal_Int16 val
, sal_uInt8
*ptr
, size_t offset
, int bigendian
)
328 ptr
[offset
] = (sal_uInt8
)((val
>> 8) & 0xFF);
329 ptr
[offset
+1] = (sal_uInt8
)(val
& 0xFF);
331 ptr
[offset
+1] = (sal_uInt8
)((val
>> 8) & 0xFF);
332 ptr
[offset
] = (sal_uInt8
)(val
& 0xFF);
337 #if defined(OSL_BIGENDIAN)
338 #define Int16FromMOTA(a) (a)
339 #define Int32FromMOTA(a) (a)
341 static sal_uInt16
Int16FromMOTA(sal_uInt16 a
) {
342 return (sal_uInt16
) (((sal_uInt8
)((a
) >> 8)) | ((sal_uInt8
)(a
) << 8));
344 static sal_uInt32
Int32FromMOTA(sal_uInt32 a
) {
345 return ((a
>>24)&0xFF) | (((a
>>8)&0xFF00) | ((a
&0xFF00)<<8) | ((a
&0xFF)<<24));
349 _inline F16Dot16
fixedMul(F16Dot16 a
, F16Dot16 b
)
356 sign
= (a
& 0x80000000) ^ (b
& 0x80000000);
367 /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */
370 res
+= a1
* b2
+ b1
* a2
+ ((b1
* b2
) >> 16);
372 return sign
? -res
: res
;
376 _inline F16Dot16
fixedDiv(F16Dot16 a
, F16Dot16 b
)
382 sign
= (a
& 0x80000000) ^ (b
& 0x80000000);
389 /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */
396 res
= (f
<< 16) + (r
<< 16) / b
;
398 return sign
? -res
: res
;
401 /*- returns a * b / c -*/
402 /* XXX provide a real implementation that preserves accuracy */
403 _inline F16Dot16
fixedMulDiv(F16Dot16 a
, F16Dot16 b
, F16Dot16 c
)
407 res
= fixedMul(a
, b
);
408 return fixedDiv(res
, c
);
411 /*- Translate units from TT to PS (standard 1/1000) -*/
412 _inline
int XUnits(int unitsPerEm
, int n
)
414 return (n
* 1000) / unitsPerEm
;
417 _inline
const char *UnicodeRangeName(sal_uInt16 bit
)
419 if (bit
> LAST_URANGE_BIT
) bit
= LAST_URANGE_BIT
+1;
424 _inline
const sal_uInt8
* getTable( TrueTypeFont
*ttf
, sal_uInt32 ord
)
426 return (sal_uInt8
*)ttf
->tables
[ord
];
429 _inline sal_uInt32
getTableSize(TrueTypeFont
*ttf
, sal_uInt32 ord
)
431 return ttf
->tlens
[ord
];
435 /* Hex Formatter functions */
436 static char HexChars
[] = "0123456789ABCDEF";
438 static HexFmt
*HexFmtNew(FILE *outf
)
440 HexFmt
* res
= (HexFmt
*)smalloc(sizeof(HexFmt
));
441 res
->bufpos
= res
->total
= 0;
446 static void HexFmtFlush(HexFmt
*_this
)
449 fwrite(_this
->buffer
, 1, _this
->bufpos
, _this
->o
);
455 _inline
void HexFmtOpenString(HexFmt
*_this
)
457 fputs("<\n", _this
->o
);
460 _inline
void HexFmtCloseString(HexFmt
*_this
)
463 fputs("00\n>\n", _this
->o
);
466 _inline
void HexFmtDispose(HexFmt
*_this
)
472 static void HexFmtBlockWrite(HexFmt
*_this
, const void *ptr
, sal_uInt32 size
)
477 if (_this
->total
+ size
> 65534) {
479 HexFmtCloseString(_this
);
481 HexFmtOpenString(_this
);
483 for (i
=0; i
<size
; i
++) {
484 Ch
= ((sal_uInt8
*) ptr
)[i
];
485 _this
->buffer
[_this
->bufpos
++] = HexChars
[Ch
>> 4];
486 _this
->buffer
[_this
->bufpos
++] = HexChars
[Ch
& 0xF];
487 if (_this
->bufpos
== HFORMAT_LINELEN
) {
489 fputc('\n', _this
->o
);
493 _this
->total
+= size
;
499 /* Outline Extraction functions */ /*FOLD01*/
501 /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
502 static void GetMetrics(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, TTGlyphMetrics
*metrics
)
504 const sal_uInt8
* table
= getTable( ttf
, O_hmtx
);
506 metrics
->aw
= metrics
->lsb
= metrics
->ah
= metrics
->tsb
= 0;
507 if (!table
|| !ttf
->numberOfHMetrics
) return;
509 if (glyphID
< ttf
->numberOfHMetrics
) {
510 metrics
->aw
= GetUInt16(table
, 4 * glyphID
, 1);
511 metrics
->lsb
= GetInt16(table
, 4 * glyphID
+ 2, 1);
513 metrics
->aw
= GetUInt16(table
, 4 * (ttf
->numberOfHMetrics
- 1), 1);
514 metrics
->lsb
= GetInt16(table
+ ttf
->numberOfHMetrics
* 4, (glyphID
- ttf
->numberOfHMetrics
) * 2, 1);
517 table
= getTable(ttf
, O_vmtx
);
518 if( !table
|| !ttf
->numOfLongVerMetrics
)
521 if (glyphID
< ttf
->numOfLongVerMetrics
) {
522 metrics
->ah
= GetUInt16(table
, 4 * glyphID
, 1);
523 metrics
->tsb
= GetInt16(table
, 4 * glyphID
+ 2, 1);
525 metrics
->ah
= GetUInt16(table
, 4 * (ttf
->numOfLongVerMetrics
- 1), 1);
526 metrics
->tsb
= GetInt16(table
+ ttf
->numOfLongVerMetrics
* 4, (glyphID
- ttf
->numOfLongVerMetrics
) * 2, 1);
530 static int GetTTGlyphOutline(TrueTypeFont
*, sal_uInt32
, ControlPoint
**, TTGlyphMetrics
*, std::vector
< sal_uInt32
>* );
532 /* returns the number of control points, allocates the pointArray */
533 static int GetSimpleTTOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
) /*FOLD02*/
535 const sal_uInt8
* table
= getTable( ttf
, O_glyf
);
537 sal_uInt16 t
, lastPoint
=0;
542 /* printf("GetSimpleTTOutline(%d)\n", glyphID); */
544 if( glyphID
>= ttf
->nglyphs
) /*- glyph is not present in the font */
546 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
547 const sal_Int16 numberOfContours
= GetInt16(ptr
, 0, 1);
548 if( numberOfContours
<= 0 ) /*- glyph is not simple */
551 if (metrics
) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
552 metrics
->xMin
= GetInt16(ptr
, 2, 1);
553 metrics
->yMin
= GetInt16(ptr
, 4, 1);
554 metrics
->xMax
= GetInt16(ptr
, 6, 1);
555 metrics
->yMax
= GetInt16(ptr
, 8, 1);
556 GetMetrics(ttf
, glyphID
, metrics
);
559 /* determine the last point and be extra safe about it. But probably this code is not needed */
561 for (i
=0; i
<numberOfContours
; i
++) {
562 if ((t
= GetUInt16(ptr
, 10+i
*2, 1)) > lastPoint
) lastPoint
= t
;
565 sal_uInt16 instLen
= GetUInt16(ptr
, 10 + numberOfContours
*2, 1);
566 const sal_uInt8
* p
= ptr
+ 10 + 2 * numberOfContours
+ 2 + instLen
;
567 ControlPoint
* pa
= (ControlPoint
*)calloc(lastPoint
+1, sizeof(ControlPoint
));
570 while (i
<= lastPoint
) {
571 pa
[i
++].flags
= (sal_uInt32
) (flag
= *p
++);
572 if (flag
& 8) { /*- repeat flag */
574 for (j
=0; j
<n
; j
++) {
575 if (i
> lastPoint
) { /*- if the font is really broken */
579 pa
[i
++].flags
= flag
;
584 /*- Process the X coordinate */
586 for (i
= 0; i
<= lastPoint
; i
++) {
587 if (pa
[i
].flags
& 0x02) {
588 if (pa
[i
].flags
& 0x10) {
593 } else if ( !(pa
[i
].flags
& 0x10)) {
594 z
+= GetInt16(p
, 0, 1);
597 pa
[i
].x
= (sal_Int16
)z
;
600 /*- Process the Y coordinate */
602 for (i
= 0; i
<= lastPoint
; i
++) {
603 if (pa
[i
].flags
& 0x04) {
604 if (pa
[i
].flags
& 0x20) {
609 } else if ( !(pa
[i
].flags
& 0x20)) {
610 z
+= GetInt16(p
, 0, 1);
613 pa
[i
].y
= (sal_Int16
)z
;
616 for (i
=0; i
<numberOfContours
; i
++) {
617 pa
[GetUInt16(ptr
, 10 + i
* 2, 1)].flags
|= 0x00008000; /*- set the end contour flag */
621 return lastPoint
+ 1;
624 static int GetCompoundTTOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
, std::vector
< sal_uInt32
>& glyphlist
) /*FOLD02*/
626 sal_uInt16 flags
, index
;
627 sal_Int16 e
, f
, numberOfContours
;
628 const sal_uInt8
* table
= getTable( ttf
, O_glyf
);
629 std::vector
<ControlPoint
> myPoints
;
630 ControlPoint
*nextComponent
, *pa
;
632 F16Dot16 a
= 0x10000, b
= 0, c
= 0, d
= 0x10000, m
, n
, abs1
, abs2
, abs3
;
635 /* printf("GetCompoundTTOutline(%d)\n", glyphID); */
637 if (glyphID
>= ttf
->nglyphs
) /*- incorrect glyphID */
640 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
641 if ((numberOfContours
= GetInt16(ptr
, 0, 1)) != -1) /*- glyph is not compound */
645 metrics
->xMin
= GetInt16(ptr
, 2, 1);
646 metrics
->yMin
= GetInt16(ptr
, 4, 1);
647 metrics
->xMax
= GetInt16(ptr
, 6, 1);
648 metrics
->yMax
= GetInt16(ptr
, 8, 1);
649 GetMetrics(ttf
, glyphID
, metrics
);
655 flags
= GetUInt16(ptr
, 0, 1);
656 /* printf("flags: 0x%X\n", flags); */
657 index
= GetUInt16(ptr
, 2, 1);
660 if( std::find( glyphlist
.begin(), glyphlist
.end(), index
) != glyphlist
.end() )
662 #if OSL_DEBUG_LEVEL > 1
663 fprintf(stderr
, "Endless loop found in a compound glyph.\n");
664 fprintf(stderr
, "%d -> ", index
);
665 fprintf(stderr
," [");
666 for( std::vector
< sal_uInt32
>::const_iterator it
= glyphlist
.begin();
667 it
!= glyphlist
.end(); ++it
)
669 fprintf( stderr
,"%d ", (int) *it
);
671 fprintf(stderr
,"]\n");
676 glyphlist
.push_back( index
);
679 fprintf(stderr
,"glyphlist: += %d\n", index
);
682 if ((np
= GetTTGlyphOutline(ttf
, index
, &nextComponent
, 0, &glyphlist
)) == 0)
684 /* XXX that probably indicates a corrupted font */
685 #if OSL_DEBUG_LEVEL > 1
686 fprintf(stderr
, "An empty compound!\n");
687 /* assert(!"An empty compound"); */
692 fprintf(stderr
,"%d [", (int)glyphlist
.size() );
693 for( std::vector
< sal_uInt32
>::const_iterator it
= glyphlist
.begin();
694 it
!= glyphlist
.end(); ++it
)
696 fprintf( stderr
,"%d ", (int) *it
);
698 fprintf(stderr
, "]\n");
699 if( ! glyphlist
.empty() )
700 fprintf(stderr
, "glyphlist: -= %d\n", (int) glyphlist
.back());
703 if( ! glyphlist
.empty() )
704 glyphlist
.pop_back();
706 if (flags
& USE_MY_METRICS
) {
707 if (metrics
) GetMetrics(ttf
, index
, metrics
);
710 if (flags
& ARG_1_AND_2_ARE_WORDS
) {
711 e
= GetInt16(ptr
, 0, 1);
712 f
= GetInt16(ptr
, 2, 1);
713 /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
716 if (flags
& ARGS_ARE_XY_VALUES
) { /* args are signed */
717 e
= (sal_Int8
) *ptr
++;
718 f
= (sal_Int8
) *ptr
++;
719 /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
720 } else { /* args are unsigned */
721 /* printf("!ARGS_ARE_XY_VALUES\n"); */
731 if (flags
& WE_HAVE_A_SCALE
) {
733 fprintf(stderr
, "WE_HAVE_A_SCALE\n");
735 a
= GetInt16(ptr
, 0, 1) << 2;
738 } else if (flags
& WE_HAVE_AN_X_AND_Y_SCALE
) {
740 fprintf(stderr
, "WE_HAVE_AN_X_AND_Y_SCALE\n");
742 a
= GetInt16(ptr
, 0, 1) << 2;
743 d
= GetInt16(ptr
, 2, 1) << 2;
745 } else if (flags
& WE_HAVE_A_TWO_BY_TWO
) {
747 fprintf(stderr
, "WE_HAVE_A_TWO_BY_TWO\n");
749 a
= GetInt16(ptr
, 0, 1) << 2;
750 b
= GetInt16(ptr
, 2, 1) << 2;
751 c
= GetInt16(ptr
, 4, 1) << 2;
752 d
= GetInt16(ptr
, 6, 1) << 2;
756 abs1
= (a
< 0) ? -a
: a
;
757 abs2
= (b
< 0) ? -b
: b
;
758 m
= (abs1
> abs2
) ? abs1
: abs2
;
760 if (abs3
< 0) abs3
= -abs3
;
761 if (abs3
<= 33) m
*= 2;
763 abs1
= (c
< 0) ? -c
: c
;
764 abs2
= (d
< 0) ? -d
: d
;
765 n
= (abs1
> abs2
) ? abs1
: abs2
;
767 if (abs3
< 0) abs3
= -abs3
;
768 if (abs3
<= 33) n
*= 2;
770 if (!ARGS_ARE_XY_VALUES
) { /* match the points */
771 assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n");
775 fprintf(stderr
, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n",
776 ((double) a
) / 65536,
777 ((double) b
) / 65536,
778 ((double) c
) / 65536,
779 ((double) d
) / 65536,
780 ((double) e
) / 65536,
781 ((double) f
) / 65536,
782 ((double) m
) / 65536,
783 ((double) n
) / 65536);
786 for (i
=0; i
<np
; i
++) {
789 cp
.flags
= nextComponent
[i
].flags
;
790 t
= fixedMulDiv(a
, nextComponent
[i
].x
<< 16, m
) + fixedMulDiv(c
, nextComponent
[i
].y
<< 16, m
) + (e
<< 16);
791 cp
.x
= (sal_Int16
)(fixedMul(t
, m
) >> 16);
792 t
= fixedMulDiv(b
, nextComponent
[i
].x
<< 16, n
) + fixedMulDiv(d
, nextComponent
[i
].y
<< 16, n
) + (f
<< 16);
793 cp
.y
= (sal_Int16
)(fixedMul(t
, n
) >> 16);
796 fprintf(stderr
, "( %d %d ) -> ( %d %d )\n", nextComponent
[i
].x
, nextComponent
[i
].y
, cp
.x
, cp
.y
);
799 myPoints
.push_back( cp
);
804 } while (flags
& MORE_COMPONENTS
);
808 np
= myPoints
.size();
810 pa
= (ControlPoint
*)calloc(np
, sizeof(ControlPoint
));
813 memcpy( pa
, &myPoints
[0], np
*sizeof(ControlPoint
) );
819 /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect,
820 * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
822 * NOTE: glyphlist is the stack of glyphs traversed while constructing
823 * a composite glyph. This is a safequard against endless recursion
824 * in corrupted fonts.
826 static int GetTTGlyphOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
, std::vector
< sal_uInt32
>* glyphlist
)
828 const sal_uInt8
*table
= getTable( ttf
, O_glyf
);
829 sal_Int16 numberOfContours
;
834 memset(metrics
, 0, sizeof(TTGlyphMetrics
)); /*- metrics is initialized to all zeroes */
837 if (glyphID
>= ttf
->nglyphs
) return -1; /**/
839 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
840 int length
= ttf
->goffsets
[glyphID
+1] - ttf
->goffsets
[glyphID
];
842 if (length
== 0) { /*- empty glyphs still have hmtx and vmtx metrics values */
843 if (metrics
) GetMetrics(ttf
, glyphID
, metrics
);
847 numberOfContours
= GetInt16(ptr
, 0, 1);
849 if (numberOfContours
>= 0)
851 res
=GetSimpleTTOutline(ttf
, glyphID
, pointArray
, metrics
);
855 std::vector
< sal_uInt32
> aPrivList
;
856 aPrivList
.push_back( glyphID
);
857 res
= GetCompoundTTOutline(ttf
, glyphID
, pointArray
, metrics
, glyphlist
? *glyphlist
: aPrivList
);
863 FILE *out
= fopen("points.dat", "a");
865 fprintf(out
, "Glyph: %d\nPoints: %d\n", glyphID
, res
);
866 for (i
=0; i
<res
; i
++) {
867 fprintf(out
, "%c ", ((*pointArray
)[i
].flags
& 0x8000) ? 'X' : '.');
868 fprintf(out
, "%c ", ((*pointArray
)[i
].flags
& 1) ? '+' : '-');
869 fprintf(out
, "%d %d\n", (*pointArray
)[i
].x
, (*pointArray
)[i
].y
);
880 /*- returns the number of items in the path -*/
882 static int BSplineToPSPath(ControlPoint
*srcA
, int srcCount
, PSPathElement
**path
)
884 std::vector
< PSPathElement
> aPathList
;
886 PSPathElement
p( PS_NOOP
);
888 int x0
= 0, y0
= 0, x1
= 0, y1
= 0, x2
, y2
, curx
, cury
;
889 int lastOff
= 0; /*- last point was off-contour */
890 int scflag
= 1; /*- start contour flag */
891 int ecflag
= 0; /*- end contour flag */
892 int cp
= 0; /*- current point */
893 int StartContour
= 0, EndContour
= 1;
897 /* if (srcCount > 0) for(;;) */
898 while (srcCount
> 0) { /*- srcCount does not get changed inside the loop. */
902 while (!(srcA
[l
].flags
& 0x8000)) l
++;
904 if (StartContour
== EndContour
) {
905 if (cp
+ 1 < srcCount
) {
912 p
= PSPathElement(PS_MOVETO
);
913 if (!(srcA
[cp
].flags
& 1)) {
914 if (!(srcA
[EndContour
].flags
& 1)) {
915 p
.x1
= x0
= (srcA
[cp
].x
+ srcA
[EndContour
].x
+ 1) / 2;
916 p
.y1
= y0
= (srcA
[cp
].y
+ srcA
[EndContour
].y
+ 1) / 2;
918 p
.x1
= x0
= srcA
[EndContour
].x
;
919 p
.y1
= y0
= srcA
[EndContour
].y
;
922 p
.x1
= x0
= srcA
[cp
].x
;
923 p
.y1
= y0
= srcA
[cp
].y
;
926 aPathList
.push_back( p
);
934 if (srcA
[cp
].flags
& 1)
938 p
= PSPathElement(PS_CURVETO
);
939 p
.x1
= x0
+ (2 * (x1
- x0
) + 1) / 3;
940 p
.y1
= y0
+ (2 * (y1
- y0
) + 1) / 3;
941 p
.x2
= x1
+ (curx
- x1
+ 1) / 3;
942 p
.y2
= y1
+ (cury
- y1
+ 1) / 3;
945 aPathList
.push_back( p
);
949 if (!(x0
== curx
&& y0
== cury
))
950 { /* eliminate empty lines */
951 p
= PSPathElement(PS_LINETO
);
954 aPathList
.push_back( p
);
957 x0
= curx
; y0
= cury
; lastOff
= 0;
963 x2
= (x1
+ curx
+ 1) / 2;
964 y2
= (y1
+ cury
+ 1) / 2;
965 p
= PSPathElement(PS_CURVETO
);
966 p
.x1
= x0
+ (2 * (x1
- x0
) + 1) / 3;
967 p
.y1
= y0
+ (2 * (y1
- y0
) + 1) / 3;
968 p
.x2
= x1
+ (x2
- x1
+ 1) / 3;
969 p
.y2
= y1
+ (y2
- y1
+ 1) / 3;
972 aPathList
.push_back( p
);
974 x1
= curx
; y1
= cury
;
976 x1
= curx
; y1
= cury
;
982 aPathList
.push_back( PSPathElement(PS_CLOSEPATH
) );
986 if (cp
>= srcCount
) break;
991 if (cp
== EndContour
) {
999 if( (nPathCount
= (int)aPathList
.size()) > 0)
1001 *path
= (PSPathElement
*)calloc(nPathCount
, sizeof(PSPathElement
));
1003 memcpy( *path
, &aPathList
[0], nPathCount
* sizeof(PSPathElement
) );
1011 /*- Extracts a string from the name table and allocates memory for it -*/
1013 static char *nameExtract( const sal_uInt8
* name
, int nTableSize
, int n
, int dbFlag
, sal_uInt16
** ucs2result
)
1017 const sal_uInt8
* ptr
= name
+ GetUInt16(name
, 4, 1) + GetUInt16(name
+ 6, 12 * n
+ 10, 1);
1018 int len
= GetUInt16(name
+6, 12 * n
+ 8, 1);
1021 if( (len
<= 0) || ((ptr
+len
) > (name
+nTableSize
)) )
1031 res
= (char*)malloc(1 + len
/2);
1033 for (i
= 0; i
< len
/2; i
++) res
[i
] = *(ptr
+ i
* 2 + 1);
1037 *ucs2result
= (sal_uInt16
*)malloc( len
+2 );
1038 for (i
= 0; i
< len
/2; i
++ ) (*ucs2result
)[i
] = GetUInt16( ptr
, 2*i
, 1 );
1039 (*ucs2result
)[len
/2] = 0;
1042 res
= (char*)malloc(1 + len
);
1044 memcpy(res
, ptr
, len
);
1051 static int findname( const sal_uInt8
*name
, sal_uInt16 n
, sal_uInt16 platformID
,
1052 sal_uInt16 encodingID
, sal_uInt16 languageID
, sal_uInt16 nameID
)
1054 int l
= 0, r
= n
-1, i
;
1058 if (n
== 0) return -1;
1060 m1
= (platformID
<< 16) | encodingID
;
1061 m2
= (languageID
<< 16) | nameID
;
1065 t1
= GetUInt32(name
+ 6, i
* 12 + 0, 1);
1066 t2
= GetUInt32(name
+ 6, i
* 12 + 4, 1);
1068 if (! ((m1
< t1
) || ((m1
== t1
) && (m2
< t2
)))) l
= i
+ 1;
1069 if (! ((m1
> t1
) || ((m1
== t1
) && (m2
> t2
)))) r
= i
- 1;
1079 /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables.
1080 * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
1082 * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
1083 * and does not have (3, 1, 1033)
1084 * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
1085 * require a change in algorithm
1087 * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID,
1088 * but (1, 0, 1042) strings usable
1089 * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
1092 static void GetNames(TrueTypeFont
*t
)
1094 const sal_uInt8
* table
= getTable( t
, O_name
);
1095 int nTableSize
= getTableSize(t
, O_name
);
1097 sal_uInt16 n
= GetUInt16(table
, 2, 1);
1099 sal_Bool bPSNameOK
= sal_True
;
1101 /* #129743# simple sanity check for name table entry count */
1102 if( nTableSize
<= n
* 12 + 6 )
1105 /* PostScript name: preferred Microsoft */
1107 if ((r
= findname(table
, n
, 3, 1, 0x0409, 6)) != -1)
1108 t
->psname
= nameExtract(table
, nTableSize
, r
, 1, NULL
);
1109 if ( ! t
->psname
&& (r
= findname(table
, n
, 1, 0, 0, 6)) != -1)
1110 t
->psname
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
1111 if ( ! t
->psname
&& (r
= findname(table
, n
, 3, 0, 0x0409, 6)) != -1)
1113 // some symbol fonts like Marlett have a 3,0 name!
1114 t
->psname
= nameExtract(table
, nTableSize
, r
, 1, NULL
);
1116 // for embedded font in Ghostscript PDFs
1117 if ( ! t
->psname
&& (r
= findname(table
, n
, 2, 2, 0, 6)) != -1)
1119 t
->psname
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
1125 char* pReverse
= t
->fname
+ strlen(t
->fname
);
1126 /* take only last token of filename */
1127 while(pReverse
!= t
->fname
&& *pReverse
!= '/') pReverse
--;
1128 if(*pReverse
== '/') pReverse
++;
1129 t
->psname
= strdup(pReverse
);
1130 assert(t
->psname
!= 0);
1131 for (i
=strlen(t
->psname
) - 1; i
> 0; i
--)
1133 /*- Remove the suffix -*/
1134 if (t
->psname
[i
] == '.' ) {
1141 t
->psname
= strdup( "Unknown" );
1144 /* Font family and subfamily names: preferred Apple */
1146 if ((r
= findname(table
, n
, 0, 0, 0, 1)) != -1)
1147 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1148 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 1, 0x0409, 1)) != -1)
1149 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1150 if ( ! t
->family
&& (r
= findname(table
, n
, 1, 0, 0, 1)) != -1)
1151 t
->family
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
1152 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 1, 0x0411, 1)) != -1)
1153 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1154 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 0, 0x0409, 1)) != -1)
1155 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1158 t
->family
= strdup(t
->psname
);
1159 assert(t
->family
!= 0);
1162 t
->subfamily
= NULL
;
1163 t
->usubfamily
= NULL
;
1164 if ((r
= findname(table
, n
, 1, 0, 0, 2)) != -1)
1165 t
->subfamily
= nameExtract(table
, nTableSize
, r
, 0, &t
->usubfamily
);
1166 if ( ! t
->subfamily
&& (r
= findname(table
, n
, 3, 1, 0x0409, 2)) != -1)
1167 t
->subfamily
= nameExtract(table
, nTableSize
, r
, 1, &t
->usubfamily
);
1168 if ( ! t
->subfamily
)
1170 t
->subfamily
= strdup("");
1173 /* #i60349# sanity check psname
1174 * psname parctically has to be 7bit ascii and should not contains spaces
1175 * there is a class of broken fonts which do not fullfill that at all, so let's try
1176 * if the family name is 7bit ascii and take it instead if so
1179 for( i
= 0; t
->psname
[i
] != 0 && bPSNameOK
; i
++ )
1180 if( t
->psname
[ i
] < 33 || (t
->psname
[ i
] & 0x80) )
1181 bPSNameOK
= sal_False
;
1182 if( bPSNameOK
== sal_False
)
1184 sal_Bool bReplace
= sal_True
;
1185 /* check if family is a suitable replacement */
1186 if( t
->ufamily
&& t
->family
)
1188 for( i
= 0; t
->ufamily
[ i
] != 0 && bReplace
; i
++ )
1189 if( t
->ufamily
[ i
] < 33 || t
->ufamily
[ i
] > 127 )
1190 bReplace
= sal_False
;
1194 t
->psname
= strdup( t
->family
);
1201 CMAP_NOT_USABLE
= -1,
1202 CMAP_MS_Symbol
= 10,
1203 CMAP_MS_Unicode
= 11,
1204 CMAP_MS_ShiftJIS
= 12,
1207 CMAP_MS_Wansung
= 15,
1211 #define MISSING_GLYPH_INDEX 0
1214 * getGlyph[0246]() functions and freinds are implemented by:
1215 * @author Manpreet Singh
1216 * getGlyph12() function and friends by:
1219 static sal_uInt32
getGlyph0(const sal_uInt8
* cmap
, sal_uInt32 c
) {
1221 return *(cmap
+ 6 + c
);
1223 return MISSING_GLYPH_INDEX
;
1227 typedef struct _subHeader2
{
1228 sal_uInt16 firstCode
;
1229 sal_uInt16 entryCount
;
1231 sal_uInt16 idRangeOffset
;
1234 static sal_uInt32
getGlyph2(const sal_uInt8
*cmap
, sal_uInt32 c
) {
1235 sal_uInt16
*CMAP2
= (sal_uInt16
*) cmap
;
1236 sal_uInt8 theHighByte
;
1238 sal_uInt8 theLowByte
;
1239 subHeader2
* subHeader2s
;
1240 sal_uInt16
* subHeader2Keys
;
1241 sal_uInt16 firstCode
;
1243 sal_uInt32 ToReturn
;
1245 theHighByte
= (sal_uInt8
)((c
>> 8) & 0x00ff);
1246 theLowByte
= (sal_uInt8
)(c
& 0x00ff);
1247 subHeader2Keys
= CMAP2
+ 3;
1248 subHeader2s
= (subHeader2
*)(subHeader2Keys
+ 256);
1249 k
= Int16FromMOTA(subHeader2Keys
[theHighByte
]) / 8;
1252 firstCode
= Int16FromMOTA(subHeader2s
[k
].firstCode
);
1253 if(theLowByte
>= firstCode
&& theLowByte
< (firstCode
+ Int16FromMOTA(subHeader2s
[k
].entryCount
))) {
1254 return *((&(subHeader2s
[0].idRangeOffset
))
1255 + (Int16FromMOTA(subHeader2s
[0].idRangeOffset
)/2) /* + offset */
1256 + theLowByte
/* + to_look */
1257 - Int16FromMOTA(subHeader2s
[0].firstCode
)
1260 return MISSING_GLYPH_INDEX
;
1263 firstCode
= Int16FromMOTA(subHeader2s
[k
].firstCode
);
1264 if(theLowByte
>= firstCode
&& theLowByte
< (firstCode
+ Int16FromMOTA(subHeader2s
[k
].entryCount
))) {
1265 ToReturn
= *((&(subHeader2s
[k
].idRangeOffset
))
1266 + (Int16FromMOTA(subHeader2s
[k
].idRangeOffset
)/2)
1267 + theLowByte
- firstCode
);
1269 return MISSING_GLYPH_INDEX
;
1271 ToReturn
+= Int16FromMOTA(subHeader2s
[k
].idDelta
);
1272 return (ToReturn
& 0xFFFF);
1275 return MISSING_GLYPH_INDEX
;
1278 return MISSING_GLYPH_INDEX
;
1282 static sal_uInt32
getGlyph6(const sal_uInt8
*cmap
, sal_uInt32 c
) {
1283 sal_uInt16 firstCode
, lastCode
, count
;
1284 sal_uInt16
*CMAP6
= (sal_uInt16
*) cmap
;
1286 firstCode
= Int16FromMOTA(*(CMAP6
+ 3));
1287 count
= Int16FromMOTA(*(CMAP6
+ 4));
1288 lastCode
= firstCode
+ count
- 1;
1289 if (c
< firstCode
|| c
> lastCode
) {
1290 return MISSING_GLYPH_INDEX
;
1292 return *((CMAP6
+ 5)/*glyphIdArray*/ + (c
- firstCode
));
1296 static sal_uInt16
GEbinsearch(sal_uInt16
*ar
, sal_uInt16 length
, sal_uInt16 toSearch
) {
1297 signed int low
, mid
, high
, lastfound
= 0xffff;
1299 if(length
== (sal_uInt16
)0 || length
== (sal_uInt16
)0xFFFF) {
1300 return (sal_uInt16
)0xFFFF;
1304 while(high
>= low
) {
1305 mid
= (high
+ low
)/2;
1306 res
= Int16FromMOTA(*(ar
+mid
));
1307 if(res
>= toSearch
) {
1314 return (sal_uInt16
)lastfound
;
1318 static sal_uInt32
getGlyph4(const sal_uInt8
*cmap
, sal_uInt32 c
) {
1321 sal_uInt16 segCount
;
1322 sal_uInt16
* startCode
;
1323 sal_uInt16
* endCode
;
1324 sal_uInt16
* idDelta
;
1325 /* sal_uInt16 * glyphIdArray; */
1326 sal_uInt16
* idRangeOffset
;
1327 sal_uInt16
* glyphIndexArray
;
1328 sal_uInt16
*CMAP4
= (sal_uInt16
*) cmap
;
1329 /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */
1331 segCount
= Int16FromMOTA(*(CMAP4
+ 3))/2;
1332 endCode
= CMAP4
+ 7;
1333 i
= GEbinsearch(endCode
, segCount
, (sal_uInt16
)c
);
1335 if (i
== (sal_uInt16
) 0xFFFF) {
1336 return MISSING_GLYPH_INDEX
;
1338 startCode
= endCode
+ segCount
+ 1;
1340 if(Int16FromMOTA(startCode
[i
]) > c
) {
1341 return MISSING_GLYPH_INDEX
;
1343 idDelta
= startCode
+ segCount
;
1344 idRangeOffset
= idDelta
+ segCount
;
1345 glyphIndexArray
= idRangeOffset
+ segCount
;
1347 if(Int16FromMOTA(idRangeOffset
[i
]) != 0) {
1348 c
= Int16FromMOTA(*(&(idRangeOffset
[i
]) + (Int16FromMOTA(idRangeOffset
[i
])/2 + (c
- Int16FromMOTA(startCode
[i
])))));
1351 ToReturn
= (Int16FromMOTA(idDelta
[i
]) + c
) & 0xFFFF;
1355 static sal_uInt32
getGlyph12(const sal_uInt8
*pCmap
, sal_uInt32 cChar
) {
1356 const sal_uInt32
* pCMAP12
= (const sal_uInt32
*)pCmap
;
1357 int nLength
= Int32FromMOTA( pCMAP12
[1] );
1358 int nGroups
= Int32FromMOTA( pCMAP12
[3] );
1360 int nUpper
= nGroups
;
1362 if( nUpper
> (nLength
-16)/12 )
1363 nUpper
= (nLength
-16)/12;
1365 /* binary search in "segmented coverage" subtable */
1366 while( nLower
< nUpper
) {
1367 int nIndex
= (nLower
+ nUpper
) / 2;
1368 const sal_uInt32
* pEntry
= &pCMAP12
[ 4 + 3*nIndex
];
1369 sal_uInt32 cStart
= Int32FromMOTA( pEntry
[0] );
1370 sal_uInt32 cLast
= Int32FromMOTA( pEntry
[1] );
1371 if( cChar
< cStart
)
1373 else if( cChar
> cLast
)
1374 nLower
= nIndex
+ 1;
1375 else { /* found matching entry! */
1376 sal_uInt32 nGlyph
= Int32FromMOTA( pEntry
[2] );
1377 nGlyph
+= cChar
- cStart
;
1382 return MISSING_GLYPH_INDEX
;
1386 static void FindCmap(TrueTypeFont
*ttf
)
1388 const sal_uInt8
* table
= getTable(ttf
, O_cmap
);
1389 sal_uInt32 table_size
= getTableSize(ttf
, O_cmap
);
1390 sal_uInt16 ncmaps
= GetUInt16(table
, 2, 1);
1392 sal_uInt32 ThreeZero
= 0; /* MS Symbol */
1393 sal_uInt32 ThreeOne
= 0; /* MS UCS-2 */
1394 sal_uInt32 ThreeTwo
= 0; /* MS ShiftJIS */
1395 sal_uInt32 ThreeThree
= 0; /* MS Big5 */
1396 sal_uInt32 ThreeFour
= 0; /* MS PRC */
1397 sal_uInt32 ThreeFive
= 0; /* MS Wansung */
1398 sal_uInt32 ThreeSix
= 0; /* MS Johab */
1400 for (i
= 0; i
< ncmaps
; i
++) {
1402 sal_uInt16 pID
, eID
;
1404 /* sanity check, cmap entry must lie within table */
1405 if( i
*8+4 > table_size
)
1408 pID
= GetUInt16(table
, 4 + i
* 8, 1);
1409 eID
= GetUInt16(table
, 6 + i
* 8, 1);
1410 offset
= GetUInt32(table
, 8 + i
* 8, 1);
1412 /* sanity check, cmap must lie within file */
1413 if( (table
- ttf
->ptr
) + offset
> (sal_uInt32
)ttf
->fsize
)
1416 /* Unicode tables in Apple fonts */
1418 ThreeOne
= offset
; break;
1423 case 0: ThreeZero
= offset
; break;
1425 case 1: ThreeOne
= offset
; break;
1426 case 2: ThreeTwo
= offset
; break;
1427 case 3: ThreeThree
= offset
; break;
1428 case 4: ThreeFour
= offset
; break;
1429 case 5: ThreeFive
= offset
; break;
1430 case 6: ThreeSix
= offset
; break;
1436 ttf
->cmapType
= CMAP_MS_Unicode
;
1437 ttf
->cmap
= table
+ ThreeOne
;
1438 } else if (ThreeTwo
) {
1439 ttf
->cmapType
= CMAP_MS_ShiftJIS
;
1440 ttf
->cmap
= table
+ ThreeTwo
;
1441 } else if (ThreeThree
) {
1442 ttf
->cmapType
= CMAP_MS_Big5
;
1443 ttf
->cmap
= table
+ ThreeThree
;
1444 } else if (ThreeFour
) {
1445 ttf
->cmapType
= CMAP_MS_PRC
;
1446 ttf
->cmap
= table
+ ThreeFour
;
1447 } else if (ThreeFive
) {
1448 ttf
->cmapType
= CMAP_MS_Wansung
;
1449 ttf
->cmap
= table
+ ThreeFive
;
1450 } else if (ThreeSix
) {
1451 ttf
->cmapType
= CMAP_MS_Johab
;
1452 ttf
->cmap
= table
+ ThreeSix
;
1453 } else if (ThreeZero
) {
1454 ttf
->cmapType
= CMAP_MS_Symbol
;
1455 ttf
->cmap
= table
+ ThreeZero
;
1457 ttf
->cmapType
= CMAP_NOT_USABLE
;
1461 if (ttf
->cmapType
!= CMAP_NOT_USABLE
) {
1462 switch (GetUInt16(ttf
->cmap
, 0, 1)) {
1463 case 0: ttf
->mapper
= getGlyph0
; break;
1464 case 2: ttf
->mapper
= getGlyph2
; break;
1465 case 4: ttf
->mapper
= getGlyph4
; break;
1466 case 6: ttf
->mapper
= getGlyph6
; break;
1467 case 12: ttf
->mapper
= getGlyph12
; break;
1469 #if OSL_DEBUG_LEVEL > 1
1470 /*- if the cmap table is really broken */
1471 printf("%s: %d is not a recognized cmap format.\n", ttf
->fname
, GetUInt16(ttf
->cmap
, 0, 1));
1473 ttf
->cmapType
= CMAP_NOT_USABLE
;
1480 static void GetKern(TrueTypeFont
*ttf
)
1482 const sal_uInt8
* table
= getTable(ttf
, O_kern
);
1483 const sal_uInt8
*ptr
;
1488 if (GetUInt16(table
, 0, 1) == 0) { /* Traditional Microsoft style table with USHORT version and nTables fields */
1489 ttf
->nkern
= GetUInt16(table
, 2, 1);
1490 ttf
->kerntables
= (const sal_uInt8
**)calloc(ttf
->nkern
, sizeof(sal_uInt8
*));
1491 assert(ttf
->kerntables
!= 0);
1492 memset(ttf
->kerntables
, 0, ttf
->nkern
* sizeof(sal_uInt8
*));
1493 ttf
->kerntype
= KT_MICROSOFT
;
1495 for( unsigned i
= 0; i
< ttf
->nkern
; ++i
) {
1496 ttf
->kerntables
[i
] = ptr
;
1497 ptr
+= GetUInt16(ptr
, 2, 1);
1499 if( ptr
> ttf
->ptr
+ttf
->fsize
)
1501 free( ttf
->kerntables
);
1508 if (GetUInt32(table
, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */
1509 ttf
->nkern
= GetUInt32(table
, 4, 1);
1510 ttf
->kerntables
= (const sal_uInt8
**)calloc(ttf
->nkern
, sizeof(sal_uInt8
*));
1511 assert(ttf
->kerntables
!= 0);
1512 memset(ttf
->kerntables
, 0, ttf
->nkern
* sizeof(sal_uInt8
*));
1513 ttf
->kerntype
= KT_APPLE_NEW
;
1515 for( unsigned i
= 0; i
< ttf
->nkern
; ++i
) {
1516 ttf
->kerntables
[i
] = ptr
;
1517 ptr
+= GetUInt32(ptr
, 0, 1);
1518 /* sanity check; there are some fonts that are broken in this regard */
1519 if( ptr
> ttf
->ptr
+ttf
->fsize
)
1521 free( ttf
->kerntables
);
1529 ttf
->kerntype
= KT_NONE
;
1530 ttf
->kerntables
= 0;
1536 /* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and
1537 * that x and y elements of the kern array are initialized to zeroes
1539 static void KernGlyphsPrim1(TrueTypeFont
*ttf
, sal_uInt16
*glyphs
, int nglyphs
, int wmode
, KernData
*kern
)
1541 (void)ttf
; /* avoid warning */
1542 (void)glyphs
; /* avoid warning */
1543 (void)nglyphs
; /* avoid warning */
1544 (void)wmode
; /* avoid warning */
1545 (void)nglyphs
; /* avoid warning */
1546 (void)kern
; /* avoid warning */
1547 fprintf(stderr
, "MacOS kerning tables have not been implemented yet!\n");
1550 static void KernGlyphsPrim2(TrueTypeFont
*ttf
, sal_uInt16
*glyphs
, int nglyphs
, int wmode
, KernData
*kern
)
1558 for (i
= 0; i
< (sal_uInt32
)nglyphs
- 1; i
++) {
1559 gpair
= (glyphs
[i
] << 16) | glyphs
[i
+1];
1561 /* All fonts with MS kern table that I've seen so far contain just one kern subtable.
1562 * MS kern documentation is very poor and I doubt that font developers will be using
1563 * several subtables. I expect them to be using OpenType tables instead.
1564 * According to MS documention, format 2 subtables are not supported by Windows and OS/2.
1566 if (ttf
->nkern
> 1) {
1567 fprintf(stderr
, "KernGlyphsPrim2: %d kern tables found.\n", ttf
->nkern
);
1570 for (j
= 0; j
< ttf
->nkern
; j
++) {
1571 sal_uInt16 coverage
= GetUInt16(ttf
->kerntables
[j
], 4, 1);
1577 if (! ((coverage
& 1) ^ wmode
)) continue;
1578 if ((coverage
& 0xFFFE) != 0) {
1580 fprintf(stderr
, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage
);
1584 ptr
= ttf
->kerntables
[j
];
1585 npairs
= GetUInt16(ptr
, 6, 1);
1591 t
= GetUInt32(ptr
, k
* 6, 1);
1592 if (gpair
>= t
) l
= k
+ 1;
1593 if (gpair
<= t
) r
= k
- 1;
1597 kern
[i
].x
= XUnits(ttf
->unitsPerEm
, GetInt16(ptr
, 4 + (l
-1) * 6, 1));
1599 kern
[i
].y
= XUnits(ttf
->unitsPerEm
, GetInt16(ptr
, 4 + (l
-1) * 6, 1));
1601 /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */
1608 /*- Public functions */ /*FOLD00*/
1610 int CountTTCFonts(const char* fname
)
1613 sal_uInt8 buffer
[12];
1614 FILE* fd
= fopen(fname
, "rb");
1616 if (fread(buffer
, 1, 12, fd
) == 12) {
1617 if(GetUInt32(buffer
, 0, 1) == T_ttcf
)
1618 nFonts
= GetUInt32(buffer
, 8, 1);
1625 static void allocTrueTypeFont( TrueTypeFont
** ttf
)
1627 *ttf
= (TrueTypeFont
*)calloc(1,sizeof(TrueTypeFont
));
1634 (*ttf
)->nglyphs
= 0xFFFFFFFF;
1635 (*ttf
)->pGSubstitution
= 0;
1639 /* forward declariotn for the two entry points to use*/
1640 static int doOpenTTFont( sal_uInt32 facenum
, TrueTypeFont
* t
);
1642 #if !defined(WIN32) && !defined(OS2)
1643 int OpenTTFontFile( const char* fname
, sal_uInt32 facenum
, TrueTypeFont
** ttf
)
1648 if (!fname
|| !*fname
) return SF_BADFILE
;
1650 allocTrueTypeFont( ttf
);
1654 (*ttf
)->fname
= strdup(fname
);
1655 if( ! (*ttf
)->fname
)
1661 fd
= open(fname
, O_RDONLY
);
1668 if (fstat(fd
, &st
) == -1) {
1673 (*ttf
)->fsize
= st
.st_size
;
1675 /* On Mac OS, most likely will happen if a Mac user renames a font file
1676 * to be .ttf when its really a Mac resource-based font.
1677 * Size will be 0, but fonts smaller than 4 bytes would be broken anyway.
1679 if ((*ttf
)->fsize
== 0) {
1685 if (((*ttf
)->ptr
= (sal_uInt8
*) mmap(0, (*ttf
)->fsize
, PROT_READ
, MAP_SHARED
, fd
, 0)) == MAP_FAILED
) {
1691 return doOpenTTFont( facenum
, *ttf
);
1694 if (fd
!= -1) close(fd
);
1695 /*- t and t->fname have been allocated! */
1696 free((*ttf
)->fname
);
1703 int OpenTTFontBuffer(void* pBuffer
, sal_uInt32 nLen
, sal_uInt32 facenum
, TrueTypeFont
** ttf
)
1705 allocTrueTypeFont( ttf
);
1709 (*ttf
)->fname
= NULL
;
1710 (*ttf
)->fsize
= nLen
;
1711 (*ttf
)->ptr
= (sal_uInt8
*)pBuffer
;
1713 return doOpenTTFont( facenum
, *ttf
);
1716 static int doOpenTTFont( sal_uInt32 facenum
, TrueTypeFont
* t
)
1719 sal_uInt32 length
, tag
;
1720 sal_uInt32 tdoffset
= 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */
1723 sal_uInt32 version
= GetInt32(t
->ptr
, 0, 1);
1725 if ((version
== 0x00010000) || (version
== T_true
)) {
1727 } else if (version
== T_otto
) { /* PS-OpenType font */
1729 } else if (version
== T_ttcf
) { /* TrueType collection */
1730 if (GetUInt32(t
->ptr
, 4, 1) != 0x00010000) {
1734 if (facenum
>= GetUInt32(t
->ptr
, 8, 1)) {
1738 tdoffset
= GetUInt32(t
->ptr
, 12 + 4 * facenum
, 1);
1745 fprintf(stderr
, "tdoffset: %d\n", tdoffset
);
1749 t
->tag
= TTFontClassTag
;
1751 t
->ntables
= GetUInt16(t
->ptr
+ tdoffset
, 4, 1);
1752 if( t
->ntables
>= 128 )
1755 t
->tables
= (const sal_uInt8
**)calloc(NUM_TAGS
, sizeof(sal_uInt8
*));
1756 assert(t
->tables
!= 0);
1757 t
->tlens
= (sal_uInt32
*)calloc(NUM_TAGS
, sizeof(sal_uInt32
));
1758 assert(t
->tlens
!= 0);
1760 memset(t
->tables
, 0, NUM_TAGS
* sizeof(void *));
1761 memset(t
->tlens
, 0, NUM_TAGS
* sizeof(sal_uInt32
));
1763 /* parse the tables */
1764 for (i
=0; i
<(int)t
->ntables
; i
++) {
1766 tag
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
, 1);
1768 case T_maxp
: nIndex
= O_maxp
; break;
1769 case T_glyf
: nIndex
= O_glyf
; break;
1770 case T_head
: nIndex
= O_head
; break;
1771 case T_loca
: nIndex
= O_loca
; break;
1772 case T_name
: nIndex
= O_name
; break;
1773 case T_hhea
: nIndex
= O_hhea
; break;
1774 case T_hmtx
: nIndex
= O_hmtx
; break;
1775 case T_cmap
: nIndex
= O_cmap
; break;
1776 case T_vhea
: nIndex
= O_vhea
; break;
1777 case T_vmtx
: nIndex
= O_vmtx
; break;
1778 case T_OS2
: nIndex
= O_OS2
; break;
1779 case T_post
: nIndex
= O_post
; break;
1780 case T_kern
: nIndex
= O_kern
; break;
1781 case T_cvt
: nIndex
= O_cvt
; break;
1782 case T_prep
: nIndex
= O_prep
; break;
1783 case T_fpgm
: nIndex
= O_fpgm
; break;
1784 case T_gsub
: nIndex
= O_gsub
; break;
1785 case T_CFF
: nIndex
= O_CFF
; break;
1786 default: nIndex
= -1; break;
1789 sal_uInt32 nTableOffset
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
+ 8, 1);
1790 length
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
+ 12, 1);
1791 t
->tables
[nIndex
] = t
->ptr
+ nTableOffset
;
1792 t
->tlens
[nIndex
] = length
;
1796 /* Fixup offsets when only a TTC extract was provided */
1797 if( facenum
== (sal_uInt32
)~0 ) {
1798 sal_uInt8
* pHead
= (sal_uInt8
*)t
->tables
[O_head
];
1801 /* limit Head candidate to TTC extract's limits */
1802 if( pHead
> t
->ptr
+ (t
->fsize
- 54) )
1803 pHead
= t
->ptr
+ (t
->fsize
- 54);
1804 /* TODO: find better method than searching head table's magic */
1805 sal_uInt8
* p
= NULL
;
1806 for( p
= pHead
+ 12; p
> t
->ptr
; --p
) {
1807 if( p
[0]==0x5F && p
[1]==0x0F && p
[2]==0x3C && p
[3]==0xF5 ) {
1808 int nDelta
= (pHead
+ 12) - p
, j
;
1810 for( j
=0; j
<NUM_TAGS
; ++j
)
1812 *(char**)&t
->tables
[j
] -= nDelta
;
1820 /* Check the table offsets after TTC correction */
1821 for (i
=0; i
<NUM_TAGS
; i
++) {
1822 /* sanity check: table must lay completely within the file
1823 * at this point one could check the checksum of all contained
1824 * tables, but this would be quite time intensive.
1825 * Try to fix tables, so we can cope with minor problems.
1828 if( (sal_uInt8
*)t
->tables
[i
] < t
->ptr
)
1830 #if OSL_DEBUG_LEVEL > 1
1832 fprintf( stderr
, "font file %s has bad table offset %d (tagnum=%d)\n", t
->fname
, (sal_uInt8
*)t
->tables
[i
]-t
->ptr
, i
);
1835 t
->tables
[i
] = NULL
;
1837 else if( (sal_uInt8
*)t
->tables
[i
] + t
->tlens
[i
] > t
->ptr
+ t
->fsize
)
1839 int nMaxLen
= (t
->ptr
+ t
->fsize
) - (sal_uInt8
*)t
->tables
[i
];
1842 t
->tlens
[i
] = nMaxLen
;
1843 #if OSL_DEBUG_LEVEL > 1
1844 fprintf( stderr
, "font file %s has too big table (tagnum=%d)\n", t
->fname
, i
);
1849 /* At this point TrueTypeFont is constructed, now need to verify the font format
1850 and read the basic font properties */
1852 /* The following tables are absolutely required:
1853 * maxp, head, name, cmap
1856 if( !(getTable(t
, O_maxp
) && getTable(t
, O_head
) && getTable(t
, O_name
) && getTable(t
, O_cmap
)) ) {
1861 const sal_uInt8
* table
= getTable(t
, O_maxp
);
1862 t
->nglyphs
= GetUInt16(table
, 4, 1);
1864 table
= getTable(t
, O_head
);
1865 t
->unitsPerEm
= GetUInt16(table
, 18, 1);
1866 indexfmt
= GetInt16(table
, 50, 1);
1868 if( ((indexfmt
!= 0) && (indexfmt
!= 1)) || (t
->unitsPerEm
<= 0) ) {
1873 if( getTable(t
, O_glyf
) && getTable(t
, O_loca
) ) { /* TTF or TTF-OpenType */
1874 k
= (getTableSize(t
, O_loca
) / (indexfmt
? 4 : 2)) - 1;
1875 if( k
< (int)t
->nglyphs
) /* Hack for broken Chinese fonts */
1878 table
= getTable(t
, O_loca
);
1879 t
->goffsets
= (sal_uInt32
*) calloc(1+t
->nglyphs
, sizeof(sal_uInt32
));
1880 assert(t
->goffsets
!= 0);
1882 for( i
= 0; i
<= (int)t
->nglyphs
; ++i
)
1883 t
->goffsets
[i
] = indexfmt
? GetUInt32(table
, i
<< 2, 1) : (sal_uInt32
)GetUInt16(table
, i
<< 1, 1) << 1;
1884 } else if( getTable(t
, O_CFF
) ) { /* PS-OpenType */
1885 t
->goffsets
= (sal_uInt32
*) calloc(1+t
->nglyphs
, sizeof(sal_uInt32
));
1886 /* TODO: implement to get subsetting */
1887 assert(t
->goffsets
!= 0);
1893 table
= getTable(t
, O_hhea
);
1894 t
->numberOfHMetrics
= (table
!= 0) ? GetUInt16(table
, 34, 1) : 0;
1896 table
= getTable(t
, O_vhea
);
1897 t
->numOfLongVerMetrics
= (table
!= 0) ? GetUInt16(table
, 34, 1) : 0;
1902 ReadGSUB( t
, 0, 0 );
1907 void CloseTTFont(TrueTypeFont
*ttf
) /*FOLD01*/
1909 if (ttf
->tag
!= TTFontClassTag
) return;
1911 #if !defined(WIN32) && !defined(OS2)
1913 munmap((char *) ttf
->ptr
, ttf
->fsize
);
1916 free(ttf
->goffsets
);
1920 free( ttf
->ufamily
);
1921 free(ttf
->subfamily
);
1922 if( ttf
->usubfamily
)
1923 free( ttf
->usubfamily
);
1926 free(ttf
->kerntables
);
1934 int GetTTGlyphPoints(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
)
1936 return GetTTGlyphOutline(ttf
, glyphID
, pointArray
, 0, 0);
1939 int GetTTGlyphComponents(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, std::vector
< sal_uInt32
>& glyphlist
)
1943 if( glyphID
>= ttf
->nglyphs
)
1946 const sal_uInt8
* glyf
= getTable(ttf
, O_glyf
);
1947 const sal_uInt8
* ptr
= glyf
+ ttf
->goffsets
[glyphID
];
1949 glyphlist
.push_back( glyphID
);
1951 if (GetInt16(ptr
, 0, 1) == -1) {
1952 sal_uInt16 flags
, index
;
1955 flags
= GetUInt16(ptr
, 0, 1);
1956 index
= GetUInt16(ptr
, 2, 1);
1959 n
+= GetTTGlyphComponents(ttf
, index
, glyphlist
);
1961 if (flags
& ARG_1_AND_2_ARE_WORDS
) {
1967 if (flags
& WE_HAVE_A_SCALE
) {
1969 } else if (flags
& WE_HAVE_AN_X_AND_Y_SCALE
) {
1971 } else if (flags
& WE_HAVE_A_TWO_BY_TWO
) {
1974 } while (flags
& MORE_COMPONENTS
);
1981 int CreateT3FromTTGlyphs(TrueTypeFont
*ttf
, FILE *outf
, const char *fname
, /*FOLD00*/
1982 sal_uInt16
*glyphArray
, sal_uInt8
*encoding
, int nGlyphs
,
1986 PSPathElement
*path
;
1988 const sal_uInt8
* table
= getTable(ttf
, O_head
);
1989 TTGlyphMetrics metrics
;
1990 int UPEm
= ttf
->unitsPerEm
;
1992 const char *h01
= "%%!PS-AdobeFont-%d.%d-%d.%d\n";
1993 const char *h02
= "%% Creator: %s %s %s\n";
1994 const char *h09
= "%% Original font name: %s\n";
1998 "/PaintType 0 def\n"
2000 "/StrokeWidth 0 def\n";
2002 const char *h11
= "/FontName (%s) cvn def\n";
2005 const char *h12 = "%/UniqueID %d def\n";
2007 const char *h13
= "/FontMatrix [.001 0 0 .001 0 0] def\n";
2008 const char *h14
= "/FontBBox [%d %d %d %d] def\n";
2011 "/Encoding 256 array def\n"
2012 " 0 1 255 {Encoding exch /.notdef put} for\n";
2014 const char *h16
= " Encoding %d /glyph%d put\n";
2015 const char *h17
= "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n";
2017 const char *h30
= "/CharProcs %d dict def\n";
2018 const char *h31
= " CharProcs begin\n";
2019 const char *h32
= " /.notdef {} def\n";
2020 const char *h33
= " /glyph%d {\n";
2021 const char *h34
= " } bind def\n";
2022 const char *h35
= " end\n";
2026 " exch /CharProcs get exch\n"
2027 " 2 copy known not\n"
2028 " {pop /.notdef} if\n"
2032 " 1 index /Encoding get exch get\n"
2033 " 1 index /BuildGlyph get exec\n"
2035 "currentdict end\n";
2037 const char *h41
= "(%s) cvn exch definefont pop\n";
2040 if (!((nGlyphs
> 0) && (nGlyphs
<= 256))) return SF_GLYPHNUM
;
2041 if (!glyphArray
) return SF_BADARG
;
2042 if (!fname
) fname
= ttf
->psname
;
2044 fprintf(outf
, h01
, GetInt16(table
, 0, 1), GetUInt16(table
, 2, 1), GetInt16(table
, 4, 1), GetUInt16(table
, 6, 1));
2045 fprintf(outf
, h02
, modname
, modver
, modextra
);
2046 fprintf(outf
, h09
, ttf
->psname
);
2048 fprintf(outf
, "%s", h10
);
2049 fprintf(outf
, h11
, fname
);
2050 /* fprintf(outf, h12, 4000000); */
2053 * 103 0 0 C1 C2 C3 C4
2054 * C1 - CRC-32 of the entire source TrueType font
2055 * C2 - number of glyphs in the subset
2056 * C3 - CRC-32 of the glyph array
2057 * C4 - CRC-32 of the encoding array
2059 * All CRC-32 numbers are presented as hexadecimal numbers
2062 fprintf(outf
, h17
, rtl_crc32(0, ttf
->ptr
, ttf
->fsize
), nGlyphs
, rtl_crc32(0, glyphArray
, nGlyphs
* 2), rtl_crc32(0, encoding
, nGlyphs
));
2063 fprintf(outf
, "%s", h13
);
2064 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)));
2065 fprintf(outf
, "%s", h15
);
2067 for (i
= 0; i
< nGlyphs
; i
++) {
2068 fprintf(outf
, h16
, encoding
[i
], i
);
2071 fprintf(outf
, h30
, nGlyphs
+1);
2072 fprintf(outf
, "%s", h31
);
2073 fprintf(outf
, "%s", h32
);
2075 for (i
= 0; i
< nGlyphs
; i
++) {
2076 fprintf(outf
, h33
, i
);
2077 r
= GetTTGlyphOutline(ttf
, glyphArray
[i
] < ttf
->nglyphs
? glyphArray
[i
] : 0, &pa
, &metrics
, 0);
2080 n
= BSplineToPSPath(pa
, r
, &path
);
2082 n
= 0; /* glyph might have zero contours but valid metrics ??? */
2084 if (r
< 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */
2088 fprintf(outf
, "\t%d %d %d %d %d %d setcachedevice\n",
2089 wmode
== 0 ? XUnits(UPEm
, metrics
.aw
) : 0,
2090 wmode
== 0 ? 0 : -XUnits(UPEm
, metrics
.ah
),
2091 XUnits(UPEm
, metrics
.xMin
),
2092 XUnits(UPEm
, metrics
.yMin
),
2093 XUnits(UPEm
, metrics
.xMax
),
2094 XUnits(UPEm
, metrics
.yMax
));
2096 for (j
= 0; j
< n
; j
++)
2098 switch (path
[j
].type
)
2101 fprintf(outf
, "\t%d %d moveto\n", XUnits(UPEm
, path
[j
].x1
), XUnits(UPEm
, path
[j
].y1
));
2105 fprintf(outf
, "\t%d %d lineto\n", XUnits(UPEm
, path
[j
].x1
), XUnits(UPEm
, path
[j
].y1
));
2109 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
));
2113 fprintf(outf
, "\tclosepath\n");
2119 if (n
> 0) fprintf(outf
, "\tfill\n"); /* if glyph is not a whitespace character */
2121 fprintf(outf
, "%s", h34
);
2126 fprintf(outf
, "%s", h35
);
2128 fprintf(outf
, "%s", h40
);
2129 fprintf(outf
, h41
, fname
);
2136 int CreateTTFromTTGlyphs(TrueTypeFont
*ttf
,
2138 sal_uInt16
*glyphArray
,
2139 sal_uInt8
*encoding
,
2145 TrueTypeCreator
*ttcr
;
2146 TrueTypeTable
*head
=0, *hhea
=0, *maxp
=0, *cvt
=0, *prep
=0, *glyf
=0, *fpgm
=0, *cmap
=0, *name
=0, *post
= 0, *os2
= 0;
2150 TrueTypeCreatorNewEmpty(T_true
, &ttcr
);
2154 if (flags
& TTCF_AutoName
) {
2155 /* not implemented yet
2158 int n = GetTTNameRecords(ttf, &names);
2159 int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
2161 sal_uInt8 suffix[32];
2162 sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2);
2163 sal_uInt32 c2 = crc32(encoding, nGlyphs);
2165 snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs);
2167 name = TrueTypeTableNew_name(0, 0);
2168 for (i = 0; i < n; i++) {
2169 if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) {
2171 memcpy(newname, names+i, sizeof(NameRecord));
2172 newname.slen = name[i].slen + strlen(suffix);
2174 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'};
2175 NameRecord n1
= {1, 0, 0, 6, 14, (sal_uInt8
*)"TrueTypeSubset"};
2176 NameRecord n2
= {3, 1, 1033, 6, 28, 0};
2177 n2
.sptr
= (sal_uInt8
*) ptr
;
2178 name
= TrueTypeTableNew_name(0, 0);
2182 if (nNameRecs
== 0) {
2184 int n
= GetTTNameRecords(ttf
, &names
);
2185 name
= TrueTypeTableNew_name(n
, names
);
2186 DisposeNameRecords(names
, n
);
2188 name
= TrueTypeTableNew_name(nNameRecs
, nr
);
2193 maxp
= TrueTypeTableNew_maxp(getTable(ttf
, O_maxp
), getTableSize(ttf
, O_maxp
));
2196 const sal_uInt8
* p
= getTable(ttf
, O_hhea
);
2198 hhea
= TrueTypeTableNew_hhea(GetUInt16(p
, 4, 1), GetUInt16(p
, 6, 1), GetUInt16(p
, 8, 1), GetUInt16(p
, 18, 1), GetUInt16(p
, 20, 1));
2200 hhea
= TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2205 p
= getTable(ttf
, O_head
);
2207 head
= TrueTypeTableNew_head(GetUInt32(p
, 4, 1),
2208 GetUInt16(p
, 16, 1),
2209 GetUInt16(p
, 18, 1),
2211 GetUInt16(p
, 44, 1),
2212 GetUInt16(p
, 46, 1),
2213 GetInt16(p
, 48, 1));
2218 glyf
= TrueTypeTableNew_glyf();
2219 sal_uInt32
* gID
= (sal_uInt32
*)scalloc(nGlyphs
, sizeof(sal_uInt32
));
2221 for (i
= 0; i
< nGlyphs
; i
++) {
2222 gID
[i
] = glyfAdd(glyf
, GetTTRawGlyphData(ttf
, glyphArray
[i
]), ttf
);
2226 cmap
= TrueTypeTableNew_cmap();
2228 for (i
=0; i
< nGlyphs
; i
++) {
2229 cmapAdd(cmap
, 0x010000, encoding
[i
], gID
[i
]);
2233 if ((p
= getTable(ttf
, O_cvt
)) != 0) {
2234 cvt
= TrueTypeTableNew(T_cvt
, getTableSize(ttf
, O_cvt
), p
);
2238 if ((p
= getTable(ttf
, O_prep
)) != 0) {
2239 prep
= TrueTypeTableNew(T_prep
, getTableSize(ttf
, O_prep
), p
);
2243 if ((p
= getTable(ttf
, O_fpgm
)) != 0) {
2244 fpgm
= TrueTypeTableNew(T_fpgm
, getTableSize(ttf
, O_fpgm
), p
);
2248 if ((p
= getTable(ttf
, O_post
)) != 0) {
2249 post
= TrueTypeTableNew_post(0x00030000,
2252 GetUInt16(p
, 10, 1),
2253 GetUInt16(p
, 12, 1));
2255 post
= TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
2258 if (flags
& TTCF_IncludeOS2
) {
2259 if ((p
= getTable(ttf
, O_OS2
)) != 0) {
2260 os2
= TrueTypeTableNew(T_OS2
, getTableSize(ttf
, O_OS2
), p
);
2264 AddTable(ttcr
, name
); AddTable(ttcr
, maxp
); AddTable(ttcr
, hhea
);
2265 AddTable(ttcr
, head
); AddTable(ttcr
, glyf
); AddTable(ttcr
, cmap
);
2266 AddTable(ttcr
, cvt
); AddTable(ttcr
, prep
); AddTable(ttcr
, fpgm
);
2267 AddTable(ttcr
, post
); AddTable(ttcr
, os2
);
2269 if ((res
= StreamToFile(ttcr
, fname
)) != SF_OK
) {
2270 #if OSL_DEBUG_LEVEL > 1
2271 fprintf(stderr
, "StreamToFile: error code: %d.\n", res
);
2275 TrueTypeCreatorDispose(ttcr
);
2284 static GlyphOffsets
*GlyphOffsetsNew(sal_uInt8
*sfntP
)
2286 GlyphOffsets
* res
= (GlyphOffsets
*)smalloc(sizeof(GlyphOffsets
));
2287 sal_uInt8
*loca
= NULL
;
2288 sal_uInt16 i
, numTables
= GetUInt16(sfntP
, 4, 1);
2289 sal_uInt32 locaLen
= 0;
2290 sal_Int16 indexToLocFormat
= 0;
2292 for (i
= 0; i
< numTables
; i
++) {
2293 sal_uInt32 tag
= GetUInt32(sfntP
+ 12, 16 * i
, 1);
2294 sal_uInt32 off
= GetUInt32(sfntP
+ 12, 16 * i
+ 8, 1);
2295 sal_uInt32 len
= GetUInt32(sfntP
+ 12, 16 * i
+ 12, 1);
2297 if (tag
== T_loca
) {
2300 } else if (tag
== T_head
) {
2301 indexToLocFormat
= GetInt16(sfntP
+ off
, 50, 1);
2305 res
->nGlyphs
= locaLen
/ ((indexToLocFormat
== 1) ? 4 : 2);
2306 assert(res
->nGlyphs
!= 0);
2307 res
->offs
= (sal_uInt32
*)scalloc(res
->nGlyphs
, sizeof(sal_uInt32
));
2309 for (i
= 0; i
< res
->nGlyphs
; i
++) {
2310 if (indexToLocFormat
== 1) {
2311 res
->offs
[i
] = GetUInt32(loca
, i
* 4, 1);
2313 res
->offs
[i
] = GetUInt16(loca
, i
* 2, 1) << 1;
2319 static void GlyphOffsetsDispose(GlyphOffsets
*_this
)
2327 static void DumpSfnts(FILE *outf
, sal_uInt8
*sfntP
)
2329 HexFmt
*h
= HexFmtNew(outf
);
2330 sal_uInt16 i
, numTables
= GetUInt16(sfntP
, 4, 1);
2331 GlyphOffsets
*go
= GlyphOffsetsNew(sfntP
);
2332 sal_uInt8 pad
[] = {0,0,0,0}; /* zeroes */
2334 assert(numTables
<= 9); /* Type42 has 9 required tables */
2336 sal_uInt32
* offs
= (sal_uInt32
*)scalloc(numTables
, sizeof(sal_uInt32
));
2337 // sal_uInt32* lens = (sal_uInt32*)scalloc(numTables, sizeof(sal_uInt32));
2339 fputs("/sfnts [", outf
);
2340 HexFmtOpenString(h
);
2341 HexFmtBlockWrite(h
, sfntP
, 12); /* stream out the Offset Table */
2342 HexFmtBlockWrite(h
, sfntP
+12, 16 * numTables
); /* stream out the Table Directory */
2344 for (i
=0; i
<numTables
; i
++) {
2345 sal_uInt32 tag
= GetUInt32(sfntP
+ 12, 16 * i
, 1);
2346 sal_uInt32 off
= GetUInt32(sfntP
+ 12, 16 * i
+ 8, 1);
2347 sal_uInt32 len
= GetUInt32(sfntP
+ 12, 16 * i
+ 12, 1);
2349 if (tag
!= T_glyf
) {
2350 HexFmtBlockWrite(h
, sfntP
+ off
, len
);
2352 sal_uInt8
*glyf
= sfntP
+ off
;
2354 for (j
= 0; j
< go
->nGlyphs
- 1; j
++) {
2356 l
= go
->offs
[j
+ 1] - o
;
2357 HexFmtBlockWrite(h
, glyf
+ o
, l
);
2360 HexFmtBlockWrite(h
, pad
, (4 - (len
& 3)) & 3);
2362 HexFmtCloseString(h
);
2363 fputs("] def\n", outf
);
2364 GlyphOffsetsDispose(go
);
2370 int CreateT42FromTTGlyphs(TrueTypeFont
*ttf
,
2373 sal_uInt16
*glyphArray
,
2374 sal_uInt8
*encoding
,
2377 TrueTypeCreator
*ttcr
;
2378 TrueTypeTable
*head
=0, *hhea
=0, *maxp
=0, *cvt
=0, *prep
=0, *glyf
=0, *fpgm
=0;
2382 sal_uInt32 ver
, rev
;
2386 int UPEm
= ttf
->unitsPerEm
;
2388 if (nGlyphs
>= 256) return SF_GLYPHNUM
;
2390 assert(psname
!= 0);
2392 TrueTypeCreatorNewEmpty(T_true
, &ttcr
);
2395 const sal_uInt8
* p
= getTable(ttf
, O_head
);
2396 const sal_uInt8
* headP
= p
;
2398 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));
2399 ver
= GetUInt32(p
, 0, 1);
2400 rev
= GetUInt32(p
, 4, 1);
2403 p
= getTable(ttf
, O_hhea
);
2405 hhea
= TrueTypeTableNew_hhea(GetUInt16(p
, 4, 1), GetUInt16(p
, 6, 1), GetUInt16(p
, 8, 1), GetUInt16(p
, 18, 1), GetUInt16(p
, 20, 1));
2407 hhea
= TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2411 maxp
= TrueTypeTableNew_maxp(getTable(ttf
, O_maxp
), getTableSize(ttf
, O_maxp
));
2414 if ((p
= getTable(ttf
, O_cvt
)) != 0) {
2415 cvt
= TrueTypeTableNew(T_cvt
, getTableSize(ttf
, O_cvt
), p
);
2419 if ((p
= getTable(ttf
, O_prep
)) != 0) {
2420 prep
= TrueTypeTableNew(T_prep
, getTableSize(ttf
, O_prep
), p
);
2424 if ((p
= getTable(ttf
, O_fpgm
)) != 0) {
2425 fpgm
= TrueTypeTableNew(T_fpgm
, getTableSize(ttf
, O_fpgm
), p
);
2429 glyf
= TrueTypeTableNew_glyf();
2430 sal_uInt16
* gID
= (sal_uInt16
*)scalloc(nGlyphs
, sizeof(sal_uInt32
));
2432 for (i
= 0; i
< nGlyphs
; i
++) {
2433 gID
[i
] = (sal_uInt16
)glyfAdd(glyf
, GetTTRawGlyphData(ttf
, glyphArray
[i
]), ttf
);
2436 AddTable(ttcr
, head
); AddTable(ttcr
, hhea
); AddTable(ttcr
, maxp
); AddTable(ttcr
, cvt
);
2437 AddTable(ttcr
, prep
); AddTable(ttcr
, glyf
); AddTable(ttcr
, fpgm
);
2439 if ((res
= StreamToMemory(ttcr
, &sfntP
, &sfntLen
)) != SF_OK
) {
2440 TrueTypeCreatorDispose(ttcr
);
2445 fprintf(outf
, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver
>>16), (int)(ver
& 0xFFFF), (int)(rev
>>16), (int)(rev
& 0xFFFF));
2446 fprintf(outf
, "%%%%Creator: %s %s %s\n", modname
, modver
, modextra
);
2447 fprintf(outf
, "%%- Font subset generated from a source font file: '%s'\n", ttf
->fname
);
2448 fprintf(outf
, "%%- Original font name: %s\n", ttf
->psname
);
2449 fprintf(outf
, "%%- Original font family: %s\n", ttf
->family
);
2450 fprintf(outf
, "%%- Original font sub-family: %s\n", ttf
->subfamily
);
2451 fprintf(outf
, "11 dict begin\n");
2452 fprintf(outf
, "/FontName (%s) cvn def\n", psname
);
2453 fprintf(outf
, "/PaintType 0 def\n");
2454 fprintf(outf
, "/FontMatrix [1 0 0 1 0 0] def\n");
2455 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)));
2456 fprintf(outf
, "/FontType 42 def\n");
2457 fprintf(outf
, "/Encoding 256 array def\n");
2458 fprintf(outf
, " 0 1 255 {Encoding exch /.notdef put} for\n");
2460 for (i
= 1; i
<nGlyphs
; i
++) {
2461 fprintf(outf
, "Encoding %d /glyph%d put\n", encoding
[i
], gID
[i
]);
2463 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
));
2465 DumpSfnts(outf
, sfntP
);
2467 /* dump charstrings */
2468 fprintf(outf
, "/CharStrings %d dict dup begin\n", nGlyphs
);
2469 fprintf(outf
, "/.notdef 0 def\n");
2470 for (i
= 1; i
< (int)glyfCount(glyf
); i
++) {
2471 fprintf(outf
,"/glyph%d %d def\n", i
, i
);
2473 fprintf(outf
, "end readonly def\n");
2475 fprintf(outf
, "FontName currentdict end definefont pop\n");
2476 TrueTypeCreatorDispose(ttcr
);
2485 int MapString(TrueTypeFont
*ttf
, sal_uInt16
*str
, int nchars
, sal_uInt16
*glyphArray
, int bvertical
)
2490 if (ttf
->cmapType
== CMAP_NOT_USABLE
) return -1;
2491 if (!nchars
) return 0;
2493 if (glyphArray
== 0) {
2499 switch (ttf
->cmapType
) {
2500 case CMAP_MS_Symbol
:
2501 if( ttf
->mapper
== getGlyph0
) {
2503 for( i
= 0; i
< nchars
; i
++ ) {
2505 if( ( aChar
& 0xf000 ) == 0xf000 )
2510 else if( glyphArray
)
2511 memcpy(glyphArray
, str
, nchars
* 2);
2514 case CMAP_MS_Unicode
:
2515 if (glyphArray
!= 0) {
2516 memcpy(glyphArray
, str
, nchars
* 2);
2520 case CMAP_MS_ShiftJIS
: TranslateString12(str
, cp
, nchars
); break;
2521 case CMAP_MS_Big5
: TranslateString13(str
, cp
, nchars
); break;
2522 case CMAP_MS_PRC
: TranslateString14(str
, cp
, nchars
); break;
2523 case CMAP_MS_Wansung
: TranslateString15(str
, cp
, nchars
); break;
2524 case CMAP_MS_Johab
: TranslateString16(str
, cp
, nchars
); break;
2527 for (i
= 0; i
< nchars
; i
++) {
2528 cp
[i
] = (sal_uInt16
)ttf
->mapper(ttf
->cmap
, cp
[i
]);
2529 if (cp
[i
]!=0 && bvertical
!=0)
2530 cp
[i
] = (sal_uInt16
)UseGSUB(ttf
,cp
[i
],bvertical
);
2535 sal_uInt16
MapChar(TrueTypeFont
*ttf
, sal_uInt16 ch
, int bvertical
)
2537 switch (ttf
->cmapType
) {
2538 case CMAP_MS_Symbol
:
2540 if( ttf
->mapper
== getGlyph0
&& ( ch
& 0xf000 ) == 0xf000 )
2542 return (sal_uInt16
)ttf
->mapper(ttf
->cmap
, ch
);
2544 case CMAP_MS_Unicode
: break;
2545 case CMAP_MS_ShiftJIS
: ch
= TranslateChar12(ch
); break;
2546 case CMAP_MS_Big5
: ch
= TranslateChar13(ch
); break;
2547 case CMAP_MS_PRC
: ch
= TranslateChar14(ch
); break;
2548 case CMAP_MS_Wansung
: ch
= TranslateChar15(ch
); break;
2549 case CMAP_MS_Johab
: ch
= TranslateChar16(ch
); break;
2552 ch
= (sal_uInt16
)ttf
->mapper(ttf
->cmap
, ch
);
2553 if (ch
!=0 && bvertical
!=0)
2554 ch
= (sal_uInt16
)UseGSUB(ttf
,ch
,bvertical
);
2558 int DoesVerticalSubstitution( TrueTypeFont
*ttf
, int bvertical
)
2562 nRet
= HasVerticalGSUB( ttf
);
2568 int GetTTGlyphCount( TrueTypeFont
* ttf
)
2570 return ttf
->nglyphs
;
2573 bool GetSfntTable( TrueTypeFont
* ttf
, int nSubtableIndex
,
2574 const sal_uInt8
** ppRawBytes
, int* pRawLength
)
2576 if( (nSubtableIndex
< 0) || (nSubtableIndex
>= NUM_TAGS
) )
2578 *pRawLength
= ttf
->tlens
[ nSubtableIndex
];
2579 *ppRawBytes
= ttf
->tables
[ nSubtableIndex
];
2580 bool bOk
= (*pRawLength
> 0) && (ppRawBytes
!= NULL
);
2584 TTSimpleGlyphMetrics
*GetTTSimpleGlyphMetrics(TrueTypeFont
*ttf
, sal_uInt16
*glyphArray
, int nGlyphs
, int mode
)
2586 const sal_uInt8
* pTable
;
2591 n
= ttf
->numberOfHMetrics
;
2592 pTable
= getTable( ttf
, O_hmtx
);
2593 nTableSize
= getTableSize( ttf
, O_hmtx
);
2595 n
= ttf
->numOfLongVerMetrics
;
2596 pTable
= getTable( ttf
, O_vmtx
);
2597 nTableSize
= getTableSize( ttf
, O_vmtx
);
2600 if (!nGlyphs
|| !glyphArray
) return 0; /* invalid parameters */
2601 if (!n
|| !pTable
) return 0; /* the font does not contain the requested metrics */
2603 TTSimpleGlyphMetrics
* res
= (TTSimpleGlyphMetrics
*)calloc(nGlyphs
, sizeof(TTSimpleGlyphMetrics
));
2606 const int UPEm
= ttf
->unitsPerEm
;
2607 for( int i
= 0; i
< nGlyphs
; ++i
) {
2608 int nAdvOffset
, nLsbOffset
;
2609 sal_uInt16 glyphID
= glyphArray
[i
];
2612 nAdvOffset
= 4 * glyphID
;
2613 nLsbOffset
= nAdvOffset
+ 2;
2615 nAdvOffset
= 4 * (n
- 1);
2616 if( glyphID
< ttf
->nglyphs
)
2617 nLsbOffset
= 4 * n
+ 2 * (glyphID
- n
);
2618 else /* font is broken -> use lsb of last hmetrics */
2619 nLsbOffset
= nAdvOffset
+ 2;
2622 if( nAdvOffset
>= nTableSize
)
2623 res
[i
].adv
= 0; /* better than a crash for buggy fonts */
2625 res
[i
].adv
= static_cast<sal_uInt16
>(
2626 XUnits( UPEm
, GetUInt16( pTable
, nAdvOffset
, 1) ) );
2628 if( nLsbOffset
>= nTableSize
)
2629 res
[i
].sb
= 0; /* better than a crash for buggy fonts */
2631 res
[i
].sb
= static_cast<sal_Int16
>(
2632 XUnits( UPEm
, GetInt16( pTable
, nLsbOffset
, 1) ) );
2639 TTSimpleGlyphMetrics
*GetTTSimpleCharMetrics(TrueTypeFont
* ttf
, sal_uInt16 firstChar
, int nChars
, int mode
)
2641 TTSimpleGlyphMetrics
*res
= 0;
2644 sal_uInt16
* str
= (sal_uInt16
*)malloc(nChars
* 2);
2647 for (i
=0; i
<nChars
; i
++) str
[i
] = (sal_uInt16
)(firstChar
+ i
);
2648 if ((n
= MapString(ttf
, str
, nChars
, 0, mode
)) != -1) {
2649 res
= GetTTSimpleGlyphMetrics(ttf
, str
, n
, mode
);
2658 void GetTTGlobalFontInfo(TrueTypeFont
*ttf
, TTGlobalFontInfo
*info
)
2660 int UPEm
= ttf
->unitsPerEm
;
2662 memset(info
, 0, sizeof(TTGlobalFontInfo
));
2664 info
->family
= ttf
->family
;
2665 info
->ufamily
= ttf
->ufamily
;
2666 info
->subfamily
= ttf
->subfamily
;
2667 info
->usubfamily
= ttf
->usubfamily
;
2668 info
->psname
= ttf
->psname
;
2669 info
->symbolEncoded
= (ttf
->cmapType
== CMAP_MS_Symbol
);
2671 const sal_uInt8
* table
= getTable(ttf
, O_OS2
);
2673 info
->weight
= GetUInt16(table
, 4, 1);
2674 info
->width
= GetUInt16(table
, 6, 1);
2676 /* There are 3 different versions of OS/2 table: original (68 bytes long),
2677 * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,)
2678 * Apple's documentation recommends looking at the table length.
2680 if (getTableSize(ttf
, O_OS2
) > 68) {
2681 info
->typoAscender
= XUnits(UPEm
,GetInt16(table
, 68, 1));
2682 info
->typoDescender
= XUnits(UPEm
, GetInt16(table
, 70, 1));
2683 info
->typoLineGap
= XUnits(UPEm
, GetInt16(table
, 72, 1));
2684 info
->winAscent
= XUnits(UPEm
, GetUInt16(table
, 74, 1));
2685 info
->winDescent
= XUnits(UPEm
, GetUInt16(table
, 76, 1));
2686 /* sanity check; some fonts treat winDescent as signed
2687 * violating the standard */
2688 if( info
->winDescent
> 5*UPEm
)
2689 info
->winDescent
= XUnits(UPEm
, GetInt16(table
, 76,1));
2691 if (ttf
->cmapType
== CMAP_MS_Unicode
) {
2692 info
->rangeFlag
= 1;
2693 info
->ur1
= GetUInt32(table
, 42, 1);
2694 info
->ur2
= GetUInt32(table
, 46, 1);
2695 info
->ur3
= GetUInt32(table
, 50, 1);
2696 info
->ur4
= GetUInt32(table
, 54, 1);
2698 memcpy(info
->panose
, table
+ 32, 10);
2699 info
->typeFlags
= GetUInt16( table
, 8, 1 );
2700 if( getTable(ttf
, O_CFF
) )
2701 info
->typeFlags
|= TYPEFLAG_PS_OPENTYPE
;
2704 table
= getTable(ttf
, O_post
);
2706 info
->pitch
= GetUInt32(table
, 12, 1);
2707 info
->italicAngle
= GetInt32(table
, 4, 1);
2710 table
= getTable(ttf
, O_head
); /* 'head' tables is always there */
2711 info
->xMin
= XUnits(UPEm
, GetInt16(table
, 36, 1));
2712 info
->yMin
= XUnits(UPEm
, GetInt16(table
, 38, 1));
2713 info
->xMax
= XUnits(UPEm
, GetInt16(table
, 40, 1));
2714 info
->yMax
= XUnits(UPEm
, GetInt16(table
, 42, 1));
2715 info
->macStyle
= GetInt16(table
, 44, 1);
2717 table
= getTable(ttf
, O_hhea
);
2719 info
->ascender
= XUnits(UPEm
, GetInt16(table
, 4, 1));
2720 info
->descender
= XUnits(UPEm
, GetInt16(table
, 6, 1));
2721 info
->linegap
= XUnits(UPEm
, GetInt16(table
, 8, 1));
2724 table
= getTable(ttf
, O_vhea
);
2726 info
->vascent
= XUnits(UPEm
, GetInt16(table
, 4, 1));
2727 info
->vdescent
= XUnits(UPEm
, GetInt16(table
, 6, 1));
2732 void KernGlyphs(TrueTypeFont
*ttf
, sal_uInt16
*glyphs
, int nglyphs
, int wmode
, KernData
*kern
)
2736 if (!nglyphs
|| !glyphs
|| !kern
) return;
2738 for (i
= 0; i
< nglyphs
-1; i
++) kern
[i
].x
= kern
[i
].y
= 0;
2740 switch (ttf
->kerntype
) {
2741 case KT_APPLE_NEW
: KernGlyphsPrim1(ttf
, glyphs
, nglyphs
, wmode
, kern
); return;
2742 case KT_MICROSOFT
: KernGlyphsPrim2(ttf
, glyphs
, nglyphs
, wmode
, kern
); return;
2748 GlyphData
*GetTTRawGlyphData(TrueTypeFont
*ttf
, sal_uInt32 glyphID
)
2750 const sal_uInt8
* glyf
= getTable(ttf
, O_glyf
);
2751 const sal_uInt8
* hmtx
= getTable(ttf
, O_hmtx
);
2754 if( glyphID
>= ttf
->nglyphs
)
2757 /* #127161# check the glyph offsets */
2758 sal_uInt32 length
= getTableSize( ttf
, O_glyf
);
2759 if( length
< ttf
->goffsets
[ glyphID
+1 ] )
2762 length
= ttf
->goffsets
[glyphID
+1] - ttf
->goffsets
[glyphID
];
2764 GlyphData
* d
= (GlyphData
*)malloc(sizeof(GlyphData
)); assert(d
!= 0);
2767 const sal_uInt8
* srcptr
= glyf
+ ttf
->goffsets
[glyphID
];
2768 d
->ptr
= (sal_uInt8
*)malloc((length
+ 1) & ~1); assert(d
->ptr
!= 0);
2769 memcpy( d
->ptr
, srcptr
, length
);
2770 d
->compflag
= (GetInt16( srcptr
, 0, 1 ) < 0);
2776 d
->glyphID
= glyphID
;
2777 d
->nbytes
= (sal_uInt16
)((length
+ 1) & ~1);
2779 /* now calculate npoints and ncontours */
2781 n
= GetTTGlyphPoints(ttf
, glyphID
, &cp
);
2784 for (i
= 0; i
< n
; i
++) {
2785 if (cp
[i
].flags
& 0x8000) m
++;
2787 d
->npoints
= (sal_uInt16
)n
;
2788 d
->ncontours
= (sal_uInt16
)m
;
2795 /* get advance width and left sidebearing */
2796 if (glyphID
< ttf
->numberOfHMetrics
) {
2797 d
->aw
= GetUInt16(hmtx
, 4 * glyphID
, 1);
2798 d
->lsb
= GetInt16(hmtx
, 4 * glyphID
+ 2, 1);
2800 d
->aw
= GetUInt16(hmtx
, 4 * (ttf
->numberOfHMetrics
- 1), 1);
2801 d
->lsb
= GetInt16(hmtx
+ ttf
->numberOfHMetrics
* 4, (glyphID
- ttf
->numberOfHMetrics
) * 2, 1);
2807 int GetTTNameRecords(TrueTypeFont
*ttf
, NameRecord
**nr
)
2809 const sal_uInt8
* table
= getTable(ttf
, O_name
);
2810 int nTableSize
= getTableSize(ttf
, O_name
);
2811 sal_uInt16 n
= GetUInt16(table
, 2, 1);
2812 int nStrBase
= GetUInt16(table
, 4, 1);
2816 if (n
== 0) return 0;
2818 NameRecord
* rec
= (NameRecord
*)calloc(n
, sizeof(NameRecord
));
2820 for (i
= 0; i
< n
; i
++) {
2821 int nStrOffset
= GetUInt16(table
+ 6, 10 + 12 * i
, 1);
2822 rec
[i
].platformID
= GetUInt16(table
+ 6, 12 * i
, 1);
2823 rec
[i
].encodingID
= GetUInt16(table
+ 6, 2 + 12 * i
, 1);
2824 rec
[i
].languageID
= GetUInt16(table
+ 6, 4 + 12 * i
, 1);
2825 rec
[i
].nameID
= GetUInt16(table
+ 6, 6 + 12 * i
, 1);
2826 rec
[i
].slen
= GetUInt16(table
+ 6, 8 + 12 * i
, 1);
2828 if( nStrBase
+nStrOffset
+rec
[i
].slen
>= nTableSize
) {
2834 const sal_uInt8
* rec_string
= table
+ nStrBase
+ nStrOffset
;
2836 if( rec_string
> (sal_uInt8
*)ttf
->ptr
&& rec_string
< ((sal_uInt8
*)ttf
->ptr
+ ttf
->fsize
- rec
[i
].slen
) )
2838 rec
[i
].sptr
= (sal_uInt8
*) malloc(rec
[i
].slen
); assert(rec
[i
].sptr
!= 0);
2839 memcpy(rec
[i
].sptr
, rec_string
, rec
[i
].slen
);
2844 fprintf( stderr
, "found invalid name record %d with name id %d for file %s\n",
2845 i
, rec
[i
].nameID
, ttf
->fname
);
2853 // some fonts have 3.0 names => fix them to 3.1
2854 if( (rec
[i
].platformID
== 3) && (rec
[i
].encodingID
== 0) )
2855 rec
[i
].encodingID
= 1;
2862 void DisposeNameRecords(NameRecord
* nr
, int n
)
2865 for (i
= 0; i
< n
; i
++) {
2866 if (nr
[i
].sptr
) free(nr
[i
].sptr
);
2875 /* This example creates a subset of a TrueType font with two encoded characters */
2876 int main(int ac
, char **av
)
2881 /* Array of Unicode source characters */
2882 sal_uInt16 chars
[2];
2884 /* Encoding vector maps character encoding to the ordinal number
2885 * of the glyph in the output file */
2886 sal_uInt8 encoding
[2];
2888 /* This array is for glyph IDs that source characters map to */
2892 if (ac
< 2) return 0;
2894 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
2895 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
2900 /* We want to create the output file that only contains two Unicode characters:
2906 /* Figure out what glyphs do these characters map in our font */
2907 MapString(fnt
, chars
, 2, g
);
2909 /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the
2910 * newly generated font */
2911 encoding
[0] = chars
[0];
2912 encoding
[1] = chars
[1];
2915 /* Generate a subset */
2916 CreateT3FromTTGlyphs(fnt
, stdout
, 0, g
, encoding
, 2, 0);
2918 /* Now call the dtor for the font */
2925 /* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */
2926 int main(int ac
, char **av
)
2931 /* Array of Unicode source characters */
2932 sal_uInt16 glyphs
[224];
2934 /* Encoding vector maps character encoding to the ordinal number
2935 * of the glyph in the output file */
2936 sal_uInt8 encoding
[224];
2940 for (i
=0; i
<224; i
++) {
2942 encoding
[i
] = 32 + i
;
2945 if (ac
< 2) return 0;
2947 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
2948 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
2953 /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the
2954 * newly generated font */
2956 /* Generate a subset */
2957 CreateT3FromTTGlyphs(fnt
, stdout
, 0, glyphs
, encoding
, 224, 0);
2959 /* Now call the dtor for the font */
2966 /* Glyph metrics example */
2967 int main(int ac
, char **av
)
2971 sal_uInt16 glyphs
[224];
2972 TTSimpleGlyphMetrics
*m
;
2974 for (i
=0; i
<224; i
++) {
2978 if (ac
< 2) return 0;
2980 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
2981 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
2985 if ((m
= GetTTSimpleGlyphMetrics(fnt
, glyphs
, 224, 0)) == 0) {
2986 printf("Requested metrics is not available\n");
2988 for (i
=0; i
<224; i
++) {
2989 printf("%d. advWid: %5d, LSBear: %5d\n", i
, m
[i
].adv
, m
[i
].sb
);
2993 /* Now call the dtor for the font */
3001 int main(int ac
, char **av
)
3004 TTGlobalFontInfo info
;
3008 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
3009 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
3013 printf("Font file: %s\n", av
[1]);
3016 switch (fnt
->kerntype
) {
3018 printf("\tkern: MICROSOFT, ntables: %d.", fnt
->nkern
);
3021 for (i
=0; i
<fnt
->nkern
; i
++) {
3022 printf("%04X ", GetUInt16(fnt
->kerntables
[i
], 4, 1));
3030 printf("\tkern: APPLE_NEW, ntables: %d.", fnt
->nkern
);
3033 for (i
=0; i
<fnt
->nkern
; i
++) {
3034 printf("%04X ", GetUInt16(fnt
->kerntables
[i
], 4, 1));
3042 printf("\tkern: none.\n");
3046 printf("\tkern: unrecoginzed.\n");
3052 GetTTGlobalFontInfo(fnt
, &info
);
3053 printf("\tfamily name: `%s`\n", info
.family
);
3054 printf("\tsubfamily name: `%s`\n", info
.subfamily
);
3055 printf("\tpostscript name: `%s`\n", info
.psname
);
3056 printf("\tweight: %d\n", info
.weight
);
3057 printf("\twidth: %d\n", info
.width
);
3058 printf("\tpitch: %d\n", info
.pitch
);
3059 printf("\titalic angle: %d\n", info
.italicAngle
);
3060 printf("\tbouding box: [%d %d %d %d]\n", info
.xMin
, info
.yMin
, info
.xMax
, info
.yMax
);
3061 printf("\tascender: %d\n", info
.ascender
);
3062 printf("\tdescender: %d\n", info
.descender
);
3063 printf("\tlinegap: %d\n", info
.linegap
);
3064 printf("\tvascent: %d\n", info
.vascent
);
3065 printf("\tvdescent: %d\n", info
.vdescent
);
3066 printf("\ttypoAscender: %d\n", info
.typoAscender
);
3067 printf("\ttypoDescender: %d\n", info
.typoDescender
);
3068 printf("\ttypoLineGap: %d\n", info
.typoLineGap
);
3069 printf("\twinAscent: %d\n", info
.winAscent
);
3070 printf("\twinDescent: %d\n", info
.winDescent
);
3071 printf("\tUnicode ranges:\n");
3072 for (i
= 0; i
< 32; i
++) {
3073 if ((info
.ur1
>> i
) & 1) {
3074 printf("\t\t\t%s\n", UnicodeRangeName(i
));
3077 for (i
= 0; i
< 32; i
++) {
3078 if ((info
.ur2
>> i
) & 1) {
3079 printf("\t\t\t%s\n", UnicodeRangeName(i
+32));
3082 for (i
= 0; i
< 32; i
++) {
3083 if ((info
.ur3
>> i
) & 1) {
3084 printf("\t\t\t%s\n", UnicodeRangeName(i
+64));
3087 for (i
= 0; i
< 32; i
++) {
3088 if ((info
.ur4
>> i
) & 1) {
3089 printf("\t\t\t%s\n", UnicodeRangeName(i
+96));
3099 /* Kerning example */
3100 int main(int ac
, char **av
)
3118 if (ac
< 2) return 0;
3120 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
3121 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
3125 KernGlyphs(fnt
, g
, k
, 0, d
);
3127 for (i
= 0; i
< k
-1; i
++) {
3128 printf("%3d %3d: [%3d %3d]\n", g
[i
], g
[i
+1], d
[i
].x
, d
[i
].y
);
3139 /* This example extracts a single glyph from a font */
3140 int main(int ac
, char **av
)
3145 sal_uInt16 glyphs
[256];
3146 sal_uInt8 encoding
[256];
3148 for (i
=0; i
<256; i
++) {
3149 glyphs
[i
] = 512 + i
;
3179 encoding
[i
++] = r
++;
3180 encoding
[i
++] = r
++;
3181 encoding
[i
++] = r
++;
3182 encoding
[i
++] = r
++;
3183 encoding
[i
++] = r
++;
3184 encoding
[i
++] = r
++;
3185 encoding
[i
++] = r
++;
3186 encoding
[i
++] = r
++;
3187 encoding
[i
++] = r
++;
3188 encoding
[i
++] = r
++;
3189 encoding
[i
++] = r
++;
3190 encoding
[i
++] = r
++;
3191 encoding
[i
++] = r
++;
3192 encoding
[i
++] = r
++;
3193 encoding
[i
++] = r
++;
3194 encoding
[i
++] = r
++;
3195 encoding
[i
++] = r
++;
3196 encoding
[i
++] = r
++;
3197 encoding
[i
++] = r
++;
3198 encoding
[i
++] = r
++;
3201 if (ac
< 2) return 0;
3203 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
3204 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
3208 /* Generate a subset */
3209 CreateT3FromTTGlyphs(fnt
, stdout
, 0, glyphs
, encoding
, 256, 0);
3211 fprintf(stderr
, "UnitsPerEm: %d.\n", fnt
->unitsPerEm
);
3213 /* Now call the dtor for the font */
3220 /* NameRecord extraction example */
3221 int main(int ac
, char **av
)
3227 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
3228 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
3232 if ((n
= GetTTNameRecords(fnt
, &nr
)) == 0) {
3233 fprintf(stderr
, "No name records in the font.\n");
3237 printf("Number of name records: %d.\n", n
);
3238 for (i
= 0; i
< n
; i
++) {
3239 printf("%d %d %04X %d [", nr
[i
].platformID
, nr
[i
].encodingID
, nr
[i
].languageID
, nr
[i
].nameID
);
3240 for (j
=0; j
<nr
[i
].slen
; j
++) {
3241 printf("%c", isprint(nr
[i
].sptr
[j
]) ? nr
[i
].sptr
[j
] : '.');
3247 DisposeNameRecords(nr
, n
);
3254 /* TrueType -> TrueType subsetting */
3255 int main(int ac
, char **av
)
3258 sal_uInt16 glyphArray
[] = { 0, 98, 99, 22, 24, 25, 26, 27, 28, 29, 30, 31, 1270, 1289, 34};
3259 sal_uInt8 encoding
[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3262 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
3263 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
3267 CreateTTFromTTGlyphs(fnt
, "subfont.ttf", glyphArray
, encoding
, 15, 0, 0, TTCF_AutoName
| TTCF_IncludeOS2
);
3277 /* TrueType -> Type42 subsetting */
3278 int main(int ac
, char **av
)
3282 sal_uInt16 glyphArray[] = { 0, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34};
3283 sal_uInt8 encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3285 sal_uInt16 glyphArray
[] = { 0, 6711, 6724, 11133, 11144, 14360, 26, 27, 28, 29, 30, 31, 1270, 1289, 34};
3286 sal_uInt8 encoding
[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
3289 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
3290 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
3294 CreateT42FromTTGlyphs(fnt
, stdout
, "testfont", glyphArray
, encoding
, 15);
3303 /* Component glyph test */
3304 int main(int ac
, char **av
)
3308 list glyphlist
= listNewEmpty();
3311 if ((r
= OpenTTFont(av
[1], 0, &fnt
)) != SF_OK
) {
3312 fprintf(stderr
, "Error %d opening font file: `%s`.\n", r
, av
[1]);
3316 for (i
= 0; i
< fnt
->nglyphs
; i
++) {
3317 r
= GetTTGlyphComponents(fnt
, i
, glyphlist
);
3319 printf("%d -> ", i
);
3320 listToFirst(glyphlist
);
3322 printf("%d ", (int) listCurrent(glyphlist
));
3323 } while (listNext(glyphlist
));
3326 printf("%d: single glyph.\n", i
);
3328 listClear(glyphlist
);
3332 listDispose(glyphlist
);