1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/ots/src/gasp.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,112 @@ 1.4 +// Copyright (c) 2009 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "gasp.h" 1.9 + 1.10 +// gasp - Grid-fitting And Scan-conversion Procedure 1.11 +// http://www.microsoft.com/typography/otspec/gasp.htm 1.12 + 1.13 +#define TABLE_NAME "gasp" 1.14 + 1.15 +#define DROP_THIS_TABLE \ 1.16 + do { \ 1.17 + delete file->gasp; \ 1.18 + file->gasp = 0; \ 1.19 + OTS_FAILURE_MSG("Table discarded"); \ 1.20 + } while (0) 1.21 + 1.22 +namespace ots { 1.23 + 1.24 +bool ots_gasp_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 1.25 + Buffer table(data, length); 1.26 + 1.27 + OpenTypeGASP *gasp = new OpenTypeGASP; 1.28 + file->gasp = gasp; 1.29 + 1.30 + uint16_t num_ranges = 0; 1.31 + if (!table.ReadU16(&gasp->version) || 1.32 + !table.ReadU16(&num_ranges)) { 1.33 + return OTS_FAILURE_MSG("Failed to read table header"); 1.34 + } 1.35 + 1.36 + if (gasp->version > 1) { 1.37 + // Lots of Linux fonts have bad version numbers... 1.38 + OTS_WARNING("bad version: %u", gasp->version); 1.39 + DROP_THIS_TABLE; 1.40 + return true; 1.41 + } 1.42 + 1.43 + if (num_ranges == 0) { 1.44 + OTS_WARNING("num_ranges is zero"); 1.45 + DROP_THIS_TABLE; 1.46 + return true; 1.47 + } 1.48 + 1.49 + gasp->gasp_ranges.reserve(num_ranges); 1.50 + for (unsigned i = 0; i < num_ranges; ++i) { 1.51 + uint16_t max_ppem = 0; 1.52 + uint16_t behavior = 0; 1.53 + if (!table.ReadU16(&max_ppem) || 1.54 + !table.ReadU16(&behavior)) { 1.55 + return OTS_FAILURE_MSG("Failed to read subrange %d", i); 1.56 + } 1.57 + if ((i > 0) && (gasp->gasp_ranges[i - 1].first >= max_ppem)) { 1.58 + // The records in the gaspRange[] array must be sorted in order of 1.59 + // increasing rangeMaxPPEM value. 1.60 + OTS_WARNING("ranges are not sorted"); 1.61 + DROP_THIS_TABLE; 1.62 + return true; 1.63 + } 1.64 + if ((i == num_ranges - 1u) && // never underflow. 1.65 + (max_ppem != 0xffffu)) { 1.66 + OTS_WARNING("The last record should be 0xFFFF as a sentinel value " 1.67 + "for rangeMaxPPEM"); 1.68 + DROP_THIS_TABLE; 1.69 + return true; 1.70 + } 1.71 + 1.72 + if (behavior >> 8) { 1.73 + OTS_WARNING("undefined bits are used: %x", behavior); 1.74 + // mask undefined bits. 1.75 + behavior &= 0x000fu; 1.76 + } 1.77 + 1.78 + if (gasp->version == 0 && (behavior >> 2) != 0) { 1.79 + OTS_WARNING("changed the version number to 1"); 1.80 + gasp->version = 1; 1.81 + } 1.82 + 1.83 + gasp->gasp_ranges.push_back(std::make_pair(max_ppem, behavior)); 1.84 + } 1.85 + 1.86 + return true; 1.87 +} 1.88 + 1.89 +bool ots_gasp_should_serialise(OpenTypeFile *file) { 1.90 + return file->gasp != NULL; 1.91 +} 1.92 + 1.93 +bool ots_gasp_serialise(OTSStream *out, OpenTypeFile *file) { 1.94 + const OpenTypeGASP *gasp = file->gasp; 1.95 + 1.96 + if (!out->WriteU16(gasp->version) || 1.97 + !out->WriteU16(gasp->gasp_ranges.size())) { 1.98 + return OTS_FAILURE_MSG("failed to write gasp header"); 1.99 + } 1.100 + 1.101 + for (unsigned i = 0; i < gasp->gasp_ranges.size(); ++i) { 1.102 + if (!out->WriteU16(gasp->gasp_ranges[i].first) || 1.103 + !out->WriteU16(gasp->gasp_ranges[i].second)) { 1.104 + return OTS_FAILURE_MSG("Failed to write gasp subtable %d", i); 1.105 + } 1.106 + } 1.107 + 1.108 + return true; 1.109 +} 1.110 + 1.111 +void ots_gasp_free(OpenTypeFile *file) { 1.112 + delete file->gasp; 1.113 +} 1.114 + 1.115 +} // namespace ots