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

Side by Side Diff: src/cmap.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
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 "cmap.h" 5 #include "cmap.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "maxp.h" 12 #include "maxp.h"
13 #include "os2.h" 13 #include "os2.h"
14 14
15 // cmap - Character To Glyph Index Mapping Table 15 // cmap - Character To Glyph Index Mapping Table
16 // http://www.microsoft.com/opentype/otspec/cmap.htm 16 // http://www.microsoft.com/typography/otspec/cmap.htm
17
18 #define TABLE_NAME "cmap"
17 19
18 namespace { 20 namespace {
19 21
20 struct CMAPSubtableHeader { 22 struct CMAPSubtableHeader {
21 uint16_t platform; 23 uint16_t platform;
22 uint16_t encoding; 24 uint16_t encoding;
23 uint32_t offset; 25 uint32_t offset;
24 uint16_t format; 26 uint16_t format;
25 uint32_t length; 27 uint32_t length;
28 uint32_t language;
26 }; 29 };
27 30
28 struct Subtable314Range { 31 struct Subtable314Range {
29 uint16_t start_range; 32 uint16_t start_range;
30 uint16_t end_range; 33 uint16_t end_range;
31 int16_t id_delta; 34 int16_t id_delta;
32 uint16_t id_range_offset; 35 uint16_t id_range_offset;
33 uint32_t id_range_offset_offset; 36 uint32_t id_range_offset_offset;
34 }; 37 };
35 38
(...skipping 24 matching lines...) Expand all
60 // Parses Format 4 tables 63 // Parses Format 4 tables
61 bool ParseFormat4(ots::OpenTypeFile *file, int platform, int encoding, 64 bool ParseFormat4(ots::OpenTypeFile *file, int platform, int encoding,
62 const uint8_t *data, size_t length, uint16_t num_glyphs) { 65 const uint8_t *data, size_t length, uint16_t num_glyphs) {
63 ots::Buffer subtable(data, length); 66 ots::Buffer subtable(data, length);
64 67
65 // 0.3.4, 3.0.4 or 3.1.4 subtables are complex and, rather than expanding the 68 // 0.3.4, 3.0.4 or 3.1.4 subtables are complex and, rather than expanding the
66 // whole thing and recompacting it, we validate it and include it verbatim 69 // whole thing and recompacting it, we validate it and include it verbatim
67 // in the output. 70 // in the output.
68 71
69 if (!file->os2) { 72 if (!file->os2) {
70 return OTS_FAILURE(); 73 return OTS_FAILURE_MSG("Required OS/2 table missing");
71 } 74 }
72 75
73 if (!subtable.Skip(4)) { 76 if (!subtable.Skip(4)) {
74 return OTS_FAILURE(); 77 return OTS_FAILURE_MSG("Can't read 4 bytes at start of cmap format 4 subtabl e");
75 } 78 }
76 uint16_t language = 0; 79 uint16_t language = 0;
77 if (!subtable.ReadU16(&language)) { 80 if (!subtable.ReadU16(&language)) {
78 return OTS_FAILURE(); 81 return OTS_FAILURE_MSG("Can't read language");
79 } 82 }
80 if (language) { 83 if (language) {
81 // Platform ID 3 (windows) subtables should have language '0'. 84 // Platform ID 3 (windows) subtables should have language '0'.
82 return OTS_FAILURE(); 85 return OTS_FAILURE_MSG("Languages should be 0 (%d)", language);
83 } 86 }
84 87
85 uint16_t segcountx2, search_range, entry_selector, range_shift; 88 uint16_t segcountx2, search_range, entry_selector, range_shift;
86 segcountx2 = search_range = entry_selector = range_shift = 0; 89 segcountx2 = search_range = entry_selector = range_shift = 0;
87 if (!subtable.ReadU16(&segcountx2) || 90 if (!subtable.ReadU16(&segcountx2) ||
88 !subtable.ReadU16(&search_range) || 91 !subtable.ReadU16(&search_range) ||
89 !subtable.ReadU16(&entry_selector) || 92 !subtable.ReadU16(&entry_selector) ||
90 !subtable.ReadU16(&range_shift)) { 93 !subtable.ReadU16(&range_shift)) {
91 return OTS_FAILURE(); 94 return OTS_FAILURE_MSG("Failed to read subcmap structure");
92 } 95 }
93 96
94 if (segcountx2 & 1 || search_range & 1) { 97 if (segcountx2 & 1 || search_range & 1) {
95 return OTS_FAILURE(); 98 return OTS_FAILURE_MSG("Bad subcmap structure");
96 } 99 }
97 const uint16_t segcount = segcountx2 >> 1; 100 const uint16_t segcount = segcountx2 >> 1;
98 // There must be at least one segment according the spec. 101 // There must be at least one segment according the spec.
99 if (segcount < 1) { 102 if (segcount < 1) {
100 return OTS_FAILURE(); 103 return OTS_FAILURE_MSG("Segcount < 1 (%d)", segcount);
101 } 104 }
102 105
103 // log2segcount is the maximal x s.t. 2^x < segcount 106 // log2segcount is the maximal x s.t. 2^x < segcount
104 unsigned log2segcount = 0; 107 unsigned log2segcount = 0;
105 while (1u << (log2segcount + 1) <= segcount) { 108 while (1u << (log2segcount + 1) <= segcount) {
106 log2segcount++; 109 log2segcount++;
107 } 110 }
108 111
109 const uint16_t expected_search_range = 2 * 1u << log2segcount; 112 const uint16_t expected_search_range = 2 * 1u << log2segcount;
110 if (expected_search_range != search_range) { 113 if (expected_search_range != search_range) {
111 return OTS_FAILURE(); 114 return OTS_FAILURE_MSG("expected search range != search range (%d != %d)", e xpected_search_range, search_range);
112 } 115 }
113 116
114 if (entry_selector != log2segcount) { 117 if (entry_selector != log2segcount) {
115 return OTS_FAILURE(); 118 return OTS_FAILURE_MSG("entry selector != log2(segement count) (%d != %d)", entry_selector, log2segcount);
116 } 119 }
117 120
118 const uint16_t expected_range_shift = segcountx2 - search_range; 121 const uint16_t expected_range_shift = segcountx2 - search_range;
119 if (range_shift != expected_range_shift) { 122 if (range_shift != expected_range_shift) {
120 return OTS_FAILURE(); 123 return OTS_FAILURE_MSG("unexpected range shift (%d != %d)", range_shift, exp ected_range_shift);
121 } 124 }
122 125
123 std::vector<Subtable314Range> ranges(segcount); 126 std::vector<Subtable314Range> ranges(segcount);
124 127
125 for (unsigned i = 0; i < segcount; ++i) { 128 for (unsigned i = 0; i < segcount; ++i) {
126 if (!subtable.ReadU16(&ranges[i].end_range)) { 129 if (!subtable.ReadU16(&ranges[i].end_range)) {
127 return OTS_FAILURE(); 130 return OTS_FAILURE_MSG("Failed to read segment %d", i);
128 } 131 }
129 } 132 }
130 133
131 uint16_t padding; 134 uint16_t padding;
132 if (!subtable.ReadU16(&padding)) { 135 if (!subtable.ReadU16(&padding)) {
133 return OTS_FAILURE(); 136 return OTS_FAILURE_MSG("Failed to read cmap subtable segment padding");
134 } 137 }
135 if (padding) { 138 if (padding) {
136 return OTS_FAILURE(); 139 return OTS_FAILURE_MSG("Non zero cmap subtable segment padding (%d)", paddin g);
137 } 140 }
138 141
139 for (unsigned i = 0; i < segcount; ++i) { 142 for (unsigned i = 0; i < segcount; ++i) {
140 if (!subtable.ReadU16(&ranges[i].start_range)) { 143 if (!subtable.ReadU16(&ranges[i].start_range)) {
141 return OTS_FAILURE(); 144 return OTS_FAILURE_MSG("Failed to read segment start range %d", i);
142 } 145 }
143 } 146 }
144 for (unsigned i = 0; i < segcount; ++i) { 147 for (unsigned i = 0; i < segcount; ++i) {
145 if (!subtable.ReadS16(&ranges[i].id_delta)) { 148 if (!subtable.ReadS16(&ranges[i].id_delta)) {
146 return OTS_FAILURE(); 149 return OTS_FAILURE_MSG("Failed to read segment delta %d", i);
147 } 150 }
148 } 151 }
149 for (unsigned i = 0; i < segcount; ++i) { 152 for (unsigned i = 0; i < segcount; ++i) {
150 ranges[i].id_range_offset_offset = subtable.offset(); 153 ranges[i].id_range_offset_offset = subtable.offset();
151 if (!subtable.ReadU16(&ranges[i].id_range_offset)) { 154 if (!subtable.ReadU16(&ranges[i].id_range_offset)) {
152 return OTS_FAILURE(); 155 return OTS_FAILURE_MSG("Failed to read segment range offset %d", i);
153 } 156 }
154 157
155 if (ranges[i].id_range_offset & 1) { 158 if (ranges[i].id_range_offset & 1) {
156 // Some font generators seem to put 65535 on id_range_offset 159 // Some font generators seem to put 65535 on id_range_offset
157 // for 0xFFFF-0xFFFF range. 160 // for 0xFFFF-0xFFFF range.
158 // (e.g., many fonts in http://www.princexml.com/fonts/) 161 // (e.g., many fonts in http://www.princexml.com/fonts/)
159 if (i == segcount - 1u) { 162 if (i == segcount - 1u) {
160 OTS_WARNING("bad id_range_offset"); 163 OTS_WARNING("bad id_range_offset");
161 ranges[i].id_range_offset = 0; 164 ranges[i].id_range_offset = 0;
162 // The id_range_offset value in the transcoded font will not change 165 // The id_range_offset value in the transcoded font will not change
163 // since this table is not actually "transcoded" yet. 166 // since this table is not actually "transcoded" yet.
164 } else { 167 } else {
165 return OTS_FAILURE(); 168 return OTS_FAILURE_MSG("Bad segment offset (%d)", ranges[i].id_range_off set);
166 } 169 }
167 } 170 }
168 } 171 }
169 172
170 // ranges must be ascending order, based on the end_code. Ranges may not 173 // ranges must be ascending order, based on the end_code. Ranges may not
171 // overlap. 174 // overlap.
172 for (unsigned i = 1; i < segcount; ++i) { 175 for (unsigned i = 1; i < segcount; ++i) {
173 if ((i == segcount - 1u) && 176 if ((i == segcount - 1u) &&
174 (ranges[i - 1].start_range == 0xffff) && 177 (ranges[i - 1].start_range == 0xffff) &&
175 (ranges[i - 1].end_range == 0xffff) && 178 (ranges[i - 1].end_range == 0xffff) &&
176 (ranges[i].start_range == 0xffff) && 179 (ranges[i].start_range == 0xffff) &&
177 (ranges[i].end_range == 0xffff)) { 180 (ranges[i].end_range == 0xffff)) {
178 // Some fonts (e.g., Germania.ttf) have multiple 0xffff terminators. 181 // Some fonts (e.g., Germania.ttf) have multiple 0xffff terminators.
179 // We'll accept them as an exception. 182 // We'll accept them as an exception.
180 OTS_WARNING("multiple 0xffff terminators found"); 183 OTS_WARNING("multiple 0xffff terminators found");
181 continue; 184 continue;
182 } 185 }
183 186
184 // Note: some Linux fonts (e.g., LucidaSansOblique.ttf, bsmi00lp.ttf) have 187 // Note: some Linux fonts (e.g., LucidaSansOblique.ttf, bsmi00lp.ttf) have
185 // unsorted table... 188 // unsorted table...
186 if (ranges[i].end_range <= ranges[i - 1].end_range) { 189 if (ranges[i].end_range <= ranges[i - 1].end_range) {
187 return OTS_FAILURE(); 190 return OTS_FAILURE_MSG("Out of order end range (%d <= %d)", ranges[i].end_ range, ranges[i-1].end_range);
188 } 191 }
189 if (ranges[i].start_range <= ranges[i - 1].end_range) { 192 if (ranges[i].start_range <= ranges[i - 1].end_range) {
190 return OTS_FAILURE(); 193 return OTS_FAILURE_MSG("out of order start range (%d <= %d)", ranges[i].st art_range, ranges[i-1].end_range);
191 } 194 }
192 195
193 // On many fonts, the value of {first, last}_char_index are incorrect. 196 // On many fonts, the value of {first, last}_char_index are incorrect.
194 // Fix them. 197 // Fix them.
195 if (file->os2->first_char_index != 0xFFFF && 198 if (file->os2->first_char_index != 0xFFFF &&
196 ranges[i].start_range != 0xFFFF && 199 ranges[i].start_range != 0xFFFF &&
197 file->os2->first_char_index > ranges[i].start_range) { 200 file->os2->first_char_index > ranges[i].start_range) {
198 file->os2->first_char_index = ranges[i].start_range; 201 file->os2->first_char_index = ranges[i].start_range;
199 } 202 }
200 if (file->os2->last_char_index != 0xFFFF && 203 if (file->os2->last_char_index != 0xFFFF &&
201 ranges[i].end_range != 0xFFFF && 204 ranges[i].end_range != 0xFFFF &&
202 file->os2->last_char_index < ranges[i].end_range) { 205 file->os2->last_char_index < ranges[i].end_range) {
203 file->os2->last_char_index = ranges[i].end_range; 206 file->os2->last_char_index = ranges[i].end_range;
204 } 207 }
205 } 208 }
206 209
207 // The last range must end at 0xffff 210 // The last range must end at 0xffff
208 if (ranges[segcount - 1].end_range != 0xffff) { 211 if (ranges[segcount - 1].start_range != 0xffff || ranges[segcount - 1].end_ran ge != 0xffff) {
209 return OTS_FAILURE(); 212 return OTS_FAILURE_MSG("Final segment start and end must be 0xFFFF (0x%04X-0 x%04X)",
213 ranges[segcount - 1].start_range, ranges[segcount - 1 ].end_range);
210 } 214 }
211 215
212 // A format 4 CMAP subtable is complex. To be safe we simulate a lookup of 216 // A format 4 CMAP subtable is complex. To be safe we simulate a lookup of
213 // each code-point defined in the table and make sure that they are all valid 217 // each code-point defined in the table and make sure that they are all valid
214 // glyphs and that we don't access anything out-of-bounds. 218 // glyphs and that we don't access anything out-of-bounds.
215 for (unsigned i = 0; i < segcount; ++i) { 219 for (unsigned i = 0; i < segcount; ++i) {
216 for (unsigned cp = ranges[i].start_range; cp <= ranges[i].end_range; ++cp) { 220 for (unsigned cp = ranges[i].start_range; cp <= ranges[i].end_range; ++cp) {
217 const uint16_t code_point = static_cast<uint16_t>(cp); 221 const uint16_t code_point = static_cast<uint16_t>(cp);
218 if (ranges[i].id_range_offset == 0) { 222 if (ranges[i].id_range_offset == 0) {
219 // this is explictly allowed to overflow in the spec 223 // this is explictly allowed to overflow in the spec
220 const uint16_t glyph = code_point + ranges[i].id_delta; 224 const uint16_t glyph = code_point + ranges[i].id_delta;
221 if (glyph >= num_glyphs) { 225 if (glyph >= num_glyphs) {
222 return OTS_FAILURE(); 226 return OTS_FAILURE_MSG("Range glyph reference too high (%d > %d)", gly ph, num_glyphs - 1);
223 } 227 }
224 } else { 228 } else {
225 const uint16_t range_delta = code_point - ranges[i].start_range; 229 const uint16_t range_delta = code_point - ranges[i].start_range;
226 // this might seem odd, but it's true. The offset is relative to the 230 // this might seem odd, but it's true. The offset is relative to the
227 // location of the offset value itself. 231 // location of the offset value itself.
228 const uint32_t glyph_id_offset = ranges[i].id_range_offset_offset + 232 const uint32_t glyph_id_offset = ranges[i].id_range_offset_offset +
229 ranges[i].id_range_offset + 233 ranges[i].id_range_offset +
230 range_delta * 2; 234 range_delta * 2;
231 // We need to be able to access a 16-bit value from this offset 235 // We need to be able to access a 16-bit value from this offset
232 if (glyph_id_offset + 1 >= length) { 236 if (glyph_id_offset + 1 >= length) {
233 return OTS_FAILURE(); 237 return OTS_FAILURE_MSG("bad glyph id offset (%d > %ld)", glyph_id_offs et, length);
234 } 238 }
235 uint16_t glyph; 239 uint16_t glyph;
236 std::memcpy(&glyph, data + glyph_id_offset, 2); 240 std::memcpy(&glyph, data + glyph_id_offset, 2);
237 glyph = ntohs(glyph); 241 glyph = ntohs(glyph);
238 if (glyph >= num_glyphs) { 242 if (glyph >= num_glyphs) {
239 return OTS_FAILURE(); 243 return OTS_FAILURE_MSG("Range glyph reference too high (%d > %d)", gly ph, num_glyphs - 1);
240 } 244 }
241 } 245 }
242 } 246 }
243 } 247 }
244 248
245 // We accept the table. 249 // We accept the table.
246 // TODO(yusukes): transcode the subtable. 250 // TODO(yusukes): transcode the subtable.
247 if (platform == 3 && encoding == 0) { 251 if (platform == 3 && encoding == 0) {
248 file->cmap->subtable_3_0_4_data = data; 252 file->cmap->subtable_3_0_4_data = data;
249 file->cmap->subtable_3_0_4_length = length; 253 file->cmap->subtable_3_0_4_length = length;
250 } else if (platform == 3 && encoding == 1) { 254 } else if (platform == 3 && encoding == 1) {
251 file->cmap->subtable_3_1_4_data = data; 255 file->cmap->subtable_3_1_4_data = data;
252 file->cmap->subtable_3_1_4_length = length; 256 file->cmap->subtable_3_1_4_length = length;
253 } else if (platform == 0 && encoding == 3) { 257 } else if (platform == 0 && encoding == 3) {
254 file->cmap->subtable_0_3_4_data = data; 258 file->cmap->subtable_0_3_4_data = data;
255 file->cmap->subtable_0_3_4_length = length; 259 file->cmap->subtable_0_3_4_length = length;
256 } else { 260 } else {
257 return OTS_FAILURE(); 261 return OTS_FAILURE_MSG("Unknown cmap subtable type (platform=%d, encoding=%d )", platform, encoding);
258 } 262 }
259 263
260 return true; 264 return true;
261 } 265 }
262 266
263 bool Parse31012(ots::OpenTypeFile *file, 267 bool Parse31012(ots::OpenTypeFile *file,
264 const uint8_t *data, size_t length, uint16_t num_glyphs) { 268 const uint8_t *data, size_t length, uint16_t num_glyphs) {
265 ots::Buffer subtable(data, length); 269 ots::Buffer subtable(data, length);
266 270
267 // Format 12 tables are simple. We parse these and fully serialise them 271 // Format 12 tables are simple. We parse these and fully serialise them
268 // later. 272 // later.
269 273
270 if (!subtable.Skip(8)) { 274 if (!subtable.Skip(8)) {
271 return OTS_FAILURE(); 275 return OTS_FAILURE_MSG("failed to skip the first 8 bytes of format 12 subtab le");
272 } 276 }
273 uint32_t language = 0; 277 uint32_t language = 0;
274 if (!subtable.ReadU32(&language)) { 278 if (!subtable.ReadU32(&language)) {
275 return OTS_FAILURE(); 279 return OTS_FAILURE_MSG("can't read format 12 subtable language");
276 } 280 }
277 if (language) { 281 if (language) {
278 return OTS_FAILURE(); 282 return OTS_FAILURE_MSG("format 12 subtable language should be zero (%d)", la nguage);
279 } 283 }
280 284
281 uint32_t num_groups = 0; 285 uint32_t num_groups = 0;
282 if (!subtable.ReadU32(&num_groups)) { 286 if (!subtable.ReadU32(&num_groups)) {
283 return OTS_FAILURE(); 287 return OTS_FAILURE_MSG("can't read number of format 12 subtable groups");
284 } 288 }
285 if (num_groups == 0 || num_groups > kMaxCMAPGroups) { 289 if (num_groups == 0 || num_groups > kMaxCMAPGroups) {
286 return OTS_FAILURE(); 290 return OTS_FAILURE_MSG("bad format 12 subtable group count %d", num_groups);
287 } 291 }
288 292
289 std::vector<ots::OpenTypeCMAPSubtableRange> &groups 293 std::vector<ots::OpenTypeCMAPSubtableRange> &groups
290 = file->cmap->subtable_3_10_12; 294 = file->cmap->subtable_3_10_12;
291 groups.resize(num_groups); 295 groups.resize(num_groups);
292 296
293 for (unsigned i = 0; i < num_groups; ++i) { 297 for (unsigned i = 0; i < num_groups; ++i) {
294 if (!subtable.ReadU32(&groups[i].start_range) || 298 if (!subtable.ReadU32(&groups[i].start_range) ||
295 !subtable.ReadU32(&groups[i].end_range) || 299 !subtable.ReadU32(&groups[i].end_range) ||
296 !subtable.ReadU32(&groups[i].start_glyph_id)) { 300 !subtable.ReadU32(&groups[i].start_glyph_id)) {
297 return OTS_FAILURE(); 301 return OTS_FAILURE_MSG("can't read format 12 subtable group");
298 } 302 }
299 303
300 if (groups[i].start_range > kUnicodeUpperLimit || 304 if (groups[i].start_range > kUnicodeUpperLimit ||
301 groups[i].end_range > kUnicodeUpperLimit || 305 groups[i].end_range > kUnicodeUpperLimit ||
302 groups[i].start_glyph_id > 0xFFFF) { 306 groups[i].start_glyph_id > 0xFFFF) {
303 return OTS_FAILURE(); 307 return OTS_FAILURE_MSG("bad format 12 subtable group (startCharCode=0x%4X, endCharCode=0x%4X, startGlyphID=%d)",
308 groups[i].start_range, groups[i].end_range, groups[ i].start_glyph_id);
304 } 309 }
305 310
306 // [0xD800, 0xDFFF] are surrogate code points. 311 // [0xD800, 0xDFFF] are surrogate code points.
307 if (groups[i].start_range >= 0xD800 && 312 if (groups[i].start_range >= 0xD800 &&
308 groups[i].start_range <= 0xDFFF) { 313 groups[i].start_range <= 0xDFFF) {
309 return OTS_FAILURE(); 314 return OTS_FAILURE_MSG("format 12 subtable out of range group startCharCod e (0x%4X)", groups[i].start_range);
310 } 315 }
311 if (groups[i].end_range >= 0xD800 && 316 if (groups[i].end_range >= 0xD800 &&
312 groups[i].end_range <= 0xDFFF) { 317 groups[i].end_range <= 0xDFFF) {
313 return OTS_FAILURE(); 318 return OTS_FAILURE_MSG("format 12 subtable out of range group endCharCode (0x%4X)", groups[i].end_range);
314 } 319 }
315 if (groups[i].start_range < 0xD800 && 320 if (groups[i].start_range < 0xD800 &&
316 groups[i].end_range > 0xDFFF) { 321 groups[i].end_range > 0xDFFF) {
317 return OTS_FAILURE(); 322 return OTS_FAILURE_MSG("bad format 12 subtable group startCharCode (0x%4X) or endCharCode (0x%4X)",
323 groups[i].start_range, groups[i].end_range);
318 } 324 }
319 325
320 // We assert that the glyph value is within range. Because of the range 326 // We assert that the glyph value is within range. Because of the range
321 // limits, above, we don't need to worry about overflow. 327 // limits, above, we don't need to worry about overflow.
322 if (groups[i].end_range < groups[i].start_range) { 328 if (groups[i].end_range < groups[i].start_range) {
323 return OTS_FAILURE(); 329 return OTS_FAILURE_MSG("format 12 subtable group endCharCode before startC harCode (0x%4X < 0x%4X)",
330 groups[i].end_range, groups[i].start_range);
324 } 331 }
325 if ((groups[i].end_range - groups[i].start_range) + 332 if ((groups[i].end_range - groups[i].start_range) +
326 groups[i].start_glyph_id > num_glyphs) { 333 groups[i].start_glyph_id > num_glyphs) {
327 return OTS_FAILURE(); 334 return OTS_FAILURE_MSG("bad format 12 subtable group startGlyphID (%d)", g roups[i].start_glyph_id);
328 } 335 }
329 } 336 }
330 337
331 // the groups must be sorted by start code and may not overlap 338 // the groups must be sorted by start code and may not overlap
332 for (unsigned i = 1; i < num_groups; ++i) { 339 for (unsigned i = 1; i < num_groups; ++i) {
333 if (groups[i].start_range <= groups[i - 1].start_range) { 340 if (groups[i].start_range <= groups[i - 1].start_range) {
334 return OTS_FAILURE(); 341 return OTS_FAILURE_MSG("out of order format 12 subtable group (startCharCo de=0x%4X <= startCharCode=0x%4X of previous group)",
342 groups[i].start_range, groups[i-1].start_range);
335 } 343 }
336 if (groups[i].start_range <= groups[i - 1].end_range) { 344 if (groups[i].start_range <= groups[i - 1].end_range) {
337 return OTS_FAILURE(); 345 return OTS_FAILURE_MSG("overlapping format 12 subtable groups (startCharCo de=0x%4X <= endCharCode=0x%4X of previous group)",
346 groups[i].start_range, groups[i-1].end_range);
338 } 347 }
339 } 348 }
340 349
341 return true; 350 return true;
342 } 351 }
343 352
344 bool Parse31013(ots::OpenTypeFile *file, 353 bool Parse31013(ots::OpenTypeFile *file,
345 const uint8_t *data, size_t length, uint16_t num_glyphs) { 354 const uint8_t *data, size_t length, uint16_t num_glyphs) {
346 ots::Buffer subtable(data, length); 355 ots::Buffer subtable(data, length);
347 356
348 // Format 13 tables are simple. We parse these and fully serialise them 357 // Format 13 tables are simple. We parse these and fully serialise them
349 // later. 358 // later.
350 359
351 if (!subtable.Skip(8)) { 360 if (!subtable.Skip(8)) {
352 return OTS_FAILURE(); 361 return OTS_FAILURE_MSG("Bad cmap subtable length");
353 } 362 }
354 uint32_t language = 0; 363 uint32_t language = 0;
355 if (!subtable.ReadU32(&language)) { 364 if (!subtable.ReadU32(&language)) {
356 return OTS_FAILURE(); 365 return OTS_FAILURE_MSG("Can't read cmap subtable language");
357 } 366 }
358 if (language) { 367 if (language) {
359 return OTS_FAILURE(); 368 return OTS_FAILURE_MSG("Cmap subtable language should be zero but is %d", la nguage);
360 } 369 }
361 370
362 uint32_t num_groups = 0; 371 uint32_t num_groups = 0;
363 if (!subtable.ReadU32(&num_groups)) { 372 if (!subtable.ReadU32(&num_groups)) {
364 return OTS_FAILURE(); 373 return OTS_FAILURE_MSG("Can't read number of groups in a cmap subtable");
365 } 374 }
366 375
367 // We limit the number of groups in the same way as in 3.10.12 tables. See 376 // We limit the number of groups in the same way as in 3.10.12 tables. See
368 // the comment there in 377 // the comment there in
369 if (num_groups == 0 || num_groups > kMaxCMAPGroups) { 378 if (num_groups == 0 || num_groups > kMaxCMAPGroups) {
370 return OTS_FAILURE(); 379 return OTS_FAILURE_MSG("Bad number of groups (%d) in a cmap subtable", num_g roups);
371 } 380 }
372 381
373 std::vector<ots::OpenTypeCMAPSubtableRange> &groups 382 std::vector<ots::OpenTypeCMAPSubtableRange> &groups
374 = file->cmap->subtable_3_10_13; 383 = file->cmap->subtable_3_10_13;
375 groups.resize(num_groups); 384 groups.resize(num_groups);
376 385
377 for (unsigned i = 0; i < num_groups; ++i) { 386 for (unsigned i = 0; i < num_groups; ++i) {
378 if (!subtable.ReadU32(&groups[i].start_range) || 387 if (!subtable.ReadU32(&groups[i].start_range) ||
379 !subtable.ReadU32(&groups[i].end_range) || 388 !subtable.ReadU32(&groups[i].end_range) ||
380 !subtable.ReadU32(&groups[i].start_glyph_id)) { 389 !subtable.ReadU32(&groups[i].start_glyph_id)) {
381 return OTS_FAILURE(); 390 return OTS_FAILURE_MSG("Can't read subrange structure in a cmap subtable") ;
382 } 391 }
383 392
384 // We conservatively limit all of the values to protect some parsers from 393 // We conservatively limit all of the values to protect some parsers from
385 // overflows 394 // overflows
386 if (groups[i].start_range > kUnicodeUpperLimit || 395 if (groups[i].start_range > kUnicodeUpperLimit ||
387 groups[i].end_range > kUnicodeUpperLimit || 396 groups[i].end_range > kUnicodeUpperLimit ||
388 groups[i].start_glyph_id > 0xFFFF) { 397 groups[i].start_glyph_id > 0xFFFF) {
389 return OTS_FAILURE(); 398 return OTS_FAILURE_MSG("Bad subrange with start_range=%d, end_range=%d, st art_glyph_id=%d", groups[i].start_range, groups[i].end_range, groups[i].start_gl yph_id);
390 } 399 }
391 400
392 if (groups[i].start_glyph_id >= num_glyphs) { 401 if (groups[i].start_glyph_id >= num_glyphs) {
393 return OTS_FAILURE(); 402 return OTS_FAILURE_MSG("Subrange starting glyph id too high (%d > %d)", gr oups[i].start_glyph_id, num_glyphs);
394 } 403 }
395 } 404 }
396 405
397 // the groups must be sorted by start code and may not overlap 406 // the groups must be sorted by start code and may not overlap
398 for (unsigned i = 1; i < num_groups; ++i) { 407 for (unsigned i = 1; i < num_groups; ++i) {
399 if (groups[i].start_range <= groups[i - 1].start_range) { 408 if (groups[i].start_range <= groups[i - 1].start_range) {
400 return OTS_FAILURE(); 409 return OTS_FAILURE_MSG("Overlapping subrange starts (%d >= %d)", groups[i] . start_range, groups[i-1].start_range);
401 } 410 }
402 if (groups[i].start_range <= groups[i - 1].end_range) { 411 if (groups[i].start_range <= groups[i - 1].end_range) {
403 return OTS_FAILURE(); 412 return OTS_FAILURE_MSG("Overlapping subranges (%d <= %d)", groups[i].start _range, groups[i-1].end_range);
404 } 413 }
405 } 414 }
406 415
407 return true; 416 return true;
408 } 417 }
409 418
410 bool Parse0514(ots::OpenTypeFile *file, 419 bool Parse0514(ots::OpenTypeFile *file,
411 const uint8_t *data, size_t length, uint16_t num_glyphs) { 420 const uint8_t *data, size_t length, uint16_t num_glyphs) {
412 // Unicode Variation Selector table 421 // Unicode Variation Selector table
413 ots::Buffer subtable(data, length); 422 ots::Buffer subtable(data, length);
414 423
415 // Format 14 tables are simple. We parse these and fully serialise them 424 // Format 14 tables are simple. We parse these and fully serialise them
416 // later. 425 // later.
417 426
418 // Skip format (USHORT) and length (ULONG) 427 // Skip format (USHORT) and length (ULONG)
419 if (!subtable.Skip(6)) { 428 if (!subtable.Skip(6)) {
420 return OTS_FAILURE(); 429 return OTS_FAILURE_MSG("Can't read start of cmap subtable");
421 } 430 }
422 431
423 uint32_t num_records = 0; 432 uint32_t num_records = 0;
424 if (!subtable.ReadU32(&num_records)) { 433 if (!subtable.ReadU32(&num_records)) {
425 return OTS_FAILURE(); 434 return OTS_FAILURE_MSG("Can't read number of records in cmap subtable");
426 } 435 }
427 if (num_records == 0 || num_records > kMaxCMAPSelectorRecords) { 436 if (num_records == 0 || num_records > kMaxCMAPSelectorRecords) {
428 return OTS_FAILURE(); 437 return OTS_FAILURE_MSG("Bad number of records (%d) in cmap subtable", num_re cords);
429 } 438 }
430 439
431 std::vector<ots::OpenTypeCMAPSubtableVSRecord>& records 440 std::vector<ots::OpenTypeCMAPSubtableVSRecord>& records
432 = file->cmap->subtable_0_5_14; 441 = file->cmap->subtable_0_5_14;
433 records.resize(num_records); 442 records.resize(num_records);
434 443
435 for (unsigned i = 0; i < num_records; ++i) { 444 for (unsigned i = 0; i < num_records; ++i) {
436 if (!subtable.ReadU24(&records[i].var_selector) || 445 if (!subtable.ReadU24(&records[i].var_selector) ||
437 !subtable.ReadU32(&records[i].default_offset) || 446 !subtable.ReadU32(&records[i].default_offset) ||
438 !subtable.ReadU32(&records[i].non_default_offset)) { 447 !subtable.ReadU32(&records[i].non_default_offset)) {
439 return OTS_FAILURE(); 448 return OTS_FAILURE_MSG("Can't read record structure of record %d in cmap s ubtale", i);
440 } 449 }
441 // Checks the value of variation selector 450 // Checks the value of variation selector
442 if (!((records[i].var_selector >= kMongolianVSStart && 451 if (!((records[i].var_selector >= kMongolianVSStart &&
443 records[i].var_selector <= kMongolianVSEnd) || 452 records[i].var_selector <= kMongolianVSEnd) ||
444 (records[i].var_selector >= kVSStart && 453 (records[i].var_selector >= kVSStart &&
445 records[i].var_selector <= kVSEnd) || 454 records[i].var_selector <= kVSEnd) ||
446 (records[i].var_selector >= kIVSStart && 455 (records[i].var_selector >= kIVSStart &&
447 records[i].var_selector <= kIVSEnd))) { 456 records[i].var_selector <= kIVSEnd))) {
448 return OTS_FAILURE(); 457 return OTS_FAILURE_MSG("Bad record variation selector (%04X) in record %i" , records[i].var_selector, i);
449 } 458 }
450 if (i > 0 && 459 if (i > 0 &&
451 records[i-1].var_selector >= records[i].var_selector) { 460 records[i-1].var_selector >= records[i].var_selector) {
452 return OTS_FAILURE(); 461 return OTS_FAILURE_MSG("Out of order variation selector (%04X >= %04X) in record %d", records[i-1].var_selector, records[i].var_selector, i);
453 } 462 }
454 463
455 // Checks offsets 464 // Checks offsets
456 if (!records[i].default_offset && !records[i].non_default_offset) { 465 if (!records[i].default_offset && !records[i].non_default_offset) {
457 return OTS_FAILURE(); 466 return OTS_FAILURE_MSG("No default aoffset in variation selector record %d ", i);
458 } 467 }
459 if (records[i].default_offset && 468 if (records[i].default_offset &&
460 records[i].default_offset >= length) { 469 records[i].default_offset >= length) {
461 return OTS_FAILURE(); 470 return OTS_FAILURE_MSG("Default offset too high (%d >= %ld) in record %d", records[i].default_offset, length, i);
462 } 471 }
463 if (records[i].non_default_offset && 472 if (records[i].non_default_offset &&
464 records[i].non_default_offset >= length) { 473 records[i].non_default_offset >= length) {
465 return OTS_FAILURE(); 474 return OTS_FAILURE_MSG("Non default offset too high (%d >= %ld) in record %d", records[i].non_default_offset, length, i);
466 } 475 }
467 } 476 }
468 477
469 for (unsigned i = 0; i < num_records; ++i) { 478 for (unsigned i = 0; i < num_records; ++i) {
470 // Checks default UVS table 479 // Checks default UVS table
471 if (records[i].default_offset) { 480 if (records[i].default_offset) {
472 subtable.set_offset(records[i].default_offset); 481 subtable.set_offset(records[i].default_offset);
473 uint32_t num_ranges = 0; 482 uint32_t num_ranges = 0;
474 if (!subtable.ReadU32(&num_ranges)) { 483 if (!subtable.ReadU32(&num_ranges)) {
475 return OTS_FAILURE(); 484 return OTS_FAILURE_MSG("Can't read number of ranges in record %d", i);
476 } 485 }
477 if (!num_ranges || num_ranges > kMaxCMAPGroups) { 486 if (!num_ranges || num_ranges > kMaxCMAPGroups) {
478 return OTS_FAILURE(); 487 return OTS_FAILURE_MSG("number of ranges too high (%d > %d) in record %d ", num_ranges, kMaxCMAPGroups, i);
479 } 488 }
480 489
481 uint32_t last_unicode_value = 0; 490 uint32_t last_unicode_value = 0;
482 std::vector<ots::OpenTypeCMAPSubtableVSRange>& ranges 491 std::vector<ots::OpenTypeCMAPSubtableVSRange>& ranges
483 = records[i].ranges; 492 = records[i].ranges;
484 ranges.resize(num_ranges); 493 ranges.resize(num_ranges);
485 494
486 for (unsigned j = 0; j < num_ranges; ++j) { 495 for (unsigned j = 0; j < num_ranges; ++j) {
487 if (!subtable.ReadU24(&ranges[j].unicode_value) || 496 if (!subtable.ReadU24(&ranges[j].unicode_value) ||
488 !subtable.ReadU8(&ranges[j].additional_count)) { 497 !subtable.ReadU8(&ranges[j].additional_count)) {
489 return OTS_FAILURE(); 498 return OTS_FAILURE_MSG("Can't read range info in variation selector re cord %d", i);
490 } 499 }
491 const uint32_t check_value = 500 const uint32_t check_value =
492 ranges[j].unicode_value + ranges[j].additional_count; 501 ranges[j].unicode_value + ranges[j].additional_count;
493 if (ranges[j].unicode_value == 0 || 502 if (ranges[j].unicode_value == 0 ||
494 ranges[j].unicode_value > kUnicodeUpperLimit || 503 ranges[j].unicode_value > kUnicodeUpperLimit ||
495 check_value > kUVSUpperLimit || 504 check_value > kUVSUpperLimit ||
496 (last_unicode_value && 505 (last_unicode_value &&
497 ranges[j].unicode_value <= last_unicode_value)) { 506 ranges[j].unicode_value <= last_unicode_value)) {
498 return OTS_FAILURE(); 507 return OTS_FAILURE_MSG("Bad Unicode value *%04X) in variation selector range %d record %d", ranges[j].unicode_value, j, i);
499 } 508 }
500 last_unicode_value = check_value; 509 last_unicode_value = check_value;
501 } 510 }
502 } 511 }
503 512
504 // Checks non default UVS table 513 // Checks non default UVS table
505 if (records[i].non_default_offset) { 514 if (records[i].non_default_offset) {
506 subtable.set_offset(records[i].non_default_offset); 515 subtable.set_offset(records[i].non_default_offset);
507 uint32_t num_mappings = 0; 516 uint32_t num_mappings = 0;
508 if (!subtable.ReadU32(&num_mappings)) { 517 if (!subtable.ReadU32(&num_mappings)) {
509 return OTS_FAILURE(); 518 return OTS_FAILURE_MSG("Can't read number of mappings in variation selec tor record %d", i);
510 } 519 }
511 if (!num_mappings || num_mappings > kMaxCMAPGroups) { 520 if (!num_mappings || num_mappings > kMaxCMAPGroups) {
512 return OTS_FAILURE(); 521 return OTS_FAILURE_MSG("Number of mappings too high (%d) in variation se lector record %d", num_mappings, i);
513 } 522 }
514 523
515 uint32_t last_unicode_value = 0; 524 uint32_t last_unicode_value = 0;
516 std::vector<ots::OpenTypeCMAPSubtableVSMapping>& mappings 525 std::vector<ots::OpenTypeCMAPSubtableVSMapping>& mappings
517 = records[i].mappings; 526 = records[i].mappings;
518 mappings.resize(num_mappings); 527 mappings.resize(num_mappings);
519 528
520 for (unsigned j = 0; j < num_mappings; ++j) { 529 for (unsigned j = 0; j < num_mappings; ++j) {
521 if (!subtable.ReadU24(&mappings[j].unicode_value) || 530 if (!subtable.ReadU24(&mappings[j].unicode_value) ||
522 !subtable.ReadU16(&mappings[j].glyph_id)) { 531 !subtable.ReadU16(&mappings[j].glyph_id)) {
523 return OTS_FAILURE(); 532 return OTS_FAILURE_MSG("Can't read mapping %d in variation selector re cord %d", j, i);
524 } 533 }
525 if (mappings[j].glyph_id == 0 || 534 if (mappings[j].glyph_id == 0 ||
526 mappings[j].unicode_value == 0 || 535 mappings[j].unicode_value == 0 ||
527 mappings[j].unicode_value > kUnicodeUpperLimit || 536 mappings[j].unicode_value > kUnicodeUpperLimit ||
528 (last_unicode_value && 537 (last_unicode_value &&
529 mappings[j].unicode_value <= last_unicode_value)) { 538 mappings[j].unicode_value <= last_unicode_value)) {
530 return OTS_FAILURE(); 539 return OTS_FAILURE_MSG("Bad mapping (%04X -> %d) in mapping %d of vari ation selector %d", mappings[j].unicode_value, mappings[j].glyph_id, j, i);
531 } 540 }
532 last_unicode_value = mappings[j].unicode_value; 541 last_unicode_value = mappings[j].unicode_value;
533 } 542 }
534 } 543 }
535 } 544 }
536 545
537 if (subtable.offset() != length) { 546 if (subtable.offset() != length) {
538 return OTS_FAILURE(); 547 return OTS_FAILURE_MSG("Bad subtable offset (%ld != %ld)", subtable.offset() , length);
539 } 548 }
540 file->cmap->subtable_0_5_14_length = subtable.offset(); 549 file->cmap->subtable_0_5_14_length = subtable.offset();
541 return true; 550 return true;
542 } 551 }
543 552
544 bool Parse100(ots::OpenTypeFile *file, const uint8_t *data, size_t length) { 553 bool Parse100(ots::OpenTypeFile *file, const uint8_t *data, size_t length) {
545 // Mac Roman table 554 // Mac Roman table
546 ots::Buffer subtable(data, length); 555 ots::Buffer subtable(data, length);
547 556
548 if (!subtable.Skip(4)) { 557 if (!subtable.Skip(4)) {
549 return OTS_FAILURE(); 558 return OTS_FAILURE_MSG("Bad cmap subtable");
550 } 559 }
551 uint16_t language = 0; 560 uint16_t language = 0;
552 if (!subtable.ReadU16(&language)) { 561 if (!subtable.ReadU16(&language)) {
553 return OTS_FAILURE(); 562 return OTS_FAILURE_MSG("Can't read language in cmap subtable");
554 } 563 }
555 if (language) { 564 if (language) {
556 // simsun.ttf has non-zero language id. 565 // simsun.ttf has non-zero language id.
557 OTS_WARNING("language id should be zero: %u", language); 566 OTS_WARNING("language id should be zero: %u", language);
558 } 567 }
559 568
560 file->cmap->subtable_1_0_0.reserve(kFormat0ArraySize); 569 file->cmap->subtable_1_0_0.reserve(kFormat0ArraySize);
561 for (size_t i = 0; i < kFormat0ArraySize; ++i) { 570 for (size_t i = 0; i < kFormat0ArraySize; ++i) {
562 uint8_t glyph_id = 0; 571 uint8_t glyph_id = 0;
563 if (!subtable.ReadU8(&glyph_id)) { 572 if (!subtable.ReadU8(&glyph_id)) {
564 return OTS_FAILURE(); 573 return OTS_FAILURE_MSG("Can't read glyph id at array[%ld] in cmap subtable ", i);
565 } 574 }
566 file->cmap->subtable_1_0_0.push_back(glyph_id); 575 file->cmap->subtable_1_0_0.push_back(glyph_id);
567 } 576 }
568 577
569 return true; 578 return true;
570 } 579 }
571 580
572 } // namespace 581 } // namespace
573 582
574 namespace ots { 583 namespace ots {
575 584
576 bool ots_cmap_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 585 bool ots_cmap_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
577 Buffer table(data, length); 586 Buffer table(data, length);
578 file->cmap = new OpenTypeCMAP; 587 file->cmap = new OpenTypeCMAP;
579 588
580 uint16_t version = 0; 589 uint16_t version = 0;
581 uint16_t num_tables = 0; 590 uint16_t num_tables = 0;
582 if (!table.ReadU16(&version) || 591 if (!table.ReadU16(&version) ||
583 !table.ReadU16(&num_tables)) { 592 !table.ReadU16(&num_tables)) {
584 return OTS_FAILURE(); 593 return OTS_FAILURE_MSG("Can't read structure of cmap");
585 } 594 }
586 595
587 if (version != 0) { 596 if (version != 0) {
588 return OTS_FAILURE(); 597 return OTS_FAILURE_MSG("Non zero cmap version (%d)", version);
589 } 598 }
590 if (!num_tables) { 599 if (!num_tables) {
591 return OTS_FAILURE(); 600 return OTS_FAILURE_MSG("No subtables in cmap!");
592 } 601 }
593 602
594 std::vector<CMAPSubtableHeader> subtable_headers; 603 std::vector<CMAPSubtableHeader> subtable_headers;
595 604
596 // read the subtable headers 605 // read the subtable headers
597 subtable_headers.reserve(num_tables); 606 subtable_headers.reserve(num_tables);
598 for (unsigned i = 0; i < num_tables; ++i) { 607 for (unsigned i = 0; i < num_tables; ++i) {
599 CMAPSubtableHeader subt; 608 CMAPSubtableHeader subt;
600 609
601 if (!table.ReadU16(&subt.platform) || 610 if (!table.ReadU16(&subt.platform) ||
602 !table.ReadU16(&subt.encoding) || 611 !table.ReadU16(&subt.encoding) ||
603 !table.ReadU32(&subt.offset)) { 612 !table.ReadU32(&subt.offset)) {
604 return OTS_FAILURE(); 613 return OTS_FAILURE_MSG("Can't read subtable information cmap subtable %d", i);
605 } 614 }
606 615
607 subtable_headers.push_back(subt); 616 subtable_headers.push_back(subt);
608 } 617 }
609 618
610 const size_t data_offset = table.offset(); 619 const size_t data_offset = table.offset();
611 620
612 // make sure that all the offsets are valid. 621 // make sure that all the offsets are valid.
613 uint32_t last_id = 0;
614 for (unsigned i = 0; i < num_tables; ++i) { 622 for (unsigned i = 0; i < num_tables; ++i) {
615 if (subtable_headers[i].offset > 1024 * 1024 * 1024) { 623 if (subtable_headers[i].offset > 1024 * 1024 * 1024) {
616 return OTS_FAILURE(); 624 return OTS_FAILURE_MSG("Bad subtable offset in cmap subtable %d", i);
617 } 625 }
618 if (subtable_headers[i].offset < data_offset || 626 if (subtable_headers[i].offset < data_offset ||
619 subtable_headers[i].offset >= length) { 627 subtable_headers[i].offset >= length) {
620 return OTS_FAILURE(); 628 return OTS_FAILURE_MSG("Bad subtable offset (%d) in cmap subtable %d", sub table_headers[i].offset, i);
621 } 629 }
622
623 // check if the table is sorted first by platform ID, then by encoding ID.
624 uint32_t current_id
625 = (subtable_headers[i].platform << 16) + subtable_headers[i].encoding;
626 if ((i != 0) && (last_id >= current_id)) {
627 return OTS_FAILURE();
628 }
629 last_id = current_id;
630 } 630 }
631 631
632 // the format of the table is the first couple of bytes in the table. The 632 // the format of the table is the first couple of bytes in the table. The
633 // length of the table is stored in a format-specific way. 633 // length of the table is stored in a format-specific way.
634 for (unsigned i = 0; i < num_tables; ++i) { 634 for (unsigned i = 0; i < num_tables; ++i) {
635 table.set_offset(subtable_headers[i].offset); 635 table.set_offset(subtable_headers[i].offset);
636 if (!table.ReadU16(&subtable_headers[i].format)) { 636 if (!table.ReadU16(&subtable_headers[i].format)) {
637 return OTS_FAILURE(); 637 return OTS_FAILURE_MSG("Can't read cmap subtable header format %d", i);
638 } 638 }
639 639
640 uint16_t len = 0; 640 uint16_t len = 0;
641 uint16_t lang = 0;
641 switch (subtable_headers[i].format) { 642 switch (subtable_headers[i].format) {
642 case 0: 643 case 0:
643 case 4: 644 case 4:
644 if (!table.ReadU16(&len)) { 645 if (!table.ReadU16(&len)) {
645 return OTS_FAILURE(); 646 return OTS_FAILURE_MSG("Can't read cmap subtable %d length", i);
647 }
648 if (!table.ReadU16(&lang)) {
649 return OTS_FAILURE_MSG("Can't read cmap subtable %d language", i);
646 } 650 }
647 subtable_headers[i].length = len; 651 subtable_headers[i].length = len;
652 subtable_headers[i].language = lang;
648 break; 653 break;
649 case 12: 654 case 12:
650 case 13: 655 case 13:
651 if (!table.Skip(2)) { 656 if (!table.Skip(2)) {
652 return OTS_FAILURE(); 657 return OTS_FAILURE_MSG("Bad cmap subtable %d structure", i);
653 } 658 }
654 if (!table.ReadU32(&subtable_headers[i].length)) { 659 if (!table.ReadU32(&subtable_headers[i].length)) {
655 return OTS_FAILURE(); 660 return OTS_FAILURE_MSG("Can read cmap subtable %d length", i);
661 }
662 if (!table.ReadU32(&subtable_headers[i].language)) {
663 return OTS_FAILURE_MSG("Can't read cmap subtable %d language", i);
656 } 664 }
657 break; 665 break;
658 case 14: 666 case 14:
659 if (!table.ReadU32(&subtable_headers[i].length)) { 667 if (!table.ReadU32(&subtable_headers[i].length)) {
660 return OTS_FAILURE(); 668 return OTS_FAILURE_MSG("Can't read cmap subtable %d length", i);
661 } 669 }
670 subtable_headers[i].language = 0;
662 break; 671 break;
663 default: 672 default:
664 subtable_headers[i].length = 0; 673 subtable_headers[i].length = 0;
674 subtable_headers[i].language = 0;
665 break; 675 break;
666 } 676 }
667 } 677 }
668 678
679 // check if the table is sorted first by platform ID, then by encoding ID.
680 uint32_t last_id = 0;
681 for (unsigned i = 0; i < num_tables; ++i) {
682 uint32_t current_id
683 = (subtable_headers[i].platform << 24)
684 + (subtable_headers[i].encoding << 16)
685 + subtable_headers[i].language;
686 if ((i != 0) && (last_id >= current_id)) {
687 return OTS_FAILURE_MSG("subtable %d with platform ID %d, encoding ID %d, l anguage ID %d "
688 "following subtable with platform ID %d, encoding I D %d, language ID %d",
689 i,
690 (uint8_t)(current_id >> 24), (uint8_t)(current_id > > 16), (uint8_t)(current_id),
691 (uint8_t)(last_id >> 24), (uint8_t)(last_id >> 16), (uint8_t)(last_id));
692 }
693 last_id = current_id;
694 }
695
669 // Now, verify that all the lengths are sane 696 // Now, verify that all the lengths are sane
670 for (unsigned i = 0; i < num_tables; ++i) { 697 for (unsigned i = 0; i < num_tables; ++i) {
671 if (!subtable_headers[i].length) continue; 698 if (!subtable_headers[i].length) continue;
672 if (subtable_headers[i].length > 1024 * 1024 * 1024) { 699 if (subtable_headers[i].length > 1024 * 1024 * 1024) {
673 return OTS_FAILURE(); 700 return OTS_FAILURE_MSG("Bad cmap subtable %d length", i);
674 } 701 }
675 // We know that both the offset and length are < 1GB, so the following 702 // We know that both the offset and length are < 1GB, so the following
676 // addition doesn't overflow 703 // addition doesn't overflow
677 const uint32_t end_byte 704 const uint32_t end_byte
678 = subtable_headers[i].offset + subtable_headers[i].length; 705 = subtable_headers[i].offset + subtable_headers[i].length;
679 if (end_byte > length) { 706 if (end_byte > length) {
680 return OTS_FAILURE(); 707 return OTS_FAILURE_MSG("Over long cmap subtable %d @ %d for %d", i, subtab le_headers[i].offset, subtable_headers[i].length);
681 } 708 }
682 } 709 }
683 710
684 // check that the cmap subtables are not overlapping. 711 // check that the cmap subtables are not overlapping.
685 std::set<std::pair<uint32_t, uint32_t> > uniq_checker; 712 std::set<std::pair<uint32_t, uint32_t> > uniq_checker;
686 std::vector<std::pair<uint32_t, uint8_t> > overlap_checker; 713 std::vector<std::pair<uint32_t, uint8_t> > overlap_checker;
687 for (unsigned i = 0; i < num_tables; ++i) { 714 for (unsigned i = 0; i < num_tables; ++i) {
688 const uint32_t end_byte 715 const uint32_t end_byte
689 = subtable_headers[i].offset + subtable_headers[i].length; 716 = subtable_headers[i].offset + subtable_headers[i].length;
690 717
691 if (!uniq_checker.insert(std::make_pair(subtable_headers[i].offset, 718 if (!uniq_checker.insert(std::make_pair(subtable_headers[i].offset,
692 end_byte)).second) { 719 end_byte)).second) {
693 // Sometimes Unicode table and MS table share exactly the same data. 720 // Sometimes Unicode table and MS table share exactly the same data.
694 // We'll allow this. 721 // We'll allow this.
695 continue; 722 continue;
696 } 723 }
697 overlap_checker.push_back( 724 overlap_checker.push_back(
698 std::make_pair(subtable_headers[i].offset, 725 std::make_pair(subtable_headers[i].offset,
699 static_cast<uint8_t>(1) /* start */)); 726 static_cast<uint8_t>(1) /* start */));
700 overlap_checker.push_back( 727 overlap_checker.push_back(
701 std::make_pair(end_byte, static_cast<uint8_t>(0) /* end */)); 728 std::make_pair(end_byte, static_cast<uint8_t>(0) /* end */));
702 } 729 }
703 std::sort(overlap_checker.begin(), overlap_checker.end()); 730 std::sort(overlap_checker.begin(), overlap_checker.end());
704 int overlap_count = 0; 731 int overlap_count = 0;
705 for (unsigned i = 0; i < overlap_checker.size(); ++i) { 732 for (unsigned i = 0; i < overlap_checker.size(); ++i) {
706 overlap_count += (overlap_checker[i].second ? 1 : -1); 733 overlap_count += (overlap_checker[i].second ? 1 : -1);
707 if (overlap_count > 1) { 734 if (overlap_count > 1) {
708 return OTS_FAILURE(); 735 return OTS_FAILURE_MSG("Excessive overlap count %d", overlap_count);
709 } 736 }
710 } 737 }
711 738
712 // we grab the number of glyphs in the file from the maxp table to make sure 739 // we grab the number of glyphs in the file from the maxp table to make sure
713 // that the character map isn't referencing anything beyound this range. 740 // that the character map isn't referencing anything beyound this range.
714 if (!file->maxp) { 741 if (!file->maxp) {
715 return OTS_FAILURE(); 742 return OTS_FAILURE_MSG("No maxp table in font! Needed by cmap.");
716 } 743 }
717 const uint16_t num_glyphs = file->maxp->num_glyphs; 744 const uint16_t num_glyphs = file->maxp->num_glyphs;
718 745
719 // We only support a subset of the possible character map tables. Microsoft 746 // We only support a subset of the possible character map tables. Microsoft
720 // 'strongly recommends' that everyone supports the Unicode BMP table with 747 // 'strongly recommends' that everyone supports the Unicode BMP table with
721 // the UCS-4 table for non-BMP glyphs. We'll pass the following subtables: 748 // the UCS-4 table for non-BMP glyphs. We'll pass the following subtables:
722 // Platform ID Encoding ID Format 749 // Platform ID Encoding ID Format
723 // 0 0 4 (Unicode Default) 750 // 0 0 4 (Unicode Default)
751 // 0 1 4 (Unicode 1.1)
724 // 0 3 4 (Unicode BMP) 752 // 0 3 4 (Unicode BMP)
725 // 0 3 12 (Unicode UCS-4) 753 // 0 3 12 (Unicode UCS-4)
726 // 0 5 14 (Unicode Variation Sequences) 754 // 0 5 14 (Unicode Variation Sequences)
727 // 1 0 0 (Mac Roman) 755 // 1 0 0 (Mac Roman)
728 // 3 0 4 (MS Symbol) 756 // 3 0 4 (MS Symbol)
729 // 3 1 4 (MS Unicode BMP) 757 // 3 1 4 (MS Unicode BMP)
730 // 3 10 12 (MS Unicode UCS-4) 758 // 3 10 12 (MS Unicode UCS-4)
731 // 3 10 13 (MS UCS-4 Fallback mapping) 759 // 3 10 13 (MS UCS-4 Fallback mapping)
732 // 760 //
733 // Note: 761 // Note:
734 // * 0-0-4 table is (usually) written as a 3-1-4 table. If 3-1-4 table 762 // * 0-0-4 and 0-1-4 tables are (usually) written as a 3-1-4 table. If 3-1-4 table
735 // also exists, the 0-0-4 table is ignored. 763 // also exists, the 0-0-4 or 0-1-4 tables are ignored.
736 // * Unlike 0-0-4 table, 0-3-4 table is written as a 0-3-4 table. 764 // * Unlike 0-0-4 table, 0-3-4 table is written as a 0-3-4 table.
737 // Some fonts which include 0-5-14 table seems to be required 0-3-4 765 // Some fonts which include 0-5-14 table seems to be required 0-3-4
738 // table. The 0-3-4 table will be wriiten even if 3-1-4 table also exists. 766 // table. The 0-3-4 table will be wriiten even if 3-1-4 table also exists.
739 // * 0-3-12 table is written as a 3-10-12 table. If 3-10-12 table also 767 // * 0-3-12 table is written as a 3-10-12 table. If 3-10-12 table also
740 // exists, the 0-3-12 table is ignored. 768 // exists, the 0-3-12 table is ignored.
741 // 769 //
742 770
743 for (unsigned i = 0; i < num_tables; ++i) { 771 for (unsigned i = 0; i < num_tables; ++i) {
744 if (subtable_headers[i].platform == 0) { 772 if (subtable_headers[i].platform == 0) {
745 // Unicode platform 773 // Unicode platform
746 774
747 if ((subtable_headers[i].encoding == 0) && 775 if ((subtable_headers[i].encoding == 0 || subtable_headers[i].encoding == 1) &&
748 (subtable_headers[i].format == 4)) { 776 (subtable_headers[i].format == 4)) {
749 // parse and output the 0-0-4 table as 3-1-4 table. Sometimes the 0-0-4 777 // parse and output the 0-0-4 and 0-1-4 tables as 3-1-4 table. Sometimes the 0-0-4
750 // table actually points to MS symbol data and thus should be parsed as 778 // table actually points to MS symbol data and thus should be parsed as
751 // 3-0-4 table (e.g., marqueem.ttf and quixotic.ttf). This error will be 779 // 3-0-4 table (e.g., marqueem.ttf and quixotic.ttf). This error will be
752 // recovered in ots_cmap_serialise(). 780 // recovered in ots_cmap_serialise().
753 if (!ParseFormat4(file, 3, 1, data + subtable_headers[i].offset, 781 if (!ParseFormat4(file, 3, 1, data + subtable_headers[i].offset,
754 subtable_headers[i].length, num_glyphs)) { 782 subtable_headers[i].length, num_glyphs)) {
755 return OTS_FAILURE(); 783 return OTS_FAILURE_MSG("Failed to parse format 4 cmap subtable %d", i) ;
756 } 784 }
757 } else if ((subtable_headers[i].encoding == 3) && 785 } else if ((subtable_headers[i].encoding == 3) &&
758 (subtable_headers[i].format == 4)) { 786 (subtable_headers[i].format == 4)) {
759 // parse and output the 0-3-4 table as 0-3-4 table. 787 // parse and output the 0-3-4 table as 0-3-4 table.
760 if (!ParseFormat4(file, 0, 3, data + subtable_headers[i].offset, 788 if (!ParseFormat4(file, 0, 3, data + subtable_headers[i].offset,
761 subtable_headers[i].length, num_glyphs)) { 789 subtable_headers[i].length, num_glyphs)) {
762 return OTS_FAILURE(); 790 return OTS_FAILURE_MSG("Failed to parse format 4 cmap subtable %d", i) ;
763 } 791 }
764 } else if ((subtable_headers[i].encoding == 3) && 792 } else if ((subtable_headers[i].encoding == 3) &&
765 (subtable_headers[i].format == 12)) { 793 (subtable_headers[i].format == 12)) {
766 // parse and output the 0-3-12 table as 3-10-12 table. 794 // parse and output the 0-3-12 table as 3-10-12 table.
767 if (!Parse31012(file, data + subtable_headers[i].offset, 795 if (!Parse31012(file, data + subtable_headers[i].offset,
768 subtable_headers[i].length, num_glyphs)) { 796 subtable_headers[i].length, num_glyphs)) {
769 return OTS_FAILURE(); 797 return OTS_FAILURE_MSG("Failed to parse format 12 cmap subtable %d", i );
770 } 798 }
771 } else if ((subtable_headers[i].encoding == 5) && 799 } else if ((subtable_headers[i].encoding == 5) &&
772 (subtable_headers[i].format == 14)) { 800 (subtable_headers[i].format == 14)) {
773 if (!Parse0514(file, data + subtable_headers[i].offset, 801 if (!Parse0514(file, data + subtable_headers[i].offset,
774 subtable_headers[i].length, num_glyphs)) { 802 subtable_headers[i].length, num_glyphs)) {
775 return OTS_FAILURE(); 803 return OTS_FAILURE_MSG("Failed to parse format 14 cmap subtable %d", i );
776 } 804 }
777 } 805 }
778 } else if (subtable_headers[i].platform == 1) { 806 } else if (subtable_headers[i].platform == 1) {
779 // Mac platform 807 // Mac platform
780 808
781 if ((subtable_headers[i].encoding == 0) && 809 if ((subtable_headers[i].encoding == 0) &&
782 (subtable_headers[i].format == 0)) { 810 (subtable_headers[i].format == 0)) {
783 // parse and output the 1-0-0 table. 811 // parse and output the 1-0-0 table.
784 if (!Parse100(file, data + subtable_headers[i].offset, 812 if (!Parse100(file, data + subtable_headers[i].offset,
785 subtable_headers[i].length)) { 813 subtable_headers[i].length)) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 const uint16_t num_subtables = static_cast<uint16_t>(have_034) + 869 const uint16_t num_subtables = static_cast<uint16_t>(have_034) +
842 static_cast<uint16_t>(have_0514) + 870 static_cast<uint16_t>(have_0514) +
843 static_cast<uint16_t>(have_100) + 871 static_cast<uint16_t>(have_100) +
844 static_cast<uint16_t>(have_304) + 872 static_cast<uint16_t>(have_304) +
845 static_cast<uint16_t>(have_314) + 873 static_cast<uint16_t>(have_314) +
846 static_cast<uint16_t>(have_31012) + 874 static_cast<uint16_t>(have_31012) +
847 static_cast<uint16_t>(have_31013); 875 static_cast<uint16_t>(have_31013);
848 const off_t table_start = out->Tell(); 876 const off_t table_start = out->Tell();
849 877
850 // Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables 878 // Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables
851 // (e.g., old fonts for Mac). We don't support them except for color bitmap 879 // (e.g., old fonts for Mac). We don't support them.
852 // fonts. 880 if (!have_304 && !have_314 && !have_034 && !have_31012 && !have_31013) {
853 if (!have_304 && !have_314 && !have_034) {
854 if (!(file->cbdt && file->cblc)) { 881 if (!(file->cbdt && file->cblc)) {
855 return OTS_FAILURE(); 882 » return OTS_FAILURE_MSG("no supported subtables were found");
856 } 883 » }
857 } 884 }
858 885
859 if (!out->WriteU16(0) || 886 if (!out->WriteU16(0) ||
860 !out->WriteU16(num_subtables)) { 887 !out->WriteU16(num_subtables)) {
861 return OTS_FAILURE(); 888 return OTS_FAILURE();
862 } 889 }
863 890
864 const off_t record_offset = out->Tell(); 891 const off_t record_offset = out->Tell();
865 if (!out->Pad(num_subtables * 8)) { 892 if (!out->Pad(num_subtables * 8)) {
866 return OTS_FAILURE(); 893 return OTS_FAILURE();
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 out->RestoreChecksum(saved_checksum); 1097 out->RestoreChecksum(saved_checksum);
1071 1098
1072 return true; 1099 return true;
1073 } 1100 }
1074 1101
1075 void ots_cmap_free(OpenTypeFile *file) { 1102 void ots_cmap_free(OpenTypeFile *file) {
1076 delete file->cmap; 1103 delete file->cmap;
1077 } 1104 }
1078 1105
1079 } // namespace ots 1106 } // namespace ots
1107
1108 #undef TABLE_NAME
OLDNEW
« .gitmodules ('K') | « src/cff_type2_charstring.cc ('k') | src/cvt.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698