• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
13 namespace ots {
14 
ots_gasp_parse(OpenTypeFile * file,const uint8_t * data,size_t length)15 bool 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 
21   uint16_t num_ranges = 0;
22   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) {
42     uint16_t max_ppem = 0;
43     uint16_t behavior = 0;
44     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 
ots_gasp_should_serialise(OpenTypeFile * file)80 bool ots_gasp_should_serialise(OpenTypeFile *file) {
81   return file->gasp != NULL;
82 }
83 
ots_gasp_serialise(OTSStream * out,OpenTypeFile * file)84 bool 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 
ots_gasp_free(OpenTypeFile * file)102 void ots_gasp_free(OpenTypeFile *file) {
103   delete file->gasp;
104 }
105 
106 }  // namespace ots
107