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 { cmpOT::TableRecord56 int cmp (Tag t) const 57 { return t.cmp (tag); } 58 sanitizeOT::TableRecord59 inline bool sanitize (hb_sanitize_context_t *c) const 60 { 61 TRACE_SANITIZE (this); 62 return_trace (c->check_struct (this)); 63 } 64 65 Tag tag; /* 4-byte identifier. */ 66 CheckSum checkSum; /* CheckSum for this table. */ 67 UINT32 offset; /* Offset from beginning of TrueType font 68 * file. */ 69 UINT32 length; /* Length of this table. */ 70 public: 71 DEFINE_SIZE_STATIC (16); 72 } OpenTypeTable; 73 74 typedef struct OffsetTable 75 { 76 friend struct OpenTypeFontFile; 77 get_table_countOT::OffsetTable78 inline unsigned int get_table_count (void) const 79 { return tables.len; } get_tableOT::OffsetTable80 inline const TableRecord& get_table (unsigned int i) const 81 { 82 return tables[i]; 83 } get_table_tagsOT::OffsetTable84 inline unsigned int get_table_tags (unsigned int start_offset, 85 unsigned int *table_count, /* IN/OUT */ 86 hb_tag_t *table_tags /* OUT */) const 87 { 88 if (table_count) 89 { 90 if (start_offset >= tables.len) 91 *table_count = 0; 92 else 93 *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset); 94 95 const TableRecord *sub_tables = tables.array + start_offset; 96 unsigned int count = *table_count; 97 for (unsigned int i = 0; i < count; i++) 98 table_tags[i] = sub_tables[i].tag; 99 } 100 return tables.len; 101 } find_table_indexOT::OffsetTable102 inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const 103 { 104 Tag t; 105 t.set (tag); 106 /* Linear-search for small tables to work around fonts with unsorted 107 * table list. */ 108 int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t); 109 if (table_index) 110 *table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i; 111 return i != -1; 112 } get_table_by_tagOT::OffsetTable113 inline const TableRecord& get_table_by_tag (hb_tag_t tag) const 114 { 115 unsigned int table_index; 116 find_table_index (tag, &table_index); 117 return get_table (table_index); 118 } 119 120 public: sanitizeOT::OffsetTable121 inline bool sanitize (hb_sanitize_context_t *c) const 122 { 123 TRACE_SANITIZE (this); 124 return_trace (c->check_struct (this) && tables.sanitize (c)); 125 } 126 127 protected: 128 Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */ 129 BinSearchArrayOf<TableRecord> 130 tables; 131 public: 132 DEFINE_SIZE_ARRAY (12, tables); 133 } OpenTypeFontFace; 134 135 136 /* 137 * TrueType Collections 138 */ 139 140 struct TTCHeaderVersion1 141 { 142 friend struct TTCHeader; 143 get_face_countOT::TTCHeaderVersion1144 inline unsigned int get_face_count (void) const { return table.len; } get_faceOT::TTCHeaderVersion1145 inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; } 146 sanitizeOT::TTCHeaderVersion1147 inline bool sanitize (hb_sanitize_context_t *c) const 148 { 149 TRACE_SANITIZE (this); 150 return_trace (table.sanitize (c, this)); 151 } 152 153 protected: 154 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ 155 FixedVersion<>version; /* Version of the TTC Header (1.0), 156 * 0x00010000u */ 157 ArrayOf<LOffsetTo<OffsetTable>, UINT32> 158 table; /* Array of offsets to the OffsetTable for each font 159 * from the beginning of the file */ 160 public: 161 DEFINE_SIZE_ARRAY (12, table); 162 }; 163 164 struct TTCHeader 165 { 166 friend struct OpenTypeFontFile; 167 168 private: 169 get_face_countOT::TTCHeader170 inline unsigned int get_face_count (void) const 171 { 172 switch (u.header.version.major) { 173 case 2: /* version 2 is compatible with version 1 */ 174 case 1: return u.version1.get_face_count (); 175 default:return 0; 176 } 177 } get_faceOT::TTCHeader178 inline const OpenTypeFontFace& get_face (unsigned int i) const 179 { 180 switch (u.header.version.major) { 181 case 2: /* version 2 is compatible with version 1 */ 182 case 1: return u.version1.get_face (i); 183 default:return Null(OpenTypeFontFace); 184 } 185 } 186 sanitizeOT::TTCHeader187 inline bool sanitize (hb_sanitize_context_t *c) const 188 { 189 TRACE_SANITIZE (this); 190 if (unlikely (!u.header.version.sanitize (c))) return_trace (false); 191 switch (u.header.version.major) { 192 case 2: /* version 2 is compatible with version 1 */ 193 case 1: return_trace (u.version1.sanitize (c)); 194 default:return_trace (true); 195 } 196 } 197 198 protected: 199 union { 200 struct { 201 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ 202 FixedVersion<>version; /* Version of the TTC Header (1.0 or 2.0), 203 * 0x00010000u or 0x00020000u */ 204 } header; 205 TTCHeaderVersion1 version1; 206 } u; 207 }; 208 209 210 /* 211 * OpenType Font File 212 */ 213 214 struct OpenTypeFontFile 215 { 216 static const hb_tag_t tableTag = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */ 217 218 static const hb_tag_t CFFTag = HB_TAG ('O','T','T','O'); /* OpenType with Postscript outlines */ 219 static const hb_tag_t TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ); /* OpenType with TrueType outlines */ 220 static const hb_tag_t TTCTag = HB_TAG ('t','t','c','f'); /* TrueType Collection */ 221 static const hb_tag_t TrueTag = HB_TAG ('t','r','u','e'); /* Obsolete Apple TrueType */ 222 static const hb_tag_t Typ1Tag = HB_TAG ('t','y','p','1'); /* Obsolete Apple Type1 font in SFNT container */ 223 get_tagOT::OpenTypeFontFile224 inline hb_tag_t get_tag (void) const { return u.tag; } 225 get_face_countOT::OpenTypeFontFile226 inline unsigned int get_face_count (void) const 227 { 228 switch (u.tag) { 229 case CFFTag: /* All the non-collection tags */ 230 case TrueTag: 231 case Typ1Tag: 232 case TrueTypeTag: return 1; 233 case TTCTag: return u.ttcHeader.get_face_count (); 234 default: return 0; 235 } 236 } get_faceOT::OpenTypeFontFile237 inline const OpenTypeFontFace& get_face (unsigned int i) const 238 { 239 switch (u.tag) { 240 /* Note: for non-collection SFNT data we ignore index. This is because 241 * Apple dfont container is a container of SFNT's. So each SFNT is a 242 * non-TTC, but the index is more than zero. */ 243 case CFFTag: /* All the non-collection tags */ 244 case TrueTag: 245 case Typ1Tag: 246 case TrueTypeTag: return u.fontFace; 247 case TTCTag: return u.ttcHeader.get_face (i); 248 default: return Null(OpenTypeFontFace); 249 } 250 } 251 sanitizeOT::OpenTypeFontFile252 inline bool sanitize (hb_sanitize_context_t *c) const 253 { 254 TRACE_SANITIZE (this); 255 if (unlikely (!u.tag.sanitize (c))) return_trace (false); 256 switch (u.tag) { 257 case CFFTag: /* All the non-collection tags */ 258 case TrueTag: 259 case Typ1Tag: 260 case TrueTypeTag: return_trace (u.fontFace.sanitize (c)); 261 case TTCTag: return_trace (u.ttcHeader.sanitize (c)); 262 default: return_trace (true); 263 } 264 } 265 266 protected: 267 union { 268 Tag tag; /* 4-byte identifier. */ 269 OpenTypeFontFace fontFace; 270 TTCHeader ttcHeader; 271 } u; 272 public: 273 DEFINE_SIZE_UNION (4, tag); 274 }; 275 276 277 } /* namespace OT */ 278 279 280 #endif /* HB_OPEN_FILE_PRIVATE_HH */ 281