]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/letest/PortableFontInstance.cpp
ICU-8.11.tar.gz
[apple/icu.git] / icuSources / test / letest / PortableFontInstance.cpp
1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 1999-2006, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 *******************************************************************************
8 * file name: PortableFontInstance.cpp
9 *
10 * created on: 11/22/1999
11 * created by: Eric R. Mader
12 */
13
14 #include <stdio.h>
15
16 #include "layout/LETypes.h"
17 #include "layout/LEFontInstance.h"
18 #include "layout/LESwaps.h"
19
20 #include "PortableFontInstance.h"
21
22 #include "letest.h"
23 #include "sfnt.h"
24
25 #include <string.h>
26
27 //
28 // Finds the high bit by binary searching
29 // through the bits in n.
30 //
31 le_int8 PortableFontInstance::highBit(le_int32 value)
32 {
33 if (value <= 0) {
34 return -32;
35 }
36
37 le_uint8 bit = 0;
38
39 if (value >= 1 << 16) {
40 value >>= 16;
41 bit += 16;
42 }
43
44 if (value >= 1 << 8) {
45 value >>= 8;
46 bit += 8;
47 }
48
49 if (value >= 1 << 4) {
50 value >>= 4;
51 bit += 4;
52 }
53
54 if (value >= 1 << 2) {
55 value >>= 2;
56 bit += 2;
57 }
58
59 if (value >= 1 << 1) {
60 value >>= 1;
61 bit += 1;
62 }
63
64 return bit;
65 }
66
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)
70 {
71 if (LE_FAILURE(status)) {
72 return;
73 }
74
75 // open the font file
76 fFile = fopen(fileName, "rb");
77
78 if (fFile == NULL) {
79 status = LE_FONT_FILE_NOT_FOUND_ERROR;
80 return;
81 }
82
83 // read in the directory
84 SFNTDirectory tempDir;
85
86 fread(&tempDir, sizeof tempDir, 1, fFile);
87
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;
95
96 fDirectory = (const SFNTDirectory *) NEW_ARRAY(char, dirSize);
97
98 if (fDirectory == NULL) {
99 status = LE_MEMORY_ALLOCATION_ERROR;
100 goto error_exit;
101 }
102
103 fseek(fFile, 0L, SEEK_SET);
104 fread((void *) fDirectory, sizeof(char), dirSize, fFile);
105
106 //
107 // We calculate these numbers 'cause some fonts
108 // have bogus values for them in the directory header.
109 //
110 numTables = SWAPW(fDirectory->numTables);
111 fDirPower = 1 << highBit(numTables);
112 fDirExtra = numTables - fDirPower;
113
114 // read unitsPerEm from 'head' table
115 headTable = (const HEADTable *) readFontTable(headTag);
116
117 if (headTable == NULL) {
118 status = LE_MISSING_FONT_TABLE_ERROR;
119 goto error_exit;
120 }
121
122 fUnitsPerEM = SWAPW(headTable->unitsPerEm);
123 fFontChecksum = SWAPL(headTable->checksumAdjustment);
124 deleteTable(headTable);
125
126 //nameTable = (NAMETable *) readFontTable(nameTag);
127
128 //if (nameTable == NULL) {
129 // status = LE_MISSING_FONT_TABLE_ERROR;
130 // goto error_exit;
131 //}
132
133 //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
134
135 //if (fFontVersionString == NULL) {
136 // status = LE_MISSING_FONT_TABLE_ERROR;
137 // goto error_exit;
138 //}
139
140 //deleteTable(nameTable);
141
142 hheaTable = (HHEATable *) readFontTable(hheaTag);
143
144 if (hheaTable == NULL) {
145 status = LE_MISSING_FONT_TABLE_ERROR;
146 goto error_exit;
147 }
148
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));
152
153 fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
154
155 deleteTable((void *) hheaTable);
156
157 fCMAPMapper = findUnicodeMapper();
158
159 if (fCMAPMapper == NULL) {
160 status = LE_MISSING_FONT_TABLE_ERROR;
161 goto error_exit;
162 }
163
164 return;
165
166 error_exit:
167 fclose(fFile);
168 fFile = NULL;
169 return;
170 }
171
172 PortableFontInstance::~PortableFontInstance()
173 {
174 if (fFile != NULL) {
175 fclose(fFile);
176
177 deleteTable(fHMTXTable);
178 deleteTable(fNAMETable);
179
180 delete fCMAPMapper;
181
182 DELETE_ARRAY(fDirectory);
183 }
184 }
185
186 void PortableFontInstance::deleteTable(const void *table) const
187 {
188 DELETE_ARRAY(table);
189 }
190
191 const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const
192 {
193 if (fDirectory != NULL) {
194 le_uint16 table = 0;
195 le_uint16 probe = fDirPower;
196
197 if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) {
198 table = fDirExtra;
199 }
200
201 while (probe > (1 << 0)) {
202 probe >>= 1;
203
204 if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) {
205 table += probe;
206 }
207 }
208
209 if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) {
210 return &fDirectory->tableDirectory[table];
211 }
212 }
213
214 return NULL;
215 }
216
217 const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const
218 {
219 const DirectoryEntry *entry = findTable(tag);
220
221 if (entry == NULL) {
222 *length = 0;
223 return NULL;
224 }
225
226 *length = SWAPL(entry->length);
227
228 void *table = NEW_ARRAY(char, *length);
229
230 if (table != NULL) {
231 fseek(fFile, SWAPL(entry->offset), SEEK_SET);
232 fread(table, sizeof(char), *length, fFile);
233 }
234
235 return table;
236 }
237
238 const void *PortableFontInstance::getFontTable(LETag tableTag) const
239 {
240 return FontTableCache::find(tableTag);
241 }
242
243 const void *PortableFontInstance::readFontTable(LETag tableTag) const
244 {
245 le_uint32 len;
246
247 return readTable(tableTag, &len);
248 }
249
250 CMAPMapper *PortableFontInstance::findUnicodeMapper()
251 {
252 LETag cmapTag = LE_CMAP_TABLE_TAG;
253 const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag);
254
255 if (cmap == NULL) {
256 return NULL;
257 }
258
259 return CMAPMapper::createUnicodeMapper(cmap);
260 }
261
262 const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const
263 {
264 if (fNAMETable == NULL) {
265 LETag nameTag = LE_NAME_TABLE_TAG;
266 PortableFontInstance *realThis = (PortableFontInstance *) this;
267
268 realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag);
269
270 if (realThis->fNAMETable != NULL) {
271 realThis->fNameCount = SWAPW(realThis->fNAMETable->count);
272 realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset);
273 }
274 }
275
276 for(le_int32 i = 0; i < fNameCount; i += 1) {
277 const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
278
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);
284
285 ARRAY_COPY(result, name, length);
286 result[length] = result[length + 1] = 0;
287
288 return result;
289 }
290 }
291
292 return NULL;
293 }
294
295 void PortableFontInstance::deleteNameString(const char *name) const
296 {
297 DELETE_ARRAY(name);
298 }
299
300 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
301 {
302 TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
303
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;
309
310 if (maxpTable != NULL) {
311 realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs);
312 deleteTable(maxpTable);
313 }
314
315 realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag);
316 }
317
318 le_uint16 index = ttGlyph;
319
320 if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) {
321 advance.fX = advance.fY = 0;
322 return;
323 }
324
325 if (ttGlyph >= fNumLongHorMetrics) {
326 index = fNumLongHorMetrics - 1;
327 }
328
329 advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth));
330 advance.fY = 0;
331 }
332
333 le_bool PortableFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*pointNumber*/, LEPoint &/*point*/) const
334 {
335 return FALSE;
336 }
337
338 le_int32 PortableFontInstance::getUnitsPerEM() const
339 {
340 return fUnitsPerEM;
341 }
342
343 le_uint32 PortableFontInstance::getFontChecksum() const
344 {
345 return fFontChecksum;
346 }
347
348 le_int32 PortableFontInstance::getAscent() const
349 {
350 return fAscent;
351 }
352
353 le_int32 PortableFontInstance::getDescent() const
354 {
355 return fDescent;
356 }
357
358 le_int32 PortableFontInstance::getLeading() const
359 {
360 return fLeading;
361 }
362
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
366 {
367 return LEFontInstance::mapCharToGlyph(ch, mapper, filterZeroWidth);
368 }
369
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
373 {
374 return LEFontInstance::mapCharToGlyph(ch, mapper);
375 }
376
377 LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const
378 {
379 return fCMAPMapper->unicodeToGlyph(ch);
380 }
381
382 float PortableFontInstance::getXPixelsPerEm() const
383 {
384 return fPointSize;
385 }
386
387 float PortableFontInstance::getYPixelsPerEm() const
388 {
389 return fPointSize;
390 }
391
392 float PortableFontInstance::getScaleFactorX() const
393 {
394 return 1.0;
395 }
396
397 float PortableFontInstance::getScaleFactorY() const
398 {
399 return 1.0;
400 }