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 .
23 * Author: Alexander Gelfenbain
41 #include <rtl/ustring.hxx>
43 #include <osl/endian.h>
49 /*- module identification */
51 static const char *modname
= "SunTypeTools-TT";
52 static const char *modver
= "1.0";
53 static const char *modextra
= "gelf";
55 /*- private functions, constants and data types */
57 enum PathSegmentType
{
72 PSPathElement( PathSegmentType i_eType
) : type( i_eType
),
80 /*- In horizontal writing mode right sidebearing is calculated using this formula
81 *- rsb = aw - (lsb + xMax - xMin) -*/
87 sal_uInt16 aw
; /*- Advance Width (horizontal writing mode) */
88 sal_Int16 lsb
; /*- Left sidebearing (horizontal writing mode) */
89 sal_uInt16 ah
; /*- advance height (vertical writing mode) */
90 sal_Int16 tsb
; /*- top sidebearing (vertical writing mode) */
93 #define HFORMAT_LINELEN 64
97 char buffer
[HFORMAT_LINELEN
];
103 sal_uInt32 nGlyphs
; /* number of glyphs in the font + 1 */
104 sal_uInt32
*offs
; /* array of nGlyphs offsets */
108 static const sal_uInt32 TTFontClassTag
= 0x74746663; /* 'ttfc' */
110 static const sal_uInt32 T_true
= 0x74727565; /* 'true' */
111 static const sal_uInt32 T_ttcf
= 0x74746366; /* 'ttcf' */
112 static const sal_uInt32 T_otto
= 0x4f54544f; /* 'OTTO' */
114 /* standard TrueType table tags */
115 #define T_maxp 0x6D617870
116 #define T_glyf 0x676C7966
117 #define T_head 0x68656164
118 #define T_loca 0x6C6F6361
119 #define T_name 0x6E616D65
120 #define T_hhea 0x68686561
121 #define T_hmtx 0x686D7478
122 #define T_cmap 0x636D6170
123 #define T_vhea 0x76686561
124 #define T_vmtx 0x766D7478
125 #define T_OS2 0x4F532F32
126 #define T_post 0x706F7374
127 #define T_kern 0x6B65726E
128 #define T_cvt 0x63767420
129 #define T_prep 0x70726570
130 #define T_fpgm 0x6670676D
131 #define T_gsub 0x47535542
132 #define T_CFF 0x43464620
134 /*- inline functions */
136 #define _inline static __inline__
138 #define _inline static
141 _inline
void *smalloc(size_t size
)
143 void *res
= malloc(size
);
148 _inline
void *scalloc(size_t n
, size_t size
)
150 void *res
= calloc(n
, size
);
155 /*- Data access macros for data stored in big-endian or little-endian format */
156 _inline sal_Int16
GetInt16(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
162 t
= (ptr
+offset
)[0] << 8 | (ptr
+offset
)[1];
164 t
= (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
170 _inline sal_uInt16
GetUInt16(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
176 t
= (ptr
+offset
)[0] << 8 | (ptr
+offset
)[1];
178 t
= (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
184 _inline sal_Int32
GetInt32(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
190 t
= (ptr
+offset
)[0] << 24 | (ptr
+offset
)[1] << 16 |
191 (ptr
+offset
)[2] << 8 | (ptr
+offset
)[3];
193 t
= (ptr
+offset
)[3] << 24 | (ptr
+offset
)[2] << 16 |
194 (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
200 _inline sal_uInt32
GetUInt32(const sal_uInt8
*ptr
, size_t offset
, int bigendian
)
206 t
= (ptr
+offset
)[0] << 24 | (ptr
+offset
)[1] << 16 |
207 (ptr
+offset
)[2] << 8 | (ptr
+offset
)[3];
209 t
= (ptr
+offset
)[3] << 24 | (ptr
+offset
)[2] << 16 |
210 (ptr
+offset
)[1] << 8 | (ptr
+offset
)[0];
216 #if defined(OSL_BIGENDIAN)
217 #define Int16FromMOTA(a) (a)
218 #define Int32FromMOTA(a) (a)
220 static sal_uInt16
Int16FromMOTA(sal_uInt16 a
) {
221 return (sal_uInt16
) (((sal_uInt8
)((a
) >> 8)) | ((sal_uInt8
)(a
) << 8));
223 static sal_uInt32
Int32FromMOTA(sal_uInt32 a
) {
224 return ((a
>>24)&0xFF) | (((a
>>8)&0xFF00) | ((a
&0xFF00)<<8) | ((a
&0xFF)<<24));
228 _inline F16Dot16
fixedMul(F16Dot16 a
, F16Dot16 b
)
235 sign
= (a
& 0x80000000) ^ (b
& 0x80000000);
246 /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */
249 res
+= a1
* b2
+ b1
* a2
+ ((b1
* b2
) >> 16);
251 return sign
? -res
: res
;
254 _inline F16Dot16
fixedDiv(F16Dot16 a
, F16Dot16 b
)
260 sign
= (a
& 0x80000000) ^ (b
& 0x80000000);
267 /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */
274 res
= (f
<< 16) + (r
<< 16) / b
;
276 return sign
? -res
: res
;
279 /*- returns a * b / c -*/
280 /* XXX provide a real implementation that preserves accuracy */
281 _inline F16Dot16
fixedMulDiv(F16Dot16 a
, F16Dot16 b
, F16Dot16 c
)
285 res
= fixedMul(a
, b
);
286 return fixedDiv(res
, c
);
289 /*- Translate units from TT to PS (standard 1/1000) -*/
290 _inline
int XUnits(int unitsPerEm
, int n
)
292 return (n
* 1000) / unitsPerEm
;
295 _inline
const sal_uInt8
* getTable( TrueTypeFont
*ttf
, sal_uInt32 ord
)
297 return ttf
->tables
[ord
];
300 _inline sal_uInt32
getTableSize(TrueTypeFont
*ttf
, sal_uInt32 ord
)
302 return ttf
->tlens
[ord
];
305 /* Hex Formatter functions */
306 static const char HexChars
[] = "0123456789ABCDEF";
308 static HexFmt
*HexFmtNew(FILE *outf
)
310 HexFmt
* res
= static_cast<HexFmt
*>(smalloc(sizeof(HexFmt
)));
311 res
->bufpos
= res
->total
= 0;
316 static bool HexFmtFlush(HexFmt
*_this
)
320 size_t nWritten
= fwrite(_this
->buffer
, 1, _this
->bufpos
, _this
->o
);
321 bRet
= nWritten
== _this
->bufpos
;
327 _inline
void HexFmtOpenString(HexFmt
*_this
)
329 fputs("<\n", _this
->o
);
332 _inline
void HexFmtCloseString(HexFmt
*_this
)
335 fputs("00\n>\n", _this
->o
);
338 _inline
void HexFmtDispose(HexFmt
*_this
)
344 static void HexFmtBlockWrite(HexFmt
*_this
, const void *ptr
, sal_uInt32 size
)
349 if (_this
->total
+ size
> 65534) {
351 HexFmtCloseString(_this
);
353 HexFmtOpenString(_this
);
355 for (i
=0; i
<size
; i
++) {
356 Ch
= static_cast<sal_uInt8
const *>(ptr
)[i
];
357 _this
->buffer
[_this
->bufpos
++] = HexChars
[Ch
>> 4];
358 _this
->buffer
[_this
->bufpos
++] = HexChars
[Ch
& 0xF];
359 if (_this
->bufpos
== HFORMAT_LINELEN
) {
361 fputc('\n', _this
->o
);
365 _this
->total
+= size
;
368 /* Outline Extraction functions */
370 /* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
371 static void GetMetrics(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, TTGlyphMetrics
*metrics
)
373 const sal_uInt8
* table
= getTable( ttf
, O_hmtx
);
375 metrics
->aw
= metrics
->lsb
= metrics
->ah
= metrics
->tsb
= 0;
376 if (!table
|| !ttf
->numberOfHMetrics
) return;
378 if (glyphID
< ttf
->numberOfHMetrics
) {
379 metrics
->aw
= GetUInt16(table
, 4 * glyphID
, 1);
380 metrics
->lsb
= GetInt16(table
, 4 * glyphID
+ 2, 1);
382 metrics
->aw
= GetUInt16(table
, 4 * (ttf
->numberOfHMetrics
- 1), 1);
383 metrics
->lsb
= GetInt16(table
+ ttf
->numberOfHMetrics
* 4, (glyphID
- ttf
->numberOfHMetrics
) * 2, 1);
386 table
= getTable(ttf
, O_vmtx
);
387 if( !table
|| !ttf
->numOfLongVerMetrics
)
390 if (glyphID
< ttf
->numOfLongVerMetrics
) {
391 metrics
->ah
= GetUInt16(table
, 4 * glyphID
, 1);
392 metrics
->tsb
= GetInt16(table
, 4 * glyphID
+ 2, 1);
394 metrics
->ah
= GetUInt16(table
, 4 * (ttf
->numOfLongVerMetrics
- 1), 1);
395 metrics
->tsb
= GetInt16(table
+ ttf
->numOfLongVerMetrics
* 4, (glyphID
- ttf
->numOfLongVerMetrics
) * 2, 1);
399 static int GetTTGlyphOutline(TrueTypeFont
*, sal_uInt32
, ControlPoint
**, TTGlyphMetrics
*, std::vector
< sal_uInt32
>* );
401 /* returns the number of control points, allocates the pointArray */
402 static int GetSimpleTTOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
)
404 const sal_uInt8
* table
= getTable(ttf
, O_glyf
);
405 const sal_uInt32 nTableSize
= getTableSize(ttf
, O_glyf
);
411 /* printf("GetSimpleTTOutline(%d)\n", glyphID); */
413 if( glyphID
>= ttf
->nglyphs
) /*- glyph is not present in the font */
415 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
416 const sal_Int16 numberOfContours
= GetInt16(ptr
, 0, 1);
417 if( numberOfContours
<= 0 ) /*- glyph is not simple */
420 if (metrics
) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
421 metrics
->xMin
= GetInt16(ptr
, 2, 1);
422 metrics
->yMin
= GetInt16(ptr
, 4, 1);
423 metrics
->xMax
= GetInt16(ptr
, 6, 1);
424 metrics
->yMax
= GetInt16(ptr
, 8, 1);
425 GetMetrics(ttf
, glyphID
, metrics
);
428 /* determine the last point and be extra safe about it. But probably this code is not needed */
429 sal_uInt16 lastPoint
=0;
430 const sal_Int32 nMaxContours
= (nTableSize
- 10)/2;
431 if (numberOfContours
> nMaxContours
)
433 for (i
=0; i
<numberOfContours
; i
++)
435 const sal_uInt16 t
= GetUInt16(ptr
, 10+i
*2, 1);
440 sal_uInt16 instLen
= GetUInt16(ptr
, 10 + numberOfContours
*2, 1);
441 sal_uInt32 nOffset
= 10 + 2 * numberOfContours
+ 2 + instLen
;
442 if (nOffset
> nTableSize
)
444 const sal_uInt8
* p
= ptr
+ nOffset
;
446 const sal_uInt32 nBytesRemaining
= nTableSize
- nOffset
;
447 const sal_uInt16 palen
= lastPoint
+1;
449 //at a minimum its one byte per entry
450 if (palen
> nBytesRemaining
|| lastPoint
> nBytesRemaining
-1)
452 SAL_WARN("vcl.fonts", "Font " << OUString::createFromAscii(ttf
->fname
) <<
453 "claimed a palen of "
454 << palen
<< " but max bytes remaining is " << nBytesRemaining
);
458 ControlPoint
* pa
= static_cast<ControlPoint
*>(calloc(palen
, sizeof(ControlPoint
)));
461 while (i
<= lastPoint
) {
462 pa
[i
++].flags
= (sal_uInt32
) (flag
= *p
++);
463 if (flag
& 8) { /*- repeat flag */
465 for (j
=0; j
<n
; j
++) {
466 if (i
> lastPoint
) { /*- if the font is really broken */
470 pa
[i
++].flags
= flag
;
475 /*- Process the X coordinate */
477 for (i
= 0; i
<= lastPoint
; i
++) {
478 if (pa
[i
].flags
& 0x02) {
479 if (pa
[i
].flags
& 0x10) {
484 } else if ( !(pa
[i
].flags
& 0x10)) {
485 z
+= GetInt16(p
, 0, 1);
488 pa
[i
].x
= (sal_Int16
)z
;
491 /*- Process the Y coordinate */
493 for (i
= 0; i
<= lastPoint
; i
++) {
494 if (pa
[i
].flags
& 0x04) {
495 if (pa
[i
].flags
& 0x20) {
500 } else if ( !(pa
[i
].flags
& 0x20)) {
501 z
+= GetInt16(p
, 0, 1);
504 pa
[i
].y
= (sal_Int16
)z
;
507 for (i
=0; i
<numberOfContours
; i
++) {
508 sal_uInt16 offset
= GetUInt16(ptr
, 10 + i
* 2, 1);
509 SAL_WARN_IF(offset
>= palen
, "vcl.fonts", "Font " << OUString::createFromAscii(ttf
->fname
) <<
510 " contour " << i
<< " claimed an illegal offset of "
511 << offset
<< " but max offset is " << palen
-1);
514 pa
[offset
].flags
|= 0x00008000; /*- set the end contour flag */
518 return lastPoint
+ 1;
521 static int GetCompoundTTOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
, std::vector
< sal_uInt32
>& glyphlist
)
523 sal_uInt16 flags
, index
;
524 sal_Int16 e
, f
, numberOfContours
;
525 const sal_uInt8
* table
= getTable( ttf
, O_glyf
);
526 std::vector
<ControlPoint
> myPoints
;
527 ControlPoint
*nextComponent
, *pa
;
529 F16Dot16 a
= 0x10000, b
= 0, c
= 0, d
= 0x10000, m
, n
, abs1
, abs2
, abs3
;
532 /* printf("GetCompoundTTOutline(%d)\n", glyphID); */
534 if (glyphID
>= ttf
->nglyphs
) /*- incorrect glyphID */
537 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
538 if ((numberOfContours
= GetInt16(ptr
, 0, 1)) != -1) /*- glyph is not compound */
542 metrics
->xMin
= GetInt16(ptr
, 2, 1);
543 metrics
->yMin
= GetInt16(ptr
, 4, 1);
544 metrics
->xMax
= GetInt16(ptr
, 6, 1);
545 metrics
->yMax
= GetInt16(ptr
, 8, 1);
546 GetMetrics(ttf
, glyphID
, metrics
);
552 flags
= GetUInt16(ptr
, 0, 1);
553 /* printf("flags: 0x%X\n", flags); */
554 index
= GetUInt16(ptr
, 2, 1);
557 if( std::find( glyphlist
.begin(), glyphlist
.end(), index
) != glyphlist
.end() )
559 #if OSL_DEBUG_LEVEL > 1
560 fprintf(stderr
, "Endless loop found in a compound glyph.\n");
561 fprintf(stderr
, "%d -> ", index
);
562 fprintf(stderr
," [");
563 for( std::vector
< sal_uInt32
>::const_iterator it
= glyphlist
.begin();
564 it
!= glyphlist
.end(); ++it
)
566 fprintf( stderr
,"%d ", (int) *it
);
568 fprintf(stderr
,"]\n");
573 glyphlist
.push_back( index
);
575 if ((np
= GetTTGlyphOutline(ttf
, index
, &nextComponent
, 0, &glyphlist
)) == 0)
577 /* XXX that probably indicates a corrupted font */
578 #if OSL_DEBUG_LEVEL > 1
579 fprintf(stderr
, "An empty compound!\n");
580 /* assert(!"An empty compound"); */
584 if( ! glyphlist
.empty() )
585 glyphlist
.pop_back();
587 if (flags
& USE_MY_METRICS
) {
588 if (metrics
) GetMetrics(ttf
, index
, metrics
);
591 if (flags
& ARG_1_AND_2_ARE_WORDS
) {
592 e
= GetInt16(ptr
, 0, 1);
593 f
= GetInt16(ptr
, 2, 1);
594 /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
597 if (flags
& ARGS_ARE_XY_VALUES
) { /* args are signed */
598 e
= (sal_Int8
) *ptr
++;
599 f
= (sal_Int8
) *ptr
++;
600 /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
601 } else { /* args are unsigned */
602 /* printf("!ARGS_ARE_XY_VALUES\n"); */
612 if (flags
& WE_HAVE_A_SCALE
) {
613 a
= GetInt16(ptr
, 0, 1) << 2;
616 } else if (flags
& WE_HAVE_AN_X_AND_Y_SCALE
) {
617 a
= GetInt16(ptr
, 0, 1) << 2;
618 d
= GetInt16(ptr
, 2, 1) << 2;
620 } else if (flags
& WE_HAVE_A_TWO_BY_TWO
) {
621 a
= GetInt16(ptr
, 0, 1) << 2;
622 b
= GetInt16(ptr
, 2, 1) << 2;
623 c
= GetInt16(ptr
, 4, 1) << 2;
624 d
= GetInt16(ptr
, 6, 1) << 2;
628 abs1
= (a
< 0) ? -a
: a
;
629 abs2
= (b
< 0) ? -b
: b
;
630 m
= (abs1
> abs2
) ? abs1
: abs2
;
632 if (abs3
< 0) abs3
= -abs3
;
633 if (abs3
<= 33) m
*= 2;
635 abs1
= (c
< 0) ? -c
: c
;
636 abs2
= (d
< 0) ? -d
: d
;
637 n
= (abs1
> abs2
) ? abs1
: abs2
;
639 if (abs3
< 0) abs3
= -abs3
;
640 if (abs3
<= 33) n
*= 2;
642 for (i
=0; i
<np
; i
++) {
645 cp
.flags
= nextComponent
[i
].flags
;
646 t
= fixedMulDiv(a
, nextComponent
[i
].x
<< 16, m
) + fixedMulDiv(c
, nextComponent
[i
].y
<< 16, m
) + (e
<< 16);
647 cp
.x
= (sal_Int16
)(fixedMul(t
, m
) >> 16);
648 t
= fixedMulDiv(b
, nextComponent
[i
].x
<< 16, n
) + fixedMulDiv(d
, nextComponent
[i
].y
<< 16, n
) + (f
<< 16);
649 cp
.y
= (sal_Int16
)(fixedMul(t
, n
) >> 16);
651 myPoints
.push_back( cp
);
656 } while (flags
& MORE_COMPONENTS
);
658 // #i123417# some fonts like IFAOGrec have no outline points in some compound glyphs
659 // so this unlikely but possible scenario should be handled gracefully
660 if( myPoints
.empty() )
663 np
= myPoints
.size();
665 pa
= static_cast<ControlPoint
*>(calloc(np
, sizeof(ControlPoint
)));
669 memcpy( pa
, &myPoints
[0], np
*sizeof(ControlPoint
) );
675 /* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect,
676 * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
678 * NOTE: glyphlist is the stack of glyphs traversed while constructing
679 * a composite glyph. This is a safequard against endless recursion
680 * in corrupted fonts.
682 static int GetTTGlyphOutline(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
, TTGlyphMetrics
*metrics
, std::vector
< sal_uInt32
>* glyphlist
)
684 const sal_uInt8
*table
= getTable( ttf
, O_glyf
);
685 sal_Int16 numberOfContours
;
690 memset(metrics
, 0, sizeof(TTGlyphMetrics
)); /*- metrics is initialized to all zeroes */
693 if (glyphID
>= ttf
->nglyphs
) return -1; /**/
695 const sal_uInt8
* ptr
= table
+ ttf
->goffsets
[glyphID
];
696 int length
= ttf
->goffsets
[glyphID
+1] - ttf
->goffsets
[glyphID
];
698 if (length
== 0) { /*- empty glyphs still have hmtx and vmtx metrics values */
699 if (metrics
) GetMetrics(ttf
, glyphID
, metrics
);
703 numberOfContours
= GetInt16(ptr
, 0, 1);
705 if (numberOfContours
>= 0)
707 res
=GetSimpleTTOutline(ttf
, glyphID
, pointArray
, metrics
);
711 std::vector
< sal_uInt32
> aPrivList
;
712 aPrivList
.push_back( glyphID
);
713 res
= GetCompoundTTOutline(ttf
, glyphID
, pointArray
, metrics
, glyphlist
? *glyphlist
: aPrivList
);
719 /*- returns the number of items in the path -*/
721 static int BSplineToPSPath(ControlPoint
*srcA
, int srcCount
, PSPathElement
**path
)
723 std::vector
< PSPathElement
> aPathList
;
725 PSPathElement
p( PS_NOOP
);
727 int x0
= 0, y0
= 0, x1
= 0, y1
= 0, x2
, y2
, curx
, cury
;
728 bool lastOff
= false; /*- last point was off-contour */
729 int scflag
= 1; /*- start contour flag */
730 bool ecflag
= false; /*- end contour flag */
731 int cp
= 0; /*- current point */
732 int StartContour
= 0, EndContour
= 1;
736 /* if (srcCount > 0) for(;;) */
737 while (srcCount
> 0) { /*- srcCount does not get changed inside the loop. */
741 while (!(srcA
[l
].flags
& 0x8000)) l
++;
743 if (StartContour
== EndContour
) {
744 if (cp
+ 1 < srcCount
) {
751 p
= PSPathElement(PS_MOVETO
);
752 if (!(srcA
[cp
].flags
& 1)) {
753 if (!(srcA
[EndContour
].flags
& 1)) {
754 p
.x1
= x0
= (srcA
[cp
].x
+ srcA
[EndContour
].x
+ 1) / 2;
755 p
.y1
= y0
= (srcA
[cp
].y
+ srcA
[EndContour
].y
+ 1) / 2;
757 p
.x1
= x0
= srcA
[EndContour
].x
;
758 p
.y1
= y0
= srcA
[EndContour
].y
;
761 p
.x1
= x0
= srcA
[cp
].x
;
762 p
.y1
= y0
= srcA
[cp
].y
;
765 aPathList
.push_back( p
);
773 if (srcA
[cp
].flags
& 1)
777 p
= PSPathElement(PS_CURVETO
);
778 p
.x1
= x0
+ (2 * (x1
- x0
) + 1) / 3;
779 p
.y1
= y0
+ (2 * (y1
- y0
) + 1) / 3;
780 p
.x2
= x1
+ (curx
- x1
+ 1) / 3;
781 p
.y2
= y1
+ (cury
- y1
+ 1) / 3;
784 aPathList
.push_back( p
);
788 if (!(x0
== curx
&& y0
== cury
))
789 { /* eliminate empty lines */
790 p
= PSPathElement(PS_LINETO
);
793 aPathList
.push_back( p
);
796 x0
= curx
; y0
= cury
; lastOff
= false;
802 x2
= (x1
+ curx
+ 1) / 2;
803 y2
= (y1
+ cury
+ 1) / 2;
804 p
= PSPathElement(PS_CURVETO
);
805 p
.x1
= x0
+ (2 * (x1
- x0
) + 1) / 3;
806 p
.y1
= y0
+ (2 * (y1
- y0
) + 1) / 3;
807 p
.x2
= x1
+ (x2
- x1
+ 1) / 3;
808 p
.y2
= y1
+ (y2
- y1
+ 1) / 3;
811 aPathList
.push_back( p
);
813 x1
= curx
; y1
= cury
;
815 x1
= curx
; y1
= cury
;
821 aPathList
.push_back( PSPathElement(PS_CLOSEPATH
) );
825 if (cp
>= srcCount
) break;
829 if (cp
== EndContour
) {
837 if( (nPathCount
= (int)aPathList
.size()) > 0)
839 *path
= static_cast<PSPathElement
*>(calloc(nPathCount
, sizeof(PSPathElement
)));
841 memcpy( *path
, &aPathList
[0], nPathCount
* sizeof(PSPathElement
) );
847 /*- Extracts a string from the name table and allocates memory for it -*/
849 static char *nameExtract( const sal_uInt8
* name
, int nTableSize
, int n
, int dbFlag
, sal_uInt16
** ucs2result
)
852 const sal_uInt8
* ptr
= name
+ GetUInt16(name
, 4, 1) + GetUInt16(name
+ 6, 12 * n
+ 10, 1);
853 int len
= GetUInt16(name
+6, 12 * n
+ 8, 1);
856 const sal_uInt8
* end_table
= name
+nTableSize
;
857 const int available_space
= ptr
> end_table
? 0 : (end_table
- ptr
);
858 if( (len
<= 0) || len
> available_space
)
868 res
= static_cast<char*>(malloc(1 + len
/2));
870 for (int i
= 0; i
< len
/2; i
++)
871 res
[i
] = *(ptr
+ i
* 2 + 1);
875 *ucs2result
= static_cast<sal_uInt16
*>(malloc( len
+2 ));
876 for (int i
= 0; i
< len
/2; i
++ )
877 (*ucs2result
)[i
] = GetUInt16( ptr
, 2*i
, 1 );
878 (*ucs2result
)[len
/2] = 0;
881 res
= static_cast<char*>(malloc(1 + len
));
883 memcpy(res
, ptr
, len
);
890 static int findname( const sal_uInt8
*name
, sal_uInt16 n
, sal_uInt16 platformID
,
891 sal_uInt16 encodingID
, sal_uInt16 languageID
, sal_uInt16 nameID
)
893 if (n
== 0) return -1;
899 m1
= (platformID
<< 16) | encodingID
;
900 m2
= (languageID
<< 16) | nameID
;
903 const int i
= (l
+ r
) >> 1;
904 t1
= GetUInt32(name
+ 6, i
* 12 + 0, 1);
905 t2
= GetUInt32(name
+ 6, i
* 12 + 4, 1);
907 if (! ((m1
< t1
) || ((m1
== t1
) && (m2
< t2
)))) l
= i
+ 1;
908 if (! ((m1
> t1
) || ((m1
== t1
) && (m2
> t2
)))) r
= i
- 1;
918 /* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables.
919 * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
921 * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
922 * and does not have (3, 1, 1033)
923 * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
924 * require a change in algorithm
926 * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID,
927 * but (1, 0, 1042) strings usable
928 * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
931 static void GetNames(TrueTypeFont
*t
)
933 const sal_uInt8
* table
= getTable( t
, O_name
);
934 const sal_uInt32 nTableSize
= getTableSize(t
, O_name
);
938 #if OSL_DEBUG_LEVEL > 1
939 fprintf(stderr
, "O_name table too small\n");
944 sal_uInt16 n
= GetUInt16(table
, 2, 1);
946 /* simple sanity check for name table entry count */
947 const size_t nMinRecordSize
= 12;
948 const size_t nSpaceAvailable
= nTableSize
- 6;
949 const size_t nMaxRecords
= nSpaceAvailable
/nMinRecordSize
;
950 if (n
>= nMaxRecords
)
954 bool bPSNameOK
= true;
956 /* PostScript name: preferred Microsoft */
958 if ((r
= findname(table
, n
, 3, 1, 0x0409, 6)) != -1)
959 t
->psname
= nameExtract(table
, nTableSize
, r
, 1, NULL
);
960 if ( ! t
->psname
&& (r
= findname(table
, n
, 1, 0, 0, 6)) != -1)
961 t
->psname
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
962 if ( ! t
->psname
&& (r
= findname(table
, n
, 3, 0, 0x0409, 6)) != -1)
964 // some symbol fonts like Marlett have a 3,0 name!
965 t
->psname
= nameExtract(table
, nTableSize
, r
, 1, NULL
);
967 // for embedded font in Ghostscript PDFs
968 if ( ! t
->psname
&& (r
= findname(table
, n
, 2, 2, 0, 6)) != -1)
970 t
->psname
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
976 char* pReverse
= t
->fname
+ strlen(t
->fname
);
977 /* take only last token of filename */
978 while(pReverse
!= t
->fname
&& *pReverse
!= '/') pReverse
--;
979 if(*pReverse
== '/') pReverse
++;
980 t
->psname
= strdup(pReverse
);
981 assert(t
->psname
!= 0);
982 for (i
=strlen(t
->psname
) - 1; i
> 0; i
--)
984 /*- Remove the suffix -*/
985 if (t
->psname
[i
] == '.' ) {
992 t
->psname
= strdup( "Unknown" );
995 /* Font family and subfamily names: preferred Apple */
997 if ((r
= findname(table
, n
, 0, 0, 0, 1)) != -1)
998 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
999 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 1, 0x0409, 1)) != -1)
1000 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1001 if ( ! t
->family
&& (r
= findname(table
, n
, 1, 0, 0, 1)) != -1)
1002 t
->family
= nameExtract(table
, nTableSize
, r
, 0, NULL
);
1003 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 1, 0x0411, 1)) != -1)
1004 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1005 if ( ! t
->family
&& (r
= findname(table
, n
, 3, 0, 0x0409, 1)) != -1)
1006 t
->family
= nameExtract(table
, nTableSize
, r
, 1, &t
->ufamily
);
1009 t
->family
= strdup(t
->psname
);
1010 assert(t
->family
!= 0);
1013 t
->subfamily
= NULL
;
1014 t
->usubfamily
= NULL
;
1015 if ((r
= findname(table
, n
, 1, 0, 0, 2)) != -1)
1016 t
->subfamily
= nameExtract(table
, nTableSize
, r
, 0, &t
->usubfamily
);
1017 if ( ! t
->subfamily
&& (r
= findname(table
, n
, 3, 1, 0x0409, 2)) != -1)
1018 t
->subfamily
= nameExtract(table
, nTableSize
, r
, 1, &t
->usubfamily
);
1019 if ( ! t
->subfamily
)
1021 t
->subfamily
= strdup("");
1024 /* #i60349# sanity check psname
1025 * psname parctically has to be 7bit ascii and should not contains spaces
1026 * there is a class of broken fonts which do not fulfill that at all, so let's try
1027 * if the family name is 7bit ascii and take it instead if so
1030 for( i
= 0; t
->psname
[i
] != 0 && bPSNameOK
; i
++ )
1031 if( t
->psname
[ i
] < 33 || (t
->psname
[ i
] & 0x80) )
1035 /* check if family is a suitable replacement */
1036 if( t
->ufamily
&& t
->family
)
1038 bool bReplace
= true;
1040 for( i
= 0; t
->ufamily
[ i
] != 0 && bReplace
; i
++ )
1041 if( t
->ufamily
[ i
] < 33 || t
->ufamily
[ i
] > 127 )
1046 t
->psname
= strdup( t
->family
);
1053 CMAP_NOT_USABLE
= -1,
1054 CMAP_MS_Symbol
= 10,
1055 CMAP_MS_Unicode
= 11,
1056 CMAP_MS_ShiftJIS
= 12,
1059 CMAP_MS_Wansung
= 15,
1063 #define MISSING_GLYPH_INDEX 0
1066 * getGlyph[0246]() functions and friends are implemented by:
1067 * @author Manpreet Singh
1068 * getGlyph12() function and friends by:
1071 static sal_uInt32
getGlyph0(const sal_uInt8
* cmap
, sal_uInt32
, sal_uInt32 c
) {
1073 return *(cmap
+ 6 + c
);
1075 return MISSING_GLYPH_INDEX
;
1079 typedef struct _subHeader2
{
1080 sal_uInt16 firstCode
;
1081 sal_uInt16 entryCount
;
1083 sal_uInt16 idRangeOffset
;
1086 static sal_uInt32
getGlyph2(const sal_uInt8
*cmap
, const sal_uInt32 nMaxCmapSize
, sal_uInt32 c
) {
1087 sal_uInt16
const *CMAP2
= reinterpret_cast<sal_uInt16
const *>(cmap
);
1088 sal_uInt8 theHighByte
;
1090 sal_uInt8 theLowByte
;
1091 subHeader2
const * subHeader2s
;
1092 sal_uInt16
const * subHeader2Keys
;
1093 sal_uInt16 firstCode
;
1095 sal_uInt32 ToReturn
;
1097 theHighByte
= (sal_uInt8
)((c
>> 8) & 0x00ff);
1098 theLowByte
= (sal_uInt8
)(c
& 0x00ff);
1099 subHeader2Keys
= CMAP2
+ 3;
1100 subHeader2s
= reinterpret_cast<subHeader2
const *>(subHeader2Keys
+ 256);
1101 if(reinterpret_cast<sal_uInt8
const *>(&subHeader2Keys
[theHighByte
]) - cmap
< int(nMaxCmapSize
- 2))
1103 k
= Int16FromMOTA(subHeader2Keys
[theHighByte
]) / 8;
1104 // check if the subheader record fits into available space
1105 if((k
>= 0) && (reinterpret_cast<sal_uInt8
const *>(&subHeader2s
[k
]) - cmap
>= int(nMaxCmapSize
- sizeof(subHeader2
))))
1110 firstCode
= Int16FromMOTA(subHeader2s
[0].firstCode
);
1111 if(theLowByte
>= firstCode
&& theLowByte
< (firstCode
+ Int16FromMOTA(subHeader2s
[k
].entryCount
))) {
1112 sal_uInt16
const * pGlyph
= (&(subHeader2s
[0].idRangeOffset
))
1113 + (Int16FromMOTA(subHeader2s
[0].idRangeOffset
)/2) /* + offset */
1114 + theLowByte
/* + to_look */
1117 if (reinterpret_cast<sal_uInt8
const *>(pGlyph
) - cmap
< int(nMaxCmapSize
) - 4)
1120 return MISSING_GLYPH_INDEX
;
1122 return MISSING_GLYPH_INDEX
;
1125 firstCode
= Int16FromMOTA(subHeader2s
[k
].firstCode
);
1126 if(theLowByte
>= firstCode
&& theLowByte
< (firstCode
+ Int16FromMOTA(subHeader2s
[k
].entryCount
))) {
1127 ToReturn
= *((&(subHeader2s
[k
].idRangeOffset
))
1128 + (Int16FromMOTA(subHeader2s
[k
].idRangeOffset
)/2)
1129 + theLowByte
- firstCode
);
1131 return MISSING_GLYPH_INDEX
;
1133 ToReturn
+= Int16FromMOTA(subHeader2s
[k
].idDelta
);
1134 return (ToReturn
& 0xFFFF);
1137 return MISSING_GLYPH_INDEX
;
1140 return MISSING_GLYPH_INDEX
;
1144 static sal_uInt32
getGlyph6(const sal_uInt8
*cmap
, sal_uInt32
, sal_uInt32 c
) {
1145 sal_uInt16 firstCode
, lastCode
, count
;
1146 sal_uInt16
const *CMAP6
= reinterpret_cast<sal_uInt16
const *>(cmap
);
1148 firstCode
= Int16FromMOTA(*(CMAP6
+ 3));
1149 count
= Int16FromMOTA(*(CMAP6
+ 4));
1150 lastCode
= firstCode
+ count
- 1;
1151 if (c
< firstCode
|| c
> lastCode
) {
1152 return MISSING_GLYPH_INDEX
;
1154 return *((CMAP6
+ 5)/*glyphIdArray*/ + (c
- firstCode
));
1158 static sal_uInt16
GEbinsearch(sal_uInt16
const *ar
, sal_uInt16 length
, sal_uInt16 toSearch
) {
1159 signed int low
, high
, lastfound
= 0xffff;
1161 if(length
== (sal_uInt16
)0 || length
== (sal_uInt16
)0xFFFF) {
1162 return (sal_uInt16
)0xFFFF;
1166 while(high
>= low
) {
1167 int mid
= (high
+ low
)/2;
1168 res
= Int16FromMOTA(*(ar
+mid
));
1169 if(res
>= toSearch
) {
1176 return (sal_uInt16
)lastfound
;
1179 static sal_uInt32
getGlyph4(const sal_uInt8
*cmap
, const sal_uInt32 nMaxCmapSize
, sal_uInt32 c
) {
1182 sal_uInt16 segCount
;
1183 sal_uInt16
const * startCode
;
1184 sal_uInt16
const * endCode
;
1185 sal_uInt16
const * idDelta
;
1186 /* sal_uInt16 * glyphIdArray; */
1187 sal_uInt16
const * idRangeOffset
;
1188 /*sal_uInt16 * glyphIndexArray;*/
1189 sal_uInt16
const *CMAP4
= reinterpret_cast<sal_uInt16
const *>(cmap
);
1190 /* sal_uInt16 GEbinsearch(sal_uInt16 *ar, sal_uInt16 length, sal_uInt16 toSearch); */
1192 segCount
= Int16FromMOTA(*(CMAP4
+ 3))/2;
1193 endCode
= CMAP4
+ 7;
1194 i
= GEbinsearch(endCode
, segCount
, (sal_uInt16
)c
);
1196 if (i
== (sal_uInt16
) 0xFFFF) {
1197 return MISSING_GLYPH_INDEX
;
1199 startCode
= endCode
+ segCount
+ 1;
1201 if((reinterpret_cast<sal_uInt8
const *>(&startCode
[i
]) - cmap
>= int(nMaxCmapSize
- 2)) || Int16FromMOTA(startCode
[i
]) > c
) {
1202 return MISSING_GLYPH_INDEX
;
1204 idDelta
= startCode
+ segCount
;
1205 idRangeOffset
= idDelta
+ segCount
;
1206 /*glyphIndexArray = idRangeOffset + segCount;*/
1208 if((reinterpret_cast<sal_uInt8
const *>(&idRangeOffset
[i
]) - cmap
< int(nMaxCmapSize
- 2)) && Int16FromMOTA(idRangeOffset
[i
]) != 0) {
1209 sal_uInt16
const * pGlyphOffset
= &(idRangeOffset
[i
]) + (Int16FromMOTA(idRangeOffset
[i
])/2 + (c
- Int16FromMOTA(startCode
[i
])));
1210 if(reinterpret_cast<sal_uInt8
const *>(pGlyphOffset
) - cmap
>= int(nMaxCmapSize
- 2))
1211 return MISSING_GLYPH_INDEX
;
1212 c
= Int16FromMOTA(*pGlyphOffset
);
1215 ToReturn
= (Int16FromMOTA(idDelta
[i
]) + c
) & 0xFFFF;
1219 static sal_uInt32
getGlyph12(const sal_uInt8
*pCmap
, sal_uInt32
, sal_uInt32 cChar
) {
1220 const sal_uInt32
* pCMAP12
= reinterpret_cast<const sal_uInt32
*>(pCmap
);
1221 int nLength
= Int32FromMOTA( pCMAP12
[1] );
1222 int nGroups
= Int32FromMOTA( pCMAP12
[3] );
1224 int nUpper
= nGroups
;
1226 if( nUpper
> (nLength
-16)/12 )
1227 nUpper
= (nLength
-16)/12;
1229 /* binary search in "segmented coverage" subtable */
1230 while( nLower
< nUpper
) {
1231 int nIndex
= (nLower
+ nUpper
) / 2;
1232 const sal_uInt32
* pEntry
= &pCMAP12
[ 4 + 3*nIndex
];
1233 sal_uInt32 cStart
= Int32FromMOTA( pEntry
[0] );
1234 sal_uInt32 cLast
= Int32FromMOTA( pEntry
[1] );
1235 if( cChar
< cStart
)
1237 else if( cChar
> cLast
)
1238 nLower
= nIndex
+ 1;
1239 else { /* found matching entry! */
1240 sal_uInt32 nGlyph
= Int32FromMOTA( pEntry
[2] );
1241 nGlyph
+= cChar
- cStart
;
1246 return MISSING_GLYPH_INDEX
;
1249 static void FindCmap(TrueTypeFont
*ttf
)
1251 const sal_uInt8
* table
= getTable(ttf
, O_cmap
);
1252 sal_uInt32 table_size
= getTableSize(ttf
, O_cmap
);
1253 sal_uInt16 ncmaps
= GetUInt16(table
, 2, 1);
1254 sal_uInt32 AppleUni
= 0; // Apple Unicode
1255 sal_uInt32 ThreeZero
= 0; /* MS Symbol */
1256 sal_uInt32 ThreeOne
= 0; /* MS UCS-2 */
1257 sal_uInt32 ThreeTwo
= 0; /* MS ShiftJIS */
1258 sal_uInt32 ThreeThree
= 0; /* MS Big5 */
1259 sal_uInt32 ThreeFour
= 0; /* MS PRC */
1260 sal_uInt32 ThreeFive
= 0; /* MS Wansung */
1261 sal_uInt32 ThreeSix
= 0; /* MS Johab */
1263 const sal_uInt32 remaining_table_size
= table_size
-4;
1264 const sal_uInt32 nMinRecordSize
= 8;
1265 const sal_uInt32 nMaxRecords
= remaining_table_size
/ nMinRecordSize
;
1266 if (ncmaps
> nMaxRecords
)
1268 SAL_WARN("vcl.fonts", "Parsing error in " << OUString::createFromAscii(ttf
->fname
) <<
1269 ": " << nMaxRecords
<< " max possible entries, but " <<
1270 ncmaps
<< " claimed, truncating");
1271 ncmaps
= nMaxRecords
;
1274 for (unsigned int i
= 0; i
< ncmaps
; i
++) {
1275 /* sanity check, cmap entry must lie within table */
1276 sal_uInt32 nLargestFixedOffsetPos
= 8 + i
* 8;
1277 sal_uInt32 nMinSize
= nLargestFixedOffsetPos
+ sizeof(sal_uInt32
);
1278 if (nMinSize
> table_size
)
1280 SAL_WARN( "vcl.fonts", "Font " << OUString::createFromAscii(ttf
->fname
) << " claimed to have "
1281 << ncmaps
<< " cmaps, but only space for " << i
);
1285 sal_uInt16 pID
= GetUInt16(table
, 4 + i
* 8, 1);
1286 sal_uInt16 eID
= GetUInt16(table
, 6 + i
* 8, 1);
1287 sal_uInt32 offset
= GetUInt32(table
, nLargestFixedOffsetPos
, 1);
1289 /* sanity check, cmap must lie within file */
1290 if( (table
- ttf
->ptr
) + offset
> (sal_uInt32
)ttf
->fsize
)
1293 /* Unicode tables in Apple fonts */
1300 case 0: ThreeZero
= offset
; break;
1302 case 1: ThreeOne
= offset
; break;
1303 case 2: ThreeTwo
= offset
; break;
1304 case 3: ThreeThree
= offset
; break;
1305 case 4: ThreeFour
= offset
; break;
1306 case 5: ThreeFive
= offset
; break;
1307 case 6: ThreeSix
= offset
; break;
1312 // fall back to AppleUnicode if there are no ThreeOne/Threezero tables
1313 if( AppleUni
&& !ThreeZero
&& !ThreeOne
)
1314 ThreeOne
= AppleUni
;
1317 ttf
->cmapType
= CMAP_MS_Unicode
;
1318 ttf
->cmap
= table
+ ThreeOne
;
1319 } else if (ThreeTwo
) {
1320 ttf
->cmapType
= CMAP_MS_ShiftJIS
;
1321 ttf
->cmap
= table
+ ThreeTwo
;
1322 } else if (ThreeThree
) {
1323 ttf
->cmapType
= CMAP_MS_Big5
;
1324 ttf
->cmap
= table
+ ThreeThree
;
1325 } else if (ThreeFour
) {
1326 ttf
->cmapType
= CMAP_MS_PRC
;
1327 ttf
->cmap
= table
+ ThreeFour
;
1328 } else if (ThreeFive
) {
1329 ttf
->cmapType
= CMAP_MS_Wansung
;
1330 ttf
->cmap
= table
+ ThreeFive
;
1331 } else if (ThreeSix
) {
1332 ttf
->cmapType
= CMAP_MS_Johab
;
1333 ttf
->cmap
= table
+ ThreeSix
;
1334 } else if (ThreeZero
) {
1335 ttf
->cmapType
= CMAP_MS_Symbol
;
1336 ttf
->cmap
= table
+ ThreeZero
;
1338 ttf
->cmapType
= CMAP_NOT_USABLE
;
1342 if (ttf
->cmapType
!= CMAP_NOT_USABLE
) {
1343 switch (GetUInt16(ttf
->cmap
, 0, 1)) {
1344 case 0: ttf
->mapper
= getGlyph0
; break;
1345 case 2: ttf
->mapper
= getGlyph2
; break;
1346 case 4: ttf
->mapper
= getGlyph4
; break;
1347 case 6: ttf
->mapper
= getGlyph6
; break;
1348 case 12: ttf
->mapper
= getGlyph12
; break;
1350 #if OSL_DEBUG_LEVEL > 1
1351 /*- if the cmap table is really broken */
1352 printf("%s: %d is not a recognized cmap format.\n", ttf
->fname
, GetUInt16(ttf
->cmap
, 0, 1));
1354 ttf
->cmapType
= CMAP_NOT_USABLE
;
1361 static void GetKern(TrueTypeFont
*ttf
)
1363 const sal_uInt8
* table
= getTable(ttf
, O_kern
);
1364 int nTableSize
= getTableSize(ttf
, O_kern
);
1365 const sal_uInt8
*ptr
;
1370 if (GetUInt16(table
, 0, 1) == 0) { /* Traditional Microsoft style table with sal_uInt16 version and nTables fields */
1371 ttf
->nkern
= GetUInt16(table
, 2, 1);
1372 ttf
->kerntype
= KT_MICROSOFT
;
1375 const sal_uInt32 remaining_table_size
= nTableSize
-4;
1376 const sal_uInt32 nMinRecordSize
= 2;
1377 const sal_uInt32 nMaxRecords
= remaining_table_size
/ nMinRecordSize
;
1378 if (ttf
->nkern
> nMaxRecords
)
1380 SAL_WARN("vcl.fonts", "Parsing error in " << OUString::createFromAscii(ttf
->fname
) <<
1381 ": " << nMaxRecords
<< " max possible entries, but " <<
1382 ttf
->nkern
<< " claimed, truncating");
1383 ttf
->nkern
= nMaxRecords
;
1386 ttf
->kerntables
= static_cast<const sal_uInt8
**>(calloc(ttf
->nkern
, sizeof(sal_uInt8
*)));
1387 assert(ttf
->kerntables
!= 0);
1389 for( unsigned i
= 0; i
< ttf
->nkern
; ++i
) {
1390 ttf
->kerntables
[i
] = ptr
;
1391 ptr
+= GetUInt16(ptr
, 2, 1);
1393 if( ptr
> ttf
->ptr
+ttf
->fsize
)
1395 free( ttf
->kerntables
);
1402 if (GetUInt32(table
, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and sal_uInt32 nTables fields */
1403 ttf
->nkern
= GetUInt32(table
, 4, 1);
1404 ttf
->kerntype
= KT_APPLE_NEW
;
1407 const sal_uInt32 remaining_table_size
= nTableSize
-8;
1408 const sal_uInt32 nMinRecordSize
= 4;
1409 const sal_uInt32 nMaxRecords
= remaining_table_size
/ nMinRecordSize
;
1410 if (ttf
->nkern
> nMaxRecords
)
1412 SAL_WARN("vcl.fonts", "Parsing error in " << OUString::createFromAscii(ttf
->fname
) <<
1413 ": " << nMaxRecords
<< " max possible entries, but " <<
1414 ttf
->nkern
<< " claimed, truncating");
1415 ttf
->nkern
= nMaxRecords
;
1418 ttf
->kerntables
= static_cast<const sal_uInt8
**>(calloc(ttf
->nkern
, sizeof(sal_uInt8
*)));
1419 assert(ttf
->kerntables
!= 0);
1421 for( unsigned i
= 0; i
< ttf
->nkern
; ++i
) {
1422 ttf
->kerntables
[i
] = ptr
;
1423 ptr
+= GetUInt32(ptr
, 0, 1);
1424 /* sanity check; there are some fonts that are broken in this regard */
1425 if( ptr
> ttf
->ptr
+ttf
->fsize
)
1427 free( ttf
->kerntables
);
1435 ttf
->kerntype
= KT_NONE
;
1436 ttf
->kerntables
= 0;
1441 /*- Public functions */
1443 int CountTTCFonts(const char* fname
)
1446 sal_uInt8 buffer
[12];
1447 FILE* fd
= fopen(fname
, "rb");
1449 if (fread(buffer
, 1, 12, fd
) == 12) {
1450 if(GetUInt32(buffer
, 0, 1) == T_ttcf
)
1451 nFonts
= GetUInt32(buffer
, 8, 1);
1458 static void allocTrueTypeFont( TrueTypeFont
** ttf
)
1460 *ttf
= static_cast<TrueTypeFont
*>(calloc(1,sizeof(TrueTypeFont
)));
1467 (*ttf
)->nglyphs
= 0xFFFFFFFF;
1468 (*ttf
)->pGSubstitution
= 0;
1472 /* forward declariotn for the two entry points to use*/
1473 static int doOpenTTFont( sal_uInt32 facenum
, TrueTypeFont
* t
);
1476 int OpenTTFontFile( const char* fname
, sal_uInt32 facenum
, TrueTypeFont
** ttf
)
1481 if (!fname
|| !*fname
) return SF_BADFILE
;
1483 allocTrueTypeFont( ttf
);
1487 (*ttf
)->fname
= strdup(fname
);
1488 if( ! (*ttf
)->fname
)
1494 fd
= open(fname
, O_RDONLY
);
1501 if (fstat(fd
, &st
) == -1) {
1506 (*ttf
)->fsize
= st
.st_size
;
1508 /* On Mac OS, most likely will happen if a Mac user renames a font file
1509 * to be .ttf when its really a Mac resource-based font.
1510 * Size will be 0, but fonts smaller than 4 bytes would be broken anyway.
1512 if ((*ttf
)->fsize
== 0) {
1517 if (((*ttf
)->ptr
= static_cast<sal_uInt8
*>(mmap(0, (*ttf
)->fsize
, PROT_READ
, MAP_SHARED
, fd
, 0))) == MAP_FAILED
) {
1523 return doOpenTTFont( facenum
, *ttf
);
1526 if (fd
!= -1) close(fd
);
1527 /*- t and t->fname have been allocated! */
1528 free((*ttf
)->fname
);
1535 int OpenTTFontBuffer(const void* pBuffer
, sal_uInt32 nLen
, sal_uInt32 facenum
, TrueTypeFont
** ttf
)
1537 allocTrueTypeFont( ttf
);
1541 (*ttf
)->fname
= NULL
;
1542 (*ttf
)->fsize
= nLen
;
1543 (*ttf
)->ptr
= const_cast<sal_uInt8
*>(static_cast<sal_uInt8
const *>(pBuffer
));
1545 return doOpenTTFont( facenum
, *ttf
);
1548 static int doOpenTTFont( sal_uInt32 facenum
, TrueTypeFont
* t
)
1551 sal_uInt32 length
, tag
;
1552 sal_uInt32 tdoffset
= 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */
1555 sal_uInt32 TTCTag
= GetInt32(t
->ptr
, 0, 1);
1557 if ((TTCTag
== 0x00010000) || (TTCTag
== T_true
)) {
1559 } else if (TTCTag
== T_otto
) { /* PS-OpenType font */
1561 } else if (TTCTag
== T_ttcf
) { /* TrueType collection */
1562 sal_uInt32 Version
= GetUInt32(t
->ptr
, 4, 1);
1563 if (Version
!= 0x00010000 && Version
!= 0x00020000) {
1567 if (facenum
>= GetUInt32(t
->ptr
, 8, 1)) {
1571 tdoffset
= GetUInt32(t
->ptr
, 12 + 4 * facenum
, 1);
1578 t
->tag
= TTFontClassTag
;
1580 t
->ntables
= GetUInt16(t
->ptr
+ tdoffset
, 4, 1);
1581 if( t
->ntables
>= 128 )
1584 t
->tables
= static_cast<const sal_uInt8
**>(calloc(NUM_TAGS
, sizeof(sal_uInt8
*)));
1585 assert(t
->tables
!= 0);
1586 t
->tlens
= static_cast<sal_uInt32
*>(calloc(NUM_TAGS
, sizeof(sal_uInt32
)));
1587 assert(t
->tlens
!= 0);
1589 /* parse the tables */
1590 for (i
=0; i
<(int)t
->ntables
; i
++) {
1592 tag
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
, 1);
1594 case T_maxp
: nIndex
= O_maxp
; break;
1595 case T_glyf
: nIndex
= O_glyf
; break;
1596 case T_head
: nIndex
= O_head
; break;
1597 case T_loca
: nIndex
= O_loca
; break;
1598 case T_name
: nIndex
= O_name
; break;
1599 case T_hhea
: nIndex
= O_hhea
; break;
1600 case T_hmtx
: nIndex
= O_hmtx
; break;
1601 case T_cmap
: nIndex
= O_cmap
; break;
1602 case T_vhea
: nIndex
= O_vhea
; break;
1603 case T_vmtx
: nIndex
= O_vmtx
; break;
1604 case T_OS2
: nIndex
= O_OS2
; break;
1605 case T_post
: nIndex
= O_post
; break;
1606 case T_kern
: nIndex
= O_kern
; break;
1607 case T_cvt
: nIndex
= O_cvt
; break;
1608 case T_prep
: nIndex
= O_prep
; break;
1609 case T_fpgm
: nIndex
= O_fpgm
; break;
1610 case T_gsub
: nIndex
= O_gsub
; break;
1611 case T_CFF
: nIndex
= O_CFF
; break;
1612 default: nIndex
= -1; break;
1615 sal_uInt32 nTableOffset
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
+ 8, 1);
1616 length
= GetUInt32(t
->ptr
+ tdoffset
+ 12, 16 * i
+ 12, 1);
1617 t
->tables
[nIndex
] = t
->ptr
+ nTableOffset
;
1618 t
->tlens
[nIndex
] = length
;
1622 /* Fixup offsets when only a TTC extract was provided */
1623 if( facenum
== (sal_uInt32
)~0 ) {
1624 sal_uInt8
* pHead
= const_cast<sal_uInt8
*>(t
->tables
[O_head
]);
1627 /* limit Head candidate to TTC extract's limits */
1628 if( pHead
> t
->ptr
+ (t
->fsize
- 54) )
1629 pHead
= t
->ptr
+ (t
->fsize
- 54);
1630 /* TODO: find better method than searching head table's magic */
1631 sal_uInt8
* p
= NULL
;
1632 for( p
= pHead
+ 12; p
> t
->ptr
; --p
) {
1633 if( p
[0]==0x5F && p
[1]==0x0F && p
[2]==0x3C && p
[3]==0xF5 ) {
1634 int nDelta
= (pHead
+ 12) - p
;
1636 for( int j
= 0; j
< NUM_TAGS
; ++j
)
1638 *reinterpret_cast<char const **>(&t
->tables
[j
]) -= nDelta
;
1646 /* Check the table offsets after TTC correction */
1647 for (i
=0; i
<NUM_TAGS
; i
++) {
1648 /* sanity check: table must lay completely within the file
1649 * at this point one could check the checksum of all contained
1650 * tables, but this would be quite time intensive.
1651 * Try to fix tables, so we can cope with minor problems.
1654 if( t
->tables
[i
] < t
->ptr
)
1656 #if OSL_DEBUG_LEVEL > 1
1658 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
);
1661 t
->tables
[i
] = NULL
;
1663 else if( const_cast<sal_uInt8
*>(t
->tables
[i
]) + t
->tlens
[i
] > t
->ptr
+ t
->fsize
)
1665 int nMaxLen
= (t
->ptr
+ t
->fsize
) - t
->tables
[i
];
1668 t
->tlens
[i
] = nMaxLen
;
1669 #if OSL_DEBUG_LEVEL > 1
1670 fprintf( stderr
, "font file %s has too big table (tagnum=%d)\n", t
->fname
, i
);
1675 /* At this point TrueTypeFont is constructed, now need to verify the font format
1676 and read the basic font properties */
1678 /* The following tables are absolutely required:
1679 * maxp, head, name, cmap
1682 if( !(getTable(t
, O_maxp
) && getTable(t
, O_head
) && getTable(t
, O_name
) && getTable(t
, O_cmap
)) ) {
1687 const sal_uInt8
* table
= getTable(t
, O_maxp
);
1688 t
->nglyphs
= GetUInt16(table
, 4, 1);
1690 table
= getTable(t
, O_head
);
1691 t
->unitsPerEm
= GetUInt16(table
, 18, 1);
1692 indexfmt
= GetInt16(table
, 50, 1);
1694 if( ((indexfmt
!= 0) && (indexfmt
!= 1)) || (t
->unitsPerEm
<= 0) ) {
1699 if( getTable(t
, O_glyf
) && getTable(t
, O_loca
) ) /* TTF or TTF-OpenType */
1701 int k
= (getTableSize(t
, O_loca
) / (indexfmt
? 4 : 2)) - 1;
1702 if( k
< (int)t
->nglyphs
) /* Hack for broken Chinese fonts */
1705 table
= getTable(t
, O_loca
);
1706 t
->goffsets
= static_cast<sal_uInt32
*>(calloc(1+t
->nglyphs
, sizeof(sal_uInt32
)));
1707 assert(t
->goffsets
!= 0);
1709 for( i
= 0; i
<= (int)t
->nglyphs
; ++i
)
1710 t
->goffsets
[i
] = indexfmt
? GetUInt32(table
, i
<< 2, 1) : (sal_uInt32
)GetUInt16(table
, i
<< 1, 1) << 1;
1711 } else if( getTable(t
, O_CFF
) ) { /* PS-OpenType */
1712 t
->goffsets
= static_cast<sal_uInt32
*>(calloc(1+t
->nglyphs
, sizeof(sal_uInt32
)));
1713 /* TODO: implement to get subsetting */
1714 assert(t
->goffsets
!= 0);
1720 table
= getTable(t
, O_hhea
);
1721 t
->numberOfHMetrics
= (table
!= 0) ? GetUInt16(table
, 34, 1) : 0;
1723 table
= getTable(t
, O_vhea
);
1724 t
->numOfLongVerMetrics
= (table
!= 0) ? GetUInt16(table
, 34, 1) : 0;
1729 ReadGSUB( t
, 0, 0 );
1734 void CloseTTFont(TrueTypeFont
*ttf
)
1738 munmap(ttf
->ptr
, ttf
->fsize
);
1741 free(ttf
->goffsets
);
1745 free( ttf
->ufamily
);
1746 free(ttf
->subfamily
);
1747 if( ttf
->usubfamily
)
1748 free( ttf
->usubfamily
);
1751 free(ttf
->kerntables
);
1759 int GetTTGlyphPoints(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, ControlPoint
**pointArray
)
1761 return GetTTGlyphOutline(ttf
, glyphID
, pointArray
, 0, 0);
1764 int GetTTGlyphComponents(TrueTypeFont
*ttf
, sal_uInt32 glyphID
, std::vector
< sal_uInt32
>& glyphlist
)
1768 if( glyphID
>= ttf
->nglyphs
)
1771 const sal_uInt8
* glyf
= getTable(ttf
, O_glyf
);
1772 const sal_uInt8
* ptr
= glyf
+ ttf
->goffsets
[glyphID
];
1774 glyphlist
.push_back( glyphID
);
1776 if (GetInt16(ptr
, 0, 1) == -1) {
1777 sal_uInt16 flags
, index
;
1780 flags
= GetUInt16(ptr
, 0, 1);
1781 index
= GetUInt16(ptr
, 2, 1);
1784 n
+= GetTTGlyphComponents(ttf
, index
, glyphlist
);
1786 if (flags
& ARG_1_AND_2_ARE_WORDS
) {
1792 if (flags
& WE_HAVE_A_SCALE
) {
1794 } else if (flags
& WE_HAVE_AN_X_AND_Y_SCALE
) {
1796 } else if (flags
& WE_HAVE_A_TWO_BY_TWO
) {
1799 } while (flags
& MORE_COMPONENTS
);
1805 int CreateT3FromTTGlyphs(TrueTypeFont
*ttf
, FILE *outf
, const char *fname
,
1806 sal_uInt16
*glyphArray
, sal_uInt8
*encoding
, int nGlyphs
,
1810 PSPathElement
*path
;
1812 const sal_uInt8
* table
= getTable(ttf
, O_head
);
1813 TTGlyphMetrics metrics
;
1814 int UPEm
= ttf
->unitsPerEm
;
1816 const char *h01
= "%%!PS-AdobeFont-%d.%d-%d.%d\n";
1817 const char *h02
= "%% Creator: %s %s %s\n";
1818 const char *h09
= "%% Original font name: %s\n";
1822 "/PaintType 0 def\n"
1824 "/StrokeWidth 0 def\n";
1826 const char *h11
= "/FontName (%s) cvn def\n";
1829 const char *h12 = "%/UniqueID %d def\n";
1831 const char *h13
= "/FontMatrix [.001 0 0 .001 0 0] def\n";
1832 const char *h14
= "/FontBBox [%d %d %d %d] def\n";
1835 "/Encoding 256 array def\n"
1836 " 0 1 255 {Encoding exch /.notdef put} for\n";
1838 const char *h16
= " Encoding %d /glyph%d put\n";
1839 const char *h17
= "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n";
1841 const char *h30
= "/CharProcs %d dict def\n";
1842 const char *h31
= " CharProcs begin\n";
1843 const char *h32
= " /.notdef {} def\n";
1844 const char *h33
= " /glyph%d {\n";
1845 const char *h34
= " } bind def\n";
1846 const char *h35
= " end\n";
1850 " exch /CharProcs get exch\n"
1851 " 2 copy known not\n"
1852 " {pop /.notdef} if\n"
1856 " 1 index /Encoding get exch get\n"
1857 " 1 index /BuildGlyph get exec\n"
1859 "currentdict end\n";
1861 const char *h41
= "(%s) cvn exch definefont pop\n";
1863 if (!((nGlyphs
> 0) && (nGlyphs
<= 256))) return SF_GLYPHNUM
;
1864 if (!glyphArray
) return SF_BADARG
;
1865 if (!fname
) fname
= ttf
->psname
;
1867 fprintf(outf
, h01
, GetInt16(table
, 0, 1), GetUInt16(table
, 2, 1), GetInt16(table
, 4, 1), GetUInt16(table
, 6, 1));
1868 fprintf(outf
, h02
, modname
, modver
, modextra
);
1869 fprintf(outf
, h09
, ttf
->psname
);
1871 fprintf(outf
, "%s", h10
);
1872 fprintf(outf
, h11
, fname
);
1873 /* fprintf(outf, h12, 4000000); */
1876 * 103 0 0 C1 C2 C3 C4
1877 * C1 - CRC-32 of the entire source TrueType font
1878 * C2 - number of glyphs in the subset
1879 * C3 - CRC-32 of the glyph array
1880 * C4 - CRC-32 of the encoding array
1882 * All CRC-32 numbers are presented as hexadecimal numbers
1885 fprintf(outf
, h17
, rtl_crc32(0, ttf
->ptr
, ttf
->fsize
), nGlyphs
, rtl_crc32(0, glyphArray
, nGlyphs
* 2), rtl_crc32(0, encoding
, nGlyphs
));
1886 fprintf(outf
, "%s", h13
);
1887 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)));
1888 fprintf(outf
, "%s", h15
);
1890 for (i
= 0; i
< nGlyphs
; i
++) {
1891 fprintf(outf
, h16
, encoding
[i
], i
);
1894 fprintf(outf
, h30
, nGlyphs
+1);
1895 fprintf(outf
, "%s", h31
);
1896 fprintf(outf
, "%s", h32
);
1898 for (i
= 0; i
< nGlyphs
; i
++) {
1899 fprintf(outf
, h33
, i
);
1900 int r
= GetTTGlyphOutline(ttf
, glyphArray
[i
] < ttf
->nglyphs
? glyphArray
[i
] : 0, &pa
, &metrics
, 0);
1903 n
= BSplineToPSPath(pa
, r
, &path
);
1905 n
= 0; /* glyph might have zero contours but valid metrics ??? */
1907 if (r
< 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */
1911 fprintf(outf
, "\t%d %d %d %d %d %d setcachedevice\n",
1912 wmode
== 0 ? XUnits(UPEm
, metrics
.aw
) : 0,
1913 wmode
== 0 ? 0 : -XUnits(UPEm
, metrics
.ah
),
1914 XUnits(UPEm
, metrics
.xMin
),
1915 XUnits(UPEm
, metrics
.yMin
),
1916 XUnits(UPEm
, metrics
.xMax
),
1917 XUnits(UPEm
, metrics
.yMax
));
1919 for (j
= 0; j
< n
; j
++)
1921 switch (path
[j
].type
)
1924 fprintf(outf
, "\t%d %d moveto\n", XUnits(UPEm
, path
[j
].x1
), XUnits(UPEm
, path
[j
].y1
));
1928 fprintf(outf
, "\t%d %d lineto\n", XUnits(UPEm
, path
[j
].x1
), XUnits(UPEm
, path
[j
].y1
));
1932 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
));
1936 fprintf(outf
, "\tclosepath\n");
1942 if (n
> 0) fprintf(outf
, "\tfill\n"); /* if glyph is not a whitespace character */
1944 fprintf(outf
, "%s", h34
);
1949 fprintf(outf
, "%s", h35
);
1951 fprintf(outf
, "%s", h40
);
1952 fprintf(outf
, h41
, fname
);
1957 int CreateTTFromTTGlyphs(TrueTypeFont
*ttf
,
1959 sal_uInt16
*glyphArray
,
1960 sal_uInt8
*encoding
,
1966 TrueTypeCreator
*ttcr
;
1967 TrueTypeTable
*head
=0, *hhea
=0, *maxp
=0, *cvt
=0, *prep
=0, *glyf
=0, *fpgm
=0, *cmap
=0, *name
=0, *post
= 0, *os2
= 0;
1971 TrueTypeCreatorNewEmpty(T_true
, &ttcr
);
1975 if (flags
& TTCF_AutoName
) {
1976 /* not implemented yet
1979 int n = GetTTNameRecords(ttf, &names);
1980 int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
1982 sal_uInt8 suffix[32];
1983 sal_uInt32 c1 = crc32(glyphArray, nGlyphs * 2);
1984 sal_uInt32 c2 = crc32(encoding, nGlyphs);
1986 snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs);
1988 name = TrueTypeTableNew_name(0, 0);
1989 for (i = 0; i < n; i++) {
1990 if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) {
1992 memcpy(newname, names+i, sizeof(NameRecord));
1993 newname.slen = name[i].slen + strlen(suffix);
1995 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'};
1996 NameRecord n1
= {1, 0, 0, 6, 14, const_cast<sal_uInt8
*>(reinterpret_cast<sal_uInt8
const *>("TrueTypeSubset"))};
1997 NameRecord n2
= {3, 1, 1033, 6, 28, 0};
1998 n2
.sptr
= const_cast<sal_uInt8
*>(ptr
);
1999 name
= TrueTypeTableNew_name(0, 0);
2003 if (nNameRecs
== 0) {
2005 int n
= GetTTNameRecords(ttf
, &names
);
2006 name
= TrueTypeTableNew_name(n
, names
);
2007 DisposeNameRecords(names
, n
);
2009 name
= TrueTypeTableNew_name(nNameRecs
, nr
);
2014 maxp
= TrueTypeTableNew_maxp(getTable(ttf
, O_maxp
), getTableSize(ttf
, O_maxp
));
2017 const sal_uInt8
* p
= getTable(ttf
, O_hhea
);
2019 hhea
= TrueTypeTableNew_hhea(GetUInt16(p
, 4, 1), GetUInt16(p
, 6, 1), GetUInt16(p
, 8, 1), GetUInt16(p
, 18, 1), GetUInt16(p
, 20, 1));
2021 hhea
= TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2026 p
= getTable(ttf
, O_head
);
2028 head
= TrueTypeTableNew_head(GetUInt32(p
, 4, 1),
2029 GetUInt16(p
, 16, 1),
2030 GetUInt16(p
, 18, 1),
2032 GetUInt16(p
, 44, 1),
2033 GetUInt16(p
, 46, 1),
2034 GetInt16(p
, 48, 1));
2038 glyf
= TrueTypeTableNew_glyf();
2039 sal_uInt32
* gID
= static_cast<sal_uInt32
*>(scalloc(nGlyphs
, sizeof(sal_uInt32
)));
2041 for (i
= 0; i
< nGlyphs
; i
++) {
2042 gID
[i
] = glyfAdd(glyf
, GetTTRawGlyphData(ttf
, glyphArray
[i
]), ttf
);
2046 cmap
= TrueTypeTableNew_cmap();
2048 for (i
=0; i
< nGlyphs
; i
++) {
2049 cmapAdd(cmap
, 0x010000, encoding
[i
], gID
[i
]);
2053 if ((p
= getTable(ttf
, O_cvt
)) != 0) {
2054 cvt
= TrueTypeTableNew(T_cvt
, getTableSize(ttf
, O_cvt
), p
);
2058 if ((p
= getTable(ttf
, O_prep
)) != 0) {
2059 prep
= TrueTypeTableNew(T_prep
, getTableSize(ttf
, O_prep
), p
);
2063 if ((p
= getTable(ttf
, O_fpgm
)) != 0) {
2064 fpgm
= TrueTypeTableNew(T_fpgm
, getTableSize(ttf
, O_fpgm
), p
);
2068 if ((p
= getTable(ttf
, O_post
)) != 0) {
2069 post
= TrueTypeTableNew_post(0x00030000,
2072 GetUInt16(p
, 10, 1),
2073 GetUInt16(p
, 12, 1));
2075 post
= TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
2078 if (flags
& TTCF_IncludeOS2
) {
2079 if ((p
= getTable(ttf
, O_OS2
)) != 0) {
2080 os2
= TrueTypeTableNew(T_OS2
, getTableSize(ttf
, O_OS2
), p
);
2084 AddTable(ttcr
, name
); AddTable(ttcr
, maxp
); AddTable(ttcr
, hhea
);
2085 AddTable(ttcr
, head
); AddTable(ttcr
, glyf
); AddTable(ttcr
, cmap
);
2086 AddTable(ttcr
, cvt
); AddTable(ttcr
, prep
); AddTable(ttcr
, fpgm
);
2087 AddTable(ttcr
, post
); AddTable(ttcr
, os2
);
2089 if ((res
= StreamToFile(ttcr
, fname
)) != SF_OK
) {
2090 #if OSL_DEBUG_LEVEL > 1
2091 fprintf(stderr
, "StreamToFile: error code: %d.\n", res
);
2095 TrueTypeCreatorDispose(ttcr
);
2101 static GlyphOffsets
*GlyphOffsetsNew(sal_uInt8
*sfntP
, sal_uInt32 sfntLen
)
2103 GlyphOffsets
* res
= static_cast<GlyphOffsets
*>(smalloc(sizeof(GlyphOffsets
)));
2104 sal_uInt8
*loca
= NULL
;
2105 sal_uInt16 i
, numTables
= GetUInt16(sfntP
, 4, 1);
2106 sal_uInt32 locaLen
= 0;
2107 sal_Int16 indexToLocFormat
= 0;
2109 sal_uInt32 nMaxPossibleTables
= sfntLen
/ (3*sizeof(sal_uInt32
)); /*the three GetUInt32 calls*/
2110 if (numTables
> nMaxPossibleTables
)
2112 SAL_WARN( "vcl.fonts", "GlyphOffsetsNew claimed to have "
2113 << numTables
<< " tables, but that's impossibly large");
2114 numTables
= nMaxPossibleTables
;
2117 for (i
= 0; i
< numTables
; i
++) {
2118 sal_uInt32 nLargestFixedOffsetPos
= 12 + 16 * i
+ 12;
2119 sal_uInt32 nMinSize
= nLargestFixedOffsetPos
+ sizeof(sal_uInt32
);
2120 if (nMinSize
> sfntLen
)
2122 SAL_WARN( "vcl.fonts", "GlyphOffsetsNew claimed to have "
2123 << numTables
<< " tables, but only space for " << i
);
2127 sal_uInt32 tag
= GetUInt32(sfntP
, 12 + 16 * i
, 1);
2128 sal_uInt32 off
= GetUInt32(sfntP
, 12 + 16 * i
+ 8, 1);
2129 sal_uInt32 len
= GetUInt32(sfntP
, nLargestFixedOffsetPos
, 1);
2131 if (tag
== T_loca
) {
2134 } else if (tag
== T_head
) {
2135 indexToLocFormat
= GetInt16(sfntP
+ off
, 50, 1);
2139 res
->nGlyphs
= locaLen
/ ((indexToLocFormat
== 1) ? 4 : 2);
2140 assert(res
->nGlyphs
!= 0);
2141 res
->offs
= static_cast<sal_uInt32
*>(scalloc(res
->nGlyphs
, sizeof(sal_uInt32
)));
2143 for (i
= 0; i
< res
->nGlyphs
; i
++) {
2144 if (indexToLocFormat
== 1) {
2145 res
->offs
[i
] = GetUInt32(loca
, i
* 4, 1);
2147 res
->offs
[i
] = GetUInt16(loca
, i
* 2, 1) << 1;
2153 static void GlyphOffsetsDispose(GlyphOffsets
*_this
)
2161 static void DumpSfnts(FILE *outf
, sal_uInt8
*sfntP
, sal_uInt32 sfntLen
)
2165 SAL_WARN( "vcl.fonts", "DumpSfnts sfntLen is too short: "
2166 << sfntLen
<< " legal min is: " << 12);
2170 const sal_uInt32 nSpaceForTables
= sfntLen
- 12;
2171 const sal_uInt32 nTableSize
= 16;
2172 const sal_uInt32 nMaxPossibleTables
= nSpaceForTables
/nTableSize
;
2174 HexFmt
*h
= HexFmtNew(outf
);
2175 sal_uInt16 i
, numTables
= GetUInt16(sfntP
, 4, 1);
2176 GlyphOffsets
*go
= GlyphOffsetsNew(sfntP
, sfntLen
);
2177 sal_uInt8 pad
[] = {0,0,0,0}; /* zeroes */
2179 if (numTables
> nMaxPossibleTables
)
2181 SAL_WARN( "vcl.fonts", "DumpSfnts claimed to have "
2182 << numTables
<< " tables, but only space for " << nMaxPossibleTables
);
2183 numTables
= nMaxPossibleTables
;
2186 assert(numTables
<= 9); /* Type42 has 9 required tables */
2188 sal_uInt32
* offs
= static_cast<sal_uInt32
*>(scalloc(numTables
, sizeof(sal_uInt32
)));
2190 fputs("/sfnts [", outf
);
2191 HexFmtOpenString(h
);
2192 HexFmtBlockWrite(h
, sfntP
, 12); /* stream out the Offset Table */
2193 HexFmtBlockWrite(h
, sfntP
+12, 16 * numTables
); /* stream out the Table Directory */
2195 for (i
=0; i
<numTables
; i
++)
2197 sal_uInt32 nLargestFixedOffsetPos
= 12 + 16 * i
+ 12;
2198 sal_uInt32 nMinSize
= nLargestFixedOffsetPos
+ sizeof(sal_uInt32
);
2199 if (nMinSize
> sfntLen
)
2201 SAL_WARN( "vcl.fonts", "DumpSfnts claimed to have "
2202 << numTables
<< " tables, but only space for " << i
);
2206 sal_uInt32 tag
= GetUInt32(sfntP
, 12 + 16 * i
, 1);
2207 sal_uInt32 off
= GetUInt32(sfntP
, 12 + 16 * i
+ 8, 1);
2210 SAL_WARN( "vcl.fonts", "DumpSfnts claims offset of "
2211 << off
<< " but max possible is " << sfntLen
);
2214 sal_uInt8
*pRecordStart
= sfntP
+ off
;
2215 sal_uInt32 len
= GetUInt32(sfntP
, nLargestFixedOffsetPos
, 1);
2216 sal_uInt32 nMaxLenPossible
= sfntLen
- off
;
2217 if (len
> nMaxLenPossible
)
2219 SAL_WARN( "vcl.fonts", "DumpSfnts claims len of "
2220 << len
<< " but only space for " << nMaxLenPossible
);
2226 HexFmtBlockWrite(h
, pRecordStart
, len
);
2230 sal_uInt8
*glyf
= pRecordStart
;
2231 for (sal_uInt32 j
= 0; j
< go
->nGlyphs
- 1; j
++)
2233 sal_uInt32 o
= go
->offs
[j
];
2234 sal_uInt32 l
= go
->offs
[j
+ 1] - o
;
2235 HexFmtBlockWrite(h
, glyf
+ o
, l
);
2238 HexFmtBlockWrite(h
, pad
, (4 - (len
& 3)) & 3);
2240 HexFmtCloseString(h
);
2241 fputs("] def\n", outf
);
2242 GlyphOffsetsDispose(go
);
2247 int CreateT42FromTTGlyphs(TrueTypeFont
*ttf
,
2250 sal_uInt16
*glyphArray
,
2251 sal_uInt8
*encoding
,
2254 TrueTypeCreator
*ttcr
;
2255 TrueTypeTable
*head
=0, *hhea
=0, *maxp
=0, *cvt
=0, *prep
=0, *glyf
=0, *fpgm
=0;
2259 sal_uInt32 ver
, rev
;
2263 int UPEm
= ttf
->unitsPerEm
;
2265 if (nGlyphs
>= 256) return SF_GLYPHNUM
;
2267 assert(psname
!= 0);
2269 TrueTypeCreatorNewEmpty(T_true
, &ttcr
);
2272 const sal_uInt8
* p
= getTable(ttf
, O_head
);
2273 const sal_uInt8
* headP
= p
;
2275 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));
2276 ver
= GetUInt32(p
, 0, 1);
2277 rev
= GetUInt32(p
, 4, 1);
2280 p
= getTable(ttf
, O_hhea
);
2282 hhea
= TrueTypeTableNew_hhea(GetUInt16(p
, 4, 1), GetUInt16(p
, 6, 1), GetUInt16(p
, 8, 1), GetUInt16(p
, 18, 1), GetUInt16(p
, 20, 1));
2284 hhea
= TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
2288 maxp
= TrueTypeTableNew_maxp(getTable(ttf
, O_maxp
), getTableSize(ttf
, O_maxp
));
2291 if ((p
= getTable(ttf
, O_cvt
)) != 0) {
2292 cvt
= TrueTypeTableNew(T_cvt
, getTableSize(ttf
, O_cvt
), p
);
2296 if ((p
= getTable(ttf
, O_prep
)) != 0) {
2297 prep
= TrueTypeTableNew(T_prep
, getTableSize(ttf
, O_prep
), p
);
2301 if ((p
= getTable(ttf
, O_fpgm
)) != 0) {
2302 fpgm
= TrueTypeTableNew(T_fpgm
, getTableSize(ttf
, O_fpgm
), p
);
2306 glyf
= TrueTypeTableNew_glyf();
2307 sal_uInt16
* gID
= static_cast<sal_uInt16
*>(scalloc(nGlyphs
, sizeof(sal_uInt32
)));
2309 for (i
= 0; i
< nGlyphs
; i
++) {
2310 gID
[i
] = (sal_uInt16
)glyfAdd(glyf
, GetTTRawGlyphData(ttf
, glyphArray
[i
]), ttf
);
2313 AddTable(ttcr
, head
); AddTable(ttcr
, hhea
); AddTable(ttcr
, maxp
); AddTable(ttcr
, cvt
);
2314 AddTable(ttcr
, prep
); AddTable(ttcr
, glyf
); AddTable(ttcr
, fpgm
);
2316 if ((res
= StreamToMemory(ttcr
, &sfntP
, &sfntLen
)) != SF_OK
) {
2317 TrueTypeCreatorDispose(ttcr
);
2322 fprintf(outf
, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", (int)(ver
>>16), (int)(ver
& 0xFFFF), (int)(rev
>>16), (int)(rev
& 0xFFFF));
2323 fprintf(outf
, "%%%%Creator: %s %s %s\n", modname
, modver
, modextra
);
2324 fprintf(outf
, "%%- Font subset generated from a source font file: '%s'\n", ttf
->fname
);
2325 fprintf(outf
, "%%- Original font name: %s\n", ttf
->psname
);
2326 fprintf(outf
, "%%- Original font family: %s\n", ttf
->family
);
2327 fprintf(outf
, "%%- Original font sub-family: %s\n", ttf
->subfamily
);
2328 fprintf(outf
, "11 dict begin\n");
2329 fprintf(outf
, "/FontName (%s) cvn def\n", psname
);
2330 fprintf(outf
, "/PaintType 0 def\n");
2331 fprintf(outf
, "/FontMatrix [1 0 0 1 0 0] def\n");
2332 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)));
2333 fprintf(outf
, "/FontType 42 def\n");
2334 fprintf(outf
, "/Encoding 256 array def\n");
2335 fprintf(outf
, " 0 1 255 {Encoding exch /.notdef put} for\n");
2337 for (i
= 1; i
<nGlyphs
; i
++) {
2338 fprintf(outf
, "Encoding %d /glyph%d put\n", encoding
[i
], gID
[i
]);
2340 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
));
2342 DumpSfnts(outf
, sfntP
, sfntLen
);
2344 /* dump charstrings */
2345 fprintf(outf
, "/CharStrings %d dict dup begin\n", nGlyphs
);
2346 fprintf(outf
, "/.notdef 0 def\n");
2347 for (i
= 1; i
< (int)glyfCount(glyf
); i
++) {
2348 fprintf(outf
,"/glyph%d %d def\n", i
, i
);
2350 fprintf(outf
, "end readonly def\n");
2352 fprintf(outf
, "FontName currentdict end definefont pop\n");
2353 TrueTypeCreatorDispose(ttcr
);
2359 int MapString(TrueTypeFont
*ttf
, sal_uInt16
*str
, int nchars
, sal_uInt16
*glyphArray
, bool bvertical
)
2364 if (ttf
->cmapType
== CMAP_NOT_USABLE
) return -1;
2365 if (!nchars
) return 0;
2367 if (glyphArray
== 0) {
2373 switch (ttf
->cmapType
) {
2374 case CMAP_MS_Symbol
:
2375 if( ttf
->mapper
== getGlyph0
) {
2377 for( i
= 0; i
< nchars
; i
++ ) {
2379 if( ( aChar
& 0xf000 ) == 0xf000 )
2384 else if( glyphArray
)
2385 memcpy(glyphArray
, str
, nchars
* 2);
2388 case CMAP_MS_Unicode
:
2389 if (glyphArray
!= 0) {
2390 memcpy(glyphArray
, str
, nchars
* 2);
2394 case CMAP_MS_ShiftJIS
: TranslateString12(str
, cp
, nchars
); break;
2395 case CMAP_MS_Big5
: TranslateString13(str
, cp
, nchars
); break;
2396 case CMAP_MS_PRC
: TranslateString14(str
, cp
, nchars
); break;
2397 case CMAP_MS_Wansung
: TranslateString15(str
, cp
, nchars
); break;
2398 case CMAP_MS_Johab
: TranslateString16(str
, cp
, nchars
); break;
2401 const sal_uInt32 nMaxCmapSize
= ttf
->ptr
+ ttf
->fsize
- ttf
->cmap
;
2402 for (i
= 0; i
< nchars
; i
++) {
2403 cp
[i
] = (sal_uInt16
)ttf
->mapper(ttf
->cmap
, nMaxCmapSize
, cp
[i
]);
2404 if (cp
[i
]!=0 && bvertical
)
2405 cp
[i
] = (sal_uInt16
)UseGSUB(ttf
,cp
[i
]);
2410 sal_uInt16
MapChar(TrueTypeFont
*ttf
, sal_uInt16 ch
, bool bvertical
)
2412 switch (ttf
->cmapType
) {
2413 case CMAP_MS_Symbol
:
2415 const sal_uInt32 nMaxCmapSize
= ttf
->ptr
+ ttf
->fsize
- ttf
->cmap
;
2416 if( ttf
->mapper
== getGlyph0
&& ( ch
& 0xf000 ) == 0xf000 )
2418 return (sal_uInt16
)ttf
->mapper(ttf
->cmap
, nMaxCmapSize
, ch
);
2421 case CMAP_MS_Unicode
: break;
2422 case CMAP_MS_ShiftJIS
: ch
= TranslateChar12(ch
); break;
2423 case CMAP_MS_Big5
: ch
= TranslateChar13(ch
); break;
2424 case CMAP_MS_PRC
: ch
= TranslateChar14(ch
); break;
2425 case CMAP_MS_Wansung
: ch
= TranslateChar15(ch
); break;
2426 case CMAP_MS_Johab
: ch
= TranslateChar16(ch
); break;
2429 const sal_uInt32 nMaxCmapSize
= ttf
->ptr
+ ttf
->fsize
- ttf
->cmap
;
2430 ch
= (sal_uInt16
)ttf
->mapper(ttf
->cmap
, nMaxCmapSize
, ch
);
2431 if (ch
!=0 && bvertical
)
2432 ch
= (sal_uInt16
)UseGSUB(ttf
,ch
);
2436 int DoesVerticalSubstitution( TrueTypeFont
*ttf
, int bvertical
)
2440 nRet
= HasVerticalGSUB( ttf
);
2444 int GetTTGlyphCount( TrueTypeFont
* ttf
)
2446 return ttf
->nglyphs
;
2449 bool GetSfntTable( TrueTypeFont
* ttf
, int nSubtableIndex
,
2450 const sal_uInt8
** ppRawBytes
, int* pRawLength
)
2452 if( (nSubtableIndex
< 0) || (nSubtableIndex
>= NUM_TAGS
) )
2454 *pRawLength
= ttf
->tlens
[ nSubtableIndex
];
2455 *ppRawBytes
= ttf
->tables
[ nSubtableIndex
];
2456 bool bOk
= (*pRawLength
> 0) && (*ppRawBytes
!= NULL
);
2460 TTSimpleGlyphMetrics
*GetTTSimpleGlyphMetrics(TrueTypeFont
*ttf
, sal_uInt16
*glyphArray
, int nGlyphs
, bool vertical
)
2462 const sal_uInt8
* pTable
;
2467 n
= ttf
->numberOfHMetrics
;
2468 pTable
= getTable( ttf
, O_hmtx
);
2469 nTableSize
= getTableSize( ttf
, O_hmtx
);
2471 n
= ttf
->numOfLongVerMetrics
;
2472 pTable
= getTable( ttf
, O_vmtx
);
2473 nTableSize
= getTableSize( ttf
, O_vmtx
);
2476 if (!nGlyphs
|| !glyphArray
) return 0; /* invalid parameters */
2477 if (!n
|| !pTable
) return 0; /* the font does not contain the requested metrics */
2479 TTSimpleGlyphMetrics
* res
= static_cast<TTSimpleGlyphMetrics
*>(calloc(nGlyphs
, sizeof(TTSimpleGlyphMetrics
)));
2482 const int UPEm
= ttf
->unitsPerEm
;
2483 for( int i
= 0; i
< nGlyphs
; ++i
) {
2484 int nAdvOffset
, nLsbOffset
;
2485 sal_uInt16 glyphID
= glyphArray
[i
];
2488 nAdvOffset
= 4 * glyphID
;
2489 nLsbOffset
= nAdvOffset
+ 2;
2491 nAdvOffset
= 4 * (n
- 1);
2492 if( glyphID
< ttf
->nglyphs
)
2493 nLsbOffset
= 4 * n
+ 2 * (glyphID
- n
);
2494 else /* font is broken -> use lsb of last hmetrics */
2495 nLsbOffset
= nAdvOffset
+ 2;
2498 if( nAdvOffset
>= nTableSize
)
2499 res
[i
].adv
= 0; /* better than a crash for buggy fonts */
2501 res
[i
].adv
= static_cast<sal_uInt16
>(
2502 XUnits( UPEm
, GetUInt16( pTable
, nAdvOffset
, 1) ) );
2504 if( nLsbOffset
>= nTableSize
)
2505 res
[i
].sb
= 0; /* better than a crash for buggy fonts */
2507 res
[i
].sb
= static_cast<sal_Int16
>(
2508 XUnits( UPEm
, GetInt16( pTable
, nLsbOffset
, 1) ) );
2514 TTSimpleGlyphMetrics
*GetTTSimpleCharMetrics(TrueTypeFont
* ttf
, sal_uInt16 firstChar
, int nChars
, bool vertical
)
2516 TTSimpleGlyphMetrics
*res
= 0;
2519 sal_uInt16
* str
= static_cast<sal_uInt16
*>(malloc(nChars
* 2));
2522 for (i
=0; i
<nChars
; i
++) str
[i
] = (sal_uInt16
)(firstChar
+ i
);
2523 if ((n
= MapString(ttf
, str
, nChars
, 0, vertical
)) != -1) {
2524 res
= GetTTSimpleGlyphMetrics(ttf
, str
, n
, vertical
);
2532 void GetTTGlobalFontInfo(TrueTypeFont
*ttf
, TTGlobalFontInfo
*info
)
2534 int UPEm
= ttf
->unitsPerEm
;
2536 memset(info
, 0, sizeof(TTGlobalFontInfo
));
2538 info
->family
= ttf
->family
;
2539 info
->ufamily
= ttf
->ufamily
;
2540 info
->subfamily
= ttf
->subfamily
;
2541 info
->usubfamily
= ttf
->usubfamily
;
2542 info
->psname
= ttf
->psname
;
2543 info
->symbolEncoded
= (ttf
->cmapType
== CMAP_MS_Symbol
);
2545 const sal_uInt8
* table
= getTable(ttf
, O_OS2
);
2547 info
->weight
= GetUInt16(table
, 4, 1);
2548 info
->width
= GetUInt16(table
, 6, 1);
2550 /* There are 3 different versions of OS/2 table: original (68 bytes long),
2551 * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,)
2552 * Apple's documentation recommends looking at the table length.
2554 if (getTableSize(ttf
, O_OS2
) > 68) {
2555 info
->typoAscender
= XUnits(UPEm
,GetInt16(table
, 68, 1));
2556 info
->typoDescender
= XUnits(UPEm
, GetInt16(table
, 70, 1));
2557 info
->typoLineGap
= XUnits(UPEm
, GetInt16(table
, 72, 1));
2558 info
->winAscent
= XUnits(UPEm
, GetUInt16(table
, 74, 1));
2559 info
->winDescent
= XUnits(UPEm
, GetUInt16(table
, 76, 1));
2560 /* sanity check; some fonts treat winDescent as signed
2561 * violating the standard */
2562 if( info
->winDescent
> 5*UPEm
)
2563 info
->winDescent
= XUnits(UPEm
, GetInt16(table
, 76,1));
2565 if (ttf
->cmapType
== CMAP_MS_Unicode
) {
2566 info
->rangeFlag
= 1;
2567 info
->ur1
= GetUInt32(table
, 42, 1);
2568 info
->ur2
= GetUInt32(table
, 46, 1);
2569 info
->ur3
= GetUInt32(table
, 50, 1);
2570 info
->ur4
= GetUInt32(table
, 54, 1);
2572 memcpy(info
->panose
, table
+ 32, 10);
2573 info
->typeFlags
= GetUInt16( table
, 8, 1 );
2574 if( getTable(ttf
, O_CFF
) )
2575 info
->typeFlags
|= TYPEFLAG_PS_OPENTYPE
;
2578 table
= getTable(ttf
, O_post
);
2579 if (table
&& getTableSize(ttf
, O_post
) >= 12+sizeof(sal_uInt32
)) {
2580 info
->pitch
= GetUInt32(table
, 12, 1);
2581 info
->italicAngle
= GetInt32(table
, 4, 1);
2584 table
= getTable(ttf
, O_head
); /* 'head' tables is always there */
2585 info
->xMin
= XUnits(UPEm
, GetInt16(table
, 36, 1));
2586 info
->yMin
= XUnits(UPEm
, GetInt16(table
, 38, 1));
2587 info
->xMax
= XUnits(UPEm
, GetInt16(table
, 40, 1));
2588 info
->yMax
= XUnits(UPEm
, GetInt16(table
, 42, 1));
2589 info
->macStyle
= GetInt16(table
, 44, 1);
2591 table
= getTable(ttf
, O_hhea
);
2593 info
->ascender
= XUnits(UPEm
, GetInt16(table
, 4, 1));
2594 info
->descender
= XUnits(UPEm
, GetInt16(table
, 6, 1));
2595 info
->linegap
= XUnits(UPEm
, GetInt16(table
, 8, 1));
2598 table
= getTable(ttf
, O_vhea
);
2600 info
->vascent
= XUnits(UPEm
, GetInt16(table
, 4, 1));
2601 info
->vdescent
= XUnits(UPEm
, GetInt16(table
, 6, 1));
2605 GlyphData
*GetTTRawGlyphData(TrueTypeFont
*ttf
, sal_uInt32 glyphID
)
2607 const sal_uInt8
* glyf
= getTable(ttf
, O_glyf
);
2608 const sal_uInt8
* hmtx
= getTable(ttf
, O_hmtx
);
2611 if( glyphID
>= ttf
->nglyphs
)
2614 /* #127161# check the glyph offsets */
2615 sal_uInt32 length
= getTableSize( ttf
, O_glyf
);
2616 if( length
< ttf
->goffsets
[ glyphID
+1 ] )
2619 length
= ttf
->goffsets
[glyphID
+1] - ttf
->goffsets
[glyphID
];
2621 GlyphData
* d
= static_cast<GlyphData
*>(malloc(sizeof(GlyphData
))); assert(d
!= 0);
2624 const sal_uInt8
* srcptr
= glyf
+ ttf
->goffsets
[glyphID
];
2625 d
->ptr
= static_cast<sal_uInt8
*>(malloc((length
+ 1) & ~1)); assert(d
->ptr
!= 0);
2626 memcpy( d
->ptr
, srcptr
, length
);
2627 d
->compflag
= (GetInt16( srcptr
, 0, 1 ) < 0);
2630 d
->compflag
= false;
2633 d
->glyphID
= glyphID
;
2634 d
->nbytes
= (sal_uInt16
)((length
+ 1) & ~1);
2636 /* now calculate npoints and ncontours */
2638 n
= GetTTGlyphPoints(ttf
, glyphID
, &cp
);
2642 for (int i
= 0; i
< n
; i
++)
2644 if (cp
[i
].flags
& 0x8000)
2647 d
->npoints
= (sal_uInt16
)n
;
2648 d
->ncontours
= (sal_uInt16
)m
;
2655 /* get advance width and left sidebearing */
2656 if (glyphID
< ttf
->numberOfHMetrics
) {
2657 d
->aw
= GetUInt16(hmtx
, 4 * glyphID
, 1);
2658 d
->lsb
= GetInt16(hmtx
, 4 * glyphID
+ 2, 1);
2660 d
->aw
= GetUInt16(hmtx
, 4 * (ttf
->numberOfHMetrics
- 1), 1);
2661 d
->lsb
= GetInt16(hmtx
+ ttf
->numberOfHMetrics
* 4, (glyphID
- ttf
->numberOfHMetrics
) * 2, 1);
2667 int GetTTNameRecords(TrueTypeFont
*ttf
, NameRecord
**nr
)
2669 const sal_uInt8
* table
= getTable(ttf
, O_name
);
2670 int nTableSize
= getTableSize(ttf
, O_name
);
2674 #if OSL_DEBUG_LEVEL > 1
2675 fprintf(stderr
, "O_name table too small\n");
2680 sal_uInt16 n
= GetUInt16(table
, 2, 1);
2681 int nStrBase
= GetUInt16(table
, 4, 1);
2685 if (n
== 0) return 0;
2687 const sal_uInt32 remaining_table_size
= nTableSize
-6;
2688 const sal_uInt32 nMinRecordSize
= 12;
2689 const sal_uInt32 nMaxRecords
= remaining_table_size
/ nMinRecordSize
;
2690 if (n
> nMaxRecords
)
2692 SAL_WARN("vcl.fonts", "Parsing error in " << OUString::createFromAscii(ttf
->fname
) <<
2693 ": " << nMaxRecords
<< " max possible entries, but " <<
2694 n
<< " claimed, truncating");
2698 NameRecord
* rec
= static_cast<NameRecord
*>(calloc(n
, sizeof(NameRecord
)));
2700 for (i
= 0; i
< n
; i
++) {
2701 int nLargestFixedOffsetPos
= 6 + 10 + 12 * i
;
2702 int nMinSize
= nLargestFixedOffsetPos
+ sizeof(sal_uInt16
);
2703 if (nMinSize
> nTableSize
)
2705 SAL_WARN( "vcl.fonts", "Font " << OUString::createFromAscii(ttf
->fname
) << " claimed to have "
2706 << n
<< " name records, but only space for " << i
);
2711 rec
[i
].platformID
= GetUInt16(table
, 6 + 0 + 12 * i
, 1);
2712 rec
[i
].encodingID
= GetUInt16(table
, 6 + 2 + 12 * i
, 1);
2713 rec
[i
].languageID
= GetUInt16(table
, 6 + 4 + 12 * i
, 1);
2714 rec
[i
].nameID
= GetUInt16(table
, 6 + 6 + 12 * i
, 1);
2715 rec
[i
].slen
= GetUInt16(table
, 6 + 8 + 12 * i
, 1);
2716 int nStrOffset
= GetUInt16(table
, nLargestFixedOffsetPos
, 1);
2718 if( nStrBase
+nStrOffset
+rec
[i
].slen
>= nTableSize
) {
2724 const sal_uInt8
* rec_string
= table
+ nStrBase
+ nStrOffset
;
2726 const sal_uInt8
* end_table
= ttf
->ptr
+ ttf
->fsize
;
2727 const size_t available_space
= rec_string
> end_table
? 0 : (end_table
- rec_string
);
2728 if (rec
[i
].slen
<= available_space
)
2730 rec
[i
].sptr
= static_cast<sal_uInt8
*>(malloc(rec
[i
].slen
)); assert(rec
[i
].sptr
!= 0);
2731 memcpy(rec
[i
].sptr
, rec_string
, rec
[i
].slen
);
2741 // some fonts have 3.0 names => fix them to 3.1
2742 if( (rec
[i
].platformID
== 3) && (rec
[i
].encodingID
== 0) )
2743 rec
[i
].encodingID
= 1;
2750 void DisposeNameRecords(NameRecord
* nr
, int n
)
2753 for (i
= 0; i
< n
; i
++) {
2754 if (nr
[i
].sptr
) free(nr
[i
].sptr
);
2760 boost::dynamic_bitset
<sal_uInt32
> &rUnicodeRange
,
2761 boost::dynamic_bitset
<sal_uInt32
> &rCodePageRange
,
2762 const unsigned char* pTable
, size_t nLength
)
2765 // parse OS/2 header
2768 rUnicodeRange
.append(GetUInt32(pTable
, 42, 1));
2769 rUnicodeRange
.append(GetUInt32(pTable
, 46, 1));
2770 rUnicodeRange
.append(GetUInt32(pTable
, 50, 1));
2771 rUnicodeRange
.append(GetUInt32(pTable
, 54, 1));
2775 rCodePageRange
.append(GetUInt32(pTable
, 78, 1));
2776 rCodePageRange
.append(GetUInt32(pTable
, 82, 1));
2782 void getTTScripts(std::vector
< sal_uInt32
> &rScriptTags
, const unsigned char* pTable
, size_t nLength
)
2787 // parse GSUB/GPOS header
2788 const sal_uInt16 nOfsScriptList
= GetUInt16(pTable
, 4, 1);
2790 // parse Script Table
2791 const sal_uInt16 nCntScript
= GetUInt16(pTable
, nOfsScriptList
, 1);
2792 sal_uInt32 nCurrentPos
= nOfsScriptList
+2;
2793 for( sal_uInt16 nScriptIndex
= 0;
2794 nScriptIndex
< nCntScript
&& nLength
>= 6; ++nScriptIndex
,
2797 sal_uInt32 nTag
= GetUInt32(pTable
, nCurrentPos
, 1);
2799 rScriptTags
.push_back(nTag
); // e.g. hani/arab/kana/hang
2802 std::sort(rScriptTags
.begin(), rScriptTags
.end());
2803 rScriptTags
.erase(std::unique(rScriptTags
.begin(), rScriptTags
.end()), rScriptTags
.end());
2808 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */