Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: src/glyf.cc

Issue 658573004: Updating to new OTS repo from https://github.com/khaledhosny/ots.git (Closed) Base URL: https://chromium.googlesource.com/external/ots@master
Patch Set: Adding Colored Emoji changes from external/git repo Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« .gitmodules ('K') | « src/glyf.h ('k') | src/gpos.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "glyf.h" 5 #include "glyf.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "head.h" 10 #include "head.h"
11 #include "loca.h" 11 #include "loca.h"
12 #include "maxp.h" 12 #include "maxp.h"
13 13
14 // glyf - Glyph Data 14 // glyf - Glyph Data
15 // http://www.microsoft.com/opentype/otspec/glyf.htm 15 // http://www.microsoft.com/typography/otspec/glyf.htm
16
17 #define TABLE_NAME "glyf"
16 18
17 namespace { 19 namespace {
18 20
19 bool ParseFlagsForSimpleGlyph(ots::Buffer *table, 21 bool ParseFlagsForSimpleGlyph(ots::OpenTypeFile *file,
22 ots::Buffer *table,
20 uint32_t gly_length, 23 uint32_t gly_length,
21 uint32_t num_flags, 24 uint32_t num_flags,
22 uint32_t *flags_count_logical, 25 uint32_t *flags_count_logical,
23 uint32_t *flags_count_physical, 26 uint32_t *flags_count_physical,
24 uint32_t *xy_coordinates_length) { 27 uint32_t *xy_coordinates_length) {
25 uint8_t flag = 0; 28 uint8_t flag = 0;
26 if (!table->ReadU8(&flag)) { 29 if (!table->ReadU8(&flag)) {
27 return OTS_FAILURE(); 30 return OTS_FAILURE_MSG("Can't read flag");
28 } 31 }
29 32
30 uint32_t delta = 0; 33 uint32_t delta = 0;
31 if (flag & (1u << 1)) { // x-Short 34 if (flag & (1u << 1)) { // x-Short
32 ++delta; 35 ++delta;
33 } else if (!(flag & (1u << 4))) { 36 } else if (!(flag & (1u << 4))) {
34 delta += 2; 37 delta += 2;
35 } 38 }
36 39
37 if (flag & (1u << 2)) { // y-Short 40 if (flag & (1u << 2)) { // y-Short
38 ++delta; 41 ++delta;
39 } else if (!(flag & (1u << 5))) { 42 } else if (!(flag & (1u << 5))) {
40 delta += 2; 43 delta += 2;
41 } 44 }
42 45
43 if (flag & (1u << 3)) { // repeat 46 if (flag & (1u << 3)) { // repeat
44 if (*flags_count_logical + 1 >= num_flags) { 47 if (*flags_count_logical + 1 >= num_flags) {
45 return OTS_FAILURE(); 48 return OTS_FAILURE_MSG("Count too high (%d + 1 >= %d)", *flags_count_logic al, num_flags);
46 } 49 }
47 uint8_t repeat = 0; 50 uint8_t repeat = 0;
48 if (!table->ReadU8(&repeat)) { 51 if (!table->ReadU8(&repeat)) {
49 return OTS_FAILURE(); 52 return OTS_FAILURE_MSG("Can't read repeat value");
50 } 53 }
51 if (repeat == 0) { 54 if (repeat == 0) {
52 return OTS_FAILURE(); 55 return OTS_FAILURE_MSG("Zero repeat");
53 } 56 }
54 delta += (delta * repeat); 57 delta += (delta * repeat);
55 58
56 *flags_count_logical += repeat; 59 *flags_count_logical += repeat;
57 if (*flags_count_logical >= num_flags) { 60 if (*flags_count_logical >= num_flags) {
58 return OTS_FAILURE(); 61 return OTS_FAILURE_MSG("Count too high (%d >= %d)", *flags_count_logical, num_flags);
59 } 62 }
60 ++(*flags_count_physical); 63 ++(*flags_count_physical);
61 } 64 }
62 65
63 if ((flag & (1u << 6)) || (flag & (1u << 7))) { // reserved flags 66 if ((flag & (1u << 6)) || (flag & (1u << 7))) { // reserved flags
64 return OTS_FAILURE(); 67 return OTS_FAILURE_MSG("Bad flag value (%d)", flag);
65 } 68 }
66 69
67 *xy_coordinates_length += delta; 70 *xy_coordinates_length += delta;
68 if (gly_length < *xy_coordinates_length) { 71 if (gly_length < *xy_coordinates_length) {
69 return OTS_FAILURE(); 72 return OTS_FAILURE_MSG("Glyph coordinates length too low (%d < %d)", gly_len gth, *xy_coordinates_length);
70 } 73 }
71 74
72 return true; 75 return true;
73 } 76 }
74 77
75 bool ParseSimpleGlyph(ots::OpenTypeFile *file, const uint8_t *data, 78 bool ParseSimpleGlyph(ots::OpenTypeFile *file, const uint8_t *data,
76 ots::Buffer *table, int16_t num_contours, 79 ots::Buffer *table, int16_t num_contours,
77 uint32_t gly_offset, uint32_t gly_length, 80 uint32_t gly_offset, uint32_t gly_length,
78 uint32_t *new_size) { 81 uint32_t *new_size) {
79 ots::OpenTypeGLYF *glyf = file->glyf; 82 ots::OpenTypeGLYF *glyf = file->glyf;
80 83
81 // read the end-points array 84 // read the end-points array
82 uint16_t num_flags = 0; 85 uint16_t num_flags = 0;
83 for (int i = 0; i < num_contours; ++i) { 86 for (int i = 0; i < num_contours; ++i) {
84 uint16_t tmp_index = 0; 87 uint16_t tmp_index = 0;
85 if (!table->ReadU16(&tmp_index)) { 88 if (!table->ReadU16(&tmp_index)) {
86 return OTS_FAILURE(); 89 return OTS_FAILURE_MSG("Can't read contour index %d", i);
87 } 90 }
88 if (tmp_index == 0xffffu) { 91 if (tmp_index == 0xffffu) {
89 return OTS_FAILURE(); 92 return OTS_FAILURE_MSG("Bad contour index %d", i);
90 } 93 }
91 // check if the indices are monotonically increasing 94 // check if the indices are monotonically increasing
92 if (i && (tmp_index + 1 <= num_flags)) { 95 if (i && (tmp_index + 1 <= num_flags)) {
93 return OTS_FAILURE(); 96 return OTS_FAILURE_MSG("Decreasing contour index %d + 1 <= %d", tmp_index, num_flags);
94 } 97 }
95 num_flags = tmp_index + 1; 98 num_flags = tmp_index + 1;
96 } 99 }
97 100
98 uint16_t bytecode_length = 0; 101 uint16_t bytecode_length = 0;
99 if (!table->ReadU16(&bytecode_length)) { 102 if (!table->ReadU16(&bytecode_length)) {
100 return OTS_FAILURE(); 103 return OTS_FAILURE_MSG("Can't read bytecode length");
101 } 104 }
102 if ((file->maxp->version_1) && 105 if ((file->maxp->version_1) &&
103 (file->maxp->max_size_glyf_instructions < bytecode_length)) { 106 (file->maxp->max_size_glyf_instructions < bytecode_length)) {
104 return OTS_FAILURE(); 107 return OTS_FAILURE_MSG("Bytecode length too high %d", bytecode_length);
105 } 108 }
106 109
107 const uint32_t gly_header_length = 10 + num_contours * 2 + 2; 110 const uint32_t gly_header_length = 10 + num_contours * 2 + 2;
108 if (gly_length < (gly_header_length + bytecode_length)) { 111 if (gly_length < (gly_header_length + bytecode_length)) {
109 return OTS_FAILURE(); 112 return OTS_FAILURE_MSG("Glyph header length too high %d", gly_header_length) ;
110 } 113 }
111 114
112 if (ots::g_transcode_hints) { 115 glyf->iov.push_back(std::make_pair(
113 glyf->iov.push_back(std::make_pair( 116 data + gly_offset,
114 data + gly_offset, 117 static_cast<size_t>(gly_header_length + bytecode_length)));
115 static_cast<size_t>(gly_header_length + bytecode_length)));
116 } else {
117 // enqueue two vectors: the glyph data up to the bytecode length, then
118 // a pointer to a static uint16_t 0 to overwrite the length.
119 glyf->iov.push_back(std::make_pair(
120 data + gly_offset,
121 static_cast<size_t>(gly_header_length - 2)));
122 glyf->iov.push_back(std::make_pair((const uint8_t*) "\x00\x00",
123 static_cast<size_t>(2)));
124 }
125 118
126 if (!table->Skip(bytecode_length)) { 119 if (!table->Skip(bytecode_length)) {
127 return OTS_FAILURE(); 120 return OTS_FAILURE_MSG("Can't skip bytecode of length %d", bytecode_length);
128 } 121 }
129 122
130 uint32_t flags_count_physical = 0; // on memory 123 uint32_t flags_count_physical = 0; // on memory
131 uint32_t xy_coordinates_length = 0; 124 uint32_t xy_coordinates_length = 0;
132 for (uint32_t flags_count_logical = 0; 125 for (uint32_t flags_count_logical = 0;
133 flags_count_logical < num_flags; 126 flags_count_logical < num_flags;
134 ++flags_count_logical, ++flags_count_physical) { 127 ++flags_count_logical, ++flags_count_physical) {
135 if (!ParseFlagsForSimpleGlyph(table, 128 if (!ParseFlagsForSimpleGlyph(file,
129 table,
136 gly_length, 130 gly_length,
137 num_flags, 131 num_flags,
138 &flags_count_logical, 132 &flags_count_logical,
139 &flags_count_physical, 133 &flags_count_physical,
140 &xy_coordinates_length)) { 134 &xy_coordinates_length)) {
141 return OTS_FAILURE(); 135 return OTS_FAILURE_MSG("Failed to parse glyph flags %d", flags_count_logic al);
142 } 136 }
143 } 137 }
144 138
145 if (gly_length < (gly_header_length + bytecode_length + 139 if (gly_length < (gly_header_length + bytecode_length +
146 flags_count_physical + xy_coordinates_length)) { 140 flags_count_physical + xy_coordinates_length)) {
147 return OTS_FAILURE(); 141 return OTS_FAILURE_MSG("Glyph too short %d", gly_length);
148 } 142 }
149 143
150 if (gly_length - (gly_header_length + bytecode_length + 144 if (gly_length - (gly_header_length + bytecode_length +
151 flags_count_physical + xy_coordinates_length) > 3) { 145 flags_count_physical + xy_coordinates_length) > 3) {
152 // We allow 0-3 bytes difference since gly_length is 4-bytes aligned, 146 // We allow 0-3 bytes difference since gly_length is 4-bytes aligned,
153 // zero-padded length. 147 // zero-padded length.
154 return OTS_FAILURE(); 148 return OTS_FAILURE_MSG("Invalid glyph length %d", gly_length);
155 } 149 }
156 150
157 glyf->iov.push_back(std::make_pair( 151 glyf->iov.push_back(std::make_pair(
158 data + gly_offset + gly_header_length + bytecode_length, 152 data + gly_offset + gly_header_length + bytecode_length,
159 static_cast<size_t>(flags_count_physical + xy_coordinates_length))); 153 static_cast<size_t>(flags_count_physical + xy_coordinates_length)));
160 154
161 *new_size 155 *new_size
162 = gly_header_length + flags_count_physical + xy_coordinates_length; 156 = gly_header_length + flags_count_physical + xy_coordinates_length + bytec ode_length;
163 if (ots::g_transcode_hints) {
164 *new_size += bytecode_length;
165 }
166 157
167 return true; 158 return true;
168 } 159 }
169 160
170 } // namespace 161 } // namespace
171 162
172 namespace ots { 163 namespace ots {
173 164
174 bool ots_glyf_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 165 bool ots_glyf_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
175 Buffer table(data, length); 166 Buffer table(data, length);
176 167
177 if (!file->maxp || !file->loca || !file->head) { 168 if (!file->maxp || !file->loca || !file->head) {
178 return OTS_FAILURE(); 169 return OTS_FAILURE_MSG("Missing maxp or loca or head table needed by glyf ta ble");
179 } 170 }
180 171
181 OpenTypeGLYF *glyf = new OpenTypeGLYF; 172 OpenTypeGLYF *glyf = new OpenTypeGLYF;
182 file->glyf = glyf; 173 file->glyf = glyf;
183 174
184 const unsigned num_glyphs = file->maxp->num_glyphs; 175 const unsigned num_glyphs = file->maxp->num_glyphs;
185 std::vector<uint32_t> &offsets = file->loca->offsets; 176 std::vector<uint32_t> &offsets = file->loca->offsets;
186 177
187 if (offsets.size() != num_glyphs + 1) { 178 if (offsets.size() != num_glyphs + 1) {
188 return OTS_FAILURE(); 179 return OTS_FAILURE_MSG("Invalide glyph offsets size %ld != %d", offsets.size (), num_glyphs + 1);
189 } 180 }
190 181
191 std::vector<uint32_t> resulting_offsets(num_glyphs + 1); 182 std::vector<uint32_t> resulting_offsets(num_glyphs + 1);
192 uint32_t current_offset = 0; 183 uint32_t current_offset = 0;
193 184
194 for (unsigned i = 0; i < num_glyphs; ++i) { 185 for (unsigned i = 0; i < num_glyphs; ++i) {
195 const unsigned gly_offset = offsets[i]; 186 const unsigned gly_offset = offsets[i];
196 // The LOCA parser checks that these values are monotonic 187 // The LOCA parser checks that these values are monotonic
197 const unsigned gly_length = offsets[i + 1] - offsets[i]; 188 const unsigned gly_length = offsets[i + 1] - offsets[i];
198 if (!gly_length) { 189 if (!gly_length) {
199 // this glyph has no outline (e.g. the space charactor) 190 // this glyph has no outline (e.g. the space charactor)
200 resulting_offsets[i] = current_offset; 191 resulting_offsets[i] = current_offset;
201 continue; 192 continue;
202 } 193 }
203 194
204 if (gly_offset >= length) { 195 if (gly_offset >= length) {
205 return OTS_FAILURE(); 196 return OTS_FAILURE_MSG("Glyph %d offset %d too high %ld", i, gly_offset, l ength);
206 } 197 }
207 // Since these are unsigned types, the compiler is not allowed to assume 198 // Since these are unsigned types, the compiler is not allowed to assume
208 // that they never overflow. 199 // that they never overflow.
209 if (gly_offset + gly_length < gly_offset) { 200 if (gly_offset + gly_length < gly_offset) {
210 return OTS_FAILURE(); 201 return OTS_FAILURE_MSG("Glyph %d length (%d < 0)!", i, gly_length);
211 } 202 }
212 if (gly_offset + gly_length > length) { 203 if (gly_offset + gly_length > length) {
213 return OTS_FAILURE(); 204 return OTS_FAILURE_MSG("Glyph %d length %d too high", i, gly_length);
214 } 205 }
215 206
216 table.set_offset(gly_offset); 207 table.set_offset(gly_offset);
217 int16_t num_contours, xmin, ymin, xmax, ymax; 208 int16_t num_contours, xmin, ymin, xmax, ymax;
218 if (!table.ReadS16(&num_contours) || 209 if (!table.ReadS16(&num_contours) ||
219 !table.ReadS16(&xmin) || 210 !table.ReadS16(&xmin) ||
220 !table.ReadS16(&ymin) || 211 !table.ReadS16(&ymin) ||
221 !table.ReadS16(&xmax) || 212 !table.ReadS16(&xmax) ||
222 !table.ReadS16(&ymax)) { 213 !table.ReadS16(&ymax)) {
223 return OTS_FAILURE(); 214 return OTS_FAILURE_MSG("Can't read glyph %d header", i);
224 } 215 }
225 216
226 if (num_contours <= -2) { 217 if (num_contours <= -2) {
227 // -2, -3, -4, ... are reserved for future use. 218 // -2, -3, -4, ... are reserved for future use.
228 return OTS_FAILURE(); 219 return OTS_FAILURE_MSG("Bad number of contours %d in glyph %d", num_contou rs, i);
229 } 220 }
230 221
231 // workaround for fonts in http://www.princexml.com/fonts/ 222 // workaround for fonts in http://www.princexml.com/fonts/
232 if ((xmin == 32767) && 223 if ((xmin == 32767) &&
233 (xmax == -32767) && 224 (xmax == -32767) &&
234 (ymin == 32767) && 225 (ymin == 32767) &&
235 (ymax == -32767)) { 226 (ymax == -32767)) {
236 OTS_WARNING("bad xmin/xmax/ymin/ymax values"); 227 OTS_WARNING("bad xmin/xmax/ymin/ymax values");
237 xmin = xmax = ymin = ymax = 0; 228 xmin = xmax = ymin = ymax = 0;
238 } 229 }
239 230
240 if (xmin > xmax || ymin > ymax) { 231 if (xmin > xmax || ymin > ymax) {
241 return OTS_FAILURE(); 232 return OTS_FAILURE_MSG("Bad bounding box values bl=(%d, %d), tr=(%d, %d) i n glyph %d", xmin, ymin, xmax, ymax, i);
242 } 233 }
243 234
244 unsigned new_size = 0; 235 unsigned new_size = 0;
245 if (num_contours >= 0) { 236 if (num_contours >= 0) {
246 // this is a simple glyph and might contain bytecode 237 // this is a simple glyph and might contain bytecode
247 if (!ParseSimpleGlyph(file, data, &table, 238 if (!ParseSimpleGlyph(file, data, &table,
248 num_contours, gly_offset, gly_length, &new_size)) { 239 num_contours, gly_offset, gly_length, &new_size)) {
249 return OTS_FAILURE(); 240 return OTS_FAILURE_MSG("Failed to parse glyph %d", i);
250 } 241 }
251 } else { 242 } else {
252 // it's a composite glyph without any bytecode. Enqueue the whole thing 243 // it's a composite glyph without any bytecode. Enqueue the whole thing
253 glyf->iov.push_back(std::make_pair(data + gly_offset, 244 glyf->iov.push_back(std::make_pair(data + gly_offset,
254 static_cast<size_t>(gly_length))); 245 static_cast<size_t>(gly_length)));
255 new_size = gly_length; 246 new_size = gly_length;
256 } 247 }
257 248
258 resulting_offsets[i] = current_offset; 249 resulting_offsets[i] = current_offset;
259 // glyphs must be four byte aligned 250 // glyphs must be four byte aligned
(...skipping 24 matching lines...) Expand all
284 275
285 bool ots_glyf_should_serialise(OpenTypeFile *file) { 276 bool ots_glyf_should_serialise(OpenTypeFile *file) {
286 return file->glyf != NULL; 277 return file->glyf != NULL;
287 } 278 }
288 279
289 bool ots_glyf_serialise(OTSStream *out, OpenTypeFile *file) { 280 bool ots_glyf_serialise(OTSStream *out, OpenTypeFile *file) {
290 const OpenTypeGLYF *glyf = file->glyf; 281 const OpenTypeGLYF *glyf = file->glyf;
291 282
292 for (unsigned i = 0; i < glyf->iov.size(); ++i) { 283 for (unsigned i = 0; i < glyf->iov.size(); ++i) {
293 if (!out->Write(glyf->iov[i].first, glyf->iov[i].second)) { 284 if (!out->Write(glyf->iov[i].first, glyf->iov[i].second)) {
294 return OTS_FAILURE(); 285 return OTS_FAILURE_MSG("Falied to write glyph %d", i);
295 } 286 }
296 } 287 }
297 288
298 return true; 289 return true;
299 } 290 }
300 291
301 void ots_glyf_free(OpenTypeFile *file) { 292 void ots_glyf_free(OpenTypeFile *file) {
302 delete file->glyf; 293 delete file->glyf;
303 } 294 }
304 295
305 } // namespace ots 296 } // namespace ots
297
298 #undef TABLE_NAME
OLDNEW
« .gitmodules ('K') | « src/glyf.h ('k') | src/gpos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698