Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: third_party/ots/src/layout.cc

Issue 1252363005: Update OTS to revision a7a3b94 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/ots/src/layout.h ('k') | third_party/ots/src/loca.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "layout.h" 5 #include "layout.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <vector> 8 #include <vector>
9 9
10 #include "gdef.h" 10 #include "gdef.h"
(...skipping 28 matching lines...) Expand all
39 struct LangSysRecord { 39 struct LangSysRecord {
40 uint32_t tag; 40 uint32_t tag;
41 uint16_t offset; 41 uint16_t offset;
42 }; 42 };
43 43
44 struct FeatureRecord { 44 struct FeatureRecord {
45 uint32_t tag; 45 uint32_t tag;
46 uint16_t offset; 46 uint16_t offset;
47 }; 47 };
48 48
49 bool ParseLangSysTable(const ots::OpenTypeFile *file, 49 bool ParseLangSysTable(const ots::Font *font,
50 ots::Buffer *subtable, const uint32_t tag, 50 ots::Buffer *subtable, const uint32_t tag,
51 const uint16_t num_features) { 51 const uint16_t num_features) {
52 uint16_t offset_lookup_order = 0; 52 uint16_t offset_lookup_order = 0;
53 uint16_t req_feature_index = 0; 53 uint16_t req_feature_index = 0;
54 uint16_t feature_count = 0; 54 uint16_t feature_count = 0;
55 if (!subtable->ReadU16(&offset_lookup_order) || 55 if (!subtable->ReadU16(&offset_lookup_order) ||
56 !subtable->ReadU16(&req_feature_index) || 56 !subtable->ReadU16(&req_feature_index) ||
57 !subtable->ReadU16(&feature_count)) { 57 !subtable->ReadU16(&feature_count)) {
58 return OTS_FAILURE_MSG("Failed to read langsys header for tag %4.4s", (char *)&tag); 58 return OTS_FAILURE_MSG("Failed to read langsys header for tag %c%c%c%c", OTS _UNTAG(tag));
59 } 59 }
60 // |offset_lookup_order| is reserved and should be NULL. 60 // |offset_lookup_order| is reserved and should be NULL.
61 if (offset_lookup_order != 0) { 61 if (offset_lookup_order != 0) {
62 return OTS_FAILURE_MSG("Bad lookup offset order %d for langsys tag %4.4s", o ffset_lookup_order, (char *)&tag); 62 return OTS_FAILURE_MSG("Bad lookup offset order %d for langsys tag %c%c%c%c" , offset_lookup_order, OTS_UNTAG(tag));
63 } 63 }
64 if (req_feature_index != kNoRequiredFeatureIndexDefined && 64 if (req_feature_index != kNoRequiredFeatureIndexDefined &&
65 req_feature_index >= num_features) { 65 req_feature_index >= num_features) {
66 return OTS_FAILURE_MSG("Bad required features index %d for langsys tag %4.4s ", req_feature_index, (char *)&tag); 66 return OTS_FAILURE_MSG("Bad required features index %d for langsys tag %c%c% c%c", req_feature_index, OTS_UNTAG(tag));
67 } 67 }
68 if (feature_count > num_features) { 68 if (feature_count > num_features) {
69 return OTS_FAILURE_MSG("Bad feature count %d for langsys tag %4.4s", feature _count, (char *)&tag); 69 return OTS_FAILURE_MSG("Bad feature count %d for langsys tag %c%c%c%c", feat ure_count, OTS_UNTAG(tag));
70 } 70 }
71 71
72 for (unsigned i = 0; i < feature_count; ++i) { 72 for (unsigned i = 0; i < feature_count; ++i) {
73 uint16_t feature_index = 0; 73 uint16_t feature_index = 0;
74 if (!subtable->ReadU16(&feature_index)) { 74 if (!subtable->ReadU16(&feature_index)) {
75 return OTS_FAILURE_MSG("Failed to read feature index %d for langsys tag %4 .4s", i, (char *)&tag); 75 return OTS_FAILURE_MSG("Failed to read feature index %d for langsys tag %c %c%c%c", i, OTS_UNTAG(tag));
76 } 76 }
77 if (feature_index >= num_features) { 77 if (feature_index >= num_features) {
78 return OTS_FAILURE_MSG("Bad feature index %d for feature %d for langsys ta g %4.4s", feature_index, i, (char *)&tag); 78 return OTS_FAILURE_MSG("Bad feature index %d for feature %d for langsys ta g %c%c%c%c", feature_index, i, OTS_UNTAG(tag));
79 } 79 }
80 } 80 }
81 return true; 81 return true;
82 } 82 }
83 83
84 bool ParseScriptTable(const ots::OpenTypeFile *file, 84 bool ParseScriptTable(const ots::Font *font,
85 const uint8_t *data, const size_t length, 85 const uint8_t *data, const size_t length,
86 const uint32_t tag, const uint16_t num_features) { 86 const uint32_t tag, const uint16_t num_features) {
87 ots::Buffer subtable(data, length); 87 ots::Buffer subtable(data, length);
88 88
89 uint16_t offset_default_lang_sys = 0; 89 uint16_t offset_default_lang_sys = 0;
90 uint16_t lang_sys_count = 0; 90 uint16_t lang_sys_count = 0;
91 if (!subtable.ReadU16(&offset_default_lang_sys) || 91 if (!subtable.ReadU16(&offset_default_lang_sys) ||
92 !subtable.ReadU16(&lang_sys_count)) { 92 !subtable.ReadU16(&lang_sys_count)) {
93 return OTS_FAILURE_MSG("Failed to read script header for script tag %4.4s", (char *)&tag); 93 return OTS_FAILURE_MSG("Failed to read script header for script tag %c%c%c%c ", OTS_UNTAG(tag));
94 } 94 }
95 95
96 // The spec requires a script table for 'DFLT' tag must contain non-NULL 96 // The spec requires a script table for 'DFLT' tag must contain non-NULL
97 // |offset_default_lang_sys| and |lang_sys_count| == 0 97 // |offset_default_lang_sys| and |lang_sys_count| == 0
98 if (tag == kScriptTableTagDflt && 98 if (tag == kScriptTableTagDflt &&
99 (offset_default_lang_sys == 0 || lang_sys_count != 0)) { 99 (offset_default_lang_sys == 0 || lang_sys_count != 0)) {
100 return OTS_FAILURE_MSG("DFLT table doesn't satisfy the spec. for script tag %4.4s", (char *)&tag); 100 return OTS_FAILURE_MSG("DFLT table doesn't satisfy the spec. for script tag %c%c%c%c", OTS_UNTAG(tag));
101 } 101 }
102 102
103 const unsigned lang_sys_record_end = 103 const unsigned lang_sys_record_end =
104 6 * static_cast<unsigned>(lang_sys_count) + 4; 104 6 * static_cast<unsigned>(lang_sys_count) + 4;
105 if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) { 105 if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) {
106 return OTS_FAILURE_MSG("Bad end of langsys record %d for script tag %4.4s", lang_sys_record_end, (char *)&tag); 106 return OTS_FAILURE_MSG("Bad end of langsys record %d for script tag %c%c%c%c ", lang_sys_record_end, OTS_UNTAG(tag));
107 } 107 }
108 108
109 std::vector<LangSysRecord> lang_sys_records; 109 std::vector<LangSysRecord> lang_sys_records;
110 lang_sys_records.resize(lang_sys_count); 110 lang_sys_records.resize(lang_sys_count);
111 uint32_t last_tag = 0; 111 uint32_t last_tag = 0;
112 for (unsigned i = 0; i < lang_sys_count; ++i) { 112 for (unsigned i = 0; i < lang_sys_count; ++i) {
113 if (!subtable.ReadU32(&lang_sys_records[i].tag) || 113 if (!subtable.ReadU32(&lang_sys_records[i].tag) ||
114 !subtable.ReadU16(&lang_sys_records[i].offset)) { 114 !subtable.ReadU16(&lang_sys_records[i].offset)) {
115 return OTS_FAILURE_MSG("Failed to read langsys record header %d for script tag %4.4s", i, (char *)&tag); 115 return OTS_FAILURE_MSG("Failed to read langsys record header %d for script tag %c%c%c%c", i, OTS_UNTAG(tag));
116 } 116 }
117 // The record array must store the records alphabetically by tag 117 // The record array must store the records alphabetically by tag
118 if (last_tag != 0 && last_tag > lang_sys_records[i].tag) { 118 if (last_tag != 0 && last_tag > lang_sys_records[i].tag) {
119 return OTS_FAILURE_MSG("Bad last tag %d for langsys record %d for script t ag %4.4s", last_tag, i, (char *)&tag); 119 return OTS_FAILURE_MSG("Bad last tag %d for langsys record %d for script t ag %c%c%c%c", last_tag, i, OTS_UNTAG(tag));
120 } 120 }
121 if (lang_sys_records[i].offset < lang_sys_record_end || 121 if (lang_sys_records[i].offset < lang_sys_record_end ||
122 lang_sys_records[i].offset >= length) { 122 lang_sys_records[i].offset >= length) {
123 return OTS_FAILURE_MSG("bad offset to lang sys table: %x", 123 return OTS_FAILURE_MSG("bad offset to lang sys table: %x",
124 lang_sys_records[i].offset); 124 lang_sys_records[i].offset);
125 } 125 }
126 last_tag = lang_sys_records[i].tag; 126 last_tag = lang_sys_records[i].tag;
127 } 127 }
128 128
129 // Check lang sys tables 129 // Check lang sys tables
130 for (unsigned i = 0; i < lang_sys_count; ++i) { 130 for (unsigned i = 0; i < lang_sys_count; ++i) {
131 subtable.set_offset(lang_sys_records[i].offset); 131 subtable.set_offset(lang_sys_records[i].offset);
132 if (!ParseLangSysTable(file, &subtable, lang_sys_records[i].tag, num_feature s)) { 132 if (!ParseLangSysTable(font, &subtable, lang_sys_records[i].tag, num_feature s)) {
133 return OTS_FAILURE_MSG("Failed to parse langsys table %d (%4.4s) for scrip t tag %4.4s", i, (char *)&lang_sys_records[i].tag, (char *)&tag); 133 return OTS_FAILURE_MSG("Failed to parse langsys table %d (%c%c%c%c) for sc ript tag %c%c%c%c", i, OTS_UNTAG(lang_sys_records[i].tag), OTS_UNTAG(tag));
134 } 134 }
135 } 135 }
136 136
137 return true; 137 return true;
138 } 138 }
139 139
140 bool ParseFeatureTable(const ots::OpenTypeFile *file, 140 bool ParseFeatureTable(const ots::Font *font,
141 const uint8_t *data, const size_t length, 141 const uint8_t *data, const size_t length,
142 const uint16_t num_lookups) { 142 const uint16_t num_lookups) {
143 ots::Buffer subtable(data, length); 143 ots::Buffer subtable(data, length);
144 144
145 uint16_t offset_feature_params = 0; 145 uint16_t offset_feature_params = 0;
146 uint16_t lookup_count = 0; 146 uint16_t lookup_count = 0;
147 if (!subtable.ReadU16(&offset_feature_params) || 147 if (!subtable.ReadU16(&offset_feature_params) ||
148 !subtable.ReadU16(&lookup_count)) { 148 !subtable.ReadU16(&lookup_count)) {
149 return OTS_FAILURE_MSG("Failed to read feature table header"); 149 return OTS_FAILURE_MSG("Failed to read feature table header");
150 } 150 }
(...skipping 16 matching lines...) Expand all
167 return OTS_FAILURE_MSG("Failed to read lookup index for lookup %d", i); 167 return OTS_FAILURE_MSG("Failed to read lookup index for lookup %d", i);
168 } 168 }
169 // lookup index starts with 0. 169 // lookup index starts with 0.
170 if (lookup_index >= num_lookups) { 170 if (lookup_index >= num_lookups) {
171 return OTS_FAILURE_MSG("Bad lookup index %d for lookup %d", lookup_index, i); 171 return OTS_FAILURE_MSG("Bad lookup index %d for lookup %d", lookup_index, i);
172 } 172 }
173 } 173 }
174 return true; 174 return true;
175 } 175 }
176 176
177 bool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data, 177 bool ParseLookupTable(ots::Font *font, const uint8_t *data,
178 const size_t length, 178 const size_t length,
179 const ots::LookupSubtableParser* parser) { 179 const ots::LookupSubtableParser* parser) {
180 ots::Buffer subtable(data, length); 180 ots::Buffer subtable(data, length);
181 181
182 uint16_t lookup_type = 0; 182 uint16_t lookup_type = 0;
183 uint16_t lookup_flag = 0; 183 uint16_t lookup_flag = 0;
184 uint16_t subtable_count = 0; 184 uint16_t subtable_count = 0;
185 if (!subtable.ReadU16(&lookup_type) || 185 if (!subtable.ReadU16(&lookup_type) ||
186 !subtable.ReadU16(&lookup_flag) || 186 !subtable.ReadU16(&lookup_flag) ||
187 !subtable.ReadU16(&subtable_count)) { 187 !subtable.ReadU16(&subtable_count)) {
188 return OTS_FAILURE_MSG("Failed to read lookup table header"); 188 return OTS_FAILURE_MSG("Failed to read lookup table header");
189 } 189 }
190 190
191 if (lookup_type == 0 || lookup_type > parser->num_types) { 191 if (lookup_type == 0 || lookup_type > parser->num_types) {
192 return OTS_FAILURE_MSG("Bad lookup type %d", lookup_type); 192 return OTS_FAILURE_MSG("Bad lookup type %d", lookup_type);
193 } 193 }
194 194
195 // Check lookup flags. 195 // Check lookup flags.
196 if ((lookup_flag & kGdefRequiredFlags) && 196 if ((lookup_flag & kGdefRequiredFlags) &&
197 (!file->gdef || !file->gdef->has_glyph_class_def)) { 197 (!font->gdef || !font->gdef->has_glyph_class_def)) {
198 return OTS_FAILURE_MSG("Bad lookup flags %d", lookup_flag); 198 return OTS_FAILURE_MSG("Bad lookup flags %d", lookup_flag);
199 } 199 }
200 if ((lookup_flag & kMarkAttachmentTypeMask) && 200 if ((lookup_flag & kMarkAttachmentTypeMask) &&
201 (!file->gdef || !file->gdef->has_mark_attachment_class_def)) { 201 (!font->gdef || !font->gdef->has_mark_attachment_class_def)) {
202 return OTS_FAILURE_MSG("lookup flag asks for mark attachment that is bad %d" , lookup_flag); 202 return OTS_FAILURE_MSG("lookup flag asks for mark attachment that is bad %d" , lookup_flag);
203 } 203 }
204 bool use_mark_filtering_set = false; 204 bool use_mark_filtering_set = false;
205 if (lookup_flag & kUseMarkFilteringSetBit) { 205 if (lookup_flag & kUseMarkFilteringSetBit) {
206 if (!file->gdef || !file->gdef->has_mark_glyph_sets_def) { 206 if (!font->gdef || !font->gdef->has_mark_glyph_sets_def) {
207 return OTS_FAILURE_MSG("lookup flag asks for mark filtering that is bad %d ", lookup_flag); 207 return OTS_FAILURE_MSG("lookup flag asks for mark filtering that is bad %d ", lookup_flag);
208 } 208 }
209 use_mark_filtering_set = true; 209 use_mark_filtering_set = true;
210 } 210 }
211 211
212 std::vector<uint16_t> subtables; 212 std::vector<uint16_t> subtables;
213 subtables.reserve(subtable_count); 213 subtables.reserve(subtable_count);
214 // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set, 214 // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set,
215 // extra 2 bytes will follow after subtable offset array. 215 // extra 2 bytes will follow after subtable offset array.
216 const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) + 216 const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) +
(...skipping 14 matching lines...) Expand all
231 } 231 }
232 if (subtables.size() != subtable_count) { 232 if (subtables.size() != subtable_count) {
233 return OTS_FAILURE_MSG("Bad subtable size %ld", subtables.size()); 233 return OTS_FAILURE_MSG("Bad subtable size %ld", subtables.size());
234 } 234 }
235 235
236 if (use_mark_filtering_set) { 236 if (use_mark_filtering_set) {
237 uint16_t mark_filtering_set = 0; 237 uint16_t mark_filtering_set = 0;
238 if (!subtable.ReadU16(&mark_filtering_set)) { 238 if (!subtable.ReadU16(&mark_filtering_set)) {
239 return OTS_FAILURE_MSG("Failed to read mark filtering set"); 239 return OTS_FAILURE_MSG("Failed to read mark filtering set");
240 } 240 }
241 if (file->gdef->num_mark_glyph_sets == 0 || 241 if (font->gdef->num_mark_glyph_sets == 0 ||
242 mark_filtering_set >= file->gdef->num_mark_glyph_sets) { 242 mark_filtering_set >= font->gdef->num_mark_glyph_sets) {
243 return OTS_FAILURE_MSG("Bad mark filtering set %d", mark_filtering_set); 243 return OTS_FAILURE_MSG("Bad mark filtering set %d", mark_filtering_set);
244 } 244 }
245 } 245 }
246 246
247 // Parse lookup subtables for this lookup type. 247 // Parse lookup subtables for this lookup type.
248 for (unsigned i = 0; i < subtable_count; ++i) { 248 for (unsigned i = 0; i < subtable_count; ++i) {
249 if (!parser->Parse(file, data + subtables[i], length - subtables[i], 249 if (!parser->Parse(font, data + subtables[i], length - subtables[i],
250 lookup_type)) { 250 lookup_type)) {
251 return OTS_FAILURE_MSG("Failed to parse subtable %d", i); 251 return OTS_FAILURE_MSG("Failed to parse subtable %d", i);
252 } 252 }
253 } 253 }
254 return true; 254 return true;
255 } 255 }
256 256
257 bool ParseClassDefFormat1(const ots::OpenTypeFile *file, 257 bool ParseClassDefFormat1(const ots::Font *font,
258 const uint8_t *data, size_t length, 258 const uint8_t *data, size_t length,
259 const uint16_t num_glyphs, 259 const uint16_t num_glyphs,
260 const uint16_t num_classes) { 260 const uint16_t num_classes) {
261 ots::Buffer subtable(data, length); 261 ots::Buffer subtable(data, length);
262 262
263 // Skip format field. 263 // Skip format field.
264 if (!subtable.Skip(2)) { 264 if (!subtable.Skip(2)) {
265 return OTS_FAILURE_MSG("Failed to skip class definition header"); 265 return OTS_FAILURE_MSG("Failed to skip class definition header");
266 } 266 }
267 267
(...skipping 18 matching lines...) Expand all
286 return OTS_FAILURE_MSG("Failed to read class value for glyph %d in class d efinition", i); 286 return OTS_FAILURE_MSG("Failed to read class value for glyph %d in class d efinition", i);
287 } 287 }
288 if (class_value > num_classes) { 288 if (class_value > num_classes) {
289 return OTS_FAILURE_MSG("Bad class value %d for glyph %d in class definitio n", class_value, i); 289 return OTS_FAILURE_MSG("Bad class value %d for glyph %d in class definitio n", class_value, i);
290 } 290 }
291 } 291 }
292 292
293 return true; 293 return true;
294 } 294 }
295 295
296 bool ParseClassDefFormat2(const ots::OpenTypeFile *file, 296 bool ParseClassDefFormat2(const ots::Font *font,
297 const uint8_t *data, size_t length, 297 const uint8_t *data, size_t length,
298 const uint16_t num_glyphs, 298 const uint16_t num_glyphs,
299 const uint16_t num_classes) { 299 const uint16_t num_classes) {
300 ots::Buffer subtable(data, length); 300 ots::Buffer subtable(data, length);
301 301
302 // Skip format field. 302 // Skip format field.
303 if (!subtable.Skip(2)) { 303 if (!subtable.Skip(2)) {
304 return OTS_FAILURE_MSG("Failed to skip format of class defintion header"); 304 return OTS_FAILURE_MSG("Failed to skip format of class defintion header");
305 } 305 }
306 306
(...skipping 20 matching lines...) Expand all
327 } 327 }
328 if (class_value > num_classes) { 328 if (class_value > num_classes) {
329 return OTS_FAILURE_MSG("bad class value: %u", class_value); 329 return OTS_FAILURE_MSG("bad class value: %u", class_value);
330 } 330 }
331 last_end = end; 331 last_end = end;
332 } 332 }
333 333
334 return true; 334 return true;
335 } 335 }
336 336
337 bool ParseCoverageFormat1(const ots::OpenTypeFile *file, 337 bool ParseCoverageFormat1(const ots::Font *font,
338 const uint8_t *data, size_t length, 338 const uint8_t *data, size_t length,
339 const uint16_t num_glyphs, 339 const uint16_t num_glyphs,
340 const uint16_t expected_num_glyphs) { 340 const uint16_t expected_num_glyphs) {
341 ots::Buffer subtable(data, length); 341 ots::Buffer subtable(data, length);
342 342
343 // Skip format field. 343 // Skip format field.
344 if (!subtable.Skip(2)) { 344 if (!subtable.Skip(2)) {
345 return OTS_FAILURE_MSG("Failed to skip coverage format"); 345 return OTS_FAILURE_MSG("Failed to skip coverage format");
346 } 346 }
347 347
(...skipping 14 matching lines...) Expand all
362 } 362 }
363 } 363 }
364 364
365 if (expected_num_glyphs && expected_num_glyphs != glyph_count) { 365 if (expected_num_glyphs && expected_num_glyphs != glyph_count) {
366 return OTS_FAILURE_MSG("unexpected number of glyphs: %u", glyph_count); 366 return OTS_FAILURE_MSG("unexpected number of glyphs: %u", glyph_count);
367 } 367 }
368 368
369 return true; 369 return true;
370 } 370 }
371 371
372 bool ParseCoverageFormat2(const ots::OpenTypeFile *file, 372 bool ParseCoverageFormat2(const ots::Font *font,
373 const uint8_t *data, size_t length, 373 const uint8_t *data, size_t length,
374 const uint16_t num_glyphs, 374 const uint16_t num_glyphs,
375 const uint16_t expected_num_glyphs) { 375 const uint16_t expected_num_glyphs) {
376 ots::Buffer subtable(data, length); 376 ots::Buffer subtable(data, length);
377 377
378 // Skip format field. 378 // Skip format field.
379 if (!subtable.Skip(2)) { 379 if (!subtable.Skip(2)) {
380 return OTS_FAILURE_MSG("Failed to skip format of coverage type 2"); 380 return OTS_FAILURE_MSG("Failed to skip format of coverage type 2");
381 } 381 }
382 382
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 if (expected_num_glyphs && 416 if (expected_num_glyphs &&
417 expected_num_glyphs != last_start_coverage_index) { 417 expected_num_glyphs != last_start_coverage_index) {
418 return OTS_FAILURE_MSG("unexpected number of glyphs: %u", last_start_cover age_index); 418 return OTS_FAILURE_MSG("unexpected number of glyphs: %u", last_start_cover age_index);
419 } 419 }
420 420
421 return true; 421 return true;
422 } 422 }
423 423
424 // Parsers for Contextual subtables in GSUB/GPOS tables. 424 // Parsers for Contextual subtables in GSUB/GPOS tables.
425 425
426 bool ParseLookupRecord(const ots::OpenTypeFile *file, 426 bool ParseLookupRecord(const ots::Font *font,
427 ots::Buffer *subtable, const uint16_t num_glyphs, 427 ots::Buffer *subtable, const uint16_t num_glyphs,
428 const uint16_t num_lookups) { 428 const uint16_t num_lookups) {
429 uint16_t sequence_index = 0; 429 uint16_t sequence_index = 0;
430 uint16_t lookup_list_index = 0; 430 uint16_t lookup_list_index = 0;
431 if (!subtable->ReadU16(&sequence_index) || 431 if (!subtable->ReadU16(&sequence_index) ||
432 !subtable->ReadU16(&lookup_list_index)) { 432 !subtable->ReadU16(&lookup_list_index)) {
433 return OTS_FAILURE_MSG("Failed to read header for lookup record"); 433 return OTS_FAILURE_MSG("Failed to read header for lookup record");
434 } 434 }
435 if (sequence_index >= num_glyphs) { 435 if (sequence_index >= num_glyphs) {
436 return OTS_FAILURE_MSG("Bad sequence index %d in lookup record", sequence_in dex); 436 return OTS_FAILURE_MSG("Bad sequence index %d in lookup record", sequence_in dex);
437 } 437 }
438 if (lookup_list_index >= num_lookups) { 438 if (lookup_list_index >= num_lookups) {
439 return OTS_FAILURE_MSG("Bad lookup list index %d in lookup record", lookup_l ist_index); 439 return OTS_FAILURE_MSG("Bad lookup list index %d in lookup record", lookup_l ist_index);
440 } 440 }
441 return true; 441 return true;
442 } 442 }
443 443
444 bool ParseRuleSubtable(const ots::OpenTypeFile *file, 444 bool ParseRuleSubtable(const ots::Font *font,
445 const uint8_t *data, const size_t length, 445 const uint8_t *data, const size_t length,
446 const uint16_t num_glyphs, 446 const uint16_t num_glyphs,
447 const uint16_t num_lookups) { 447 const uint16_t num_lookups) {
448 ots::Buffer subtable(data, length); 448 ots::Buffer subtable(data, length);
449 449
450 uint16_t glyph_count = 0; 450 uint16_t glyph_count = 0;
451 uint16_t lookup_count = 0; 451 uint16_t lookup_count = 0;
452 if (!subtable.ReadU16(&glyph_count) || 452 if (!subtable.ReadU16(&glyph_count) ||
453 !subtable.ReadU16(&lookup_count)) { 453 !subtable.ReadU16(&lookup_count)) {
454 return OTS_FAILURE_MSG("Failed to read rule subtable header"); 454 return OTS_FAILURE_MSG("Failed to read rule subtable header");
455 } 455 }
456 456
457 if (glyph_count == 0 || glyph_count >= num_glyphs) { 457 if (glyph_count == 0 || glyph_count >= num_glyphs) {
458 return OTS_FAILURE_MSG("Bad glyph count %d in rule subtable", glyph_count); 458 return OTS_FAILURE_MSG("Bad glyph count %d in rule subtable", glyph_count);
459 } 459 }
460 for (unsigned i = 0; i < glyph_count - static_cast<unsigned>(1); ++i) { 460 for (unsigned i = 0; i < glyph_count - static_cast<unsigned>(1); ++i) {
461 uint16_t glyph_id = 0; 461 uint16_t glyph_id = 0;
462 if (!subtable.ReadU16(&glyph_id)) { 462 if (!subtable.ReadU16(&glyph_id)) {
463 return OTS_FAILURE_MSG("Failed to read glyph %d", i); 463 return OTS_FAILURE_MSG("Failed to read glyph %d", i);
464 } 464 }
465 if (glyph_id > num_glyphs) { 465 if (glyph_id > num_glyphs) {
466 return OTS_FAILURE_MSG("Bad glyph %d for entry %d", glyph_id, i); 466 return OTS_FAILURE_MSG("Bad glyph %d for entry %d", glyph_id, i);
467 } 467 }
468 } 468 }
469 469
470 for (unsigned i = 0; i < lookup_count; ++i) { 470 for (unsigned i = 0; i < lookup_count; ++i) {
471 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { 471 if (!ParseLookupRecord(font, &subtable, num_glyphs, num_lookups)) {
472 return OTS_FAILURE_MSG("Failed to parse lookup record %d", i); 472 return OTS_FAILURE_MSG("Failed to parse lookup record %d", i);
473 } 473 }
474 } 474 }
475 return true; 475 return true;
476 } 476 }
477 477
478 bool ParseRuleSetTable(const ots::OpenTypeFile *file, 478 bool ParseRuleSetTable(const ots::Font *font,
479 const uint8_t *data, const size_t length, 479 const uint8_t *data, const size_t length,
480 const uint16_t num_glyphs, 480 const uint16_t num_glyphs,
481 const uint16_t num_lookups) { 481 const uint16_t num_lookups) {
482 ots::Buffer subtable(data, length); 482 ots::Buffer subtable(data, length);
483 483
484 uint16_t rule_count = 0; 484 uint16_t rule_count = 0;
485 if (!subtable.ReadU16(&rule_count)) { 485 if (!subtable.ReadU16(&rule_count)) {
486 return OTS_FAILURE_MSG("Failed to read rule count in rule set"); 486 return OTS_FAILURE_MSG("Failed to read rule count in rule set");
487 } 487 }
488 const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2; 488 const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2;
489 if (rule_end > std::numeric_limits<uint16_t>::max()) { 489 if (rule_end > std::numeric_limits<uint16_t>::max()) {
490 return OTS_FAILURE_MSG("Bad end of rule %d in rule set", rule_end); 490 return OTS_FAILURE_MSG("Bad end of rule %d in rule set", rule_end);
491 } 491 }
492 492
493 for (unsigned i = 0; i < rule_count; ++i) { 493 for (unsigned i = 0; i < rule_count; ++i) {
494 uint16_t offset_rule = 0; 494 uint16_t offset_rule = 0;
495 if (!subtable.ReadU16(&offset_rule)) { 495 if (!subtable.ReadU16(&offset_rule)) {
496 return OTS_FAILURE_MSG("Failed to read rule offset for rule set %d", i); 496 return OTS_FAILURE_MSG("Failed to read rule offset for rule set %d", i);
497 } 497 }
498 if (offset_rule < rule_end || offset_rule >= length) { 498 if (offset_rule < rule_end || offset_rule >= length) {
499 return OTS_FAILURE_MSG("Bad rule offset %d in set %d", offset_rule, i); 499 return OTS_FAILURE_MSG("Bad rule offset %d in set %d", offset_rule, i);
500 } 500 }
501 if (!ParseRuleSubtable(file, data + offset_rule, length - offset_rule, 501 if (!ParseRuleSubtable(font, data + offset_rule, length - offset_rule,
502 num_glyphs, num_lookups)) { 502 num_glyphs, num_lookups)) {
503 return OTS_FAILURE_MSG("Failed to parse rule set %d", i); 503 return OTS_FAILURE_MSG("Failed to parse rule set %d", i);
504 } 504 }
505 } 505 }
506 506
507 return true; 507 return true;
508 } 508 }
509 509
510 bool ParseContextFormat1(const ots::OpenTypeFile *file, 510 bool ParseContextFormat1(const ots::Font *font,
511 const uint8_t *data, const size_t length, 511 const uint8_t *data, const size_t length,
512 const uint16_t num_glyphs, 512 const uint16_t num_glyphs,
513 const uint16_t num_lookups) { 513 const uint16_t num_lookups) {
514 ots::Buffer subtable(data, length); 514 ots::Buffer subtable(data, length);
515 515
516 uint16_t offset_coverage = 0; 516 uint16_t offset_coverage = 0;
517 uint16_t rule_set_count = 0; 517 uint16_t rule_set_count = 0;
518 // Skip format field. 518 // Skip format field.
519 if (!subtable.Skip(2) || 519 if (!subtable.Skip(2) ||
520 !subtable.ReadU16(&offset_coverage) || 520 !subtable.ReadU16(&offset_coverage) ||
521 !subtable.ReadU16(&rule_set_count)) { 521 !subtable.ReadU16(&rule_set_count)) {
522 return OTS_FAILURE_MSG("Failed to read header of context format 1"); 522 return OTS_FAILURE_MSG("Failed to read header of context format 1");
523 } 523 }
524 524
525 const unsigned rule_set_end = static_cast<unsigned>(6) + 525 const unsigned rule_set_end = static_cast<unsigned>(6) +
526 rule_set_count * 2; 526 rule_set_count * 2;
527 if (rule_set_end > std::numeric_limits<uint16_t>::max()) { 527 if (rule_set_end > std::numeric_limits<uint16_t>::max()) {
528 return OTS_FAILURE_MSG("Bad end of rule set %d of context format 1", rule_se t_end); 528 return OTS_FAILURE_MSG("Bad end of rule set %d of context format 1", rule_se t_end);
529 } 529 }
530 if (offset_coverage < rule_set_end || offset_coverage >= length) { 530 if (offset_coverage < rule_set_end || offset_coverage >= length) {
531 return OTS_FAILURE_MSG("Bad coverage offset %d in context format 1", offset_ coverage); 531 return OTS_FAILURE_MSG("Bad coverage offset %d in context format 1", offset_ coverage);
532 } 532 }
533 if (!ots::ParseCoverageTable(file, data + offset_coverage, 533 if (!ots::ParseCoverageTable(font, data + offset_coverage,
534 length - offset_coverage, num_glyphs)) { 534 length - offset_coverage, num_glyphs)) {
535 return OTS_FAILURE_MSG("Failed to parse coverage table in context format 1") ; 535 return OTS_FAILURE_MSG("Failed to parse coverage table in context format 1") ;
536 } 536 }
537 537
538 for (unsigned i = 0; i < rule_set_count; ++i) { 538 for (unsigned i = 0; i < rule_set_count; ++i) {
539 uint16_t offset_rule = 0; 539 uint16_t offset_rule = 0;
540 if (!subtable.ReadU16(&offset_rule)) { 540 if (!subtable.ReadU16(&offset_rule)) {
541 return OTS_FAILURE_MSG("Failed to read rule offset %d in context format 1" , i); 541 return OTS_FAILURE_MSG("Failed to read rule offset %d in context format 1" , i);
542 } 542 }
543 if (offset_rule < rule_set_end || offset_rule >= length) { 543 if (offset_rule < rule_set_end || offset_rule >= length) {
544 return OTS_FAILURE_MSG("Bad rule offset %d in rule %d in context format 1" , offset_rule, i); 544 return OTS_FAILURE_MSG("Bad rule offset %d in rule %d in context format 1" , offset_rule, i);
545 } 545 }
546 if (!ParseRuleSetTable(file, data + offset_rule, length - offset_rule, 546 if (!ParseRuleSetTable(font, data + offset_rule, length - offset_rule,
547 num_glyphs, num_lookups)) { 547 num_glyphs, num_lookups)) {
548 return OTS_FAILURE_MSG("Failed to parse rule set %d in context format 1", i); 548 return OTS_FAILURE_MSG("Failed to parse rule set %d in context format 1", i);
549 } 549 }
550 } 550 }
551 551
552 return true; 552 return true;
553 } 553 }
554 554
555 bool ParseClassRuleTable(const ots::OpenTypeFile *file, 555 bool ParseClassRuleTable(const ots::Font *font,
556 const uint8_t *data, const size_t length, 556 const uint8_t *data, const size_t length,
557 const uint16_t num_glyphs, 557 const uint16_t num_glyphs,
558 const uint16_t num_lookups) { 558 const uint16_t num_lookups) {
559 ots::Buffer subtable(data, length); 559 ots::Buffer subtable(data, length);
560 560
561 uint16_t glyph_count = 0; 561 uint16_t glyph_count = 0;
562 uint16_t lookup_count = 0; 562 uint16_t lookup_count = 0;
563 if (!subtable.ReadU16(&glyph_count) || 563 if (!subtable.ReadU16(&glyph_count) ||
564 !subtable.ReadU16(&lookup_count)) { 564 !subtable.ReadU16(&lookup_count)) {
565 return OTS_FAILURE_MSG("Failed to read header of class rule table"); 565 return OTS_FAILURE_MSG("Failed to read header of class rule table");
566 } 566 }
567 567
568 if (glyph_count == 0 || glyph_count >= num_glyphs) { 568 if (glyph_count == 0 || glyph_count >= num_glyphs) {
569 return OTS_FAILURE_MSG("Bad glyph count %d in class rule table", glyph_count ); 569 return OTS_FAILURE_MSG("Bad glyph count %d in class rule table", glyph_count );
570 } 570 }
571 571
572 // ClassRule table contains an array of classes. Each value of classes 572 // ClassRule table contains an array of classes. Each value of classes
573 // could take arbitrary values including zero so we don't check these value. 573 // could take arbitrary values including zero so we don't check these value.
574 const unsigned num_classes = glyph_count - static_cast<unsigned>(1); 574 const unsigned num_classes = glyph_count - static_cast<unsigned>(1);
575 if (!subtable.Skip(2 * num_classes)) { 575 if (!subtable.Skip(2 * num_classes)) {
576 return OTS_FAILURE_MSG("Failed to skip classes in class rule table"); 576 return OTS_FAILURE_MSG("Failed to skip classes in class rule table");
577 } 577 }
578 578
579 for (unsigned i = 0; i < lookup_count; ++i) { 579 for (unsigned i = 0; i < lookup_count; ++i) {
580 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { 580 if (!ParseLookupRecord(font, &subtable, num_glyphs, num_lookups)) {
581 return OTS_FAILURE_MSG("Failed to parse lookup record %d in class rule tab le", i); 581 return OTS_FAILURE_MSG("Failed to parse lookup record %d in class rule tab le", i);
582 } 582 }
583 } 583 }
584 return true; 584 return true;
585 } 585 }
586 586
587 bool ParseClassSetTable(const ots::OpenTypeFile *file, 587 bool ParseClassSetTable(const ots::Font *font,
588 const uint8_t *data, const size_t length, 588 const uint8_t *data, const size_t length,
589 const uint16_t num_glyphs, 589 const uint16_t num_glyphs,
590 const uint16_t num_lookups) { 590 const uint16_t num_lookups) {
591 ots::Buffer subtable(data, length); 591 ots::Buffer subtable(data, length);
592 592
593 uint16_t class_rule_count = 0; 593 uint16_t class_rule_count = 0;
594 if (!subtable.ReadU16(&class_rule_count)) { 594 if (!subtable.ReadU16(&class_rule_count)) {
595 return OTS_FAILURE_MSG("Failed to read class rule count in class set table") ; 595 return OTS_FAILURE_MSG("Failed to read class rule count in class set table") ;
596 } 596 }
597 const unsigned class_rule_end = 597 const unsigned class_rule_end =
598 2 * static_cast<unsigned>(class_rule_count) + 2; 598 2 * static_cast<unsigned>(class_rule_count) + 2;
599 if (class_rule_end > std::numeric_limits<uint16_t>::max()) { 599 if (class_rule_end > std::numeric_limits<uint16_t>::max()) {
600 return OTS_FAILURE_MSG("bad class rule end %d in class set table", class_rul e_end); 600 return OTS_FAILURE_MSG("bad class rule end %d in class set table", class_rul e_end);
601 } 601 }
602 for (unsigned i = 0; i < class_rule_count; ++i) { 602 for (unsigned i = 0; i < class_rule_count; ++i) {
603 uint16_t offset_class_rule = 0; 603 uint16_t offset_class_rule = 0;
604 if (!subtable.ReadU16(&offset_class_rule)) { 604 if (!subtable.ReadU16(&offset_class_rule)) {
605 return OTS_FAILURE_MSG("Failed to read class rule offset %d in class set t able", i); 605 return OTS_FAILURE_MSG("Failed to read class rule offset %d in class set t able", i);
606 } 606 }
607 if (offset_class_rule < class_rule_end || offset_class_rule >= length) { 607 if (offset_class_rule < class_rule_end || offset_class_rule >= length) {
608 return OTS_FAILURE_MSG("Bad class rule offset %d in class %d", offset_clas s_rule, i); 608 return OTS_FAILURE_MSG("Bad class rule offset %d in class %d", offset_clas s_rule, i);
609 } 609 }
610 if (!ParseClassRuleTable(file, data + offset_class_rule, 610 if (!ParseClassRuleTable(font, data + offset_class_rule,
611 length - offset_class_rule, num_glyphs, 611 length - offset_class_rule, num_glyphs,
612 num_lookups)) { 612 num_lookups)) {
613 return OTS_FAILURE_MSG("Failed to parse class rule table %d", i); 613 return OTS_FAILURE_MSG("Failed to parse class rule table %d", i);
614 } 614 }
615 } 615 }
616 616
617 return true; 617 return true;
618 } 618 }
619 619
620 bool ParseContextFormat2(const ots::OpenTypeFile *file, 620 bool ParseContextFormat2(const ots::Font *font,
621 const uint8_t *data, const size_t length, 621 const uint8_t *data, const size_t length,
622 const uint16_t num_glyphs, 622 const uint16_t num_glyphs,
623 const uint16_t num_lookups) { 623 const uint16_t num_lookups) {
624 ots::Buffer subtable(data, length); 624 ots::Buffer subtable(data, length);
625 625
626 uint16_t offset_coverage = 0; 626 uint16_t offset_coverage = 0;
627 uint16_t offset_class_def = 0; 627 uint16_t offset_class_def = 0;
628 uint16_t class_set_cnt = 0; 628 uint16_t class_set_cnt = 0;
629 // Skip format field. 629 // Skip format field.
630 if (!subtable.Skip(2) || 630 if (!subtable.Skip(2) ||
631 !subtable.ReadU16(&offset_coverage) || 631 !subtable.ReadU16(&offset_coverage) ||
632 !subtable.ReadU16(&offset_class_def) || 632 !subtable.ReadU16(&offset_class_def) ||
633 !subtable.ReadU16(&class_set_cnt)) { 633 !subtable.ReadU16(&class_set_cnt)) {
634 return OTS_FAILURE_MSG("Failed to read header for context format 2"); 634 return OTS_FAILURE_MSG("Failed to read header for context format 2");
635 } 635 }
636 636
637 const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8; 637 const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8;
638 if (class_set_end > std::numeric_limits<uint16_t>::max()) { 638 if (class_set_end > std::numeric_limits<uint16_t>::max()) {
639 return OTS_FAILURE_MSG("Bad end of class set %d for context format 2", class _set_end); 639 return OTS_FAILURE_MSG("Bad end of class set %d for context format 2", class _set_end);
640 } 640 }
641 if (offset_coverage < class_set_end || offset_coverage >= length) { 641 if (offset_coverage < class_set_end || offset_coverage >= length) {
642 return OTS_FAILURE_MSG("Bad coverage offset %d in context format 2", offset_ coverage); 642 return OTS_FAILURE_MSG("Bad coverage offset %d in context format 2", offset_ coverage);
643 } 643 }
644 if (!ots::ParseCoverageTable(file, data + offset_coverage, 644 if (!ots::ParseCoverageTable(font, data + offset_coverage,
645 length - offset_coverage, num_glyphs)) { 645 length - offset_coverage, num_glyphs)) {
646 return OTS_FAILURE_MSG("Failed to parse coverage table in context format 2") ; 646 return OTS_FAILURE_MSG("Failed to parse coverage table in context format 2") ;
647 } 647 }
648 648
649 if (offset_class_def < class_set_end || offset_class_def >= length) { 649 if (offset_class_def < class_set_end || offset_class_def >= length) {
650 return OTS_FAILURE_MSG("bad class definition offset %d in context format 2", offset_class_def); 650 return OTS_FAILURE_MSG("bad class definition offset %d in context format 2", offset_class_def);
651 } 651 }
652 if (!ots::ParseClassDefTable(file, data + offset_class_def, 652 if (!ots::ParseClassDefTable(font, data + offset_class_def,
653 length - offset_class_def, 653 length - offset_class_def,
654 num_glyphs, kMaxClassDefValue)) { 654 num_glyphs, kMaxClassDefValue)) {
655 return OTS_FAILURE_MSG("Failed to parse class definition table in context fo rmat 2"); 655 return OTS_FAILURE_MSG("Failed to parse class definition table in context fo rmat 2");
656 } 656 }
657 657
658 for (unsigned i = 0; i < class_set_cnt; ++i) { 658 for (unsigned i = 0; i < class_set_cnt; ++i) {
659 uint16_t offset_class_rule = 0; 659 uint16_t offset_class_rule = 0;
660 if (!subtable.ReadU16(&offset_class_rule)) { 660 if (!subtable.ReadU16(&offset_class_rule)) {
661 return OTS_FAILURE_MSG("Failed to read class rule offset %d in context for mat 2", i); 661 return OTS_FAILURE_MSG("Failed to read class rule offset %d in context for mat 2", i);
662 } 662 }
663 if (offset_class_rule) { 663 if (offset_class_rule) {
664 if (offset_class_rule < class_set_end || offset_class_rule >= length) { 664 if (offset_class_rule < class_set_end || offset_class_rule >= length) {
665 return OTS_FAILURE_MSG("Bad class rule offset %d for rule %d in context format 2", offset_class_rule, i); 665 return OTS_FAILURE_MSG("Bad class rule offset %d for rule %d in context format 2", offset_class_rule, i);
666 } 666 }
667 if (!ParseClassSetTable(file, data + offset_class_rule, 667 if (!ParseClassSetTable(font, data + offset_class_rule,
668 length - offset_class_rule, num_glyphs, 668 length - offset_class_rule, num_glyphs,
669 num_lookups)) { 669 num_lookups)) {
670 return OTS_FAILURE_MSG("Failed to parse class set %d in context format 2 ", i); 670 return OTS_FAILURE_MSG("Failed to parse class set %d in context format 2 ", i);
671 } 671 }
672 } 672 }
673 } 673 }
674 674
675 return true; 675 return true;
676 } 676 }
677 677
678 bool ParseContextFormat3(const ots::OpenTypeFile *file, 678 bool ParseContextFormat3(const ots::Font *font,
679 const uint8_t *data, const size_t length, 679 const uint8_t *data, const size_t length,
680 const uint16_t num_glyphs, 680 const uint16_t num_glyphs,
681 const uint16_t num_lookups) { 681 const uint16_t num_lookups) {
682 ots::Buffer subtable(data, length); 682 ots::Buffer subtable(data, length);
683 683
684 uint16_t glyph_count = 0; 684 uint16_t glyph_count = 0;
685 uint16_t lookup_count = 0; 685 uint16_t lookup_count = 0;
686 // Skip format field. 686 // Skip format field.
687 if (!subtable.Skip(2) || 687 if (!subtable.Skip(2) ||
688 !subtable.ReadU16(&glyph_count) || 688 !subtable.ReadU16(&glyph_count) ||
(...skipping 10 matching lines...) Expand all
699 return OTS_FAILURE_MSG("Bad end of lookup %d in context format 3", lookup_re cord_end); 699 return OTS_FAILURE_MSG("Bad end of lookup %d in context format 3", lookup_re cord_end);
700 } 700 }
701 for (unsigned i = 0; i < glyph_count; ++i) { 701 for (unsigned i = 0; i < glyph_count; ++i) {
702 uint16_t offset_coverage = 0; 702 uint16_t offset_coverage = 0;
703 if (!subtable.ReadU16(&offset_coverage)) { 703 if (!subtable.ReadU16(&offset_coverage)) {
704 return OTS_FAILURE_MSG("Failed to read coverage offset %d in conxtext form at 3", i); 704 return OTS_FAILURE_MSG("Failed to read coverage offset %d in conxtext form at 3", i);
705 } 705 }
706 if (offset_coverage < lookup_record_end || offset_coverage >= length) { 706 if (offset_coverage < lookup_record_end || offset_coverage >= length) {
707 return OTS_FAILURE_MSG("Bad coverage offset %d for glyph %d in context for mat 3", offset_coverage, i); 707 return OTS_FAILURE_MSG("Bad coverage offset %d for glyph %d in context for mat 3", offset_coverage, i);
708 } 708 }
709 if (!ots::ParseCoverageTable(file, data + offset_coverage, 709 if (!ots::ParseCoverageTable(font, data + offset_coverage,
710 length - offset_coverage, num_glyphs)) { 710 length - offset_coverage, num_glyphs)) {
711 return OTS_FAILURE_MSG("Failed to parse coverage table for glyph %d in con text format 3", i); 711 return OTS_FAILURE_MSG("Failed to parse coverage table for glyph %d in con text format 3", i);
712 } 712 }
713 } 713 }
714 714
715 for (unsigned i = 0; i < lookup_count; ++i) { 715 for (unsigned i = 0; i < lookup_count; ++i) {
716 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { 716 if (!ParseLookupRecord(font, &subtable, num_glyphs, num_lookups)) {
717 return OTS_FAILURE_MSG("Failed to parse lookup record %d in context format 3", i); 717 return OTS_FAILURE_MSG("Failed to parse lookup record %d in context format 3", i);
718 } 718 }
719 } 719 }
720 720
721 return true; 721 return true;
722 } 722 }
723 723
724 // Parsers for Chaning Contextual subtables in GSUB/GPOS tables. 724 // Parsers for Chaning Contextual subtables in GSUB/GPOS tables.
725 725
726 bool ParseChainRuleSubtable(const ots::OpenTypeFile *file, 726 bool ParseChainRuleSubtable(const ots::Font *font,
727 const uint8_t *data, const size_t length, 727 const uint8_t *data, const size_t length,
728 const uint16_t num_glyphs, 728 const uint16_t num_glyphs,
729 const uint16_t num_lookups) { 729 const uint16_t num_lookups) {
730 ots::Buffer subtable(data, length); 730 ots::Buffer subtable(data, length);
731 731
732 uint16_t backtrack_count = 0; 732 uint16_t backtrack_count = 0;
733 if (!subtable.ReadU16(&backtrack_count)) { 733 if (!subtable.ReadU16(&backtrack_count)) {
734 return OTS_FAILURE_MSG("Failed to read backtrack count in chain rule subtabl e"); 734 return OTS_FAILURE_MSG("Failed to read backtrack count in chain rule subtabl e");
735 } 735 }
736 if (backtrack_count >= num_glyphs) { 736 if (backtrack_count >= num_glyphs) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 if (glyph_id > num_glyphs) { 778 if (glyph_id > num_glyphs) {
779 return OTS_FAILURE_MSG("Bad glyph id %d for lookadhead glyph %d in chain r ule subtable", glyph_id, i); 779 return OTS_FAILURE_MSG("Bad glyph id %d for lookadhead glyph %d in chain r ule subtable", glyph_id, i);
780 } 780 }
781 } 781 }
782 782
783 uint16_t lookup_count = 0; 783 uint16_t lookup_count = 0;
784 if (!subtable.ReadU16(&lookup_count)) { 784 if (!subtable.ReadU16(&lookup_count)) {
785 return OTS_FAILURE_MSG("Failed to read lookup count in chain rule subtable") ; 785 return OTS_FAILURE_MSG("Failed to read lookup count in chain rule subtable") ;
786 } 786 }
787 for (unsigned i = 0; i < lookup_count; ++i) { 787 for (unsigned i = 0; i < lookup_count; ++i) {
788 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { 788 if (!ParseLookupRecord(font, &subtable, num_glyphs, num_lookups)) {
789 return OTS_FAILURE_MSG("Failed to parse lookup record %d in chain rule sub table", i); 789 return OTS_FAILURE_MSG("Failed to parse lookup record %d in chain rule sub table", i);
790 } 790 }
791 } 791 }
792 792
793 return true; 793 return true;
794 } 794 }
795 795
796 bool ParseChainRuleSetTable(const ots::OpenTypeFile *file, 796 bool ParseChainRuleSetTable(const ots::Font *font,
797 const uint8_t *data, const size_t length, 797 const uint8_t *data, const size_t length,
798 const uint16_t num_glyphs, 798 const uint16_t num_glyphs,
799 const uint16_t num_lookups) { 799 const uint16_t num_lookups) {
800 ots::Buffer subtable(data, length); 800 ots::Buffer subtable(data, length);
801 801
802 uint16_t chain_rule_count = 0; 802 uint16_t chain_rule_count = 0;
803 if (!subtable.ReadU16(&chain_rule_count)) { 803 if (!subtable.ReadU16(&chain_rule_count)) {
804 return OTS_FAILURE_MSG("Failed to read rule count in chain rule set"); 804 return OTS_FAILURE_MSG("Failed to read rule count in chain rule set");
805 } 805 }
806 const unsigned chain_rule_end = 806 const unsigned chain_rule_end =
807 2 * static_cast<unsigned>(chain_rule_count) + 2; 807 2 * static_cast<unsigned>(chain_rule_count) + 2;
808 if (chain_rule_end > std::numeric_limits<uint16_t>::max()) { 808 if (chain_rule_end > std::numeric_limits<uint16_t>::max()) {
809 return OTS_FAILURE_MSG("Bad end of chain rule %d in chain rule set", chain_r ule_end); 809 return OTS_FAILURE_MSG("Bad end of chain rule %d in chain rule set", chain_r ule_end);
810 } 810 }
811 for (unsigned i = 0; i < chain_rule_count; ++i) { 811 for (unsigned i = 0; i < chain_rule_count; ++i) {
812 uint16_t offset_chain_rule = 0; 812 uint16_t offset_chain_rule = 0;
813 if (!subtable.ReadU16(&offset_chain_rule)) { 813 if (!subtable.ReadU16(&offset_chain_rule)) {
814 return OTS_FAILURE_MSG("Failed to read chain rule offset %d in chain rule set", i); 814 return OTS_FAILURE_MSG("Failed to read chain rule offset %d in chain rule set", i);
815 } 815 }
816 if (offset_chain_rule < chain_rule_end || offset_chain_rule >= length) { 816 if (offset_chain_rule < chain_rule_end || offset_chain_rule >= length) {
817 return OTS_FAILURE_MSG("Bad chain rule offset %d for chain rule %d in chai n rule set", offset_chain_rule, i); 817 return OTS_FAILURE_MSG("Bad chain rule offset %d for chain rule %d in chai n rule set", offset_chain_rule, i);
818 } 818 }
819 if (!ParseChainRuleSubtable(file, data + offset_chain_rule, 819 if (!ParseChainRuleSubtable(font, data + offset_chain_rule,
820 length - offset_chain_rule, 820 length - offset_chain_rule,
821 num_glyphs, num_lookups)) { 821 num_glyphs, num_lookups)) {
822 return OTS_FAILURE_MSG("Failed to parse chain rule %d in chain rule set", i); 822 return OTS_FAILURE_MSG("Failed to parse chain rule %d in chain rule set", i);
823 } 823 }
824 } 824 }
825 825
826 return true; 826 return true;
827 } 827 }
828 828
829 bool ParseChainContextFormat1(const ots::OpenTypeFile *file, 829 bool ParseChainContextFormat1(const ots::Font *font,
830 const uint8_t *data, const size_t length, 830 const uint8_t *data, const size_t length,
831 const uint16_t num_glyphs, 831 const uint16_t num_glyphs,
832 const uint16_t num_lookups) { 832 const uint16_t num_lookups) {
833 ots::Buffer subtable(data, length); 833 ots::Buffer subtable(data, length);
834 834
835 uint16_t offset_coverage = 0; 835 uint16_t offset_coverage = 0;
836 uint16_t chain_rule_set_count = 0; 836 uint16_t chain_rule_set_count = 0;
837 // Skip format field. 837 // Skip format field.
838 if (!subtable.Skip(2) || 838 if (!subtable.Skip(2) ||
839 !subtable.ReadU16(&offset_coverage) || 839 !subtable.ReadU16(&offset_coverage) ||
840 !subtable.ReadU16(&chain_rule_set_count)) { 840 !subtable.ReadU16(&chain_rule_set_count)) {
841 return OTS_FAILURE_MSG("Failed to read header of chain context format 1"); 841 return OTS_FAILURE_MSG("Failed to read header of chain context format 1");
842 } 842 }
843 843
844 const unsigned chain_rule_set_end = 844 const unsigned chain_rule_set_end =
845 2 * static_cast<unsigned>(chain_rule_set_count) + 6; 845 2 * static_cast<unsigned>(chain_rule_set_count) + 6;
846 if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) { 846 if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) {
847 return OTS_FAILURE_MSG("Bad chain rule end %d in chain context format 1", ch ain_rule_set_end); 847 return OTS_FAILURE_MSG("Bad chain rule end %d in chain context format 1", ch ain_rule_set_end);
848 } 848 }
849 if (offset_coverage < chain_rule_set_end || offset_coverage >= length) { 849 if (offset_coverage < chain_rule_set_end || offset_coverage >= length) {
850 return OTS_FAILURE_MSG("Bad coverage offset %d in chain context format 1", c hain_rule_set_end); 850 return OTS_FAILURE_MSG("Bad coverage offset %d in chain context format 1", c hain_rule_set_end);
851 } 851 }
852 if (!ots::ParseCoverageTable(file, data + offset_coverage, 852 if (!ots::ParseCoverageTable(font, data + offset_coverage,
853 length - offset_coverage, num_glyphs)) { 853 length - offset_coverage, num_glyphs)) {
854 return OTS_FAILURE_MSG("Failed to parse coverage table for chain context for mat 1"); 854 return OTS_FAILURE_MSG("Failed to parse coverage table for chain context for mat 1");
855 } 855 }
856 856
857 for (unsigned i = 0; i < chain_rule_set_count; ++i) { 857 for (unsigned i = 0; i < chain_rule_set_count; ++i) {
858 uint16_t offset_chain_rule_set = 0; 858 uint16_t offset_chain_rule_set = 0;
859 if (!subtable.ReadU16(&offset_chain_rule_set)) { 859 if (!subtable.ReadU16(&offset_chain_rule_set)) {
860 return OTS_FAILURE_MSG("Failed to read chain rule offset %d in chain conte xt format 1", i); 860 return OTS_FAILURE_MSG("Failed to read chain rule offset %d in chain conte xt format 1", i);
861 } 861 }
862 if (offset_chain_rule_set < chain_rule_set_end || 862 if (offset_chain_rule_set < chain_rule_set_end ||
863 offset_chain_rule_set >= length) { 863 offset_chain_rule_set >= length) {
864 return OTS_FAILURE_MSG("Bad chain rule set offset %d for chain rule set %d in chain context format 1", offset_chain_rule_set, i); 864 return OTS_FAILURE_MSG("Bad chain rule set offset %d for chain rule set %d in chain context format 1", offset_chain_rule_set, i);
865 } 865 }
866 if (!ParseChainRuleSetTable(file, data + offset_chain_rule_set, 866 if (!ParseChainRuleSetTable(font, data + offset_chain_rule_set,
867 length - offset_chain_rule_set, 867 length - offset_chain_rule_set,
868 num_glyphs, num_lookups)) { 868 num_glyphs, num_lookups)) {
869 return OTS_FAILURE_MSG("Failed to parse chain rule set %d in chain context format 1", i); 869 return OTS_FAILURE_MSG("Failed to parse chain rule set %d in chain context format 1", i);
870 } 870 }
871 } 871 }
872 872
873 return true; 873 return true;
874 } 874 }
875 875
876 bool ParseChainClassRuleSubtable(const ots::OpenTypeFile *file, 876 bool ParseChainClassRuleSubtable(const ots::Font *font,
877 const uint8_t *data, const size_t length, 877 const uint8_t *data, const size_t length,
878 const uint16_t num_glyphs, 878 const uint16_t num_glyphs,
879 const uint16_t num_lookups) { 879 const uint16_t num_lookups) {
880 ots::Buffer subtable(data, length); 880 ots::Buffer subtable(data, length);
881 881
882 // In this subtable, we don't check the value of classes for now since 882 // In this subtable, we don't check the value of classes for now since
883 // these could take arbitrary values. 883 // these could take arbitrary values.
884 884
885 uint16_t backtrack_count = 0; 885 uint16_t backtrack_count = 0;
886 if (!subtable.ReadU16(&backtrack_count)) { 886 if (!subtable.ReadU16(&backtrack_count)) {
(...skipping 26 matching lines...) Expand all
913 } 913 }
914 if (!subtable.Skip(2 * lookahead_count)) { 914 if (!subtable.Skip(2 * lookahead_count)) {
915 return OTS_FAILURE_MSG("Failed to skip lookahead offsets in chain class rule subtable"); 915 return OTS_FAILURE_MSG("Failed to skip lookahead offsets in chain class rule subtable");
916 } 916 }
917 917
918 uint16_t lookup_count = 0; 918 uint16_t lookup_count = 0;
919 if (!subtable.ReadU16(&lookup_count)) { 919 if (!subtable.ReadU16(&lookup_count)) {
920 return OTS_FAILURE_MSG("Failed to read lookup count in chain class rule subt able"); 920 return OTS_FAILURE_MSG("Failed to read lookup count in chain class rule subt able");
921 } 921 }
922 for (unsigned i = 0; i < lookup_count; ++i) { 922 for (unsigned i = 0; i < lookup_count; ++i) {
923 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { 923 if (!ParseLookupRecord(font, &subtable, num_glyphs, num_lookups)) {
924 return OTS_FAILURE_MSG("Failed to parse lookup record %d in chain class ru le subtable", i); 924 return OTS_FAILURE_MSG("Failed to parse lookup record %d in chain class ru le subtable", i);
925 } 925 }
926 } 926 }
927 927
928 return true; 928 return true;
929 } 929 }
930 930
931 bool ParseChainClassSetTable(const ots::OpenTypeFile *file, 931 bool ParseChainClassSetTable(const ots::Font *font,
932 const uint8_t *data, const size_t length, 932 const uint8_t *data, const size_t length,
933 const uint16_t num_glyphs, 933 const uint16_t num_glyphs,
934 const uint16_t num_lookups) { 934 const uint16_t num_lookups) {
935 ots::Buffer subtable(data, length); 935 ots::Buffer subtable(data, length);
936 936
937 uint16_t chain_class_rule_count = 0; 937 uint16_t chain_class_rule_count = 0;
938 if (!subtable.ReadU16(&chain_class_rule_count)) { 938 if (!subtable.ReadU16(&chain_class_rule_count)) {
939 return OTS_FAILURE_MSG("Failed to read rule count in chain class set"); 939 return OTS_FAILURE_MSG("Failed to read rule count in chain class set");
940 } 940 }
941 const unsigned chain_class_rule_end = 941 const unsigned chain_class_rule_end =
942 2 * static_cast<unsigned>(chain_class_rule_count) + 2; 942 2 * static_cast<unsigned>(chain_class_rule_count) + 2;
943 if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) { 943 if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) {
944 return OTS_FAILURE_MSG("Bad end of chain class set %d in chain class set", c hain_class_rule_end); 944 return OTS_FAILURE_MSG("Bad end of chain class set %d in chain class set", c hain_class_rule_end);
945 } 945 }
946 for (unsigned i = 0; i < chain_class_rule_count; ++i) { 946 for (unsigned i = 0; i < chain_class_rule_count; ++i) {
947 uint16_t offset_chain_class_rule = 0; 947 uint16_t offset_chain_class_rule = 0;
948 if (!subtable.ReadU16(&offset_chain_class_rule)) { 948 if (!subtable.ReadU16(&offset_chain_class_rule)) {
949 return OTS_FAILURE_MSG("Failed to read chain class rule offset %d in chain class set", i); 949 return OTS_FAILURE_MSG("Failed to read chain class rule offset %d in chain class set", i);
950 } 950 }
951 if (offset_chain_class_rule < chain_class_rule_end || 951 if (offset_chain_class_rule < chain_class_rule_end ||
952 offset_chain_class_rule >= length) { 952 offset_chain_class_rule >= length) {
953 return OTS_FAILURE_MSG("Bad chain class rule offset %d for chain class %d in chain class set", offset_chain_class_rule, i); 953 return OTS_FAILURE_MSG("Bad chain class rule offset %d for chain class %d in chain class set", offset_chain_class_rule, i);
954 } 954 }
955 if (!ParseChainClassRuleSubtable(file, data + offset_chain_class_rule, 955 if (!ParseChainClassRuleSubtable(font, data + offset_chain_class_rule,
956 length - offset_chain_class_rule, 956 length - offset_chain_class_rule,
957 num_glyphs, num_lookups)) { 957 num_glyphs, num_lookups)) {
958 return OTS_FAILURE_MSG("Failed to parse chain class rule %d in chain class set", i); 958 return OTS_FAILURE_MSG("Failed to parse chain class rule %d in chain class set", i);
959 } 959 }
960 } 960 }
961 961
962 return true; 962 return true;
963 } 963 }
964 964
965 bool ParseChainContextFormat2(const ots::OpenTypeFile *file, 965 bool ParseChainContextFormat2(const ots::Font *font,
966 const uint8_t *data, const size_t length, 966 const uint8_t *data, const size_t length,
967 const uint16_t num_glyphs, 967 const uint16_t num_glyphs,
968 const uint16_t num_lookups) { 968 const uint16_t num_lookups) {
969 ots::Buffer subtable(data, length); 969 ots::Buffer subtable(data, length);
970 970
971 uint16_t offset_coverage = 0; 971 uint16_t offset_coverage = 0;
972 uint16_t offset_backtrack_class_def = 0; 972 uint16_t offset_backtrack_class_def = 0;
973 uint16_t offset_input_class_def = 0; 973 uint16_t offset_input_class_def = 0;
974 uint16_t offset_lookahead_class_def = 0; 974 uint16_t offset_lookahead_class_def = 0;
975 uint16_t chain_class_set_count = 0; 975 uint16_t chain_class_set_count = 0;
976 // Skip format field. 976 // Skip format field.
977 if (!subtable.Skip(2) || 977 if (!subtable.Skip(2) ||
978 !subtable.ReadU16(&offset_coverage) || 978 !subtable.ReadU16(&offset_coverage) ||
979 !subtable.ReadU16(&offset_backtrack_class_def) || 979 !subtable.ReadU16(&offset_backtrack_class_def) ||
980 !subtable.ReadU16(&offset_input_class_def) || 980 !subtable.ReadU16(&offset_input_class_def) ||
981 !subtable.ReadU16(&offset_lookahead_class_def) || 981 !subtable.ReadU16(&offset_lookahead_class_def) ||
982 !subtable.ReadU16(&chain_class_set_count)) { 982 !subtable.ReadU16(&chain_class_set_count)) {
983 return OTS_FAILURE_MSG("Failed to read header of chain context format 2"); 983 return OTS_FAILURE_MSG("Failed to read header of chain context format 2");
984 } 984 }
985 985
986 const unsigned chain_class_set_end = 986 const unsigned chain_class_set_end =
987 2 * static_cast<unsigned>(chain_class_set_count) + 12; 987 2 * static_cast<unsigned>(chain_class_set_count) + 12;
988 if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) { 988 if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) {
989 return OTS_FAILURE_MSG("Bad chain class set end %d in chain context format 2 ", chain_class_set_end); 989 return OTS_FAILURE_MSG("Bad chain class set end %d in chain context format 2 ", chain_class_set_end);
990 } 990 }
991 if (offset_coverage < chain_class_set_end || offset_coverage >= length) { 991 if (offset_coverage < chain_class_set_end || offset_coverage >= length) {
992 return OTS_FAILURE_MSG("Bad coverage offset %d in chain context format 2", o ffset_coverage); 992 return OTS_FAILURE_MSG("Bad coverage offset %d in chain context format 2", o ffset_coverage);
993 } 993 }
994 if (!ots::ParseCoverageTable(file, data + offset_coverage, 994 if (!ots::ParseCoverageTable(font, data + offset_coverage,
995 length - offset_coverage, num_glyphs)) { 995 length - offset_coverage, num_glyphs)) {
996 return OTS_FAILURE_MSG("Failed to parse coverage table in chain context form at 2"); 996 return OTS_FAILURE_MSG("Failed to parse coverage table in chain context form at 2");
997 } 997 }
998 998
999 // Classes for backtrack/lookahead sequences might not be defined. 999 // Classes for backtrack/lookahead sequences might not be defined.
1000 if (offset_backtrack_class_def) { 1000 if (offset_backtrack_class_def) {
1001 if (offset_backtrack_class_def < chain_class_set_end || 1001 if (offset_backtrack_class_def < chain_class_set_end ||
1002 offset_backtrack_class_def >= length) { 1002 offset_backtrack_class_def >= length) {
1003 return OTS_FAILURE_MSG("Bad backtrack class offset %d in chain context for mat 2", offset_backtrack_class_def); 1003 return OTS_FAILURE_MSG("Bad backtrack class offset %d in chain context for mat 2", offset_backtrack_class_def);
1004 } 1004 }
1005 if (!ots::ParseClassDefTable(file, data + offset_backtrack_class_def, 1005 if (!ots::ParseClassDefTable(font, data + offset_backtrack_class_def,
1006 length - offset_backtrack_class_def, 1006 length - offset_backtrack_class_def,
1007 num_glyphs, kMaxClassDefValue)) { 1007 num_glyphs, kMaxClassDefValue)) {
1008 return OTS_FAILURE_MSG("Failed to parse backtrack class defn table in chai n context format 2"); 1008 return OTS_FAILURE_MSG("Failed to parse backtrack class defn table in chai n context format 2");
1009 } 1009 }
1010 } 1010 }
1011 1011
1012 if (offset_input_class_def < chain_class_set_end || 1012 if (offset_input_class_def < chain_class_set_end ||
1013 offset_input_class_def >= length) { 1013 offset_input_class_def >= length) {
1014 return OTS_FAILURE_MSG("Bad input class defn offset %d in chain context form at 2", offset_input_class_def); 1014 return OTS_FAILURE_MSG("Bad input class defn offset %d in chain context form at 2", offset_input_class_def);
1015 } 1015 }
1016 if (!ots::ParseClassDefTable(file, data + offset_input_class_def, 1016 if (!ots::ParseClassDefTable(font, data + offset_input_class_def,
1017 length - offset_input_class_def, 1017 length - offset_input_class_def,
1018 num_glyphs, kMaxClassDefValue)) { 1018 num_glyphs, kMaxClassDefValue)) {
1019 return OTS_FAILURE_MSG("Failed to parse input class defn in chain context fo rmat 2"); 1019 return OTS_FAILURE_MSG("Failed to parse input class defn in chain context fo rmat 2");
1020 } 1020 }
1021 1021
1022 if (offset_lookahead_class_def) { 1022 if (offset_lookahead_class_def) {
1023 if (offset_lookahead_class_def < chain_class_set_end || 1023 if (offset_lookahead_class_def < chain_class_set_end ||
1024 offset_lookahead_class_def >= length) { 1024 offset_lookahead_class_def >= length) {
1025 return OTS_FAILURE_MSG("Bad lookahead class defn offset %d in chain contex t format 2", offset_lookahead_class_def); 1025 return OTS_FAILURE_MSG("Bad lookahead class defn offset %d in chain contex t format 2", offset_lookahead_class_def);
1026 } 1026 }
1027 if (!ots::ParseClassDefTable(file, data + offset_lookahead_class_def, 1027 if (!ots::ParseClassDefTable(font, data + offset_lookahead_class_def,
1028 length - offset_lookahead_class_def, 1028 length - offset_lookahead_class_def,
1029 num_glyphs, kMaxClassDefValue)) { 1029 num_glyphs, kMaxClassDefValue)) {
1030 return OTS_FAILURE_MSG("Failed to parse lookahead class defn in chain cont ext format 2"); 1030 return OTS_FAILURE_MSG("Failed to parse lookahead class defn in chain cont ext format 2");
1031 } 1031 }
1032 } 1032 }
1033 1033
1034 for (unsigned i = 0; i < chain_class_set_count; ++i) { 1034 for (unsigned i = 0; i < chain_class_set_count; ++i) {
1035 uint16_t offset_chain_class_set = 0; 1035 uint16_t offset_chain_class_set = 0;
1036 if (!subtable.ReadU16(&offset_chain_class_set)) { 1036 if (!subtable.ReadU16(&offset_chain_class_set)) {
1037 return OTS_FAILURE_MSG("Failed to read chain class set offset %d", i); 1037 return OTS_FAILURE_MSG("Failed to read chain class set offset %d", i);
1038 } 1038 }
1039 // |offset_chain_class_set| could be NULL. 1039 // |offset_chain_class_set| could be NULL.
1040 if (offset_chain_class_set) { 1040 if (offset_chain_class_set) {
1041 if (offset_chain_class_set < chain_class_set_end || 1041 if (offset_chain_class_set < chain_class_set_end ||
1042 offset_chain_class_set >= length) { 1042 offset_chain_class_set >= length) {
1043 return OTS_FAILURE_MSG("Bad chain set class offset %d for chain set %d i n chain context format 2", offset_chain_class_set, i); 1043 return OTS_FAILURE_MSG("Bad chain set class offset %d for chain set %d i n chain context format 2", offset_chain_class_set, i);
1044 } 1044 }
1045 if (!ParseChainClassSetTable(file, data + offset_chain_class_set, 1045 if (!ParseChainClassSetTable(font, data + offset_chain_class_set,
1046 length - offset_chain_class_set, 1046 length - offset_chain_class_set,
1047 num_glyphs, num_lookups)) { 1047 num_glyphs, num_lookups)) {
1048 return OTS_FAILURE_MSG("Failed to parse chain class set table %d in chai n context format 2", i); 1048 return OTS_FAILURE_MSG("Failed to parse chain class set table %d in chai n context format 2", i);
1049 } 1049 }
1050 } 1050 }
1051 } 1051 }
1052 1052
1053 return true; 1053 return true;
1054 } 1054 }
1055 1055
1056 bool ParseChainContextFormat3(const ots::OpenTypeFile *file, 1056 bool ParseChainContextFormat3(const ots::Font *font,
1057 const uint8_t *data, const size_t length, 1057 const uint8_t *data, const size_t length,
1058 const uint16_t num_glyphs, 1058 const uint16_t num_glyphs,
1059 const uint16_t num_lookups) { 1059 const uint16_t num_lookups) {
1060 ots::Buffer subtable(data, length); 1060 ots::Buffer subtable(data, length);
1061 1061
1062 uint16_t backtrack_count = 0; 1062 uint16_t backtrack_count = 0;
1063 // Skip format field. 1063 // Skip format field.
1064 if (!subtable.Skip(2) || 1064 if (!subtable.Skip(2) ||
1065 !subtable.ReadU16(&backtrack_count)) { 1065 !subtable.ReadU16(&backtrack_count)) {
1066 return OTS_FAILURE_MSG("Failed to read backtrack count in chain context form at 3"); 1066 return OTS_FAILURE_MSG("Failed to read backtrack count in chain context form at 3");
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 } 1120 }
1121 if (offsets_lookahead.size() != lookahead_count) { 1121 if (offsets_lookahead.size() != lookahead_count) {
1122 return OTS_FAILURE_MSG("Bad lookahead offsets size %ld in chain context form at 3", offsets_lookahead.size()); 1122 return OTS_FAILURE_MSG("Bad lookahead offsets size %ld in chain context form at 3", offsets_lookahead.size());
1123 } 1123 }
1124 1124
1125 uint16_t lookup_count = 0; 1125 uint16_t lookup_count = 0;
1126 if (!subtable.ReadU16(&lookup_count)) { 1126 if (!subtable.ReadU16(&lookup_count)) {
1127 return OTS_FAILURE_MSG("Failed to read lookup count in chain context format 3"); 1127 return OTS_FAILURE_MSG("Failed to read lookup count in chain context format 3");
1128 } 1128 }
1129 for (unsigned i = 0; i < lookup_count; ++i) { 1129 for (unsigned i = 0; i < lookup_count; ++i) {
1130 if (!ParseLookupRecord(file, &subtable, num_glyphs, num_lookups)) { 1130 if (!ParseLookupRecord(font, &subtable, num_glyphs, num_lookups)) {
1131 return OTS_FAILURE_MSG("Failed to parse lookup %d in chain context format 3", i); 1131 return OTS_FAILURE_MSG("Failed to parse lookup %d in chain context format 3", i);
1132 } 1132 }
1133 } 1133 }
1134 1134
1135 const unsigned lookup_record_end = 1135 const unsigned lookup_record_end =
1136 2 * (static_cast<unsigned>(backtrack_count) + 1136 2 * (static_cast<unsigned>(backtrack_count) +
1137 static_cast<unsigned>(input_count) + 1137 static_cast<unsigned>(input_count) +
1138 static_cast<unsigned>(lookahead_count)) + 1138 static_cast<unsigned>(lookahead_count)) +
1139 4 * static_cast<unsigned>(lookup_count) + 10; 1139 4 * static_cast<unsigned>(lookup_count) + 10;
1140 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) { 1140 if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
1141 return OTS_FAILURE_MSG("Bad end of lookup record %d in chain context format 3", lookup_record_end); 1141 return OTS_FAILURE_MSG("Bad end of lookup record %d in chain context format 3", lookup_record_end);
1142 } 1142 }
1143 for (unsigned i = 0; i < backtrack_count; ++i) { 1143 for (unsigned i = 0; i < backtrack_count; ++i) {
1144 if (offsets_backtrack[i] < lookup_record_end || 1144 if (offsets_backtrack[i] < lookup_record_end ||
1145 offsets_backtrack[i] >= length) { 1145 offsets_backtrack[i] >= length) {
1146 return OTS_FAILURE_MSG("Bad backtrack offset of %d for backtrack %d in cha in context format 3", offsets_backtrack[i], i); 1146 return OTS_FAILURE_MSG("Bad backtrack offset of %d for backtrack %d in cha in context format 3", offsets_backtrack[i], i);
1147 } 1147 }
1148 if (!ots::ParseCoverageTable(file, data + offsets_backtrack[i], 1148 if (!ots::ParseCoverageTable(font, data + offsets_backtrack[i],
1149 length - offsets_backtrack[i], num_glyphs)) { 1149 length - offsets_backtrack[i], num_glyphs)) {
1150 return OTS_FAILURE_MSG("Failed to parse backtrack coverage %d in chain con text format 3", i); 1150 return OTS_FAILURE_MSG("Failed to parse backtrack coverage %d in chain con text format 3", i);
1151 } 1151 }
1152 } 1152 }
1153 for (unsigned i = 0; i < input_count; ++i) { 1153 for (unsigned i = 0; i < input_count; ++i) {
1154 if (offsets_input[i] < lookup_record_end || offsets_input[i] >= length) { 1154 if (offsets_input[i] < lookup_record_end || offsets_input[i] >= length) {
1155 return OTS_FAILURE_MSG("Bad input offset %d for input %d in chain context format 3", offsets_input[i], i); 1155 return OTS_FAILURE_MSG("Bad input offset %d for input %d in chain context format 3", offsets_input[i], i);
1156 } 1156 }
1157 if (!ots::ParseCoverageTable(file, data + offsets_input[i], 1157 if (!ots::ParseCoverageTable(font, data + offsets_input[i],
1158 length - offsets_input[i], num_glyphs)) { 1158 length - offsets_input[i], num_glyphs)) {
1159 return OTS_FAILURE_MSG("Failed to parse input coverage table %d in chain c ontext format 3", i); 1159 return OTS_FAILURE_MSG("Failed to parse input coverage table %d in chain c ontext format 3", i);
1160 } 1160 }
1161 } 1161 }
1162 for (unsigned i = 0; i < lookahead_count; ++i) { 1162 for (unsigned i = 0; i < lookahead_count; ++i) {
1163 if (offsets_lookahead[i] < lookup_record_end || 1163 if (offsets_lookahead[i] < lookup_record_end ||
1164 offsets_lookahead[i] >= length) { 1164 offsets_lookahead[i] >= length) {
1165 return OTS_FAILURE_MSG("Bad lookadhead offset %d for lookahead %d in chain context format 3", offsets_lookahead[i], i); 1165 return OTS_FAILURE_MSG("Bad lookadhead offset %d for lookahead %d in chain context format 3", offsets_lookahead[i], i);
1166 } 1166 }
1167 if (!ots::ParseCoverageTable(file, data + offsets_lookahead[i], 1167 if (!ots::ParseCoverageTable(font, data + offsets_lookahead[i],
1168 length - offsets_lookahead[i], num_glyphs)) { 1168 length - offsets_lookahead[i], num_glyphs)) {
1169 return OTS_FAILURE_MSG("Failed to parse lookahead coverage table %d in cha in context format 3", i); 1169 return OTS_FAILURE_MSG("Failed to parse lookahead coverage table %d in cha in context format 3", i);
1170 } 1170 }
1171 } 1171 }
1172 1172
1173 return true; 1173 return true;
1174 } 1174 }
1175 1175
1176 } // namespace 1176 } // namespace
1177 1177
1178 namespace ots { 1178 namespace ots {
1179 1179
1180 bool LookupSubtableParser::Parse(const OpenTypeFile *file, const uint8_t *data, 1180 bool LookupSubtableParser::Parse(const Font *font, const uint8_t *data,
1181 const size_t length, 1181 const size_t length,
1182 const uint16_t lookup_type) const { 1182 const uint16_t lookup_type) const {
1183 for (unsigned i = 0; i < num_types; ++i) { 1183 for (unsigned i = 0; i < num_types; ++i) {
1184 if (parsers[i].type == lookup_type && parsers[i].parse) { 1184 if (parsers[i].type == lookup_type && parsers[i].parse) {
1185 if (!parsers[i].parse(file, data, length)) { 1185 if (!parsers[i].parse(font, data, length)) {
1186 return OTS_FAILURE_MSG("Failed to parse lookup subtable %d", i); 1186 return OTS_FAILURE_MSG("Failed to parse lookup subtable %d", i);
1187 } 1187 }
1188 return true; 1188 return true;
1189 } 1189 }
1190 } 1190 }
1191 return OTS_FAILURE_MSG("No lookup subtables to parse"); 1191 return OTS_FAILURE_MSG("No lookup subtables to parse");
1192 } 1192 }
1193 1193
1194 // Parsing ScriptListTable requires number of features so we need to 1194 // Parsing ScriptListTable requires number of features so we need to
1195 // parse FeatureListTable before calling this function. 1195 // parse FeatureListTable before calling this function.
1196 bool ParseScriptListTable(const ots::OpenTypeFile *file, 1196 bool ParseScriptListTable(const ots::Font *font,
1197 const uint8_t *data, const size_t length, 1197 const uint8_t *data, const size_t length,
1198 const uint16_t num_features) { 1198 const uint16_t num_features) {
1199 Buffer subtable(data, length); 1199 Buffer subtable(data, length);
1200 1200
1201 uint16_t script_count = 0; 1201 uint16_t script_count = 0;
1202 if (!subtable.ReadU16(&script_count)) { 1202 if (!subtable.ReadU16(&script_count)) {
1203 return OTS_FAILURE_MSG("Failed to read script count in script list table"); 1203 return OTS_FAILURE_MSG("Failed to read script count in script list table");
1204 } 1204 }
1205 1205
1206 const unsigned script_record_end = 1206 const unsigned script_record_end =
(...skipping 12 matching lines...) Expand all
1219 } 1219 }
1220 // Script tags should be arranged alphabetically by tag 1220 // Script tags should be arranged alphabetically by tag
1221 if (last_tag != 0 && last_tag > record.tag) { 1221 if (last_tag != 0 && last_tag > record.tag) {
1222 // Several fonts don't arrange tags alphabetically. 1222 // Several fonts don't arrange tags alphabetically.
1223 // It seems that the order of tags might not be a security issue 1223 // It seems that the order of tags might not be a security issue
1224 // so we just warn it. 1224 // so we just warn it.
1225 OTS_WARNING("tags aren't arranged alphabetically."); 1225 OTS_WARNING("tags aren't arranged alphabetically.");
1226 } 1226 }
1227 last_tag = record.tag; 1227 last_tag = record.tag;
1228 if (record.offset < script_record_end || record.offset >= length) { 1228 if (record.offset < script_record_end || record.offset >= length) {
1229 return OTS_FAILURE_MSG("Bad record offset %d for script %4.4s entry %d in script list table", record.offset, (char *)&record.tag, i); 1229 return OTS_FAILURE_MSG("Bad record offset %d for script %c%c%c%c entry %d in script list table", record.offset, OTS_UNTAG(record.tag), i);
1230 } 1230 }
1231 script_list.push_back(record); 1231 script_list.push_back(record);
1232 } 1232 }
1233 if (script_list.size() != script_count) { 1233 if (script_list.size() != script_count) {
1234 return OTS_FAILURE_MSG("Bad script list size %ld in script list table", scri pt_list.size()); 1234 return OTS_FAILURE_MSG("Bad script list size %ld in script list table", scri pt_list.size());
1235 } 1235 }
1236 1236
1237 // Check script records. 1237 // Check script records.
1238 for (unsigned i = 0; i < script_count; ++i) { 1238 for (unsigned i = 0; i < script_count; ++i) {
1239 if (!ParseScriptTable(file, data + script_list[i].offset, 1239 if (!ParseScriptTable(font, data + script_list[i].offset,
1240 length - script_list[i].offset, 1240 length - script_list[i].offset,
1241 script_list[i].tag, num_features)) { 1241 script_list[i].tag, num_features)) {
1242 return OTS_FAILURE_MSG("Failed to parse script table %d", i); 1242 return OTS_FAILURE_MSG("Failed to parse script table %d", i);
1243 } 1243 }
1244 } 1244 }
1245 1245
1246 return true; 1246 return true;
1247 } 1247 }
1248 1248
1249 // Parsing FeatureListTable requires number of lookups so we need to parse 1249 // Parsing FeatureListTable requires number of lookups so we need to parse
1250 // LookupListTable before calling this function. 1250 // LookupListTable before calling this function.
1251 bool ParseFeatureListTable(const ots::OpenTypeFile *file, 1251 bool ParseFeatureListTable(const ots::Font *font,
1252 const uint8_t *data, const size_t length, 1252 const uint8_t *data, const size_t length,
1253 const uint16_t num_lookups, 1253 const uint16_t num_lookups,
1254 uint16_t* num_features) { 1254 uint16_t* num_features) {
1255 Buffer subtable(data, length); 1255 Buffer subtable(data, length);
1256 1256
1257 uint16_t feature_count = 0; 1257 uint16_t feature_count = 0;
1258 if (!subtable.ReadU16(&feature_count)) { 1258 if (!subtable.ReadU16(&feature_count)) {
1259 return OTS_FAILURE_MSG("Failed to read feature count"); 1259 return OTS_FAILURE_MSG("Failed to read feature count");
1260 } 1260 }
1261 1261
(...skipping 13 matching lines...) Expand all
1275 // Feature record array should be arranged alphabetically by tag 1275 // Feature record array should be arranged alphabetically by tag
1276 if (last_tag != 0 && last_tag > feature_records[i].tag) { 1276 if (last_tag != 0 && last_tag > feature_records[i].tag) {
1277 // Several fonts don't arrange tags alphabetically. 1277 // Several fonts don't arrange tags alphabetically.
1278 // It seems that the order of tags might not be a security issue 1278 // It seems that the order of tags might not be a security issue
1279 // so we just warn it. 1279 // so we just warn it.
1280 OTS_WARNING("tags aren't arranged alphabetically."); 1280 OTS_WARNING("tags aren't arranged alphabetically.");
1281 } 1281 }
1282 last_tag = feature_records[i].tag; 1282 last_tag = feature_records[i].tag;
1283 if (feature_records[i].offset < feature_record_end || 1283 if (feature_records[i].offset < feature_record_end ||
1284 feature_records[i].offset >= length) { 1284 feature_records[i].offset >= length) {
1285 return OTS_FAILURE_MSG("Bad feature offset %d for feature %d %4.4s", featu re_records[i].offset, i, (char *)&feature_records[i].tag); 1285 return OTS_FAILURE_MSG("Bad feature offset %d for feature %d %c%c%c%c", fe ature_records[i].offset, i, OTS_UNTAG(feature_records[i].tag));
1286 } 1286 }
1287 } 1287 }
1288 1288
1289 for (unsigned i = 0; i < feature_count; ++i) { 1289 for (unsigned i = 0; i < feature_count; ++i) {
1290 if (!ParseFeatureTable(file, data + feature_records[i].offset, 1290 if (!ParseFeatureTable(font, data + feature_records[i].offset,
1291 length - feature_records[i].offset, num_lookups)) { 1291 length - feature_records[i].offset, num_lookups)) {
1292 return OTS_FAILURE_MSG("Failed to parse feature table %d", i); 1292 return OTS_FAILURE_MSG("Failed to parse feature table %d", i);
1293 } 1293 }
1294 } 1294 }
1295 *num_features = feature_count; 1295 *num_features = feature_count;
1296 return true; 1296 return true;
1297 } 1297 }
1298 1298
1299 // For parsing GPOS/GSUB tables, this function should be called at first to 1299 // For parsing GPOS/GSUB tables, this function should be called at first to
1300 // obtain the number of lookups because parsing FeatureTableList requires 1300 // obtain the number of lookups because parsing FeatureTableList requires
1301 // the number. 1301 // the number.
1302 bool ParseLookupListTable(OpenTypeFile *file, const uint8_t *data, 1302 bool ParseLookupListTable(Font *font, const uint8_t *data,
1303 const size_t length, 1303 const size_t length,
1304 const LookupSubtableParser* parser, 1304 const LookupSubtableParser* parser,
1305 uint16_t *num_lookups) { 1305 uint16_t *num_lookups) {
1306 Buffer subtable(data, length); 1306 Buffer subtable(data, length);
1307 1307
1308 if (!subtable.ReadU16(num_lookups)) { 1308 if (!subtable.ReadU16(num_lookups)) {
1309 return OTS_FAILURE_MSG("Failed to read number of lookups"); 1309 return OTS_FAILURE_MSG("Failed to read number of lookups");
1310 } 1310 }
1311 1311
1312 std::vector<uint16_t> lookups; 1312 std::vector<uint16_t> lookups;
(...skipping 11 matching lines...) Expand all
1324 if (offset < lookup_end || offset >= length) { 1324 if (offset < lookup_end || offset >= length) {
1325 return OTS_FAILURE_MSG("Bad lookup offset %d for lookup %d", offset, i); 1325 return OTS_FAILURE_MSG("Bad lookup offset %d for lookup %d", offset, i);
1326 } 1326 }
1327 lookups.push_back(offset); 1327 lookups.push_back(offset);
1328 } 1328 }
1329 if (lookups.size() != *num_lookups) { 1329 if (lookups.size() != *num_lookups) {
1330 return OTS_FAILURE_MSG("Bad lookup offsets list size %ld", lookups.size()); 1330 return OTS_FAILURE_MSG("Bad lookup offsets list size %ld", lookups.size());
1331 } 1331 }
1332 1332
1333 for (unsigned i = 0; i < *num_lookups; ++i) { 1333 for (unsigned i = 0; i < *num_lookups; ++i) {
1334 if (!ParseLookupTable(file, data + lookups[i], length - lookups[i], 1334 if (!ParseLookupTable(font, data + lookups[i], length - lookups[i],
1335 parser)) { 1335 parser)) {
1336 return OTS_FAILURE_MSG("Failed to parse lookup %d", i); 1336 return OTS_FAILURE_MSG("Failed to parse lookup %d", i);
1337 } 1337 }
1338 } 1338 }
1339 1339
1340 return true; 1340 return true;
1341 } 1341 }
1342 1342
1343 bool ParseClassDefTable(const ots::OpenTypeFile *file, 1343 bool ParseClassDefTable(const ots::Font *font,
1344 const uint8_t *data, size_t length, 1344 const uint8_t *data, size_t length,
1345 const uint16_t num_glyphs, 1345 const uint16_t num_glyphs,
1346 const uint16_t num_classes) { 1346 const uint16_t num_classes) {
1347 Buffer subtable(data, length); 1347 Buffer subtable(data, length);
1348 1348
1349 uint16_t format = 0; 1349 uint16_t format = 0;
1350 if (!subtable.ReadU16(&format)) { 1350 if (!subtable.ReadU16(&format)) {
1351 return OTS_FAILURE_MSG("Failed to read class defn format"); 1351 return OTS_FAILURE_MSG("Failed to read class defn format");
1352 } 1352 }
1353 if (format == 1) { 1353 if (format == 1) {
1354 return ParseClassDefFormat1(file, data, length, num_glyphs, num_classes); 1354 return ParseClassDefFormat1(font, data, length, num_glyphs, num_classes);
1355 } else if (format == 2) { 1355 } else if (format == 2) {
1356 return ParseClassDefFormat2(file, data, length, num_glyphs, num_classes); 1356 return ParseClassDefFormat2(font, data, length, num_glyphs, num_classes);
1357 } 1357 }
1358 1358
1359 return OTS_FAILURE_MSG("Bad class defn format %d", format); 1359 return OTS_FAILURE_MSG("Bad class defn format %d", format);
1360 } 1360 }
1361 1361
1362 bool ParseCoverageTable(const ots::OpenTypeFile *file, 1362 bool ParseCoverageTable(const ots::Font *font,
1363 const uint8_t *data, size_t length, 1363 const uint8_t *data, size_t length,
1364 const uint16_t num_glyphs, 1364 const uint16_t num_glyphs,
1365 const uint16_t expected_num_glyphs) { 1365 const uint16_t expected_num_glyphs) {
1366 Buffer subtable(data, length); 1366 Buffer subtable(data, length);
1367 1367
1368 uint16_t format = 0; 1368 uint16_t format = 0;
1369 if (!subtable.ReadU16(&format)) { 1369 if (!subtable.ReadU16(&format)) {
1370 return OTS_FAILURE_MSG("Failed to read coverage table format"); 1370 return OTS_FAILURE_MSG("Failed to read coverage table format");
1371 } 1371 }
1372 if (format == 1) { 1372 if (format == 1) {
1373 return ParseCoverageFormat1(file, data, length, num_glyphs, expected_num_gly phs); 1373 return ParseCoverageFormat1(font, data, length, num_glyphs, expected_num_gly phs);
1374 } else if (format == 2) { 1374 } else if (format == 2) {
1375 return ParseCoverageFormat2(file, data, length, num_glyphs, expected_num_gly phs); 1375 return ParseCoverageFormat2(font, data, length, num_glyphs, expected_num_gly phs);
1376 } 1376 }
1377 1377
1378 return OTS_FAILURE_MSG("Bad coverage table format %d", format); 1378 return OTS_FAILURE_MSG("Bad coverage table format %d", format);
1379 } 1379 }
1380 1380
1381 bool ParseDeviceTable(const ots::OpenTypeFile *file, 1381 bool ParseDeviceTable(const ots::Font *font,
1382 const uint8_t *data, size_t length) { 1382 const uint8_t *data, size_t length) {
1383 Buffer subtable(data, length); 1383 Buffer subtable(data, length);
1384 1384
1385 uint16_t start_size = 0; 1385 uint16_t start_size = 0;
1386 uint16_t end_size = 0; 1386 uint16_t end_size = 0;
1387 uint16_t delta_format = 0; 1387 uint16_t delta_format = 0;
1388 if (!subtable.ReadU16(&start_size) || 1388 if (!subtable.ReadU16(&start_size) ||
1389 !subtable.ReadU16(&end_size) || 1389 !subtable.ReadU16(&end_size) ||
1390 !subtable.ReadU16(&delta_format)) { 1390 !subtable.ReadU16(&delta_format)) {
1391 return OTS_FAILURE_MSG("Failed to read device table header"); 1391 return OTS_FAILURE_MSG("Failed to read device table header");
1392 } 1392 }
1393 if (start_size > end_size) { 1393 if (start_size > end_size) {
1394 return OTS_FAILURE_MSG("bad size range: %u > %u", start_size, end_size); 1394 return OTS_FAILURE_MSG("bad size range: %u > %u", start_size, end_size);
1395 } 1395 }
1396 if (delta_format == 0 || delta_format > kMaxDeltaFormatType) { 1396 if (delta_format == 0 || delta_format > kMaxDeltaFormatType) {
1397 return OTS_FAILURE_MSG("bad delta format: %u", delta_format); 1397 return OTS_FAILURE_MSG("bad delta format: %u", delta_format);
1398 } 1398 }
1399 // The number of delta values per uint16. The device table should contain 1399 // The number of delta values per uint16. The device table should contain
1400 // at least |num_units| * 2 bytes compressed data. 1400 // at least |num_units| * 2 bytes compressed data.
1401 const unsigned num_units = (end_size - start_size) / 1401 const unsigned num_units = (end_size - start_size) /
1402 (1 << (4 - delta_format)) + 1; 1402 (1 << (4 - delta_format)) + 1;
1403 // Just skip |num_units| * 2 bytes since the compressed data could take 1403 // Just skip |num_units| * 2 bytes since the compressed data could take
1404 // arbitrary values. 1404 // arbitrary values.
1405 if (!subtable.Skip(num_units * 2)) { 1405 if (!subtable.Skip(num_units * 2)) {
1406 return OTS_FAILURE_MSG("Failed to skip data in device table"); 1406 return OTS_FAILURE_MSG("Failed to skip data in device table");
1407 } 1407 }
1408 return true; 1408 return true;
1409 } 1409 }
1410 1410
1411 bool ParseContextSubtable(const ots::OpenTypeFile *file, 1411 bool ParseContextSubtable(const ots::Font *font,
1412 const uint8_t *data, const size_t length, 1412 const uint8_t *data, const size_t length,
1413 const uint16_t num_glyphs, 1413 const uint16_t num_glyphs,
1414 const uint16_t num_lookups) { 1414 const uint16_t num_lookups) {
1415 Buffer subtable(data, length); 1415 Buffer subtable(data, length);
1416 1416
1417 uint16_t format = 0; 1417 uint16_t format = 0;
1418 if (!subtable.ReadU16(&format)) { 1418 if (!subtable.ReadU16(&format)) {
1419 return OTS_FAILURE_MSG("Failed to read context subtable format"); 1419 return OTS_FAILURE_MSG("Failed to read context subtable format");
1420 } 1420 }
1421 1421
1422 if (format == 1) { 1422 if (format == 1) {
1423 if (!ParseContextFormat1(file, data, length, num_glyphs, num_lookups)) { 1423 if (!ParseContextFormat1(font, data, length, num_glyphs, num_lookups)) {
1424 return OTS_FAILURE_MSG("Failed to parse context format 1 subtable"); 1424 return OTS_FAILURE_MSG("Failed to parse context format 1 subtable");
1425 } 1425 }
1426 } else if (format == 2) { 1426 } else if (format == 2) {
1427 if (!ParseContextFormat2(file, data, length, num_glyphs, num_lookups)) { 1427 if (!ParseContextFormat2(font, data, length, num_glyphs, num_lookups)) {
1428 return OTS_FAILURE_MSG("Failed to parse context format 2 subtable"); 1428 return OTS_FAILURE_MSG("Failed to parse context format 2 subtable");
1429 } 1429 }
1430 } else if (format == 3) { 1430 } else if (format == 3) {
1431 if (!ParseContextFormat3(file, data, length, num_glyphs, num_lookups)) { 1431 if (!ParseContextFormat3(font, data, length, num_glyphs, num_lookups)) {
1432 return OTS_FAILURE_MSG("Failed to parse context format 3 subtable"); 1432 return OTS_FAILURE_MSG("Failed to parse context format 3 subtable");
1433 } 1433 }
1434 } else { 1434 } else {
1435 return OTS_FAILURE_MSG("Bad context subtable format %d", format); 1435 return OTS_FAILURE_MSG("Bad context subtable format %d", format);
1436 } 1436 }
1437 1437
1438 return true; 1438 return true;
1439 } 1439 }
1440 1440
1441 bool ParseChainingContextSubtable(const ots::OpenTypeFile *file, 1441 bool ParseChainingContextSubtable(const ots::Font *font,
1442 const uint8_t *data, const size_t length, 1442 const uint8_t *data, const size_t length,
1443 const uint16_t num_glyphs, 1443 const uint16_t num_glyphs,
1444 const uint16_t num_lookups) { 1444 const uint16_t num_lookups) {
1445 Buffer subtable(data, length); 1445 Buffer subtable(data, length);
1446 1446
1447 uint16_t format = 0; 1447 uint16_t format = 0;
1448 if (!subtable.ReadU16(&format)) { 1448 if (!subtable.ReadU16(&format)) {
1449 return OTS_FAILURE_MSG("Failed to read chaining context subtable format"); 1449 return OTS_FAILURE_MSG("Failed to read chaining context subtable format");
1450 } 1450 }
1451 1451
1452 if (format == 1) { 1452 if (format == 1) {
1453 if (!ParseChainContextFormat1(file, data, length, num_glyphs, num_lookups)) { 1453 if (!ParseChainContextFormat1(font, data, length, num_glyphs, num_lookups)) {
1454 return OTS_FAILURE_MSG("Failed to parse chaining context format 1 subtable "); 1454 return OTS_FAILURE_MSG("Failed to parse chaining context format 1 subtable ");
1455 } 1455 }
1456 } else if (format == 2) { 1456 } else if (format == 2) {
1457 if (!ParseChainContextFormat2(file, data, length, num_glyphs, num_lookups)) { 1457 if (!ParseChainContextFormat2(font, data, length, num_glyphs, num_lookups)) {
1458 return OTS_FAILURE_MSG("Failed to parse chaining context format 2 subtable "); 1458 return OTS_FAILURE_MSG("Failed to parse chaining context format 2 subtable ");
1459 } 1459 }
1460 } else if (format == 3) { 1460 } else if (format == 3) {
1461 if (!ParseChainContextFormat3(file, data, length, num_glyphs, num_lookups)) { 1461 if (!ParseChainContextFormat3(font, data, length, num_glyphs, num_lookups)) {
1462 return OTS_FAILURE_MSG("Failed to parse chaining context format 3 subtable "); 1462 return OTS_FAILURE_MSG("Failed to parse chaining context format 3 subtable ");
1463 } 1463 }
1464 } else { 1464 } else {
1465 return OTS_FAILURE_MSG("Bad chaining context subtable format %d", format); 1465 return OTS_FAILURE_MSG("Bad chaining context subtable format %d", format);
1466 } 1466 }
1467 1467
1468 return true; 1468 return true;
1469 } 1469 }
1470 1470
1471 bool ParseExtensionSubtable(const OpenTypeFile *file, 1471 bool ParseExtensionSubtable(const Font *font,
1472 const uint8_t *data, const size_t length, 1472 const uint8_t *data, const size_t length,
1473 const LookupSubtableParser* parser) { 1473 const LookupSubtableParser* parser) {
1474 Buffer subtable(data, length); 1474 Buffer subtable(data, length);
1475 1475
1476 uint16_t format = 0; 1476 uint16_t format = 0;
1477 uint16_t lookup_type = 0; 1477 uint16_t lookup_type = 0;
1478 uint32_t offset_extension = 0; 1478 uint32_t offset_extension = 0;
1479 if (!subtable.ReadU16(&format) || 1479 if (!subtable.ReadU16(&format) ||
1480 !subtable.ReadU16(&lookup_type) || 1480 !subtable.ReadU16(&lookup_type) ||
1481 !subtable.ReadU32(&offset_extension)) { 1481 !subtable.ReadU32(&offset_extension)) {
1482 return OTS_FAILURE_MSG("Failed to read extension table header"); 1482 return OTS_FAILURE_MSG("Failed to read extension table header");
1483 } 1483 }
1484 1484
1485 if (format != 1) { 1485 if (format != 1) {
1486 return OTS_FAILURE_MSG("Bad extension table format %d", format); 1486 return OTS_FAILURE_MSG("Bad extension table format %d", format);
1487 } 1487 }
1488 // |lookup_type| should be other than |parser->extension_type|. 1488 // |lookup_type| should be other than |parser->extension_type|.
1489 if (lookup_type < 1 || lookup_type > parser->num_types || 1489 if (lookup_type < 1 || lookup_type > parser->num_types ||
1490 lookup_type == parser->extension_type) { 1490 lookup_type == parser->extension_type) {
1491 return OTS_FAILURE_MSG("Bad lookup type %d in extension table", lookup_type) ; 1491 return OTS_FAILURE_MSG("Bad lookup type %d in extension table", lookup_type) ;
1492 } 1492 }
1493 1493
1494 const unsigned format_end = static_cast<unsigned>(8); 1494 const unsigned format_end = static_cast<unsigned>(8);
1495 if (offset_extension < format_end || 1495 if (offset_extension < format_end ||
1496 offset_extension >= length) { 1496 offset_extension >= length) {
1497 return OTS_FAILURE_MSG("Bad extension offset %d", offset_extension); 1497 return OTS_FAILURE_MSG("Bad extension offset %d", offset_extension);
1498 } 1498 }
1499 1499
1500 // Parse the extension subtable of |lookup_type|. 1500 // Parse the extension subtable of |lookup_type|.
1501 if (!parser->Parse(file, data + offset_extension, length - offset_extension, 1501 if (!parser->Parse(font, data + offset_extension, length - offset_extension,
1502 lookup_type)) { 1502 lookup_type)) {
1503 return OTS_FAILURE_MSG("Failed to parse lookup from extension lookup"); 1503 return OTS_FAILURE_MSG("Failed to parse lookup from extension lookup");
1504 } 1504 }
1505 1505
1506 return true; 1506 return true;
1507 } 1507 }
1508 1508
1509 } // namespace ots 1509 } // namespace ots
1510 1510
1511 #undef TABLE_NAME 1511 #undef TABLE_NAME
OLDNEW
« no previous file with comments | « third_party/ots/src/layout.h ('k') | third_party/ots/src/loca.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698