tor-browser

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

avar.cc (5054B)


      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 "avar.h"
      6 
      7 #include "fvar.h"
      8 
      9 #include "variations.h"
     10 
     11 namespace ots {
     12 
     13 // -----------------------------------------------------------------------------
     14 // OpenTypeAVAR
     15 // -----------------------------------------------------------------------------
     16 
     17 bool OpenTypeAVAR::Parse(const uint8_t* data, size_t length) {
     18  Buffer table(data, length);
     19  if (!table.ReadU16(&this->majorVersion) ||
     20      !table.ReadU16(&this->minorVersion) ||
     21      !table.ReadU16(&this->reserved) ||
     22      !table.ReadU16(&this->axisCount)) {
     23    return Drop("Failed to read table header");
     24  }
     25  if (this->majorVersion > 2) {
     26    return Drop("Unknown table version");
     27  }
     28  if (this->majorVersion == 1) {
     29    // We can fix table
     30    if (this->minorVersion > 0) {
     31      // we only know how to serialize version 1.0
     32      Warning("Downgrading minor version to 0");
     33      this->minorVersion = 0;
     34    }
     35    if (this->reserved != 0) {
     36      Warning("Expected reserved=0");
     37      this->reserved = 0;
     38    }
     39  } else {
     40    // We serialize data unchanged, so drop even for minor errors
     41    if (this->minorVersion > 0) {
     42      return Drop("Unknown minor table version");
     43    }
     44    if (this->reserved != 0) {
     45      return Drop("Expected reserved=0");
     46    }
     47  }
     48 
     49  OpenTypeFVAR* fvar = static_cast<OpenTypeFVAR*>(
     50      GetFont()->GetTypedTable(OTS_TAG_FVAR));
     51  if (!fvar) {
     52    return DropVariations("Required fvar table is missing");
     53  }
     54  if (axisCount != fvar->AxisCount()) {
     55    return Drop("Axis count mismatch");
     56  }
     57 
     58  for (size_t i = 0; i < this->axisCount; i++) {
     59    this->axisSegmentMaps.emplace_back();
     60    uint16_t positionMapCount;
     61    if (!table.ReadU16(&positionMapCount)) {
     62      return Drop("Failed to read position map count");
     63    }
     64    int foundRequiredMappings = 0;
     65    for (size_t j = 0; j < positionMapCount; j++) {
     66      AxisValueMap map;
     67      if (!table.ReadS16(&map.fromCoordinate) ||
     68          !table.ReadS16(&map.toCoordinate)) {
     69        return Drop("Failed to read axis value map");
     70      }
     71      if (map.fromCoordinate < -0x4000 ||
     72          map.fromCoordinate > 0x4000 ||
     73          map.toCoordinate < -0x4000 ||
     74          map.toCoordinate > 0x4000) {
     75        return Drop("Axis value map coordinate out of range");
     76      }
     77      if (j > 0) {
     78        if (map.fromCoordinate <= this->axisSegmentMaps[i].back().fromCoordinate ||
     79            map.toCoordinate < this->axisSegmentMaps[i].back().toCoordinate) {
     80          return Drop("Axis value map out of order");
     81        }
     82      }
     83      if ((map.fromCoordinate == -0x4000 && map.toCoordinate == -0x4000) ||
     84          (map.fromCoordinate == 0 && map.toCoordinate == 0) ||
     85          (map.fromCoordinate == 0x4000 && map.toCoordinate == 0x4000)) {
     86        ++foundRequiredMappings;
     87      }
     88      this->axisSegmentMaps[i].push_back(map);
     89    }
     90    if (positionMapCount > 0 && foundRequiredMappings != 3) {
     91      return Drop("A required mapping (for -1, 0 or 1) is missing");
     92    }
     93  }
     94 
     95  if (this->majorVersion < 2)
     96    return true;
     97 
     98  uint32_t axisIndexMapOffset;
     99  uint32_t varStoreOffset;
    100 
    101  if (!table.ReadU32(&axisIndexMapOffset) ||
    102      !table.ReadU32(&varStoreOffset)) {
    103    return Drop("Failed to read version 2 offsets");
    104  }
    105 
    106  Font *font = GetFont();
    107  uint32_t headerSize = table.offset();
    108 
    109  if (axisIndexMapOffset) {
    110    if (axisIndexMapOffset < headerSize || axisIndexMapOffset >= length) {
    111      return Drop("Bad delta set index offset in table header");
    112    }
    113    if (!ParseDeltaSetIndexMap(font, data + axisIndexMapOffset, length - axisIndexMapOffset)) {
    114      return Drop("Failed to parse delta set index map");
    115    }
    116  }
    117 
    118  if (varStoreOffset) {
    119    if (varStoreOffset < headerSize || varStoreOffset >= length) {
    120      return Drop("Bad item variation store offset in table header");
    121    }
    122    if (!ParseItemVariationStore(font, data + varStoreOffset, length - varStoreOffset)) {
    123      return Drop("Failed to parse item variation store");
    124    }
    125  }
    126 
    127  this->m_data = data;
    128  this->m_length = length;
    129 
    130  return true;
    131 }
    132 
    133 bool OpenTypeAVAR::Serialize(OTSStream* out) {
    134  if (this->majorVersion >= 2) {
    135    if (!out->Write(this->m_data, this->m_length)) {
    136      return Error("Failed to write table");
    137    }
    138    return true;
    139  }
    140 
    141  if (!out->WriteU16(this->majorVersion) ||
    142      !out->WriteU16(this->minorVersion) ||
    143      !out->WriteU16(this->reserved) ||
    144      !out->WriteU16(this->axisCount)) {
    145    return Error("Failed to write table");
    146  }
    147 
    148  for (size_t i = 0; i < this->axisCount; i++) {
    149    const auto& axisValueMap = this->axisSegmentMaps[i];
    150    if (!out->WriteU16(axisValueMap.size())) {
    151      return Error("Failed to write table");
    152    }
    153    for (size_t j = 0; j < axisValueMap.size(); j++) {
    154      if (!out->WriteS16(axisValueMap[j].fromCoordinate) ||
    155          !out->WriteS16(axisValueMap[j].toCoordinate)) {
    156        return Error("Failed to write table");
    157      }
    158    }
    159  }
    160 
    161  return true;
    162 }
    163 
    164 }  // namespace ots