Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  2007,2008,2009  Red Hat, Inc.
      3  * Copyright  2012  Google, Inc.
      4  *
      5  *  This is part of HarfBuzz, a text shaping library.
      6  *
      7  * Permission is hereby granted, without written agreement and without
      8  * license or royalty fees, to use, copy, modify, and distribute this
      9  * software and its documentation for any purpose, provided that the
     10  * above copyright notice and the following two paragraphs appear in
     11  * all copies of this software.
     12  *
     13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     17  * DAMAGE.
     18  *
     19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     24  *
     25  * Red Hat Author(s): Behdad Esfahbod
     26  * Google Author(s): Behdad Esfahbod
     27  */
     28 
     29 #ifndef HB_OPEN_FILE_PRIVATE_HH
     30 #define HB_OPEN_FILE_PRIVATE_HH
     31 
     32 #include "hb-open-type-private.hh"
     33 
     34 
     35 namespace OT {
     36 
     37 
     38 /*
     39  *
     40  * The OpenType Font File
     41  *
     42  */
     43 
     44 
     45 /*
     46  * Organization of an OpenType Font
     47  */
     48 
     49 struct OpenTypeFontFile;
     50 struct OffsetTable;
     51 struct TTCHeader;
     52 
     53 
     54 typedef struct TableRecord
     55 {
     56   inline bool sanitize (hb_sanitize_context_t *c) const
     57   {
     58     TRACE_SANITIZE (this);
     59     return_trace (c->check_struct (this));
     60   }
     61 
     62   Tag		tag;		/* 4-byte identifier. */
     63   CheckSum	checkSum;	/* CheckSum for this table. */
     64   ULONG		offset;		/* Offset from beginning of TrueType font
     65 				 * file. */
     66   ULONG		length;		/* Length of this table. */
     67   public:
     68   DEFINE_SIZE_STATIC (16);
     69 } OpenTypeTable;
     70 
     71 typedef struct OffsetTable
     72 {
     73   friend struct OpenTypeFontFile;
     74 
     75   inline unsigned int get_table_count (void) const
     76   { return numTables; }
     77   inline const TableRecord& get_table (unsigned int i) const
     78   {
     79     if (unlikely (i >= numTables)) return Null(TableRecord);
     80     return tables[i];
     81   }
     82   inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
     83   {
     84     Tag t;
     85     t.set (tag);
     86     unsigned int count = numTables;
     87     for (unsigned int i = 0; i < count; i++)
     88     {
     89       if (t == tables[i].tag)
     90       {
     91         if (table_index) *table_index = i;
     92         return true;
     93       }
     94     }
     95     if (table_index) *table_index = Index::NOT_FOUND_INDEX;
     96     return false;
     97   }
     98   inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
     99   {
    100     unsigned int table_index;
    101     find_table_index (tag, &table_index);
    102     return get_table (table_index);
    103   }
    104 
    105   public:
    106   inline bool sanitize (hb_sanitize_context_t *c) const
    107   {
    108     TRACE_SANITIZE (this);
    109     return_trace (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables));
    110   }
    111 
    112   protected:
    113   Tag		sfnt_version;	/* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
    114   USHORT	numTables;	/* Number of tables. */
    115   USHORT	searchRangeZ;	/* (Maximum power of 2 <= numTables) x 16 */
    116   USHORT	entrySelectorZ;	/* Log2(maximum power of 2 <= numTables). */
    117   USHORT	rangeShiftZ;	/* NumTables x 16-searchRange. */
    118   TableRecord	tables[VAR];	/* TableRecord entries. numTables items */
    119   public:
    120   DEFINE_SIZE_ARRAY (12, tables);
    121 } OpenTypeFontFace;
    122 
    123 
    124 /*
    125  * TrueType Collections
    126  */
    127 
    128 struct TTCHeaderVersion1
    129 {
    130   friend struct TTCHeader;
    131 
    132   inline unsigned int get_face_count (void) const { return table.len; }
    133   inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
    134 
    135   inline bool sanitize (hb_sanitize_context_t *c) const
    136   {
    137     TRACE_SANITIZE (this);
    138     return_trace (table.sanitize (c, this));
    139   }
    140 
    141   protected:
    142   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
    143   FixedVersion<>version;	/* Version of the TTC Header (1.0),
    144 				 * 0x00010000u */
    145   ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG>
    146 		table;		/* Array of offsets to the OffsetTable for each font
    147 				 * from the beginning of the file */
    148   public:
    149   DEFINE_SIZE_ARRAY (12, table);
    150 };
    151 
    152 struct TTCHeader
    153 {
    154   friend struct OpenTypeFontFile;
    155 
    156   private:
    157 
    158   inline unsigned int get_face_count (void) const
    159   {
    160     switch (u.header.version.major) {
    161     case 2: /* version 2 is compatible with version 1 */
    162     case 1: return u.version1.get_face_count ();
    163     default:return 0;
    164     }
    165   }
    166   inline const OpenTypeFontFace& get_face (unsigned int i) const
    167   {
    168     switch (u.header.version.major) {
    169     case 2: /* version 2 is compatible with version 1 */
    170     case 1: return u.version1.get_face (i);
    171     default:return Null(OpenTypeFontFace);
    172     }
    173   }
    174 
    175   inline bool sanitize (hb_sanitize_context_t *c) const
    176   {
    177     TRACE_SANITIZE (this);
    178     if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
    179     switch (u.header.version.major) {
    180     case 2: /* version 2 is compatible with version 1 */
    181     case 1: return_trace (u.version1.sanitize (c));
    182     default:return_trace (true);
    183     }
    184   }
    185 
    186   protected:
    187   union {
    188   struct {
    189   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
    190   FixedVersion<>version;	/* Version of the TTC Header (1.0 or 2.0),
    191 				 * 0x00010000u or 0x00020000u */
    192   }			header;
    193   TTCHeaderVersion1	version1;
    194   } u;
    195 };
    196 
    197 
    198 /*
    199  * OpenType Font File
    200  */
    201 
    202 struct OpenTypeFontFile
    203 {
    204   static const hb_tag_t tableTag	= HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
    205 
    206   static const hb_tag_t CFFTag		= HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */
    207   static const hb_tag_t TrueTypeTag	= HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */
    208   static const hb_tag_t TTCTag		= HB_TAG ('t','t','c','f'); /* TrueType Collection */
    209   static const hb_tag_t TrueTag		= HB_TAG ('t','r','u','e'); /* Obsolete Apple TrueType */
    210   static const hb_tag_t Typ1Tag		= HB_TAG ('t','y','p','1'); /* Obsolete Apple Type1 font in SFNT container */
    211 
    212   inline hb_tag_t get_tag (void) const { return u.tag; }
    213 
    214   inline unsigned int get_face_count (void) const
    215   {
    216     switch (u.tag) {
    217     case CFFTag:	/* All the non-collection tags */
    218     case TrueTag:
    219     case Typ1Tag:
    220     case TrueTypeTag:	return 1;
    221     case TTCTag:	return u.ttcHeader.get_face_count ();
    222     default:		return 0;
    223     }
    224   }
    225   inline const OpenTypeFontFace& get_face (unsigned int i) const
    226   {
    227     switch (u.tag) {
    228     /* Note: for non-collection SFNT data we ignore index.  This is because
    229      * Apple dfont container is a container of SFNT's.  So each SFNT is a
    230      * non-TTC, but the index is more than zero. */
    231     case CFFTag:	/* All the non-collection tags */
    232     case TrueTag:
    233     case Typ1Tag:
    234     case TrueTypeTag:	return u.fontFace;
    235     case TTCTag:	return u.ttcHeader.get_face (i);
    236     default:		return Null(OpenTypeFontFace);
    237     }
    238   }
    239 
    240   inline bool sanitize (hb_sanitize_context_t *c) const
    241   {
    242     TRACE_SANITIZE (this);
    243     if (unlikely (!u.tag.sanitize (c))) return_trace (false);
    244     switch (u.tag) {
    245     case CFFTag:	/* All the non-collection tags */
    246     case TrueTag:
    247     case Typ1Tag:
    248     case TrueTypeTag:	return_trace (u.fontFace.sanitize (c));
    249     case TTCTag:	return_trace (u.ttcHeader.sanitize (c));
    250     default:		return_trace (true);
    251     }
    252   }
    253 
    254   protected:
    255   union {
    256   Tag			tag;		/* 4-byte identifier. */
    257   OpenTypeFontFace	fontFace;
    258   TTCHeader		ttcHeader;
    259   } u;
    260   public:
    261   DEFINE_SIZE_UNION (4, tag);
    262 };
    263 
    264 
    265 } /* namespace OT */
    266 
    267 
    268 #endif /* HB_OPEN_FILE_PRIVATE_HH */
    269