2 *******************************************************************************
4 * Copyright (C) 1999-2006, 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"
28 // Finds the high bit by binary searching
29 // through the bits in n.
31 le_int8
PortableFontInstance::highBit(le_int32 value
)
39 if (value
>= 1 << 16) {
44 if (value
>= 1 << 8) {
49 if (value
>= 1 << 4) {
54 if (value
>= 1 << 2) {
59 if (value
>= 1 << 1) {
67 PortableFontInstance::PortableFontInstance(const char *fileName
, float pointSize
, LEErrorCode
&status
)
68 : fFile(NULL
), fPointSize(pointSize
), fUnitsPerEM(0), fFontChecksum(0), fAscent(0), fDescent(0), fLeading(0),
69 fDirectory(NULL
), fNAMETable(NULL
), fNameCount(0), fNameStringOffset(0), fCMAPMapper(NULL
), fHMTXTable(NULL
), fNumGlyphs(0), fNumLongHorMetrics(0)
71 if (LE_FAILURE(status
)) {
76 fFile
= fopen(fileName
, "rb");
79 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
83 // read in the directory
84 SFNTDirectory tempDir
;
86 fread(&tempDir
, sizeof tempDir
, 1, fFile
);
88 le_int32 dirSize
= sizeof tempDir
+ ((SWAPW(tempDir
.numTables
) - ANY_NUMBER
) * sizeof(DirectoryEntry
));
89 const LETag headTag
= LE_HEAD_TABLE_TAG
;
90 const LETag hheaTag
= LE_HHEA_TABLE_TAG
;
91 const HEADTable
*headTable
= NULL
;
92 const HHEATable
*hheaTable
= NULL
;
93 // const NAMETable *nameTable = NULL;
94 le_uint16 numTables
= 0;
96 fDirectory
= (const SFNTDirectory
*) NEW_ARRAY(char, dirSize
);
98 if (fDirectory
== NULL
) {
99 status
= LE_MEMORY_ALLOCATION_ERROR
;
103 fseek(fFile
, 0L, SEEK_SET
);
104 fread((void *) fDirectory
, sizeof(char), dirSize
, fFile
);
107 // We calculate these numbers 'cause some fonts
108 // have bogus values for them in the directory header.
110 numTables
= SWAPW(fDirectory
->numTables
);
111 fDirPower
= 1 << highBit(numTables
);
112 fDirExtra
= numTables
- fDirPower
;
114 // read unitsPerEm from 'head' table
115 headTable
= (const HEADTable
*) readFontTable(headTag
);
117 if (headTable
== NULL
) {
118 status
= LE_MISSING_FONT_TABLE_ERROR
;
122 fUnitsPerEM
= SWAPW(headTable
->unitsPerEm
);
123 fFontChecksum
= SWAPL(headTable
->checksumAdjustment
);
124 deleteTable(headTable
);
126 //nameTable = (NAMETable *) readFontTable(nameTag);
128 //if (nameTable == NULL) {
129 // status = LE_MISSING_FONT_TABLE_ERROR;
133 //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
135 //if (fFontVersionString == NULL) {
136 // status = LE_MISSING_FONT_TABLE_ERROR;
140 //deleteTable(nameTable);
142 hheaTable
= (HHEATable
*) readFontTable(hheaTag
);
144 if (hheaTable
== NULL
) {
145 status
= LE_MISSING_FONT_TABLE_ERROR
;
149 fAscent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->ascent
));
150 fDescent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->descent
));
151 fLeading
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->lineGap
));
153 fNumLongHorMetrics
= SWAPW(hheaTable
->numOfLongHorMetrics
);
155 deleteTable((void *) hheaTable
);
157 fCMAPMapper
= findUnicodeMapper();
159 if (fCMAPMapper
== NULL
) {
160 status
= LE_MISSING_FONT_TABLE_ERROR
;
172 PortableFontInstance::~PortableFontInstance()
177 deleteTable(fHMTXTable
);
178 deleteTable(fNAMETable
);
182 DELETE_ARRAY(fDirectory
);
186 void PortableFontInstance::deleteTable(const void *table
) const
191 const DirectoryEntry
*PortableFontInstance::findTable(LETag tag
) const
193 if (fDirectory
!= NULL
) {
195 le_uint16 probe
= fDirPower
;
197 if (SWAPL(fDirectory
->tableDirectory
[fDirExtra
].tag
) <= tag
) {
201 while (probe
> (1 << 0)) {
204 if (SWAPL(fDirectory
->tableDirectory
[table
+ probe
].tag
) <= tag
) {
209 if (SWAPL(fDirectory
->tableDirectory
[table
].tag
) == tag
) {
210 return &fDirectory
->tableDirectory
[table
];
217 const void *PortableFontInstance::readTable(LETag tag
, le_uint32
*length
) const
219 const DirectoryEntry
*entry
= findTable(tag
);
226 *length
= SWAPL(entry
->length
);
228 void *table
= NEW_ARRAY(char, *length
);
231 fseek(fFile
, SWAPL(entry
->offset
), SEEK_SET
);
232 fread(table
, sizeof(char), *length
, fFile
);
238 const void *PortableFontInstance::getFontTable(LETag tableTag
) const
240 return FontTableCache::find(tableTag
);
243 const void *PortableFontInstance::readFontTable(LETag tableTag
) const
247 return readTable(tableTag
, &len
);
250 CMAPMapper
*PortableFontInstance::findUnicodeMapper()
252 LETag cmapTag
= LE_CMAP_TABLE_TAG
;
253 const CMAPTable
*cmap
= (CMAPTable
*) readFontTable(cmapTag
);
259 return CMAPMapper::createUnicodeMapper(cmap
);
262 const char *PortableFontInstance::getNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
264 if (fNAMETable
== NULL
) {
265 LETag nameTag
= LE_NAME_TABLE_TAG
;
266 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
268 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
270 if (realThis
->fNAMETable
!= NULL
) {
271 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
272 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
276 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
277 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
279 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
== encodingID
) &&
280 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
281 char *name
= ((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
);
282 le_uint16 length
= SWAPW(nameRecord
->length
);
283 char *result
= NEW_ARRAY(char, length
+ 2);
285 ARRAY_COPY(result
, name
, length
);
286 result
[length
] = result
[length
+ 1] = 0;
295 void PortableFontInstance::deleteNameString(const char *name
) const
300 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph
, LEPoint
&advance
) const
302 TTGlyphID ttGlyph
= (TTGlyphID
) LE_GET_GLYPH(glyph
);
304 if (fHMTXTable
== NULL
) {
305 LETag maxpTag
= LE_MAXP_TABLE_TAG
;
306 LETag hmtxTag
= LE_HMTX_TABLE_TAG
;
307 const MAXPTable
*maxpTable
= (MAXPTable
*) readFontTable(maxpTag
);
308 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
310 if (maxpTable
!= NULL
) {
311 realThis
->fNumGlyphs
= SWAPW(maxpTable
->numGlyphs
);
312 deleteTable(maxpTable
);
315 realThis
->fHMTXTable
= (const HMTXTable
*) readFontTable(hmtxTag
);
318 le_uint16 index
= ttGlyph
;
320 if (ttGlyph
>= fNumGlyphs
|| fHMTXTable
== NULL
) {
321 advance
.fX
= advance
.fY
= 0;
325 if (ttGlyph
>= fNumLongHorMetrics
) {
326 index
= fNumLongHorMetrics
- 1;
329 advance
.fX
= xUnitsToPoints(SWAPW(fHMTXTable
->hMetrics
[index
].advanceWidth
));
333 le_bool
PortableFontInstance::getGlyphPoint(LEGlyphID
/*glyph*/, le_int32
/*pointNumber*/, LEPoint
&/*point*/) const
338 le_int32
PortableFontInstance::getUnitsPerEM() const
343 le_uint32
PortableFontInstance::getFontChecksum() const
345 return fFontChecksum
;
348 le_int32
PortableFontInstance::getAscent() const
353 le_int32
PortableFontInstance::getDescent() const
358 le_int32
PortableFontInstance::getLeading() const
363 // We really want to inherit this method from the superclass, but some compilers
364 // issue a warning if we don't implement it...
365 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
, le_bool filterZeroWidth
) const
367 return LEFontInstance::mapCharToGlyph(ch
, mapper
, filterZeroWidth
);
370 // We really want to inherit this method from the superclass, but some compilers
371 // issue a warning if we don't implement it...
372 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
) const
374 return LEFontInstance::mapCharToGlyph(ch
, mapper
);
377 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
) const
379 return fCMAPMapper
->unicodeToGlyph(ch
);
382 float PortableFontInstance::getXPixelsPerEm() const
387 float PortableFontInstance::getYPixelsPerEm() const
392 float PortableFontInstance::getScaleFactorX() const
397 float PortableFontInstance::getScaleFactorY() const