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

Side by Side Diff: src/gsub.cc

Issue 658573004: Updating to new OTS repo from https://github.com/khaledhosny/ots.git (Closed) Base URL: https://chromium.googlesource.com/external/ots@master
Patch Set: Adding Colored Emoji changes from external/git repo Created 6 years, 2 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
« .gitmodules ('K') | « src/gpos.cc ('k') | src/hdmx.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 "gsub.h" 5 #include "gsub.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <vector> 8 #include <vector>
9 9
10 #include "gdef.h"
11 #include "gpos.h"
12 #include "layout.h" 10 #include "layout.h"
13 #include "maxp.h" 11 #include "maxp.h"
14 12
15 // GSUB - The Glyph Substitution Table 13 // GSUB - The Glyph Substitution Table
16 // http://www.microsoft.com/typography/otspec/gsub.htm 14 // http://www.microsoft.com/typography/otspec/gsub.htm
17 15
16 #define TABLE_NAME "GSUB"
17
18 namespace { 18 namespace {
19 19
20 // The GSUB header size 20 // The GSUB header size
21 const size_t kGsubHeaderSize = 4 + 3 * 2; 21 const size_t kGsubHeaderSize = 4 + 3 * 2;
22 22
23 enum GSUB_TYPE { 23 enum GSUB_TYPE {
24 GSUB_TYPE_SINGLE = 1, 24 GSUB_TYPE_SINGLE = 1,
25 GSUB_TYPE_MULTIPLE = 2, 25 GSUB_TYPE_MULTIPLE = 2,
26 GSUB_TYPE_ALTERNATE = 3, 26 GSUB_TYPE_ALTERNATE = 3,
27 GSUB_TYPE_LIGATURE = 4, 27 GSUB_TYPE_LIGATURE = 4,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 // Single Substitution Subtable 72 // Single Substitution Subtable
73 bool ParseSingleSubstitution(const ots::OpenTypeFile *file, 73 bool ParseSingleSubstitution(const ots::OpenTypeFile *file,
74 const uint8_t *data, const size_t length) { 74 const uint8_t *data, const size_t length) {
75 ots::Buffer subtable(data, length); 75 ots::Buffer subtable(data, length);
76 76
77 uint16_t format = 0; 77 uint16_t format = 0;
78 uint16_t offset_coverage = 0; 78 uint16_t offset_coverage = 0;
79 79
80 if (!subtable.ReadU16(&format) || 80 if (!subtable.ReadU16(&format) ||
81 !subtable.ReadU16(&offset_coverage)) { 81 !subtable.ReadU16(&offset_coverage)) {
82 return OTS_FAILURE(); 82 return OTS_FAILURE_MSG("Failed to read single subst table header");
83 } 83 }
84 84
85 const uint16_t num_glyphs = file->maxp->num_glyphs; 85 const uint16_t num_glyphs = file->maxp->num_glyphs;
86 if (format == 1) { 86 if (format == 1) {
87 // Parse SingleSubstFormat1 87 // Parse SingleSubstFormat1
88 int16_t delta_glyph_id = 0; 88 int16_t delta_glyph_id = 0;
89 if (!subtable.ReadS16(&delta_glyph_id)) { 89 if (!subtable.ReadS16(&delta_glyph_id)) {
90 return OTS_FAILURE(); 90 return OTS_FAILURE_MSG("Failed to read glyph shift from format 1 single su bst table");
91 } 91 }
92 if (std::abs(delta_glyph_id) >= num_glyphs) { 92 if (std::abs(delta_glyph_id) >= num_glyphs) {
93 return OTS_FAILURE(); 93 return OTS_FAILURE_MSG("bad glyph shift of %d in format 1 single subst tab le", delta_glyph_id);
94 } 94 }
95 } else if (format == 2) { 95 } else if (format == 2) {
96 // Parse SingleSubstFormat2 96 // Parse SingleSubstFormat2
97 uint16_t glyph_count = 0; 97 uint16_t glyph_count = 0;
98 if (!subtable.ReadU16(&glyph_count)) { 98 if (!subtable.ReadU16(&glyph_count)) {
99 return OTS_FAILURE(); 99 return OTS_FAILURE_MSG("Failed to read glyph cound in format 2 single subs t table");
100 } 100 }
101 if (glyph_count > num_glyphs) { 101 if (glyph_count > num_glyphs) {
102 return OTS_FAILURE(); 102 return OTS_FAILURE_MSG("Bad glyph count %d > %d in format 2 single subst t able", glyph_count, num_glyphs);
103 } 103 }
104 for (unsigned i = 0; i < glyph_count; ++i) { 104 for (unsigned i = 0; i < glyph_count; ++i) {
105 uint16_t substitute = 0; 105 uint16_t substitute = 0;
106 if (!subtable.ReadU16(&substitute)) { 106 if (!subtable.ReadU16(&substitute)) {
107 return OTS_FAILURE(); 107 return OTS_FAILURE_MSG("Failed to read substitution %d in format 2 singl e subst table", i);
108 } 108 }
109 if (substitute >= num_glyphs) { 109 if (substitute >= num_glyphs) {
110 OTS_WARNING("too large substitute: %u", substitute); 110 return OTS_FAILURE_MSG("too large substitute: %u", substitute);
111 return OTS_FAILURE();
112 } 111 }
113 } 112 }
114 } else { 113 } else {
115 return OTS_FAILURE(); 114 return OTS_FAILURE_MSG("Bad single subst table format %d", format);
116 } 115 }
117 116
118 if (offset_coverage < subtable.offset() || offset_coverage >= length) { 117 if (offset_coverage < subtable.offset() || offset_coverage >= length) {
119 return OTS_FAILURE(); 118 return OTS_FAILURE_MSG("Bad coverage offset %x", offset_coverage);
120 } 119 }
121 if (!ots::ParseCoverageTable(data + offset_coverage, 120 if (!ots::ParseCoverageTable(file, data + offset_coverage,
122 length - offset_coverage, num_glyphs)) { 121 length - offset_coverage, num_glyphs)) {
123 return OTS_FAILURE(); 122 return OTS_FAILURE_MSG("Failed to parse coverage table");
124 } 123 }
125 124
126 return true; 125 return true;
127 } 126 }
128 127
129 bool ParseSequenceTable(const uint8_t *data, const size_t length, 128 bool ParseSequenceTable(const ots::OpenTypeFile *file,
129 const uint8_t *data, const size_t length,
130 const uint16_t num_glyphs) { 130 const uint16_t num_glyphs) {
131 ots::Buffer subtable(data, length); 131 ots::Buffer subtable(data, length);
132 132
133 uint16_t glyph_count = 0; 133 uint16_t glyph_count = 0;
134 if (!subtable.ReadU16(&glyph_count)) { 134 if (!subtable.ReadU16(&glyph_count)) {
135 return OTS_FAILURE(); 135 return OTS_FAILURE_MSG("Failed to read glyph count in sequence table");
136 } 136 }
137 if (glyph_count > num_glyphs) { 137 if (glyph_count > num_glyphs) {
138 return OTS_FAILURE(); 138 return OTS_FAILURE_MSG("bad glyph count %d > %d", glyph_count, num_glyphs);
139 } 139 }
140 for (unsigned i = 0; i < glyph_count; ++i) { 140 for (unsigned i = 0; i < glyph_count; ++i) {
141 uint16_t substitute = 0; 141 uint16_t substitute = 0;
142 if (!subtable.ReadU16(&substitute)) { 142 if (!subtable.ReadU16(&substitute)) {
143 return OTS_FAILURE(); 143 return OTS_FAILURE_MSG("Failedt o read substitution %d in sequence table", i);
144 } 144 }
145 if (substitute >= num_glyphs) { 145 if (substitute >= num_glyphs) {
146 return OTS_FAILURE(); 146 return OTS_FAILURE_MSG("Bad subsitution (%d) %d > %d", i, substitute, num_ glyphs);
147 } 147 }
148 } 148 }
149 149
150 return true; 150 return true;
151 } 151 }
152 152
153 // Lookup Type 2: 153 // Lookup Type 2:
154 // Multiple Substitution Subtable 154 // Multiple Substitution Subtable
155 bool ParseMutipleSubstitution(const ots::OpenTypeFile *file, 155 bool ParseMutipleSubstitution(const ots::OpenTypeFile *file,
156 const uint8_t *data, const size_t length) { 156 const uint8_t *data, const size_t length) {
157 ots::Buffer subtable(data, length); 157 ots::Buffer subtable(data, length);
158 158
159 uint16_t format = 0; 159 uint16_t format = 0;
160 uint16_t offset_coverage = 0; 160 uint16_t offset_coverage = 0;
161 uint16_t sequence_count = 0; 161 uint16_t sequence_count = 0;
162 162
163 if (!subtable.ReadU16(&format) || 163 if (!subtable.ReadU16(&format) ||
164 !subtable.ReadU16(&offset_coverage) || 164 !subtable.ReadU16(&offset_coverage) ||
165 !subtable.ReadU16(&sequence_count)) { 165 !subtable.ReadU16(&sequence_count)) {
166 return OTS_FAILURE(); 166 return OTS_FAILURE_MSG("Can't read header of multiple subst table");
167 } 167 }
168 168
169 if (format != 1) { 169 if (format != 1) {
170 return OTS_FAILURE(); 170 return OTS_FAILURE_MSG("Bad multiple subst table format %d", format);
171 } 171 }
172 172
173 const uint16_t num_glyphs = file->maxp->num_glyphs; 173 const uint16_t num_glyphs = file->maxp->num_glyphs;
174 const unsigned sequence_end = static_cast<unsigned>(6) + 174 const unsigned sequence_end = static_cast<unsigned>(6) +
175 sequence_count * 2; 175 sequence_count * 2;
176 if (sequence_end > std::numeric_limits<uint16_t>::max()) { 176 if (sequence_end > std::numeric_limits<uint16_t>::max()) {
177 return OTS_FAILURE(); 177 return OTS_FAILURE_MSG("Bad segence end %d, in multiple subst", sequence_end );
178 } 178 }
179 for (unsigned i = 0; i < sequence_count; ++i) { 179 for (unsigned i = 0; i < sequence_count; ++i) {
180 uint16_t offset_sequence = 0; 180 uint16_t offset_sequence = 0;
181 if (!subtable.ReadU16(&offset_sequence)) { 181 if (!subtable.ReadU16(&offset_sequence)) {
182 return OTS_FAILURE(); 182 return OTS_FAILURE_MSG("Failed to read sequence offset for sequence %d", i );
183 } 183 }
184 if (offset_sequence < sequence_end || offset_sequence >= length) { 184 if (offset_sequence < sequence_end || offset_sequence >= length) {
185 return OTS_FAILURE(); 185 return OTS_FAILURE_MSG("Bad sequence offset %d for sequence %d", offset_se quence, i);
186 } 186 }
187 if (!ParseSequenceTable(data + offset_sequence, length - offset_sequence, 187 if (!ParseSequenceTable(file, data + offset_sequence, length - offset_sequen ce,
188 num_glyphs)) { 188 num_glyphs)) {
189 return OTS_FAILURE(); 189 return OTS_FAILURE_MSG("Failed to parse sequence table %d", i);
190 } 190 }
191 } 191 }
192 192
193 if (offset_coverage < sequence_end || offset_coverage >= length) { 193 if (offset_coverage < sequence_end || offset_coverage >= length) {
194 return OTS_FAILURE(); 194 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage);
195 } 195 }
196 if (!ots::ParseCoverageTable(data + offset_coverage, 196 if (!ots::ParseCoverageTable(file, data + offset_coverage,
197 length - offset_coverage, num_glyphs)) { 197 length - offset_coverage, num_glyphs)) {
198 return OTS_FAILURE(); 198 return OTS_FAILURE_MSG("Failed to parse coverage table");
199 } 199 }
200 200
201 return true; 201 return true;
202 } 202 }
203 203
204 bool ParseAlternateSetTable(const uint8_t *data, const size_t length, 204 bool ParseAlternateSetTable(const ots::OpenTypeFile *file,
205 const uint8_t *data, const size_t length,
205 const uint16_t num_glyphs) { 206 const uint16_t num_glyphs) {
206 ots::Buffer subtable(data, length); 207 ots::Buffer subtable(data, length);
207 208
208 uint16_t glyph_count = 0; 209 uint16_t glyph_count = 0;
209 if (!subtable.ReadU16(&glyph_count)) { 210 if (!subtable.ReadU16(&glyph_count)) {
210 return OTS_FAILURE(); 211 return OTS_FAILURE_MSG("Failed to read alternate set header");
211 } 212 }
212 if (glyph_count > num_glyphs) { 213 if (glyph_count > num_glyphs) {
213 return OTS_FAILURE(); 214 return OTS_FAILURE_MSG("Bad glyph count %d > %d in alternate set table", gly ph_count, num_glyphs);
214 } 215 }
215 for (unsigned i = 0; i < glyph_count; ++i) { 216 for (unsigned i = 0; i < glyph_count; ++i) {
216 uint16_t alternate = 0; 217 uint16_t alternate = 0;
217 if (!subtable.ReadU16(&alternate)) { 218 if (!subtable.ReadU16(&alternate)) {
218 return OTS_FAILURE(); 219 return OTS_FAILURE_MSG("Can't read alternate %d", i);
219 } 220 }
220 if (alternate >= num_glyphs) { 221 if (alternate >= num_glyphs) {
221 OTS_WARNING("too arge alternate: %u", alternate); 222 return OTS_FAILURE_MSG("Too large alternate: %u", alternate);
222 return OTS_FAILURE();
223 } 223 }
224 } 224 }
225 return true; 225 return true;
226 } 226 }
227 227
228 // Lookup Type 3: 228 // Lookup Type 3:
229 // Alternate Substitution Subtable 229 // Alternate Substitution Subtable
230 bool ParseAlternateSubstitution(const ots::OpenTypeFile *file, 230 bool ParseAlternateSubstitution(const ots::OpenTypeFile *file,
231 const uint8_t *data, const size_t length) { 231 const uint8_t *data, const size_t length) {
232 ots::Buffer subtable(data, length); 232 ots::Buffer subtable(data, length);
233 233
234 uint16_t format = 0; 234 uint16_t format = 0;
235 uint16_t offset_coverage = 0; 235 uint16_t offset_coverage = 0;
236 uint16_t alternate_set_count = 0; 236 uint16_t alternate_set_count = 0;
237 237
238 if (!subtable.ReadU16(&format) || 238 if (!subtable.ReadU16(&format) ||
239 !subtable.ReadU16(&offset_coverage) || 239 !subtable.ReadU16(&offset_coverage) ||
240 !subtable.ReadU16(&alternate_set_count)) { 240 !subtable.ReadU16(&alternate_set_count)) {
241 return OTS_FAILURE(); 241 return OTS_FAILURE_MSG("Can't read alternate subst header");
242 } 242 }
243 243
244 if (format != 1) { 244 if (format != 1) {
245 return OTS_FAILURE(); 245 return OTS_FAILURE_MSG("Bad alternate subst table format %d", format);
246 } 246 }
247 247
248 const uint16_t num_glyphs = file->maxp->num_glyphs; 248 const uint16_t num_glyphs = file->maxp->num_glyphs;
249 const unsigned alternate_set_end = static_cast<unsigned>(6) + 249 const unsigned alternate_set_end = static_cast<unsigned>(6) +
250 alternate_set_count * 2; 250 alternate_set_count * 2;
251 if (alternate_set_end > std::numeric_limits<uint16_t>::max()) { 251 if (alternate_set_end > std::numeric_limits<uint16_t>::max()) {
252 return OTS_FAILURE(); 252 return OTS_FAILURE_MSG("Bad end of alternate set %d", alternate_set_end);
253 } 253 }
254 for (unsigned i = 0; i < alternate_set_count; ++i) { 254 for (unsigned i = 0; i < alternate_set_count; ++i) {
255 uint16_t offset_alternate_set = 0; 255 uint16_t offset_alternate_set = 0;
256 if (!subtable.ReadU16(&offset_alternate_set)) { 256 if (!subtable.ReadU16(&offset_alternate_set)) {
257 return OTS_FAILURE(); 257 return OTS_FAILURE_MSG("Can't read alternate set offset for set %d", i);
258 } 258 }
259 if (offset_alternate_set < alternate_set_end || 259 if (offset_alternate_set < alternate_set_end ||
260 offset_alternate_set >= length) { 260 offset_alternate_set >= length) {
261 return OTS_FAILURE(); 261 return OTS_FAILURE_MSG("Bad alternate set offset %d for set %d", offset_al ternate_set, i);
262 } 262 }
263 if (!ParseAlternateSetTable(data + offset_alternate_set, 263 if (!ParseAlternateSetTable(file, data + offset_alternate_set,
264 length - offset_alternate_set, 264 length - offset_alternate_set,
265 num_glyphs)) { 265 num_glyphs)) {
266 return OTS_FAILURE(); 266 return OTS_FAILURE_MSG("Failed to parse alternate set");
267 } 267 }
268 } 268 }
269 269
270 if (offset_coverage < alternate_set_end || offset_coverage >= length) { 270 if (offset_coverage < alternate_set_end || offset_coverage >= length) {
271 return OTS_FAILURE(); 271 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage);
272 } 272 }
273 if (!ots::ParseCoverageTable(data + offset_coverage, 273 if (!ots::ParseCoverageTable(file, data + offset_coverage,
274 length - offset_coverage, num_glyphs)) { 274 length - offset_coverage, num_glyphs)) {
275 return OTS_FAILURE(); 275 return OTS_FAILURE_MSG("Failed to parse coverage table");
276 } 276 }
277 277
278 return true; 278 return true;
279 } 279 }
280 280
281 bool ParseLigatureTable(const uint8_t *data, const size_t length, 281 bool ParseLigatureTable(const ots::OpenTypeFile *file,
282 const uint8_t *data, const size_t length,
282 const uint16_t num_glyphs) { 283 const uint16_t num_glyphs) {
283 ots::Buffer subtable(data, length); 284 ots::Buffer subtable(data, length);
284 285
285 uint16_t lig_glyph = 0; 286 uint16_t lig_glyph = 0;
286 uint16_t comp_count = 0; 287 uint16_t comp_count = 0;
287 288
288 if (!subtable.ReadU16(&lig_glyph) || 289 if (!subtable.ReadU16(&lig_glyph) ||
289 !subtable.ReadU16(&comp_count)) { 290 !subtable.ReadU16(&comp_count)) {
290 return OTS_FAILURE(); 291 return OTS_FAILURE_MSG("Failed to read ligatuer table header");
291 } 292 }
292 293
293 if (lig_glyph >= num_glyphs) { 294 if (lig_glyph >= num_glyphs) {
294 OTS_WARNING("too large lig_glyph: %u", lig_glyph); 295 return OTS_FAILURE_MSG("too large lig_glyph: %u", lig_glyph);
295 return OTS_FAILURE();
296 } 296 }
297 if (comp_count == 0 || comp_count > num_glyphs) { 297 if (comp_count == 0 || comp_count > num_glyphs) {
298 return OTS_FAILURE(); 298 return OTS_FAILURE_MSG("Bad component count of %d", comp_count);
299 } 299 }
300 for (unsigned i = 0; i < comp_count - static_cast<unsigned>(1); ++i) { 300 for (unsigned i = 0; i < comp_count - static_cast<unsigned>(1); ++i) {
301 uint16_t component = 0; 301 uint16_t component = 0;
302 if (!subtable.ReadU16(&component)) { 302 if (!subtable.ReadU16(&component)) {
303 return OTS_FAILURE(); 303 return OTS_FAILURE_MSG("Can't read ligature component %d", i);
304 } 304 }
305 if (component >= num_glyphs) { 305 if (component >= num_glyphs) {
306 return OTS_FAILURE(); 306 return OTS_FAILURE_MSG("Bad ligature component %d of %d", i, component);
307 } 307 }
308 } 308 }
309 309
310 return true; 310 return true;
311 } 311 }
312 312
313 bool ParseLigatureSetTable(const uint8_t *data, const size_t length, 313 bool ParseLigatureSetTable(const ots::OpenTypeFile *file,
314 const uint8_t *data, const size_t length,
314 const uint16_t num_glyphs) { 315 const uint16_t num_glyphs) {
315 ots::Buffer subtable(data, length); 316 ots::Buffer subtable(data, length);
316 317
317 uint16_t ligature_count = 0; 318 uint16_t ligature_count = 0;
318 319
319 if (!subtable.ReadU16(&ligature_count)) { 320 if (!subtable.ReadU16(&ligature_count)) {
320 return OTS_FAILURE(); 321 return OTS_FAILURE_MSG("Can't read ligature count in ligature set");
321 } 322 }
322 323
323 const unsigned ligature_end = static_cast<unsigned>(2) + ligature_count * 2; 324 const unsigned ligature_end = static_cast<unsigned>(2) + ligature_count * 2;
324 if (ligature_end > std::numeric_limits<uint16_t>::max()) { 325 if (ligature_end > std::numeric_limits<uint16_t>::max()) {
325 return OTS_FAILURE(); 326 return OTS_FAILURE_MSG("Bad end of ligature %d in ligature set", ligature_en d);
326 } 327 }
327 for (unsigned i = 0; i < ligature_count; ++i) { 328 for (unsigned i = 0; i < ligature_count; ++i) {
328 uint16_t offset_ligature = 0; 329 uint16_t offset_ligature = 0;
329 if (!subtable.ReadU16(&offset_ligature)) { 330 if (!subtable.ReadU16(&offset_ligature)) {
330 return OTS_FAILURE(); 331 return OTS_FAILURE_MSG("Failed to read ligature offset %d", i);
331 } 332 }
332 if (offset_ligature < ligature_end || offset_ligature >= length) { 333 if (offset_ligature < ligature_end || offset_ligature >= length) {
333 return OTS_FAILURE(); 334 return OTS_FAILURE_MSG("Bad ligature offset %d for ligature %d", offset_li gature, i);
334 } 335 }
335 if (!ParseLigatureTable(data + offset_ligature, length - offset_ligature, 336 if (!ParseLigatureTable(file, data + offset_ligature, length - offset_ligatu re,
336 num_glyphs)) { 337 num_glyphs)) {
337 return OTS_FAILURE(); 338 return OTS_FAILURE_MSG("Failed to parse ligature %d", i);
338 } 339 }
339 } 340 }
340 341
341 return true; 342 return true;
342 } 343 }
343 344
344 // Lookup Type 4: 345 // Lookup Type 4:
345 // Ligature Substitution Subtable 346 // Ligature Substitution Subtable
346 bool ParseLigatureSubstitution(const ots::OpenTypeFile *file, 347 bool ParseLigatureSubstitution(const ots::OpenTypeFile *file,
347 const uint8_t *data, const size_t length) { 348 const uint8_t *data, const size_t length) {
348 ots::Buffer subtable(data, length); 349 ots::Buffer subtable(data, length);
349 350
350 uint16_t format = 0; 351 uint16_t format = 0;
351 uint16_t offset_coverage = 0; 352 uint16_t offset_coverage = 0;
352 uint16_t lig_set_count = 0; 353 uint16_t lig_set_count = 0;
353 354
354 if (!subtable.ReadU16(&format) || 355 if (!subtable.ReadU16(&format) ||
355 !subtable.ReadU16(&offset_coverage) || 356 !subtable.ReadU16(&offset_coverage) ||
356 !subtable.ReadU16(&lig_set_count)) { 357 !subtable.ReadU16(&lig_set_count)) {
357 return OTS_FAILURE(); 358 return OTS_FAILURE_MSG("Failed to read ligature substitution header");
358 } 359 }
359 360
360 if (format != 1) { 361 if (format != 1) {
361 return OTS_FAILURE(); 362 return OTS_FAILURE_MSG("Bad ligature substitution table format %d", format);
362 } 363 }
363 364
364 const uint16_t num_glyphs = file->maxp->num_glyphs; 365 const uint16_t num_glyphs = file->maxp->num_glyphs;
365 const unsigned ligature_set_end = static_cast<unsigned>(6) + 366 const unsigned ligature_set_end = static_cast<unsigned>(6) +
366 lig_set_count * 2; 367 lig_set_count * 2;
367 if (ligature_set_end > std::numeric_limits<uint16_t>::max()) { 368 if (ligature_set_end > std::numeric_limits<uint16_t>::max()) {
368 return OTS_FAILURE(); 369 return OTS_FAILURE_MSG("Bad end of ligature set %d in ligature substitution table", ligature_set_end);
369 } 370 }
370 for (unsigned i = 0; i < lig_set_count; ++i) { 371 for (unsigned i = 0; i < lig_set_count; ++i) {
371 uint16_t offset_ligature_set = 0; 372 uint16_t offset_ligature_set = 0;
372 if (!subtable.ReadU16(&offset_ligature_set)) { 373 if (!subtable.ReadU16(&offset_ligature_set)) {
373 return OTS_FAILURE(); 374 return OTS_FAILURE_MSG("Can't read ligature set offset %d", i);
374 } 375 }
375 if (offset_ligature_set < ligature_set_end || 376 if (offset_ligature_set < ligature_set_end ||
376 offset_ligature_set >= length) { 377 offset_ligature_set >= length) {
377 return OTS_FAILURE(); 378 return OTS_FAILURE_MSG("Bad ligature set offset %d for set %d", offset_lig ature_set, i);
378 } 379 }
379 if (!ParseLigatureSetTable(data + offset_ligature_set, 380 if (!ParseLigatureSetTable(file, data + offset_ligature_set,
380 length - offset_ligature_set, num_glyphs)) { 381 length - offset_ligature_set, num_glyphs)) {
381 return OTS_FAILURE(); 382 return OTS_FAILURE_MSG("Failed to parse ligature set %d", i);
382 } 383 }
383 } 384 }
384 385
385 if (offset_coverage < ligature_set_end || offset_coverage >= length) { 386 if (offset_coverage < ligature_set_end || offset_coverage >= length) {
386 return OTS_FAILURE(); 387 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage);
387 } 388 }
388 if (!ots::ParseCoverageTable(data + offset_coverage, 389 if (!ots::ParseCoverageTable(file, data + offset_coverage,
389 length - offset_coverage, num_glyphs)) { 390 length - offset_coverage, num_glyphs)) {
390 return OTS_FAILURE(); 391 return OTS_FAILURE_MSG("Failed to parse coverage table");
391 } 392 }
392 393
393 return true; 394 return true;
394 } 395 }
395 396
396 // Lookup Type 5: 397 // Lookup Type 5:
397 // Contextual Substitution Subtable 398 // Contextual Substitution Subtable
398 bool ParseContextSubstitution(const ots::OpenTypeFile *file, 399 bool ParseContextSubstitution(const ots::OpenTypeFile *file,
399 const uint8_t *data, const size_t length) { 400 const uint8_t *data, const size_t length) {
400 return ots::ParseContextSubtable(data, length, file->maxp->num_glyphs, 401 return ots::ParseContextSubtable(file, data, length, file->maxp->num_glyphs,
401 file->gsub->num_lookups); 402 file->gsub->num_lookups);
402 } 403 }
403 404
404 // Lookup Type 6: 405 // Lookup Type 6:
405 // Chaining Contextual Substitution Subtable 406 // Chaining Contextual Substitution Subtable
406 bool ParseChainingContextSubstitution(const ots::OpenTypeFile *file, 407 bool ParseChainingContextSubstitution(const ots::OpenTypeFile *file,
407 const uint8_t *data, 408 const uint8_t *data,
408 const size_t length) { 409 const size_t length) {
409 return ots::ParseChainingContextSubtable(data, length, 410 return ots::ParseChainingContextSubtable(file, data, length,
410 file->maxp->num_glyphs, 411 file->maxp->num_glyphs,
411 file->gsub->num_lookups); 412 file->gsub->num_lookups);
412 } 413 }
413 414
414 // Lookup Type 7: 415 // Lookup Type 7:
415 // Extension Substition 416 // Extension Substition
416 bool ParseExtensionSubstitution(const ots::OpenTypeFile *file, 417 bool ParseExtensionSubstitution(const ots::OpenTypeFile *file,
417 const uint8_t *data, const size_t length) { 418 const uint8_t *data, const size_t length) {
418 return ots::ParseExtensionSubtable(file, data, length, 419 return ots::ParseExtensionSubtable(file, data, length,
419 &kGsubLookupSubtableParser); 420 &kGsubLookupSubtableParser);
420 } 421 }
421 422
422 // Lookup Type 8: 423 // Lookup Type 8:
423 // Reverse Chaining Contexual Single Substitution Subtable 424 // Reverse Chaining Contexual Single Substitution Subtable
424 bool ParseReverseChainingContextSingleSubstitution( 425 bool ParseReverseChainingContextSingleSubstitution(
425 const ots::OpenTypeFile *file, const uint8_t *data, const size_t length) { 426 const ots::OpenTypeFile *file, const uint8_t *data, const size_t length) {
426 ots::Buffer subtable(data, length); 427 ots::Buffer subtable(data, length);
427 428
428 uint16_t format = 0; 429 uint16_t format = 0;
429 uint16_t offset_coverage = 0; 430 uint16_t offset_coverage = 0;
430 431
431 if (!subtable.ReadU16(&format) || 432 if (!subtable.ReadU16(&format) ||
432 !subtable.ReadU16(&offset_coverage)) { 433 !subtable.ReadU16(&offset_coverage)) {
433 return OTS_FAILURE(); 434 return OTS_FAILURE_MSG("Failed to read reverse chaining header");
434 } 435 }
435 436
436 const uint16_t num_glyphs = file->maxp->num_glyphs; 437 const uint16_t num_glyphs = file->maxp->num_glyphs;
437 438
438 uint16_t backtrack_glyph_count = 0; 439 uint16_t backtrack_glyph_count = 0;
439 if (!subtable.ReadU16(&backtrack_glyph_count)) { 440 if (!subtable.ReadU16(&backtrack_glyph_count)) {
440 return OTS_FAILURE(); 441 return OTS_FAILURE_MSG("Failed to read backtrack glyph count in reverse chai ning table");
441 } 442 }
442 if (backtrack_glyph_count > num_glyphs) { 443 if (backtrack_glyph_count > num_glyphs) {
443 return OTS_FAILURE(); 444 return OTS_FAILURE_MSG("Bad backtrack glyph count of %d", backtrack_glyph_co unt);
444 } 445 }
445 std::vector<uint16_t> offsets_backtrack; 446 std::vector<uint16_t> offsets_backtrack;
446 offsets_backtrack.reserve(backtrack_glyph_count); 447 offsets_backtrack.reserve(backtrack_glyph_count);
447 for (unsigned i = 0; i < backtrack_glyph_count; ++i) { 448 for (unsigned i = 0; i < backtrack_glyph_count; ++i) {
448 uint16_t offset = 0; 449 uint16_t offset = 0;
449 if (!subtable.ReadU16(&offset)) { 450 if (!subtable.ReadU16(&offset)) {
450 return OTS_FAILURE(); 451 return OTS_FAILURE_MSG("Failed to read backtrack offset %d", i);
451 } 452 }
452 offsets_backtrack.push_back(offset); 453 offsets_backtrack.push_back(offset);
453 } 454 }
454 455
455 uint16_t lookahead_glyph_count = 0; 456 uint16_t lookahead_glyph_count = 0;
456 if (!subtable.ReadU16(&lookahead_glyph_count)) { 457 if (!subtable.ReadU16(&lookahead_glyph_count)) {
457 return OTS_FAILURE(); 458 return OTS_FAILURE_MSG("Failed to read look ahead glyph count");
458 } 459 }
459 if (lookahead_glyph_count > num_glyphs) { 460 if (lookahead_glyph_count > num_glyphs) {
460 return OTS_FAILURE(); 461 return OTS_FAILURE_MSG("Bad look ahead glyph count %d", lookahead_glyph_coun t);
461 } 462 }
462 std::vector<uint16_t> offsets_lookahead; 463 std::vector<uint16_t> offsets_lookahead;
463 offsets_lookahead.reserve(lookahead_glyph_count); 464 offsets_lookahead.reserve(lookahead_glyph_count);
464 for (unsigned i = 0; i < lookahead_glyph_count; ++i) { 465 for (unsigned i = 0; i < lookahead_glyph_count; ++i) {
465 uint16_t offset = 0; 466 uint16_t offset = 0;
466 if (!subtable.ReadU16(&offset)) { 467 if (!subtable.ReadU16(&offset)) {
467 return OTS_FAILURE(); 468 return OTS_FAILURE_MSG("Can't read look ahead offset %d", i);
468 } 469 }
469 offsets_lookahead.push_back(offset); 470 offsets_lookahead.push_back(offset);
470 } 471 }
471 472
472 uint16_t glyph_count = 0; 473 uint16_t glyph_count = 0;
473 if (!subtable.ReadU16(&glyph_count)) { 474 if (!subtable.ReadU16(&glyph_count)) {
474 return OTS_FAILURE(); 475 return OTS_FAILURE_MSG("Can't read glyph count in reverse chaining table");
475 } 476 }
476 if (glyph_count > num_glyphs) { 477 if (glyph_count > num_glyphs) {
477 return OTS_FAILURE(); 478 return OTS_FAILURE_MSG("Bad glyph count of %d", glyph_count);
478 } 479 }
479 for (unsigned i = 0; i < glyph_count; ++i) { 480 for (unsigned i = 0; i < glyph_count; ++i) {
480 uint16_t substitute = 0; 481 uint16_t substitute = 0;
481 if (!subtable.ReadU16(&substitute)) { 482 if (!subtable.ReadU16(&substitute)) {
482 return OTS_FAILURE(); 483 return OTS_FAILURE_MSG("Failed to read substitution %d reverse chaining ta ble", i);
483 } 484 }
484 if (substitute >= num_glyphs) { 485 if (substitute >= num_glyphs) {
485 return OTS_FAILURE(); 486 return OTS_FAILURE_MSG("Bad substitute glyph %d in reverse chaining table substitution %d", substitute, i);
486 } 487 }
487 } 488 }
488 489
489 const unsigned substitute_end = static_cast<unsigned>(10) + 490 const unsigned substitute_end = static_cast<unsigned>(10) +
490 (backtrack_glyph_count + lookahead_glyph_count + glyph_count) * 2; 491 (backtrack_glyph_count + lookahead_glyph_count + glyph_count) * 2;
491 if (substitute_end > std::numeric_limits<uint16_t>::max()) { 492 if (substitute_end > std::numeric_limits<uint16_t>::max()) {
492 return OTS_FAILURE(); 493 return OTS_FAILURE_MSG("Bad substitute end offset in reverse chaining table" );
493 } 494 }
494 495
495 if (offset_coverage < substitute_end || offset_coverage >= length) { 496 if (offset_coverage < substitute_end || offset_coverage >= length) {
496 return OTS_FAILURE(); 497 return OTS_FAILURE_MSG("Bad coverage offset %d in reverse chaining table", o ffset_coverage);
497 } 498 }
498 if (!ots::ParseCoverageTable(data + offset_coverage, 499 if (!ots::ParseCoverageTable(file, data + offset_coverage,
499 length - offset_coverage, num_glyphs)) { 500 length - offset_coverage, num_glyphs)) {
500 return OTS_FAILURE(); 501 return OTS_FAILURE_MSG("Failed to parse coverage table in reverse chaining t able");
501 } 502 }
502 503
503 for (unsigned i = 0; i < backtrack_glyph_count; ++i) { 504 for (unsigned i = 0; i < backtrack_glyph_count; ++i) {
504 if (offsets_backtrack[i] < substitute_end || 505 if (offsets_backtrack[i] < substitute_end ||
505 offsets_backtrack[i] >= length) { 506 offsets_backtrack[i] >= length) {
506 return OTS_FAILURE(); 507 return OTS_FAILURE_MSG("Bad backtrack offset %d for backtrack %d in revers e chaining table", offsets_backtrack[i], i);
507 } 508 }
508 if (!ots::ParseCoverageTable(data + offsets_backtrack[i], 509 if (!ots::ParseCoverageTable(file, data + offsets_backtrack[i],
509 length - offsets_backtrack[i], num_glyphs)) { 510 length - offsets_backtrack[i], num_glyphs)) {
510 return OTS_FAILURE(); 511 return OTS_FAILURE_MSG("Failed to parse coverage table for backtrack %d in reverse chaining table", i);
511 } 512 }
512 } 513 }
513 514
514 for (unsigned i = 0; i < lookahead_glyph_count; ++i) { 515 for (unsigned i = 0; i < lookahead_glyph_count; ++i) {
515 if (offsets_lookahead[i] < substitute_end || 516 if (offsets_lookahead[i] < substitute_end ||
516 offsets_lookahead[i] >= length) { 517 offsets_lookahead[i] >= length) {
517 return OTS_FAILURE(); 518 return OTS_FAILURE_MSG("Bad lookahead offset %d for lookahead %d in revers e chaining table", offsets_lookahead[i], i);
518 } 519 }
519 if (!ots::ParseCoverageTable(data + offsets_lookahead[i], 520 if (!ots::ParseCoverageTable(file, data + offsets_lookahead[i],
520 length - offsets_lookahead[i], num_glyphs)) { 521 length - offsets_lookahead[i], num_glyphs)) {
521 return OTS_FAILURE(); 522 return OTS_FAILURE_MSG("Failed to parse lookahead coverage table %d in rev erse chaining table", i);
522 } 523 }
523 } 524 }
524 525
525 return true; 526 return true;
526 } 527 }
527 528
528 } // namespace 529 } // namespace
529 530
530 #define DROP_THIS_TABLE \ 531 #define DROP_THIS_TABLE(msg_) \
531 do { file->gsub->data = 0; file->gsub->length = 0; } while (0) 532 do { \
533 file->gsub->data = 0; \
534 file->gsub->length = 0; \
535 OTS_FAILURE_MSG(msg_ ", table discarded"); \
536 } while (0)
532 537
533 namespace ots { 538 namespace ots {
534 539
535 // As far as I checked, following fonts contain invalid values in GSUB table. 540 // As far as I checked, following fonts contain invalid values in GSUB table.
536 // OTS will drop their GSUB table. 541 // OTS will drop their GSUB table.
537 // 542 //
538 // # too large substitute (value is 0xFFFF) 543 // # too large substitute (value is 0xFFFF)
539 // kaiu.ttf 544 // kaiu.ttf
540 // mingliub2.ttf 545 // mingliub2.ttf
541 // mingliub1.ttf 546 // mingliub1.ttf
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 // KacstArt.ttf 583 // KacstArt.ttf
579 // KacstPoster.ttf 584 // KacstPoster.ttf
580 // KacstQurn.ttf 585 // KacstQurn.ttf
581 // KacstDigital.ttf 586 // KacstDigital.ttf
582 // KacstBook.ttf 587 // KacstBook.ttf
583 // KacstFarsi.ttf 588 // KacstFarsi.ttf
584 589
585 bool ots_gsub_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 590 bool ots_gsub_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
586 // Parsing gsub table requires |file->maxp->num_glyphs| 591 // Parsing gsub table requires |file->maxp->num_glyphs|
587 if (!file->maxp) { 592 if (!file->maxp) {
588 return OTS_FAILURE(); 593 return OTS_FAILURE_MSG("Missing maxp table in font, needed by GSUB");
589 } 594 }
590 595
591 Buffer table(data, length); 596 Buffer table(data, length);
592 597
593 OpenTypeGSUB *gsub = new OpenTypeGSUB; 598 OpenTypeGSUB *gsub = new OpenTypeGSUB;
594 file->gsub = gsub; 599 file->gsub = gsub;
595 600
596 uint32_t version = 0; 601 uint32_t version = 0;
597 uint16_t offset_script_list = 0; 602 uint16_t offset_script_list = 0;
598 uint16_t offset_feature_list = 0; 603 uint16_t offset_feature_list = 0;
599 uint16_t offset_lookup_list = 0; 604 uint16_t offset_lookup_list = 0;
600 if (!table.ReadU32(&version) || 605 if (!table.ReadU32(&version) ||
601 !table.ReadU16(&offset_script_list) || 606 !table.ReadU16(&offset_script_list) ||
602 !table.ReadU16(&offset_feature_list) || 607 !table.ReadU16(&offset_feature_list) ||
603 !table.ReadU16(&offset_lookup_list)) { 608 !table.ReadU16(&offset_lookup_list)) {
604 return OTS_FAILURE(); 609 DROP_THIS_TABLE("Incomplete table");
610 return true;
605 } 611 }
606 612
607 if (version != 0x00010000) { 613 if (version != 0x00010000) {
608 OTS_WARNING("bad GSUB version"); 614 DROP_THIS_TABLE("Bad version");
609 DROP_THIS_TABLE;
610 return true;
611 }
612 if ((offset_script_list < kGsubHeaderSize ||
613 offset_script_list >= length) ||
614 (offset_feature_list < kGsubHeaderSize ||
615 offset_feature_list >= length) ||
616 (offset_lookup_list < kGsubHeaderSize ||
617 offset_lookup_list >= length)) {
618 OTS_WARNING("bad offset in GSUB header");
619 DROP_THIS_TABLE;
620 return true; 615 return true;
621 } 616 }
622 617
623 if (!ParseLookupListTable(file, data + offset_lookup_list, 618 if (offset_lookup_list) {
624 length - offset_lookup_list, 619 if (offset_lookup_list < kGsubHeaderSize || offset_lookup_list >= length) {
625 &kGsubLookupSubtableParser, 620 DROP_THIS_TABLE("Bad lookup list offset in table header");
626 &gsub->num_lookups)) { 621 return true;
627 OTS_WARNING("faild to parse lookup list table"); 622 }
628 DROP_THIS_TABLE; 623
629 return true; 624 if (!ParseLookupListTable(file, data + offset_lookup_list,
625 length - offset_lookup_list,
626 &kGsubLookupSubtableParser,
627 &gsub->num_lookups)) {
628 DROP_THIS_TABLE("Failed to parse lookup list table");
629 return true;
630 }
630 } 631 }
631 632
632 uint16_t num_features = 0; 633 uint16_t num_features = 0;
633 if (!ParseFeatureListTable(data + offset_feature_list, 634 if (offset_feature_list) {
634 length - offset_feature_list, gsub->num_lookups, 635 if (offset_feature_list < kGsubHeaderSize || offset_feature_list >= length) {
635 &num_features)) { 636 DROP_THIS_TABLE("Bad feature list offset in table header");
636 OTS_WARNING("faild to parse feature list table"); 637 return true;
637 DROP_THIS_TABLE; 638 }
638 return true; 639
640 if (!ParseFeatureListTable(file, data + offset_feature_list,
641 length - offset_feature_list, gsub->num_lookups,
642 &num_features)) {
643 DROP_THIS_TABLE("Failed to parse feature list table");
644 return true;
645 }
639 } 646 }
640 647
641 if (!ParseScriptListTable(data + offset_script_list, 648 if (offset_script_list) {
642 length - offset_script_list, num_features)) { 649 if (offset_script_list < kGsubHeaderSize || offset_script_list >= length) {
643 OTS_WARNING("faild to parse script list table"); 650 DROP_THIS_TABLE("Bad script list offset in table header");
644 DROP_THIS_TABLE; 651 return true;
645 return true; 652 }
653
654 if (!ParseScriptListTable(file, data + offset_script_list,
655 length - offset_script_list, num_features)) {
656 DROP_THIS_TABLE("Failed to parse script list table");
657 return true;
658 }
646 } 659 }
647 660
648 gsub->data = data; 661 gsub->data = data;
649 gsub->length = length; 662 gsub->length = length;
650 return true; 663 return true;
651 } 664 }
652 665
653 bool ots_gsub_should_serialise(OpenTypeFile *file) { 666 bool ots_gsub_should_serialise(OpenTypeFile *file) {
654 const bool needed_tables_dropped = 667 return file->gsub != NULL && file->gsub->data != NULL;
655 (file->gdef && file->gdef->data == NULL) ||
656 (file->gpos && file->gpos->data == NULL);
657 return file->gsub != NULL && file->gsub->data != NULL
658 && !needed_tables_dropped;
659 } 668 }
660 669
661 bool ots_gsub_serialise(OTSStream *out, OpenTypeFile *file) { 670 bool ots_gsub_serialise(OTSStream *out, OpenTypeFile *file) {
662 if (!out->Write(file->gsub->data, file->gsub->length)) { 671 if (!out->Write(file->gsub->data, file->gsub->length)) {
663 return OTS_FAILURE(); 672 return OTS_FAILURE_MSG("Failed to write GSUB table");
664 } 673 }
665 674
666 return true; 675 return true;
667 } 676 }
668 677
669 void ots_gsub_free(OpenTypeFile *file) { 678 void ots_gsub_free(OpenTypeFile *file) {
670 delete file->gsub; 679 delete file->gsub;
671 } 680 }
672 681
673 } // namespace ots 682 } // namespace ots
674 683
684 #undef TABLE_NAME
685 #undef DROP_THIS_TABLE
OLDNEW
« .gitmodules ('K') | « src/gpos.cc ('k') | src/hdmx.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698