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