blob: 8772c79fa10bae9f48c74e91a7a06eacde6f1813 [file] [log] [blame]
Behdad Esfahbod2098a022009-08-02 19:57:00 -04001/*
Behdad Esfahbod2409d5f2011-04-21 17:14:28 -04002 * Copyright © 2007,2008,2009 Red Hat, Inc.
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02003 * Copyright © 2012 Google, Inc.
Behdad Esfahbod2098a022009-08-02 19:57:00 -04004 *
Behdad Esfahbodc755cb32010-04-22 00:11:43 -04005 * This is part of HarfBuzz, a text shaping library.
Behdad Esfahbod2098a022009-08-02 19:57:00 -04006 *
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
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +020026 * Google Author(s): Behdad Esfahbod
Behdad Esfahbod2098a022009-08-02 19:57:00 -040027 */
28
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070029#ifndef HB_OPEN_FILE_HH
30#define HB_OPEN_FILE_HH
Behdad Esfahbod2098a022009-08-02 19:57:00 -040031
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070032#include "hb-open-type.hh"
Behdad Esfahboddc5c7922018-02-23 16:42:06 -080033#include "hb-ot-head-table.hh"
Behdad Esfahbod2098a022009-08-02 19:57:00 -040034
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040035
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -040036namespace OT {
37
Behdad Esfahbod2098a022009-08-02 19:57:00 -040038
39/*
40 *
41 * The OpenType Font File
42 *
43 */
44
45
46/*
47 * Organization of an OpenType Font
48 */
49
50struct OpenTypeFontFile;
51struct OffsetTable;
52struct TTCHeader;
53
Behdad Esfahbod569da922010-05-10 16:38:32 -040054
Behdad Esfahbod22c53762010-12-14 23:51:29 -050055typedef struct TableRecord
Behdad Esfahbod2098a022009-08-02 19:57:00 -040056{
Behdad Esfahbod6c04dcb2017-10-31 20:11:00 -060057 int cmp (Tag t) const
Garret Rieger8e614ad2018-02-20 17:36:54 -080058 { return -t.cmp (tag); }
Behdad Esfahbod6c04dcb2017-10-31 20:11:00 -060059
Behdad Esfahbodc479a592018-02-07 21:13:10 -060060 static int cmp (const void *pa, const void *pb)
61 {
62 const TableRecord *a = (const TableRecord *) pa;
63 const TableRecord *b = (const TableRecord *) pb;
64 return b->cmp (a->tag);
65 }
66
Behdad Esfahbodde2118e2015-02-17 17:27:44 +030067 inline bool sanitize (hb_sanitize_context_t *c) const
68 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -050069 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +010070 return_trace (c->check_struct (this));
Behdad Esfahbodb508e5c2009-08-04 15:07:24 -040071 }
72
Behdad Esfahbod2098a022009-08-02 19:57:00 -040073 Tag tag; /* 4-byte identifier. */
74 CheckSum checkSum; /* CheckSum for this table. */
Behdad Esfahbodc479a592018-02-07 21:13:10 -060075 Offset32 offset; /* Offset from beginning of TrueType font
Behdad Esfahbod2098a022009-08-02 19:57:00 -040076 * file. */
Behdad Esfahbodc9acab32018-02-07 17:12:55 -060077 HBUINT32 length; /* Length of this table. */
Behdad Esfahbod569da922010-05-10 16:38:32 -040078 public:
79 DEFINE_SIZE_STATIC (16);
Behdad Esfahbod2098a022009-08-02 19:57:00 -040080} OpenTypeTable;
Behdad Esfahbod2098a022009-08-02 19:57:00 -040081
82typedef struct OffsetTable
83{
84 friend struct OpenTypeFontFile;
Behdad Esfahbod2098a022009-08-02 19:57:00 -040085
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -040086 inline unsigned int get_table_count (void) const
Behdad Esfahbodb0e33da2017-10-31 20:05:37 -060087 { return tables.len; }
Behdad Esfahbod22c53762010-12-14 23:51:29 -050088 inline const TableRecord& get_table (unsigned int i) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -040089 {
Behdad Esfahbod22c53762010-12-14 23:51:29 -050090 return tables[i];
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -040091 }
Behdad Esfahbodc9acab32018-02-07 17:12:55 -060092 inline unsigned int get_table_tags (unsigned int start_offset,
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +020093 unsigned int *table_count, /* IN/OUT */
94 hb_tag_t *table_tags /* OUT */) const
95 {
96 if (table_count)
97 {
Behdad Esfahbodb0e33da2017-10-31 20:05:37 -060098 if (start_offset >= tables.len)
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +020099 *table_count = 0;
100 else
ebraminio102f5ea2017-11-01 02:10:18 -0700101 *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200102
Behdad Esfahbod63f57f42018-05-08 16:56:11 -0700103 const TableRecord *sub_tables = tables.arrayZ + start_offset;
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200104 unsigned int count = *table_count;
105 for (unsigned int i = 0; i < count; i++)
106 table_tags[i] = sub_tables[i].tag;
107 }
Behdad Esfahbodb0e33da2017-10-31 20:05:37 -0600108 return tables.len;
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200109 }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400110 inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
111 {
Behdad Esfahbodffd321a2010-04-21 00:14:12 -0400112 Tag t;
113 t.set (tag);
Behdad Esfahbod6c04dcb2017-10-31 20:11:00 -0600114 /* Linear-search for small tables to work around fonts with unsorted
115 * table list. */
116 int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
117 if (table_index)
Behdad Esfahbodfda994e2018-09-07 15:02:57 -0400118 *table_index = i == -1 ? (unsigned) Index::NOT_FOUND_INDEX : (unsigned) i;
Behdad Esfahbod6c04dcb2017-10-31 20:11:00 -0600119 return i != -1;
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400120 }
Behdad Esfahbod22c53762010-12-14 23:51:29 -0500121 inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -0400122 {
123 unsigned int table_index;
124 find_table_index (tag, &table_index);
125 return get_table (table_index);
126 }
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400127
Behdad Esfahbodb508e5c2009-08-04 15:07:24 -0400128 public:
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600129
130 inline bool serialize (hb_serialize_context_t *c,
131 hb_tag_t sfnt_tag,
132 Supplier<hb_tag_t> &tags,
133 Supplier<hb_blob_t *> &blobs,
134 unsigned int table_count)
135 {
136 TRACE_SERIALIZE (this);
Behdad Esfahbodec2538c2018-02-23 15:51:26 -0800137 /* Alloc 12 for the OTHeader. */
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600138 if (unlikely (!c->extend_min (*this))) return_trace (false);
Behdad Esfahboddc5c7922018-02-23 16:42:06 -0800139 /* Write sfntVersion (bytes 0..3). */
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600140 sfnt_version.set (sfnt_tag);
Behdad Esfahbodec2538c2018-02-23 15:51:26 -0800141 /* Take space for numTables, searchRange, entrySelector, RangeShift
Behdad Esfahboddc5c7922018-02-23 16:42:06 -0800142 * and the TableRecords themselves. */
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600143 if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
Behdad Esfahbod941bbd92018-02-07 21:49:01 -0600144
Behdad Esfahboddc5c7922018-02-23 16:42:06 -0800145 const char *dir_end = (const char *) c->head;
146 HBUINT32 *checksum_adjustment = nullptr;
147
Behdad Esfahbodec2538c2018-02-23 15:51:26 -0800148 /* Write OffsetTables, alloc for and write actual table blobs. */
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600149 for (unsigned int i = 0; i < table_count; i++)
150 {
Behdad Esfahbod63f57f42018-05-08 16:56:11 -0700151 TableRecord &rec = tables.arrayZ[i];
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600152 hb_blob_t *blob = blobs[i];
Behdad Esfahbod941bbd92018-02-07 21:49:01 -0600153 rec.tag.set (tags[i]);
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600154 rec.length.set (hb_blob_get_length (blob));
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600155 rec.offset.serialize (c, this);
Behdad Esfahboddc5c7922018-02-23 16:42:06 -0800156
157 /* Allocate room for the table and copy it. */
158 char *start = (char *) c->allocate_size<void> (rec.length);
159 if (unlikely (!start)) {return false;}
160
161 memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
162
Behdad Esfahbodec2538c2018-02-23 15:51:26 -0800163 /* 4-byte allignment. */
Behdad Esfahbod22acd422018-08-31 16:38:04 -0700164 c->align (4);
Behdad Esfahbodec2538c2018-02-23 15:51:26 -0800165 const char *end = (const char *) c->head;
Behdad Esfahboddc5c7922018-02-23 16:42:06 -0800166
167 if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size)
168 {
169 head *h = (head *) start;
170 checksum_adjustment = &h->checkSumAdjustment;
171 checksum_adjustment->set (0);
172 }
173
Behdad Esfahbodec2538c2018-02-23 15:51:26 -0800174 rec.checkSum.set_for_data (start, end - start);
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600175 }
Behdad Esfahbod71130a22018-02-10 13:15:57 -0600176 tags += table_count;
177 blobs += table_count;
Behdad Esfahbod941bbd92018-02-07 21:49:01 -0600178
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600179 tables.qsort ();
Behdad Esfahboddc5c7922018-02-23 16:42:06 -0800180
181 if (checksum_adjustment)
182 {
183 CheckSum checksum;
184
185 /* The following line is a slower version of the following block. */
186 //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
187 checksum.set_for_data (this, dir_end - (const char *) this);
188 for (unsigned int i = 0; i < table_count; i++)
189 {
Behdad Esfahbod63f57f42018-05-08 16:56:11 -0700190 TableRecord &rec = tables.arrayZ[i];
Behdad Esfahboddc5c7922018-02-23 16:42:06 -0800191 checksum.set (checksum + rec.checkSum);
192 }
193
194 checksum_adjustment->set (0xB1B0AFBAu - checksum);
195 }
196
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600197 return_trace (true);
198 }
199
Behdad Esfahbodde2118e2015-02-17 17:27:44 +0300200 inline bool sanitize (hb_sanitize_context_t *c) const
201 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500202 TRACE_SANITIZE (this);
Behdad Esfahbodb0e33da2017-10-31 20:05:37 -0600203 return_trace (c->check_struct (this) && tables.sanitize (c));
Behdad Esfahbodb508e5c2009-08-04 15:07:24 -0400204 }
205
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400206 protected:
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400207 Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
Behdad Esfahbodb0e33da2017-10-31 20:05:37 -0600208 BinSearchArrayOf<TableRecord>
209 tables;
Behdad Esfahbod569da922010-05-10 16:38:32 -0400210 public:
Behdad Esfahbod22c53762010-12-14 23:51:29 -0500211 DEFINE_SIZE_ARRAY (12, tables);
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400212} OpenTypeFontFace;
Behdad Esfahbod569da922010-05-10 16:38:32 -0400213
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400214
215/*
216 * TrueType Collections
217 */
218
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400219struct TTCHeaderVersion1
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400220{
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400221 friend struct TTCHeader;
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400222
Behdad Esfahbod20b035d2009-08-10 19:00:36 -0400223 inline unsigned int get_face_count (void) const { return table.len; }
Behdad Esfahboddf3f5052010-04-22 14:11:33 -0400224 inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
Behdad Esfahbodb508e5c2009-08-04 15:07:24 -0400225
Behdad Esfahbodde2118e2015-02-17 17:27:44 +0300226 inline bool sanitize (hb_sanitize_context_t *c) const
227 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500228 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100229 return_trace (table.sanitize (c, this));
Behdad Esfahbodb508e5c2009-08-04 15:07:24 -0400230 }
231
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400232 protected:
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400233 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
Behdad Esfahbod9a13ed42016-02-22 11:44:45 +0900234 FixedVersion<>version; /* Version of the TTC Header (1.0),
Behdad Esfahbod76271002014-07-11 14:54:42 -0400235 * 0x00010000u */
Ebrahim Byagowib799fc82018-04-11 18:36:09 +0430236 LArrayOf<LOffsetTo<OffsetTable> >
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400237 table; /* Array of offsets to the OffsetTable for each font
238 * from the beginning of the file */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400239 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400240 DEFINE_SIZE_ARRAY (12, table);
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400241};
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400242
243struct TTCHeader
244{
245 friend struct OpenTypeFontFile;
246
247 private:
248
249 inline unsigned int get_face_count (void) const
250 {
Behdad Esfahbod4f28fbd2011-05-31 12:33:11 -0400251 switch (u.header.version.major) {
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400252 case 2: /* version 2 is compatible with version 1 */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400253 case 1: return u.version1.get_face_count ();
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400254 default:return 0;
255 }
256 }
257 inline const OpenTypeFontFace& get_face (unsigned int i) const
258 {
Behdad Esfahbod4f28fbd2011-05-31 12:33:11 -0400259 switch (u.header.version.major) {
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400260 case 2: /* version 2 is compatible with version 1 */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400261 case 1: return u.version1.get_face (i);
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400262 default:return Null(OpenTypeFontFace);
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400263 }
264 }
265
Behdad Esfahbodde2118e2015-02-17 17:27:44 +0300266 inline bool sanitize (hb_sanitize_context_t *c) const
267 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500268 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100269 if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
Behdad Esfahbod4f28fbd2011-05-31 12:33:11 -0400270 switch (u.header.version.major) {
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400271 case 2: /* version 2 is compatible with version 1 */
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100272 case 1: return_trace (u.version1.sanitize (c));
273 default:return_trace (true);
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400274 }
275 }
276
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400277 protected:
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400278 union {
279 struct {
280 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
Behdad Esfahbod9a13ed42016-02-22 11:44:45 +0900281 FixedVersion<>version; /* Version of the TTC Header (1.0 or 2.0),
Behdad Esfahbod76271002014-07-11 14:54:42 -0400282 * 0x00010000u or 0x00020000u */
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400283 } header;
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400284 TTCHeaderVersion1 version1;
Behdad Esfahbodae4190c2010-04-23 12:33:02 -0400285 } u;
286};
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400287
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430288/*
289 * Mac Resource Fork
Behdad Esfahbodbd75fd42018-09-11 18:12:26 +0200290 *
291 * http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430292 */
293
Behdad Esfahbodbd75fd42018-09-11 18:12:26 +0200294struct ResourceRecord
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430295{
Behdad Esfahbod4479d3a2018-09-13 19:05:59 +0200296 inline const OpenTypeFontFace & get_face (const void *data_base) const
297 { return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); }
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200298
299 inline bool sanitize (hb_sanitize_context_t *c,
300 const void *data_base) const
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430301 {
302 TRACE_SANITIZE (this);
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200303 return_trace (c->check_struct (this) &&
Behdad Esfahbod4479d3a2018-09-13 19:05:59 +0200304 offset.sanitize (c, data_base) &&
305 get_face (data_base).sanitize (c));
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430306 }
307
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200308 protected:
Behdad Esfahbod82f4d772018-09-13 18:27:20 +0200309 HBUINT16 id; /* Resource ID. */
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430310 HBINT16 nameOffset; /* Offset from beginning of resource name list
Behdad Esfahbod4134ec12018-09-11 17:56:03 +0200311 * to resource name, -1 means there is none. */
Behdad Esfahbodbd75fd42018-09-11 18:12:26 +0200312 HBUINT8 attrs; /* Resource attributes */
Behdad Esfahbodbf852f02018-09-13 18:47:53 +0200313 OffsetTo<LArrayOf<HBUINT8>, HBUINT24, false>
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200314 offset; /* Offset from beginning of data block to
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430315 * data for this resource */
316 HBUINT32 reserved; /* Reserved for handle to resource */
317 public:
318 DEFINE_SIZE_STATIC (12);
319};
320
Behdad Esfahbod4479d3a2018-09-13 19:05:59 +0200321#define HB_TAG_sfnt HB_TAG ('s','f','n','t')
322
Behdad Esfahbodbd75fd42018-09-11 18:12:26 +0200323struct ResourceTypeRecord
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430324{
Behdad Esfahbod180a88a2018-09-13 19:19:57 +0200325 inline unsigned int get_resource_count (void) const
326 { return tag == HB_TAG_sfnt ? resCountM1 + 1 : 0; }
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430327
Behdad Esfahbod8c9bdcc2018-09-13 19:08:22 +0200328 inline bool is_sfnt (void) const { return tag == HB_TAG_sfnt; }
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430329
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200330 inline const ResourceRecord& get_resource_record (unsigned int i,
331 const void *type_base) const
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430332 {
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200333 return hb_array_t<ResourceRecord> ((type_base+resourcesZ).arrayZ,
334 get_resource_count ()) [i];
335 }
336
337 inline bool sanitize (hb_sanitize_context_t *c,
338 const void *type_base,
339 const void *data_base) const
340 {
341 TRACE_SANITIZE (this);
342 return_trace (c->check_struct (this) &&
343 resourcesZ.sanitize (c, type_base,
344 get_resource_count (),
345 data_base));
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430346 }
347
348 protected:
Behdad Esfahbodbd75fd42018-09-11 18:12:26 +0200349 Tag tag; /* Resource type. */
350 HBUINT16 resCountM1; /* Number of resources minus 1. */
Behdad Esfahbodf8ccb542018-09-14 18:59:53 +0200351 OffsetTo<UnsizedArrayOf<ResourceRecord>, HBUINT16, false>
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200352 resourcesZ; /* Offset from beginning of resource type list
Behdad Esfahbodd5c50922018-09-11 17:18:21 +0200353 * to reference item list for this type. */
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430354 public:
355 DEFINE_SIZE_STATIC (8);
356};
357
358struct ResourceMap
359{
Behdad Esfahbod0ab0f1e2018-09-13 19:13:01 +0200360 inline unsigned int get_face_count (void) const
361 {
362 unsigned int count = get_type_count ();
363 for (unsigned int i = 0; i < count; i++)
364 {
365 const ResourceTypeRecord& type = get_type_record (i);
366 if (type.is_sfnt ())
367 return type.get_resource_count ();
368 }
369 return 0;
370 }
371
372 inline const OpenTypeFontFace& get_face (unsigned int idx,
373 const void *data_base) const
374 {
375 unsigned int count = get_type_count ();
376 for (unsigned int i = 0; i < count; i++)
377 {
378 const ResourceTypeRecord& type = get_type_record (i);
Behdad Esfahbod180a88a2018-09-13 19:19:57 +0200379 /* The check for idx < count is here because ResourceRecord is NOT null-safe.
380 * Because an offset of 0 there does NOT mean null. */
Behdad Esfahbod0ab0f1e2018-09-13 19:13:01 +0200381 if (type.is_sfnt () && idx < type.get_resource_count ())
Behdad Esfahbod3789c552018-09-13 20:30:04 +0200382 return type.get_resource_record (idx, &(this+typeList)).get_face (data_base);
Behdad Esfahbod0ab0f1e2018-09-13 19:13:01 +0200383 }
384 return Null (OpenTypeFontFace);
385 }
386
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200387 inline bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
388 {
389 TRACE_SANITIZE (this);
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200390 return_trace (c->check_struct (this) &&
Behdad Esfahbod3789c552018-09-13 20:30:04 +0200391 typeList.sanitize (c, this,
Behdad Esfahbod67449c32018-09-14 10:58:00 +0200392 &(this+typeList),
Behdad Esfahbod3789c552018-09-13 20:30:04 +0200393 data_base));
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430394 }
395
Behdad Esfahbod180a88a2018-09-13 19:19:57 +0200396 private:
Behdad Esfahbod3789c552018-09-13 20:30:04 +0200397 inline unsigned int get_type_count (void) const { return (this+typeList).lenM1 + 1; }
398
399 inline const ResourceTypeRecord& get_type_record (unsigned int i) const
400 { return (this+typeList)[i]; }
Behdad Esfahbod180a88a2018-09-13 19:19:57 +0200401
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430402 protected:
Behdad Esfahbodbd75fd42018-09-11 18:12:26 +0200403 HBUINT8 reserved0[16]; /* Reserved for copy of resource header */
404 HBUINT32 reserved1; /* Reserved for handle to next resource map */
405 HBUINT16 resreved2; /* Reserved for file reference number */
406 HBUINT16 attrs; /* Resource fork attribute */
Behdad Esfahbodf8ccb542018-09-14 18:59:53 +0200407 OffsetTo<ArrayOfM1<ResourceTypeRecord>, HBUINT16, false>
Behdad Esfahbod3789c552018-09-13 20:30:04 +0200408 typeList; /* Offset from beginning of map to
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430409 * resource type list */
Behdad Esfahbod6b5e4d02018-09-11 17:26:24 +0200410 Offset16 nameList; /* Offset from beginning of map to
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430411 * resource name list */
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430412 public:
Behdad Esfahbod3789c552018-09-13 20:30:04 +0200413 DEFINE_SIZE_STATIC (28);
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430414};
415
416struct ResourceForkHeader
417{
Behdad Esfahbod8c9bdcc2018-09-13 19:08:22 +0200418 inline unsigned int get_face_count (void) const
Behdad Esfahbod0ab0f1e2018-09-13 19:13:01 +0200419 { return (this+map).get_face_count (); }
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430420
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200421 inline const OpenTypeFontFace& get_face (unsigned int idx,
422 unsigned int *base_offset = nullptr) const
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430423 {
Behdad Esfahbod0ab0f1e2018-09-13 19:13:01 +0200424 const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data));
425 if (base_offset)
426 *base_offset = (const char *) &face - (const char *) this;
427 return face;
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430428 }
429
430 inline bool sanitize (hb_sanitize_context_t *c) const
431 {
432 TRACE_SANITIZE (this);
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200433 return_trace (c->check_struct (this) &&
Behdad Esfahbodca746f22018-09-13 20:35:21 +0200434 data.sanitize (c, this, dataLen) &&
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200435 map.sanitize (c, this, &(this+data)));
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430436 }
437
438 protected:
Behdad Esfahbodf8ccb542018-09-14 18:59:53 +0200439 LOffsetTo<UnsizedArrayOf<HBUINT8>, false>
Behdad Esfahboddbb764d2018-09-13 16:49:26 +0200440 data; /* Offset from beginning of resource fork
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430441 * to resource data */
Behdad Esfahbodf8ccb542018-09-14 18:59:53 +0200442 LOffsetTo<ResourceMap, false>
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430443 map; /* Offset from beginning of resource fork
444 * to resource map */
445 HBUINT32 dataLen; /* Length of resource data */
446 HBUINT32 mapLen; /* Length of resource map */
447 public:
448 DEFINE_SIZE_STATIC (16);
449};
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400450
451/*
452 * OpenType Font File
453 */
454
455struct OpenTypeFontFile
456{
Ebrahim Byagowi2a236062018-03-23 18:37:01 +0430457 enum {
458 CFFTag = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
Behdad Esfahboda1814e22018-09-11 14:45:23 +0200459 TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
Ebrahim Byagowi2a236062018-03-23 18:37:01 +0430460 TTCTag = HB_TAG ('t','t','c','f'), /* TrueType Collection */
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430461 DFontTag = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
Ebrahim Byagowi2a236062018-03-23 18:37:01 +0430462 TrueTag = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
463 Typ1Tag = HB_TAG ('t','y','p','1') /* Obsolete Apple Type1 font in SFNT container */
464 };
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400465
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400466 inline hb_tag_t get_tag (void) const { return u.tag; }
467
Behdad Esfahbod20b035d2009-08-10 19:00:36 -0400468 inline unsigned int get_face_count (void) const
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400469 {
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400470 switch (u.tag) {
471 case CFFTag: /* All the non-collection tags */
Jeff Muizelaar4ce578e2010-05-03 15:03:53 -0400472 case TrueTag:
473 case Typ1Tag:
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400474 case TrueTypeTag: return 1;
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400475 case TTCTag: return u.ttcHeader.get_face_count ();
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200476 case DFontTag: return u.rfHeader.get_face_count ();
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400477 default: return 0;
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400478 }
479 }
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200480 inline const OpenTypeFontFace& get_face (unsigned int i, unsigned int *base_offset = nullptr) const
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400481 {
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200482 if (base_offset)
483 *base_offset = 0;
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400484 switch (u.tag) {
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400485 /* Note: for non-collection SFNT data we ignore index. This is because
486 * Apple dfont container is a container of SFNT's. So each SFNT is a
487 * non-TTC, but the index is more than zero. */
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400488 case CFFTag: /* All the non-collection tags */
Jeff Muizelaar4ce578e2010-05-03 15:03:53 -0400489 case TrueTag:
490 case Typ1Tag:
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400491 case TrueTypeTag: return u.fontFace;
492 case TTCTag: return u.ttcHeader.get_face (i);
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200493 case DFontTag: return u.rfHeader.get_face (i, base_offset);
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400494 default: return Null(OpenTypeFontFace);
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400495 }
496 }
497
Behdad Esfahbodc479a592018-02-07 21:13:10 -0600498 inline bool serialize_single (hb_serialize_context_t *c,
499 hb_tag_t sfnt_tag,
500 Supplier<hb_tag_t> &tags,
501 Supplier<hb_blob_t *> &blobs,
502 unsigned int table_count)
503 {
504 TRACE_SERIALIZE (this);
505 assert (sfnt_tag != TTCTag);
506 if (unlikely (!c->extend_min (*this))) return_trace (false);
507 return_trace (u.fontFace.serialize (c, sfnt_tag, tags, blobs, table_count));
508 }
509
Behdad Esfahbodde2118e2015-02-17 17:27:44 +0300510 inline bool sanitize (hb_sanitize_context_t *c) const
511 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500512 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100513 if (unlikely (!u.tag.sanitize (c))) return_trace (false);
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400514 switch (u.tag) {
515 case CFFTag: /* All the non-collection tags */
Jeff Muizelaar4ce578e2010-05-03 15:03:53 -0400516 case TrueTag:
517 case Typ1Tag:
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100518 case TrueTypeTag: return_trace (u.fontFace.sanitize (c));
519 case TTCTag: return_trace (u.ttcHeader.sanitize (c));
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200520 case DFontTag: return_trace (u.rfHeader.sanitize (c));
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100521 default: return_trace (true);
Behdad Esfahbodb508e5c2009-08-04 15:07:24 -0400522 }
523 }
524
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400525 protected:
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400526 union {
527 Tag tag; /* 4-byte identifier. */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400528 OpenTypeFontFace fontFace;
529 TTCHeader ttcHeader;
Ebrahim Byagowi225b92b2018-07-01 14:32:00 +0430530 ResourceForkHeader rfHeader;
Behdad Esfahbod1aa46662010-04-23 13:32:03 -0400531 } u;
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400532 public:
533 DEFINE_SIZE_UNION (4, tag);
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400534};
Behdad Esfahbod2098a022009-08-02 19:57:00 -0400535
536
Behdad Esfahbod7d52e662012-11-16 18:49:54 -0800537} /* namespace OT */
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -0400538
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400539
Behdad Esfahbodc77ae402018-08-25 22:36:36 -0700540#endif /* HB_OPEN_FILE_HH */