mvar.cc (3346B)
1 // Copyright (c) 2018 The OTS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mvar.h" 6 7 #include "variations.h" 8 9 namespace ots { 10 11 // ----------------------------------------------------------------------------- 12 // OpenTypeMVAR 13 // ----------------------------------------------------------------------------- 14 15 bool OpenTypeMVAR::Parse(const uint8_t* data, size_t length) { 16 Buffer table(data, length); 17 18 uint16_t majorVersion; 19 uint16_t minorVersion; 20 uint16_t reserved; 21 uint16_t valueRecordSize; 22 uint16_t valueRecordCount; 23 uint16_t itemVariationStoreOffset; 24 25 if (!table.ReadU16(&majorVersion) || 26 !table.ReadU16(&minorVersion) || 27 !table.ReadU16(&reserved) || 28 !table.ReadU16(&valueRecordSize) || 29 !table.ReadU16(&valueRecordCount) || 30 !table.ReadU16(&itemVariationStoreOffset)) { 31 return DropVariations("Failed to read table header"); 32 } 33 34 if (majorVersion != 1) { 35 return DropVariations("Unknown table version"); 36 } 37 38 if (reserved != 0) { 39 Warning("Expected reserved=0"); 40 } 41 42 // The spec says that valueRecordSize "must be greater than zero", 43 // but we don't enforce this in the case where valueRecordCount 44 // is zero. 45 // The minimum size for a valueRecord to be valid is 8, for the 46 // three fields currently defined in the record (see below). 47 if (valueRecordSize < 8) { 48 if (valueRecordCount != 0) { 49 return DropVariations("Value record size too small"); 50 } 51 } 52 53 if (valueRecordCount == 0) { 54 if (itemVariationStoreOffset != 0) { 55 // The spec says "if valueRecordCount is zero, set to zero", 56 // but having a variation store even when record count is zero 57 // should be harmless -- it just won't be useful for anything. 58 // But we don't need to reject altogether. 59 Warning("Unexpected item variation store"); 60 } 61 } else { 62 if (itemVariationStoreOffset < table.offset() || itemVariationStoreOffset > length) { 63 return DropVariations("Invalid item variation store offset"); 64 } 65 if (!ParseItemVariationStore(GetFont(), data + itemVariationStoreOffset, 66 length - itemVariationStoreOffset)) { 67 return DropVariations("Failed to parse item variation store"); 68 } 69 } 70 71 uint32_t prevTag = 0; 72 size_t offset = table.offset(); 73 for (unsigned i = 0; i < valueRecordCount; i++) { 74 uint32_t tag; 75 uint16_t deltaSetOuterIndex, deltaSetInnerIndex; 76 if (!table.ReadU32(&tag) || 77 !table.ReadU16(&deltaSetOuterIndex) || 78 !table.ReadU16(&deltaSetInnerIndex)) { 79 return DropVariations("Failed to read value record"); 80 } 81 if (tag <= prevTag) { 82 return DropVariations( 83 "Out-of-order value tag: '%c%c%c%c', previous tag: '%c%c%c%c'", 84 OTS_UNTAG(tag), OTS_UNTAG(prevTag)); 85 } 86 prevTag = tag; 87 // Adjust offset in case additional fields have been added to the 88 // valueRecord by a new minor version (allowed by spec). 89 offset += valueRecordSize; 90 table.set_offset(offset); 91 } 92 93 this->m_data = data; 94 this->m_length = length; 95 96 return true; 97 } 98 99 bool OpenTypeMVAR::Serialize(OTSStream* out) { 100 if (!out->Write(this->m_data, this->m_length)) { 101 return Error("Failed to write MVAR table"); 102 } 103 104 return true; 105 } 106 107 } // namespace ots