2 *******************************************************************************
4 * Copyright (C) 1999-2008, 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 freeFontTable(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 //freeFontTable(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 freeFontTable((void *) hheaTable
);
157 fCMAPMapper
= findUnicodeMapper();
159 if (fCMAPMapper
== NULL
) {
160 status
= LE_MISSING_FONT_TABLE_ERROR
;
172 PortableFontInstance::~PortableFontInstance()
177 freeFontTable(fHMTXTable
);
178 freeFontTable(fNAMETable
);
182 DELETE_ARRAY(fDirectory
);
186 const DirectoryEntry
*PortableFontInstance::findTable(LETag tag
) const
188 if (fDirectory
!= NULL
) {
190 le_uint16 probe
= fDirPower
;
192 if (SWAPL(fDirectory
->tableDirectory
[fDirExtra
].tag
) <= tag
) {
196 while (probe
> (1 << 0)) {
199 if (SWAPL(fDirectory
->tableDirectory
[table
+ probe
].tag
) <= tag
) {
204 if (SWAPL(fDirectory
->tableDirectory
[table
].tag
) == tag
) {
205 return &fDirectory
->tableDirectory
[table
];
212 const void *PortableFontInstance::readTable(LETag tag
, le_uint32
*length
) const
214 const DirectoryEntry
*entry
= findTable(tag
);
221 *length
= SWAPL(entry
->length
);
223 void *table
= NEW_ARRAY(char, *length
);
226 fseek(fFile
, SWAPL(entry
->offset
), SEEK_SET
);
227 fread(table
, sizeof(char), *length
, fFile
);
233 const void *PortableFontInstance::getFontTable(LETag tableTag
) const
235 return FontTableCache::find(tableTag
);
238 const void *PortableFontInstance::readFontTable(LETag tableTag
) const
242 return readTable(tableTag
, &len
);
245 CMAPMapper
*PortableFontInstance::findUnicodeMapper()
247 LETag cmapTag
= LE_CMAP_TABLE_TAG
;
248 const CMAPTable
*cmap
= (CMAPTable
*) readFontTable(cmapTag
);
254 return CMAPMapper::createUnicodeMapper(cmap
);
257 const char *PortableFontInstance::getNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
259 if (fNAMETable
== NULL
) {
260 LETag nameTag
= LE_NAME_TABLE_TAG
;
261 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
263 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
265 if (realThis
->fNAMETable
!= NULL
) {
266 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
267 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
271 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
272 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
274 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
) == encodingID
&&
275 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
276 char *name
= ((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
);
277 le_uint16 length
= SWAPW(nameRecord
->length
);
278 char *result
= NEW_ARRAY(char, length
+ 2);
280 ARRAY_COPY(result
, name
, length
);
281 result
[length
] = result
[length
+ 1] = 0;
290 const LEUnicode16
*PortableFontInstance::getUnicodeNameString(le_uint16 nameID
, le_uint16 platformID
, le_uint16 encodingID
, le_uint16 languageID
) const
292 if (fNAMETable
== NULL
) {
293 LETag nameTag
= LE_NAME_TABLE_TAG
;
294 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
296 realThis
->fNAMETable
= (const NAMETable
*) readFontTable(nameTag
);
298 if (realThis
->fNAMETable
!= NULL
) {
299 realThis
->fNameCount
= SWAPW(realThis
->fNAMETable
->count
);
300 realThis
->fNameStringOffset
= SWAPW(realThis
->fNAMETable
->stringOffset
);
304 for(le_int32 i
= 0; i
< fNameCount
; i
+= 1) {
305 const NameRecord
*nameRecord
= &fNAMETable
->nameRecords
[i
];
307 if (SWAPW(nameRecord
->platformID
) == platformID
&& SWAPW(nameRecord
->encodingID
) == encodingID
&&
308 SWAPW(nameRecord
->languageID
) == languageID
&& SWAPW(nameRecord
->nameID
) == nameID
) {
309 LEUnicode16
*name
= (LEUnicode16
*) (((char *) fNAMETable
) + fNameStringOffset
+ SWAPW(nameRecord
->offset
));
310 le_uint16 length
= SWAPW(nameRecord
->length
) / 2;
311 LEUnicode16
*result
= NEW_ARRAY(LEUnicode16
, length
+ 2);
313 for (le_int32 c
= 0; c
< length
; c
+= 1) {
314 result
[c
] = SWAPW(name
[c
]);
326 void PortableFontInstance::deleteNameString(const char *name
) const
331 void PortableFontInstance::deleteNameString(const LEUnicode16
*name
) const
336 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph
, LEPoint
&advance
) const
338 TTGlyphID ttGlyph
= (TTGlyphID
) LE_GET_GLYPH(glyph
);
340 if (fHMTXTable
== NULL
) {
341 LETag maxpTag
= LE_MAXP_TABLE_TAG
;
342 LETag hmtxTag
= LE_HMTX_TABLE_TAG
;
343 const MAXPTable
*maxpTable
= (MAXPTable
*) readFontTable(maxpTag
);
344 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
346 if (maxpTable
!= NULL
) {
347 realThis
->fNumGlyphs
= SWAPW(maxpTable
->numGlyphs
);
348 freeFontTable(maxpTable
);
351 realThis
->fHMTXTable
= (const HMTXTable
*) readFontTable(hmtxTag
);
354 le_uint16 index
= ttGlyph
;
356 if (ttGlyph
>= fNumGlyphs
|| fHMTXTable
== NULL
) {
357 advance
.fX
= advance
.fY
= 0;
361 if (ttGlyph
>= fNumLongHorMetrics
) {
362 index
= fNumLongHorMetrics
- 1;
365 advance
.fX
= xUnitsToPoints(SWAPW(fHMTXTable
->hMetrics
[index
].advanceWidth
));
369 le_bool
PortableFontInstance::getGlyphPoint(LEGlyphID
/*glyph*/, le_int32
/*pointNumber*/, LEPoint
&/*point*/) const
374 le_int32
PortableFontInstance::getUnitsPerEM() const
379 le_uint32
PortableFontInstance::getFontChecksum() const
381 return fFontChecksum
;
384 le_int32
PortableFontInstance::getAscent() const
389 le_int32
PortableFontInstance::getDescent() const
394 le_int32
PortableFontInstance::getLeading() const
399 // We really want to inherit this method from the superclass, but some compilers
400 // issue a warning if we don't implement it...
401 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
, le_bool filterZeroWidth
) const
403 return LEFontInstance::mapCharToGlyph(ch
, mapper
, filterZeroWidth
);
406 // We really want to inherit this method from the superclass, but some compilers
407 // issue a warning if we don't implement it...
408 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
, const LECharMapper
*mapper
) const
410 return LEFontInstance::mapCharToGlyph(ch
, mapper
);
413 LEGlyphID
PortableFontInstance::mapCharToGlyph(LEUnicode32 ch
) const
415 return fCMAPMapper
->unicodeToGlyph(ch
);
418 float PortableFontInstance::getXPixelsPerEm() const
423 float PortableFontInstance::getYPixelsPerEm() const
428 float PortableFontInstance::getScaleFactorX() const
433 float PortableFontInstance::getScaleFactorY() const