summaryrefslogtreecommitdiffstats
path: root/gfx/ots/src/mvar.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/ots/src/mvar.cc107
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