2 *******************************************************************************
4 * Copyright (C) 1999-2003, 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"
27 // Finds the high bit by binary searching
28 // through the bits in n.
30 le_int8
PortableFontInstance::highBit(le_int32 value
)
38 if (value
>= 1 << 16) {
43 if (value
>= 1 << 8) {
48 if (value
>= 1 << 4) {
53 if (value
>= 1 << 2) {
58 if (value
>= 1 << 1) {
67 PortableFontInstance::PortableFontInstance(char *fileName
, float pointSize
, LEErrorCode
&status
)
68 : fFile(NULL
), fUnitsPerEM(0), fPointSize(pointSize
), fAscent(0), fDescent(0), fLeading(0),
69 fDirectory(NULL
), 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 le_uint16 numTables
= 0;
95 fDirectory
= (const SFNTDirectory
*) LE_NEW_ARRAY(char, dirSize
);
97 if (fDirectory
== NULL
) {
98 status
= LE_MEMORY_ALLOCATION_ERROR
;
102 fseek(fFile
, 0L, SEEK_SET
);
103 fread((void *) fDirectory
, sizeof(char), dirSize
, fFile
);
106 // We calculate these numbers 'cause some fonts
107 // have bogus values for them in the directory header.
109 numTables
= SWAPW(fDirectory
->numTables
);
110 fDirPower
= 1 << highBit(numTables
);
111 fDirExtra
= numTables
- fDirPower
;
113 // read unitsPerEm from 'head' table
114 headTable
= (const HEADTable
*) readFontTable(headTag
);
116 if (headTable
== NULL
) {
117 status
= LE_MISSING_FONT_TABLE_ERROR
;
121 fUnitsPerEM
= SWAPW(headTable
->unitsPerEm
);
122 deleteTable(headTable
);
124 hheaTable
= (HHEATable
*) readFontTable(hheaTag
);
126 if (hheaTable
== NULL
) {
127 status
= LE_MISSING_FONT_TABLE_ERROR
;
131 fAscent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->ascent
));
132 fDescent
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->descent
));
133 fLeading
= (le_int32
) yUnitsToPoints((float) SWAPW(hheaTable
->lineGap
));
135 fNumLongHorMetrics
= SWAPW(hheaTable
->numOfLongHorMetrics
);
137 deleteTable((void *) hheaTable
);
139 fCMAPMapper
= findUnicodeMapper();
141 if (fCMAPMapper
== NULL
) {
142 status
= LE_MISSING_FONT_TABLE_ERROR
;
154 PortableFontInstance::~PortableFontInstance()
159 deleteTable(fHMTXTable
);
163 LE_DELETE_ARRAY(fDirectory
);
167 void PortableFontInstance::deleteTable(const void *table
) const
169 LE_DELETE_ARRAY(table
);
172 const DirectoryEntry
*PortableFontInstance::findTable(LETag tag
) const
174 if (fDirectory
!= NULL
) {
176 le_uint16 probe
= fDirPower
;
178 if (SWAPL(fDirectory
->tableDirectory
[fDirExtra
].tag
) <= tag
) {
182 while (probe
> (1 << 0)) {
185 if (SWAPL(fDirectory
->tableDirectory
[table
+ probe
].tag
) <= tag
) {
190 if (SWAPL(fDirectory
->tableDirectory
[table
].tag
) == tag
) {
191 return &fDirectory
->tableDirectory
[table
];
198 const void *PortableFontInstance::readTable(LETag tag
, le_uint32
*length
) const
200 const DirectoryEntry
*entry
= findTable(tag
);
207 *length
= SWAPL(entry
->length
);
209 void *table
= LE_NEW_ARRAY(char, *length
);
212 fseek(fFile
, SWAPL(entry
->offset
), SEEK_SET
);
213 fread(table
, sizeof(char), *length
, fFile
);
219 const void *PortableFontInstance::getFontTable(LETag tableTag
) const
221 return FontTableCache::find(tableTag
);
224 const void *PortableFontInstance::readFontTable(LETag tableTag
) const
228 return readTable(tableTag
, &len
);
231 CMAPMapper
*PortableFontInstance::findUnicodeMapper()
233 LETag cmapTag
= LE_CMAP_TABLE_TAG
;
234 const CMAPTable
*cmap
= (CMAPTable
*) readFontTable(cmapTag
);
240 return CMAPMapper::createUnicodeMapper(cmap
);
244 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph
, LEPoint
&advance
) const
246 TTGlyphID ttGlyph
= (TTGlyphID
) LE_GET_GLYPH(glyph
);
248 if (fHMTXTable
== NULL
) {
249 LETag maxpTag
= LE_MAXP_TABLE_TAG
;
250 LETag hmtxTag
= LE_HMTX_TABLE_TAG
;
251 const MAXPTable
*maxpTable
= (MAXPTable
*) readFontTable(maxpTag
);
252 PortableFontInstance
*realThis
= (PortableFontInstance
*) this;
254 if (maxpTable
!= NULL
) {
255 realThis
->fNumGlyphs
= SWAPW(maxpTable
->numGlyphs
);
256 deleteTable(maxpTable
);
259 realThis
->fHMTXTable
= (const HMTXTable
*) readFontTable(hmtxTag
);
262 le_uint16 index
= ttGlyph
;
264 if (ttGlyph
>= fNumGlyphs
|| fHMTXTable
== NULL
) {
265 advance
.fX
= advance
.fY
= 0;
269 if (ttGlyph
>= fNumLongHorMetrics
) {
270 index
= fNumLongHorMetrics
- 1;
273 advance
.fX
= xUnitsToPoints(SWAPW(fHMTXTable
->hMetrics
[index
].advanceWidth
));
277 le_bool
PortableFontInstance::getGlyphPoint(LEGlyphID glyph
, le_int32 pointNumber
, LEPoint
&point
) const