blob: 311219bf7593e0b2877a52090bf4bf8b02416dbb [file] [log] [blame]
yusukes@chromium.orgd257d182009-11-04 04:56:32 +00001// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "gasp.h"
6
7// gasp - Grid-fitting And Scan-conversion Procedure
8// http://www.microsoft.com/opentype/otspec/gasp.htm
9
10#define DROP_THIS_TABLE \
11 do { delete file->gasp; file->gasp = 0; } while (0)
12
13namespace ots {
14
15bool ots_gasp_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
16 Buffer table(data, length);
17
18 OpenTypeGASP *gasp = new OpenTypeGASP;
19 file->gasp = gasp;
20
yusukes@chromium.org8ad0a172009-11-04 06:07:58 +000021 uint16_t num_ranges = 0;
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000022 if (!table.ReadU16(&gasp->version) ||
23 !table.ReadU16(&num_ranges)) {
24 return OTS_FAILURE();
25 }
26
27 if (gasp->version > 1) {
28 // Lots of Linux fonts have bad version numbers...
29 OTS_WARNING("bad version: %u", gasp->version);
30 DROP_THIS_TABLE;
31 return true;
32 }
33
34 if (num_ranges == 0) {
35 OTS_WARNING("num_ranges is zero");
36 DROP_THIS_TABLE;
37 return true;
38 }
39
40 gasp->gasp_ranges.reserve(num_ranges);
41 for (unsigned i = 0; i < num_ranges; ++i) {
yusukes@chromium.org8ad0a172009-11-04 06:07:58 +000042 uint16_t max_ppem = 0;
43 uint16_t behavior = 0;
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000044 if (!table.ReadU16(&max_ppem) ||
45 !table.ReadU16(&behavior)) {
46 return OTS_FAILURE();
47 }
48 if ((i > 0) && (gasp->gasp_ranges[i - 1].first >= max_ppem)) {
49 // The records in the gaspRange[] array must be sorted in order of
50 // increasing rangeMaxPPEM value.
51 OTS_WARNING("ranges are not sorted");
52 DROP_THIS_TABLE;
53 return true;
54 }
55 if ((i == num_ranges - 1u) && // never underflow.
56 (max_ppem != 0xffffu)) {
57 OTS_WARNING("The last record should be 0xFFFF as a sentinel value "
58 "for rangeMaxPPEM");
59 DROP_THIS_TABLE;
60 return true;
61 }
62
63 if (behavior >> 8) {
64 OTS_WARNING("undefined bits are used: %x", behavior);
65 // mask undefined bits.
66 behavior &= 0x000fu;
67 }
68
69 if (gasp->version == 0 && (behavior >> 2) != 0) {
70 OTS_WARNING("changed the version number to 1");
71 gasp->version = 1;
72 }
73
74 gasp->gasp_ranges.push_back(std::make_pair(max_ppem, behavior));
75 }
76
77 return true;
78}
79
80bool ots_gasp_should_serialise(OpenTypeFile *file) {
agl@chromium.org2beaf1d2011-01-21 17:19:34 +000081 return file->gasp != NULL;
yusukes@chromium.orgd257d182009-11-04 04:56:32 +000082}
83
84bool ots_gasp_serialise(OTSStream *out, OpenTypeFile *file) {
85 const OpenTypeGASP *gasp = file->gasp;
86
87 if (!out->WriteU16(gasp->version) ||
88 !out->WriteU16(gasp->gasp_ranges.size())) {
89 return OTS_FAILURE();
90 }
91
92 for (unsigned i = 0; i < gasp->gasp_ranges.size(); ++i) {
93 if (!out->WriteU16(gasp->gasp_ranges[i].first) ||
94 !out->WriteU16(gasp->gasp_ranges[i].second)) {
95 return OTS_FAILURE();
96 }
97 }
98
99 return true;
100}
101
102void ots_gasp_free(OpenTypeFile *file) {
103 delete file->gasp;
104}
105
106} // namespace ots