1d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Use of this source code is governed by a BSD-style license that can be 3d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// found in the LICENSE file. 4d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 5d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include "glyf.h" 6d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 7d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <algorithm> 8d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include <limits> 9d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 10d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include "head.h" 11d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include "loca.h" 12d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#include "maxp.h" 13d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 14d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// glyf - Glyph Data 15d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// http://www.microsoft.com/opentype/otspec/glyf.htm 16d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 17a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.orgnamespace { 18a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 19a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.orgbool ParseFlagsForSimpleGlyph(ots::Buffer *table, 20a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t gly_length, 21a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t num_flags, 22a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t *flags_count_logical, 23a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t *flags_count_physical, 24a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t *xy_coordinates_length) { 25a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint8_t flag = 0; 26a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (!table->ReadU8(&flag)) { 27a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 28a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 29a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 30a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t delta = 0; 31a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (flag & (1u << 1)) { // x-Short 32a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org ++delta; 33a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } else if (!(flag & (1u << 4))) { 34a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org delta += 2; 35a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 36a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 37a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (flag & (1u << 2)) { // y-Short 38a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org ++delta; 39a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } else if (!(flag & (1u << 5))) { 40a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org delta += 2; 41a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 42a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 43a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (flag & (1u << 3)) { // repeat 44a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (*flags_count_logical + 1 >= num_flags) { 45a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 46a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 47a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint8_t repeat = 0; 48a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (!table->ReadU8(&repeat)) { 49a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 50a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 51a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (repeat == 0) { 52a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 53a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 54a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org delta += (delta * repeat); 55a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 56a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org *flags_count_logical += repeat; 57a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (*flags_count_logical >= num_flags) { 58a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 59a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 60a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org ++(*flags_count_physical); 61a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 62a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 63a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if ((flag & (1u << 6)) || (flag & (1u << 7))) { // reserved flags 64a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 65a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 66a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 67a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org *xy_coordinates_length += delta; 68a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (gly_length < *xy_coordinates_length) { 69a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 70a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 71a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 72a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return true; 73a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org} 74a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 75a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.orgbool ParseSimpleGlyph(ots::OpenTypeFile *file, const uint8_t *data, 76a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org ots::Buffer *table, int16_t num_contours, 77a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t gly_offset, uint32_t gly_length, 78a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t *new_size) { 79a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org ots::OpenTypeGLYF *glyf = file->glyf; 80a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 81a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org // read the end-points array 82a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint16_t num_flags = 0; 83a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org for (int i = 0; i < num_contours; ++i) { 84a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint16_t tmp_index = 0; 85a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (!table->ReadU16(&tmp_index)) { 86a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 87a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 88a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (tmp_index == 0xffffu) { 89a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 90a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 91a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org // check if the indices are monotonically increasing 92a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (i && (tmp_index + 1 <= num_flags)) { 93a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 94a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 95a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org num_flags = tmp_index + 1; 96a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 97a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 98a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint16_t bytecode_length = 0; 99a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (!table->ReadU16(&bytecode_length)) { 100a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 101a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 102a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if ((file->maxp->version_1) && 103a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org (file->maxp->max_size_glyf_instructions < bytecode_length)) { 104a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 105a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 106a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 107a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org const uint32_t gly_header_length = 10 + num_contours * 2 + 2; 108a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (gly_length < (gly_header_length + bytecode_length)) { 109a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 110a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 111a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 112a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (ots::g_transcode_hints) { 113a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org glyf->iov.push_back(std::make_pair( 11479602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org data + gly_offset, 11579602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org static_cast<size_t>(gly_header_length + bytecode_length))); 116a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } else { 117a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org // enqueue two vectors: the glyph data up to the bytecode length, then 118a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org // a pointer to a static uint16_t 0 to overwrite the length. 119a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org glyf->iov.push_back(std::make_pair( 12079602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org data + gly_offset, 12179602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org static_cast<size_t>(gly_header_length - 2))); 12279602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org glyf->iov.push_back(std::make_pair((const uint8_t*) "\x00\x00", 12379602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org static_cast<size_t>(2))); 124a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 125a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 126a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (!table->Skip(bytecode_length)) { 127a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 128a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 129a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 130a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t flags_count_physical = 0; // on memory 131a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org uint32_t xy_coordinates_length = 0; 132a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org for (uint32_t flags_count_logical = 0; 133a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org flags_count_logical < num_flags; 134a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org ++flags_count_logical, ++flags_count_physical) { 135a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (!ParseFlagsForSimpleGlyph(table, 136a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org gly_length, 137a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org num_flags, 138a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org &flags_count_logical, 139a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org &flags_count_physical, 140a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org &xy_coordinates_length)) { 141a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 142a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 143a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 144a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 145a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (gly_length < (gly_header_length + bytecode_length + 146a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org flags_count_physical + xy_coordinates_length)) { 147a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 148a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 149a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 150a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (gly_length - (gly_header_length + bytecode_length + 151a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org flags_count_physical + xy_coordinates_length) > 3) { 152a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org // We allow 0-3 bytes difference since gly_length is 4-bytes aligned, 153a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org // zero-padded length. 154a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return OTS_FAILURE(); 155a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 156a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 157a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org glyf->iov.push_back(std::make_pair( 158a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org data + gly_offset + gly_header_length + bytecode_length, 15979602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org static_cast<size_t>(flags_count_physical + xy_coordinates_length))); 160a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 161a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org *new_size 162a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org = gly_header_length + flags_count_physical + xy_coordinates_length; 163a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (ots::g_transcode_hints) { 164a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org *new_size += bytecode_length; 165a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 166a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 167a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org return true; 168a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org} 169a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 170a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org} // namespace 171a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org 172d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgnamespace ots { 173d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 174d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_glyf_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 175d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org Buffer table(data, length); 176d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 177d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (!file->maxp || !file->loca || !file->head) { 178d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 179d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 180d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 181d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OpenTypeGLYF *glyf = new OpenTypeGLYF; 182d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org file->glyf = glyf; 183d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 184d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org const unsigned num_glyphs = file->maxp->num_glyphs; 185d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org std::vector<uint32_t> &offsets = file->loca->offsets; 186d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 187d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (offsets.size() != num_glyphs + 1) { 188d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 189d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 190d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 191d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org std::vector<uint32_t> resulting_offsets(num_glyphs + 1); 192d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org uint32_t current_offset = 0; 193d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 194d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org for (unsigned i = 0; i < num_glyphs; ++i) { 195d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org const unsigned gly_offset = offsets[i]; 196d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // The LOCA parser checks that these values are monotonic 197d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org const unsigned gly_length = offsets[i + 1] - offsets[i]; 198d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (!gly_length) { 199d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // this glyph has no outline (e.g. the space charactor) 200d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org resulting_offsets[i] = current_offset; 201d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org continue; 202d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 203d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 204d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (gly_offset >= length) { 205d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 206d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 207d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // Since these are unsigned types, the compiler is not allowed to assume 208d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // that they never overflow. 209d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (gly_offset + gly_length < gly_offset) { 210d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 211d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 212d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (gly_offset + gly_length > length) { 213d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 214d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 215d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 216d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org table.set_offset(gly_offset); 217d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org int16_t num_contours, xmin, ymin, xmax, ymax; 218d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (!table.ReadS16(&num_contours) || 219d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org !table.ReadS16(&xmin) || 220d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org !table.ReadS16(&ymin) || 221d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org !table.ReadS16(&xmax) || 222d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org !table.ReadS16(&ymax)) { 223d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 224d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 225d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 226a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (num_contours <= -2) { 227d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // -2, -3, -4, ... are reserved for future use. 228d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 229d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 230d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 231d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // workaround for fonts in http://www.princexml.com/fonts/ 232d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if ((xmin == 32767) && 233d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org (xmax == -32767) && 234d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org (ymin == 32767) && 235d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org (ymax == -32767)) { 236d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OTS_WARNING("bad xmin/xmax/ymin/ymax values"); 237d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org xmin = xmax = ymin = ymax = 0; 238d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 239d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 240d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (xmin > xmax || ymin > ymax) { 241d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 242d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 243d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 244d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org unsigned new_size = 0; 245d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (num_contours >= 0) { 246d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // this is a simple glyph and might contain bytecode 247a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (!ParseSimpleGlyph(file, data, &table, 248a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org num_contours, gly_offset, gly_length, &new_size)) { 249d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 250d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 251d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } else { 252d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // it's a composite glyph without any bytecode. Enqueue the whole thing 25379602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org glyf->iov.push_back(std::make_pair(data + gly_offset, 25479602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org static_cast<size_t>(gly_length))); 255d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org new_size = gly_length; 256d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 257d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 258d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org resulting_offsets[i] = current_offset; 259d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // glyphs must be four byte aligned 260d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // TODO(yusukes): investigate whether this padding is really necessary. 261d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // Which part of the spec requires this? 262d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org const unsigned padding = (4 - (new_size & 3)) % 4; 263d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (padding) { 264d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org glyf->iov.push_back(std::make_pair( 26579602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org reinterpret_cast<const uint8_t*>("\x00\x00\x00\x00"), 26679602bdcdcb2ada735c795fe058fc335d392397fbashi@chromium.org static_cast<size_t>(padding))); 267d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org new_size += padding; 268d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 269d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org current_offset += new_size; 270d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 271d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org resulting_offsets[num_glyphs] = current_offset; 272d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 273d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org const uint16_t max16 = std::numeric_limits<uint16_t>::max(); 274d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if ((*std::max_element(resulting_offsets.begin(), 275d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org resulting_offsets.end()) >= (max16 * 2u)) && 276d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org (file->head->index_to_loc_format != 1)) { 277d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OTS_WARNING("2-bytes indexing is not possible (due to the padding above)"); 278d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org file->head->index_to_loc_format = 1; 279d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 280d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 281d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org file->loca->offsets = resulting_offsets; 282d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return true; 283d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} 284d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 285d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_glyf_should_serialise(OpenTypeFile *file) { 2862beaf1d97c4ba6d953462003db9ddb104b53d196agl@chromium.org return file->glyf != NULL; 287d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} 288d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 289d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_glyf_serialise(OTSStream *out, OpenTypeFile *file) { 290d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org const OpenTypeGLYF *glyf = file->glyf; 291d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 292d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org for (unsigned i = 0; i < glyf->iov.size(); ++i) { 293d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (!out->Write(glyf->iov[i].first, glyf->iov[i].second)) { 294d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 295d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 296d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 297d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 298d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return true; 299d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} 300d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 301d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgvoid ots_glyf_free(OpenTypeFile *file) { 302d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org delete file->glyf; 303d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} 304d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 305d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} // namespace ots 306