TtfUtil.cpp (86268B)
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> 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ----------------------------------------------------------------------------------------------*/ 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 ---------------------------------------------------------------------------------------------*/ 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 ---------------------------------------------------------------------------------------------*/ 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