2 *******************************************************************************
4 * Copyright (C) 1999-2013, 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 fread(&tempDir
, sizeof tempDir
, 1, fFile
);
102 le_int32 dirSize
= sizeof tempDir
+ ((SWAPW(tempDir
.numTables
) - ANY_NUMBER
) * sizeof(DirectoryEntry
));
103 const LETag headTag
= LE_HEAD_TABLE_TAG
;
104 const LETag hheaTag
= LE_HHEA_TABLE_TAG
;
105 const HEADTable
*headTable
= NULL
;
106 const HHEATable
*hheaTable
= NULL
;
107 // const NAMETable *nameTable = NULL;
108 le_uint16 numTables
= 0;
110 fDirectory
= (const SFNTDirectory
*) LE_NEW_ARRAY(char, dirSize
);
112 if (fDirectory
== NULL
) {
113 printf("%s:%d: %s: malloc err\n", __FILE__
, __LINE__
, fileName
);
114 status
= LE_MEMORY_ALLOCATION_ERROR
;
118 fseek(fFile
, 0L, SEEK_SET
);
119 fread((void *) fDirectory
, sizeof(char), dirSize
, fFile
);
122 // We calculate these numbers 'cause some fonts
123 // have bogus values for them in the directory header.
125 numTables
= SWAPW(fDirectory
->numTables
);
126 fDirPower
= 1 << highBit(numTables
);
127 fDirExtra
= numTables
- fDirPower
;
129 // read unitsPerEm from 'head' table
130 headTable
= (const HEADTable
*) readFontTable(headTag
);
132 if (headTable
== NULL
) {
133 status
= LE_MISSING_FONT_TABLE_ERROR
;
134 printf("%s:%d: %s: missing head table\n", __FILE__
, __LINE__
, fileName
);
138 fUnitsPerEM
= SWAPW(headTable
->unitsPerEm
);
139 fFontChecksum
= SWAPL(headTable
->checksumAdjustment
);
140 freeFontTable(headTable
);
142 //nameTable = (NAMETable *) readFontTable(nameTag);
144 //if (nameTable == NULL) {
145 // status = LE_MISSING_FONT_TABLE_ERROR;
149 //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
151 //if (fFontVersionString == NULL) {
152 // status = LE_MISSING_FONT_TABLE_ERROR;
156 //freeFontTable(nameTable);
158 hheaTable
= (HHEATable
*) readFontTable(hheaTag
);
160 if (hheaTable
== NULL
) {
161 printf("%s:%d: %s: missing hhea table\n", __FILE__
, __LINE__
, fileName
);
162 status
= LE_MISSING_FONT_TABLE_ERROR
;
166 fAscent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->ascent
));
167 fDescent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->descent
));
168 fLeading
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->lineGap
));
170 fNumLongHorMetrics
= SWAPW(hheaTable
->numOfLongHorMetrics
);
172 freeFontTable((void *) hheaTable
);
174 fCMAPMapper
= findUnicodeMapper();
176 if (fCMAPMapper
== NULL
) {
177 printf("%s:%d: %s: can't load cmap\n", __FILE__
, __LINE__
, fileName
);
178 status
= LE_MISSING_FONT_TABLE_ERROR
;
190 PortableFontInstance::~PortableFontInstance()
195 freeFontTable(fHMTXTable
);
196 freeFontTable(fNAMETable
);
200 LE_DELETE_ARRAY(fDirectory
);
204 const DirectoryEntry
*PortableFontInstance::findTable(LETag tag
) const
206 if (fDirectory
!= NULL
) {
208 le_uint16 probe
= fDirPower
;
210 if (SWAPL(fDirectory
->tableDirectory
[fDirExtra
].tag
) <= tag
) {
214 while (probe
> (1 << 0)) {
217 if (SWAPL(fDirectory
->tableDirectory
[table
+ probe
].tag
) <= tag
) {
222 if (SWAPL(fDirectory
->tableDirectory
[table
].tag
) == tag
) {
223 return &fDirectory
->tableDirectory
[table
];
230 const void *PortableFontInstance::readTable(LETag tag
, le_uint32
*length
) const
232 const DirectoryEntry
*entry
= findTable(tag
);
239 *length
= SWAPL(entry
->length
);
241 void *table
= LE_NEW_ARRAY(char, *length
);
244 fseek(fFile
, SWAPL(entry
->offset
), SEEK_SET
);
245 fread(table
, sizeof(char), *length
, fFile
);
251 const void *PortableFontInstance::getFontTable(LETag tableTag
) const
254 return getFontTable(tableTag
, ignored
);
257 const void *PortableFontInstance::getFontTable(LETag tableTag
, size_t &length
) const
259 return FontTableCache::find(tableTag
, length
);
262 const void *PortableFontInstance::readFontTable(LETag tableTag
, size_t &length
) const
266 const void *data
= readTable(tableTag
, &len
);
269 //printf("Read %s, result %p #%d\n", letagToStr(tableTag,tag5), data,len);
273 CMAPMapper
*PortableFontInstance::findUnicodeMapper()
275 LETag cmapTag
= LE_CMAP_TABLE_TAG
;
276 const CMAPTable
*cmap
= (CMAPTable
*) readFontTable(cmapTag
);
282 return CMAPMapper::createUnicodeMapper(cmap
);
285 const char *PortableFontInstance::getNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
287 if (fNAMETable
== NULL
) {
288 LETag nameTag
= LE_NAME_TABLE_TAG
;
289 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
291 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
293 if (realThis
->fNAMETable
!= NULL
) {
294 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
295 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
299 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
300 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
302 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
) == encodingID
&&
303 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
304 char *name
= ((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
);
305 le_uint16 length
= SWAPW(nameRecord
->length
);
306 char *result
= LE_NEW_ARRAY(char, length
+ 2);
308 LE_ARRAY_COPY(result
, name
, length
);
309 result
[length
] = result
[length
+ 1] = 0;
318 const LEUnicode16
*PortableFontInstance::getUnicodeNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
320 if (fNAMETable
== NULL
) {
321 LETag nameTag
= LE_NAME_TABLE_TAG
;
322 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
324 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
326 if (realThis
->fNAMETable
!= NULL
) {
327 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
328 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
332 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
333 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
335 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
) == encodingID
&&
336 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
337 LEUnicode16
*name
= (LEUnicode16
*) (((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
));
338 le_uint16 length
= SWAPW(nameRecord
->length
) / 2;
339 LEUnicode16
*result
= LE_NEW_ARRAY(LEUnicode16
, length
+ 2);
341 for (le_int32 c
= 0; c
< length
; c
+= 1) {
342 result
[c
] = SWAPW(name
[c
]);
354 void PortableFontInstance::deleteNameString(const char *name
) const
356 LE_DELETE_ARRAY(name
);
359 void PortableFontInstance::deleteNameString(const LEUnicode16
*name
) const
361 LE_DELETE_ARRAY(name
);
364 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph
, LEPoint
&advance
) const
366 TTGlyphID ttGlyph
= (TTGlyphID
) LE_GET_GLYPH(glyph
);
368 if (fHMTXTable
== NULL
) {
369 LETag maxpTag
= LE_MAXP_TABLE_TAG
;
370 LETag hmtxTag
= LE_HMTX_TABLE_TAG
;
371 const MAXPTable
*maxpTable
= (MAXPTable
*) readFontTable(maxpTag
);
372 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
374 if (maxpTable
!= NULL
) {
375 realThis
->fNumGlyphs
= SWAPW(maxpTable
->numGlyphs
);
376 freeFontTable(maxpTable
);
379 realThis
->fHMTXTable
= (const HMTXTable
*) readFontTable(hmtxTag
);
382 le_uint16 index
= ttGlyph
;
384 if (ttGlyph
>= fNumGlyphs
|| fHMTXTable
== NULL
) {
385 advance
.fX
= advance
.fY
= 0;
389 if (ttGlyph
>= fNumLongHorMetrics
) {
390 index
= fNumLongHorMetrics
- 1;
393 advance
.fX
= xUnitsToPoints(SWAPW(fHMTXTable
->hMetrics
[index
].advanceWidth
));
397 le_bool
PortableFontInstance::getGlyphPoint(LEGlyphID
/*glyph*/, le_int32
/*pointNumber*/, LEPoint
&/*point*/) const
402 le_int32
PortableFontInstance::getUnitsPerEM() const
407 le_uint32
PortableFontInstance::getFontChecksum() const
409 return fFontChecksum
;
412 le_uint32
PortableFontInstance::getRawChecksum() const
415 // fseek(fFile, 0L, SEEK_END);
416 // long size = ftell(fFile);
419 fseek(fFile
, 0L, SEEK_SET
);
422 while((r
= fgetc(fFile
)) != EOF
) {
426 return (le_uint32
) chksum
; // cast to signed
429 le_int32
PortableFontInstance::getAscent() const
434 le_int32
PortableFontInstance::getDescent() const
439 le_int32
PortableFontInstance::getLeading() const
444 // We really want to inherit this method from the superclass, but some compilers
445 // issue a warning if we don't implement it...
446 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
, le_bool filterZeroWidth
) const
448 return LEFontInstance::mapCharToGlyph(ch
, mapper
, filterZeroWidth
);
451 // We really want to inherit this method from the superclass, but some compilers
452 // issue a warning if we don't implement it...
453 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
) const
455 return LEFontInstance::mapCharToGlyph(ch
, mapper
);
458 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
) const
460 return fCMAPMapper
->unicodeToGlyph(ch
);
463 float PortableFontInstance::getXPixelsPerEm() const
468 float PortableFontInstance::getYPixelsPerEm() const
473 float PortableFontInstance::getScaleFactorX() const
478 float PortableFontInstance::getScaleFactorY() const