| Index: third_party/ots/src/math.cc
|
| diff --git a/third_party/ots/src/math.cc b/third_party/ots/src/math.cc
|
| deleted file mode 100644
|
| index 9124a88c512de0492566811a8463f407a65e64bd..0000000000000000000000000000000000000000
|
| --- a/third_party/ots/src/math.cc
|
| +++ /dev/null
|
| @@ -1,609 +0,0 @@
|
| -// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -// We use an underscore to avoid confusion with the standard math.h library.
|
| -#include "math_.h"
|
| -
|
| -#include <limits>
|
| -#include <vector>
|
| -
|
| -#include "layout.h"
|
| -#include "maxp.h"
|
| -
|
| -// MATH - The MATH Table
|
| -// The specification is not yet public but has been submitted to the MPEG group
|
| -// in response to the 'Call for Proposals for ISO/IEC 14496-22 "Open Font
|
| -// Format" Color Font Technology and MATH layout support'. Meanwhile, you can
|
| -// contact Microsoft's engineer Murray Sargent to obtain a copy.
|
| -
|
| -#define TABLE_NAME "MATH"
|
| -
|
| -namespace {
|
| -
|
| -// The size of MATH header.
|
| -// Version
|
| -// MathConstants
|
| -// MathGlyphInfo
|
| -// MathVariants
|
| -const unsigned kMathHeaderSize = 4 + 3 * 2;
|
| -
|
| -// The size of the MathGlyphInfo header.
|
| -// MathItalicsCorrectionInfo
|
| -// MathTopAccentAttachment
|
| -// ExtendedShapeCoverage
|
| -// MathKernInfo
|
| -const unsigned kMathGlyphInfoHeaderSize = 4 * 2;
|
| -
|
| -// The size of the MathValueRecord.
|
| -// Value
|
| -// DeviceTable
|
| -const unsigned kMathValueRecordSize = 2 * 2;
|
| -
|
| -// The size of the GlyphPartRecord.
|
| -// glyph
|
| -// StartConnectorLength
|
| -// EndConnectorLength
|
| -// FullAdvance
|
| -// PartFlags
|
| -const unsigned kGlyphPartRecordSize = 5 * 2;
|
| -
|
| -// Shared Table: MathValueRecord
|
| -
|
| -bool ParseMathValueRecord(const ots::OpenTypeFile *file,
|
| - ots::Buffer* subtable, const uint8_t *data,
|
| - const size_t length) {
|
| - // Check the Value field.
|
| - if (!subtable->Skip(2)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check the offset to device table.
|
| - uint16_t offset = 0;
|
| - if (!subtable->ReadU16(&offset)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (offset) {
|
| - if (offset >= length) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (!ots::ParseDeviceTable(file, data + offset, length - offset)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseMathConstantsTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data, size_t length) {
|
| - ots::Buffer subtable(data, length);
|
| -
|
| - // Part 1: int16 or uint16 constants.
|
| - // ScriptPercentScaleDown
|
| - // ScriptScriptPercentScaleDown
|
| - // DelimitedSubFormulaMinHeight
|
| - // DisplayOperatorMinHeight
|
| - if (!subtable.Skip(4 * 2)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Part 2: MathValueRecord constants.
|
| - // MathLeading
|
| - // AxisHeight
|
| - // AccentBaseHeight
|
| - // FlattenedAccentBaseHeight
|
| - // SubscriptShiftDown
|
| - // SubscriptTopMax
|
| - // SubscriptBaselineDropMin
|
| - // SuperscriptShiftUp
|
| - // SuperscriptShiftUpCramped
|
| - // SuperscriptBottomMin
|
| - //
|
| - // SuperscriptBaselineDropMax
|
| - // SubSuperscriptGapMin
|
| - // SuperscriptBottomMaxWithSubscript
|
| - // SpaceAfterScript
|
| - // UpperLimitGapMin
|
| - // UpperLimitBaselineRiseMin
|
| - // LowerLimitGapMin
|
| - // LowerLimitBaselineDropMin
|
| - // StackTopShiftUp
|
| - // StackTopDisplayStyleShiftUp
|
| - //
|
| - // StackBottomShiftDown
|
| - // StackBottomDisplayStyleShiftDown
|
| - // StackGapMin
|
| - // StackDisplayStyleGapMin
|
| - // StretchStackTopShiftUp
|
| - // StretchStackBottomShiftDown
|
| - // StretchStackGapAboveMin
|
| - // StretchStackGapBelowMin
|
| - // FractionNumeratorShiftUp
|
| - // FractionNumeratorDisplayStyleShiftUp
|
| - //
|
| - // FractionDenominatorShiftDown
|
| - // FractionDenominatorDisplayStyleShiftDown
|
| - // FractionNumeratorGapMin
|
| - // FractionNumDisplayStyleGapMin
|
| - // FractionRuleThickness
|
| - // FractionDenominatorGapMin
|
| - // FractionDenomDisplayStyleGapMin
|
| - // SkewedFractionHorizontalGap
|
| - // SkewedFractionVerticalGap
|
| - // OverbarVerticalGap
|
| - //
|
| - // OverbarRuleThickness
|
| - // OverbarExtraAscender
|
| - // UnderbarVerticalGap
|
| - // UnderbarRuleThickness
|
| - // UnderbarExtraDescender
|
| - // RadicalVerticalGap
|
| - // RadicalDisplayStyleVerticalGap
|
| - // RadicalRuleThickness
|
| - // RadicalExtraAscender
|
| - // RadicalKernBeforeDegree
|
| - //
|
| - // RadicalKernAfterDegree
|
| - for (unsigned i = 0; i < static_cast<unsigned>(51); ++i) {
|
| - if (!ParseMathValueRecord(file, &subtable, data, length)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| -
|
| - // Part 3: uint16 constant
|
| - // RadicalDegreeBottomRaisePercent
|
| - if (!subtable.Skip(2)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseMathValueRecordSequenceForGlyphs(const ots::OpenTypeFile *file,
|
| - ots::Buffer* subtable,
|
| - const uint8_t *data,
|
| - const size_t length,
|
| - const uint16_t num_glyphs) {
|
| - // Check the header.
|
| - uint16_t offset_coverage = 0;
|
| - uint16_t sequence_count = 0;
|
| - if (!subtable->ReadU16(&offset_coverage) ||
|
| - !subtable->ReadU16(&sequence_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - const unsigned sequence_end = static_cast<unsigned>(2 * 2) +
|
| - sequence_count * kMathValueRecordSize;
|
| - if (sequence_end > std::numeric_limits<uint16_t>::max()) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check coverage table.
|
| - if (offset_coverage < sequence_end || offset_coverage >= length) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (!ots::ParseCoverageTable(file, data + offset_coverage,
|
| - length - offset_coverage,
|
| - num_glyphs, sequence_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check sequence.
|
| - for (unsigned i = 0; i < sequence_count; ++i) {
|
| - if (!ParseMathValueRecord(file, subtable, data, length)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseMathItalicsCorrectionInfoTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data,
|
| - size_t length,
|
| - const uint16_t num_glyphs) {
|
| - ots::Buffer subtable(data, length);
|
| - return ParseMathValueRecordSequenceForGlyphs(file, &subtable, data, length,
|
| - num_glyphs);
|
| -}
|
| -
|
| -bool ParseMathTopAccentAttachmentTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data,
|
| - size_t length,
|
| - const uint16_t num_glyphs) {
|
| - ots::Buffer subtable(data, length);
|
| - return ParseMathValueRecordSequenceForGlyphs(file, &subtable, data, length,
|
| - num_glyphs);
|
| -}
|
| -
|
| -bool ParseMathKernTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data, size_t length) {
|
| - ots::Buffer subtable(data, length);
|
| -
|
| - // Check the Height count.
|
| - uint16_t height_count = 0;
|
| - if (!subtable.ReadU16(&height_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check the Correction Heights.
|
| - for (unsigned i = 0; i < height_count; ++i) {
|
| - if (!ParseMathValueRecord(file, &subtable, data, length)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| -
|
| - // Check the Kern Values.
|
| - for (unsigned i = 0; i <= height_count; ++i) {
|
| - if (!ParseMathValueRecord(file, &subtable, data, length)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseMathKernInfoTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data, size_t length,
|
| - const uint16_t num_glyphs) {
|
| - ots::Buffer subtable(data, length);
|
| -
|
| - // Check the header.
|
| - uint16_t offset_coverage = 0;
|
| - uint16_t sequence_count = 0;
|
| - if (!subtable.ReadU16(&offset_coverage) ||
|
| - !subtable.ReadU16(&sequence_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - const unsigned sequence_end = static_cast<unsigned>(2 * 2) +
|
| - sequence_count * 4 * 2;
|
| - if (sequence_end > std::numeric_limits<uint16_t>::max()) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check coverage table.
|
| - if (offset_coverage < sequence_end || offset_coverage >= length) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (!ots::ParseCoverageTable(file, data + offset_coverage, length - offset_coverage,
|
| - num_glyphs, sequence_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check sequence of MathKernInfoRecord
|
| - for (unsigned i = 0; i < sequence_count; ++i) {
|
| - // Check TopRight, TopLeft, BottomRight and BottomLeft Math Kern.
|
| - for (unsigned j = 0; j < 4; ++j) {
|
| - uint16_t offset_math_kern = 0;
|
| - if (!subtable.ReadU16(&offset_math_kern)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (offset_math_kern) {
|
| - if (offset_math_kern < sequence_end || offset_math_kern >= length ||
|
| - !ParseMathKernTable(file, data + offset_math_kern,
|
| - length - offset_math_kern)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseMathGlyphInfoTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data, size_t length,
|
| - const uint16_t num_glyphs) {
|
| - ots::Buffer subtable(data, length);
|
| -
|
| - // Check Header.
|
| - uint16_t offset_math_italics_correction_info = 0;
|
| - uint16_t offset_math_top_accent_attachment = 0;
|
| - uint16_t offset_extended_shaped_coverage = 0;
|
| - uint16_t offset_math_kern_info = 0;
|
| - if (!subtable.ReadU16(&offset_math_italics_correction_info) ||
|
| - !subtable.ReadU16(&offset_math_top_accent_attachment) ||
|
| - !subtable.ReadU16(&offset_extended_shaped_coverage) ||
|
| - !subtable.ReadU16(&offset_math_kern_info)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check subtables.
|
| - // The specification does not say whether the offsets for
|
| - // MathItalicsCorrectionInfo, MathTopAccentAttachment and MathKernInfo may
|
| - // be NULL, but that's the case in some fonts (e.g STIX) so we accept that.
|
| - if (offset_math_italics_correction_info) {
|
| - if (offset_math_italics_correction_info >= length ||
|
| - offset_math_italics_correction_info < kMathGlyphInfoHeaderSize ||
|
| - !ParseMathItalicsCorrectionInfoTable(
|
| - file, data + offset_math_italics_correction_info,
|
| - length - offset_math_italics_correction_info,
|
| - num_glyphs)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| - if (offset_math_top_accent_attachment) {
|
| - if (offset_math_top_accent_attachment >= length ||
|
| - offset_math_top_accent_attachment < kMathGlyphInfoHeaderSize ||
|
| - !ParseMathTopAccentAttachmentTable(file, data +
|
| - offset_math_top_accent_attachment,
|
| - length -
|
| - offset_math_top_accent_attachment,
|
| - num_glyphs)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| - if (offset_extended_shaped_coverage) {
|
| - if (offset_extended_shaped_coverage >= length ||
|
| - offset_extended_shaped_coverage < kMathGlyphInfoHeaderSize ||
|
| - !ots::ParseCoverageTable(file, data + offset_extended_shaped_coverage,
|
| - length - offset_extended_shaped_coverage,
|
| - num_glyphs)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| - if (offset_math_kern_info) {
|
| - if (offset_math_kern_info >= length ||
|
| - offset_math_kern_info < kMathGlyphInfoHeaderSize ||
|
| - !ParseMathKernInfoTable(file, data + offset_math_kern_info,
|
| - length - offset_math_kern_info, num_glyphs)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseGlyphAssemblyTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data,
|
| - size_t length, const uint16_t num_glyphs) {
|
| - ots::Buffer subtable(data, length);
|
| -
|
| - // Check the header.
|
| - uint16_t part_count = 0;
|
| - if (!ParseMathValueRecord(file, &subtable, data, length) ||
|
| - !subtable.ReadU16(&part_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - const unsigned sequence_end = kMathValueRecordSize +
|
| - static_cast<unsigned>(2) + part_count * kGlyphPartRecordSize;
|
| - if (sequence_end > std::numeric_limits<uint16_t>::max()) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check the sequence of GlyphPartRecord.
|
| - for (unsigned i = 0; i < part_count; ++i) {
|
| - uint16_t glyph = 0;
|
| - uint16_t part_flags = 0;
|
| - if (!subtable.ReadU16(&glyph) ||
|
| - !subtable.Skip(2 * 3) ||
|
| - !subtable.ReadU16(&part_flags)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (glyph >= num_glyphs) {
|
| - return OTS_FAILURE_MSG("bad glyph ID: %u", glyph);
|
| - }
|
| - if (part_flags & ~0x00000001) {
|
| - return OTS_FAILURE_MSG("unknown part flag: %u", part_flags);
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseMathGlyphConstructionTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data,
|
| - size_t length, const uint16_t num_glyphs) {
|
| - ots::Buffer subtable(data, length);
|
| -
|
| - // Check the header.
|
| - uint16_t offset_glyph_assembly = 0;
|
| - uint16_t variant_count = 0;
|
| - if (!subtable.ReadU16(&offset_glyph_assembly) ||
|
| - !subtable.ReadU16(&variant_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - const unsigned sequence_end = static_cast<unsigned>(2 * 2) +
|
| - variant_count * 2 * 2;
|
| - if (sequence_end > std::numeric_limits<uint16_t>::max()) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check the GlyphAssembly offset.
|
| - if (offset_glyph_assembly) {
|
| - if (offset_glyph_assembly >= length ||
|
| - offset_glyph_assembly < sequence_end) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (!ParseGlyphAssemblyTable(file, data + offset_glyph_assembly,
|
| - length - offset_glyph_assembly, num_glyphs)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| -
|
| - // Check the sequence of MathGlyphVariantRecord.
|
| - for (unsigned i = 0; i < variant_count; ++i) {
|
| - uint16_t glyph = 0;
|
| - if (!subtable.ReadU16(&glyph) ||
|
| - !subtable.Skip(2)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (glyph >= num_glyphs) {
|
| - return OTS_FAILURE_MSG("bad glyph ID: %u", glyph);
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseMathGlyphConstructionSequence(const ots::OpenTypeFile *file,
|
| - ots::Buffer* subtable,
|
| - const uint8_t *data,
|
| - size_t length,
|
| - const uint16_t num_glyphs,
|
| - uint16_t offset_coverage,
|
| - uint16_t glyph_count,
|
| - const unsigned sequence_end) {
|
| - // Check coverage table.
|
| - if (offset_coverage < sequence_end || offset_coverage >= length) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (!ots::ParseCoverageTable(file, data + offset_coverage,
|
| - length - offset_coverage,
|
| - num_glyphs, glyph_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - // Check sequence of MathGlyphConstruction.
|
| - for (unsigned i = 0; i < glyph_count; ++i) {
|
| - uint16_t offset_glyph_construction = 0;
|
| - if (!subtable->ReadU16(&offset_glyph_construction)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (offset_glyph_construction < sequence_end ||
|
| - offset_glyph_construction >= length ||
|
| - !ParseMathGlyphConstructionTable(file, data + offset_glyph_construction,
|
| - length - offset_glyph_construction,
|
| - num_glyphs)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ParseMathVariantsTable(const ots::OpenTypeFile *file,
|
| - const uint8_t *data,
|
| - size_t length, const uint16_t num_glyphs) {
|
| - ots::Buffer subtable(data, length);
|
| -
|
| - // Check the header.
|
| - uint16_t offset_vert_glyph_coverage = 0;
|
| - uint16_t offset_horiz_glyph_coverage = 0;
|
| - uint16_t vert_glyph_count = 0;
|
| - uint16_t horiz_glyph_count = 0;
|
| - if (!subtable.Skip(2) || // MinConnectorOverlap
|
| - !subtable.ReadU16(&offset_vert_glyph_coverage) ||
|
| - !subtable.ReadU16(&offset_horiz_glyph_coverage) ||
|
| - !subtable.ReadU16(&vert_glyph_count) ||
|
| - !subtable.ReadU16(&horiz_glyph_count)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - const unsigned sequence_end = 5 * 2 + vert_glyph_count * 2 +
|
| - horiz_glyph_count * 2;
|
| - if (sequence_end > std::numeric_limits<uint16_t>::max()) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - if (!ParseMathGlyphConstructionSequence(file, &subtable, data, length, num_glyphs,
|
| - offset_vert_glyph_coverage,
|
| - vert_glyph_count,
|
| - sequence_end) ||
|
| - !ParseMathGlyphConstructionSequence(file, &subtable, data, length, num_glyphs,
|
| - offset_horiz_glyph_coverage,
|
| - horiz_glyph_count,
|
| - sequence_end)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -#define DROP_THIS_TABLE(msg_) \
|
| - do { \
|
| - OTS_FAILURE_MSG(msg_ ", table discarded"); \
|
| - file->math->data = 0; \
|
| - file->math->length = 0; \
|
| - } while (0)
|
| -
|
| -namespace ots {
|
| -
|
| -bool ots_math_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
|
| - // Grab the number of glyphs in the file from the maxp table to check
|
| - // GlyphIDs in MATH table.
|
| - if (!file->maxp) {
|
| - return OTS_FAILURE();
|
| - }
|
| - const uint16_t num_glyphs = file->maxp->num_glyphs;
|
| -
|
| - Buffer table(data, length);
|
| -
|
| - OpenTypeMATH* math = new OpenTypeMATH;
|
| - file->math = math;
|
| -
|
| - uint32_t version = 0;
|
| - if (!table.ReadU32(&version)) {
|
| - return OTS_FAILURE();
|
| - }
|
| - if (version != 0x00010000) {
|
| - DROP_THIS_TABLE("bad MATH version");
|
| - return true;
|
| - }
|
| -
|
| - uint16_t offset_math_constants = 0;
|
| - uint16_t offset_math_glyph_info = 0;
|
| - uint16_t offset_math_variants = 0;
|
| - if (!table.ReadU16(&offset_math_constants) ||
|
| - !table.ReadU16(&offset_math_glyph_info) ||
|
| - !table.ReadU16(&offset_math_variants)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - if (offset_math_constants >= length ||
|
| - offset_math_constants < kMathHeaderSize ||
|
| - offset_math_glyph_info >= length ||
|
| - offset_math_glyph_info < kMathHeaderSize ||
|
| - offset_math_variants >= length ||
|
| - offset_math_variants < kMathHeaderSize) {
|
| - DROP_THIS_TABLE("bad offset in MATH header");
|
| - return true;
|
| - }
|
| -
|
| - if (!ParseMathConstantsTable(file, data + offset_math_constants,
|
| - length - offset_math_constants)) {
|
| - DROP_THIS_TABLE("failed to parse MathConstants table");
|
| - return true;
|
| - }
|
| - if (!ParseMathGlyphInfoTable(file, data + offset_math_glyph_info,
|
| - length - offset_math_glyph_info, num_glyphs)) {
|
| - DROP_THIS_TABLE("failed to parse MathGlyphInfo table");
|
| - return true;
|
| - }
|
| - if (!ParseMathVariantsTable(file, data + offset_math_variants,
|
| - length - offset_math_variants, num_glyphs)) {
|
| - DROP_THIS_TABLE("failed to parse MathVariants table");
|
| - return true;
|
| - }
|
| -
|
| - math->data = data;
|
| - math->length = length;
|
| - return true;
|
| -}
|
| -
|
| -bool ots_math_should_serialise(OpenTypeFile *file) {
|
| - return file->math != NULL && file->math->data != NULL;
|
| -}
|
| -
|
| -bool ots_math_serialise(OTSStream *out, OpenTypeFile *file) {
|
| - if (!out->Write(file->math->data, file->math->length)) {
|
| - return OTS_FAILURE();
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void ots_math_free(OpenTypeFile *file) {
|
| - delete file->math;
|
| -}
|
| -
|
| -} // namespace ots
|
| -
|
| -#undef TABLE_NAME
|
| -#undef DROP_THIS_TABLE
|
|
|