OLD | NEW |
| (Empty) |
1 /* | |
2 ******************************************************************************* | |
3 * | |
4 * Copyright (C) 1999-2013, 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 #include <stdio.h> | |
27 | |
28 #if 0 | |
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); | |
34 str[4]= 0; | |
35 return str; | |
36 } | |
37 #endif | |
38 | |
39 // | |
40 // Finds the high bit by binary searching | |
41 // through the bits in n. | |
42 // | |
43 le_int8 PortableFontInstance::highBit(le_int32 value) | |
44 { | |
45 if (value <= 0) { | |
46 return -32; | |
47 } | |
48 | |
49 le_uint8 bit = 0; | |
50 | |
51 if (value >= 1 << 16) { | |
52 value >>= 16; | |
53 bit += 16; | |
54 } | |
55 | |
56 if (value >= 1 << 8) { | |
57 value >>= 8; | |
58 bit += 8; | |
59 } | |
60 | |
61 if (value >= 1 << 4) { | |
62 value >>= 4; | |
63 bit += 4; | |
64 } | |
65 | |
66 if (value >= 1 << 2) { | |
67 value >>= 2; | |
68 bit += 2; | |
69 } | |
70 | |
71 if (value >= 1 << 1) { | |
72 value >>= 1; | |
73 bit += 1; | |
74 } | |
75 | |
76 return bit; | |
77 } | |
78 | |
79 PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize
, LEErrorCode &status) | |
80 : fFile(NULL), fPointSize(pointSize), fUnitsPerEM(0), fFontChecksum(0), fAsc
ent(0), fDescent(0), fLeading(0), | |
81 fDirectory(NULL), fNAMETable(NULL), fNameCount(0), fNameStringOffset(0), f
CMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0) | |
82 { | |
83 if (LE_FAILURE(status)) { | |
84 return; | |
85 } | |
86 | |
87 // open the font file | |
88 fFile = fopen(fileName, "rb"); | |
89 //printf("Open Font: %s\n", fileName); | |
90 | |
91 if (fFile == NULL) { | |
92 printf("%s:%d: %s: FNF\n", __FILE__, __LINE__, fileName); | |
93 status = LE_FONT_FILE_NOT_FOUND_ERROR; | |
94 return; | |
95 } | |
96 | |
97 // read in the directory | |
98 SFNTDirectory tempDir; | |
99 | |
100 fread(&tempDir, sizeof tempDir, 1, fFile); | |
101 | |
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; | |
109 | |
110 fDirectory = (const SFNTDirectory *) LE_NEW_ARRAY(char, dirSize); | |
111 | |
112 if (fDirectory == NULL) { | |
113 printf("%s:%d: %s: malloc err\n", __FILE__, __LINE__, fileName); | |
114 status = LE_MEMORY_ALLOCATION_ERROR; | |
115 goto error_exit; | |
116 } | |
117 | |
118 fseek(fFile, 0L, SEEK_SET); | |
119 fread((void *) fDirectory, sizeof(char), dirSize, fFile); | |
120 | |
121 // | |
122 // We calculate these numbers 'cause some fonts | |
123 // have bogus values for them in the directory header. | |
124 // | |
125 numTables = SWAPW(fDirectory->numTables); | |
126 fDirPower = 1 << highBit(numTables); | |
127 fDirExtra = numTables - fDirPower; | |
128 | |
129 // read unitsPerEm from 'head' table | |
130 headTable = (const HEADTable *) readFontTable(headTag); | |
131 | |
132 if (headTable == NULL) { | |
133 status = LE_MISSING_FONT_TABLE_ERROR; | |
134 printf("%s:%d: %s: missing head table\n", __FILE__, __LINE__, fileName); | |
135 goto error_exit; | |
136 } | |
137 | |
138 fUnitsPerEM = SWAPW(headTable->unitsPerEm); | |
139 fFontChecksum = SWAPL(headTable->checksumAdjustment); | |
140 freeFontTable(headTable); | |
141 | |
142 //nameTable = (NAMETable *) readFontTable(nameTag); | |
143 | |
144 //if (nameTable == NULL) { | |
145 // status = LE_MISSING_FONT_TABLE_ERROR; | |
146 // goto error_exit; | |
147 //} | |
148 | |
149 //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MAC
INTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH); | |
150 | |
151 //if (fFontVersionString == NULL) { | |
152 // status = LE_MISSING_FONT_TABLE_ERROR; | |
153 // goto error_exit; | |
154 //} | |
155 | |
156 //freeFontTable(nameTable); | |
157 | |
158 hheaTable = (HHEATable *) readFontTable(hheaTag); | |
159 | |
160 if (hheaTable == NULL) { | |
161 printf("%s:%d: %s: missing hhea table\n", __FILE__, __LINE__, fileName); | |
162 status = LE_MISSING_FONT_TABLE_ERROR; | |
163 goto error_exit; | |
164 } | |
165 | |
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)); | |
169 | |
170 fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics); | |
171 | |
172 freeFontTable((void *) hheaTable); | |
173 | |
174 fCMAPMapper = findUnicodeMapper(); | |
175 | |
176 if (fCMAPMapper == NULL) { | |
177 printf("%s:%d: %s: can't load cmap\n", __FILE__, __LINE__, fileName); | |
178 status = LE_MISSING_FONT_TABLE_ERROR; | |
179 goto error_exit; | |
180 } | |
181 | |
182 return; | |
183 | |
184 error_exit: | |
185 fclose(fFile); | |
186 fFile = NULL; | |
187 return; | |
188 } | |
189 | |
190 PortableFontInstance::~PortableFontInstance() | |
191 { | |
192 if (fFile != NULL) { | |
193 fclose(fFile); | |
194 | |
195 freeFontTable(fHMTXTable); | |
196 freeFontTable(fNAMETable); | |
197 | |
198 delete fCMAPMapper; | |
199 | |
200 LE_DELETE_ARRAY(fDirectory); | |
201 } | |
202 } | |
203 | |
204 const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const | |
205 { | |
206 if (fDirectory != NULL) { | |
207 le_uint16 table = 0; | |
208 le_uint16 probe = fDirPower; | |
209 | |
210 if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) { | |
211 table = fDirExtra; | |
212 } | |
213 | |
214 while (probe > (1 << 0)) { | |
215 probe >>= 1; | |
216 | |
217 if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) { | |
218 table += probe; | |
219 } | |
220 } | |
221 | |
222 if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) { | |
223 return &fDirectory->tableDirectory[table]; | |
224 } | |
225 } | |
226 | |
227 return NULL; | |
228 } | |
229 | |
230 const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const | |
231 { | |
232 const DirectoryEntry *entry = findTable(tag); | |
233 | |
234 if (entry == NULL) { | |
235 *length = 0; | |
236 return NULL; | |
237 } | |
238 | |
239 *length = SWAPL(entry->length); | |
240 | |
241 void *table = LE_NEW_ARRAY(char, *length); | |
242 | |
243 if (table != NULL) { | |
244 fseek(fFile, SWAPL(entry->offset), SEEK_SET); | |
245 fread(table, sizeof(char), *length, fFile); | |
246 } | |
247 | |
248 return table; | |
249 } | |
250 | |
251 const void *PortableFontInstance::getFontTable(LETag tableTag) const | |
252 { | |
253 size_t ignored; | |
254 return getFontTable(tableTag, ignored); | |
255 } | |
256 | |
257 const void *PortableFontInstance::getFontTable(LETag tableTag, size_t &length) c
onst | |
258 { | |
259 return FontTableCache::find(tableTag, length); | |
260 } | |
261 | |
262 const void *PortableFontInstance::readFontTable(LETag tableTag, size_t &length)
const | |
263 { | |
264 le_uint32 len; | |
265 | |
266 const void *data= readTable(tableTag, &len); | |
267 length = len; | |
268 //char tag5[5]; | |
269 //printf("Read %s, result %p #%d\n", letagToStr(tableTag,tag5), data,len); | |
270 return data; | |
271 } | |
272 | |
273 CMAPMapper *PortableFontInstance::findUnicodeMapper() | |
274 { | |
275 LETag cmapTag = LE_CMAP_TABLE_TAG; | |
276 const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag); | |
277 | |
278 if (cmap == NULL) { | |
279 return NULL; | |
280 } | |
281 | |
282 return CMAPMapper::createUnicodeMapper(cmap); | |
283 } | |
284 | |
285 const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 plat
formID, le_uint16 encodingID, le_uint16 languageID) const | |
286 { | |
287 if (fNAMETable == NULL) { | |
288 LETag nameTag = LE_NAME_TABLE_TAG; | |
289 PortableFontInstance *realThis = (PortableFontInstance *) this; | |
290 | |
291 realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag); | |
292 | |
293 if (realThis->fNAMETable != NULL) { | |
294 realThis->fNameCount = SWAPW(realThis->fNAMETable->count); | |
295 realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffs
et); | |
296 } | |
297 } | |
298 | |
299 for(le_int32 i = 0; i < fNameCount; i += 1) { | |
300 const NameRecord *nameRecord = &fNAMETable->nameRecords[i]; | |
301 | |
302 if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->enc
odingID) == encodingID && | |
303 SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nam
eID) == nameID) { | |
304 char *name = ((char *) fNAMETable) + fNameStringOffset + SWAPW(nameR
ecord->offset); | |
305 le_uint16 length = SWAPW(nameRecord->length); | |
306 char *result = LE_NEW_ARRAY(char, length + 2); | |
307 | |
308 LE_ARRAY_COPY(result, name, length); | |
309 result[length] = result[length + 1] = 0; | |
310 | |
311 return result; | |
312 } | |
313 } | |
314 | |
315 return NULL; | |
316 } | |
317 | |
318 const LEUnicode16 *PortableFontInstance::getUnicodeNameString(le_uint16 nameID,
le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const | |
319 { | |
320 if (fNAMETable == NULL) { | |
321 LETag nameTag = LE_NAME_TABLE_TAG; | |
322 PortableFontInstance *realThis = (PortableFontInstance *) this; | |
323 | |
324 realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag); | |
325 | |
326 if (realThis->fNAMETable != NULL) { | |
327 realThis->fNameCount = SWAPW(realThis->fNAMETable->count); | |
328 realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffs
et); | |
329 } | |
330 } | |
331 | |
332 for(le_int32 i = 0; i < fNameCount; i += 1) { | |
333 const NameRecord *nameRecord = &fNAMETable->nameRecords[i]; | |
334 | |
335 if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->enc
odingID) == encodingID && | |
336 SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nam
eID) == nameID) { | |
337 LEUnicode16 *name = (LEUnicode16 *) (((char *) fNAMETable) + fNameSt
ringOffset + SWAPW(nameRecord->offset)); | |
338 le_uint16 length = SWAPW(nameRecord->length) / 2; | |
339 LEUnicode16 *result = LE_NEW_ARRAY(LEUnicode16, length + 2); | |
340 | |
341 for (le_int32 c = 0; c < length; c += 1) { | |
342 result[c] = SWAPW(name[c]); | |
343 } | |
344 | |
345 result[length] = 0; | |
346 | |
347 return result; | |
348 } | |
349 } | |
350 | |
351 return NULL; | |
352 } | |
353 | |
354 void PortableFontInstance::deleteNameString(const char *name) const | |
355 { | |
356 LE_DELETE_ARRAY(name); | |
357 } | |
358 | |
359 void PortableFontInstance::deleteNameString(const LEUnicode16 *name) const | |
360 { | |
361 LE_DELETE_ARRAY(name); | |
362 } | |
363 | |
364 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) co
nst | |
365 { | |
366 TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph); | |
367 | |
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; | |
373 | |
374 if (maxpTable != NULL) { | |
375 realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs); | |
376 freeFontTable(maxpTable); | |
377 } | |
378 | |
379 realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag); | |
380 } | |
381 | |
382 le_uint16 index = ttGlyph; | |
383 | |
384 if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) { | |
385 advance.fX = advance.fY = 0; | |
386 return; | |
387 } | |
388 | |
389 if (ttGlyph >= fNumLongHorMetrics) { | |
390 index = fNumLongHorMetrics - 1; | |
391 } | |
392 | |
393 advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth))
; | |
394 advance.fY = 0; | |
395 } | |
396 | |
397 le_bool PortableFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*poin
tNumber*/, LEPoint &/*point*/) const | |
398 { | |
399 return FALSE; | |
400 } | |
401 | |
402 le_int32 PortableFontInstance::getUnitsPerEM() const | |
403 { | |
404 return fUnitsPerEM; | |
405 } | |
406 | |
407 le_uint32 PortableFontInstance::getFontChecksum() const | |
408 { | |
409 return fFontChecksum; | |
410 } | |
411 | |
412 le_uint32 PortableFontInstance::getRawChecksum() const | |
413 { | |
414 // how big is it? | |
415 // fseek(fFile, 0L, SEEK_END); | |
416 // long size = ftell(fFile); | |
417 le_int32 chksum = 0; | |
418 // now, calculate | |
419 fseek(fFile, 0L, SEEK_SET); | |
420 int r; | |
421 int count =0; | |
422 while((r = fgetc(fFile)) != EOF) { | |
423 chksum += r; | |
424 count ++; | |
425 } | |
426 return (le_uint32) chksum; // cast to signed | |
427 } | |
428 | |
429 le_int32 PortableFontInstance::getAscent() const | |
430 { | |
431 return fAscent; | |
432 } | |
433 | |
434 le_int32 PortableFontInstance::getDescent() const | |
435 { | |
436 return fDescent; | |
437 } | |
438 | |
439 le_int32 PortableFontInstance::getLeading() const | |
440 { | |
441 return fLeading; | |
442 } | |
443 | |
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 LECharMappe
r *mapper, le_bool filterZeroWidth) const | |
447 { | |
448 return LEFontInstance::mapCharToGlyph(ch, mapper, filterZeroWidth); | |
449 } | |
450 | |
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 LECharMappe
r *mapper) const | |
454 { | |
455 return LEFontInstance::mapCharToGlyph(ch, mapper); | |
456 } | |
457 | |
458 LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const | |
459 { | |
460 return fCMAPMapper->unicodeToGlyph(ch); | |
461 } | |
462 | |
463 float PortableFontInstance::getXPixelsPerEm() const | |
464 { | |
465 return fPointSize; | |
466 } | |
467 | |
468 float PortableFontInstance::getYPixelsPerEm() const | |
469 { | |
470 return fPointSize; | |
471 } | |
472 | |
473 float PortableFontInstance::getScaleFactorX() const | |
474 { | |
475 return 1.0; | |
476 } | |
477 | |
478 float PortableFontInstance::getScaleFactorY() const | |
479 { | |
480 return 1.0; | |
481 } | |
OLD | NEW |