tor-browser

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

gasp.cc (2430B)


      1 // Copyright (c) 2009-2017 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 "gasp.h"
      6 
      7 // gasp - Grid-fitting And Scan-conversion Procedure
      8 // http://www.microsoft.com/typography/otspec/gasp.htm
      9 
     10 namespace ots {
     11 
     12 bool OpenTypeGASP::Parse(const uint8_t *data, size_t length) {
     13  Buffer table(data, length);
     14 
     15  uint16_t num_ranges = 0;
     16  if (!table.ReadU16(&this->version) ||
     17      !table.ReadU16(&num_ranges)) {
     18    return Error("Failed to read table header");
     19  }
     20 
     21  if (this->version > 1) {
     22    // Lots of Linux fonts have bad version numbers...
     23    return Drop("Unsupported version: %u", this->version);
     24  }
     25 
     26  if (num_ranges == 0) {
     27    return Drop("numRanges is zero");
     28  }
     29 
     30  this->gasp_ranges.reserve(num_ranges);
     31  for (unsigned i = 0; i < num_ranges; ++i) {
     32    uint16_t max_ppem = 0;
     33    uint16_t behavior = 0;
     34    if (!table.ReadU16(&max_ppem) ||
     35        !table.ReadU16(&behavior)) {
     36      return Error("Failed to read GASPRANGE %d", i);
     37    }
     38    if ((i > 0) && (this->gasp_ranges[i - 1].first >= max_ppem)) {
     39      // The records in the gaspRange[] array must be sorted in order of
     40      // increasing rangeMaxPPEM value.
     41      return Drop("Ranges are not sorted");
     42    }
     43    if ((i == num_ranges - 1u) &&  // never underflow.
     44        (max_ppem != 0xffffu)) {
     45      return Drop("The last record should be 0xFFFF as a sentinel value "
     46                  "for rangeMaxPPEM");
     47    }
     48 
     49    if (behavior >> 8) {
     50      Warning("Undefined bits are used: %x", behavior);
     51      // mask undefined bits.
     52      behavior &= 0x000fu;
     53    }
     54 
     55    if (this->version == 0 && (behavior >> 2) != 0) {
     56      Warning("Changed the version number to 1");
     57      this->version = 1;
     58    }
     59 
     60    this->gasp_ranges.push_back(std::make_pair(max_ppem, behavior));
     61  }
     62 
     63  return true;
     64 }
     65 
     66 bool OpenTypeGASP::Serialize(OTSStream *out) {
     67  const uint16_t num_ranges = static_cast<uint16_t>(this->gasp_ranges.size());
     68  if (num_ranges != this->gasp_ranges.size() ||
     69      !out->WriteU16(this->version) ||
     70      !out->WriteU16(num_ranges)) {
     71    return Error("Failed to write table header");
     72  }
     73 
     74  for (uint16_t i = 0; i < num_ranges; ++i) {
     75    if (!out->WriteU16(this->gasp_ranges[i].first) ||
     76        !out->WriteU16(this->gasp_ranges[i].second)) {
     77      return Error("Failed to write GASPRANGE %d", i);
     78    }
     79  }
     80 
     81  return true;
     82 }
     83 
     84 }  // namespace ots