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

Side by Side Diff: third_party/ots/src/gsub.cc

Issue 1252363005: Update OTS to revision a7a3b94 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 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
« no previous file with comments | « third_party/ots/src/gpos.cc ('k') | third_party/ots/src/hdmx.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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "gsub.h" 5 #include "gsub.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <vector> 8 #include <vector>
9 9
10 #include "layout.h" 10 #include "layout.h"
(...skipping 15 matching lines...) Expand all
26 GSUB_TYPE_ALTERNATE = 3, 26 GSUB_TYPE_ALTERNATE = 3,
27 GSUB_TYPE_LIGATURE = 4, 27 GSUB_TYPE_LIGATURE = 4,
28 GSUB_TYPE_CONTEXT = 5, 28 GSUB_TYPE_CONTEXT = 5,
29 GSUB_TYPE_CHANGING_CONTEXT = 6, 29 GSUB_TYPE_CHANGING_CONTEXT = 6,
30 GSUB_TYPE_EXTENSION_SUBSTITUTION = 7, 30 GSUB_TYPE_EXTENSION_SUBSTITUTION = 7,
31 GSUB_TYPE_REVERSE_CHAINING_CONTEXT_SINGLE = 8, 31 GSUB_TYPE_REVERSE_CHAINING_CONTEXT_SINGLE = 8,
32 GSUB_TYPE_RESERVED = 9 32 GSUB_TYPE_RESERVED = 9
33 }; 33 };
34 34
35 // Lookup type parsers. 35 // Lookup type parsers.
36 bool ParseSingleSubstitution(const ots::OpenTypeFile *file, 36 bool ParseSingleSubstitution(const ots::Font *font,
37 const uint8_t *data, const size_t length); 37 const uint8_t *data, const size_t length);
38 bool ParseMutipleSubstitution(const ots::OpenTypeFile *file, 38 bool ParseMutipleSubstitution(const ots::Font *font,
39 const uint8_t *data, const size_t length); 39 const uint8_t *data, const size_t length);
40 bool ParseAlternateSubstitution(const ots::OpenTypeFile *file, 40 bool ParseAlternateSubstitution(const ots::Font *font,
41 const uint8_t *data, const size_t length); 41 const uint8_t *data, const size_t length);
42 bool ParseLigatureSubstitution(const ots::OpenTypeFile *file, 42 bool ParseLigatureSubstitution(const ots::Font *font,
43 const uint8_t *data, const size_t length); 43 const uint8_t *data, const size_t length);
44 bool ParseContextSubstitution(const ots::OpenTypeFile *file, 44 bool ParseContextSubstitution(const ots::Font *font,
45 const uint8_t *data, const size_t length); 45 const uint8_t *data, const size_t length);
46 bool ParseChainingContextSubstitution(const ots::OpenTypeFile *file, 46 bool ParseChainingContextSubstitution(const ots::Font *font,
47 const uint8_t *data, 47 const uint8_t *data,
48 const size_t length); 48 const size_t length);
49 bool ParseExtensionSubstitution(const ots::OpenTypeFile *file, 49 bool ParseExtensionSubstitution(const ots::Font *font,
50 const uint8_t *data, const size_t length); 50 const uint8_t *data, const size_t length);
51 bool ParseReverseChainingContextSingleSubstitution( 51 bool ParseReverseChainingContextSingleSubstitution(
52 const ots::OpenTypeFile *file, const uint8_t *data, const size_t length); 52 const ots::Font *font, const uint8_t *data, const size_t length);
53 53
54 const ots::LookupSubtableParser::TypeParser kGsubTypeParsers[] = { 54 const ots::LookupSubtableParser::TypeParser kGsubTypeParsers[] = {
55 {GSUB_TYPE_SINGLE, ParseSingleSubstitution}, 55 {GSUB_TYPE_SINGLE, ParseSingleSubstitution},
56 {GSUB_TYPE_MULTIPLE, ParseMutipleSubstitution}, 56 {GSUB_TYPE_MULTIPLE, ParseMutipleSubstitution},
57 {GSUB_TYPE_ALTERNATE, ParseAlternateSubstitution}, 57 {GSUB_TYPE_ALTERNATE, ParseAlternateSubstitution},
58 {GSUB_TYPE_LIGATURE, ParseLigatureSubstitution}, 58 {GSUB_TYPE_LIGATURE, ParseLigatureSubstitution},
59 {GSUB_TYPE_CONTEXT, ParseContextSubstitution}, 59 {GSUB_TYPE_CONTEXT, ParseContextSubstitution},
60 {GSUB_TYPE_CHANGING_CONTEXT, ParseChainingContextSubstitution}, 60 {GSUB_TYPE_CHANGING_CONTEXT, ParseChainingContextSubstitution},
61 {GSUB_TYPE_EXTENSION_SUBSTITUTION, ParseExtensionSubstitution}, 61 {GSUB_TYPE_EXTENSION_SUBSTITUTION, ParseExtensionSubstitution},
62 {GSUB_TYPE_REVERSE_CHAINING_CONTEXT_SINGLE, 62 {GSUB_TYPE_REVERSE_CHAINING_CONTEXT_SINGLE,
63 ParseReverseChainingContextSingleSubstitution} 63 ParseReverseChainingContextSingleSubstitution}
64 }; 64 };
65 65
66 const ots::LookupSubtableParser kGsubLookupSubtableParser = { 66 const ots::LookupSubtableParser kGsubLookupSubtableParser = {
67 arraysize(kGsubTypeParsers), 67 arraysize(kGsubTypeParsers),
68 GSUB_TYPE_EXTENSION_SUBSTITUTION, kGsubTypeParsers 68 GSUB_TYPE_EXTENSION_SUBSTITUTION, kGsubTypeParsers
69 }; 69 };
70 70
71 // Lookup Type 1: 71 // Lookup Type 1:
72 // Single Substitution Subtable 72 // Single Substitution Subtable
73 bool ParseSingleSubstitution(const ots::OpenTypeFile *file, 73 bool ParseSingleSubstitution(const ots::Font *font,
74 const uint8_t *data, const size_t length) { 74 const uint8_t *data, const size_t length) {
75 ots::Buffer subtable(data, length); 75 ots::Buffer subtable(data, length);
76 76
77 uint16_t format = 0; 77 uint16_t format = 0;
78 uint16_t offset_coverage = 0; 78 uint16_t offset_coverage = 0;
79 79
80 if (!subtable.ReadU16(&format) || 80 if (!subtable.ReadU16(&format) ||
81 !subtable.ReadU16(&offset_coverage)) { 81 !subtable.ReadU16(&offset_coverage)) {
82 return OTS_FAILURE_MSG("Failed to read single subst table header"); 82 return OTS_FAILURE_MSG("Failed to read single subst table header");
83 } 83 }
84 84
85 const uint16_t num_glyphs = file->maxp->num_glyphs; 85 const uint16_t num_glyphs = font->maxp->num_glyphs;
86 if (format == 1) { 86 if (format == 1) {
87 // Parse SingleSubstFormat1 87 // Parse SingleSubstFormat1
88 int16_t delta_glyph_id = 0; 88 int16_t delta_glyph_id = 0;
89 if (!subtable.ReadS16(&delta_glyph_id)) { 89 if (!subtable.ReadS16(&delta_glyph_id)) {
90 return OTS_FAILURE_MSG("Failed to read glyph shift from format 1 single su bst table"); 90 return OTS_FAILURE_MSG("Failed to read glyph shift from format 1 single su bst table");
91 } 91 }
92 if (std::abs(delta_glyph_id) >= num_glyphs) { 92 if (std::abs(delta_glyph_id) >= num_glyphs) {
93 return OTS_FAILURE_MSG("bad glyph shift of %d in format 1 single subst tab le", delta_glyph_id); 93 return OTS_FAILURE_MSG("bad glyph shift of %d in format 1 single subst tab le", delta_glyph_id);
94 } 94 }
95 } else if (format == 2) { 95 } else if (format == 2) {
(...skipping 14 matching lines...) Expand all
110 return OTS_FAILURE_MSG("too large substitute: %u", substitute); 110 return OTS_FAILURE_MSG("too large substitute: %u", substitute);
111 } 111 }
112 } 112 }
113 } else { 113 } else {
114 return OTS_FAILURE_MSG("Bad single subst table format %d", format); 114 return OTS_FAILURE_MSG("Bad single subst table format %d", format);
115 } 115 }
116 116
117 if (offset_coverage < subtable.offset() || offset_coverage >= length) { 117 if (offset_coverage < subtable.offset() || offset_coverage >= length) {
118 return OTS_FAILURE_MSG("Bad coverage offset %x", offset_coverage); 118 return OTS_FAILURE_MSG("Bad coverage offset %x", offset_coverage);
119 } 119 }
120 if (!ots::ParseCoverageTable(file, data + offset_coverage, 120 if (!ots::ParseCoverageTable(font, data + offset_coverage,
121 length - offset_coverage, num_glyphs)) { 121 length - offset_coverage, num_glyphs)) {
122 return OTS_FAILURE_MSG("Failed to parse coverage table"); 122 return OTS_FAILURE_MSG("Failed to parse coverage table");
123 } 123 }
124 124
125 return true; 125 return true;
126 } 126 }
127 127
128 bool ParseSequenceTable(const ots::OpenTypeFile *file, 128 bool ParseSequenceTable(const ots::Font *font,
129 const uint8_t *data, const size_t length, 129 const uint8_t *data, const size_t length,
130 const uint16_t num_glyphs) { 130 const uint16_t num_glyphs) {
131 ots::Buffer subtable(data, length); 131 ots::Buffer subtable(data, length);
132 132
133 uint16_t glyph_count = 0; 133 uint16_t glyph_count = 0;
134 if (!subtable.ReadU16(&glyph_count)) { 134 if (!subtable.ReadU16(&glyph_count)) {
135 return OTS_FAILURE_MSG("Failed to read glyph count in sequence table"); 135 return OTS_FAILURE_MSG("Failed to read glyph count in sequence table");
136 } 136 }
137 if (glyph_count > num_glyphs) { 137 if (glyph_count > num_glyphs) {
138 return OTS_FAILURE_MSG("bad glyph count %d > %d", glyph_count, num_glyphs); 138 return OTS_FAILURE_MSG("bad glyph count %d > %d", glyph_count, num_glyphs);
139 } 139 }
140 for (unsigned i = 0; i < glyph_count; ++i) { 140 for (unsigned i = 0; i < glyph_count; ++i) {
141 uint16_t substitute = 0; 141 uint16_t substitute = 0;
142 if (!subtable.ReadU16(&substitute)) { 142 if (!subtable.ReadU16(&substitute)) {
143 return OTS_FAILURE_MSG("Failedt o read substitution %d in sequence table", i); 143 return OTS_FAILURE_MSG("Failedt o read substitution %d in sequence table", i);
144 } 144 }
145 if (substitute >= num_glyphs) { 145 if (substitute >= num_glyphs) {
146 return OTS_FAILURE_MSG("Bad subsitution (%d) %d > %d", i, substitute, num_ glyphs); 146 return OTS_FAILURE_MSG("Bad subsitution (%d) %d > %d", i, substitute, num_ glyphs);
147 } 147 }
148 } 148 }
149 149
150 return true; 150 return true;
151 } 151 }
152 152
153 // Lookup Type 2: 153 // Lookup Type 2:
154 // Multiple Substitution Subtable 154 // Multiple Substitution Subtable
155 bool ParseMutipleSubstitution(const ots::OpenTypeFile *file, 155 bool ParseMutipleSubstitution(const ots::Font *font,
156 const uint8_t *data, const size_t length) { 156 const uint8_t *data, const size_t length) {
157 ots::Buffer subtable(data, length); 157 ots::Buffer subtable(data, length);
158 158
159 uint16_t format = 0; 159 uint16_t format = 0;
160 uint16_t offset_coverage = 0; 160 uint16_t offset_coverage = 0;
161 uint16_t sequence_count = 0; 161 uint16_t sequence_count = 0;
162 162
163 if (!subtable.ReadU16(&format) || 163 if (!subtable.ReadU16(&format) ||
164 !subtable.ReadU16(&offset_coverage) || 164 !subtable.ReadU16(&offset_coverage) ||
165 !subtable.ReadU16(&sequence_count)) { 165 !subtable.ReadU16(&sequence_count)) {
166 return OTS_FAILURE_MSG("Can't read header of multiple subst table"); 166 return OTS_FAILURE_MSG("Can't read header of multiple subst table");
167 } 167 }
168 168
169 if (format != 1) { 169 if (format != 1) {
170 return OTS_FAILURE_MSG("Bad multiple subst table format %d", format); 170 return OTS_FAILURE_MSG("Bad multiple subst table format %d", format);
171 } 171 }
172 172
173 const uint16_t num_glyphs = file->maxp->num_glyphs; 173 const uint16_t num_glyphs = font->maxp->num_glyphs;
174 const unsigned sequence_end = static_cast<unsigned>(6) + 174 const unsigned sequence_end = static_cast<unsigned>(6) +
175 sequence_count * 2; 175 sequence_count * 2;
176 if (sequence_end > std::numeric_limits<uint16_t>::max()) { 176 if (sequence_end > std::numeric_limits<uint16_t>::max()) {
177 return OTS_FAILURE_MSG("Bad segence end %d, in multiple subst", sequence_end ); 177 return OTS_FAILURE_MSG("Bad segence end %d, in multiple subst", sequence_end );
178 } 178 }
179 for (unsigned i = 0; i < sequence_count; ++i) { 179 for (unsigned i = 0; i < sequence_count; ++i) {
180 uint16_t offset_sequence = 0; 180 uint16_t offset_sequence = 0;
181 if (!subtable.ReadU16(&offset_sequence)) { 181 if (!subtable.ReadU16(&offset_sequence)) {
182 return OTS_FAILURE_MSG("Failed to read sequence offset for sequence %d", i ); 182 return OTS_FAILURE_MSG("Failed to read sequence offset for sequence %d", i );
183 } 183 }
184 if (offset_sequence < sequence_end || offset_sequence >= length) { 184 if (offset_sequence < sequence_end || offset_sequence >= length) {
185 return OTS_FAILURE_MSG("Bad sequence offset %d for sequence %d", offset_se quence, i); 185 return OTS_FAILURE_MSG("Bad sequence offset %d for sequence %d", offset_se quence, i);
186 } 186 }
187 if (!ParseSequenceTable(file, data + offset_sequence, length - offset_sequen ce, 187 if (!ParseSequenceTable(font, data + offset_sequence, length - offset_sequen ce,
188 num_glyphs)) { 188 num_glyphs)) {
189 return OTS_FAILURE_MSG("Failed to parse sequence table %d", i); 189 return OTS_FAILURE_MSG("Failed to parse sequence table %d", i);
190 } 190 }
191 } 191 }
192 192
193 if (offset_coverage < sequence_end || offset_coverage >= length) { 193 if (offset_coverage < sequence_end || offset_coverage >= length) {
194 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage); 194 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage);
195 } 195 }
196 if (!ots::ParseCoverageTable(file, data + offset_coverage, 196 if (!ots::ParseCoverageTable(font, data + offset_coverage,
197 length - offset_coverage, num_glyphs)) { 197 length - offset_coverage, num_glyphs)) {
198 return OTS_FAILURE_MSG("Failed to parse coverage table"); 198 return OTS_FAILURE_MSG("Failed to parse coverage table");
199 } 199 }
200 200
201 return true; 201 return true;
202 } 202 }
203 203
204 bool ParseAlternateSetTable(const ots::OpenTypeFile *file, 204 bool ParseAlternateSetTable(const ots::Font *font,
205 const uint8_t *data, const size_t length, 205 const uint8_t *data, const size_t length,
206 const uint16_t num_glyphs) { 206 const uint16_t num_glyphs) {
207 ots::Buffer subtable(data, length); 207 ots::Buffer subtable(data, length);
208 208
209 uint16_t glyph_count = 0; 209 uint16_t glyph_count = 0;
210 if (!subtable.ReadU16(&glyph_count)) { 210 if (!subtable.ReadU16(&glyph_count)) {
211 return OTS_FAILURE_MSG("Failed to read alternate set header"); 211 return OTS_FAILURE_MSG("Failed to read alternate set header");
212 } 212 }
213 if (glyph_count > num_glyphs) { 213 if (glyph_count > num_glyphs) {
214 return OTS_FAILURE_MSG("Bad glyph count %d > %d in alternate set table", gly ph_count, num_glyphs); 214 return OTS_FAILURE_MSG("Bad glyph count %d > %d in alternate set table", gly ph_count, num_glyphs);
215 } 215 }
216 for (unsigned i = 0; i < glyph_count; ++i) { 216 for (unsigned i = 0; i < glyph_count; ++i) {
217 uint16_t alternate = 0; 217 uint16_t alternate = 0;
218 if (!subtable.ReadU16(&alternate)) { 218 if (!subtable.ReadU16(&alternate)) {
219 return OTS_FAILURE_MSG("Can't read alternate %d", i); 219 return OTS_FAILURE_MSG("Can't read alternate %d", i);
220 } 220 }
221 if (alternate >= num_glyphs) { 221 if (alternate >= num_glyphs) {
222 return OTS_FAILURE_MSG("Too large alternate: %u", alternate); 222 return OTS_FAILURE_MSG("Too large alternate: %u", alternate);
223 } 223 }
224 } 224 }
225 return true; 225 return true;
226 } 226 }
227 227
228 // Lookup Type 3: 228 // Lookup Type 3:
229 // Alternate Substitution Subtable 229 // Alternate Substitution Subtable
230 bool ParseAlternateSubstitution(const ots::OpenTypeFile *file, 230 bool ParseAlternateSubstitution(const ots::Font *font,
231 const uint8_t *data, const size_t length) { 231 const uint8_t *data, const size_t length) {
232 ots::Buffer subtable(data, length); 232 ots::Buffer subtable(data, length);
233 233
234 uint16_t format = 0; 234 uint16_t format = 0;
235 uint16_t offset_coverage = 0; 235 uint16_t offset_coverage = 0;
236 uint16_t alternate_set_count = 0; 236 uint16_t alternate_set_count = 0;
237 237
238 if (!subtable.ReadU16(&format) || 238 if (!subtable.ReadU16(&format) ||
239 !subtable.ReadU16(&offset_coverage) || 239 !subtable.ReadU16(&offset_coverage) ||
240 !subtable.ReadU16(&alternate_set_count)) { 240 !subtable.ReadU16(&alternate_set_count)) {
241 return OTS_FAILURE_MSG("Can't read alternate subst header"); 241 return OTS_FAILURE_MSG("Can't read alternate subst header");
242 } 242 }
243 243
244 if (format != 1) { 244 if (format != 1) {
245 return OTS_FAILURE_MSG("Bad alternate subst table format %d", format); 245 return OTS_FAILURE_MSG("Bad alternate subst table format %d", format);
246 } 246 }
247 247
248 const uint16_t num_glyphs = file->maxp->num_glyphs; 248 const uint16_t num_glyphs = font->maxp->num_glyphs;
249 const unsigned alternate_set_end = static_cast<unsigned>(6) + 249 const unsigned alternate_set_end = static_cast<unsigned>(6) +
250 alternate_set_count * 2; 250 alternate_set_count * 2;
251 if (alternate_set_end > std::numeric_limits<uint16_t>::max()) { 251 if (alternate_set_end > std::numeric_limits<uint16_t>::max()) {
252 return OTS_FAILURE_MSG("Bad end of alternate set %d", alternate_set_end); 252 return OTS_FAILURE_MSG("Bad end of alternate set %d", alternate_set_end);
253 } 253 }
254 for (unsigned i = 0; i < alternate_set_count; ++i) { 254 for (unsigned i = 0; i < alternate_set_count; ++i) {
255 uint16_t offset_alternate_set = 0; 255 uint16_t offset_alternate_set = 0;
256 if (!subtable.ReadU16(&offset_alternate_set)) { 256 if (!subtable.ReadU16(&offset_alternate_set)) {
257 return OTS_FAILURE_MSG("Can't read alternate set offset for set %d", i); 257 return OTS_FAILURE_MSG("Can't read alternate set offset for set %d", i);
258 } 258 }
259 if (offset_alternate_set < alternate_set_end || 259 if (offset_alternate_set < alternate_set_end ||
260 offset_alternate_set >= length) { 260 offset_alternate_set >= length) {
261 return OTS_FAILURE_MSG("Bad alternate set offset %d for set %d", offset_al ternate_set, i); 261 return OTS_FAILURE_MSG("Bad alternate set offset %d for set %d", offset_al ternate_set, i);
262 } 262 }
263 if (!ParseAlternateSetTable(file, data + offset_alternate_set, 263 if (!ParseAlternateSetTable(font, data + offset_alternate_set,
264 length - offset_alternate_set, 264 length - offset_alternate_set,
265 num_glyphs)) { 265 num_glyphs)) {
266 return OTS_FAILURE_MSG("Failed to parse alternate set"); 266 return OTS_FAILURE_MSG("Failed to parse alternate set");
267 } 267 }
268 } 268 }
269 269
270 if (offset_coverage < alternate_set_end || offset_coverage >= length) { 270 if (offset_coverage < alternate_set_end || offset_coverage >= length) {
271 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage); 271 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage);
272 } 272 }
273 if (!ots::ParseCoverageTable(file, data + offset_coverage, 273 if (!ots::ParseCoverageTable(font, data + offset_coverage,
274 length - offset_coverage, num_glyphs)) { 274 length - offset_coverage, num_glyphs)) {
275 return OTS_FAILURE_MSG("Failed to parse coverage table"); 275 return OTS_FAILURE_MSG("Failed to parse coverage table");
276 } 276 }
277 277
278 return true; 278 return true;
279 } 279 }
280 280
281 bool ParseLigatureTable(const ots::OpenTypeFile *file, 281 bool ParseLigatureTable(const ots::Font *font,
282 const uint8_t *data, const size_t length, 282 const uint8_t *data, const size_t length,
283 const uint16_t num_glyphs) { 283 const uint16_t num_glyphs) {
284 ots::Buffer subtable(data, length); 284 ots::Buffer subtable(data, length);
285 285
286 uint16_t lig_glyph = 0; 286 uint16_t lig_glyph = 0;
287 uint16_t comp_count = 0; 287 uint16_t comp_count = 0;
288 288
289 if (!subtable.ReadU16(&lig_glyph) || 289 if (!subtable.ReadU16(&lig_glyph) ||
290 !subtable.ReadU16(&comp_count)) { 290 !subtable.ReadU16(&comp_count)) {
291 return OTS_FAILURE_MSG("Failed to read ligatuer table header"); 291 return OTS_FAILURE_MSG("Failed to read ligatuer table header");
(...skipping 11 matching lines...) Expand all
303 return OTS_FAILURE_MSG("Can't read ligature component %d", i); 303 return OTS_FAILURE_MSG("Can't read ligature component %d", i);
304 } 304 }
305 if (component >= num_glyphs) { 305 if (component >= num_glyphs) {
306 return OTS_FAILURE_MSG("Bad ligature component %d of %d", i, component); 306 return OTS_FAILURE_MSG("Bad ligature component %d of %d", i, component);
307 } 307 }
308 } 308 }
309 309
310 return true; 310 return true;
311 } 311 }
312 312
313 bool ParseLigatureSetTable(const ots::OpenTypeFile *file, 313 bool ParseLigatureSetTable(const ots::Font *font,
314 const uint8_t *data, const size_t length, 314 const uint8_t *data, const size_t length,
315 const uint16_t num_glyphs) { 315 const uint16_t num_glyphs) {
316 ots::Buffer subtable(data, length); 316 ots::Buffer subtable(data, length);
317 317
318 uint16_t ligature_count = 0; 318 uint16_t ligature_count = 0;
319 319
320 if (!subtable.ReadU16(&ligature_count)) { 320 if (!subtable.ReadU16(&ligature_count)) {
321 return OTS_FAILURE_MSG("Can't read ligature count in ligature set"); 321 return OTS_FAILURE_MSG("Can't read ligature count in ligature set");
322 } 322 }
323 323
324 const unsigned ligature_end = static_cast<unsigned>(2) + ligature_count * 2; 324 const unsigned ligature_end = static_cast<unsigned>(2) + ligature_count * 2;
325 if (ligature_end > std::numeric_limits<uint16_t>::max()) { 325 if (ligature_end > std::numeric_limits<uint16_t>::max()) {
326 return OTS_FAILURE_MSG("Bad end of ligature %d in ligature set", ligature_en d); 326 return OTS_FAILURE_MSG("Bad end of ligature %d in ligature set", ligature_en d);
327 } 327 }
328 for (unsigned i = 0; i < ligature_count; ++i) { 328 for (unsigned i = 0; i < ligature_count; ++i) {
329 uint16_t offset_ligature = 0; 329 uint16_t offset_ligature = 0;
330 if (!subtable.ReadU16(&offset_ligature)) { 330 if (!subtable.ReadU16(&offset_ligature)) {
331 return OTS_FAILURE_MSG("Failed to read ligature offset %d", i); 331 return OTS_FAILURE_MSG("Failed to read ligature offset %d", i);
332 } 332 }
333 if (offset_ligature < ligature_end || offset_ligature >= length) { 333 if (offset_ligature < ligature_end || offset_ligature >= length) {
334 return OTS_FAILURE_MSG("Bad ligature offset %d for ligature %d", offset_li gature, i); 334 return OTS_FAILURE_MSG("Bad ligature offset %d for ligature %d", offset_li gature, i);
335 } 335 }
336 if (!ParseLigatureTable(file, data + offset_ligature, length - offset_ligatu re, 336 if (!ParseLigatureTable(font, data + offset_ligature, length - offset_ligatu re,
337 num_glyphs)) { 337 num_glyphs)) {
338 return OTS_FAILURE_MSG("Failed to parse ligature %d", i); 338 return OTS_FAILURE_MSG("Failed to parse ligature %d", i);
339 } 339 }
340 } 340 }
341 341
342 return true; 342 return true;
343 } 343 }
344 344
345 // Lookup Type 4: 345 // Lookup Type 4:
346 // Ligature Substitution Subtable 346 // Ligature Substitution Subtable
347 bool ParseLigatureSubstitution(const ots::OpenTypeFile *file, 347 bool ParseLigatureSubstitution(const ots::Font *font,
348 const uint8_t *data, const size_t length) { 348 const uint8_t *data, const size_t length) {
349 ots::Buffer subtable(data, length); 349 ots::Buffer subtable(data, length);
350 350
351 uint16_t format = 0; 351 uint16_t format = 0;
352 uint16_t offset_coverage = 0; 352 uint16_t offset_coverage = 0;
353 uint16_t lig_set_count = 0; 353 uint16_t lig_set_count = 0;
354 354
355 if (!subtable.ReadU16(&format) || 355 if (!subtable.ReadU16(&format) ||
356 !subtable.ReadU16(&offset_coverage) || 356 !subtable.ReadU16(&offset_coverage) ||
357 !subtable.ReadU16(&lig_set_count)) { 357 !subtable.ReadU16(&lig_set_count)) {
358 return OTS_FAILURE_MSG("Failed to read ligature substitution header"); 358 return OTS_FAILURE_MSG("Failed to read ligature substitution header");
359 } 359 }
360 360
361 if (format != 1) { 361 if (format != 1) {
362 return OTS_FAILURE_MSG("Bad ligature substitution table format %d", format); 362 return OTS_FAILURE_MSG("Bad ligature substitution table format %d", format);
363 } 363 }
364 364
365 const uint16_t num_glyphs = file->maxp->num_glyphs; 365 const uint16_t num_glyphs = font->maxp->num_glyphs;
366 const unsigned ligature_set_end = static_cast<unsigned>(6) + 366 const unsigned ligature_set_end = static_cast<unsigned>(6) +
367 lig_set_count * 2; 367 lig_set_count * 2;
368 if (ligature_set_end > std::numeric_limits<uint16_t>::max()) { 368 if (ligature_set_end > std::numeric_limits<uint16_t>::max()) {
369 return OTS_FAILURE_MSG("Bad end of ligature set %d in ligature substitution table", ligature_set_end); 369 return OTS_FAILURE_MSG("Bad end of ligature set %d in ligature substitution table", ligature_set_end);
370 } 370 }
371 for (unsigned i = 0; i < lig_set_count; ++i) { 371 for (unsigned i = 0; i < lig_set_count; ++i) {
372 uint16_t offset_ligature_set = 0; 372 uint16_t offset_ligature_set = 0;
373 if (!subtable.ReadU16(&offset_ligature_set)) { 373 if (!subtable.ReadU16(&offset_ligature_set)) {
374 return OTS_FAILURE_MSG("Can't read ligature set offset %d", i); 374 return OTS_FAILURE_MSG("Can't read ligature set offset %d", i);
375 } 375 }
376 if (offset_ligature_set < ligature_set_end || 376 if (offset_ligature_set < ligature_set_end ||
377 offset_ligature_set >= length) { 377 offset_ligature_set >= length) {
378 return OTS_FAILURE_MSG("Bad ligature set offset %d for set %d", offset_lig ature_set, i); 378 return OTS_FAILURE_MSG("Bad ligature set offset %d for set %d", offset_lig ature_set, i);
379 } 379 }
380 if (!ParseLigatureSetTable(file, data + offset_ligature_set, 380 if (!ParseLigatureSetTable(font, data + offset_ligature_set,
381 length - offset_ligature_set, num_glyphs)) { 381 length - offset_ligature_set, num_glyphs)) {
382 return OTS_FAILURE_MSG("Failed to parse ligature set %d", i); 382 return OTS_FAILURE_MSG("Failed to parse ligature set %d", i);
383 } 383 }
384 } 384 }
385 385
386 if (offset_coverage < ligature_set_end || offset_coverage >= length) { 386 if (offset_coverage < ligature_set_end || offset_coverage >= length) {
387 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage); 387 return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage);
388 } 388 }
389 if (!ots::ParseCoverageTable(file, data + offset_coverage, 389 if (!ots::ParseCoverageTable(font, data + offset_coverage,
390 length - offset_coverage, num_glyphs)) { 390 length - offset_coverage, num_glyphs)) {
391 return OTS_FAILURE_MSG("Failed to parse coverage table"); 391 return OTS_FAILURE_MSG("Failed to parse coverage table");
392 } 392 }
393 393
394 return true; 394 return true;
395 } 395 }
396 396
397 // Lookup Type 5: 397 // Lookup Type 5:
398 // Contextual Substitution Subtable 398 // Contextual Substitution Subtable
399 bool ParseContextSubstitution(const ots::OpenTypeFile *file, 399 bool ParseContextSubstitution(const ots::Font *font,
400 const uint8_t *data, const size_t length) { 400 const uint8_t *data, const size_t length) {
401 return ots::ParseContextSubtable(file, data, length, file->maxp->num_glyphs, 401 return ots::ParseContextSubtable(font, data, length, font->maxp->num_glyphs,
402 file->gsub->num_lookups); 402 font->gsub->num_lookups);
403 } 403 }
404 404
405 // Lookup Type 6: 405 // Lookup Type 6:
406 // Chaining Contextual Substitution Subtable 406 // Chaining Contextual Substitution Subtable
407 bool ParseChainingContextSubstitution(const ots::OpenTypeFile *file, 407 bool ParseChainingContextSubstitution(const ots::Font *font,
408 const uint8_t *data, 408 const uint8_t *data,
409 const size_t length) { 409 const size_t length) {
410 return ots::ParseChainingContextSubtable(file, data, length, 410 return ots::ParseChainingContextSubtable(font, data, length,
411 file->maxp->num_glyphs, 411 font->maxp->num_glyphs,
412 file->gsub->num_lookups); 412 font->gsub->num_lookups);
413 } 413 }
414 414
415 // Lookup Type 7: 415 // Lookup Type 7:
416 // Extension Substition 416 // Extension Substition
417 bool ParseExtensionSubstitution(const ots::OpenTypeFile *file, 417 bool ParseExtensionSubstitution(const ots::Font *font,
418 const uint8_t *data, const size_t length) { 418 const uint8_t *data, const size_t length) {
419 return ots::ParseExtensionSubtable(file, data, length, 419 return ots::ParseExtensionSubtable(font, data, length,
420 &kGsubLookupSubtableParser); 420 &kGsubLookupSubtableParser);
421 } 421 }
422 422
423 // Lookup Type 8: 423 // Lookup Type 8:
424 // Reverse Chaining Contexual Single Substitution Subtable 424 // Reverse Chaining Contexual Single Substitution Subtable
425 bool ParseReverseChainingContextSingleSubstitution( 425 bool ParseReverseChainingContextSingleSubstitution(
426 const ots::OpenTypeFile *file, const uint8_t *data, const size_t length) { 426 const ots::Font *font, const uint8_t *data, const size_t length) {
427 ots::Buffer subtable(data, length); 427 ots::Buffer subtable(data, length);
428 428
429 uint16_t format = 0; 429 uint16_t format = 0;
430 uint16_t offset_coverage = 0; 430 uint16_t offset_coverage = 0;
431 431
432 if (!subtable.ReadU16(&format) || 432 if (!subtable.ReadU16(&format) ||
433 !subtable.ReadU16(&offset_coverage)) { 433 !subtable.ReadU16(&offset_coverage)) {
434 return OTS_FAILURE_MSG("Failed to read reverse chaining header"); 434 return OTS_FAILURE_MSG("Failed to read reverse chaining header");
435 } 435 }
436 436
437 const uint16_t num_glyphs = file->maxp->num_glyphs; 437 const uint16_t num_glyphs = font->maxp->num_glyphs;
438 438
439 uint16_t backtrack_glyph_count = 0; 439 uint16_t backtrack_glyph_count = 0;
440 if (!subtable.ReadU16(&backtrack_glyph_count)) { 440 if (!subtable.ReadU16(&backtrack_glyph_count)) {
441 return OTS_FAILURE_MSG("Failed to read backtrack glyph count in reverse chai ning table"); 441 return OTS_FAILURE_MSG("Failed to read backtrack glyph count in reverse chai ning table");
442 } 442 }
443 if (backtrack_glyph_count > num_glyphs) { 443 if (backtrack_glyph_count > num_glyphs) {
444 return OTS_FAILURE_MSG("Bad backtrack glyph count of %d", backtrack_glyph_co unt); 444 return OTS_FAILURE_MSG("Bad backtrack glyph count of %d", backtrack_glyph_co unt);
445 } 445 }
446 std::vector<uint16_t> offsets_backtrack; 446 std::vector<uint16_t> offsets_backtrack;
447 offsets_backtrack.reserve(backtrack_glyph_count); 447 offsets_backtrack.reserve(backtrack_glyph_count);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 489
490 const unsigned substitute_end = static_cast<unsigned>(10) + 490 const unsigned substitute_end = static_cast<unsigned>(10) +
491 (backtrack_glyph_count + lookahead_glyph_count + glyph_count) * 2; 491 (backtrack_glyph_count + lookahead_glyph_count + glyph_count) * 2;
492 if (substitute_end > std::numeric_limits<uint16_t>::max()) { 492 if (substitute_end > std::numeric_limits<uint16_t>::max()) {
493 return OTS_FAILURE_MSG("Bad substitute end offset in reverse chaining table" ); 493 return OTS_FAILURE_MSG("Bad substitute end offset in reverse chaining table" );
494 } 494 }
495 495
496 if (offset_coverage < substitute_end || offset_coverage >= length) { 496 if (offset_coverage < substitute_end || offset_coverage >= length) {
497 return OTS_FAILURE_MSG("Bad coverage offset %d in reverse chaining table", o ffset_coverage); 497 return OTS_FAILURE_MSG("Bad coverage offset %d in reverse chaining table", o ffset_coverage);
498 } 498 }
499 if (!ots::ParseCoverageTable(file, data + offset_coverage, 499 if (!ots::ParseCoverageTable(font, data + offset_coverage,
500 length - offset_coverage, num_glyphs)) { 500 length - offset_coverage, num_glyphs)) {
501 return OTS_FAILURE_MSG("Failed to parse coverage table in reverse chaining t able"); 501 return OTS_FAILURE_MSG("Failed to parse coverage table in reverse chaining t able");
502 } 502 }
503 503
504 for (unsigned i = 0; i < backtrack_glyph_count; ++i) { 504 for (unsigned i = 0; i < backtrack_glyph_count; ++i) {
505 if (offsets_backtrack[i] < substitute_end || 505 if (offsets_backtrack[i] < substitute_end ||
506 offsets_backtrack[i] >= length) { 506 offsets_backtrack[i] >= length) {
507 return OTS_FAILURE_MSG("Bad backtrack offset %d for backtrack %d in revers e chaining table", offsets_backtrack[i], i); 507 return OTS_FAILURE_MSG("Bad backtrack offset %d for backtrack %d in revers e chaining table", offsets_backtrack[i], i);
508 } 508 }
509 if (!ots::ParseCoverageTable(file, data + offsets_backtrack[i], 509 if (!ots::ParseCoverageTable(font, data + offsets_backtrack[i],
510 length - offsets_backtrack[i], num_glyphs)) { 510 length - offsets_backtrack[i], num_glyphs)) {
511 return OTS_FAILURE_MSG("Failed to parse coverage table for backtrack %d in reverse chaining table", i); 511 return OTS_FAILURE_MSG("Failed to parse coverage table for backtrack %d in reverse chaining table", i);
512 } 512 }
513 } 513 }
514 514
515 for (unsigned i = 0; i < lookahead_glyph_count; ++i) { 515 for (unsigned i = 0; i < lookahead_glyph_count; ++i) {
516 if (offsets_lookahead[i] < substitute_end || 516 if (offsets_lookahead[i] < substitute_end ||
517 offsets_lookahead[i] >= length) { 517 offsets_lookahead[i] >= length) {
518 return OTS_FAILURE_MSG("Bad lookahead offset %d for lookahead %d in revers e chaining table", offsets_lookahead[i], i); 518 return OTS_FAILURE_MSG("Bad lookahead offset %d for lookahead %d in revers e chaining table", offsets_lookahead[i], i);
519 } 519 }
520 if (!ots::ParseCoverageTable(file, data + offsets_lookahead[i], 520 if (!ots::ParseCoverageTable(font, data + offsets_lookahead[i],
521 length - offsets_lookahead[i], num_glyphs)) { 521 length - offsets_lookahead[i], num_glyphs)) {
522 return OTS_FAILURE_MSG("Failed to parse lookahead coverage table %d in rev erse chaining table", i); 522 return OTS_FAILURE_MSG("Failed to parse lookahead coverage table %d in rev erse chaining table", i);
523 } 523 }
524 } 524 }
525 525
526 return true; 526 return true;
527 } 527 }
528 528
529 } // namespace 529 } // namespace
530 530
531 #define DROP_THIS_TABLE(msg_) \ 531 #define DROP_THIS_TABLE(msg_) \
532 do { \ 532 do { \
533 OTS_FAILURE_MSG(msg_ ", table discarded"); \ 533 OTS_FAILURE_MSG(msg_ ", table discarded"); \
534 file->gsub->data = 0; \ 534 font->gsub->data = 0; \
535 file->gsub->length = 0; \ 535 font->gsub->length = 0; \
536 } while (0) 536 } while (0)
537 537
538 namespace ots { 538 namespace ots {
539 539
540 // As far as I checked, following fonts contain invalid values in GSUB table. 540 // As far as I checked, following fonts contain invalid values in GSUB table.
541 // OTS will drop their GSUB table. 541 // OTS will drop their GSUB table.
542 // 542 //
543 // # too large substitute (value is 0xFFFF) 543 // # too large substitute (value is 0xFFFF)
544 // kaiu.ttf 544 // kaiu.ttf
545 // mingliub2.ttf 545 // mingliub2.ttf
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 // KacstTitleL.ttf 580 // KacstTitleL.ttf
581 // KacstDecorative.ttf 581 // KacstDecorative.ttf
582 // KacstTitle.ttf 582 // KacstTitle.ttf
583 // KacstArt.ttf 583 // KacstArt.ttf
584 // KacstPoster.ttf 584 // KacstPoster.ttf
585 // KacstQurn.ttf 585 // KacstQurn.ttf
586 // KacstDigital.ttf 586 // KacstDigital.ttf
587 // KacstBook.ttf 587 // KacstBook.ttf
588 // KacstFarsi.ttf 588 // KacstFarsi.ttf
589 589
590 bool ots_gsub_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 590 bool ots_gsub_parse(Font *font, const uint8_t *data, size_t length) {
591 // Parsing gsub table requires |file->maxp->num_glyphs| 591 // Parsing gsub table requires |font->maxp->num_glyphs|
592 if (!file->maxp) { 592 if (!font->maxp) {
593 return OTS_FAILURE_MSG("Missing maxp table in font, needed by GSUB"); 593 return OTS_FAILURE_MSG("Missing maxp table in font, needed by GSUB");
594 } 594 }
595 595
596 Buffer table(data, length); 596 Buffer table(data, length);
597 597
598 OpenTypeGSUB *gsub = new OpenTypeGSUB; 598 OpenTypeGSUB *gsub = new OpenTypeGSUB;
599 file->gsub = gsub; 599 font->gsub = gsub;
600 600
601 uint32_t version = 0; 601 uint32_t version = 0;
602 uint16_t offset_script_list = 0; 602 uint16_t offset_script_list = 0;
603 uint16_t offset_feature_list = 0; 603 uint16_t offset_feature_list = 0;
604 uint16_t offset_lookup_list = 0; 604 uint16_t offset_lookup_list = 0;
605 if (!table.ReadU32(&version) || 605 if (!table.ReadU32(&version) ||
606 !table.ReadU16(&offset_script_list) || 606 !table.ReadU16(&offset_script_list) ||
607 !table.ReadU16(&offset_feature_list) || 607 !table.ReadU16(&offset_feature_list) ||
608 !table.ReadU16(&offset_lookup_list)) { 608 !table.ReadU16(&offset_lookup_list)) {
609 DROP_THIS_TABLE("Incomplete table"); 609 DROP_THIS_TABLE("Incomplete table");
610 return true; 610 return true;
611 } 611 }
612 612
613 if (version != 0x00010000) { 613 if (version != 0x00010000) {
614 DROP_THIS_TABLE("Bad version"); 614 DROP_THIS_TABLE("Bad version");
615 return true; 615 return true;
616 } 616 }
617 617
618 if (offset_lookup_list) { 618 if (offset_lookup_list) {
619 if (offset_lookup_list < kGsubHeaderSize || offset_lookup_list >= length) { 619 if (offset_lookup_list < kGsubHeaderSize || offset_lookup_list >= length) {
620 DROP_THIS_TABLE("Bad lookup list offset in table header"); 620 DROP_THIS_TABLE("Bad lookup list offset in table header");
621 return true; 621 return true;
622 } 622 }
623 623
624 if (!ParseLookupListTable(file, data + offset_lookup_list, 624 if (!ParseLookupListTable(font, data + offset_lookup_list,
625 length - offset_lookup_list, 625 length - offset_lookup_list,
626 &kGsubLookupSubtableParser, 626 &kGsubLookupSubtableParser,
627 &gsub->num_lookups)) { 627 &gsub->num_lookups)) {
628 DROP_THIS_TABLE("Failed to parse lookup list table"); 628 DROP_THIS_TABLE("Failed to parse lookup list table");
629 return true; 629 return true;
630 } 630 }
631 } 631 }
632 632
633 uint16_t num_features = 0; 633 uint16_t num_features = 0;
634 if (offset_feature_list) { 634 if (offset_feature_list) {
635 if (offset_feature_list < kGsubHeaderSize || offset_feature_list >= length) { 635 if (offset_feature_list < kGsubHeaderSize || offset_feature_list >= length) {
636 DROP_THIS_TABLE("Bad feature list offset in table header"); 636 DROP_THIS_TABLE("Bad feature list offset in table header");
637 return true; 637 return true;
638 } 638 }
639 639
640 if (!ParseFeatureListTable(file, data + offset_feature_list, 640 if (!ParseFeatureListTable(font, data + offset_feature_list,
641 length - offset_feature_list, gsub->num_lookups, 641 length - offset_feature_list, gsub->num_lookups,
642 &num_features)) { 642 &num_features)) {
643 DROP_THIS_TABLE("Failed to parse feature list table"); 643 DROP_THIS_TABLE("Failed to parse feature list table");
644 return true; 644 return true;
645 } 645 }
646 } 646 }
647 647
648 if (offset_script_list) { 648 if (offset_script_list) {
649 if (offset_script_list < kGsubHeaderSize || offset_script_list >= length) { 649 if (offset_script_list < kGsubHeaderSize || offset_script_list >= length) {
650 DROP_THIS_TABLE("Bad script list offset in table header"); 650 DROP_THIS_TABLE("Bad script list offset in table header");
651 return true; 651 return true;
652 } 652 }
653 653
654 if (!ParseScriptListTable(file, data + offset_script_list, 654 if (!ParseScriptListTable(font, data + offset_script_list,
655 length - offset_script_list, num_features)) { 655 length - offset_script_list, num_features)) {
656 DROP_THIS_TABLE("Failed to parse script list table"); 656 DROP_THIS_TABLE("Failed to parse script list table");
657 return true; 657 return true;
658 } 658 }
659 } 659 }
660 660
661 gsub->data = data; 661 gsub->data = data;
662 gsub->length = length; 662 gsub->length = length;
663 return true; 663 return true;
664 } 664 }
665 665
666 bool ots_gsub_should_serialise(OpenTypeFile *file) { 666 bool ots_gsub_should_serialise(Font *font) {
667 return file->gsub != NULL && file->gsub->data != NULL; 667 return font->gsub != NULL && font->gsub->data != NULL;
668 } 668 }
669 669
670 bool ots_gsub_serialise(OTSStream *out, OpenTypeFile *file) { 670 bool ots_gsub_serialise(OTSStream *out, Font *font) {
671 if (!out->Write(file->gsub->data, file->gsub->length)) { 671 if (!out->Write(font->gsub->data, font->gsub->length)) {
672 return OTS_FAILURE_MSG("Failed to write GSUB table"); 672 return OTS_FAILURE_MSG("Failed to write GSUB table");
673 } 673 }
674 674
675 return true; 675 return true;
676 } 676 }
677 677
678 void ots_gsub_free(OpenTypeFile *file) { 678 void ots_gsub_reuse(Font *font, Font *other) {
679 delete file->gsub; 679 font->gsub = other->gsub;
680 font->gsub_reused = true;
681 }
682
683 void ots_gsub_free(Font *font) {
684 delete font->gsub;
680 } 685 }
681 686
682 } // namespace ots 687 } // namespace ots
683 688
684 #undef TABLE_NAME 689 #undef TABLE_NAME
685 #undef DROP_THIS_TABLE 690 #undef DROP_THIS_TABLE
OLDNEW
« no previous file with comments | « third_party/ots/src/gpos.cc ('k') | third_party/ots/src/hdmx.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698