100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// Copyright (c) 2011 The Chromium Authors. All rights reserved.
200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// Use of this source code is governed by a BSD-style license that can be
300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// found in the LICENSE file.
400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#include "gdef.h"
600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com#include <limits>
800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#include <vector>
900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
10a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org#include "gpos.h"
11a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org#include "gsub.h"
1200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#include "layout.h"
1300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#include "maxp.h"
1400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
1500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// GDEF - The Glyph Definition Table
1600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// http://www.microsoft.com/typography/otspec/gdef.htm
1700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
1800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comnamespace {
1900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
2000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// The maximum class value in class definition tables.
2100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comconst uint16_t kMaxClassDefValue = 0xFFFF;
2200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// The maximum class value in the glyph class definision table.
2300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comconst uint16_t kMaxGlyphClassDefValue = 4;
2400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// The maximum format number of caret value tables.
2500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// We don't support format 3 for now. See the comment in
2600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// ParseLigCaretListTable() for the reason.
2700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comconst uint16_t kMaxCaretValueFormat = 2;
2800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
2900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseGlyphClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
3000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                             size_t length, const uint16_t num_glyphs) {
3100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return ots::ParseClassDefTable(data, length, num_glyphs,
3200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                 kMaxGlyphClassDefValue);
3300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
3400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
3500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseAttachListTable(ots::OpenTypeFile *file, const uint8_t *data,
3600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                          size_t length, const uint16_t num_glyphs) {
3700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  ots::Buffer subtable(data, length);
3800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
3900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t offset_coverage = 0;
4000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t glyph_count = 0;
4100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&offset_coverage) ||
4200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      !subtable.ReadU16(&glyph_count)) {
4300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
4400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
4526afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned attach_points_end =
4626afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * static_cast<unsigned>(glyph_count) + 4;
4778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (attach_points_end > std::numeric_limits<uint16_t>::max()) {
4878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
4978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
5000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (offset_coverage == 0 || offset_coverage >= length ||
5100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      offset_coverage < attach_points_end) {
5200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
5300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
5400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (glyph_count > num_glyphs) {
5500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad glyph count: %u", glyph_count);
5600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
5700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
5800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
5900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  std::vector<uint16_t> attach_points;
6000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  attach_points.resize(glyph_count);
6100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < glyph_count; ++i) {
6200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU16(&attach_points[i])) {
6300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
6400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
6500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (attach_points[i] >= length ||
6600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        attach_points[i] < attach_points_end) {
6700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
6800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
6900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
7000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
7100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Parse coverage table
7200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!ots::ParseCoverageTable(data + offset_coverage,
7300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                               length - offset_coverage, num_glyphs)) {
7400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
7500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
7600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
7700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Parse attach point table
7800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < attach_points.size(); ++i) {
7900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    subtable.set_offset(attach_points[i]);
8000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t point_count = 0;
8100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU16(&point_count)) {
8200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
8300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
8400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (point_count == 0) {
8500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
8600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
8700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t last_point_index = 0;
8800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t point_index = 0;
8900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    for (unsigned j = 0; j < point_count; ++j) {
9000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      if (!subtable.ReadU16(&point_index)) {
9100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        return OTS_FAILURE();
9200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      }
9300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      // Contour point indeces are in increasing numerical order
9400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      if (last_point_index != 0 && last_point_index >= point_index) {
9500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        OTS_WARNING("bad contour indeces: %u >= %u",
9600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                    last_point_index, point_index);
9700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        return OTS_FAILURE();
9800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      }
9900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      last_point_index = point_index;
10000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
10100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
10200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
10300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
10400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
10500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseLigCaretListTable(ots::OpenTypeFile *file, const uint8_t *data,
10600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                            size_t length, const uint16_t num_glyphs) {
10700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  ots::Buffer subtable(data, length);
10800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t offset_coverage = 0;
10900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t lig_glyph_count = 0;
11000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&offset_coverage) ||
11100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      !subtable.ReadU16(&lig_glyph_count)) {
11200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
11300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
11426afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned lig_glyphs_end =
11526afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * static_cast<unsigned>(lig_glyph_count) + 4;
11678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (lig_glyphs_end > std::numeric_limits<uint16_t>::max()) {
11778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
11878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
11900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (offset_coverage == 0 || offset_coverage >= length ||
12000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      offset_coverage < lig_glyphs_end) {
12100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
12200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
12300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (lig_glyph_count > num_glyphs) {
12400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad ligature glyph count: %u", lig_glyph_count);
12500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
12600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
12700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
12800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  std::vector<uint16_t> lig_glyphs;
12900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  lig_glyphs.resize(lig_glyph_count);
13000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < lig_glyph_count; ++i) {
13100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU16(&lig_glyphs[i])) {
13200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
13300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
13400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (lig_glyphs[i] >= length || lig_glyphs[i] < lig_glyphs_end) {
13500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
13600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
13700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
13800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
13900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Parse coverage table
14000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!ots::ParseCoverageTable(data + offset_coverage,
14100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                               length - offset_coverage, num_glyphs)) {
14200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
14300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
14400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
14500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Parse ligature glyph table
14600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < lig_glyphs.size(); ++i) {
14700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    subtable.set_offset(lig_glyphs[i]);
14800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t caret_count = 0;
14900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU16(&caret_count)) {
15000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
15100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
15200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (caret_count == 0) {
15300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      OTS_WARNING("bad caret value count: %u", caret_count);
15400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
15500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
15600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
15700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    std::vector<uint16_t> caret_values;
15800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    caret_values.resize(caret_count);
15900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t last_offset_caret = 0;
16026afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org    unsigned caret_values_end = 2 * static_cast<unsigned>(caret_count) + 2;
16100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    for (unsigned j = 0; j < caret_count; ++j) {
16200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      if (!subtable.ReadU16(&caret_values[j])) {
16300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        return OTS_FAILURE();
16400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      }
16500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      if (caret_values[j] >= length || caret_values[j] < caret_values_end) {
16600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        return OTS_FAILURE();
16700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      }
16800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      // Caret offsets are in increasing coordinate order
16900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      if (last_offset_caret != 0 && last_offset_caret >= caret_values[j]) {
17000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        OTS_WARNING("offset isn't in increasing coordinate order: %u >= %u",
17100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                    last_offset_caret, caret_values[j]);
17200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        return OTS_FAILURE();
17300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      }
17400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      last_offset_caret = caret_values[j];
17500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
17600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
17700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    // Parse caret values table
17800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    for (unsigned j = 0; j < caret_count; ++j) {
17900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      subtable.set_offset(lig_glyphs[i] + caret_values[j]);
18000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      uint16_t caret_format = 0;
18100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      if (!subtable.ReadU16(&caret_format)) {
18200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        return OTS_FAILURE();
18300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      }
18400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      // TODO(bashi): We only support caret value format 1 and 2 for now
18500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      // because there are no fonts which contain caret value format 3
18600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      // as far as we investigated.
18700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      if (caret_format == 0 || caret_format > kMaxCaretValueFormat) {
18800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        OTS_WARNING("bad caret value format: %u", caret_format);
18900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        return OTS_FAILURE();
19000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      }
19100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      // CaretValueFormats contain a 2-byte field which could be
19200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      // arbitrary value.
19300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      if (!subtable.Skip(2)) {
19400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        return OTS_FAILURE();
19500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      }
19600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
19700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
19800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
19900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
20000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
20100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseMarkAttachClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
20200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                  size_t length, const uint16_t num_glyphs) {
20300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return ots::ParseClassDefTable(data, length, num_glyphs, kMaxClassDefValue);
20400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
20500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
20600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseMarkGlyphSetsDefTable(ots::OpenTypeFile *file, const uint8_t *data,
20700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                size_t length, const uint16_t num_glyphs) {
20800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  ots::Buffer subtable(data, length);
20900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t format = 0;
21000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t mark_set_count = 0;
21100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&format) ||
21200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      !subtable.ReadU16(&mark_set_count)) {
21300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
21400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
21500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (format != 1) {
21600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad mark glyph set table format: %u", format);
21700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
21800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
21900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
22026afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned mark_sets_end = 2 * static_cast<unsigned>(mark_set_count) + 4;
22178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (mark_sets_end > std::numeric_limits<uint16_t>::max()) {
22278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
22378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
22400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < mark_set_count; ++i) {
22500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint32_t offset_coverage = 0;
22600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU32(&offset_coverage)) {
22700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
22800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
22900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (offset_coverage >= length ||
23000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        offset_coverage < mark_sets_end) {
23100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
23200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
23300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!ots::ParseCoverageTable(data + offset_coverage,
23400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                 length - offset_coverage, num_glyphs)) {
23500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
23600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
23700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
23878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  file->gdef->num_mark_glyph_sets = mark_set_count;
23900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
24000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
24100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
24200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}  // namespace
24300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
24400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#define DROP_THIS_TABLE \
245a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org  do { file->gdef->data = 0; file->gdef->length = 0; } while (0)
24600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
24700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comnamespace ots {
24800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
24900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ots_gdef_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
25000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Grab the number of glyphs in the file from the maxp table to check
25100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // GlyphIDs in GDEF table.
25200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!file->maxp) {
25300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
25400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
25500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  const uint16_t num_glyphs = file->maxp->num_glyphs;
25600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
25700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  Buffer table(data, length);
25800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
25900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  OpenTypeGDEF *gdef = new OpenTypeGDEF;
26000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  file->gdef = gdef;
26100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
26200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint32_t version = 0;
26300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!table.ReadU32(&version)) {
26400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
26500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
26600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (version < 0x00010000 || version == 0x00010001) {
26700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad GDEF version");
26800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    DROP_THIS_TABLE;
26900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return true;
27000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
27100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
27200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (version >= 0x00010002) {
27300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    gdef->version_2 = true;
27400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
27500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
27600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t offset_glyph_class_def = 0;
27700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t offset_attach_list = 0;
27800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t offset_lig_caret_list = 0;
27900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t offset_mark_attach_class_def = 0;
28000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!table.ReadU16(&offset_glyph_class_def) ||
28100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      !table.ReadU16(&offset_attach_list) ||
28200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      !table.ReadU16(&offset_lig_caret_list) ||
28300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      !table.ReadU16(&offset_mark_attach_class_def)) {
28400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
28500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
28600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t offset_mark_glyph_sets_def = 0;
28700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (gdef->version_2) {
28800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!table.ReadU16(&offset_mark_glyph_sets_def)) {
28900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
29000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
29100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
29200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
293ced1463271677983367c47e131441ce27aa17440ksakamoto@chromium.org  unsigned gdef_header_end = 4 + 4 * 2;
294d668582b5057eaa91dfc12129eb79a3b24dcf884agl@chromium.org  if (gdef->version_2)
295d668582b5057eaa91dfc12129eb79a3b24dcf884agl@chromium.org    gdef_header_end += 2;
29678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
29700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Parse subtables
29800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (offset_glyph_class_def) {
29900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (offset_glyph_class_def >= length ||
30000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        offset_glyph_class_def < gdef_header_end) {
30100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
30200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
30300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!ParseGlyphClassDefTable(file, data + offset_glyph_class_def,
30400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                 length - offset_glyph_class_def,
30500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                 num_glyphs)) {
30600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      DROP_THIS_TABLE;
30700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return true;
30800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
309df5b76f08621c6589b4dde7f0b7177bab1bb297cbashi@chromium.org    gdef->has_glyph_class_def = true;
31000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
31100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
31200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (offset_attach_list) {
31300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (offset_attach_list >= length ||
31400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        offset_attach_list < gdef_header_end) {
31500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
31600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
31700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!ParseAttachListTable(file, data + offset_attach_list,
31800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                              length - offset_attach_list,
31900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                              num_glyphs)) {
32000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      DROP_THIS_TABLE;
32100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return true;
32200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
32300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
32400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
32500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (offset_lig_caret_list) {
32600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (offset_lig_caret_list >= length ||
32700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        offset_lig_caret_list < gdef_header_end) {
32800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
32900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
33000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!ParseLigCaretListTable(file, data + offset_lig_caret_list,
33100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                              length - offset_lig_caret_list,
33200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                              num_glyphs)) {
33300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      DROP_THIS_TABLE;
33400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return true;
33500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
33600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
33700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
33800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (offset_mark_attach_class_def) {
33900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (offset_mark_attach_class_def >= length ||
34000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        offset_mark_attach_class_def < gdef_header_end) {
34100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
34200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
34300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!ParseMarkAttachClassDefTable(file,
34400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                      data + offset_mark_attach_class_def,
34500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                      length - offset_mark_attach_class_def,
34600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                      num_glyphs)) {
34700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      DROP_THIS_TABLE;
34800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return true;
34900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
35078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    gdef->has_mark_attachment_class_def = true;
35100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
35200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
35300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (offset_mark_glyph_sets_def) {
35400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (offset_mark_glyph_sets_def >= length ||
35500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        offset_mark_glyph_sets_def < gdef_header_end) {
35600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
35700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
35800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!ParseMarkGlyphSetsDefTable(file,
35900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                    data + offset_mark_glyph_sets_def,
36000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                    length - offset_mark_glyph_sets_def,
36100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                    num_glyphs)) {
36200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      DROP_THIS_TABLE;
36300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return true;
36400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
36578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    gdef->has_mark_glyph_sets_def = true;
36600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
36700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  gdef->data = data;
36800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  gdef->length = length;
36900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
37000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
37100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
37200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ots_gdef_should_serialise(OpenTypeFile *file) {
373a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org  const bool needed_tables_dropped =
374a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      (file->gsub && file->gsub->data == NULL) ||
375a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      (file->gpos && file->gpos->data == NULL);
376a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org  return file->gdef != NULL && file->gdef->data != NULL &&
377a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      !needed_tables_dropped;
37800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
37900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
38000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ots_gdef_serialise(OTSStream *out, OpenTypeFile *file) {
38100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!out->Write(file->gdef->data, file->gdef->length)) {
38200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
38300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
38400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
38500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
38600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
38700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
38800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comvoid ots_gdef_free(OpenTypeFile *file) {
38900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  delete file->gdef;
39000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
39100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
39200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}  // namespace ots
39300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
394