tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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