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
31namespace sfntly {
32
33// CMap subtable formats
34struct 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
49class CMapTable : public SubTableContainerTable, public RefCounted<CMapTable> {
50public:
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};
704typedef std::vector<CMapTable::CMapId> CMapIdList;
705typedef Ptr<CMapTable> CMapTablePtr;
706typedef std::vector<Ptr<CMapTable::CMapFormat4::Builder::Segment> > SegmentList;
707}  // namespace sfntly
708
709#endif  // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_
710