Home | History | Annotate | Download | only in core
      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.
     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);
     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.
    134       virtual CMapId cmap_id() { return cmap_id_; }
    135       virtual int32_t platform_id() { return cmap_id_.platform_id; }
    136       virtual int32_t encoding_id() { return cmap_id_.encoding_id; }
    137       virtual int32_t format() { return format_; }
    138       virtual int32_t language() { return 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:
    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.
    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 
    182     virtual int32_t format() { return format_; }
    183     virtual CMapId cmap_id() { return cmap_id_; }
    184     virtual int32_t platform_id() { return cmap_id_.platform_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       IntegerList* glyph_id_array();
    378       void set_glyph_id_array(IntegerList* 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, IntegerList* 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       IntegerList 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();
    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