diff options
Diffstat (limited to 'gfx/ots/src/mvar.cc')
-rw-r--r-- | gfx/ots/src/mvar.cc | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/gfx/ots/src/mvar.cc b/gfx/ots/src/mvar.cc new file mode 100644 index 0000000000..e485ec0488 --- /dev/null +++ b/gfx/ots/src/mvar.cc @@ -0,0 +1,107 @@ +// Copyright (c) 2018 The OTS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mvar.h" + +#include "variations.h" + +namespace ots { + +// ----------------------------------------------------------------------------- +// OpenTypeMVAR +// ----------------------------------------------------------------------------- + +bool OpenTypeMVAR::Parse(const uint8_t* data, size_t length) { + Buffer table(data, length); + + uint16_t majorVersion; + uint16_t minorVersion; + uint16_t reserved; + uint16_t valueRecordSize; + uint16_t valueRecordCount; + uint16_t itemVariationStoreOffset; + + if (!table.ReadU16(&majorVersion) || + !table.ReadU16(&minorVersion) || + !table.ReadU16(&reserved) || + !table.ReadU16(&valueRecordSize) || + !table.ReadU16(&valueRecordCount) || + !table.ReadU16(&itemVariationStoreOffset)) { + return DropVariations("Failed to read table header"); + } + + if (majorVersion != 1) { + return DropVariations("Unknown table version"); + } + + if (reserved != 0) { + Warning("Expected reserved=0"); + } + + // The spec says that valueRecordSize "must be greater than zero", + // but we don't enforce this in the case where valueRecordCount + // is zero. + // The minimum size for a valueRecord to be valid is 8, for the + // three fields currently defined in the record (see below). + if (valueRecordSize < 8) { + if (valueRecordCount != 0) { + return DropVariations("Value record size too small"); + } + } + + if (valueRecordCount == 0) { + if (itemVariationStoreOffset != 0) { + // The spec says "if valueRecordCount is zero, set to zero", + // but having a variation store even when record count is zero + // should be harmless -- it just won't be useful for anything. + // But we don't need to reject altogether. + Warning("Unexpected item variation store"); + } + } else { + if (itemVariationStoreOffset < table.offset() || itemVariationStoreOffset > length) { + return DropVariations("Invalid item variation store offset"); + } + if (!ParseItemVariationStore(GetFont(), data + itemVariationStoreOffset, + length - itemVariationStoreOffset)) { + return DropVariations("Failed to parse item variation store"); + } + } + + uint32_t prevTag = 0; + size_t offset = table.offset(); + for (unsigned i = 0; i < valueRecordCount; i++) { + uint32_t tag; + uint16_t deltaSetOuterIndex, deltaSetInnerIndex; + if (!table.ReadU32(&tag) || + !table.ReadU16(&deltaSetOuterIndex) || + !table.ReadU16(&deltaSetInnerIndex)) { + return DropVariations("Failed to read value record"); + } + if (tag <= prevTag) { + return DropVariations( + "Out-of-order value tag: '%c%c%c%c', previous tag: '%c%c%c%c'", + OTS_UNTAG(tag), OTS_UNTAG(prevTag)); + } + prevTag = tag; + // Adjust offset in case additional fields have been added to the + // valueRecord by a new minor version (allowed by spec). + offset += valueRecordSize; + table.set_offset(offset); + } + + this->m_data = data; + this->m_length = length; + + return true; +} + +bool OpenTypeMVAR::Serialize(OTSStream* out) { + if (!out->Write(this->m_data, this->m_length)) { + return Error("Failed to write MVAR table"); + } + + return true; +} + +} // namespace ots |