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