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

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

Powered by Google App Engine
This is Rietveld 408576698