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