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 "gasp.h" 6d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 7d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// gasp - Grid-fitting And Scan-conversion Procedure 8d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// http://www.microsoft.com/opentype/otspec/gasp.htm 9d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 10d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org#define DROP_THIS_TABLE \ 11d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org do { delete file->gasp; file->gasp = 0; } while (0) 12d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 13d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgnamespace ots { 14d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 15d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_gasp_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 16d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org Buffer table(data, length); 17d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 18d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OpenTypeGASP *gasp = new OpenTypeGASP; 19d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org file->gasp = gasp; 20d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 218ad0a175fe440054932dd25ae9b4b1867e66d387yusukes@chromium.org uint16_t num_ranges = 0; 22d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (!table.ReadU16(&gasp->version) || 23d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org !table.ReadU16(&num_ranges)) { 24d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 25d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 26d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 27d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (gasp->version > 1) { 28d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // Lots of Linux fonts have bad version numbers... 29d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OTS_WARNING("bad version: %u", gasp->version); 30d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org DROP_THIS_TABLE; 31d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return true; 32d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 33d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 34d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (num_ranges == 0) { 35d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OTS_WARNING("num_ranges is zero"); 36d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org DROP_THIS_TABLE; 37d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return true; 38d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 39d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 40d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org gasp->gasp_ranges.reserve(num_ranges); 41d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org for (unsigned i = 0; i < num_ranges; ++i) { 428ad0a175fe440054932dd25ae9b4b1867e66d387yusukes@chromium.org uint16_t max_ppem = 0; 438ad0a175fe440054932dd25ae9b4b1867e66d387yusukes@chromium.org uint16_t behavior = 0; 44d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (!table.ReadU16(&max_ppem) || 45d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org !table.ReadU16(&behavior)) { 46d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 47d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 48d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if ((i > 0) && (gasp->gasp_ranges[i - 1].first >= max_ppem)) { 49d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // The records in the gaspRange[] array must be sorted in order of 50d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // increasing rangeMaxPPEM value. 51d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OTS_WARNING("ranges are not sorted"); 52d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org DROP_THIS_TABLE; 53d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return true; 54d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 55d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if ((i == num_ranges - 1u) && // never underflow. 56d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org (max_ppem != 0xffffu)) { 57d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OTS_WARNING("The last record should be 0xFFFF as a sentinel value " 58d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org "for rangeMaxPPEM"); 59d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org DROP_THIS_TABLE; 60d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return true; 61d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 62d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 63d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (behavior >> 8) { 64d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OTS_WARNING("undefined bits are used: %x", behavior); 65d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org // mask undefined bits. 66d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org behavior &= 0x000fu; 67d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 68d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 69d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (gasp->version == 0 && (behavior >> 2) != 0) { 70d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org OTS_WARNING("changed the version number to 1"); 71d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org gasp->version = 1; 72d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 73d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 74d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org gasp->gasp_ranges.push_back(std::make_pair(max_ppem, behavior)); 75d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 76d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 77d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return true; 78d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} 79d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 80d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_gasp_should_serialise(OpenTypeFile *file) { 812beaf1d97c4ba6d953462003db9ddb104b53d196agl@chromium.org return file->gasp != NULL; 82d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} 83d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 84d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgbool ots_gasp_serialise(OTSStream *out, OpenTypeFile *file) { 85d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org const OpenTypeGASP *gasp = file->gasp; 86d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 87d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (!out->WriteU16(gasp->version) || 88d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org !out->WriteU16(gasp->gasp_ranges.size())) { 89d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 90d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 91d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 92d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org for (unsigned i = 0; i < gasp->gasp_ranges.size(); ++i) { 93d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (!out->WriteU16(gasp->gasp_ranges[i].first) || 94d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org !out->WriteU16(gasp->gasp_ranges[i].second)) { 95d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return OTS_FAILURE(); 96d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 97d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 98d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 99d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org return true; 100d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} 101d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 102d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.orgvoid ots_gasp_free(OpenTypeFile *file) { 103d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org delete file->gasp; 104d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} 105d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 106d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org} // namespace ots 107