1 /* 2 * Copyright 2011 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ 18 #define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ 19 20 // type.h needs to be included first because of building issues on Windows 21 // Type aliases we delcare are defined in other headers and make the build 22 // fail otherwise. 23 #include "sfntly/port/type.h" 24 #include <vector> 25 #include <map> 26 27 #include "sfntly/port/refcount.h" 28 #include "sfntly/table/subtable.h" 29 #include "sfntly/table/subtable_container_table.h" 30 31 namespace sfntly { 32 33 // CMap subtable formats 34 struct CMapFormat { 35 enum { 36 kFormat0 = 0, 37 kFormat2 = 2, 38 kFormat4 = 4, 39 kFormat6 = 6, 40 kFormat8 = 8, 41 kFormat10 = 10, 42 kFormat12 = 12, 43 kFormat13 = 13, 44 kFormat14 = 14 45 }; 46 }; 47 48 // A CMap table 49 class CMapTable : public SubTableContainerTable, public RefCounted<CMapTable> { 50 public: 51 // CMapTable::CMapId 52 struct CMapId { 53 int32_t platform_id; 54 int32_t encoding_id; 55 bool operator==(const CMapId& obj) const { 56 return platform_id == obj.platform_id && encoding_id == obj.encoding_id; 57 } 58 }; 59 static CMapId WINDOWS_BMP; 60 static CMapId WINDOWS_UCS4; 61 static CMapId MAC_ROMAN; 62 63 // CMapTable::CMapIdComparator 64 class CMapIdComparator { 65 public: 66 bool operator()(const CMapId& lhs, const CMapId& rhs) const; 67 }; 68 69 // A filter on cmap 70 // CMapTable::CMapFilter 71 class CMapFilter { 72 public: 73 // Test on whether the cmap is acceptable or not 74 // @param cmap_id the id of the cmap 75 // @return true if the cmap is acceptable; false otherwise 76 virtual bool accept(const CMapId& cmap_id) const = 0; 77 // Make gcc -Wnon-virtual-dtor happy. ~CMapFilter()78 virtual ~CMapFilter() {} 79 }; 80 81 // Filters CMaps by CMapId to implement CMapTable::get() 82 // wanted_id is the CMap we'd like to find. 83 // We compare the current CMap to it either by equality (==) or using a 84 // comparator. 85 // CMapTable::CMapIdFilter 86 class CMapIdFilter : public CMapFilter { 87 public: 88 explicit CMapIdFilter(const CMapId wanted_id); 89 CMapIdFilter(const CMapId wanted_id, 90 const CMapIdComparator* comparator); ~CMapIdFilter()91 ~CMapIdFilter() {} 92 virtual bool accept(const CMapId& cmap_id) const; 93 private: 94 CMapIdFilter& operator=(const CMapIdFilter& that); 95 const CMapId wanted_id_; 96 const CMapIdComparator *comparator_; 97 }; 98 99 // The abstract base class for all cmaps. 100 // 101 // CMap equality is based on the equality of the (@link {@link CMapId} that 102 // defines the CMap. In the cmap table for a font there can only be one cmap 103 // with a given cmap id (pair of platform and encoding ids) no matter what the 104 // type of the cmap is. 105 // 106 // The cmap offers CharacterIterator to allow iteration over 107 // characters that are mapped by the cmap. This iteration mostly returns the 108 // characters mapped by the cmap. It will return all characters mapped by the 109 // cmap to anything but .notdef <b>but</b> it may return some that are not 110 // mapped or are mapped to .notdef. Various cmap tables provide ranges and 111 // such to describe characters for lookup but without going the full way to 112 // mapping to the glyph id it isn't always possible to tell if a character 113 // will end up with a valid glyph id. So, some of the characters returned from 114 // the Iterator may still end up pointing to the .notdef glyph. However, the 115 // number of such characters should be small in most cases with well designed 116 // cmaps. 117 class Builder; 118 class CMap : public SubTable { 119 public: 120 // CMapTable::CMap::Builder 121 class Builder : public SubTable::Builder { 122 public: 123 virtual ~Builder(); 124 125 CALLER_ATTACH static Builder* 126 GetBuilder(ReadableFontData* data, 127 int32_t offset, 128 const CMapId& cmap_id); 129 CALLER_ATTACH static Builder* 130 GetBuilder(int32_t format, 131 const CMapId& cmap_id); 132 133 // Note: yes, an object is returned on stack since it's small enough. cmap_id()134 virtual CMapId cmap_id() { return cmap_id_; } platform_id()135 virtual int32_t platform_id() { return cmap_id_.platform_id; } encoding_id()136 virtual int32_t encoding_id() { return cmap_id_.encoding_id; } format()137 virtual int32_t format() { return format_; } language()138 virtual int32_t language() { return language_; } set_language(int32_t language)139 virtual void set_language(int32_t language) { language_ = language; } 140 141 protected: 142 Builder(ReadableFontData* data, 143 int32_t format, 144 const CMapId& cmap_id); 145 Builder(WritableFontData* data, 146 int32_t format, 147 const CMapId& cmap_id); 148 149 virtual int32_t SubSerialize(WritableFontData* new_data); 150 virtual bool SubReadyToSerialize(); 151 virtual int32_t SubDataSizeToSerialize(); 152 virtual void SubDataSet(); 153 154 private: 155 int32_t format_; 156 CMapId cmap_id_; 157 int32_t language_; 158 159 friend class CMapTable::Builder; 160 }; 161 // Abstract CMap character iterator 162 // The fully qualified name is CMapTable::CMap::CharacterIterator 163 class CharacterIterator { 164 public: ~CharacterIterator()165 virtual ~CharacterIterator() {} 166 virtual bool HasNext() = 0; 167 // Returns -1 if there are no more characters to iterate through 168 // and exceptions are turned off 169 virtual int32_t Next() = 0; 170 171 protected: 172 // Use the CMap::Iterator method below instead of directly requesting 173 // a CharacterIterator. CharacterIterator()174 CharacterIterator() {} 175 }; 176 177 CMap(ReadableFontData* data, int32_t format, const CMapId& cmap_id); 178 virtual ~CMap(); 179 180 virtual CMap::CharacterIterator* Iterator() = 0; 181 format()182 virtual int32_t format() { return format_; } cmap_id()183 virtual CMapId cmap_id() { return cmap_id_; } platform_id()184 virtual int32_t platform_id() { return cmap_id_.platform_id; } encoding_id()185 virtual int32_t encoding_id() { return cmap_id_.encoding_id; } 186 187 // Get the language of the cmap. 188 // 189 // Note on the language field in 'cmap' subtables: The language field must 190 // be set to zero for all cmap subtables whose platform IDs are other than 191 // Macintosh (platform ID 1). For cmap subtables whose platform IDs are 192 // Macintosh, set this field to the Macintosh language ID of the cmap 193 // subtable plus one, or to zero if the cmap subtable is not 194 // language-specific. For example, a Mac OS Turkish cmap subtable must set 195 // this field to 18, since the Macintosh language ID for Turkish is 17. A 196 // Mac OS Roman cmap subtable must set this field to 0, since Mac OS Roman 197 // is not a language-specific encoding. 198 // 199 // @return the language id 200 virtual int32_t Language() = 0; 201 202 // Gets the glyph id for the character code provided. 203 // The character code provided must be in the encoding used by the cmap 204 // table. 205 virtual int32_t GlyphId(int32_t character) = 0; 206 207 private: 208 int32_t format_; 209 CMapId cmap_id_; 210 }; 211 typedef Ptr<CMap> CMapPtr; 212 typedef Ptr<CMap::Builder> CMapBuilderPtr; 213 typedef std::map<CMapId, CMapBuilderPtr, CMapIdComparator> CMapBuilderMap; 214 215 // A cmap format 0 sub table 216 class CMapFormat0 : public CMap, public RefCounted<CMapFormat0> { 217 public: 218 // The fully qualified name is CMapTable::CMapFormat0::Builder 219 class Builder : public CMap::Builder, 220 public RefCounted<Builder> { 221 public: 222 CALLER_ATTACH static Builder* NewInstance(ReadableFontData* data, 223 int32_t offset, 224 const CMapId& cmap_id); 225 CALLER_ATTACH static Builder* NewInstance(WritableFontData* data, 226 int32_t offset, 227 const CMapId& cmap_id); 228 CALLER_ATTACH static Builder* NewInstance(const CMapId& cmap_id); 229 virtual ~Builder(); 230 231 protected: 232 virtual CALLER_ATTACH FontDataTable* 233 SubBuildTable(ReadableFontData* data); 234 235 private: 236 // When creating a new CMapFormat0 Builder, use NewInstance instead of 237 // the constructors! This avoids a memory leak when slicing the FontData. 238 Builder(ReadableFontData* data, int32_t offset, const CMapId& cmap_id); 239 Builder(WritableFontData* data, int32_t offset, const CMapId& cmap_id); 240 Builder(const CMapId& cmap_id); 241 }; 242 243 // The fully qualified name is CMapTable::CMapFormat0::CharacterIterator 244 class CharacterIterator : public CMap::CharacterIterator { 245 public: 246 virtual ~CharacterIterator(); 247 virtual bool HasNext(); 248 virtual int32_t Next(); 249 250 private: 251 CharacterIterator(int32_t start, int32_t end); 252 friend class CMapFormat0; 253 int32_t character_, max_character_; 254 }; 255 256 virtual ~CMapFormat0(); 257 virtual int32_t Language(); 258 virtual int32_t GlyphId(int32_t character); 259 CMap::CharacterIterator* Iterator(); 260 261 private: 262 CMapFormat0(ReadableFontData* data, const CMapId& cmap_id); 263 }; 264 265 // A cmap format 2 sub table 266 // The format 2 cmap is used for multi-byte encodings such as SJIS, 267 // EUC-JP/KR/CN, Big5, etc. 268 class CMapFormat2 : public CMap, public RefCounted<CMapFormat2> { 269 public: 270 // CMapTable::CMapFormat2::Builder 271 class Builder : public CMap::Builder, 272 public RefCounted<Builder> { 273 public: 274 Builder(ReadableFontData* data, 275 int32_t offset, 276 const CMapId& cmap_id); 277 Builder(WritableFontData* data, 278 int32_t offset, 279 const CMapId& cmap_id); 280 virtual ~Builder(); 281 282 protected: 283 virtual CALLER_ATTACH FontDataTable* 284 SubBuildTable(ReadableFontData* data); 285 }; 286 // CMapTable::CMapFormat2::CharacterIterator 287 class CharacterIterator : public CMap::CharacterIterator { 288 public: 289 virtual ~CharacterIterator(); 290 virtual bool hasNext(); 291 virtual int32_t next(); 292 293 private: 294 CharacterIterator(); 295 }; 296 297 virtual int32_t Language(); 298 virtual int32_t GlyphId(int32_t character); 299 300 // Returns how many bytes would be consumed by a lookup of this character 301 // with this cmap. This comes about because the cmap format 2 table is 302 // designed around multi-byte encodings such as SJIS, EUC-JP, Big5, etc. 303 // return the number of bytes consumed from this "character" - either 1 or 2 304 virtual int32_t BytesConsumed(int32_t character); 305 306 virtual ~CMapFormat2(); 307 308 private: 309 CMapFormat2(ReadableFontData* data, const CMapId& cmap_id); 310 311 int32_t SubHeaderOffset(int32_t sub_header_index); 312 int32_t FirstCode(int32_t sub_header_index); 313 int32_t EntryCount(int32_t sub_header_index); 314 int32_t IdRangeOffset(int32_t sub_header_index); 315 int32_t IdDelta(int32_t sub_header_index); 316 CMap::CharacterIterator* Iterator(); 317 }; 318 319 // CMapTable::CMapFormat4 320 class CMapFormat4 : public CMap, 321 public RefCounted<CMapFormat4> { 322 public: 323 // CMapTable::CMapFormat4::Builder 324 class Builder : public CMap::Builder, 325 public RefCounted<Builder> { 326 public: 327 // CMapTable::CMapFormat4::Builder::Segment 328 class Segment : public RefCounted<Segment> { 329 public: 330 Segment(); 331 explicit Segment(Segment* other); 332 Segment(int32_t start_count, 333 int32_t end_count, 334 int32_t id_delta, 335 int32_t id_range_offset); 336 ~Segment(); 337 338 // @return the startCount 339 int32_t start_count(); 340 // @param startCount the startCount to set 341 void set_start_count(int32_t start_count); 342 // @return the endCount 343 int32_t end_count(); 344 // @param endcount the endCount to set 345 void set_end_count(int32_t end_count); 346 // @return the idDelta 347 int32_t id_delta(); 348 // @param idDelta the idDelta to set 349 void set_id_delta(int32_t id_delta); 350 // @return the idRangeOffset 351 int32_t id_range_offset(); 352 // @param idRangeOffset the idRangeOffset to set 353 void set_id_range_offset(int32_t id_range_offset); 354 355 static CALLER_ATTACH 356 std::vector<Ptr<Segment> >* 357 DeepCopy(std::vector<Ptr<Segment> >* original); 358 359 private: 360 int32_t start_count_; 361 int32_t end_count_; 362 int32_t id_delta_; 363 int32_t id_range_offset_; 364 }; 365 typedef std::vector<Ptr<Segment> > SegmentList; 366 367 static CALLER_ATTACH Builder* NewInstance(WritableFontData* data, 368 int32_t offset, 369 const CMapId& cmap_id); 370 static CALLER_ATTACH Builder* NewInstance(ReadableFontData* data, 371 int32_t offset, 372 const CMapId& cmap_id); 373 static CALLER_ATTACH Builder* NewInstance(const CMapId& cmap_id); 374 virtual ~Builder(); 375 SegmentList* segments(); 376 void set_segments(SegmentList* segments); 377 std::vector<int32_t>* glyph_id_array(); 378 void set_glyph_id_array(std::vector<int32_t>* glyph_id_array); 379 380 protected: 381 Builder(WritableFontData* data, int32_t offset, const CMapId& cmap_id); 382 Builder(ReadableFontData* data, int32_t offset, const CMapId& cmap_id); 383 Builder(SegmentList* segments, std::vector<int32_t>* glyph_id_array, 384 const CMapId& cmap_id); 385 explicit Builder(const CMapId& cmap_id); 386 387 virtual CALLER_ATTACH FontDataTable* SubBuildTable( 388 ReadableFontData* data); 389 virtual void SubDataSet(); 390 virtual int32_t SubDataSizeToSerialize(); 391 virtual bool SubReadyToSerialize(); 392 virtual int32_t SubSerialize(WritableFontData* new_data); 393 394 private: 395 void Initialize(ReadableFontData* data); 396 397 SegmentList segments_; 398 std::vector<int32_t> glyph_id_array_; 399 }; 400 401 CMap::CharacterIterator* Iterator(); 402 // CMapTable::CMapFormat4::CharacterIterator 403 class CharacterIterator : public CMap::CharacterIterator { 404 public: 405 bool HasNext(); 406 int32_t Next(); ~CharacterIterator()407 virtual ~CharacterIterator() {} 408 409 private: 410 explicit CharacterIterator(CMapFormat4 *parent); 411 friend CMap::CharacterIterator* CMapFormat4::Iterator(); 412 413 CMapFormat4* parent_; 414 int32_t segment_index_; 415 int32_t first_char_in_segment_; 416 int32_t last_char_in_segment_; 417 int32_t next_char_; 418 bool next_char_set_; 419 }; 420 421 virtual int32_t GlyphId(int32_t character); 422 423 // Lower level glyph code retrieval that requires processing the Format 4 424 // segments to use. 425 // @param segment the cmap segment 426 // @param startCode the start code for the segment 427 // @param character the character to be looked up 428 // @return the glyph id for the character; CMapTable.NOTDEF if not found 429 int32_t RetrieveGlyphId(int32_t segment, 430 int32_t start_count, 431 int32_t character); 432 virtual int32_t Language(); 433 434 // Get the count of the number of segments in this cmap. 435 // @return the number of segments 436 int32_t seg_count(); 437 int32_t Length(); 438 // Get the start code for a segment. 439 // @param segment the segment in the lookup table 440 // @return the start code for a segment 441 int32_t StartCode(int32_t segment); 442 // Get the end code for a segment. 443 // @param segment the segment in the look up table 444 // @return the end code for the segment 445 int32_t EndCode(int32_t segment); 446 // Get the id delta for a segment 447 // @param segment the segment in the look up table 448 // @return the id delta for the segment 449 int32_t IdDelta(int32_t segment); 450 // Get the id range offset for a segment 451 // @param segment the segment in the look up table 452 // @return the id range offset for the segment 453 int32_t IdRangeOffset(int32_t segment); 454 // Get the location of the id range offset for a segment 455 // @param segment the segment in the look up table 456 // @return the location of the id range offset for the segment 457 int32_t IdRangeOffsetLocation(int32_t segment); 458 // Declared above to allow friending inside CharacterIterator class. 459 // CMap::CharacterIterator* Iterator(); 460 virtual ~CMapFormat4(); 461 462 protected: 463 CMapFormat4(ReadableFontData* data, const CMapId& cmap_id); 464 465 private: 466 static int32_t Language(ReadableFontData* data); 467 static int32_t Length(ReadableFontData* data); 468 static int32_t SegCount(ReadableFontData* data); 469 static int32_t StartCode(ReadableFontData* data, 470 int32_t seg_count, 471 int32_t index); 472 static int32_t StartCodeOffset(int32_t seg_count); 473 static int32_t EndCode(ReadableFontData* data, 474 int32_t seg_count, 475 int32_t index); 476 static int32_t IdDelta(ReadableFontData* data, 477 int32_t seg_count, 478 int32_t index); 479 static int32_t IdDeltaOffset(int32_t seg_count); 480 static int32_t IdRangeOffset(ReadableFontData* data, 481 int32_t seg_count, 482 int32_t index); 483 static int32_t IdRangeOffsetOffset(int32_t seg_count); 484 static int32_t GlyphIdArrayOffset(int32_t seg_count); 485 // Refactored void to bool to work without exceptions. 486 bool IsValidIndex(int32_t segment); 487 int32_t GlyphIdArray(int32_t index); 488 489 int32_t seg_count_; 490 int32_t start_code_offset_; 491 int32_t id_delta_offset_; 492 int32_t glyph_id_array_offset_; 493 }; 494 495 // CMapTable::Builder 496 class Builder : public SubTableContainerTable::Builder, 497 public RefCounted<Builder> { 498 public: 499 // Constructor scope is public because C++ does not allow base class to 500 // instantiate derived class with protected constructors. 501 Builder(Header* header, WritableFontData* data); 502 Builder(Header* header, ReadableFontData* data); 503 virtual ~Builder(); 504 505 virtual int32_t SubSerialize(WritableFontData* new_data); 506 virtual bool SubReadyToSerialize(); 507 virtual int32_t SubDataSizeToSerialize(); 508 virtual void SubDataSet(); 509 virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); 510 511 static CALLER_ATTACH Builder* CreateBuilder(Header* header, 512 WritableFontData* data); 513 514 CMap::Builder* NewCMapBuilder(const CMapId& cmap_id, 515 ReadableFontData* data); 516 // Create a new empty CMapBuilder of the type specified in the id. 517 CMap::Builder* NewCMapBuilder(int32_t format, const CMapId& cmap_id); 518 CMap::Builder* CMapBuilder(const CMapId& cmap_id); 519 520 int32_t NumCMaps(); 521 void SetVersion(int32_t version); 522 523 CMapBuilderMap* GetCMapBuilders(); 524 525 protected: 526 static CALLER_ATTACH CMap::Builder* CMapBuilder(ReadableFontData* data, 527 int32_t index); 528 529 private: 530 void Initialize(ReadableFontData* data); 531 static int32_t NumCMaps(ReadableFontData* data); 532 533 int32_t version_; 534 CMapBuilderMap cmap_builders_; 535 }; 536 typedef Ptr<Builder> CMapTableBuilderPtr; 537 538 class CMapIterator { 539 public: 540 // If filter is NULL, filter through all tables. 541 CMapIterator(CMapTable* table, const CMapFilter* filter); 542 bool HasNext(); 543 CMap* Next(); 544 545 private: 546 int32_t table_index_; 547 const CMapFilter* filter_; 548 CMapTable* table_; 549 }; 550 551 // Make a CMapId from a platform_id, encoding_id pair 552 static CMapId NewCMapId(int32_t platform_id, int32_t encoding_id); 553 // Make a CMapId from another CMapId 554 static CMapId NewCMapId(const CMapId& obj); 555 556 // Get the CMap with the specified parameters if it exists. 557 // Returns NULL otherwise. 558 CALLER_ATTACH CMap* GetCMap(const int32_t index); 559 CALLER_ATTACH CMap* GetCMap(const int32_t platform_id, 560 const int32_t encoding_id); 561 CALLER_ATTACH CMap* GetCMap(const CMapId GetCMap_id); 562 563 // Get the table version. 564 virtual int32_t Version(); 565 566 // Get the number of cmaps within the CMap table. 567 virtual int32_t NumCMaps(); 568 569 // Get the cmap id for the cmap with the given index. 570 // Note: yes, an object is returned on stack since it's small enough. 571 // This function is renamed from cmapId to GetCMapId(). 572 virtual CMapId GetCMapId(int32_t index); 573 574 virtual int32_t PlatformId(int32_t index); 575 virtual int32_t EncodingId(int32_t index); 576 577 // Get the offset in the table data for the cmap table with the given index. 578 // The offset is from the beginning of the table. 579 virtual int32_t Offset(int32_t index); 580 581 virtual ~CMapTable(); 582 583 static const int32_t NOTDEF; 584 585 private: 586 // Offsets to specific elements in the underlying data. These offsets are 587 // relative to the start of the table or the start of sub-blocks within 588 // the table. 589 struct Offset { 590 enum { 591 kVersion = 0, 592 kNumTables = 2, 593 kEncodingRecordStart = 4, 594 595 // offsets relative to the encoding record 596 kEncodingRecordPlatformId = 0, 597 kEncodingRecordEncodingId = 2, 598 kEncodingRecordOffset = 4, 599 kEncodingRecordSize = 8, 600 601 kFormat = 0, 602 603 // Format 0: Byte encoding table 604 kFormat0Format = 0, 605 kFormat0Length = 2, 606 kFormat0Language = 4, 607 kFormat0GlyphIdArray = 6, 608 609 // Format 2: High-byte mapping through table 610 kFormat2Format = 0, 611 kFormat2Length = 2, 612 kFormat2Language = 4, 613 kFormat2SubHeaderKeys = 6, 614 kFormat2SubHeaders = 518, 615 // offset relative to the subHeader structure 616 kFormat2SubHeader_firstCode = 0, 617 kFormat2SubHeader_entryCount = 2, 618 kFormat2SubHeader_idDelta = 4, 619 kFormat2SubHeader_idRangeOffset = 6, 620 kFormat2SubHeader_structLength = 8, 621 622 // Format 4: Segment mapping to delta values 623 kFormat4Format = 0, 624 kFormat4Length = 2, 625 kFormat4Language = 4, 626 kFormat4SegCountX2 = 6, 627 kFormat4SearchRange = 8, 628 kFormat4EntrySelector = 10, 629 kFormat4RangeShift = 12, 630 kFormat4EndCount = 14, 631 kFormat4FixedSize = 16, 632 633 // format 6: Trimmed table mapping 634 kFormat6Format = 0, 635 kFormat6Length = 2, 636 kFormat6Language = 4, 637 kFormat6FirstCode = 6, 638 kFormat6EntryCount = 8, 639 kFormat6GlyphIdArray = 10, 640 641 // Format 8: mixed 16-bit and 32-bit coverage 642 kFormat8Format = 0, 643 kFormat8Length = 4, 644 kFormat8Language = 8, 645 kFormat8Is32 = 12, 646 kFormat8nGroups204 = 8204, 647 kFormat8Groups208 = 8208, 648 // offset relative to the group structure 649 kFormat8Group_startCharCode = 0, 650 kFormat8Group_endCharCode = 4, 651 kFormat8Group_startGlyphId = 8, 652 kFormat8Group_structLength = 12, 653 654 // Format 10: Trimmed array 655 kFormat10Format = 0, 656 kFormat10Length = 4, 657 kFormat10Language = 8, 658 kFormat10StartCharCode = 12, 659 kFormat10NumChars = 16, 660 kFormat10Glyphs0 = 20, 661 662 // Format 12: Segmented coverage 663 kFormat12Format = 0, 664 kFormat12Length = 4, 665 kFormat12Language = 8, 666 kFormat12nGroups = 12, 667 kFormat12Groups = 16, 668 kFormat12Groups_structLength = 12, 669 // offsets within the group structure 670 kFormat12_startCharCode = 0, 671 kFormat12_endCharCode = 4, 672 kFormat12_startGlyphId = 8, 673 674 // Format 13: Last Resort Font 675 kFormat13Format = 0, 676 kFormat13Length = 4, 677 kFormat13Language = 8, 678 kFormat13nGroups = 12, 679 kFormat13Groups = 16, 680 kFormat13Groups_structLength = 12, 681 // offsets within the group structure 682 kFormat13_startCharCode = 0, 683 kFormat13_endCharCode = 4, 684 kFormat13_glyphId = 8, 685 686 // Format 14: Unicode Variation Sequences 687 kFormat14Format = 0, 688 kFormat14Length = 2, 689 690 // TODO(stuartg): finish tables 691 // Default UVS Table 692 693 // Non-default UVS Table 694 kLast = -1 695 }; 696 }; 697 698 CMapTable(Header* header, ReadableFontData* data); 699 700 // Get the offset in the table data for the encoding record for the cmap with 701 // the given index. The offset is from the beginning of the table. 702 static int32_t OffsetForEncodingRecord(int32_t index); 703 }; 704 typedef std::vector<CMapTable::CMapId> CMapIdList; 705 typedef Ptr<CMapTable> CMapTablePtr; 706 typedef std::vector<Ptr<CMapTable::CMapFormat4::Builder::Segment> > SegmentList; 707 } // namespace sfntly 708 709 #endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ 710