2 *******************************************************************************
4 * © 2016 and later: Unicode, Inc. and others.
5 * License & terms of use: http://www.unicode.org/copyright.html#License
7 *******************************************************************************
8 *******************************************************************************
10 * Copyright (C) 1999-2013, International Business Machines
11 * Corporation and others. All Rights Reserved.
13 *******************************************************************************
14 * file name: PortableFontInstance.cpp
16 * created on: 11/22/1999
17 * created by: Eric R. Mader
22 #include "layout/LETypes.h"
23 #include "layout/LEFontInstance.h"
24 #include "layout/LESwaps.h"
26 #include "PortableFontInstance.h"
35 static const char *letagToStr(LETag tag
, char *str
) {
36 str
[0]= 0xFF & (tag
>>24);
37 str
[1]= 0xFF & (tag
>>16);
38 str
[2]= 0xFF & (tag
>>8);
39 str
[3]= 0xFF & (tag
>>0);
46 // Finds the high bit by binary searching
47 // through the bits in n.
49 le_int8
PortableFontInstance::highBit(le_int32 value
)
57 if (value
>= 1 << 16) {
62 if (value
>= 1 << 8) {
67 if (value
>= 1 << 4) {
72 if (value
>= 1 << 2) {
77 if (value
>= 1 << 1) {
85 PortableFontInstance::PortableFontInstance(const char *fileName
, float pointSize
, LEErrorCode
&status
)
86 : fFile(NULL
), fPointSize(pointSize
), fUnitsPerEM(0), fFontChecksum(0), fAscent(0), fDescent(0), fLeading(0),
87 fDirectory(NULL
), fNAMETable(NULL
), fNameCount(0), fNameStringOffset(0), fCMAPMapper(NULL
), fHMTXTable(NULL
), fNumGlyphs(0), fNumLongHorMetrics(0)
89 if (LE_FAILURE(status
)) {
94 fFile
= fopen(fileName
, "rb");
95 //printf("Open Font: %s\n", fileName);
98 printf("%s:%d: %s: FNF\n", __FILE__
, __LINE__
, fileName
);
99 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
103 // read in the directory
104 SFNTDirectory tempDir
;
106 fread(&tempDir
, sizeof tempDir
, 1, fFile
);
108 le_int32 dirSize
= sizeof tempDir
+ ((SWAPW(tempDir
.numTables
) - ANY_NUMBER
) * sizeof(DirectoryEntry
));
109 const LETag headTag
= LE_HEAD_TABLE_TAG
;
110 const LETag hheaTag
= LE_HHEA_TABLE_TAG
;
111 const HEADTable
*headTable
= NULL
;
112 const HHEATable
*hheaTable
= NULL
;
113 // const NAMETable *nameTable = NULL;
114 le_uint16 numTables
= 0;
116 fDirectory
= (const SFNTDirectory
*) LE_NEW_ARRAY(char, dirSize
);
118 if (fDirectory
== NULL
) {
119 printf("%s:%d: %s: malloc err\n", __FILE__
, __LINE__
, fileName
);
120 status
= LE_MEMORY_ALLOCATION_ERROR
;
124 fseek(fFile
, 0L, SEEK_SET
);
125 fread((void *) fDirectory
, sizeof(char), dirSize
, fFile
);
128 // We calculate these numbers 'cause some fonts
129 // have bogus values for them in the directory header.
131 numTables
= SWAPW(fDirectory
->numTables
);
132 fDirPower
= 1 << highBit(numTables
);
133 fDirExtra
= numTables
- fDirPower
;
135 // read unitsPerEm from 'head' table
136 headTable
= (const HEADTable
*) readFontTable(headTag
);
138 if (headTable
== NULL
) {
139 status
= LE_MISSING_FONT_TABLE_ERROR
;
140 printf("%s:%d: %s: missing head table\n", __FILE__
, __LINE__
, fileName
);
144 fUnitsPerEM
= SWAPW(headTable
->unitsPerEm
);
145 fFontChecksum
= SWAPL(headTable
->checksumAdjustment
);
146 freeFontTable(headTable
);
148 //nameTable = (NAMETable *) readFontTable(nameTag);
150 //if (nameTable == NULL) {
151 // status = LE_MISSING_FONT_TABLE_ERROR;
155 //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
157 //if (fFontVersionString == NULL) {
158 // status = LE_MISSING_FONT_TABLE_ERROR;
162 //freeFontTable(nameTable);
164 hheaTable
= (HHEATable
*) readFontTable(hheaTag
);
166 if (hheaTable
== NULL
) {
167 printf("%s:%d: %s: missing hhea table\n", __FILE__
, __LINE__
, fileName
);
168 status
= LE_MISSING_FONT_TABLE_ERROR
;
172 fAscent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->ascent
));
173 fDescent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->descent
));
174 fLeading
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->lineGap
));
176 fNumLongHorMetrics
= SWAPW(hheaTable
->numOfLongHorMetrics
);
178 freeFontTable((void *) hheaTable
);
180 fCMAPMapper
= findUnicodeMapper();
182 if (fCMAPMapper
== NULL
) {
183 printf("%s:%d: %s: can't load cmap\n", __FILE__
, __LINE__
, fileName
);
184 status
= LE_MISSING_FONT_TABLE_ERROR
;
196 PortableFontInstance::~PortableFontInstance()
201 freeFontTable(fHMTXTable
);
202 freeFontTable(fNAMETable
);
206 LE_DELETE_ARRAY(fDirectory
);
210 const DirectoryEntry
*PortableFontInstance::findTable(LETag tag
) const
212 if (fDirectory
!= NULL
) {
214 le_uint16 probe
= fDirPower
;
216 if (SWAPL(fDirectory
->tableDirectory
[fDirExtra
].tag
) <= tag
) {
220 while (probe
> (1 << 0)) {
223 if (SWAPL(fDirectory
->tableDirectory
[table
+ probe
].tag
) <= tag
) {
228 if (SWAPL(fDirectory
->tableDirectory
[table
].tag
) == tag
) {
229 return &fDirectory
->tableDirectory
[table
];
236 const void *PortableFontInstance::readTable(LETag tag
, le_uint32
*length
) const
238 const DirectoryEntry
*entry
= findTable(tag
);
245 *length
= SWAPL(entry
->length
);
247 void *table
= LE_NEW_ARRAY(char, *length
);
250 fseek(fFile
, SWAPL(entry
->offset
), SEEK_SET
);
251 fread(table
, sizeof(char), *length
, fFile
);
257 const void *PortableFontInstance::getFontTable(LETag tableTag
) const
260 return getFontTable(tableTag
, ignored
);
263 const void *PortableFontInstance::getFontTable(LETag tableTag
, size_t &length
) const
265 return FontTableCache::find(tableTag
, length
);
268 const void *PortableFontInstance::readFontTable(LETag tableTag
, size_t &length
) const
272 const void *data
= readTable(tableTag
, &len
);
275 //printf("Read %s, result %p #%d\n", letagToStr(tableTag,tag5), data,len);
279 CMAPMapper
*PortableFontInstance::findUnicodeMapper()
281 LETag cmapTag
= LE_CMAP_TABLE_TAG
;
282 const CMAPTable
*cmap
= (CMAPTable
*) readFontTable(cmapTag
);
288 return CMAPMapper::createUnicodeMapper(cmap
);
291 const char *PortableFontInstance::getNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
293 if (fNAMETable
== NULL
) {
294 LETag nameTag
= LE_NAME_TABLE_TAG
;
295 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
297 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
299 if (realThis
->fNAMETable
!= NULL
) {
300 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
301 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
305 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
306 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
308 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
) == encodingID
&&
309 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
310 char *name
= ((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
);
311 le_uint16 length
= SWAPW(nameRecord
->length
);
312 char *result
= LE_NEW_ARRAY(char, length
+ 2);
314 LE_ARRAY_COPY(result
, name
, length
);
315 result
[length
] = result
[length
+ 1] = 0;
324 const LEUnicode16
*PortableFontInstance::getUnicodeNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
326 if (fNAMETable
== NULL
) {
327 LETag nameTag
= LE_NAME_TABLE_TAG
;
328 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
330 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
332 if (realThis
->fNAMETable
!= NULL
) {
333 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
334 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
338 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
339 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
341 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
) == encodingID
&&
342 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
343 LEUnicode16
*name
= (LEUnicode16
*) (((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
));
344 le_uint16 length
= SWAPW(nameRecord
->length
) / 2;
345 LEUnicode16
*result
= LE_NEW_ARRAY(LEUnicode16
, length
+ 2);
347 for (le_int32 c
= 0; c
< length
; c
+= 1) {
348 result
[c
] = SWAPW(name
[c
]);
360 void PortableFontInstance::deleteNameString(const char *name
) const
362 LE_DELETE_ARRAY(name
);
365 void PortableFontInstance::deleteNameString(const LEUnicode16
*name
) const
367 LE_DELETE_ARRAY(name
);
370 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph
, LEPoint
&advance
) const
372 TTGlyphID ttGlyph
= (TTGlyphID
) LE_GET_GLYPH(glyph
);
374 if (fHMTXTable
== NULL
) {
375 LETag maxpTag
= LE_MAXP_TABLE_TAG
;
376 LETag hmtxTag
= LE_HMTX_TABLE_TAG
;
377 const MAXPTable
*maxpTable
= (MAXPTable
*) readFontTable(maxpTag
);
378 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
380 if (maxpTable
!= NULL
) {
381 realThis
->fNumGlyphs
= SWAPW(maxpTable
->numGlyphs
);
382 freeFontTable(maxpTable
);
385 realThis
->fHMTXTable
= (const HMTXTable
*) readFontTable(hmtxTag
);
388 le_uint16 index
= ttGlyph
;
390 if (ttGlyph
>= fNumGlyphs
|| fHMTXTable
== NULL
) {
391 advance
.fX
= advance
.fY
= 0;
395 if (ttGlyph
>= fNumLongHorMetrics
) {
396 index
= fNumLongHorMetrics
- 1;
399 advance
.fX
= xUnitsToPoints(SWAPW(fHMTXTable
->hMetrics
[index
].advanceWidth
));
403 le_bool
PortableFontInstance::getGlyphPoint(LEGlyphID
/*glyph*/, le_int32
/*pointNumber*/, LEPoint
&/*point*/) const
408 le_int32
PortableFontInstance::getUnitsPerEM() const
413 le_uint32
PortableFontInstance::getFontChecksum() const
415 return fFontChecksum
;
418 le_uint32
PortableFontInstance::getRawChecksum() const
421 // fseek(fFile, 0L, SEEK_END);
422 // long size = ftell(fFile);
425 fseek(fFile
, 0L, SEEK_SET
);
428 while((r
= fgetc(fFile
)) != EOF
) {
432 return (le_uint32
) chksum
; // cast to signed
435 le_int32
PortableFontInstance::getAscent() const
440 le_int32
PortableFontInstance::getDescent() const
445 le_int32
PortableFontInstance::getLeading() const
450 // We really want to inherit this method from the superclass, but some compilers
451 // issue a warning if we don't implement it...
452 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
, le_bool filterZeroWidth
) const
454 return LEFontInstance::mapCharToGlyph(ch
, mapper
, filterZeroWidth
);
457 // We really want to inherit this method from the superclass, but some compilers
458 // issue a warning if we don't implement it...
459 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
) const
461 return LEFontInstance::mapCharToGlyph(ch
, mapper
);
464 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
) const
466 return fCMAPMapper
->unicodeToGlyph(ch
);
469 float PortableFontInstance::getXPixelsPerEm() const
474 float PortableFontInstance::getYPixelsPerEm() const
479 float PortableFontInstance::getScaleFactorX() const
484 float PortableFontInstance::getScaleFactorY() const