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