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

Side by Side Diff: src/math.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/ltsh.cc ('k') | src/maxp.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) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 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 // We use an underscore to avoid confusion with the standard math.h library. 5 // We use an underscore to avoid confusion with the standard math.h library.
6 #include "math_.h" 6 #include "math_.h"
7 7
8 #include <limits> 8 #include <limits>
9 #include <vector> 9 #include <vector>
10 10
11 #include "layout.h" 11 #include "layout.h"
12 #include "maxp.h" 12 #include "maxp.h"
13 13
14 // MATH - The MATH Table 14 // MATH - The MATH Table
15 // The specification is not yet public but has been submitted to the MPEG group 15 // The specification is not yet public but has been submitted to the MPEG group
16 // in response to the 'Call for Proposals for ISO/IEC 14496-22 "Open Font 16 // in response to the 'Call for Proposals for ISO/IEC 14496-22 "Open Font
17 // Format" Color Font Technology and MATH layout support'. Meanwhile, you can 17 // Format" Color Font Technology and MATH layout support'. Meanwhile, you can
18 // contact Microsoft's engineer Murray Sargent to obtain a copy. 18 // contact Microsoft's engineer Murray Sargent to obtain a copy.
19 19
20 #define TABLE_NAME "MATH"
21
20 namespace { 22 namespace {
21 23
22 // The size of MATH header. 24 // The size of MATH header.
23 // Version 25 // Version
24 // MathConstants 26 // MathConstants
25 // MathGlyphInfo 27 // MathGlyphInfo
26 // MathVariants 28 // MathVariants
27 const unsigned kMathHeaderSize = 4 + 3 * 2; 29 const unsigned kMathHeaderSize = 4 + 3 * 2;
28 30
29 // The size of the MathGlyphInfo header. 31 // The size of the MathGlyphInfo header.
(...skipping 11 matching lines...) Expand all
41 // The size of the GlyphPartRecord. 43 // The size of the GlyphPartRecord.
42 // glyph 44 // glyph
43 // StartConnectorLength 45 // StartConnectorLength
44 // EndConnectorLength 46 // EndConnectorLength
45 // FullAdvance 47 // FullAdvance
46 // PartFlags 48 // PartFlags
47 const unsigned kGlyphPartRecordSize = 5 * 2; 49 const unsigned kGlyphPartRecordSize = 5 * 2;
48 50
49 // Shared Table: MathValueRecord 51 // Shared Table: MathValueRecord
50 52
51 bool ParseMathValueRecord(ots::Buffer* subtable, const uint8_t *data, 53 bool ParseMathValueRecord(const ots::OpenTypeFile *file,
54 ots::Buffer* subtable, const uint8_t *data,
52 const size_t length) { 55 const size_t length) {
53 // Check the Value field. 56 // Check the Value field.
54 if (!subtable->Skip(2)) { 57 if (!subtable->Skip(2)) {
55 return OTS_FAILURE(); 58 return OTS_FAILURE();
56 } 59 }
57 60
58 // Check the offset to device table. 61 // Check the offset to device table.
59 uint16_t offset = 0; 62 uint16_t offset = 0;
60 if (!subtable->ReadU16(&offset)) { 63 if (!subtable->ReadU16(&offset)) {
61 return OTS_FAILURE(); 64 return OTS_FAILURE();
62 } 65 }
63 if (offset) { 66 if (offset) {
64 if (offset >= length) { 67 if (offset >= length) {
65 return OTS_FAILURE(); 68 return OTS_FAILURE();
66 } 69 }
67 if (!ots::ParseDeviceTable(data + offset, length - offset)) { 70 if (!ots::ParseDeviceTable(file, data + offset, length - offset)) {
68 return OTS_FAILURE(); 71 return OTS_FAILURE();
69 } 72 }
70 } 73 }
71 74
72 return true; 75 return true;
73 } 76 }
74 77
75 bool ParseMathConstantsTable(const uint8_t *data, size_t length) { 78 bool ParseMathConstantsTable(const ots::OpenTypeFile *file,
79 const uint8_t *data, size_t length) {
76 ots::Buffer subtable(data, length); 80 ots::Buffer subtable(data, length);
77 81
78 // Part 1: int16 or uint16 constants. 82 // Part 1: int16 or uint16 constants.
79 // ScriptPercentScaleDown 83 // ScriptPercentScaleDown
80 // ScriptScriptPercentScaleDown 84 // ScriptScriptPercentScaleDown
81 // DelimitedSubFormulaMinHeight 85 // DelimitedSubFormulaMinHeight
82 // DisplayOperatorMinHeight 86 // DisplayOperatorMinHeight
83 if (!subtable.Skip(4 * 2)) { 87 if (!subtable.Skip(4 * 2)) {
84 return OTS_FAILURE(); 88 return OTS_FAILURE();
85 } 89 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 // UnderbarRuleThickness 139 // UnderbarRuleThickness
136 // UnderbarExtraDescender 140 // UnderbarExtraDescender
137 // RadicalVerticalGap 141 // RadicalVerticalGap
138 // RadicalDisplayStyleVerticalGap 142 // RadicalDisplayStyleVerticalGap
139 // RadicalRuleThickness 143 // RadicalRuleThickness
140 // RadicalExtraAscender 144 // RadicalExtraAscender
141 // RadicalKernBeforeDegree 145 // RadicalKernBeforeDegree
142 // 146 //
143 // RadicalKernAfterDegree 147 // RadicalKernAfterDegree
144 for (unsigned i = 0; i < static_cast<unsigned>(51); ++i) { 148 for (unsigned i = 0; i < static_cast<unsigned>(51); ++i) {
145 if (!ParseMathValueRecord(&subtable, data, length)) { 149 if (!ParseMathValueRecord(file, &subtable, data, length)) {
146 return OTS_FAILURE(); 150 return OTS_FAILURE();
147 } 151 }
148 } 152 }
149 153
150 // Part 3: uint16 constant 154 // Part 3: uint16 constant
151 // RadicalDegreeBottomRaisePercent 155 // RadicalDegreeBottomRaisePercent
152 if (!subtable.Skip(2)) { 156 if (!subtable.Skip(2)) {
153 return OTS_FAILURE(); 157 return OTS_FAILURE();
154 } 158 }
155 159
156 return true; 160 return true;
157 } 161 }
158 162
159 bool ParseMathValueRecordSequenceForGlyphs(ots::Buffer* subtable, 163 bool ParseMathValueRecordSequenceForGlyphs(const ots::OpenTypeFile *file,
164 ots::Buffer* subtable,
160 const uint8_t *data, 165 const uint8_t *data,
161 const size_t length, 166 const size_t length,
162 const uint16_t num_glyphs) { 167 const uint16_t num_glyphs) {
163 // Check the header. 168 // Check the header.
164 uint16_t offset_coverage = 0; 169 uint16_t offset_coverage = 0;
165 uint16_t sequence_count = 0; 170 uint16_t sequence_count = 0;
166 if (!subtable->ReadU16(&offset_coverage) || 171 if (!subtable->ReadU16(&offset_coverage) ||
167 !subtable->ReadU16(&sequence_count)) { 172 !subtable->ReadU16(&sequence_count)) {
168 return OTS_FAILURE(); 173 return OTS_FAILURE();
169 } 174 }
170 175
171 const unsigned sequence_end = static_cast<unsigned>(2 * 2) + 176 const unsigned sequence_end = static_cast<unsigned>(2 * 2) +
172 sequence_count * kMathValueRecordSize; 177 sequence_count * kMathValueRecordSize;
173 if (sequence_end > std::numeric_limits<uint16_t>::max()) { 178 if (sequence_end > std::numeric_limits<uint16_t>::max()) {
174 return OTS_FAILURE(); 179 return OTS_FAILURE();
175 } 180 }
176 181
177 // Check coverage table. 182 // Check coverage table.
178 if (offset_coverage < sequence_end || offset_coverage >= length) { 183 if (offset_coverage < sequence_end || offset_coverage >= length) {
179 return OTS_FAILURE(); 184 return OTS_FAILURE();
180 } 185 }
181 if (!ots::ParseCoverageTable(data + offset_coverage, 186 if (!ots::ParseCoverageTable(file, data + offset_coverage,
182 length - offset_coverage, 187 length - offset_coverage,
183 num_glyphs, sequence_count)) { 188 num_glyphs, sequence_count)) {
184 return OTS_FAILURE(); 189 return OTS_FAILURE();
185 } 190 }
186 191
187 // Check sequence. 192 // Check sequence.
188 for (unsigned i = 0; i < sequence_count; ++i) { 193 for (unsigned i = 0; i < sequence_count; ++i) {
189 if (!ParseMathValueRecord(subtable, data, length)) { 194 if (!ParseMathValueRecord(file, subtable, data, length)) {
190 return OTS_FAILURE(); 195 return OTS_FAILURE();
191 } 196 }
192 } 197 }
193 198
194 return true; 199 return true;
195 } 200 }
196 201
197 bool ParseMathItalicsCorrectionInfoTable(const uint8_t *data, 202 bool ParseMathItalicsCorrectionInfoTable(const ots::OpenTypeFile *file,
203 const uint8_t *data,
198 size_t length, 204 size_t length,
199 const uint16_t num_glyphs) { 205 const uint16_t num_glyphs) {
200 ots::Buffer subtable(data, length); 206 ots::Buffer subtable(data, length);
201 return ParseMathValueRecordSequenceForGlyphs(&subtable, data, length, 207 return ParseMathValueRecordSequenceForGlyphs(file, &subtable, data, length,
202 num_glyphs); 208 num_glyphs);
203 } 209 }
204 210
205 bool ParseMathTopAccentAttachmentTable(const uint8_t *data, 211 bool ParseMathTopAccentAttachmentTable(const ots::OpenTypeFile *file,
212 const uint8_t *data,
206 size_t length, 213 size_t length,
207 const uint16_t num_glyphs) { 214 const uint16_t num_glyphs) {
208 ots::Buffer subtable(data, length); 215 ots::Buffer subtable(data, length);
209 return ParseMathValueRecordSequenceForGlyphs(&subtable, data, length, 216 return ParseMathValueRecordSequenceForGlyphs(file, &subtable, data, length,
210 num_glyphs); 217 num_glyphs);
211 } 218 }
212 219
213 bool ParseMathKernTable(const uint8_t *data, size_t length) { 220 bool ParseMathKernTable(const ots::OpenTypeFile *file,
221 const uint8_t *data, size_t length) {
214 ots::Buffer subtable(data, length); 222 ots::Buffer subtable(data, length);
215 223
216 // Check the Height count. 224 // Check the Height count.
217 uint16_t height_count = 0; 225 uint16_t height_count = 0;
218 if (!subtable.ReadU16(&height_count)) { 226 if (!subtable.ReadU16(&height_count)) {
219 return OTS_FAILURE(); 227 return OTS_FAILURE();
220 } 228 }
221 229
222 // Check the Correction Heights. 230 // Check the Correction Heights.
223 for (unsigned i = 0; i < height_count; ++i) { 231 for (unsigned i = 0; i < height_count; ++i) {
224 if (!ParseMathValueRecord(&subtable, data, length)) { 232 if (!ParseMathValueRecord(file, &subtable, data, length)) {
225 return OTS_FAILURE(); 233 return OTS_FAILURE();
226 } 234 }
227 } 235 }
228 236
229 // Check the Kern Values. 237 // Check the Kern Values.
230 for (unsigned i = 0; i <= height_count; ++i) { 238 for (unsigned i = 0; i <= height_count; ++i) {
231 if (!ParseMathValueRecord(&subtable, data, length)) { 239 if (!ParseMathValueRecord(file, &subtable, data, length)) {
232 return OTS_FAILURE(); 240 return OTS_FAILURE();
233 } 241 }
234 } 242 }
235 243
236 return true; 244 return true;
237 } 245 }
238 246
239 bool ParseMathKernInfoTable(const uint8_t *data, size_t length, 247 bool ParseMathKernInfoTable(const ots::OpenTypeFile *file,
248 const uint8_t *data, size_t length,
240 const uint16_t num_glyphs) { 249 const uint16_t num_glyphs) {
241 ots::Buffer subtable(data, length); 250 ots::Buffer subtable(data, length);
242 251
243 // Check the header. 252 // Check the header.
244 uint16_t offset_coverage = 0; 253 uint16_t offset_coverage = 0;
245 uint16_t sequence_count = 0; 254 uint16_t sequence_count = 0;
246 if (!subtable.ReadU16(&offset_coverage) || 255 if (!subtable.ReadU16(&offset_coverage) ||
247 !subtable.ReadU16(&sequence_count)) { 256 !subtable.ReadU16(&sequence_count)) {
248 return OTS_FAILURE(); 257 return OTS_FAILURE();
249 } 258 }
250 259
251 const unsigned sequence_end = static_cast<unsigned>(2 * 2) + 260 const unsigned sequence_end = static_cast<unsigned>(2 * 2) +
252 sequence_count * 4 * 2; 261 sequence_count * 4 * 2;
253 if (sequence_end > std::numeric_limits<uint16_t>::max()) { 262 if (sequence_end > std::numeric_limits<uint16_t>::max()) {
254 return OTS_FAILURE(); 263 return OTS_FAILURE();
255 } 264 }
256 265
257 // Check coverage table. 266 // Check coverage table.
258 if (offset_coverage < sequence_end || offset_coverage >= length) { 267 if (offset_coverage < sequence_end || offset_coverage >= length) {
259 return OTS_FAILURE(); 268 return OTS_FAILURE();
260 } 269 }
261 if (!ots::ParseCoverageTable(data + offset_coverage, length - offset_coverage, 270 if (!ots::ParseCoverageTable(file, data + offset_coverage, length - offset_cov erage,
262 num_glyphs, sequence_count)) { 271 num_glyphs, sequence_count)) {
263 return OTS_FAILURE(); 272 return OTS_FAILURE();
264 } 273 }
265 274
266 // Check sequence of MathKernInfoRecord 275 // Check sequence of MathKernInfoRecord
267 for (unsigned i = 0; i < sequence_count; ++i) { 276 for (unsigned i = 0; i < sequence_count; ++i) {
268 // Check TopRight, TopLeft, BottomRight and BottomLeft Math Kern. 277 // Check TopRight, TopLeft, BottomRight and BottomLeft Math Kern.
269 for (unsigned j = 0; j < 4; ++j) { 278 for (unsigned j = 0; j < 4; ++j) {
270 uint16_t offset_math_kern = 0; 279 uint16_t offset_math_kern = 0;
271 if (!subtable.ReadU16(&offset_math_kern)) { 280 if (!subtable.ReadU16(&offset_math_kern)) {
272 return OTS_FAILURE(); 281 return OTS_FAILURE();
273 } 282 }
274 if (offset_math_kern) { 283 if (offset_math_kern) {
275 if (offset_math_kern < sequence_end || offset_math_kern >= length || 284 if (offset_math_kern < sequence_end || offset_math_kern >= length ||
276 !ParseMathKernTable(data + offset_math_kern, 285 !ParseMathKernTable(file, data + offset_math_kern,
277 length - offset_math_kern)) { 286 length - offset_math_kern)) {
278 return OTS_FAILURE(); 287 return OTS_FAILURE();
279 } 288 }
280 } 289 }
281 } 290 }
282 } 291 }
283 292
284 return true; 293 return true;
285 } 294 }
286 295
287 bool ParseMathGlyphInfoTable(const uint8_t *data, size_t length, 296 bool ParseMathGlyphInfoTable(const ots::OpenTypeFile *file,
297 const uint8_t *data, size_t length,
288 const uint16_t num_glyphs) { 298 const uint16_t num_glyphs) {
289 ots::Buffer subtable(data, length); 299 ots::Buffer subtable(data, length);
290 300
291 // Check Header. 301 // Check Header.
292 uint16_t offset_math_italics_correction_info = 0; 302 uint16_t offset_math_italics_correction_info = 0;
293 uint16_t offset_math_top_accent_attachment = 0; 303 uint16_t offset_math_top_accent_attachment = 0;
294 uint16_t offset_extended_shaped_coverage = 0; 304 uint16_t offset_extended_shaped_coverage = 0;
295 uint16_t offset_math_kern_info = 0; 305 uint16_t offset_math_kern_info = 0;
296 if (!subtable.ReadU16(&offset_math_italics_correction_info) || 306 if (!subtable.ReadU16(&offset_math_italics_correction_info) ||
297 !subtable.ReadU16(&offset_math_top_accent_attachment) || 307 !subtable.ReadU16(&offset_math_top_accent_attachment) ||
298 !subtable.ReadU16(&offset_extended_shaped_coverage) || 308 !subtable.ReadU16(&offset_extended_shaped_coverage) ||
299 !subtable.ReadU16(&offset_math_kern_info)) { 309 !subtable.ReadU16(&offset_math_kern_info)) {
300 return OTS_FAILURE(); 310 return OTS_FAILURE();
301 } 311 }
302 312
303 // Check subtables. 313 // Check subtables.
304 // The specification does not say whether the offsets for 314 // The specification does not say whether the offsets for
305 // MathItalicsCorrectionInfo, MathTopAccentAttachment and MathKernInfo may 315 // MathItalicsCorrectionInfo, MathTopAccentAttachment and MathKernInfo may
306 // be NULL, but that's the case in some fonts (e.g STIX) so we accept that. 316 // be NULL, but that's the case in some fonts (e.g STIX) so we accept that.
307 if (offset_math_italics_correction_info) { 317 if (offset_math_italics_correction_info) {
308 if (offset_math_italics_correction_info >= length || 318 if (offset_math_italics_correction_info >= length ||
309 offset_math_italics_correction_info < kMathGlyphInfoHeaderSize || 319 offset_math_italics_correction_info < kMathGlyphInfoHeaderSize ||
310 !ParseMathItalicsCorrectionInfoTable( 320 !ParseMathItalicsCorrectionInfoTable(
311 data + offset_math_italics_correction_info, 321 file, data + offset_math_italics_correction_info,
312 length - offset_math_italics_correction_info, 322 length - offset_math_italics_correction_info,
313 num_glyphs)) { 323 num_glyphs)) {
314 return OTS_FAILURE(); 324 return OTS_FAILURE();
315 } 325 }
316 } 326 }
317 if (offset_math_top_accent_attachment) { 327 if (offset_math_top_accent_attachment) {
318 if (offset_math_top_accent_attachment >= length || 328 if (offset_math_top_accent_attachment >= length ||
319 offset_math_top_accent_attachment < kMathGlyphInfoHeaderSize || 329 offset_math_top_accent_attachment < kMathGlyphInfoHeaderSize ||
320 !ParseMathTopAccentAttachmentTable(data + 330 !ParseMathTopAccentAttachmentTable(file, data +
321 offset_math_top_accent_attachment, 331 offset_math_top_accent_attachment,
322 length - 332 length -
323 offset_math_top_accent_attachment, 333 offset_math_top_accent_attachment,
324 num_glyphs)) { 334 num_glyphs)) {
325 return OTS_FAILURE(); 335 return OTS_FAILURE();
326 } 336 }
327 } 337 }
328 if (offset_extended_shaped_coverage) { 338 if (offset_extended_shaped_coverage) {
329 if (offset_extended_shaped_coverage >= length || 339 if (offset_extended_shaped_coverage >= length ||
330 offset_extended_shaped_coverage < kMathGlyphInfoHeaderSize || 340 offset_extended_shaped_coverage < kMathGlyphInfoHeaderSize ||
331 !ots::ParseCoverageTable(data + offset_extended_shaped_coverage, 341 !ots::ParseCoverageTable(file, data + offset_extended_shaped_coverage,
332 length - offset_extended_shaped_coverage, 342 length - offset_extended_shaped_coverage,
333 num_glyphs)) { 343 num_glyphs)) {
334 return OTS_FAILURE(); 344 return OTS_FAILURE();
335 } 345 }
336 } 346 }
337 if (offset_math_kern_info) { 347 if (offset_math_kern_info) {
338 if (offset_math_kern_info >= length || 348 if (offset_math_kern_info >= length ||
339 offset_math_kern_info < kMathGlyphInfoHeaderSize || 349 offset_math_kern_info < kMathGlyphInfoHeaderSize ||
340 !ParseMathKernInfoTable(data + offset_math_kern_info, 350 !ParseMathKernInfoTable(file, data + offset_math_kern_info,
341 length - offset_math_kern_info, num_glyphs)) { 351 length - offset_math_kern_info, num_glyphs)) {
342 return OTS_FAILURE(); 352 return OTS_FAILURE();
343 } 353 }
344 } 354 }
345 355
346 return true; 356 return true;
347 } 357 }
348 358
349 bool ParseGlyphAssemblyTable(const uint8_t *data, 359 bool ParseGlyphAssemblyTable(const ots::OpenTypeFile *file,
360 const uint8_t *data,
350 size_t length, const uint16_t num_glyphs) { 361 size_t length, const uint16_t num_glyphs) {
351 ots::Buffer subtable(data, length); 362 ots::Buffer subtable(data, length);
352 363
353 // Check the header. 364 // Check the header.
354 uint16_t part_count = 0; 365 uint16_t part_count = 0;
355 if (!ParseMathValueRecord(&subtable, data, length) || 366 if (!ParseMathValueRecord(file, &subtable, data, length) ||
356 !subtable.ReadU16(&part_count)) { 367 !subtable.ReadU16(&part_count)) {
357 return OTS_FAILURE(); 368 return OTS_FAILURE();
358 } 369 }
359 370
360 const unsigned sequence_end = kMathValueRecordSize + 371 const unsigned sequence_end = kMathValueRecordSize +
361 static_cast<unsigned>(2) + part_count * kGlyphPartRecordSize; 372 static_cast<unsigned>(2) + part_count * kGlyphPartRecordSize;
362 if (sequence_end > std::numeric_limits<uint16_t>::max()) { 373 if (sequence_end > std::numeric_limits<uint16_t>::max()) {
363 return OTS_FAILURE(); 374 return OTS_FAILURE();
364 } 375 }
365 376
366 // Check the sequence of GlyphPartRecord. 377 // Check the sequence of GlyphPartRecord.
367 for (unsigned i = 0; i < part_count; ++i) { 378 for (unsigned i = 0; i < part_count; ++i) {
368 uint16_t glyph = 0; 379 uint16_t glyph = 0;
369 uint16_t part_flags = 0; 380 uint16_t part_flags = 0;
370 if (!subtable.ReadU16(&glyph) || 381 if (!subtable.ReadU16(&glyph) ||
371 !subtable.Skip(2 * 3) || 382 !subtable.Skip(2 * 3) ||
372 !subtable.ReadU16(&part_flags)) { 383 !subtable.ReadU16(&part_flags)) {
373 return OTS_FAILURE(); 384 return OTS_FAILURE();
374 } 385 }
375 if (glyph >= num_glyphs) { 386 if (glyph >= num_glyphs) {
376 OTS_WARNING("bad glyph ID: %u", glyph); 387 return OTS_FAILURE_MSG("bad glyph ID: %u", glyph);
377 return OTS_FAILURE();
378 } 388 }
379 if (part_flags & ~0x00000001) { 389 if (part_flags & ~0x00000001) {
380 OTS_WARNING("unknown part flag: %u", part_flags); 390 return OTS_FAILURE_MSG("unknown part flag: %u", part_flags);
381 return OTS_FAILURE();
382 } 391 }
383 } 392 }
384 393
385 return true; 394 return true;
386 } 395 }
387 396
388 bool ParseMathGlyphConstructionTable(const uint8_t *data, 397 bool ParseMathGlyphConstructionTable(const ots::OpenTypeFile *file,
398 const uint8_t *data,
389 size_t length, const uint16_t num_glyphs) { 399 size_t length, const uint16_t num_glyphs) {
390 ots::Buffer subtable(data, length); 400 ots::Buffer subtable(data, length);
391 401
392 // Check the header. 402 // Check the header.
393 uint16_t offset_glyph_assembly = 0; 403 uint16_t offset_glyph_assembly = 0;
394 uint16_t variant_count = 0; 404 uint16_t variant_count = 0;
395 if (!subtable.ReadU16(&offset_glyph_assembly) || 405 if (!subtable.ReadU16(&offset_glyph_assembly) ||
396 !subtable.ReadU16(&variant_count)) { 406 !subtable.ReadU16(&variant_count)) {
397 return OTS_FAILURE(); 407 return OTS_FAILURE();
398 } 408 }
399 409
400 const unsigned sequence_end = static_cast<unsigned>(2 * 2) + 410 const unsigned sequence_end = static_cast<unsigned>(2 * 2) +
401 variant_count * 2 * 2; 411 variant_count * 2 * 2;
402 if (sequence_end > std::numeric_limits<uint16_t>::max()) { 412 if (sequence_end > std::numeric_limits<uint16_t>::max()) {
403 return OTS_FAILURE(); 413 return OTS_FAILURE();
404 } 414 }
405 415
406 // Check the GlyphAssembly offset. 416 // Check the GlyphAssembly offset.
407 if (offset_glyph_assembly) { 417 if (offset_glyph_assembly) {
408 if (offset_glyph_assembly >= length || 418 if (offset_glyph_assembly >= length ||
409 offset_glyph_assembly < sequence_end) { 419 offset_glyph_assembly < sequence_end) {
410 return OTS_FAILURE(); 420 return OTS_FAILURE();
411 } 421 }
412 if (!ParseGlyphAssemblyTable(data + offset_glyph_assembly, 422 if (!ParseGlyphAssemblyTable(file, data + offset_glyph_assembly,
413 length - offset_glyph_assembly, num_glyphs)) { 423 length - offset_glyph_assembly, num_glyphs)) {
414 return OTS_FAILURE(); 424 return OTS_FAILURE();
415 } 425 }
416 } 426 }
417 427
418 // Check the sequence of MathGlyphVariantRecord. 428 // Check the sequence of MathGlyphVariantRecord.
419 for (unsigned i = 0; i < variant_count; ++i) { 429 for (unsigned i = 0; i < variant_count; ++i) {
420 uint16_t glyph = 0; 430 uint16_t glyph = 0;
421 if (!subtable.ReadU16(&glyph) || 431 if (!subtable.ReadU16(&glyph) ||
422 !subtable.Skip(2)) { 432 !subtable.Skip(2)) {
423 return OTS_FAILURE(); 433 return OTS_FAILURE();
424 } 434 }
425 if (glyph >= num_glyphs) { 435 if (glyph >= num_glyphs) {
426 OTS_WARNING("bad glyph ID: %u", glyph); 436 return OTS_FAILURE_MSG("bad glyph ID: %u", glyph);
427 return OTS_FAILURE();
428 } 437 }
429 } 438 }
430 439
431 return true; 440 return true;
432 } 441 }
433 442
434 bool ParseMathGlyphConstructionSequence(ots::Buffer* subtable, 443 bool ParseMathGlyphConstructionSequence(const ots::OpenTypeFile *file,
444 ots::Buffer* subtable,
435 const uint8_t *data, 445 const uint8_t *data,
436 size_t length, 446 size_t length,
437 const uint16_t num_glyphs, 447 const uint16_t num_glyphs,
438 uint16_t offset_coverage, 448 uint16_t offset_coverage,
439 uint16_t glyph_count, 449 uint16_t glyph_count,
440 const unsigned sequence_end) { 450 const unsigned sequence_end) {
441 // Check coverage table. 451 // Check coverage table.
442 if (offset_coverage < sequence_end || offset_coverage >= length) { 452 if (offset_coverage < sequence_end || offset_coverage >= length) {
443 return OTS_FAILURE(); 453 return OTS_FAILURE();
444 } 454 }
445 if (!ots::ParseCoverageTable(data + offset_coverage, 455 if (!ots::ParseCoverageTable(file, data + offset_coverage,
446 length - offset_coverage, 456 length - offset_coverage,
447 num_glyphs, glyph_count)) { 457 num_glyphs, glyph_count)) {
448 return OTS_FAILURE(); 458 return OTS_FAILURE();
449 } 459 }
450 460
451 // Check sequence of MathGlyphConstruction. 461 // Check sequence of MathGlyphConstruction.
452 for (unsigned i = 0; i < glyph_count; ++i) { 462 for (unsigned i = 0; i < glyph_count; ++i) {
453 uint16_t offset_glyph_construction = 0; 463 uint16_t offset_glyph_construction = 0;
454 if (!subtable->ReadU16(&offset_glyph_construction)) { 464 if (!subtable->ReadU16(&offset_glyph_construction)) {
455 return OTS_FAILURE(); 465 return OTS_FAILURE();
456 } 466 }
457 if (offset_glyph_construction < sequence_end || 467 if (offset_glyph_construction < sequence_end ||
458 offset_glyph_construction >= length || 468 offset_glyph_construction >= length ||
459 !ParseMathGlyphConstructionTable(data + offset_glyph_construction, 469 !ParseMathGlyphConstructionTable(file, data + offset_glyph_constructio n,
460 length - offset_glyph_construction, 470 length - offset_glyph_construction,
461 num_glyphs)) { 471 num_glyphs)) {
462 return OTS_FAILURE(); 472 return OTS_FAILURE();
463 } 473 }
464 } 474 }
465 475
466 return true; 476 return true;
467 } 477 }
468 478
469 bool ParseMathVariantsTable(const uint8_t *data, 479 bool ParseMathVariantsTable(const ots::OpenTypeFile *file,
480 const uint8_t *data,
470 size_t length, const uint16_t num_glyphs) { 481 size_t length, const uint16_t num_glyphs) {
471 ots::Buffer subtable(data, length); 482 ots::Buffer subtable(data, length);
472 483
473 // Check the header. 484 // Check the header.
474 uint16_t offset_vert_glyph_coverage = 0; 485 uint16_t offset_vert_glyph_coverage = 0;
475 uint16_t offset_horiz_glyph_coverage = 0; 486 uint16_t offset_horiz_glyph_coverage = 0;
476 uint16_t vert_glyph_count = 0; 487 uint16_t vert_glyph_count = 0;
477 uint16_t horiz_glyph_count = 0; 488 uint16_t horiz_glyph_count = 0;
478 if (!subtable.Skip(2) || // MinConnectorOverlap 489 if (!subtable.Skip(2) || // MinConnectorOverlap
479 !subtable.ReadU16(&offset_vert_glyph_coverage) || 490 !subtable.ReadU16(&offset_vert_glyph_coverage) ||
480 !subtable.ReadU16(&offset_horiz_glyph_coverage) || 491 !subtable.ReadU16(&offset_horiz_glyph_coverage) ||
481 !subtable.ReadU16(&vert_glyph_count) || 492 !subtable.ReadU16(&vert_glyph_count) ||
482 !subtable.ReadU16(&horiz_glyph_count)) { 493 !subtable.ReadU16(&horiz_glyph_count)) {
483 return OTS_FAILURE(); 494 return OTS_FAILURE();
484 } 495 }
485 496
486 const unsigned sequence_end = 5 * 2 + vert_glyph_count * 2 + 497 const unsigned sequence_end = 5 * 2 + vert_glyph_count * 2 +
487 horiz_glyph_count * 2; 498 horiz_glyph_count * 2;
488 if (sequence_end > std::numeric_limits<uint16_t>::max()) { 499 if (sequence_end > std::numeric_limits<uint16_t>::max()) {
489 return OTS_FAILURE(); 500 return OTS_FAILURE();
490 } 501 }
491 502
492 if (!ParseMathGlyphConstructionSequence(&subtable, data, length, num_glyphs, 503 if (!ParseMathGlyphConstructionSequence(file, &subtable, data, length, num_gly phs,
493 offset_vert_glyph_coverage, 504 offset_vert_glyph_coverage,
494 vert_glyph_count, 505 vert_glyph_count,
495 sequence_end) || 506 sequence_end) ||
496 !ParseMathGlyphConstructionSequence(&subtable, data, length, num_glyphs, 507 !ParseMathGlyphConstructionSequence(file, &subtable, data, length, num_gly phs,
497 offset_horiz_glyph_coverage, 508 offset_horiz_glyph_coverage,
498 horiz_glyph_count, 509 horiz_glyph_count,
499 sequence_end)) { 510 sequence_end)) {
500 return OTS_FAILURE(); 511 return OTS_FAILURE();
501 } 512 }
502 513
503 return true; 514 return true;
504 } 515 }
505 516
506 } // namespace 517 } // namespace
507 518
508 #define DROP_THIS_TABLE \ 519 #define DROP_THIS_TABLE(msg_) \
509 do { file->math->data = 0; file->math->length = 0; } while (0) 520 do { \
521 file->math->data = 0; \
522 file->math->length = 0; \
523 OTS_FAILURE_MSG(msg_ ", table discarded"); \
524 } while (0)
510 525
511 namespace ots { 526 namespace ots {
512 527
513 bool ots_math_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 528 bool ots_math_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
514 // Grab the number of glyphs in the file from the maxp table to check 529 // Grab the number of glyphs in the file from the maxp table to check
515 // GlyphIDs in MATH table. 530 // GlyphIDs in MATH table.
516 if (!file->maxp) { 531 if (!file->maxp) {
517 return OTS_FAILURE(); 532 return OTS_FAILURE();
518 } 533 }
519 const uint16_t num_glyphs = file->maxp->num_glyphs; 534 const uint16_t num_glyphs = file->maxp->num_glyphs;
520 535
521 Buffer table(data, length); 536 Buffer table(data, length);
522 537
523 OpenTypeMATH* math = new OpenTypeMATH; 538 OpenTypeMATH* math = new OpenTypeMATH;
524 file->math = math; 539 file->math = math;
525 540
526 uint32_t version = 0; 541 uint32_t version = 0;
527 if (!table.ReadU32(&version)) { 542 if (!table.ReadU32(&version)) {
528 return OTS_FAILURE(); 543 return OTS_FAILURE();
529 } 544 }
530 if (version != 0x00010000) { 545 if (version != 0x00010000) {
531 OTS_WARNING("bad MATH version"); 546 DROP_THIS_TABLE("bad MATH version");
532 DROP_THIS_TABLE;
533 return true; 547 return true;
534 } 548 }
535 549
536 uint16_t offset_math_constants = 0; 550 uint16_t offset_math_constants = 0;
537 uint16_t offset_math_glyph_info = 0; 551 uint16_t offset_math_glyph_info = 0;
538 uint16_t offset_math_variants = 0; 552 uint16_t offset_math_variants = 0;
539 if (!table.ReadU16(&offset_math_constants) || 553 if (!table.ReadU16(&offset_math_constants) ||
540 !table.ReadU16(&offset_math_glyph_info) || 554 !table.ReadU16(&offset_math_glyph_info) ||
541 !table.ReadU16(&offset_math_variants)) { 555 !table.ReadU16(&offset_math_variants)) {
542 return OTS_FAILURE(); 556 return OTS_FAILURE();
543 } 557 }
544 558
545 if (offset_math_constants >= length || 559 if (offset_math_constants >= length ||
546 offset_math_constants < kMathHeaderSize || 560 offset_math_constants < kMathHeaderSize ||
547 offset_math_glyph_info >= length || 561 offset_math_glyph_info >= length ||
548 offset_math_glyph_info < kMathHeaderSize || 562 offset_math_glyph_info < kMathHeaderSize ||
549 offset_math_variants >= length || 563 offset_math_variants >= length ||
550 offset_math_variants < kMathHeaderSize) { 564 offset_math_variants < kMathHeaderSize) {
551 OTS_WARNING("bad offset in MATH header"); 565 DROP_THIS_TABLE("bad offset in MATH header");
552 DROP_THIS_TABLE;
553 return true; 566 return true;
554 } 567 }
555 568
556 if (!ParseMathConstantsTable(data + offset_math_constants, 569 if (!ParseMathConstantsTable(file, data + offset_math_constants,
557 length - offset_math_constants)) { 570 length - offset_math_constants)) {
558 DROP_THIS_TABLE; 571 DROP_THIS_TABLE("failed to parse MathConstants table");
559 return true; 572 return true;
560 } 573 }
561 if (!ParseMathGlyphInfoTable(data + offset_math_glyph_info, 574 if (!ParseMathGlyphInfoTable(file, data + offset_math_glyph_info,
562 length - offset_math_glyph_info, num_glyphs)) { 575 length - offset_math_glyph_info, num_glyphs)) {
563 DROP_THIS_TABLE; 576 DROP_THIS_TABLE("failed to parse MathGlyphInfo table");
564 return true; 577 return true;
565 } 578 }
566 if (!ParseMathVariantsTable(data + offset_math_variants, 579 if (!ParseMathVariantsTable(file, data + offset_math_variants,
567 length - offset_math_variants, num_glyphs)) { 580 length - offset_math_variants, num_glyphs)) {
568 DROP_THIS_TABLE; 581 DROP_THIS_TABLE("failed to parse MathVariants table");
569 return true; 582 return true;
570 } 583 }
571 584
572 math->data = data; 585 math->data = data;
573 math->length = length; 586 math->length = length;
574 return true; 587 return true;
575 } 588 }
576 589
577 bool ots_math_should_serialise(OpenTypeFile *file) { 590 bool ots_math_should_serialise(OpenTypeFile *file) {
578 return file->math != NULL && file->math->data != NULL; 591 return file->math != NULL && file->math->data != NULL;
579 } 592 }
580 593
581 bool ots_math_serialise(OTSStream *out, OpenTypeFile *file) { 594 bool ots_math_serialise(OTSStream *out, OpenTypeFile *file) {
582 if (!out->Write(file->math->data, file->math->length)) { 595 if (!out->Write(file->math->data, file->math->length)) {
583 return OTS_FAILURE(); 596 return OTS_FAILURE();
584 } 597 }
585 598
586 return true; 599 return true;
587 } 600 }
588 601
589 void ots_math_free(OpenTypeFile *file) { 602 void ots_math_free(OpenTypeFile *file) {
590 delete file->math; 603 delete file->math;
591 } 604 }
592 605
593 } // namespace ots 606 } // namespace ots
594 607
608 #undef TABLE_NAME
609 #undef DROP_THIS_TABLE
OLDNEW
« .gitmodules ('K') | « src/ltsh.cc ('k') | src/maxp.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698