2 *******************************************************************************
4 * Copyright (C) 1999-2015, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: PortableFontInstance.cpp
10 * created on: 11/22/1999
11 * created by: Eric R. Mader
16 #include "layout/LETypes.h"
17 #include "layout/LEFontInstance.h"
18 #include "layout/LESwaps.h"
20 #include "PortableFontInstance.h"
29 static const char *letagToStr(LETag tag
, char *str
) {
30 str
[0]= 0xFF & (tag
>>24);
31 str
[1]= 0xFF & (tag
>>16);
32 str
[2]= 0xFF & (tag
>>8);
33 str
[3]= 0xFF & (tag
>>0);
40 // Finds the high bit by binary searching
41 // through the bits in n.
43 le_int8
PortableFontInstance::highBit(le_int32 value
)
51 if (value
>= 1 << 16) {
56 if (value
>= 1 << 8) {
61 if (value
>= 1 << 4) {
66 if (value
>= 1 << 2) {
71 if (value
>= 1 << 1) {
79 PortableFontInstance::PortableFontInstance(const char *fileName
, float pointSize
, LEErrorCode
&status
)
80 : fFile(NULL
), fPointSize(pointSize
), fUnitsPerEM(0), fFontChecksum(0), fAscent(0), fDescent(0), fLeading(0),
81 fDirectory(NULL
), fNAMETable(NULL
), fNameCount(0), fNameStringOffset(0), fCMAPMapper(NULL
), fHMTXTable(NULL
), fNumGlyphs(0), fNumLongHorMetrics(0)
83 if (LE_FAILURE(status
)) {
88 fFile
= fopen(fileName
, "rb");
89 //printf("Open Font: %s\n", fileName);
92 printf("%s:%d: %s: FNF\n", __FILE__
, __LINE__
, fileName
);
93 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
97 // read in the directory
98 SFNTDirectory tempDir
;
100 size_t numRead
= fread(&tempDir
, sizeof tempDir
, 1, fFile
);
103 le_int32 dirSize
= sizeof tempDir
+ ((SWAPW(tempDir
.numTables
) - ANY_NUMBER
) * sizeof(DirectoryEntry
));
104 const LETag headTag
= LE_HEAD_TABLE_TAG
;
105 const LETag hheaTag
= LE_HHEA_TABLE_TAG
;
106 const HEADTable
*headTable
= NULL
;
107 const HHEATable
*hheaTable
= NULL
;
108 // const NAMETable *nameTable = NULL;
109 le_uint16 numTables
= 0;
111 fDirectory
= (const SFNTDirectory
*) LE_NEW_ARRAY(char, dirSize
);
113 if (fDirectory
== NULL
) {
114 printf("%s:%d: %s: malloc err\n", __FILE__
, __LINE__
, fileName
);
115 status
= LE_MEMORY_ALLOCATION_ERROR
;
119 fseek(fFile
, 0L, SEEK_SET
);
120 numRead
= fread((void *) fDirectory
, sizeof(char), dirSize
, fFile
);
123 // We calculate these numbers 'cause some fonts
124 // have bogus values for them in the directory header.
126 numTables
= SWAPW(fDirectory
->numTables
);
127 fDirPower
= 1 << highBit(numTables
);
128 fDirExtra
= numTables
- fDirPower
;
130 // read unitsPerEm from 'head' table
131 headTable
= (const HEADTable
*) readFontTable(headTag
);
133 if (headTable
== NULL
) {
134 status
= LE_MISSING_FONT_TABLE_ERROR
;
135 printf("%s:%d: %s: missing head table\n", __FILE__
, __LINE__
, fileName
);
139 fUnitsPerEM
= SWAPW(headTable
->unitsPerEm
);
140 fFontChecksum
= SWAPL(headTable
->checksumAdjustment
);
141 freeFontTable(headTable
);
143 //nameTable = (NAMETable *) readFontTable(nameTag);
145 //if (nameTable == NULL) {
146 // status = LE_MISSING_FONT_TABLE_ERROR;
150 //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
152 //if (fFontVersionString == NULL) {
153 // status = LE_MISSING_FONT_TABLE_ERROR;
157 //freeFontTable(nameTable);
159 hheaTable
= (HHEATable
*) readFontTable(hheaTag
);
161 if (hheaTable
== NULL
) {
162 printf("%s:%d: %s: missing hhea table\n", __FILE__
, __LINE__
, fileName
);
163 status
= LE_MISSING_FONT_TABLE_ERROR
;
167 fAscent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->ascent
));
168 fDescent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->descent
));
169 fLeading
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->lineGap
));
171 fNumLongHorMetrics
= SWAPW(hheaTable
->numOfLongHorMetrics
);
173 freeFontTable((void *) hheaTable
);
175 fCMAPMapper
= findUnicodeMapper();
177 if (fCMAPMapper
== NULL
) {
178 printf("%s:%d: %s: can't load cmap\n", __FILE__
, __LINE__
, fileName
);
179 status
= LE_MISSING_FONT_TABLE_ERROR
;
191 PortableFontInstance::~PortableFontInstance()
196 freeFontTable(fHMTXTable
);
197 freeFontTable(fNAMETable
);
201 LE_DELETE_ARRAY(fDirectory
);
205 const DirectoryEntry
*PortableFontInstance::findTable(LETag tag
) const
207 if (fDirectory
!= NULL
) {
209 le_uint16 probe
= fDirPower
;
211 if (SWAPL(fDirectory
->tableDirectory
[fDirExtra
].tag
) <= tag
) {
215 while (probe
> (1 << 0)) {
218 if (SWAPL(fDirectory
->tableDirectory
[table
+ probe
].tag
) <= tag
) {
223 if (SWAPL(fDirectory
->tableDirectory
[table
].tag
) == tag
) {
224 return &fDirectory
->tableDirectory
[table
];
231 const void *PortableFontInstance::readTable(LETag tag
, le_uint32
*length
) const
233 const DirectoryEntry
*entry
= findTable(tag
);
240 *length
= SWAPL(entry
->length
);
242 void *table
= LE_NEW_ARRAY(char, *length
);
245 fseek(fFile
, SWAPL(entry
->offset
), SEEK_SET
);
246 size_t numRead
= fread(table
, sizeof(char), *length
, fFile
);
253 const void *PortableFontInstance::getFontTable(LETag tableTag
, size_t &length
) const
255 return FontTableCache::find(tableTag
, length
);
258 const void *PortableFontInstance::readFontTable(LETag tableTag
, size_t &length
) const
262 const void *data
= readTable(tableTag
, &len
);
265 //printf("Read %s, result %p #%d\n", letagToStr(tableTag,tag5), data,len);
269 CMAPMapper
*PortableFontInstance::findUnicodeMapper()
271 LETag cmapTag
= LE_CMAP_TABLE_TAG
;
272 const CMAPTable
*cmap
= (CMAPTable
*) readFontTable(cmapTag
);
278 return CMAPMapper::createUnicodeMapper(cmap
);
281 const char *PortableFontInstance::getNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
283 if (fNAMETable
== NULL
) {
284 LETag nameTag
= LE_NAME_TABLE_TAG
;
285 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
287 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
289 if (realThis
->fNAMETable
!= NULL
) {
290 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
291 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
295 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
296 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
298 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
) == encodingID
&&
299 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
300 char *name
= ((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
);
301 le_uint16 length
= SWAPW(nameRecord
->length
);
302 char *result
= LE_NEW_ARRAY(char, length
+ 2);
304 LE_ARRAY_COPY(result
, name
, length
);
305 result
[length
] = result
[length
+ 1] = 0;
314 const LEUnicode16
*PortableFontInstance::getUnicodeNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
316 if (fNAMETable
== NULL
) {
317 LETag nameTag
= LE_NAME_TABLE_TAG
;
318 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
320 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
322 if (realThis
->fNAMETable
!= NULL
) {
323 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
324 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
328 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
329 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
331 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
) == encodingID
&&
332 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
333 LEUnicode16
*name
= (LEUnicode16
*) (((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
));
334 le_uint16 length
= SWAPW(nameRecord
->length
) / 2;
335 LEUnicode16
*result
= LE_NEW_ARRAY(LEUnicode16
, length
+ 2);
337 for (le_int32 c
= 0; c
< length
; c
+= 1) {
338 result
[c
] = SWAPW(name
[c
]);
350 void PortableFontInstance::deleteNameString(const char *name
) const
352 LE_DELETE_ARRAY(name
);
355 void PortableFontInstance::deleteNameString(const LEUnicode16
*name
) const
357 LE_DELETE_ARRAY(name
);
360 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph
, LEPoint
&advance
) const
362 TTGlyphID ttGlyph
= (TTGlyphID
) LE_GET_GLYPH(glyph
);
364 if (fHMTXTable
== NULL
) {
365 LETag maxpTag
= LE_MAXP_TABLE_TAG
;
366 LETag hmtxTag
= LE_HMTX_TABLE_TAG
;
367 const MAXPTable
*maxpTable
= (MAXPTable
*) readFontTable(maxpTag
);
368 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
370 if (maxpTable
!= NULL
) {
371 realThis
->fNumGlyphs
= SWAPW(maxpTable
->numGlyphs
);
372 freeFontTable(maxpTable
);
375 realThis
->fHMTXTable
= (const HMTXTable
*) readFontTable(hmtxTag
);
378 le_uint16 index
= ttGlyph
;
380 if (ttGlyph
>= fNumGlyphs
|| fHMTXTable
== NULL
) {
381 advance
.fX
= advance
.fY
= 0;
385 if (ttGlyph
>= fNumLongHorMetrics
) {
386 index
= fNumLongHorMetrics
- 1;
389 advance
.fX
= xUnitsToPoints(SWAPW(fHMTXTable
->hMetrics
[index
].advanceWidth
));
393 le_bool
PortableFontInstance::getGlyphPoint(LEGlyphID
/*glyph*/, le_int32
/*pointNumber*/, LEPoint
&/*point*/) const
398 le_int32
PortableFontInstance::getUnitsPerEM() const
403 le_uint32
PortableFontInstance::getFontChecksum() const
405 return fFontChecksum
;
408 le_uint32
PortableFontInstance::getRawChecksum() const
411 // fseek(fFile, 0L, SEEK_END);
412 // long size = ftell(fFile);
415 fseek(fFile
, 0L, SEEK_SET
);
418 while((r
= fgetc(fFile
)) != EOF
) {
422 return (le_uint32
) chksum
; // cast to signed
425 le_int32
PortableFontInstance::getAscent() const
430 le_int32
PortableFontInstance::getDescent() const
435 le_int32
PortableFontInstance::getLeading() const
440 // We really want to inherit this method from the superclass, but some compilers
441 // issue a warning if we don't implement it...
442 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
, le_bool filterZeroWidth
) const
444 return LEFontInstance::mapCharToGlyph(ch
, mapper
, filterZeroWidth
);
447 // We really want to inherit this method from the superclass, but some compilers
448 // issue a warning if we don't implement it...
449 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
) const
451 return LEFontInstance::mapCharToGlyph(ch
, mapper
);
454 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
) const
456 return fCMAPMapper
->unicodeToGlyph(ch
);
459 float PortableFontInstance::getXPixelsPerEm() const
464 float PortableFontInstance::getYPixelsPerEm() const
469 float PortableFontInstance::getScaleFactorX() const
474 float PortableFontInstance::getScaleFactorY() const