tor-browser

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

glyf.cc (25231B)


      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 "glyf.h"
      6 
      7 #include <algorithm>
      8 #include <limits>
      9 
     10 #include "head.h"
     11 #include "loca.h"
     12 #include "maxp.h"
     13 #include "name.h"
     14 
     15 // glyf - Glyph Data
     16 // http://www.microsoft.com/typography/otspec/glyf.htm
     17 
     18 #define TABLE_NAME "glyf"
     19 
     20 namespace ots {
     21 
     22 bool OpenTypeGLYF::ParseFlagsForSimpleGlyph(Buffer &glyph,
     23                                            uint32_t num_flags,
     24                                            std::vector<uint8_t>& flags,
     25                                            uint32_t *flag_index,
     26                                            uint32_t *coordinates_length) {
     27  uint8_t flag = 0;
     28  if (!glyph.ReadU8(&flag)) {
     29    return Error("Can't read flag");
     30  }
     31 
     32  uint32_t delta = 0;
     33  if (flag & (1u << 1)) {  // x-Short
     34    ++delta;
     35  } else if (!(flag & (1u << 4))) {
     36    delta += 2;
     37  }
     38 
     39  if (flag & (1u << 2)) {  // y-Short
     40    ++delta;
     41  } else if (!(flag & (1u << 5))) {
     42    delta += 2;
     43  }
     44 
     45  /* MS and Apple specs say this bit is reserved and must be set to zero, but
     46   * Apple spec then contradicts itself and says it should be set on the first
     47   * contour flag for simple glyphs with overlapping contours:
     48   * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
     49   * (“Overlapping contours” section) */
     50  if (flag & (1u << 6) && *flag_index != 0) {
     51    return Error("Bad glyph flag (%d), "
     52                 "bit 6 must be set to zero for flag %d", flag, *flag_index);
     53  }
     54 
     55  flags[*flag_index] = flag & ~(1u << 3);
     56 
     57  if (flag & (1u << 3)) {  // repeat
     58    if (*flag_index + 1 >= num_flags) {
     59      return Error("Count too high (%d + 1 >= %d)", *flag_index, num_flags);
     60    }
     61    uint8_t repeat = 0;
     62    if (!glyph.ReadU8(&repeat)) {
     63      return Error("Can't read repeat value");
     64    }
     65    if (repeat == 0) {
     66      return Error("Zero repeat");
     67    }
     68    delta += (delta * repeat);
     69 
     70    if (*flag_index + repeat >= num_flags) {
     71      return Error("Count too high (%d >= %d)", *flag_index + repeat, num_flags);
     72    }
     73 
     74    while (repeat--) {
     75      flags[++*flag_index] = flag & ~(1u << 3);
     76    }
     77  }
     78 
     79  if (flag & (1u << 7)) {  // reserved flag
     80    return Error("Bad glyph flag (%d), reserved bit 7 must be set to zero", flag);
     81  }
     82 
     83  *coordinates_length += delta;
     84  if (glyph.length() < *coordinates_length) {
     85    return Error("Glyph coordinates length bigger than glyph length (%d > %d)",
     86                 *coordinates_length, glyph.length());
     87  }
     88 
     89  return true;
     90 }
     91 
     92 #define X_SHORT_VECTOR                        (1u << 1)
     93 #define Y_SHORT_VECTOR                        (1u << 2)
     94 #define X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR  (1u << 4)
     95 #define Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR  (1u << 5)
     96 
     97 bool OpenTypeGLYF::ParseSimpleGlyph(Buffer &glyph,
     98                                    unsigned gid,
     99                                    int16_t num_contours,
    100                                    int16_t xmin,
    101                                    int16_t ymin,
    102                                    int16_t xmax,
    103                                    int16_t ymax,
    104                                    bool is_tricky_font) {
    105  // read the end-points array
    106  uint16_t num_flags = 0;
    107  for (int i = 0; i < num_contours; ++i) {
    108    uint16_t tmp_index = 0;
    109    if (!glyph.ReadU16(&tmp_index)) {
    110      return Error("Can't read contour index %d (glyph %u)", i, gid);
    111    }
    112    if (tmp_index == 0xffffu) {
    113      return Error("Bad contour index %d (glyph %u)", i, gid);
    114    }
    115    // check if the indices are monotonically increasing
    116    if (i && (tmp_index + 1 <= num_flags)) {
    117      return Error("Decreasing contour index %d + 1 <= %d (glyph %u)", tmp_index, num_flags, gid);
    118    }
    119    num_flags = tmp_index + 1;
    120  }
    121 
    122  if (this->maxp->version_1 &&
    123      num_flags > this->maxp->max_points) {
    124    Warning("Number of contour points exceeds maxp maxPoints, adjusting limit (glyph %u)", gid);
    125    this->maxp->max_points = num_flags;
    126  }
    127 
    128  uint16_t bytecode_length = 0;
    129  if (!glyph.ReadU16(&bytecode_length)) {
    130    return Error("Can't read bytecode length");
    131  }
    132 
    133  if (this->maxp->version_1 &&
    134      this->maxp->max_size_glyf_instructions < bytecode_length) {
    135    Warning("Bytecode length is bigger than maxp.maxSizeOfInstructions %d: %d (glyph %u)",
    136            this->maxp->max_size_glyf_instructions, bytecode_length, gid);
    137    this->maxp->max_size_glyf_instructions = bytecode_length;
    138  }
    139 
    140  if (!glyph.Skip(bytecode_length)) {
    141    return Error("Can't read bytecode of length %d (glyph %u)", bytecode_length, gid);
    142  }
    143 
    144  uint32_t coordinates_length = 0;
    145  std::vector<uint8_t> flags(num_flags);
    146  for (uint32_t i = 0; i < num_flags; ++i) {
    147    if (!ParseFlagsForSimpleGlyph(glyph, num_flags, flags, &i, &coordinates_length)) {
    148      return Error("Failed to parse glyph flags %d (glyph %u)", i, gid);
    149    }
    150  }
    151 
    152  bool adjusted_bbox = false;
    153  int16_t x = 0, y = 0;
    154 
    155  // Read and check x-coords
    156  for (uint32_t i = 0; i < num_flags; ++i) {
    157    uint8_t flag = flags[i];
    158    if (flag & X_SHORT_VECTOR) {
    159      uint8_t dx;
    160      if (!glyph.ReadU8(&dx)) {
    161        return Error("Glyph too short %d (glyph %u)", glyph.length(), gid);
    162      }
    163      if (flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
    164        x += dx;
    165      } else {
    166        x -= dx;
    167      }
    168    } else if (flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
    169      // x remains unchanged
    170    } else {
    171      int16_t dx;
    172      if (!glyph.ReadS16(&dx)) {
    173        return Error("Glyph too short %d (glyph %u)", glyph.length(), gid);
    174      }
    175      x += dx;
    176    }
    177    if (x < xmin) {
    178      xmin = x;
    179      adjusted_bbox = true;
    180    }
    181    if (x > xmax) {
    182      xmax = x;
    183      adjusted_bbox = true;
    184    }
    185  }
    186 
    187  // Read and check y-coords
    188  for (uint32_t i = 0; i < num_flags; ++i) {
    189    uint8_t flag = flags[i];
    190    if (flag & Y_SHORT_VECTOR) {
    191      uint8_t dy;
    192      if (!glyph.ReadU8(&dy)) {
    193        return Error("Glyph too short %d (glyph %u)", glyph.length(), gid);
    194      }
    195      if (flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
    196        y += dy;
    197      } else {
    198        y -= dy;
    199      }
    200    } else if (flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
    201      // x remains unchanged
    202    } else {
    203      int16_t dy;
    204      if (!glyph.ReadS16(&dy)) {
    205        return Error("Glyph too short %d (glyph %u)", glyph.length(), gid);
    206      }
    207      y += dy;
    208    }
    209    if (y < ymin) {
    210      ymin = y;
    211      adjusted_bbox = true;
    212    }
    213    if (y > ymax) {
    214      ymax = y;
    215      adjusted_bbox = true;
    216    }
    217  }
    218 
    219  if (glyph.remaining() > 3) {
    220    // We allow 0-3 bytes difference since gly_length is 4-bytes aligned,
    221    // zero-padded length.
    222    Warning("Extra bytes at end of the glyph: %d (glyph %u)", glyph.remaining(), gid);
    223  }
    224 
    225  if (adjusted_bbox) {
    226    if (is_tricky_font) {
    227      Warning("Glyph bbox was incorrect; NOT adjusting tricky font (glyph %u)", gid);
    228    } else {
    229      Warning("Glyph bbox was incorrect; adjusting (glyph %u)", gid);
    230      // copy the numberOfContours field
    231      this->iov.push_back(std::make_pair(glyph.buffer(), 2));
    232      // output a fixed-up version of the bounding box
    233      uint8_t* fixed_bbox = new uint8_t[8];
    234      replacements.push_back(fixed_bbox);
    235      xmin = ots_htons(xmin);
    236      std::memcpy(fixed_bbox, &xmin, 2);
    237      ymin = ots_htons(ymin);
    238      std::memcpy(fixed_bbox + 2, &ymin, 2);
    239      xmax = ots_htons(xmax);
    240      std::memcpy(fixed_bbox + 4, &xmax, 2);
    241      ymax = ots_htons(ymax);
    242      std::memcpy(fixed_bbox + 6, &ymax, 2);
    243      this->iov.push_back(std::make_pair(fixed_bbox, 8));
    244      // copy the remainder of the glyph data
    245      this->iov.push_back(std::make_pair(glyph.buffer() + 10, glyph.offset() - 10));
    246      return true;
    247    }
    248  }
    249 
    250  this->iov.push_back(std::make_pair(glyph.buffer(), glyph.offset()));
    251 
    252  return true;
    253 }
    254 
    255 #define ARG_1_AND_2_ARE_WORDS    (1u << 0)
    256 #define WE_HAVE_A_SCALE          (1u << 3)
    257 #define MORE_COMPONENTS          (1u << 5)
    258 #define WE_HAVE_AN_X_AND_Y_SCALE (1u << 6)
    259 #define WE_HAVE_A_TWO_BY_TWO     (1u << 7)
    260 #define WE_HAVE_INSTRUCTIONS     (1u << 8)
    261 
    262 bool OpenTypeGLYF::ParseCompositeGlyph(
    263    Buffer &glyph,
    264    unsigned glyph_id,
    265    ComponentPointCount* component_point_count,
    266    unsigned* skip_count) {
    267  uint16_t flags = 0;
    268  uint16_t gid = 0;
    269  enum class edit_t : uint8_t {
    270    skip_bytes,  // param is number of bytes to skip from offset
    271    set_flag,    // param is flag to be set (in the 16-bit field at offset)
    272    clear_flag,  // param is flag to be cleared
    273  };
    274  // List of glyph data edits to be applied: first value is offset in the data,
    275  // second is a pair of <edit-action, param>.
    276  typedef std::pair<unsigned, std::pair<edit_t, unsigned>> edit_rec;
    277  std::vector<edit_rec> edits;
    278  unsigned prev_start = 0;
    279  bool we_have_instructions = false;
    280  do {
    281    unsigned start = glyph.offset();
    282 
    283    if (!glyph.ReadU16(&flags) || !glyph.ReadU16(&gid)) {
    284      return Error("Can't read composite glyph flags or glyphIndex");
    285    }
    286 
    287    if (gid >= this->maxp->num_glyphs) {
    288      return Error("Invalid glyph id used in composite glyph: %d", gid);
    289    }
    290 
    291    if (flags & ARG_1_AND_2_ARE_WORDS) {
    292      int16_t argument1;
    293      int16_t argument2;
    294      if (!glyph.ReadS16(&argument1) || !glyph.ReadS16(&argument2)) {
    295        return Error("Can't read argument1 or argument2");
    296      }
    297    } else {
    298      uint8_t argument1;
    299      uint8_t argument2;
    300      if (!glyph.ReadU8(&argument1) || !glyph.ReadU8(&argument2)) {
    301        return Error("Can't read argument1 or argument2");
    302      }
    303    }
    304 
    305    if (flags & WE_HAVE_A_SCALE) {
    306      int16_t scale;
    307      if (!glyph.ReadS16(&scale)) {
    308        return Error("Can't read scale");
    309      }
    310    } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
    311      int16_t xscale;
    312      int16_t yscale;
    313      if (!glyph.ReadS16(&xscale) || !glyph.ReadS16(&yscale)) {
    314        return Error("Can't read xscale or yscale");
    315      }
    316    } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
    317      int16_t xscale;
    318      int16_t scale01;
    319      int16_t scale10;
    320      int16_t yscale;
    321      if (!glyph.ReadS16(&xscale) ||
    322          !glyph.ReadS16(&scale01) ||
    323          !glyph.ReadS16(&scale10) ||
    324          !glyph.ReadS16(&yscale)) {
    325        return Error("Can't read transform");
    326      }
    327    }
    328 
    329    if (this->loca->offsets[gid] == this->loca->offsets[gid + 1]) {
    330      Warning("empty gid %u used as component in glyph %u", gid, glyph_id);
    331      // DirectWrite chokes on composite glyphs that have a completely empty glyph
    332      // as a component; see https://github.com/mozilla/pdf.js/issues/18848.
    333      // To work around this, we attempt to drop empty components.
    334      // But we don't drop the component if it's the only (remaining) one in the composite.
    335      if (prev_start > 0 || (flags & MORE_COMPONENTS)) {
    336        if (!(flags & MORE_COMPONENTS)) {
    337          // We're dropping the last component, so we need to clear the MORE_COMPONENTS flag
    338          // on the previous one.
    339          edits.push_back(edit_rec{prev_start, std::make_pair(edit_t::clear_flag, MORE_COMPONENTS)});
    340        }
    341        // If this component was the first to provide WE_HAVE_INSTRUCTIONS, set it on the previous (if any).
    342        if ((flags & WE_HAVE_INSTRUCTIONS) && !we_have_instructions && prev_start > 0) {
    343          edits.push_back(edit_rec{prev_start, std::make_pair(edit_t::set_flag, WE_HAVE_INSTRUCTIONS)});
    344        }
    345        // Finally, skip the actual bytes of this component.
    346        edits.push_back(edit_rec{start, std::make_pair(edit_t::skip_bytes, glyph.offset() - start)});
    347      }
    348    } else {
    349      // If this is the first component we're keeping, but we already saw WE_HAVE_INSTRUCTIONS
    350      // (on a dropped component), we need to ensure that flag is set here.
    351      if (prev_start == 0 && we_have_instructions && !(flags & WE_HAVE_INSTRUCTIONS)) {
    352        edits.push_back(edit_rec{start, std::make_pair(edit_t::set_flag, WE_HAVE_INSTRUCTIONS)});
    353      }
    354      prev_start = start;
    355    }
    356 
    357    we_have_instructions = we_have_instructions || (flags & WE_HAVE_INSTRUCTIONS);
    358 
    359    // Push initial components on stack at level 1
    360    // to traverse them in parent function.
    361    component_point_count->gid_stack.push_back({gid, 1});
    362  } while (flags & MORE_COMPONENTS);
    363 
    364  // Sort any required edits by offset in the glyph data.
    365  struct {
    366    bool operator() (const edit_rec& a, const edit_rec& b) const {
    367      return a.first < b.first;
    368    }
    369  } cmp;
    370  std::sort(edits.begin(), edits.end(), cmp);
    371 
    372  if (we_have_instructions) {
    373    uint16_t bytecode_length;
    374    if (!glyph.ReadU16(&bytecode_length)) {
    375      return Error("Can't read instructions size");
    376    }
    377 
    378    if (this->maxp->version_1 &&
    379        this->maxp->max_size_glyf_instructions < bytecode_length) {
    380      Warning("Bytecode length is bigger than maxp.maxSizeOfInstructions "
    381              "%d: %d",
    382              this->maxp->max_size_glyf_instructions, bytecode_length);
    383      this->maxp->max_size_glyf_instructions = bytecode_length;
    384    }
    385 
    386    if (!glyph.Skip(bytecode_length)) {
    387      return Error("Can't read bytecode of length %d", bytecode_length);
    388    }
    389  }
    390 
    391  // Record the glyph data in this->iov, accounting for any required edits.
    392  *skip_count = 0;
    393  unsigned offset = 0;
    394  while (!edits.empty()) {
    395    auto& edit = edits.front();
    396    // Handle any glyph data between current offset and the next edit position.
    397    if (edit.first > offset) {
    398      this->iov.push_back(std::make_pair(glyph.buffer() + offset, edit.first - offset));
    399      offset = edit.first;
    400    }
    401 
    402    // Handle the edit. Note that there may be multiple set_flag/clear_flag edits
    403    // at the same offset, but skip_bytes will never coincide with another edit.
    404    auto& action = edit.second;
    405    switch (action.first) {
    406      case edit_t::set_flag:
    407      case edit_t::clear_flag: {
    408        // Read the existing flags word.
    409        uint16_t flags;
    410        std::memcpy(&flags, glyph.buffer() + offset, 2);
    411        flags = ots_ntohs(flags);
    412        // Apply all flag changes for the current offset.
    413        while (!edits.empty() && edits.front().first == offset) {
    414          auto& e = edits.front();
    415          switch (e.second.first) {
    416            case edit_t::set_flag:
    417              flags |= e.second.second;
    418              break;
    419            case edit_t::clear_flag:
    420              flags &= ~e.second.second;
    421              break;
    422            default:
    423              assert(false);
    424              break;
    425          }
    426          edits.erase(edits.begin());
    427        }
    428        // Record the modified flags word.
    429        flags = ots_htons(flags);
    430        uint8_t* flags_data = new uint8_t[2];
    431        std::memcpy(flags_data, &flags, 2);
    432        replacements.push_back(flags_data);
    433        this->iov.push_back(std::make_pair(flags_data, 2));
    434        offset += 2;
    435        break;
    436      }
    437 
    438      case edit_t::skip_bytes:
    439        offset = edit.first + action.second;
    440        *skip_count += action.second;
    441        edits.erase(edits.begin());
    442        break;
    443 
    444      default:
    445        assert(false);
    446        break;
    447    }
    448  }
    449 
    450  // Handle any remaining glyph data after the last edit.
    451  if (glyph.offset() > offset) {
    452    this->iov.push_back(std::make_pair(glyph.buffer() + offset, glyph.offset() - offset));
    453  }
    454 
    455  return true;
    456 }
    457 
    458 bool OpenTypeGLYF::Parse(const uint8_t *data, size_t length) {
    459  OpenTypeMAXP *maxp = static_cast<OpenTypeMAXP*>(
    460      GetFont()->GetTypedTable(OTS_TAG_MAXP));
    461  OpenTypeLOCA *loca = static_cast<OpenTypeLOCA*>(
    462      GetFont()->GetTypedTable(OTS_TAG_LOCA));
    463  OpenTypeHEAD *head = static_cast<OpenTypeHEAD*>(
    464      GetFont()->GetTypedTable(OTS_TAG_HEAD));
    465  if (!maxp || !loca || !head) {
    466    return Error("Missing maxp or loca or head table needed by glyf table");
    467  }
    468 
    469  OpenTypeNAME *name = static_cast<OpenTypeNAME*>(
    470      GetFont()->GetTypedTable(OTS_TAG_NAME));
    471  bool is_tricky = name->IsTrickyFont();
    472 
    473  this->loca = loca;
    474  this->maxp = maxp;
    475 
    476  const unsigned num_glyphs = maxp->num_glyphs;
    477  std::vector<uint32_t> &offsets = loca->offsets;
    478 
    479  if (offsets.size() != num_glyphs + 1) {
    480    return Error("Invalid glyph offsets size %ld != %d", offsets.size(), num_glyphs + 1);
    481  }
    482 
    483  std::vector<uint32_t> resulting_offsets(num_glyphs + 1);
    484  uint32_t current_offset = 0;
    485 
    486  for (unsigned i = 0; i < num_glyphs; ++i) {
    487    // Used by ParseCompositeGlyph to return the number of bytes being skipped
    488    // in the glyph description, so we can adjust offsets properly.
    489    unsigned skip_count = 0;
    490 
    491    Buffer glyph(GetGlyphBufferSection(data, length, offsets, i));
    492    if (!glyph.buffer())
    493      return false;
    494 
    495    if (!glyph.length()) {
    496      resulting_offsets[i] = current_offset;
    497      continue;
    498    }
    499 
    500    int16_t num_contours, xmin, ymin, xmax, ymax;
    501    if (!glyph.ReadS16(&num_contours) ||
    502        !glyph.ReadS16(&xmin) ||
    503        !glyph.ReadS16(&ymin) ||
    504        !glyph.ReadS16(&xmax) ||
    505        !glyph.ReadS16(&ymax)) {
    506      return Error("Can't read glyph %d header", i);
    507    }
    508 
    509    if (num_contours <= -2) {
    510      // -2, -3, -4, ... are reserved for future use.
    511      return Error("Bad number of contours %d in glyph %d", num_contours, i);
    512    }
    513 
    514    // workaround for fonts in http://www.princexml.com/fonts/
    515    if ((xmin == 32767) &&
    516        (xmax == -32767) &&
    517        (ymin == 32767) &&
    518        (ymax == -32767)) {
    519      Warning("bad xmin/xmax/ymin/ymax values");
    520      xmin = xmax = ymin = ymax = 0;
    521    }
    522 
    523    if (xmin > xmax || ymin > ymax) {
    524      return Error("Bad bounding box values bl=(%d, %d), tr=(%d, %d) in glyph %d", xmin, ymin, xmax, ymax, i);
    525    }
    526 
    527    if (num_contours == 0) {
    528      // This is an empty glyph and shouldn’t have any glyph data, but if it
    529      // does we will simply ignore it.
    530      glyph.set_offset(0);
    531    } else if (num_contours > 0) {
    532      if (!ParseSimpleGlyph(glyph, i, num_contours, xmin, ymin, xmax, ymax, is_tricky)) {
    533        return Error("Failed to parse glyph %d", i);
    534      }
    535    } else {
    536 
    537      ComponentPointCount component_point_count;
    538      if (!ParseCompositeGlyph(glyph, i, &component_point_count, &skip_count)) {
    539        return Error("Failed to parse glyph %d", i);
    540      }
    541 
    542      // Check maxComponentDepth and validate maxComponentPoints.
    543      // ParseCompositeGlyph placed the first set of component glyphs on the
    544      // component_point_count.gid_stack, which we start to process below. If a
    545      // nested glyph is in turn a component glyph, additional glyphs are placed
    546      // on the stack.
    547      while (component_point_count.gid_stack.size()) {
    548        GidAtLevel stack_top_gid = component_point_count.gid_stack.back();
    549        component_point_count.gid_stack.pop_back();
    550 
    551        Buffer points_count_glyph(GetGlyphBufferSection(
    552            data,
    553            length,
    554            offsets,
    555            stack_top_gid.gid));
    556 
    557        if (!points_count_glyph.buffer())
    558          return false;
    559 
    560        if (!points_count_glyph.length())
    561          continue;
    562 
    563        if (!TraverseComponentsCountingPoints(points_count_glyph,
    564                                              i,
    565                                              stack_top_gid.level,
    566                                              &component_point_count)) {
    567          return Error("Error validating component points and depth.");
    568        }
    569 
    570        if (component_point_count.accumulated_component_points >
    571            std::numeric_limits<uint16_t>::max()) {
    572          return Error("Illegal composite points value "
    573                       "exceeding 0xFFFF for base glyph %d.", i);
    574        } else if (this->maxp->version_1 &&
    575                   component_point_count.accumulated_component_points >
    576                   this->maxp->max_c_points) {
    577          Warning("Number of composite points in glyph %d exceeds "
    578                  "maxp maxCompositePoints: %d vs %d, adjusting limit.",
    579                  i,
    580                  component_point_count.accumulated_component_points,
    581                  this->maxp->max_c_points
    582                  );
    583          this->maxp->max_c_points =
    584              component_point_count.accumulated_component_points;
    585        }
    586      }
    587    }
    588 
    589    size_t new_size = glyph.offset() - skip_count;
    590    resulting_offsets[i] = current_offset;
    591    // glyphs must be four byte aligned
    592    // TODO(yusukes): investigate whether this padding is really necessary.
    593    //                Which part of the spec requires this?
    594    const unsigned padding = (4 - (new_size & 3)) % 4;
    595    if (padding) {
    596      this->iov.push_back(std::make_pair(
    597          reinterpret_cast<const uint8_t*>("\x00\x00\x00\x00"),
    598          static_cast<size_t>(padding)));
    599      new_size += padding;
    600    }
    601    current_offset += new_size;
    602  }
    603  resulting_offsets[num_glyphs] = current_offset;
    604 
    605  const uint16_t max16 = std::numeric_limits<uint16_t>::max();
    606  if ((*std::max_element(resulting_offsets.begin(),
    607                         resulting_offsets.end()) >= (max16 * 2u)) &&
    608      (head->index_to_loc_format != 1)) {
    609    head->index_to_loc_format = 1;
    610  }
    611 
    612  loca->offsets = resulting_offsets;
    613 
    614  if (this->iov.empty()) {
    615    // As a special case when all glyph in the font are empty, add a zero byte
    616    // to the table, so that we don’t reject it down the way, and to make the
    617    // table work on Windows as well.
    618    // See https://github.com/khaledhosny/ots/issues/52
    619    static const uint8_t kZero = 0;
    620    this->iov.push_back(std::make_pair(&kZero, 1));
    621  }
    622 
    623  return true;
    624 }
    625 
    626 bool OpenTypeGLYF::TraverseComponentsCountingPoints(
    627    Buffer &glyph,
    628    uint16_t base_glyph_id,
    629    uint32_t level,
    630    ComponentPointCount* component_point_count) {
    631 
    632  int16_t num_contours;
    633  if (!glyph.ReadS16(&num_contours) ||
    634      !glyph.Skip(8)) {
    635    return Error("Can't read glyph header.");
    636  }
    637 
    638  if (num_contours <= -2) {
    639    return Error("Bad number of contours %d in glyph.", num_contours);
    640  }
    641 
    642  if (num_contours == 0)
    643    return true;
    644 
    645  // FontTools counts a component level for each traversed recursion. We start
    646  // counting at level 0. If we reach a level that's deeper than
    647  // maxComponentDepth, we expand maxComponentDepth unless it's larger than
    648  // the maximum possible depth.
    649  if (level > std::numeric_limits<uint16_t>::max()) {
    650    return Error("Illegal component depth exceeding 0xFFFF in base glyph id %d.",
    651                 base_glyph_id);
    652  } else if (this->maxp->version_1 &&
    653             level > this->maxp->max_c_depth) {
    654    this->maxp->max_c_depth = level;
    655    Warning("Component depth exceeds maxp maxComponentDepth "
    656            "in glyph %d, adjust limit to %d.",
    657            base_glyph_id, level);
    658  }
    659 
    660  if (num_contours > 0) {
    661    uint16_t num_points = 0;
    662    for (int i = 0; i < num_contours; ++i) {
    663      // Simple glyph, add contour points.
    664      uint16_t tmp_index = 0;
    665      if (!glyph.ReadU16(&tmp_index)) {
    666        return Error("Can't read contour index %d", i);
    667      }
    668      num_points = tmp_index + 1;
    669    }
    670 
    671    component_point_count->accumulated_component_points += num_points;
    672    return true;
    673  } else  {
    674    assert(num_contours == -1);
    675 
    676    // Composite glyph, add gid's to stack.
    677    uint16_t flags = 0;
    678    uint16_t gid = 0;
    679    do {
    680      if (!glyph.ReadU16(&flags) || !glyph.ReadU16(&gid)) {
    681        return Error("Can't read composite glyph flags or glyphIndex");
    682      }
    683 
    684      size_t skip_bytes = 0;
    685      skip_bytes += flags & ARG_1_AND_2_ARE_WORDS ? 4 : 2;
    686 
    687      if (flags & WE_HAVE_A_SCALE) {
    688        skip_bytes += 2;
    689      } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
    690        skip_bytes += 4;
    691      } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
    692        skip_bytes += 8;
    693      }
    694 
    695      if (!glyph.Skip(skip_bytes)) {
    696        return Error("Failed to parse component glyph.");
    697      }
    698 
    699      if (gid >= this->maxp->num_glyphs) {
    700        return Error("Invalid glyph id used in composite glyph: %d", gid);
    701      }
    702 
    703      component_point_count->gid_stack.push_back({gid, level + 1u});
    704    } while (flags & MORE_COMPONENTS);
    705    return true;
    706  }
    707 }
    708 
    709 Buffer OpenTypeGLYF::GetGlyphBufferSection(
    710    const uint8_t *data,
    711    size_t length,
    712    const std::vector<uint32_t>& loca_offsets,
    713    unsigned glyph_id) {
    714 
    715  Buffer null_buffer(nullptr, 0);
    716 
    717  const unsigned gly_offset = loca_offsets[glyph_id];
    718  // The LOCA parser checks that these values are monotonic
    719  const unsigned gly_length = loca_offsets[glyph_id + 1] - loca_offsets[glyph_id];
    720  if (!gly_length) {
    721    // this glyph has no outline (e.g. the space character)
    722    return Buffer(data + gly_offset, 0);
    723  }
    724 
    725  if (gly_offset >= length) {
    726    Error("Glyph %d offset %d too high %ld", glyph_id, gly_offset, length);
    727    return null_buffer;
    728  }
    729  // Since these are unsigned types, the compiler is not allowed to assume
    730  // that they never overflow.
    731  if (gly_offset + gly_length < gly_offset) {
    732    Error("Glyph %d length (%d < 0)!", glyph_id, gly_length);
    733    return null_buffer;
    734  }
    735  if (gly_offset + gly_length > length) {
    736    Error("Glyph %d length %d too high", glyph_id, gly_length);
    737    return null_buffer;
    738  }
    739 
    740  return Buffer(data + gly_offset, gly_length);
    741 }
    742 
    743 bool OpenTypeGLYF::Serialize(OTSStream *out) {
    744  for (unsigned i = 0; i < this->iov.size(); ++i) {
    745    if (!out->Write(this->iov[i].first, this->iov[i].second)) {
    746      return Error("Failed to write glyph %d", i);
    747    }
    748  }
    749 
    750  return true;
    751 }
    752 
    753 }  // namespace ots
    754 
    755 #undef TABLE_NAME