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