1 /*--------------------------------------------------------------------*//*:Ignore this sentence.
2 Copyright (C) 2000, 2001 SIL International. All rights reserved.
3
4 Distributable under the terms of either the Common Public License or the
5 GNU Lesser General Public License, as specified in the LICENSING.txt file.
6
7 File: TtfUtil.cpp
8 Responsibility: Alan Ward
9 Last reviewed: Not yet.
10
11 Description:
12 Implements the methods for TtfUtil class. This file should remain portable to any C++
13 environment by only using standard C++ and the TTF structurs defined in Tt.h.
14 -------------------------------------------------------------------------------*//*:End Ignore*/
15
16
17 /***********************************************************************************************
18 Include files
19 ***********************************************************************************************/
20 // Language headers
21 #include <algorithm>
22 #include <cassert>
23 #include <cstddef>
24 #include <cstring>
25 #include <climits>
26 #include <stdexcept>
27 // Platform headers
28 // Module headers
29 #include "TtfUtil.h"
30 #include "TtfTypes.h"
31
32 /***********************************************************************************************
33 Forward declarations
34 ***********************************************************************************************/
35
36 /***********************************************************************************************
37 Local Constants and static variables
38 ***********************************************************************************************/
39 namespace
40 {
41 // max number of components allowed in composite glyphs
42 const int kMaxGlyphComponents = 8;
43
44 // These are basic byte order swapping functions
rev16(const T d)45 template<typename T> inline T rev16(const T d) {
46 T r = (d & 0xff) << 8; r |= (d & 0xff00) >> 8;
47 return r;
48 }
49
rev32(const T d)50 template<typename T> inline T rev32(const T d) {
51 T r = (d & 0xff) << 24; r |= (d & 0xff00) << 8;
52 r |= (d & 0xff0000) >> 8; r |= (d & 0xff000000) >> 24;
53 return r;
54 }
55
56 // This is the generic read function which does the swapping
read(const T d)57 template<typename T> inline T read(const T d) {
58 return d;
59 }
60
61 #if !defined WORDS_BIGENDIAN || defined PC_OS
read(const TtfUtil::uint16 d)62 template<> inline TtfUtil::uint16 read(const TtfUtil::uint16 d) {
63 return rev16(d);
64 }
65
read(const TtfUtil::int16 d)66 template<> inline TtfUtil::int16 read(const TtfUtil::int16 d) {
67 return rev16(d);
68 }
69
read(const TtfUtil::uint32 d)70 template<> inline TtfUtil::uint32 read(const TtfUtil::uint32 d) {
71 return rev32(d);
72 }
73
read(const TtfUtil::int32 d)74 template<> inline TtfUtil::int32 read(const TtfUtil::int32 d) {
75 return rev32(d);
76 }
77 #endif
78
79 template <int R, typename T>
fixed_to_float(const T f)80 inline float fixed_to_float(const T f) {
81 return float(f)/float(2^R);
82 }
83
84 #define MAKE_TAG(a,b,c,d) ((a << 24UL) + (b << 16UL) + (c << 8UL) + (d))
85 const gr::fontTableId32 mapIdToTag[] = {
86 MAKE_TAG('c','m','a','p'),
87 MAKE_TAG('c','v','t',' '),
88 MAKE_TAG('c','r','y','p'),
89 MAKE_TAG('h','e','a','d'),
90 MAKE_TAG('f','p','g','m'),
91 MAKE_TAG('g','d','i','r'),
92 MAKE_TAG('g','l','y','f'),
93 MAKE_TAG('h','d','m','x'),
94 MAKE_TAG('h','h','e','a'),
95 MAKE_TAG('h','m','t','x'),
96 MAKE_TAG('l','o','c','a'),
97 MAKE_TAG('k','e','r','n'),
98 MAKE_TAG('L','T','S','H'),
99 MAKE_TAG('m','a','x','p'),
100 MAKE_TAG('n','a','m','e'),
101 MAKE_TAG('O','S','/','2'),
102 MAKE_TAG('p','o','s','t'),
103 MAKE_TAG('p','r','e','p'),
104 MAKE_TAG('F','e','a','t'),
105 MAKE_TAG('G','l','a','t'),
106 MAKE_TAG('G','l','o','c'),
107 MAKE_TAG('S','i','l','f'),
108 MAKE_TAG('S','i','l','e'),
109 MAKE_TAG('S','i','l','l')
110 };
111
112
113 /*----------------------------------------------------------------------------------------------
114 Table of standard Postscript glyph names. From Martin Hosken. Disagress with ttfdump.exe
115 ---------------------------------------------------------------------------------------------*/
116 const int kcPostNames = 258;
117
118 const char * rgPostName[kcPostNames] = {
119 ".notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl", "numbersign",
120 "dollar", "percent", "ampersand", "quotesingle", "parenleft",
121 "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
122 "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
123 "nine", "colon", "semicolon", "less", "equal", "greater", "question",
124 "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
125 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
126 "bracketleft", "backslash", "bracketright", "asciicircum",
127 "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i",
128 "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
129 "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde",
130 "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis",
131 "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde",
132 "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis",
133 "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute",
134 "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave",
135 "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling",
136 "section", "bullet", "paragraph", "germandbls", "registered",
137 "copyright", "trademark", "acute", "dieresis", "notequal", "AE",
138 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen",
139 "mu", "partialdiff", "summation", "product", "pi", "integral",
140 "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown",
141 "exclamdown", "logicalnot", "radical", "florin", "approxequal",
142 "Delta", "guillemotleft", "guillemotright", "ellipsis", "nonbreakingspace",
143 "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash",
144 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
145 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
146 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered",
147 "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
148 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
149 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
150 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
151 "circumflex", "tilde", "macron", "breve", "dotaccent", "ring",
152 "cedilla", "hungarumlaut", "ogonek", "caron", "Lslash", "lslash",
153 "Scaron", "scaron", "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
154 "Yacute", "yacute", "Thorn", "thorn", "minus", "multiply",
155 "onesuperior", "twosuperior", "threesuperior", "onehalf", "onequarter",
156 "threequarters", "franc", "Gbreve", "gbreve", "Idotaccent", "Scedilla",
157 "scedilla", "Cacute", "cacute", "Ccaron", "ccaron",
158 "dcroat" };
159
160 } // end of namespace
161
162 /***********************************************************************************************
163 Methods
164 ***********************************************************************************************/
165
166 /* Note on error processing: The code guards against bad glyph ids being used to look up data
167 in open ended tables (loca, hmtx). If the glyph id comes from a cmap this shouldn't happen
168 but it seems prudent to check for user errors here. The code does assume that data obtained
169 from the TTF file is valid otherwise (though the CheckTable method seeks to check for
170 obvious problems that might accompany a change in table versions). For example an invalid
171 offset in the loca table which could exceed the size of the glyf table is NOT trapped.
172 Likewise if numberOf_LongHorMetrics in the hhea table is wrong, this will NOT be trapped,
173 which could cause a lookup in the hmtx table to exceed the table length. Of course, TTF tables
174 that are completely corrupt will cause unpredictable results. */
175
176 /* Note on composite glyphs: Glyphs that have components that are themselves composites
177 are not supported. IsDeepComposite can be used to test for this. False is returned from many
178 of the methods in this cases. It is unclear how to build composite glyphs in some cases,
179 so this code represents my best guess until test cases can be found. See notes on the high-
180 level GlyfPoints method. */
181
182 namespace TtfUtil
183 {
184
185
186 /*----------------------------------------------------------------------------------------------
187 Get offset and size of the offset table needed to find table directory
188 Return true if success, false otherwise
189 lSize excludes any table directory entries
190 ----------------------------------------------------------------------------------------------*/
GetHeaderInfo(size_t & lOffset,size_t & lSize)191 bool GetHeaderInfo(size_t & lOffset, size_t & lSize)
192 {
193 lOffset = 0;
194 lSize = offsetof(Sfnt::OffsetSubTable, table_directory);
195 assert(sizeof(uint32) + 4*sizeof (uint16) == lSize);
196 return true;
197 }
198
199 /*----------------------------------------------------------------------------------------------
200 Check the offset table for expected data
201 Return true if success, false otherwise
202 ----------------------------------------------------------------------------------------------*/
CheckHeader(const void * pHdr)203 bool CheckHeader(const void * pHdr)
204 {
205 const Sfnt::OffsetSubTable * pOffsetTable
206 = reinterpret_cast<const Sfnt::OffsetSubTable *>(pHdr);
207
208 return read(pOffsetTable->scaler_type) == Sfnt::OffsetSubTable::TrueTypeWin;
209 }
210
211 /*----------------------------------------------------------------------------------------------
212 Get offset and size of the table directory
213 Return true if successful, false otherwise
214 ----------------------------------------------------------------------------------------------*/
GetTableDirInfo(const void * pHdr,size_t & lOffset,size_t & lSize)215 bool GetTableDirInfo(const void * pHdr, size_t & lOffset, size_t & lSize)
216 {
217 const Sfnt::OffsetSubTable * pOffsetTable
218 = reinterpret_cast<const Sfnt::OffsetSubTable *>(pHdr);
219
220 lOffset = offsetof(Sfnt::OffsetSubTable, table_directory);
221 lSize = read(pOffsetTable->num_tables)
222 * sizeof(Sfnt::OffsetSubTable::Entry);
223
224 return true;
225 }
226
227
228 /*----------------------------------------------------------------------------------------------
229 Get offset and size of the specified table
230 Return true if successful, false otherwise. On false, offset and size will be 0
231 ----------------------------------------------------------------------------------------------*/
GetTableInfo(TableId ktiTableId,const void * pHdr,const void * pTableDir,size_t & lOffset,size_t & lSize)232 bool GetTableInfo(TableId ktiTableId, const void * pHdr, const void * pTableDir,
233 size_t & lOffset, size_t & lSize)
234 {
235 gr::fontTableId32 lTableTag = TableIdTag(ktiTableId);
236 if (!lTableTag)
237 {
238 lOffset = 0;
239 lSize = 0;
240 return false;
241 }
242
243 const Sfnt::OffsetSubTable * pOffsetTable
244 = reinterpret_cast<const Sfnt::OffsetSubTable *>(pHdr);
245 const Sfnt::OffsetSubTable::Entry
246 * entry_itr = reinterpret_cast<const Sfnt::OffsetSubTable::Entry *>(
247 pTableDir),
248 * const dir_end = entry_itr + read(pOffsetTable->num_tables);
249
250 assert(read(pOffsetTable->num_tables) < 40);
251 if (read(pOffsetTable->num_tables) > 40)
252 return false;
253
254 for (;entry_itr != dir_end; ++entry_itr) // 40 - safe guard
255 {
256 if (read(entry_itr->tag) == lTableTag)
257 {
258 lOffset = read(entry_itr->offset);
259 lSize = read(entry_itr->length);
260 return true;
261 }
262 }
263
264 return false;
265 }
266
267 /*----------------------------------------------------------------------------------------------
268 Check the specified table. Tests depend on the table type.
269 Return true if successful, false otherwise
270 ----------------------------------------------------------------------------------------------*/
CheckTable(TableId ktiTableId,const void * pTable,size_t lTableSize)271 bool CheckTable(TableId ktiTableId, const void * pTable, size_t lTableSize)
272 {
273 using namespace Sfnt;
274
275 switch(ktiTableId)
276 {
277 case ktiCmap: // cmap
278 {
279 const Sfnt::CharacterCodeMap * const pCmap
280 = reinterpret_cast<const Sfnt::CharacterCodeMap *>(pTable);
281 assert(read(pCmap->version) == 0);
282 return read(pCmap->version) == 0;
283 }
284
285 case ktiHead: // head
286 {
287 const Sfnt::FontHeader * const pHead
288 = reinterpret_cast<const Sfnt::FontHeader *>(pTable);
289 bool r = read(pHead->version) == OneFix
290 && read(pHead->magic_number) == FontHeader::MagicNumber
291 && read(pHead->glyph_data_format)
292 == FontHeader::GlypDataFormat
293 && (read(pHead->index_to_loc_format)
294 == FontHeader::ShortIndexLocFormat
295 || read(pHead->index_to_loc_format)
296 == FontHeader::LongIndexLocFormat)
297 && sizeof(FontHeader) <= lTableSize;
298 assert(r); return r;
299 }
300
301 case ktiPost: // post
302 {
303 const Sfnt::PostScriptGlyphName * const pPost
304 = reinterpret_cast<const Sfnt::PostScriptGlyphName *>(pTable);
305 const fixed format = read(pPost->format);
306 bool r = format == PostScriptGlyphName::Format1
307 || format == PostScriptGlyphName::Format2
308 || format == PostScriptGlyphName::Format3
309 || format == PostScriptGlyphName::Format25;
310 assert(r); return r;
311 }
312
313 case ktiHhea: // hhea
314 {
315 const Sfnt::HorizontalHeader * pHhea =
316 reinterpret_cast<const Sfnt::HorizontalHeader *>(pTable);
317 bool r = read(pHhea->version) == OneFix
318 && read(pHhea->metric_data_format) == 0
319 && sizeof (Sfnt::HorizontalHeader) <= lTableSize;
320 assert(r); return r;
321 }
322
323 case ktiMaxp: // maxp
324 {
325 const Sfnt::MaximumProfile * pMaxp =
326 reinterpret_cast<const Sfnt::MaximumProfile *>(pTable);
327 bool r = read(pMaxp->version) == OneFix
328 && sizeof(Sfnt::MaximumProfile) <= lTableSize;
329 assert(r); return r;
330 }
331
332 case ktiOs2: // OS/2
333 {
334 const Sfnt::Compatibility * pOs2
335 = reinterpret_cast<const Sfnt::Compatibility *>(pTable);
336 if (read(pOs2->version) == 0)
337 { // OS/2 table version 1 size
338 // if (sizeof(Sfnt::Compatibility)
339 // - sizeof(uint32)*2 - sizeof(int16)*2
340 // - sizeof(uint16)*3 <= lTableSize)
341 if (sizeof(Sfnt::Compatibility0) <= lTableSize)
342 return true;
343 }
344 else if (read(pOs2->version) == 1)
345 { // OS/2 table version 2 size
346 // if (sizeof(Sfnt::Compatibility)
347 // - sizeof(int16) *2
348 // - sizeof(uint16)*3 <= lTableSize)
349 if (sizeof(Sfnt::Compatibility1) <= lTableSize)
350 return true;
351 }
352 else if (read(pOs2->version) == 2)
353 { // OS/2 table version 3 size
354 if (sizeof(Sfnt::Compatibility2) <= lTableSize)
355 return true;
356 }
357 else if (read(pOs2->version) == 3)
358 { // OS/2 table version 4 size - version 4 changed the meaning of some fields which we don't use
359 if (sizeof(Sfnt::Compatibility3) <= lTableSize)
360 return true;
361 }
362 else
363 return false;
364 }
365
366 case ktiName:
367 {
368 const Sfnt::FontNames * pName
369 = reinterpret_cast<const Sfnt::FontNames *>(pTable);
370 assert(read(pName->format) == 0);
371 return read(pName->format) == 0;
372 }
373
374 default:
375 break;
376 }
377
378 return true;
379 }
380
381 /*----------------------------------------------------------------------------------------------
382 Return the number of glyphs in the font. Should never be less than zero.
383 ----------------------------------------------------------------------------------------------*/
GlyphCount(const void * pMaxp)384 size_t GlyphCount(const void * pMaxp)
385 {
386 const Sfnt::MaximumProfile * pTable =
387 reinterpret_cast<const Sfnt::MaximumProfile *>(pMaxp);
388 return read(pTable->num_glyphs);
389 }
390
391 /*----------------------------------------------------------------------------------------------
392 Return the maximum number of components for any composite glyph in the font
393 ----------------------------------------------------------------------------------------------*/
MaxCompositeComponentCount(const void * pMaxp)394 size_t MaxCompositeComponentCount(const void * pMaxp)
395 {
396 const Sfnt::MaximumProfile * pTable =
397 reinterpret_cast<const Sfnt::MaximumProfile *>(pMaxp);
398 return read(pTable->max_component_elements);
399 }
400
401 /*----------------------------------------------------------------------------------------------
402 Composite glyphs can be composed of glyphs that are themselves composites.
403 This method returns the maximum number of levels like this for any glyph in the font.
404 A non-composite glyph has a level of 1
405 ----------------------------------------------------------------------------------------------*/
MaxCompositeLevelCount(const void * pMaxp)406 size_t MaxCompositeLevelCount(const void * pMaxp)
407 {
408 const Sfnt::MaximumProfile * pTable =
409 reinterpret_cast<const Sfnt::MaximumProfile *>(pMaxp);
410 return read(pTable->max_component_depth);
411 }
412
413 /*----------------------------------------------------------------------------------------------
414 Return the number of glyphs in the font according to a differt source.
415 Should never be less than zero. Return -1 on failure.
416 ----------------------------------------------------------------------------------------------*/
LocaGlyphCount(size_t lLocaSize,const void * pHead)417 size_t LocaGlyphCount(size_t lLocaSize, const void * pHead) throw(std::domain_error)
418 {
419
420 const Sfnt::FontHeader * pTable
421 = reinterpret_cast<const Sfnt::FontHeader *>(pHead);
422
423 if (read(pTable->index_to_loc_format)
424 == Sfnt::FontHeader::ShortIndexLocFormat)
425 // loca entries are two bytes and have been divided by two
426 return (lLocaSize >> 1) - 1;
427
428 if (read(pTable->index_to_loc_format)
429 == Sfnt::FontHeader::LongIndexLocFormat)
430 // loca entries are four bytes
431 return (lLocaSize >> 2) - 1;
432
433 //return -1;
434 throw std::domain_error("head table in inconsistent state. The font may be corrupted");
435 }
436
437 /*----------------------------------------------------------------------------------------------
438 Return the design units the font is designed with
439 ----------------------------------------------------------------------------------------------*/
DesignUnits(const void * pHead)440 int DesignUnits(const void * pHead)
441 {
442 const Sfnt::FontHeader * pTable =
443 reinterpret_cast<const Sfnt::FontHeader *>(pHead);
444
445 return read(pTable->units_per_em);
446 }
447
448 /*----------------------------------------------------------------------------------------------
449 Return the checksum from the head table, which serves as a unique identifer for the font.
450 ----------------------------------------------------------------------------------------------*/
HeadTableCheckSum(const void * pHead)451 int HeadTableCheckSum(const void * pHead)
452 {
453 const Sfnt::FontHeader * pTable =
454 reinterpret_cast<const Sfnt::FontHeader *>(pHead);
455
456 return read(pTable->check_sum_adjustment);
457 }
458
459 /*----------------------------------------------------------------------------------------------
460 Return the create time from the head table. This consists of a 64-bit integer, which
461 we return here as two 32-bit integers.
462 ----------------------------------------------------------------------------------------------*/
HeadTableCreateTime(const void * pHead,unsigned int * pnDateBC,unsigned int * pnDateAD)463 void HeadTableCreateTime(const void * pHead,
464 unsigned int * pnDateBC, unsigned int * pnDateAD)
465 {
466 const Sfnt::FontHeader * pTable =
467 reinterpret_cast<const Sfnt::FontHeader *>(pHead);
468
469 *pnDateBC = read(pTable->created[0]);
470 *pnDateAD = read(pTable->created[1]);
471 }
472
473 /*----------------------------------------------------------------------------------------------
474 Return the modify time from the head table.This consists of a 64-bit integer, which
475 we return here as two 32-bit integers.
476 ----------------------------------------------------------------------------------------------*/
HeadTableModifyTime(const void * pHead,unsigned int * pnDateBC,unsigned int * pnDateAD)477 void HeadTableModifyTime(const void * pHead,
478 unsigned int * pnDateBC, unsigned int *pnDateAD)
479 {
480 const Sfnt::FontHeader * pTable =
481 reinterpret_cast<const Sfnt::FontHeader *>(pHead);
482
483 *pnDateBC = read(pTable->modified[0]);
484 *pnDateAD = read(pTable->modified[1]);
485 }
486
487 /*----------------------------------------------------------------------------------------------
488 Return true if the font is italic.
489 ----------------------------------------------------------------------------------------------*/
IsItalic(const void * pHead)490 bool IsItalic(const void * pHead)
491 {
492 const Sfnt::FontHeader * pTable =
493 reinterpret_cast<const Sfnt::FontHeader *>(pHead);
494
495 return ((read(pTable->mac_style) & 0x00000002) != 0);
496 }
497
498 /*----------------------------------------------------------------------------------------------
499 Return the ascent for the font
500 ----------------------------------------------------------------------------------------------*/
FontAscent(const void * pOs2)501 int FontAscent(const void * pOs2)
502 {
503 const Sfnt::Compatibility * pTable = reinterpret_cast<const Sfnt::Compatibility *>(pOs2);
504
505 return read(pTable->win_ascent);
506 }
507
508 /*----------------------------------------------------------------------------------------------
509 Return the descent for the font
510 ----------------------------------------------------------------------------------------------*/
FontDescent(const void * pOs2)511 int FontDescent(const void * pOs2)
512 {
513 const Sfnt::Compatibility * pTable = reinterpret_cast<const Sfnt::Compatibility *>(pOs2);
514
515 return read(pTable->win_descent);
516 }
517
518 /*----------------------------------------------------------------------------------------------
519 Get the bold and italic style bits.
520 Return true if successful. false otherwise.
521 In addition to checking the OS/2 table, one could also check
522 the head table's macStyle field (overridden by the OS/2 table on Win)
523 the sub-family name in the name table (though this can contain oblique, dark, etc too)
524 ----------------------------------------------------------------------------------------------*/
FontOs2Style(const void * pOs2,bool & fBold,bool & fItalic)525 bool FontOs2Style(const void *pOs2, bool & fBold, bool & fItalic)
526 {
527 const Sfnt::Compatibility * pTable = reinterpret_cast<const Sfnt::Compatibility *>(pOs2);
528
529 fBold = (read(pTable->fs_selection) & Sfnt::Compatibility::Bold) != 0;
530 fItalic = (read(pTable->fs_selection) & Sfnt::Compatibility::Italic) != 0;
531
532 return true;
533 }
534
535 /*----------------------------------------------------------------------------------------------
536 Method for searching name table.
537 ----------------------------------------------------------------------------------------------*/
GetNameInfo(const void * pName,int nPlatformId,int nEncodingId,int nLangId,int nNameId,size_t & lOffset,size_t & lSize)538 bool GetNameInfo(const void * pName, int nPlatformId, int nEncodingId,
539 int nLangId, int nNameId, size_t & lOffset, size_t & lSize)
540 {
541 lOffset = 0;
542 lSize = 0;
543
544 const Sfnt::FontNames * pTable = reinterpret_cast<const Sfnt::FontNames *>(pName);
545 uint16 cRecord = read(pTable->count);
546 uint16 nRecordOffset = read(pTable->string_offset);
547 const Sfnt::NameRecord * pRecord = reinterpret_cast<const Sfnt::NameRecord *>(pTable + 1);
548
549 for (int i = 0; i < cRecord; ++i)
550 {
551 if (read(pRecord->platform_id) == nPlatformId &&
552 read(pRecord->platform_specific_id) == nEncodingId &&
553 read(pRecord->language_id) == nLangId &&
554 read(pRecord->name_id) == nNameId)
555 {
556 lOffset = read(pRecord->offset) + nRecordOffset;
557 lSize = read(pRecord->length);
558 return true;
559 }
560 pRecord++;
561 }
562
563 return false;
564 }
565
566 /*----------------------------------------------------------------------------------------------
567 Return all the lang-IDs that have data for the given name-IDs. Assume that there is room
568 in the return array (langIdList) for 128 items. The purpose of this method is to return
569 a list of all possible lang-IDs.
570 ----------------------------------------------------------------------------------------------*/
GetLangsForNames(const void * pName,int nPlatformId,int nEncodingId,int * nameIdList,int cNameIds,short * langIdList)571 int GetLangsForNames(const void * pName, int nPlatformId, int nEncodingId,
572 int * nameIdList, int cNameIds, short * langIdList)
573 {
574 const Sfnt::FontNames * pTable = reinterpret_cast<const Sfnt::FontNames *>(pName);
575 uint16 cRecord = read(pTable->count);
576 //uint16 nRecordOffset = swapw(pTable->stringOffset);
577 const Sfnt::NameRecord * pRecord = reinterpret_cast<const Sfnt::NameRecord *>(pTable + 1);
578
579 int cLangIds = 0;
580 for (int i = 0; i < cRecord; ++i)
581 {
582 if (read(pRecord->platform_id) == nPlatformId &&
583 read(pRecord->platform_specific_id) == nEncodingId)
584 {
585 bool fNameFound = false;
586 int nLangId = read(pRecord->language_id);
587 int nNameId = read(pRecord->name_id);
588 for (int j = 0; j < cNameIds; j++)
589 {
590 if (nNameId == nameIdList[j])
591 {
592 fNameFound = true;
593 break;
594 }
595 }
596 if (fNameFound)
597 {
598 // Add it if it's not there.
599 int ilang;
600 for (ilang = 0; ilang < cLangIds; ilang++)
601 if (langIdList[ilang] == nLangId)
602 break;
603 if (ilang >= cLangIds)
604 {
605 langIdList[cLangIds] = short(nLangId);
606 cLangIds++;
607 }
608 if (cLangIds == 128)
609 return cLangIds;
610 }
611 }
612 pRecord++;
613 }
614
615 return cLangIds;
616 }
617
618 /*----------------------------------------------------------------------------------------------
619 Get the offset and size of the font family name in English for the MS Platform with Unicode
620 writing system. The offset is within the pName data. The string is double byte with MSB first.
621 ----------------------------------------------------------------------------------------------*/
Get31EngFamilyInfo(const void * pName,size_t & lOffset,size_t & lSize)622 bool Get31EngFamilyInfo(const void * pName, size_t & lOffset, size_t & lSize)
623 {
624 return GetNameInfo(pName, Sfnt::NameRecord::Microsoft, 1, 1033,
625 Sfnt::NameRecord::Family, lOffset, lSize);
626 }
627
628 /*----------------------------------------------------------------------------------------------
629 Get the offset and size of the full font name in English for the MS Platform with Unicode
630 writing system. The offset is within the pName data. The string is double byte with MSB first.
631 ----------------------------------------------------------------------------------------------*/
Get31EngFullFontInfo(const void * pName,size_t & lOffset,size_t & lSize)632 bool Get31EngFullFontInfo(const void * pName, size_t & lOffset, size_t & lSize)
633 {
634 return GetNameInfo(pName, Sfnt::NameRecord::Microsoft, 1, 1033,
635 Sfnt::NameRecord::Fullname, lOffset, lSize);
636 }
637
638 /*----------------------------------------------------------------------------------------------
639 Get the offset and size of the font family name in English for the MS Platform with Symbol
640 writing system. The offset is within the pName data. The string is double byte with MSB first.
641 ----------------------------------------------------------------------------------------------*/
Get30EngFamilyInfo(const void * pName,size_t & lOffset,size_t & lSize)642 bool Get30EngFamilyInfo(const void * pName, size_t & lOffset, size_t & lSize)
643 {
644 return GetNameInfo(pName, Sfnt::NameRecord::Microsoft, 0, 1033,
645 Sfnt::NameRecord::Family, lOffset, lSize);
646 }
647
648 /*----------------------------------------------------------------------------------------------
649 Get the offset and size of the full font name in English for the MS Platform with Symbol
650 writing system. The offset is within the pName data. The string is double byte with MSB first.
651 ----------------------------------------------------------------------------------------------*/
Get30EngFullFontInfo(const void * pName,size_t & lOffset,size_t & lSize)652 bool Get30EngFullFontInfo(const void * pName, size_t & lOffset, size_t & lSize)
653 {
654 return GetNameInfo(pName, Sfnt::NameRecord::Microsoft, 0, 1033,
655 Sfnt::NameRecord::Fullname, lOffset, lSize);
656 }
657
658 /*----------------------------------------------------------------------------------------------
659 Return the Glyph ID for a given Postscript name. This method finds the first glyph which
660 matches the requested Postscript name. Ideally every glyph should have a unique Postscript
661 name (except for special names such as .notdef), but this is not always true.
662 On failure return value less than zero.
663 -1 - table search failed
664 -2 - format 3 table (no Postscript glyph info)
665 -3 - other failures
666 ----------------------------------------------------------------------------------------------*/
PostLookup(const void * pPost,size_t lPostSize,const void * pMaxp,const char * pPostName)667 int PostLookup(const void * pPost, size_t lPostSize, const void * pMaxp,
668 const char * pPostName)
669 {
670 using namespace Sfnt;
671
672 const Sfnt::PostScriptGlyphName * pTable
673 = reinterpret_cast<const Sfnt::PostScriptGlyphName *>(pPost);
674 fixed format = read(pTable->format);
675
676 if (format == PostScriptGlyphName::Format3)
677 { // format 3 - no Postscript glyph info in font
678 return -2;
679 }
680
681 // search for given Postscript name among the standard names
682 int iPostName = -1; // index in standard names
683 for (int i = 0; i < kcPostNames; i++)
684 {
685 if (!strcmp(pPostName, rgPostName[i]))
686 {
687 iPostName = i;
688 break;
689 }
690 }
691
692 if (format == PostScriptGlyphName::Format1)
693 { // format 1 - use standard Postscript names
694 return iPostName;
695 }
696
697 if (format == PostScriptGlyphName::Format25)
698 {
699 if (iPostName == -1)
700 return -1;
701
702 const PostScriptGlyphName25 * pTable25
703 = static_cast<const PostScriptGlyphName25 *>(pTable);
704 int cnGlyphs = GlyphCount(pMaxp);
705 for (gr::gid16 nGlyphId = 0; nGlyphId < cnGlyphs && nGlyphId < kcPostNames;
706 nGlyphId++)
707 { // glyph_name_index25 contains bytes so no byte swapping needed
708 // search for first glyph id that uses the standard name
709 if (nGlyphId + pTable25->offset[nGlyphId] == iPostName)
710 return nGlyphId;
711 }
712 }
713
714 if (format == PostScriptGlyphName::Format2)
715 { // format 2
716 const PostScriptGlyphName2 * pTable2
717 = static_cast<const PostScriptGlyphName2 *>(pTable);
718
719 int cnGlyphs = read(pTable2->number_of_glyphs);
720
721 if (iPostName != -1)
722 { // did match a standard name, look for first glyph id mapped to that name
723 for (gr::gid16 nGlyphId = 0; nGlyphId < cnGlyphs; nGlyphId++)
724 {
725 if (read(pTable2->glyph_name_index[nGlyphId]) == iPostName)
726 return nGlyphId;
727 }
728 return -1; // no glyph with this standard name
729 }
730
731 else
732 { // did not match a standard name, search font specific names
733 size_t nStrSizeGoal = strlen(pPostName);
734 const char * pFirstGlyphName = reinterpret_cast<const char *>(
735 &pTable2->glyph_name_index[0] + cnGlyphs);
736 const char * pGlyphName = pFirstGlyphName;
737 int iInNames = 0; // index in font specific names
738 bool fFound = false;
739 const char * const endOfTable
740 = reinterpret_cast<const char *>(pTable2) + lPostSize;
741 while (pGlyphName < endOfTable && !fFound)
742 { // search Pascal strings for first matching name
743 size_t nStringSize = size_t(*pGlyphName);
744 if (nStrSizeGoal != nStringSize ||
745 strncmp(pGlyphName + 1, pPostName, nStringSize))
746 { // did not match
747 ++iInNames;
748 pGlyphName += nStringSize + 1;
749 }
750 else
751 { // did match
752 fFound = true;
753 }
754 }
755 if (!fFound)
756 return -1; // no font specific name matches request
757
758 iInNames += kcPostNames;
759 for (gr::gid16 nGlyphId = 0; nGlyphId < cnGlyphs; nGlyphId++)
760 { // search for first glyph id that maps to the found string index
761 if (read(pTable2->glyph_name_index[nGlyphId]) == iInNames)
762 return nGlyphId;
763 }
764 return -1; // no glyph mapped to this index (very strange)
765 }
766 }
767
768 return -3;
769 }
770
771 /*----------------------------------------------------------------------------------------------
772 Convert a Unicode character string from big endian (MSB first, Motorola) format to little
773 endian (LSB first, Intel) format.
774 nSize is the number of Unicode characters in the string. It should not include any
775 terminating null. If nSize is 0, it is assumed the string is null terminated. nSize
776 defaults to 0.
777 Return true if successful, false otherwise.
778 ----------------------------------------------------------------------------------------------*/
SwapWString(void * pWStr,size_t nSize)779 void SwapWString(void * pWStr, size_t nSize /* = 0 */) throw (std::invalid_argument)
780 {
781 if (pWStr == 0)
782 throw std::invalid_argument("null pointer given");
783
784 uint16 * pStr = reinterpret_cast<uint16 *>(pWStr);
785 uint16 * const pStrEnd = pStr + (nSize == 0 ? gr::utf16len(pStr) : nSize);
786
787 std::transform(pStr, pStrEnd, pStr, read<uint16>);
788
789 // for (int i = 0; i < nSize; i++)
790 // { // swap the wide characters in the string
791 // pStr[i] = gr::utf16(read(uint16(pStr[i])));
792 // }
793 }
794
795 /*----------------------------------------------------------------------------------------------
796 Get the left-side bearing and and advance width based on the given tables and Glyph ID
797 Return true if successful, false otherwise. On false, one or both value could be INT_MIN
798 ----------------------------------------------------------------------------------------------*/
HorMetrics(gr::gid16 nGlyphId,const void * pHmtx,size_t lHmtxSize,const void * pHhea,int & nLsb,unsigned int & nAdvWid)799 bool HorMetrics(gr::gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize, const void * pHhea,
800 int & nLsb, unsigned int & nAdvWid)
801 {
802 const Sfnt::HorizontalMetric * phmtx =
803 reinterpret_cast<const Sfnt::HorizontalMetric *>(pHmtx);
804
805 const Sfnt::HorizontalHeader * phhea =
806 reinterpret_cast<const Sfnt::HorizontalHeader *>(pHhea);
807
808 size_t cLongHorMetrics = read(phhea->num_long_hor_metrics);
809 if (nGlyphId < cLongHorMetrics)
810 { // glyph id is acceptable
811 nAdvWid = read(phmtx[nGlyphId].advance_width);
812 nLsb = read(phmtx[nGlyphId].left_side_bearing);
813 }
814 else
815 {
816 nAdvWid = read(phmtx[cLongHorMetrics - 1].advance_width);
817
818 // guard against bad glyph id
819 size_t lLsbOffset = sizeof(Sfnt::HorizontalMetric) * cLongHorMetrics +
820 sizeof(int16) * (nGlyphId - cLongHorMetrics); // offset in bytes
821 if (lLsbOffset + 1 >= lHmtxSize) // + 1 because entries are two bytes wide
822 {
823 nLsb = 0;
824 return false;
825 }
826 const int16 * pLsb = reinterpret_cast<const int16 *>(phmtx) +
827 lLsbOffset / sizeof(int16);
828 nLsb = read(*pLsb);
829 }
830
831 return true;
832 }
833
834 /*----------------------------------------------------------------------------------------------
835 Return a pointer to the requested cmap subtable. By default find the Microsoft Unicode
836 subtable. Pass nEncoding as -1 to find first table that matches only nPlatformId.
837 Return NULL if the subtable cannot be found.
838 ----------------------------------------------------------------------------------------------*/
FindCmapSubtable(const void * pCmap,int nPlatformId,int nEncodingId)839 void * FindCmapSubtable(const void * pCmap,
840 int nPlatformId, /* =3 */
841 int nEncodingId) /* = 1 */
842 {
843 const Sfnt::CharacterCodeMap * pTable =
844 reinterpret_cast<const Sfnt::CharacterCodeMap *>(pCmap);
845
846 uint16 csuPlatforms = read(pTable->num_subtables);
847 for (int i = 0; i < csuPlatforms; i++)
848 {
849 if (read(pTable->encoding[i].platform_id) == nPlatformId &&
850 (nEncodingId == -1 || read(pTable->encoding[i].platform_specific_id) == nEncodingId))
851 {
852 const void * pRtn = reinterpret_cast<const uint8 *>(pCmap) +
853 read(pTable->encoding[i].offset);
854 return const_cast<void *>(pRtn);
855 }
856 }
857
858 return 0;
859 }
860
861 /*----------------------------------------------------------------------------------------------
862 Check the Microsoft Unicode subtable for expected values
863 ----------------------------------------------------------------------------------------------*/
CheckCmap31Subtable(const void * pCmap31)864 bool CheckCmap31Subtable(const void * pCmap31)
865 {
866 const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmap31);
867 // Bob H says ome freeware TT fonts have version 1 (eg, CALIGULA.TTF)
868 // so don't check subtable version. 21 Mar 2002 spec changes version to language.
869
870 return read(pTable->format) == 4;
871 }
872
873 /*----------------------------------------------------------------------------------------------
874 Return the Glyph ID for the given Unicode ID in the Microsoft Unicode subtable.
875 (Actually this code only depends on subtable being format 4.)
876 Return 0 if the Unicode ID is not in the subtable.
877 ----------------------------------------------------------------------------------------------*/
Cmap31Lookup(const void * pCmap31,int nUnicodeId)878 gr::gid16 Cmap31Lookup(const void * pCmap31, int nUnicodeId)
879 {
880 const Sfnt::CmapSubTableFormat4 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmap31);
881
882 uint16 nSeg = read(pTable->seg_count_x2) >> 1;
883
884 uint16 n;
885 const uint16 * pLeft, * pMid;
886 uint16 cMid, chStart, chEnd;
887
888 // Binary search of the endCode[] array
889 pLeft = &(pTable->end_code[0]);
890 n = nSeg;
891 while (n > 0)
892 {
893 cMid = n >> 1; // Pick an element in the middle
894 pMid = pLeft + cMid;
895 chEnd = read(*pMid);
896 if (nUnicodeId <= chEnd)
897 {
898 if (cMid == 0 || nUnicodeId > read(pMid[-1]))
899 break; // Must be this seg or none!
900 n = cMid; // Continue on left side, omitting mid point
901 }
902 else
903 {
904 pLeft = pMid + 1; // Continue on right side, omitting mid point
905 n -= (cMid + 1);
906 }
907 }
908
909 if (!n)
910 return 0;
911
912 // Ok, we're down to one segment and pMid points to the endCode element
913 // Either this is it or none is.
914
915 chStart = read(*(pMid += nSeg + 1));
916 if (chEnd >= nUnicodeId && nUnicodeId >= chStart)
917 {
918 // Found correct segment. Find Glyph Id
919 int16 idDelta = read(*(pMid += nSeg));
920 uint16 idRangeOffset = read(*(pMid += nSeg));
921
922 if (idRangeOffset == 0)
923 return (uint16)(idDelta + nUnicodeId); // must use modulus 2^16
924
925 // Look up value in glyphIdArray
926 gr::gid16 nGlyphId = read(*(pMid + (nUnicodeId - chStart) + (idRangeOffset >> 1)));
927 // If this value is 0, return 0. Else add the idDelta
928 return nGlyphId ? nGlyphId + idDelta : 0;
929 }
930
931 return 0;
932 }
933
934 /*----------------------------------------------------------------------------------------------
935 Return the next Unicode value in the cmap. Pass 0 to obtain the first item.
936 Returns 0xFFFF as the last item.
937 pRangeKey is an optional key that is used to optimize the search; its value is the range
938 in which the character is found.
939 ----------------------------------------------------------------------------------------------*/
Cmap31NextCodepoint(const void * pCmap31,unsigned int nUnicodeId,int * pRangeKey)940 unsigned int Cmap31NextCodepoint(const void *pCmap31, unsigned int nUnicodeId, int * pRangeKey)
941 {
942 const Sfnt::CmapSubTableFormat4 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmap31);
943
944 uint16 nRange = read(pTable->seg_count_x2) >> 1;
945
946 uint32 nUnicodePrev = (uint32)nUnicodeId;
947
948 const uint16 * pStartCode = &(pTable->end_code[0])
949 + nRange // length of end code array
950 + 1; // reserved word
951
952 if (nUnicodePrev == 0)
953 {
954 // return the first codepoint.
955 if (pRangeKey)
956 *pRangeKey = 0;
957 return read(pStartCode[0]);
958 }
959 else if (nUnicodePrev >= 0xFFFF)
960 {
961 if (pRangeKey)
962 *pRangeKey = nRange - 1;
963 return 0xFFFF;
964 }
965
966 int iRange = (pRangeKey) ? *pRangeKey : 0;
967 // Just in case we have a bad key:
968 while (iRange > 0 && read(pStartCode[iRange]) > nUnicodePrev)
969 iRange--;
970 while (read(pTable->end_code[iRange]) < nUnicodePrev)
971 iRange++;
972
973 // Now iRange is the range containing nUnicodePrev.
974 unsigned int nStartCode = read(pStartCode[iRange]);
975 unsigned int nEndCode = read(pTable->end_code[iRange]);
976
977 if (nStartCode > nUnicodePrev)
978 // Oops, nUnicodePrev is not in the cmap! Adjust so we get a reasonable
979 // answer this time around.
980 nUnicodePrev = nStartCode - 1;
981
982 if (nEndCode > nUnicodePrev)
983 {
984 // Next is in the same range; it is the next successive codepoint.
985 if (pRangeKey)
986 *pRangeKey = iRange;
987 return nUnicodePrev + 1;
988 }
989
990 // Otherwise the next codepoint is the first one in the next range.
991 // There is guaranteed to be a next range because there must be one that
992 // ends with 0xFFFF.
993 if (pRangeKey)
994 *pRangeKey = iRange + 1;
995 return read(pStartCode[iRange + 1]);
996 }
997
998 /*----------------------------------------------------------------------------------------------
999 Check the Microsoft UCS-4 subtable for expected values
1000 ----------------------------------------------------------------------------------------------*/
CheckCmap310Subtable(const void * pCmap310)1001 bool CheckCmap310Subtable(const void *pCmap310)
1002 {
1003 const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmap310);
1004 return read(pTable->format) == 12;
1005 }
1006
1007 /*----------------------------------------------------------------------------------------------
1008 Return the Glyph ID for the given Unicode ID in the Microsoft UCS-4 subtable.
1009 (Actually this code only depends on subtable being format 12.)
1010 Return 0 if the Unicode ID is not in the subtable.
1011 ----------------------------------------------------------------------------------------------*/
Cmap310Lookup(const void * pCmap310,unsigned int uUnicodeId)1012 gr::gid16 Cmap310Lookup(const void * pCmap310, unsigned int uUnicodeId)
1013 {
1014 const Sfnt::CmapSubTableFormat12 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmap310);
1015
1016 //uint32 uLength = read(pTable->length); //could use to test for premature end of table
1017 uint32 ucGroups = read(pTable->num_groups);
1018
1019 for (unsigned int i = 0; i < ucGroups; i++)
1020 {
1021 uint32 uStartCode = read(pTable->group[i].start_char_code);
1022 uint32 uEndCode = read(pTable->group[i].end_char_code);
1023 if (uUnicodeId >= uStartCode && uUnicodeId <= uEndCode)
1024 {
1025 uint32 uDiff = uUnicodeId - uStartCode;
1026 uint32 uStartGid = read(pTable->group[i].start_glyph_id);
1027 return static_cast<gr::gid16>(uStartGid + uDiff);
1028 }
1029 }
1030
1031 return 0;
1032 }
1033
1034 /*----------------------------------------------------------------------------------------------
1035 Return the next Unicode value in the cmap. Pass 0 to obtain the first item.
1036 Returns 0x10FFFF as the last item.
1037 pRangeKey is an optional key that is used to optimize the search; its value is the range
1038 in which the character is found.
1039 ----------------------------------------------------------------------------------------------*/
Cmap310NextCodepoint(const void * pCmap310,unsigned int nUnicodeId,int * pRangeKey)1040 unsigned int Cmap310NextCodepoint(const void *pCmap310, unsigned int nUnicodeId, int * pRangeKey)
1041 {
1042 const Sfnt::CmapSubTableFormat12 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmap310);
1043
1044 int nRange = read(pTable->num_groups);
1045
1046 uint32 nUnicodePrev = (uint32)nUnicodeId;
1047
1048 if (nUnicodePrev == 0)
1049 {
1050 // return the first codepoint.
1051 if (pRangeKey)
1052 *pRangeKey = 0;
1053 return read(pTable->group[0].start_char_code);
1054 }
1055 else if (nUnicodePrev >= 0x10FFFF)
1056 {
1057 if (pRangeKey)
1058 *pRangeKey = nRange;
1059 return 0x10FFFF;
1060 }
1061
1062 int iRange = (pRangeKey) ? *pRangeKey : 0;
1063 // Just in case we have a bad key:
1064 while (iRange > 0 && read(pTable->group[iRange].start_char_code) > nUnicodePrev)
1065 iRange--;
1066 while (read(pTable->group[iRange].end_char_code) < nUnicodePrev)
1067 iRange++;
1068
1069 // Now iRange is the range containing nUnicodePrev.
1070
1071 unsigned int nStartCode = read(pTable->group[iRange].start_char_code);
1072 unsigned int nEndCode = read(pTable->group[iRange].end_char_code);
1073
1074 if (nStartCode > nUnicodePrev)
1075 // Oops, nUnicodePrev is not in the cmap! Adjust so we get a reasonable
1076 // answer this time around.
1077 nUnicodePrev = nStartCode - 1;
1078
1079 if (nEndCode > nUnicodePrev)
1080 {
1081 // Next is in the same range; it is the next successive codepoint.
1082 if (pRangeKey)
1083 *pRangeKey = iRange;
1084 return nUnicodePrev + 1;
1085 }
1086
1087 // Otherwise the next codepoint is the first one in the next range, or 10FFFF if we're done.
1088 if (pRangeKey)
1089 *pRangeKey = iRange + 1;
1090 return (iRange + 1 >= nRange) ? 0x10FFFF : read(pTable->group[iRange + 1].start_char_code);
1091 }
1092
1093 /*----------------------------------------------------------------------------------------------
1094 Return the offset stored in the loca table for the given Glyph ID.
1095 (This offset is into the glyf table.)
1096 Return -1 if the lookup failed.
1097 Technically this method should return an unsigned long but it is unlikely the offset will
1098 exceed 2^31.
1099 ----------------------------------------------------------------------------------------------*/
LocaLookup(gr::gid16 nGlyphId,const void * pLoca,size_t lLocaSize,const void * pHead)1100 size_t LocaLookup(gr::gid16 nGlyphId,
1101 const void * pLoca, size_t lLocaSize,
1102 const void * pHead) throw (std::out_of_range)
1103 {
1104 const Sfnt::FontHeader * pTable = reinterpret_cast<const Sfnt::FontHeader *>(pHead);
1105
1106 // CheckTable verifies the index_to_loc_format is valid
1107 if (read(pTable->index_to_loc_format) == Sfnt::FontHeader::ShortIndexLocFormat)
1108 { // loca entries are two bytes and have been divided by two
1109 if (lLocaSize >= 2 && nGlyphId <= (lLocaSize >> 1) - 1) // allow sentinel value to be accessed
1110 {
1111 const uint16 * pTableLoca = reinterpret_cast<const uint16 *>(pLoca);
1112 return (read(pTableLoca[nGlyphId]) << 1);
1113 }
1114 }
1115
1116 if (read(pTable->index_to_loc_format) == Sfnt::FontHeader::LongIndexLocFormat)
1117 { // loca entries are four bytes
1118 if (lLocaSize >= 4 && nGlyphId <= (lLocaSize >> 2) - 1)
1119 {
1120 const uint32 * pTableLoca = reinterpret_cast<const uint32 *>(pLoca);
1121 return read(pTableLoca[nGlyphId]);
1122 }
1123 }
1124
1125 // only get here if glyph id was bad
1126 //return -1;
1127 throw std::out_of_range("glyph id out of range for font");
1128 }
1129
1130 /*----------------------------------------------------------------------------------------------
1131 Return a pointer into the glyf table based on the given offset (from LocaLookup).
1132 Return NULL on error.
1133 ----------------------------------------------------------------------------------------------*/
GlyfLookup(const void * pGlyf,size_t nGlyfOffset)1134 void * GlyfLookup(const void * pGlyf, size_t nGlyfOffset)
1135 {
1136 const uint8 * pByte = reinterpret_cast<const uint8 *>(pGlyf);
1137 return const_cast<uint8 *>(pByte + nGlyfOffset);
1138 }
1139
1140 /*----------------------------------------------------------------------------------------------
1141 Get the bounding box coordinates for a simple glyf entry (non-composite)
1142 Return true if successful, false otherwise
1143 ----------------------------------------------------------------------------------------------*/
GlyfBox(const void * pSimpleGlyf,int & xMin,int & yMin,int & xMax,int & yMax)1144 bool GlyfBox(const void * pSimpleGlyf, int & xMin, int & yMin,
1145 int & xMax, int & yMax)
1146 {
1147 const Sfnt::Glyph * pGlyph = reinterpret_cast<const Sfnt::Glyph *>(pSimpleGlyf);
1148
1149 xMin = read(pGlyph->x_min);
1150 yMin = read(pGlyph->y_min);
1151 xMax = read(pGlyph->x_max);
1152 yMax = read(pGlyph->y_max);
1153
1154 return true;
1155 }
1156
1157 /*----------------------------------------------------------------------------------------------
1158 Return the number of contours for a simple glyf entry (non-composite)
1159 Returning -1 means this is a composite glyph
1160 ----------------------------------------------------------------------------------------------*/
GlyfContourCount(const void * pSimpleGlyf)1161 int GlyfContourCount(const void * pSimpleGlyf)
1162 {
1163 const Sfnt::Glyph * pGlyph = reinterpret_cast<const Sfnt::Glyph *>(pSimpleGlyf);
1164 return read(pGlyph->number_of_contours); // -1 means composite glyph
1165 }
1166
1167 /*----------------------------------------------------------------------------------------------
1168 Get the point numbers for the end points of the glyph contours for a simple
1169 glyf entry (non-composite).
1170 cnPointsTotal - count of contours from GlyfContourCount(); (same as number of end points)
1171 prgnContourEndPoints - should point to a buffer large enough to hold cnPoints integers
1172 cnPoints - count of points placed in above range
1173 Return true if successful, false otherwise.
1174 False could indicate a multi-level composite glyphs.
1175 ----------------------------------------------------------------------------------------------*/
GlyfContourEndPoints(const void * pSimpleGlyf,int * prgnContourEndPoint,int cnPointsTotal,int & cnPoints)1176 bool GlyfContourEndPoints(const void * pSimpleGlyf, int * prgnContourEndPoint,
1177 int cnPointsTotal, int & cnPoints)
1178 {
1179 const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
1180
1181 int cContours = read(pGlyph->number_of_contours);
1182 if (cContours < 0)
1183 return false; // this method isn't supposed handle composite glyphs
1184
1185 for (int i = 0; i < cContours && i < cnPointsTotal; i++)
1186 {
1187 prgnContourEndPoint[i] = read(pGlyph->end_pts_of_contours[i]);
1188 }
1189
1190 cnPoints = cContours;
1191 return true;
1192 }
1193
1194 /*----------------------------------------------------------------------------------------------
1195 Get the points for a simple glyf entry (non-composite)
1196 cnPointsTotal - count of points from largest end point obtained from GlyfContourEndPoints
1197 prgnX & prgnY - should point to buffers large enough to hold cnPointsTotal integers
1198 The ranges are parallel so that coordinates for point(n) are found at offset n in both
1199 ranges. This is raw point data with relative coordinates.
1200 prgbFlag - should point to a buffer a large enough to hold cnPointsTotal bytes
1201 This range is parallel to the prgnX & prgnY
1202 cnPoints - count of points placed in above ranges
1203 Return true if successful, false otherwise.
1204 False could indicate a composite glyph
1205 TODO: implement
1206 ----------------------------------------------------------------------------------------------*/
GlyfPoints(const void * pSimpleGlyf,int * prgnX,int * prgnY,char * prgbFlag,int cnPointsTotal,int & cnPoints)1207 bool GlyfPoints(const void * pSimpleGlyf, int * prgnX, int * prgnY,
1208 char * prgbFlag, int cnPointsTotal, int & cnPoints)
1209 {
1210 using namespace Sfnt;
1211
1212 const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
1213 int cContours = read(pGlyph->number_of_contours);
1214 // return false for composite glyph
1215 if (cContours <= 0)
1216 return false;
1217 int cPts = read(pGlyph->end_pts_of_contours[cContours - 1]) + 1;
1218 if (cPts > cnPointsTotal)
1219 return false;
1220
1221 // skip over bounding box data & point to byte count of instructions (hints)
1222 const uint8 * pbGlyph = reinterpret_cast<const uint8 *>
1223 (&pGlyph->end_pts_of_contours[cContours]);
1224
1225 // skip over hints & point to first flag
1226 int cbHints = read(*(uint16 *)pbGlyph);
1227 pbGlyph += sizeof(uint16);
1228 pbGlyph += cbHints;
1229
1230 // load flags & point to first x coordinate
1231 int iFlag = 0;
1232 while (iFlag < cPts)
1233 {
1234 if (!(*pbGlyph & SimpleGlyph::Repeat))
1235 { // flag isn't repeated
1236 prgbFlag[iFlag] = (char)*pbGlyph;
1237 pbGlyph++;
1238 iFlag++;
1239 }
1240 else
1241 { // flag is repeated; count specified by next byte
1242 char chFlag = (char)*pbGlyph;
1243 pbGlyph++;
1244 int cFlags = (int)*pbGlyph;
1245 pbGlyph++;
1246 prgbFlag[iFlag] = chFlag;
1247 iFlag++;
1248 for (int i = 0; i < cFlags; i++)
1249 {
1250 prgbFlag[iFlag + i] = chFlag;
1251 }
1252 iFlag += cFlags;
1253 }
1254 }
1255 if (iFlag != cPts)
1256 return false;
1257
1258 // load x coordinates
1259 iFlag = 0;
1260 while (iFlag < cPts)
1261 {
1262 if (prgbFlag[iFlag] & SimpleGlyph::XShort)
1263 {
1264 prgnX[iFlag] = *pbGlyph;
1265 if (!(prgbFlag[iFlag] & SimpleGlyph::XIsPos))
1266 {
1267 prgnX[iFlag] = -prgnX[iFlag];
1268 }
1269 pbGlyph++;
1270 }
1271 else
1272 {
1273 if (prgbFlag[iFlag] & SimpleGlyph::XIsSame)
1274 {
1275 prgnX[iFlag] = 0;
1276 // do NOT increment pbGlyph
1277 }
1278 else
1279 {
1280 prgnX[iFlag] = read(*(int16 *)pbGlyph);
1281 pbGlyph += sizeof(int16);
1282 }
1283 }
1284 iFlag++;
1285 }
1286
1287 // load y coordinates
1288 iFlag = 0;
1289 while (iFlag < cPts)
1290 {
1291 if (prgbFlag[iFlag] & SimpleGlyph::YShort)
1292 {
1293 prgnY[iFlag] = *pbGlyph;
1294 if (!(prgbFlag[iFlag] & SimpleGlyph::YIsPos))
1295 {
1296 prgnY[iFlag] = -prgnY[iFlag];
1297 }
1298 pbGlyph++;
1299 }
1300 else
1301 {
1302 if (prgbFlag[iFlag] & SimpleGlyph::YIsSame)
1303 {
1304 prgnY[iFlag] = 0;
1305 // do NOT increment pbGlyph
1306 }
1307 else
1308 {
1309 prgnY[iFlag] = read(*(int16 *)pbGlyph);
1310 pbGlyph += sizeof(int16);
1311 }
1312 }
1313 iFlag++;
1314 }
1315
1316 cnPoints = cPts;
1317 return true;
1318 }
1319
1320 /*----------------------------------------------------------------------------------------------
1321 Fill prgnCompId with the component Glyph IDs from pSimpleGlyf.
1322 Client must allocate space before calling.
1323 pSimpleGlyf - assumed to point to a composite glyph
1324 cCompIdTotal - the number of elements in prgnCompId
1325 cCompId - the total number of Glyph IDs stored in prgnCompId
1326 Return true if successful, false otherwise
1327 False could indicate a non-composite glyph or the input array was not big enough
1328 ----------------------------------------------------------------------------------------------*/
GetComponentGlyphIds(const void * pSimpleGlyf,int * prgnCompId,size_t cnCompIdTotal,size_t & cnCompId)1329 bool GetComponentGlyphIds(const void * pSimpleGlyf, int * prgnCompId,
1330 size_t cnCompIdTotal, size_t & cnCompId)
1331 {
1332 using namespace Sfnt;
1333
1334 if (GlyfContourCount(pSimpleGlyf) >= 0)
1335 return false;
1336
1337 const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
1338 // for a composite glyph, the special data begins here
1339 const uint8 * pbGlyph = reinterpret_cast<const uint8 *>(&pGlyph->end_pts_of_contours[0]);
1340
1341 uint16 GlyphFlags;
1342 size_t iCurrentComp = 0;
1343 do
1344 {
1345 GlyphFlags = read(*((uint16 *)pbGlyph));
1346 pbGlyph += sizeof(uint16);
1347 prgnCompId[iCurrentComp++] = read(*((uint16 *)pbGlyph));
1348 pbGlyph += sizeof(uint16);
1349 if (iCurrentComp >= cnCompIdTotal)
1350 return false;
1351 int nOffset = 0;
1352 nOffset += GlyphFlags & CompoundGlyph::Arg1Arg2Words ? 4 : 2;
1353 nOffset += GlyphFlags & CompoundGlyph::HaveScale ? 2 : 0;
1354 nOffset += GlyphFlags & CompoundGlyph::HaveXAndYScale ? 4 : 0;
1355 nOffset += GlyphFlags & CompoundGlyph::HaveTwoByTwo ? 8 : 0;
1356 pbGlyph += nOffset;
1357 } while (GlyphFlags & CompoundGlyph::MoreComponents);
1358
1359 cnCompId = iCurrentComp;
1360
1361 return true;
1362 }
1363
1364 /*----------------------------------------------------------------------------------------------
1365 Return info on how a component glyph is to be placed
1366 pSimpleGlyph - assumed to point to a composite glyph
1367 nCompId - glyph id for component of interest
1368 bOffset - if true, a & b are the x & y offsets for this component
1369 if false, b is the point on this component that is attaching to point a on the
1370 preceding glyph
1371 Return true if successful, false otherwise
1372 False could indicate a non-composite glyph or that component wasn't found
1373 ----------------------------------------------------------------------------------------------*/
GetComponentPlacement(const void * pSimpleGlyf,int nCompId,bool fOffset,int & a,int & b)1374 bool GetComponentPlacement(const void * pSimpleGlyf, int nCompId,
1375 bool fOffset, int & a, int & b)
1376 {
1377 using namespace Sfnt;
1378
1379 if (GlyfContourCount(pSimpleGlyf) >= 0)
1380 return false;
1381
1382 const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
1383 // for a composite glyph, the special data begins here
1384 const uint8 * pbGlyph = reinterpret_cast<const uint8 *>(&pGlyph->end_pts_of_contours[0]);
1385
1386 uint16 GlyphFlags;
1387 do
1388 {
1389 GlyphFlags = read(*((uint16 *)pbGlyph));
1390 pbGlyph += sizeof(uint16);
1391 if (read(*((uint16 *)pbGlyph)) == nCompId)
1392 {
1393 pbGlyph += sizeof(uint16); // skip over glyph id of component
1394 fOffset = (GlyphFlags & CompoundGlyph::ArgsAreXYValues) == CompoundGlyph::ArgsAreXYValues;
1395
1396 if (GlyphFlags & CompoundGlyph::Arg1Arg2Words )
1397 {
1398 a = read(*(int16 *)pbGlyph);
1399 pbGlyph += sizeof(int16);
1400 b = read(*(int16 *)pbGlyph);
1401 pbGlyph += sizeof(int16);
1402 }
1403 else
1404 { // args are signed bytes
1405 a = *pbGlyph++;
1406 b = *pbGlyph++;
1407 }
1408 return true;
1409 }
1410 pbGlyph += sizeof(uint16); // skip over glyph id of component
1411 int nOffset = 0;
1412 nOffset += GlyphFlags & CompoundGlyph::Arg1Arg2Words ? 4 : 2;
1413 nOffset += GlyphFlags & CompoundGlyph::HaveScale ? 2 : 0;
1414 nOffset += GlyphFlags & CompoundGlyph::HaveXAndYScale ? 4 : 0;
1415 nOffset += GlyphFlags & CompoundGlyph::HaveTwoByTwo ? 8 : 0;
1416 pbGlyph += nOffset;
1417 } while (GlyphFlags & CompoundGlyph::MoreComponents);
1418
1419 // didn't find requested component
1420 fOffset = true;
1421 a = 0;
1422 b = 0;
1423 return false;
1424 }
1425
1426 /*----------------------------------------------------------------------------------------------
1427 Return info on how a component glyph is to be transformed
1428 pSimpleGlyph - assumed to point to a composite glyph
1429 nCompId - glyph id for component of interest
1430 flt11, flt11, flt11, flt11 - a 2x2 matrix giving the transform
1431 bTransOffset - whether to transform the offset from above method
1432 The spec is unclear about the meaning of this flag
1433 Currently - initialize to true for MS rasterizer and false for Mac rasterizer, then
1434 on return it will indicate whether transform should apply to offset (MSDN CD 10/99)
1435 Return true if successful, false otherwise
1436 False could indicate a non-composite glyph or that component wasn't found
1437 ----------------------------------------------------------------------------------------------*/
GetComponentTransform(const void * pSimpleGlyf,int nCompId,float & flt11,float & flt12,float & flt21,float & flt22,bool & fTransOffset)1438 bool GetComponentTransform(const void * pSimpleGlyf, int nCompId,
1439 float & flt11, float & flt12, float & flt21, float & flt22,
1440 bool & fTransOffset)
1441 {
1442 using namespace Sfnt;
1443
1444 if (GlyfContourCount(pSimpleGlyf) >= 0)
1445 return false;
1446
1447 const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
1448 // for a composite glyph, the special data begins here
1449 const uint8 * pbGlyph = reinterpret_cast<const uint8 *>(&pGlyph->end_pts_of_contours[0]);
1450
1451 uint16 GlyphFlags;
1452 do
1453 {
1454 GlyphFlags = read(*((uint16 *)pbGlyph));
1455 pbGlyph += sizeof(uint16);
1456 if (read(*((uint16 *)pbGlyph)) == nCompId)
1457 {
1458 pbGlyph += sizeof(uint16); // skip over glyph id of component
1459 pbGlyph += GlyphFlags & CompoundGlyph::Arg1Arg2Words ? 4 : 2; // skip over placement data
1460
1461 if (fTransOffset) // MS rasterizer
1462 fTransOffset = !(GlyphFlags & CompoundGlyph::UnscaledOffset);
1463 else // Apple rasterizer
1464 fTransOffset = (GlyphFlags & CompoundGlyph::ScaledOffset) != 0;
1465
1466 if (GlyphFlags & CompoundGlyph::HaveScale)
1467 {
1468 flt11 = fixed_to_float<14>(read(*(uint16 *)pbGlyph));
1469 pbGlyph += sizeof(uint16);
1470 flt12 = 0;
1471 flt21 = 0;
1472 flt22 = flt11;
1473 }
1474 else if (GlyphFlags & CompoundGlyph::HaveXAndYScale)
1475 {
1476 flt11 = fixed_to_float<14>(read(*(uint16 *)pbGlyph));
1477 pbGlyph += sizeof(uint16);
1478 flt12 = 0;
1479 flt21 = 0;
1480 flt22 = fixed_to_float<14>(read(*(uint16 *)pbGlyph));
1481 pbGlyph += sizeof(uint16);
1482 }
1483 else if (GlyphFlags & CompoundGlyph::HaveTwoByTwo)
1484 {
1485 flt11 = fixed_to_float<14>(read(*(uint16 *)pbGlyph));
1486 pbGlyph += sizeof(uint16);
1487 flt12 = fixed_to_float<14>(read(*(uint16 *)pbGlyph));
1488 pbGlyph += sizeof(uint16);
1489 flt21 = fixed_to_float<14>(read(*(uint16 *)pbGlyph));
1490 pbGlyph += sizeof(uint16);
1491 flt22 = fixed_to_float<14>(read(*(uint16 *)pbGlyph));
1492 pbGlyph += sizeof(uint16);
1493 }
1494 else
1495 { // identity transform
1496 flt11 = 1.0;
1497 flt12 = 0.0;
1498 flt21 = 0.0;
1499 flt22 = 1.0;
1500 }
1501 return true;
1502 }
1503 pbGlyph += sizeof(uint16); // skip over glyph id of component
1504 int nOffset = 0;
1505 nOffset += GlyphFlags & CompoundGlyph::Arg1Arg2Words ? 4 : 2;
1506 nOffset += GlyphFlags & CompoundGlyph::HaveScale ? 2 : 0;
1507 nOffset += GlyphFlags & CompoundGlyph::HaveXAndYScale ? 4 : 0;
1508 nOffset += GlyphFlags & CompoundGlyph::HaveTwoByTwo ? 8 : 0;
1509 pbGlyph += nOffset;
1510 } while (GlyphFlags & CompoundGlyph::MoreComponents);
1511
1512 // didn't find requested component
1513 fTransOffset = false;
1514 flt11 = 1;
1515 flt12 = 0;
1516 flt21 = 0;
1517 flt22 = 1;
1518 return false;
1519 }
1520
1521 /*----------------------------------------------------------------------------------------------
1522 Return a pointer into the glyf table based on the given tables and Glyph ID
1523 Since this method doesn't check for spaces, it is good to call IsSpace before using it.
1524 Return NULL on error
1525 ----------------------------------------------------------------------------------------------*/
GlyfLookup(gr::gid16 nGlyphId,const void * pGlyf,const void * pLoca,size_t lLocaSize,const void * pHead)1526 void * GlyfLookup(gr::gid16 nGlyphId, const void * pGlyf, const void * pLoca,
1527 size_t lLocaSize, const void * pHead)
1528 {
1529 // test for valid glyph id
1530 // CheckTable verifies the index_to_loc_format is valid
1531
1532 const Sfnt::FontHeader * pTable
1533 = reinterpret_cast<const Sfnt::FontHeader *>(pHead);
1534
1535 if (read(pTable->index_to_loc_format) == Sfnt::FontHeader::ShortIndexLocFormat)
1536 { // loca entries are two bytes (and have been divided by two)
1537 if (nGlyphId >= (lLocaSize >> 1) - 1) // don't allow nGlyphId to access sentinel
1538 throw std::out_of_range("glyph id out of range for font");
1539 }
1540 if (read(pTable->index_to_loc_format) == Sfnt::FontHeader::LongIndexLocFormat)
1541 { // loca entries are four bytes
1542 if (nGlyphId >= (lLocaSize >> 2) - 1)
1543 throw std::out_of_range("glyph id out of range for font");
1544 }
1545
1546 long lGlyfOffset = LocaLookup(nGlyphId, pLoca, lLocaSize, pHead);
1547 void * pSimpleGlyf = GlyfLookup(pGlyf, lGlyfOffset); // invalid loca offset returns null
1548 return pSimpleGlyf;
1549 }
1550
1551 /*----------------------------------------------------------------------------------------------
1552 Determine if a particular Glyph ID has any data in the glyf table. If it is white space,
1553 there will be no glyf data, though there will be metric data in hmtx, etc.
1554 ----------------------------------------------------------------------------------------------*/
IsSpace(gr::gid16 nGlyphId,const void * pLoca,size_t lLocaSize,const void * pHead)1555 bool IsSpace(gr::gid16 nGlyphId, const void * pLoca, size_t lLocaSize, const void * pHead)
1556 {
1557 size_t lGlyfOffset = LocaLookup(nGlyphId, pLoca, lLocaSize, pHead);
1558
1559 // the +1 should always work because there is a sentinel value at the end of the loca table
1560 size_t lNextGlyfOffset = LocaLookup(nGlyphId + 1, pLoca, lLocaSize, pHead);
1561
1562 return (lNextGlyfOffset - lGlyfOffset) == 0;
1563 }
1564
1565 /*----------------------------------------------------------------------------------------------
1566 Determine if a particular Glyph ID is a multi-level composite.
1567 ----------------------------------------------------------------------------------------------*/
IsDeepComposite(gr::gid16 nGlyphId,const void * pGlyf,const void * pLoca,long lLocaSize,const void * pHead)1568 bool IsDeepComposite(gr::gid16 nGlyphId, const void * pGlyf, const void * pLoca,
1569 long lLocaSize, const void * pHead)
1570 {
1571 if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) {return false;}
1572
1573 void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lLocaSize, pHead);
1574 if (pSimpleGlyf == NULL)
1575 return false; // no way to really indicate an error occured here
1576
1577 if (GlyfContourCount(pSimpleGlyf) >= 0)
1578 return false;
1579
1580 int rgnCompId[kMaxGlyphComponents]; // assumes only a limited number of glyph components
1581 size_t cCompIdTotal = kMaxGlyphComponents;
1582 size_t cCompId = 0;
1583
1584 if (!GetComponentGlyphIds(pSimpleGlyf, rgnCompId, cCompIdTotal, cCompId))
1585 return false;
1586
1587 for (size_t i = 0; i < cCompId; i++)
1588 {
1589 pSimpleGlyf = GlyfLookup(static_cast<gr::gid16>(rgnCompId[i]),
1590 pGlyf, pLoca, lLocaSize, pHead);
1591 if (pSimpleGlyf == NULL) {return false;}
1592
1593 if (GlyfContourCount(pSimpleGlyf) < 0)
1594 return true;
1595 }
1596
1597 return false;
1598 }
1599
1600 /*----------------------------------------------------------------------------------------------
1601 Get the bounding box coordinates based on the given tables and Glyph ID
1602 Handles both simple and composite glyphs.
1603 Return true if successful, false otherwise. On false, all point values will be INT_MIN
1604 False may indicate a white space glyph
1605 ----------------------------------------------------------------------------------------------*/
GlyfBox(gr::gid16 nGlyphId,const void * pGlyf,const void * pLoca,size_t lLocaSize,const void * pHead,int & xMin,int & yMin,int & xMax,int & yMax)1606 bool GlyfBox(gr::gid16 nGlyphId, const void * pGlyf, const void * pLoca,
1607 size_t lLocaSize, const void * pHead, int & xMin, int & yMin, int & xMax, int & yMax)
1608 {
1609 xMin = yMin = xMax = yMax = INT_MIN;
1610
1611 if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) {return false;}
1612
1613 void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lLocaSize, pHead);
1614 if (pSimpleGlyf == NULL) {return false;}
1615
1616 return GlyfBox(pSimpleGlyf, xMin, yMin, xMax, yMax);
1617 }
1618
1619 /*----------------------------------------------------------------------------------------------
1620 Get the number of contours based on the given tables and Glyph ID
1621 Handles both simple and composite glyphs.
1622 Return true if successful, false otherwise. On false, cnContours will be INT_MIN
1623 False may indicate a white space glyph or a multi-level composite glyph.
1624 ----------------------------------------------------------------------------------------------*/
GlyfContourCount(gr::gid16 nGlyphId,const void * pGlyf,const void * pLoca,size_t lLocaSize,const void * pHead,size_t & cnContours)1625 bool GlyfContourCount(gr::gid16 nGlyphId, const void * pGlyf, const void * pLoca,
1626 size_t lLocaSize, const void * pHead, size_t & cnContours)
1627 {
1628 cnContours = static_cast<size_t>(INT_MIN);
1629
1630 if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) {return false;}
1631
1632 void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lLocaSize, pHead);
1633 if (pSimpleGlyf == NULL) {return false;}
1634
1635 int cRtnContours = GlyfContourCount(pSimpleGlyf);
1636 if (cRtnContours >= 0)
1637 {
1638 cnContours = size_t(cRtnContours);
1639 return true;
1640 }
1641
1642 //handle composite glyphs
1643
1644 int rgnCompId[kMaxGlyphComponents]; // assumes no glyph will be made of more than 8 components
1645 size_t cCompIdTotal = kMaxGlyphComponents;
1646 size_t cCompId = 0;
1647
1648 if (!GetComponentGlyphIds(pSimpleGlyf, rgnCompId, cCompIdTotal, cCompId))
1649 return false;
1650
1651 cRtnContours = 0;
1652 int cTmp = 0;
1653 for (size_t i = 0; i < cCompId; i++)
1654 {
1655 if (IsSpace(static_cast<gr::gid16>(rgnCompId[i]), pLoca, lLocaSize, pHead)) {return false;}
1656 pSimpleGlyf = GlyfLookup(static_cast<gr::gid16>(rgnCompId[i]),
1657 pGlyf, pLoca, lLocaSize, pHead);
1658 if (pSimpleGlyf == 0) {return false;}
1659 // return false on multi-level composite
1660 if ((cTmp = GlyfContourCount(pSimpleGlyf)) < 0)
1661 return false;
1662 cRtnContours += cTmp;
1663 }
1664
1665 cnContours = size_t(cRtnContours);
1666 return true;
1667 }
1668
1669 /*----------------------------------------------------------------------------------------------
1670 Get the point numbers for the end points of the glyph contours based on the given tables
1671 and Glyph ID
1672 Handles both simple and composite glyphs.
1673 cnPoints - count of contours from GlyfContourCount (same as number of end points)
1674 prgnContourEndPoints - should point to a buffer large enough to hold cnPoints integers
1675 Return true if successful, false otherwise. On false, all end points are INT_MIN
1676 False may indicate a white space glyph or a multi-level composite glyph.
1677 ----------------------------------------------------------------------------------------------*/
GlyfContourEndPoints(gr::gid16 nGlyphId,const void * pGlyf,const void * pLoca,size_t lLocaSize,const void * pHead,int * prgnContourEndPoint,size_t cnPoints)1678 bool GlyfContourEndPoints(gr::gid16 nGlyphId, const void * pGlyf, const void * pLoca,
1679 size_t lLocaSize, const void * pHead,
1680 int * prgnContourEndPoint, size_t cnPoints)
1681 {
1682 std::fill_n(prgnContourEndPoint, cnPoints, INT_MIN);
1683
1684 if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) {return false;}
1685
1686 void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lLocaSize, pHead);
1687 if (pSimpleGlyf == NULL) {return false;}
1688
1689 int cContours = GlyfContourCount(pSimpleGlyf);
1690 int cActualPts = 0;
1691 if (cContours > 0)
1692 return GlyfContourEndPoints(pSimpleGlyf, prgnContourEndPoint, cnPoints, cActualPts);
1693
1694 // handle composite glyphs
1695
1696 int rgnCompId[kMaxGlyphComponents]; // assumes no glyph will be made of more than 8 components
1697 size_t cCompIdTotal = kMaxGlyphComponents;
1698 size_t cCompId = 0;
1699
1700 if (!GetComponentGlyphIds(pSimpleGlyf, rgnCompId, cCompIdTotal, cCompId))
1701 return false;
1702
1703 int * prgnCurrentEndPoint = prgnContourEndPoint;
1704 int cCurrentPoints = cnPoints;
1705 int nPrevPt = 0;
1706 for (size_t i = 0; i < cCompId; i++)
1707 {
1708 if (IsSpace(static_cast<gr::gid16>(rgnCompId[i]), pLoca, lLocaSize, pHead)) {return false;}
1709 pSimpleGlyf = GlyfLookup(static_cast<gr::gid16>(rgnCompId[i]), pGlyf, pLoca, lLocaSize, pHead);
1710 if (pSimpleGlyf == NULL) {return false;}
1711 // returns false on multi-level composite
1712 if (!GlyfContourEndPoints(pSimpleGlyf, prgnCurrentEndPoint, cCurrentPoints, cActualPts))
1713 return false;
1714 // points in composite are numbered sequentially as components are added
1715 // must adjust end point numbers for new point numbers
1716 for (int j = 0; j < cActualPts; j++)
1717 prgnCurrentEndPoint[j] += nPrevPt;
1718 nPrevPt = prgnCurrentEndPoint[cActualPts - 1] + 1;
1719
1720 prgnCurrentEndPoint += cActualPts;
1721 cCurrentPoints -= cActualPts;
1722 }
1723
1724 return true;
1725 }
1726
1727 /*----------------------------------------------------------------------------------------------
1728 Get the points for a glyph based on the given tables and Glyph ID
1729 Handles both simple and composite glyphs.
1730 cnPoints - count of points from largest end point obtained from GlyfContourEndPoints
1731 prgnX & prgnY - should point to buffers large enough to hold cnPoints integers
1732 The ranges are parallel so that coordinates for point(n) are found at offset n in
1733 both ranges. These points are in absolute coordinates.
1734 prgfOnCurve - should point to a buffer a large enough to hold cnPoints bytes (bool)
1735 This range is parallel to the prgnX & prgnY
1736 Return true if successful, false otherwise. On false, all points may be INT_MIN
1737 False may indicate a white space glyph, a multi-level composite, or a corrupt font
1738 // TODO: doesn't support composite glyphs whose components are themselves components
1739 It's not clear from the TTF spec when the transforms should be applied. Should the
1740 transform be done before or after attachment point calcs? (current code - before)
1741 Should the transform be applied to other offsets? (currently - no; however commented
1742 out code is in place so that if CompoundGlyph::UnscaledOffset on the MS rasterizer is
1743 clear (typical) then yes, and if CompoundGlyph::ScaledOffset on the Apple rasterizer is
1744 clear (typical?) then no). See GetComponentTransform.
1745 It's also unclear where point numbering with attachment poinst starts
1746 (currently - first point number is relative to whole glyph, second point number is
1747 relative to current glyph).
1748 ----------------------------------------------------------------------------------------------*/
GlyfPoints(gr::gid16 nGlyphId,const void * pGlyf,const void * pLoca,size_t lLocaSize,const void * pHead,const int *,size_t,int * prgnX,int * prgnY,bool * prgfOnCurve,size_t cnPoints)1749 bool GlyfPoints(gr::gid16 nGlyphId, const void * pGlyf,
1750 const void * pLoca, size_t lLocaSize, const void * pHead,
1751 const int * /*prgnContourEndPoint*/, size_t /*cnEndPoints*/,
1752 int * prgnX, int * prgnY, bool * prgfOnCurve, size_t cnPoints)
1753 {
1754 std::fill_n(prgnX, cnPoints, INT_MAX);
1755 std::fill_n(prgnY, cnPoints, INT_MAX);
1756
1757 if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead))
1758 return false;
1759
1760 void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lLocaSize, pHead);
1761 if (pSimpleGlyf == NULL)
1762 return false;
1763
1764 int cContours = GlyfContourCount(pSimpleGlyf);
1765 int cActualPts;
1766 if (cContours > 0)
1767 {
1768 if (!GlyfPoints(pSimpleGlyf, prgnX, prgnY, (char *)prgfOnCurve, cnPoints, cActualPts))
1769 return false;
1770 CalcAbsolutePoints(prgnX, prgnY, cnPoints);
1771 SimplifyFlags((char *)prgfOnCurve, cnPoints);
1772 return true;
1773 }
1774
1775 // handle composite glyphs
1776 int rgnCompId[kMaxGlyphComponents]; // assumes no glyph will be made of more than 8 components
1777 size_t cCompIdTotal = kMaxGlyphComponents;
1778 size_t cCompId = 0;
1779
1780 // this will fail if there are more components than there is room for
1781 if (!GetComponentGlyphIds(pSimpleGlyf, rgnCompId, cCompIdTotal, cCompId))
1782 return false;
1783
1784 int * prgnCurrentX = prgnX;
1785 int * prgnCurrentY = prgnY;
1786 char * prgbCurrentFlag = (char *)prgfOnCurve; // converting bool to char should be safe
1787 int cCurrentPoints = cnPoints;
1788 bool fOffset = true, fTransOff = true;
1789 int a, b;
1790 float flt11, flt12, flt21, flt22;
1791 // int * prgnPrevX = prgnX; // in case first att pt number relative to preceding glyph
1792 // int * prgnPrevY = prgnY;
1793 for (size_t i = 0; i < cCompId; i++)
1794 {
1795 if (IsSpace(static_cast<gr::gid16>(rgnCompId[i]), pLoca, lLocaSize, pHead)) {return false;}
1796 void * pCompGlyf = GlyfLookup(static_cast<gr::gid16>(rgnCompId[i]), pGlyf, pLoca, lLocaSize, pHead);
1797 if (pCompGlyf == NULL) {return false;}
1798 // returns false on multi-level composite
1799 if (!GlyfPoints(pCompGlyf, prgnCurrentX, prgnCurrentY, prgbCurrentFlag,
1800 cCurrentPoints, cActualPts))
1801 return false;
1802 if (!GetComponentPlacement(pSimpleGlyf, rgnCompId[i], fOffset, a, b))
1803 return false;
1804 if (!GetComponentTransform(pSimpleGlyf, rgnCompId[i],
1805 flt11, flt12, flt21, flt22, fTransOff))
1806 return false;
1807 bool fIdTrans = flt11 == 1.0 && flt12 == 0.0 && flt21 == 0.0 && flt22 == 1.0;
1808
1809 // convert points to absolute coordinates
1810 // do before transform and attachment point placement are applied
1811 CalcAbsolutePoints(prgnCurrentX, prgnCurrentY, cActualPts);
1812
1813 // apply transform - see main method note above
1814 // do before attachment point calcs
1815 if (!fIdTrans)
1816 for (int j = 0; j < cActualPts; j++)
1817 {
1818 int x = prgnCurrentX[j]; // store before transform applied
1819 int y = prgnCurrentY[j];
1820 prgnCurrentX[j] = (int)(x * flt11 + y * flt12);
1821 prgnCurrentY[j] = (int)(x * flt21 + y * flt22);
1822 }
1823
1824 // apply placement - see main method note above
1825 int nXOff, nYOff;
1826 if (fOffset) // explicit x & y offsets
1827 {
1828 /* ignore fTransOff for now
1829 if (fTransOff && !fIdTrans)
1830 { // transform x & y offsets
1831 nXOff = (int)(a * flt11 + b * flt12);
1832 nYOff = (int)(a * flt21 + b * flt22);
1833 }
1834 else */
1835 { // don't transform offset
1836 nXOff = a;
1837 nYOff = b;
1838 }
1839 }
1840 else // attachment points
1841 { // in case first point is relative to preceding glyph and second relative to current
1842 // nXOff = prgnPrevX[a] - prgnCurrentX[b];
1843 // nYOff = prgnPrevY[a] - prgnCurrentY[b];
1844 // first point number relative to whole composite, second relative to current glyph
1845 nXOff = prgnX[a] - prgnCurrentX[b];
1846 nYOff = prgnY[a] - prgnCurrentY[b];
1847 }
1848 for (int j = 0; j < cActualPts; j++)
1849 {
1850 prgnCurrentX[j] += nXOff;
1851 prgnCurrentY[j] += nYOff;
1852 }
1853
1854 // prgnPrevX = prgnCurrentX;
1855 // prgnPrevY = prgnCurrentY;
1856 prgnCurrentX += cActualPts;
1857 prgnCurrentY += cActualPts;
1858 prgbCurrentFlag += cActualPts;
1859 cCurrentPoints -= cActualPts;
1860 }
1861
1862 SimplifyFlags((char *)prgfOnCurve, cnPoints);
1863
1864 return true;
1865 }
1866
1867 /*----------------------------------------------------------------------------------------------
1868 Simplify the meaning of flags to just indicate whether point is on-curve or off-curve
1869 ---------------------------------------------------------------------------------------------*/
SimplifyFlags(char * prgbFlags,int cnPoints)1870 bool SimplifyFlags(char * prgbFlags, int cnPoints)
1871 {
1872 for (int i = 0; i < cnPoints; i++)
1873 prgbFlags[i] = static_cast<char>(prgbFlags[i] & Sfnt::SimpleGlyph::OnCurve);
1874 return true;
1875 }
1876
1877 /*----------------------------------------------------------------------------------------------
1878 Convert relative point coordinates to absolute coordinates
1879 Points are stored in the font such that they are offsets from one another except for the
1880 first point of a glyph.
1881 ---------------------------------------------------------------------------------------------*/
CalcAbsolutePoints(int * prgnX,int * prgnY,int cnPoints)1882 bool CalcAbsolutePoints(int * prgnX, int * prgnY, int cnPoints)
1883 {
1884 int nX = prgnX[0];
1885 int nY = prgnY[0];
1886 for (int i = 1; i < cnPoints; i++)
1887 {
1888 prgnX[i] += nX;
1889 nX = prgnX[i];
1890 prgnY[i] += nY;
1891 nY = prgnY[i];
1892 }
1893
1894 return true;
1895 }
1896
1897 /*----------------------------------------------------------------------------------------------
1898 Convert a numerical table ID to a string containing the actual name of the table.
1899 Returns native order unsigned long.
1900 ---------------------------------------------------------------------------------------------*/
TableIdTag(const TableId tid)1901 gr::fontTableId32 TableIdTag(const TableId tid)
1902 {
1903 assert(sizeof(mapIdToTag) == sizeof(gr::fontTableId32) * ktiLast);
1904 assert(tid < ktiLast);
1905
1906 return mapIdToTag[tid];
1907 }
1908
1909 /*----------------------------------------------------------------------------------------------
1910 Return the length of the 'name' table in bytes.
1911 Currently used.
1912 ---------------------------------------------------------------------------------------------*/
1913 #if 0
1914 size_t NameTableLength(const gr::byte * pTable)
1915 {
1916 gr::byte * pb = (const_cast<gr::byte *>(pTable)) + 2; // skip format
1917 size_t cRecords = *pb++ << 8; cRecords += *pb++;
1918 int dbStringOffset0 = (*pb++) << 8; dbStringOffset0 += *pb++;
1919 int dbMaxStringOffset = 0;
1920 for (size_t irec = 0; irec < cRecords; irec++)
1921 {
1922 int nPlatform = (*pb++) << 8; nPlatform += *pb++;
1923 int nEncoding = (*pb++) << 8; nEncoding += *pb++;
1924 int nLanguage = (*pb++) << 8; nLanguage += *pb++;
1925 int nName = (*pb++) << 8; nName += *pb++;
1926 int cbStringLen = (*pb++) << 8; cbStringLen += *pb++;
1927 int dbStringOffset = (*pb++) << 8; dbStringOffset += *pb++;
1928 if (dbMaxStringOffset < dbStringOffset + cbStringLen)
1929 dbMaxStringOffset = dbStringOffset + cbStringLen;
1930 }
1931 return dbStringOffset0 + dbMaxStringOffset;
1932 }
1933 #endif
1934
1935 } // end of namespace TtfUtil
1936