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

Side by Side Diff: third_party/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh

Issue 10510004: Roll harfbuzz-ng 3b8fd9c48f4bde368bf2d465c148b9743a9216ee (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 6 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 /* 1 /*
2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
3 * Copyright © 2010 Google, Inc. 3 * Copyright © 2010,2012 Google, Inc.
4 * 4 *
5 * This is part of HarfBuzz, a text shaping library. 5 * This is part of HarfBuzz, a text shaping library.
6 * 6 *
7 * Permission is hereby granted, without written agreement and without 7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this 8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the 9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in 10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software. 11 * all copies of this software.
12 * 12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
(...skipping 18 matching lines...) Expand all
32 #include "hb-ot-layout-gsubgpos-private.hh" 32 #include "hb-ot-layout-gsubgpos-private.hh"
33 33
34 34
35 35
36 struct SingleSubstFormat1 36 struct SingleSubstFormat1
37 { 37 {
38 friend struct SingleSubst; 38 friend struct SingleSubst;
39 39
40 private: 40 private:
41 41
42 inline void closure (hb_closure_context_t *c) const
43 {
44 TRACE_CLOSURE ();
45 Coverage::Iter iter;
46 for (iter.init (this+coverage); iter.more (); iter.next ()) {
47 hb_codepoint_t glyph_id = iter.get_glyph ();
48 if (c->glyphs->has (glyph_id))
49 c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF);
50 }
51 }
52
53 inline bool would_apply (hb_codepoint_t glyph_id) const
54 {
55 return (this+coverage) (glyph_id) != NOT_COVERED;
56 }
57
42 inline bool apply (hb_apply_context_t *c) const 58 inline bool apply (hb_apply_context_t *c) const
43 { 59 {
44 TRACE_APPLY (); 60 TRACE_APPLY ();
45 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint; 61 hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
46 unsigned int index = (this+coverage) (glyph_id); 62 unsigned int index = (this+coverage) (glyph_id);
47 if (likely (index == NOT_COVERED)) 63 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
48 return false;
49 64
50 /* According to the Adobe Annotated OpenType Suite, result is always 65 /* According to the Adobe Annotated OpenType Suite, result is always
51 * limited to 16bit. */ 66 * limited to 16bit. */
52 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF; 67 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF;
53 c->replace_glyph (glyph_id); 68 c->replace_glyph (glyph_id);
54 69
55 return true; 70 return TRACE_RETURN (true);
56 } 71 }
57 72
58 inline bool sanitize (hb_sanitize_context_t *c) { 73 inline bool sanitize (hb_sanitize_context_t *c) {
59 TRACE_SANITIZE (); 74 TRACE_SANITIZE ();
60 return coverage.sanitize (c, this) 75 return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c ));
61 » && deltaGlyphID.sanitize (c);
62 } 76 }
63 77
64 private: 78 private:
65 USHORT format; /* Format identifier--format = 1 */ 79 USHORT format; /* Format identifier--format = 1 */
66 OffsetTo<Coverage> 80 OffsetTo<Coverage>
67 coverage; /* Offset to Coverage table--from 81 coverage; /* Offset to Coverage table--from
68 * beginning of Substitution table */ 82 * beginning of Substitution table */
69 SHORT deltaGlyphID; /* Add to original GlyphID to get 83 SHORT deltaGlyphID; /* Add to original GlyphID to get
70 * substitute GlyphID */ 84 * substitute GlyphID */
71 public: 85 public:
72 DEFINE_SIZE_STATIC (6); 86 DEFINE_SIZE_STATIC (6);
73 }; 87 };
74 88
75 struct SingleSubstFormat2 89 struct SingleSubstFormat2
76 { 90 {
77 friend struct SingleSubst; 91 friend struct SingleSubst;
78 92
79 private: 93 private:
80 94
95 inline void closure (hb_closure_context_t *c) const
96 {
97 TRACE_CLOSURE ();
98 Coverage::Iter iter;
99 for (iter.init (this+coverage); iter.more (); iter.next ()) {
100 if (c->glyphs->has (iter.get_glyph ()))
101 c->glyphs->add (substitute[iter.get_coverage ()]);
102 }
103 }
104
105 inline bool would_apply (hb_codepoint_t glyph_id) const
106 {
107 return (this+coverage) (glyph_id) != NOT_COVERED;
108 }
109
81 inline bool apply (hb_apply_context_t *c) const 110 inline bool apply (hb_apply_context_t *c) const
82 { 111 {
83 TRACE_APPLY (); 112 TRACE_APPLY ();
84 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint; 113 hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
85 unsigned int index = (this+coverage) (glyph_id); 114 unsigned int index = (this+coverage) (glyph_id);
86 if (likely (index == NOT_COVERED)) 115 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
87 return false;
88 116
89 if (unlikely (index >= substitute.len)) 117 if (unlikely (index >= substitute.len)) return TRACE_RETURN (false);
90 return false;
91 118
92 glyph_id = substitute[index]; 119 glyph_id = substitute[index];
93 c->replace_glyph (glyph_id); 120 c->replace_glyph (glyph_id);
94 121
95 return true; 122 return TRACE_RETURN (true);
96 } 123 }
97 124
98 inline bool sanitize (hb_sanitize_context_t *c) { 125 inline bool sanitize (hb_sanitize_context_t *c) {
99 TRACE_SANITIZE (); 126 TRACE_SANITIZE ();
100 return coverage.sanitize (c, this) 127 return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c)) ;
101 » && substitute.sanitize (c);
102 } 128 }
103 129
104 private: 130 private:
105 USHORT format; /* Format identifier--format = 2 */ 131 USHORT format; /* Format identifier--format = 2 */
106 OffsetTo<Coverage> 132 OffsetTo<Coverage>
107 coverage; /* Offset to Coverage table--from 133 coverage; /* Offset to Coverage table--from
108 * beginning of Substitution table */ 134 * beginning of Substitution table */
109 ArrayOf<GlyphID> 135 ArrayOf<GlyphID>
110 substitute; /* Array of substitute 136 substitute; /* Array of substitute
111 * GlyphIDs--ordered by Coverage Index * / 137 * GlyphIDs--ordered by Coverage Index * /
112 public: 138 public:
113 DEFINE_SIZE_ARRAY (6, substitute); 139 DEFINE_SIZE_ARRAY (6, substitute);
114 }; 140 };
115 141
116 struct SingleSubst 142 struct SingleSubst
117 { 143 {
118 friend struct SubstLookupSubTable; 144 friend struct SubstLookupSubTable;
119 145
120 private: 146 private:
121 147
148 inline void closure (hb_closure_context_t *c) const
149 {
150 TRACE_CLOSURE ();
151 switch (u.format) {
152 case 1: u.format1.closure (c); break;
153 case 2: u.format2.closure (c); break;
154 default: break;
155 }
156 }
157
158 inline bool would_apply (hb_codepoint_t glyph_id) const
159 {
160 switch (u.format) {
161 case 1: return u.format1.would_apply (glyph_id);
162 case 2: return u.format2.would_apply (glyph_id);
163 default:return false;
164 }
165 }
166
122 inline bool apply (hb_apply_context_t *c) const 167 inline bool apply (hb_apply_context_t *c) const
123 { 168 {
124 TRACE_APPLY (); 169 TRACE_APPLY ();
125 switch (u.format) { 170 switch (u.format) {
126 case 1: return u.format1.apply (c); 171 case 1: return TRACE_RETURN (u.format1.apply (c));
127 case 2: return u.format2.apply (c); 172 case 2: return TRACE_RETURN (u.format2.apply (c));
128 default:return false; 173 default:return TRACE_RETURN (false);
129 } 174 }
130 } 175 }
131 176
132 inline bool sanitize (hb_sanitize_context_t *c) { 177 inline bool sanitize (hb_sanitize_context_t *c) {
133 TRACE_SANITIZE (); 178 TRACE_SANITIZE ();
134 if (!u.format.sanitize (c)) return false; 179 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
135 switch (u.format) { 180 switch (u.format) {
136 case 1: return u.format1.sanitize (c); 181 case 1: return TRACE_RETURN (u.format1.sanitize (c));
137 case 2: return u.format2.sanitize (c); 182 case 2: return TRACE_RETURN (u.format2.sanitize (c));
138 default:return true; 183 default:return TRACE_RETURN (true);
139 } 184 }
140 } 185 }
141 186
142 private: 187 private:
143 union { 188 union {
144 USHORT format; /* Format identifier */ 189 USHORT format; /* Format identifier */
145 SingleSubstFormat1 format1; 190 SingleSubstFormat1 format1;
146 SingleSubstFormat2 format2; 191 SingleSubstFormat2 format2;
147 } u; 192 } u;
148 }; 193 };
149 194
150 195
151 struct Sequence 196 struct Sequence
152 { 197 {
153 friend struct MultipleSubstFormat1; 198 friend struct MultipleSubstFormat1;
154 199
155 private: 200 private:
201
202 inline void closure (hb_closure_context_t *c) const
203 {
204 TRACE_CLOSURE ();
205 unsigned int count = substitute.len;
206 for (unsigned int i = 0; i < count; i++)
207 c->glyphs->add (substitute[i]);
208 }
209
156 inline bool apply (hb_apply_context_t *c) const 210 inline bool apply (hb_apply_context_t *c) const
157 { 211 {
158 TRACE_APPLY (); 212 TRACE_APPLY ();
159 if (unlikely (!substitute.len)) 213 if (unlikely (!substitute.len)) return TRACE_RETURN (false);
160 return false;
161 214
162 if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE) 215 unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ? HB_OT _LAYOUT_GLYPH_CLASS_BASE_GLYPH : 0;
163 c->guess_glyph_class (HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH); 216 c->replace_glyphs_be16 (1, substitute.len, (const uint16_t *) substitute.arr ay, klass);
164 c->replace_glyphs_be16 (1, substitute.len, (const uint16_t *) substitute.arr ay);
165 217
166 return true; 218 return TRACE_RETURN (true);
167 } 219 }
168 220
169 public: 221 public:
170 inline bool sanitize (hb_sanitize_context_t *c) { 222 inline bool sanitize (hb_sanitize_context_t *c) {
171 TRACE_SANITIZE (); 223 TRACE_SANITIZE ();
172 return substitute.sanitize (c); 224 return TRACE_RETURN (substitute.sanitize (c));
173 } 225 }
174 226
175 private: 227 private:
176 ArrayOf<GlyphID> 228 ArrayOf<GlyphID>
177 substitute; /* String of GlyphIDs to substitute */ 229 substitute; /* String of GlyphIDs to substitute */
178 public: 230 public:
179 DEFINE_SIZE_ARRAY (2, substitute); 231 DEFINE_SIZE_ARRAY (2, substitute);
180 }; 232 };
181 233
182 struct MultipleSubstFormat1 234 struct MultipleSubstFormat1
183 { 235 {
184 friend struct MultipleSubst; 236 friend struct MultipleSubst;
185 237
186 private: 238 private:
187 239
240 inline void closure (hb_closure_context_t *c) const
241 {
242 TRACE_CLOSURE ();
243 Coverage::Iter iter;
244 for (iter.init (this+coverage); iter.more (); iter.next ()) {
245 if (c->glyphs->has (iter.get_glyph ()))
246 (this+sequence[iter.get_coverage ()]).closure (c);
247 }
248 }
249
250 inline bool would_apply (hb_codepoint_t glyph_id) const
251 {
252 return (this+coverage) (glyph_id) != NOT_COVERED;
253 }
254
188 inline bool apply (hb_apply_context_t *c) const 255 inline bool apply (hb_apply_context_t *c) const
189 { 256 {
190 TRACE_APPLY (); 257 TRACE_APPLY ();
191 258
192 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepo int); 259 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
193 if (likely (index == NOT_COVERED)) 260 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
194 return false;
195 261
196 return (this+sequence[index]).apply (c); 262 return TRACE_RETURN ((this+sequence[index]).apply (c));
197 } 263 }
198 264
199 inline bool sanitize (hb_sanitize_context_t *c) { 265 inline bool sanitize (hb_sanitize_context_t *c) {
200 TRACE_SANITIZE (); 266 TRACE_SANITIZE ();
201 return coverage.sanitize (c, this) 267 return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, th is));
202 » && sequence.sanitize (c, this);
203 } 268 }
204 269
205 private: 270 private:
206 USHORT format; /* Format identifier--format = 1 */ 271 USHORT format; /* Format identifier--format = 1 */
207 OffsetTo<Coverage> 272 OffsetTo<Coverage>
208 coverage; /* Offset to Coverage table--from 273 coverage; /* Offset to Coverage table--from
209 * beginning of Substitution table */ 274 * beginning of Substitution table */
210 OffsetArrayOf<Sequence> 275 OffsetArrayOf<Sequence>
211 sequence; /* Array of Sequence tables 276 sequence; /* Array of Sequence tables
212 * ordered by Coverage Index */ 277 * ordered by Coverage Index */
213 public: 278 public:
214 DEFINE_SIZE_ARRAY (6, sequence); 279 DEFINE_SIZE_ARRAY (6, sequence);
215 }; 280 };
216 281
217 struct MultipleSubst 282 struct MultipleSubst
218 { 283 {
219 friend struct SubstLookupSubTable; 284 friend struct SubstLookupSubTable;
220 285
221 private: 286 private:
222 287
288 inline void closure (hb_closure_context_t *c) const
289 {
290 TRACE_CLOSURE ();
291 switch (u.format) {
292 case 1: u.format1.closure (c); break;
293 default: break;
294 }
295 }
296
297 inline bool would_apply (hb_codepoint_t glyph_id) const
298 {
299 switch (u.format) {
300 case 1: return u.format1.would_apply (glyph_id);
301 default:return false;
302 }
303 }
304
223 inline bool apply (hb_apply_context_t *c) const 305 inline bool apply (hb_apply_context_t *c) const
224 { 306 {
225 TRACE_APPLY (); 307 TRACE_APPLY ();
226 switch (u.format) { 308 switch (u.format) {
227 case 1: return u.format1.apply (c); 309 case 1: return TRACE_RETURN (u.format1.apply (c));
228 default:return false; 310 default:return TRACE_RETURN (false);
229 } 311 }
230 } 312 }
231 313
232 inline bool sanitize (hb_sanitize_context_t *c) { 314 inline bool sanitize (hb_sanitize_context_t *c) {
233 TRACE_SANITIZE (); 315 TRACE_SANITIZE ();
234 if (!u.format.sanitize (c)) return false; 316 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
235 switch (u.format) { 317 switch (u.format) {
236 case 1: return u.format1.sanitize (c); 318 case 1: return TRACE_RETURN (u.format1.sanitize (c));
237 default:return true; 319 default:return TRACE_RETURN (true);
238 } 320 }
239 } 321 }
240 322
241 private: 323 private:
242 union { 324 union {
243 USHORT format; /* Format identifier */ 325 USHORT format; /* Format identifier */
244 MultipleSubstFormat1 format1; 326 MultipleSubstFormat1 format1;
245 } u; 327 } u;
246 }; 328 };
247 329
248 330
249 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in 331 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in
250 * arbitrary order */ 332 * arbitrary order */
251 333
252 struct AlternateSubstFormat1 334 struct AlternateSubstFormat1
253 { 335 {
254 friend struct AlternateSubst; 336 friend struct AlternateSubst;
255 337
256 private: 338 private:
257 339
340 inline void closure (hb_closure_context_t *c) const
341 {
342 TRACE_CLOSURE ();
343 Coverage::Iter iter;
344 for (iter.init (this+coverage); iter.more (); iter.next ()) {
345 if (c->glyphs->has (iter.get_glyph ())) {
346 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
347 unsigned int count = alt_set.len;
348 for (unsigned int i = 0; i < count; i++)
349 c->glyphs->add (alt_set[i]);
350 }
351 }
352 }
353
354 inline bool would_apply (hb_codepoint_t glyph_id) const
355 {
356 return (this+coverage) (glyph_id) != NOT_COVERED;
357 }
358
258 inline bool apply (hb_apply_context_t *c) const 359 inline bool apply (hb_apply_context_t *c) const
259 { 360 {
260 TRACE_APPLY (); 361 TRACE_APPLY ();
261 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint; 362 hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
262 hb_mask_t glyph_mask = c->buffer->info[c->buffer->idx].mask;
263 hb_mask_t lookup_mask = c->lookup_mask;
264 363
265 unsigned int index = (this+coverage) (glyph_id); 364 unsigned int index = (this+coverage) (glyph_id);
266 if (likely (index == NOT_COVERED)) 365 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
267 return false;
268 366
269 const AlternateSet &alt_set = this+alternateSet[index]; 367 const AlternateSet &alt_set = this+alternateSet[index];
270 368
271 if (unlikely (!alt_set.len)) 369 if (unlikely (!alt_set.len)) return TRACE_RETURN (false);
272 return false; 370
371 hb_mask_t glyph_mask = c->buffer->cur().mask;
372 hb_mask_t lookup_mask = c->lookup_mask;
273 373
274 /* Note: This breaks badly if two features enabled this lookup together. */ 374 /* Note: This breaks badly if two features enabled this lookup together. */
275 unsigned int shift = _hb_ctz (lookup_mask); 375 unsigned int shift = _hb_ctz (lookup_mask);
276 unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift); 376 unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
277 377
278 if (unlikely (alt_index > alt_set.len || alt_index == 0)) 378 if (unlikely (alt_index > alt_set.len || alt_index == 0)) return TRACE_RETUR N (false);
279 return false;
280 379
281 glyph_id = alt_set[alt_index - 1]; 380 glyph_id = alt_set[alt_index - 1];
282 381
283 c->replace_glyph (glyph_id); 382 c->replace_glyph (glyph_id);
284 383
285 return true; 384 return TRACE_RETURN (true);
286 } 385 }
287 386
288 inline bool sanitize (hb_sanitize_context_t *c) { 387 inline bool sanitize (hb_sanitize_context_t *c) {
289 TRACE_SANITIZE (); 388 TRACE_SANITIZE ();
290 return coverage.sanitize (c, this) 389 return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c , this));
291 » && alternateSet.sanitize (c, this);
292 } 390 }
293 391
294 private: 392 private:
295 USHORT format; /* Format identifier--format = 1 */ 393 USHORT format; /* Format identifier--format = 1 */
296 OffsetTo<Coverage> 394 OffsetTo<Coverage>
297 coverage; /* Offset to Coverage table--from 395 coverage; /* Offset to Coverage table--from
298 * beginning of Substitution table */ 396 * beginning of Substitution table */
299 OffsetArrayOf<AlternateSet> 397 OffsetArrayOf<AlternateSet>
300 alternateSet; /* Array of AlternateSet tables 398 alternateSet; /* Array of AlternateSet tables
301 * ordered by Coverage Index */ 399 * ordered by Coverage Index */
302 public: 400 public:
303 DEFINE_SIZE_ARRAY (6, alternateSet); 401 DEFINE_SIZE_ARRAY (6, alternateSet);
304 }; 402 };
305 403
306 struct AlternateSubst 404 struct AlternateSubst
307 { 405 {
308 friend struct SubstLookupSubTable; 406 friend struct SubstLookupSubTable;
309 407
310 private: 408 private:
311 409
410 inline void closure (hb_closure_context_t *c) const
411 {
412 TRACE_CLOSURE ();
413 switch (u.format) {
414 case 1: u.format1.closure (c); break;
415 default: break;
416 }
417 }
418
419 inline bool would_apply (hb_codepoint_t glyph_id) const
420 {
421 switch (u.format) {
422 case 1: return u.format1.would_apply (glyph_id);
423 default:return false;
424 }
425 }
426
312 inline bool apply (hb_apply_context_t *c) const 427 inline bool apply (hb_apply_context_t *c) const
313 { 428 {
314 TRACE_APPLY (); 429 TRACE_APPLY ();
315 switch (u.format) { 430 switch (u.format) {
316 case 1: return u.format1.apply (c); 431 case 1: return TRACE_RETURN (u.format1.apply (c));
317 default:return false; 432 default:return TRACE_RETURN (false);
318 } 433 }
319 } 434 }
320 435
321 inline bool sanitize (hb_sanitize_context_t *c) { 436 inline bool sanitize (hb_sanitize_context_t *c) {
322 TRACE_SANITIZE (); 437 TRACE_SANITIZE ();
323 if (!u.format.sanitize (c)) return false; 438 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
324 switch (u.format) { 439 switch (u.format) {
325 case 1: return u.format1.sanitize (c); 440 case 1: return TRACE_RETURN (u.format1.sanitize (c));
326 default:return true; 441 default:return TRACE_RETURN (true);
327 } 442 }
328 } 443 }
329 444
330 private: 445 private:
331 union { 446 union {
332 USHORT format; /* Format identifier */ 447 USHORT format; /* Format identifier */
333 AlternateSubstFormat1 format1; 448 AlternateSubstFormat1 format1;
334 } u; 449 } u;
335 }; 450 };
336 451
337 452
338 struct Ligature 453 struct Ligature
339 { 454 {
340 friend struct LigatureSet; 455 friend struct LigatureSet;
341 456
342 private: 457 private:
458
459 inline void closure (hb_closure_context_t *c) const
460 {
461 TRACE_CLOSURE ();
462 unsigned int count = component.len;
463 for (unsigned int i = 1; i < count; i++)
464 if (!c->glyphs->has (component[i]))
465 return;
466 c->glyphs->add (ligGlyph);
467 }
468
469 inline bool would_apply (hb_codepoint_t second) const
470 {
471 return component.len == 2 && component[1] == second;
472 }
473
343 inline bool apply (hb_apply_context_t *c) const 474 inline bool apply (hb_apply_context_t *c) const
344 { 475 {
345 TRACE_APPLY (); 476 TRACE_APPLY ();
346 unsigned int count = component.len; 477 unsigned int count = component.len;
347 if (unlikely (count < 2)) 478 if (unlikely (count < 2)) return TRACE_RETURN (false);
348 return false;
349 479
350 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff er->idx, count - 1); 480 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff er->idx, count - 1);
351 if (skippy_iter.has_no_chance ()) 481 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
352 return false;
353 482
354 bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); 483 bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
355 bool found_non_mark = false; 484 bool found_non_mark = false;
356 485
357 for (unsigned int i = 1; i < count; i++) 486 for (unsigned int i = 1; i < count; i++)
358 { 487 {
359 unsigned int property; 488 unsigned int property;
360 489
361 if (!skippy_iter.next (&property)) 490 if (!skippy_iter.next (&property)) return TRACE_RETURN (false);
362 » return false;
363 491
364 found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); 492 found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK);
365 493
366 if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) 494 if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) r eturn TRACE_RETURN (false);
367 return false;
368 } 495 }
369 496
370 if (first_was_mark && found_non_mark) 497 unsigned int klass = first_was_mark && found_non_mark ? HB_OT_LAYOUT_GLYPH_C LASS_LIGATURE : 0;
371 c->guess_glyph_class (HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE);
372 498
373 /* Allocate new ligature id */ 499 /* Allocate new ligature id */
374 unsigned int lig_id = allocate_lig_id (c->buffer); 500 unsigned int lig_id = allocate_lig_id (c->buffer);
375 c->buffer->info[c->buffer->idx].lig_comp() = 0; 501 set_lig_props (c->buffer->cur(), lig_id, 0);
376 c->buffer->info[c->buffer->idx].lig_id() = lig_id;
377 502
378 if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */ 503 if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */
379 { 504 {
380 c->replace_glyphs_be16 (count, 1, (const uint16_t *) &ligGlyph); 505 c->replace_glyphs_be16 (count, 1, (const uint16_t *) &ligGlyph, klass);
381 } 506 }
382 else 507 else
383 { 508 {
384 c->replace_glyph (ligGlyph); 509 c->replace_glyph (ligGlyph);
385 510
386 /* Now we must do a second loop to copy the skipped glyphs to 511 /* Now we must do a second loop to copy the skipped glyphs to
387 `out' and assign component values to it. We start with the 512 `out' and assign component values to it. We start with the
388 glyph after the first component. Glyphs between component 513 glyph after the first component. Glyphs between component
389 i and i+1 belong to component i. Together with the lig_id 514 i and i+1 belong to component i. Together with the lig_id
390 value it is later possible to check whether a specific 515 value it is later possible to check whether a specific
391 component value really belongs to a given ligature. */ 516 component value really belongs to a given ligature. */
392 517
393 for (unsigned int i = 1; i < count; i++) 518 for (unsigned int i = 1; i < count; i++)
394 { 519 {
395 while (c->should_mark_skip_current_glyph ()) 520 while (c->should_mark_skip_current_glyph ())
396 { 521 {
397 » c->buffer->info[c->buffer->idx].lig_comp() = i; 522 » set_lig_props (c->buffer->cur(), lig_id, i);
398 » c->buffer->info[c->buffer->idx].lig_id() = lig_id; 523 » c->replace_glyph (c->buffer->cur().codepoint);
399 » c->replace_glyph (c->buffer->info[c->buffer->idx].codepoint);
400 } 524 }
401 525
402 /* Skip the base glyph */ 526 /* Skip the base glyph */
403 c->buffer->idx++; 527 c->buffer->idx++;
404 } 528 }
405 } 529 }
406 530
407 return true; 531 return TRACE_RETURN (true);
408 } 532 }
409 533
410 public: 534 public:
411 inline bool sanitize (hb_sanitize_context_t *c) { 535 inline bool sanitize (hb_sanitize_context_t *c) {
412 TRACE_SANITIZE (); 536 TRACE_SANITIZE ();
413 return ligGlyph.sanitize (c) 537 return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c));
414 && component.sanitize (c);
415 } 538 }
416 539
417 private: 540 private:
418 GlyphID ligGlyph; /* GlyphID of ligature to substitute */ 541 GlyphID ligGlyph; /* GlyphID of ligature to substitute */
419 HeadlessArrayOf<GlyphID> 542 HeadlessArrayOf<GlyphID>
420 component; /* Array of component GlyphIDs--start 543 component; /* Array of component GlyphIDs--start
421 * with the second component--ordered 544 * with the second component--ordered
422 * in writing direction */ 545 * in writing direction */
423 public: 546 public:
424 DEFINE_SIZE_ARRAY (4, component); 547 DEFINE_SIZE_ARRAY (4, component);
425 }; 548 };
426 549
427 struct LigatureSet 550 struct LigatureSet
428 { 551 {
429 friend struct LigatureSubstFormat1; 552 friend struct LigatureSubstFormat1;
430 553
431 private: 554 private:
555
556 inline void closure (hb_closure_context_t *c) const
557 {
558 TRACE_CLOSURE ();
559 unsigned int num_ligs = ligature.len;
560 for (unsigned int i = 0; i < num_ligs; i++)
561 (this+ligature[i]).closure (c);
562 }
563
564 inline bool would_apply (hb_codepoint_t second) const
565 {
566 unsigned int num_ligs = ligature.len;
567 for (unsigned int i = 0; i < num_ligs; i++)
568 {
569 const Ligature &lig = this+ligature[i];
570 if (lig.would_apply (second))
571 return true;
572 }
573 return false;
574 }
575
432 inline bool apply (hb_apply_context_t *c) const 576 inline bool apply (hb_apply_context_t *c) const
433 { 577 {
434 TRACE_APPLY (); 578 TRACE_APPLY ();
435 unsigned int num_ligs = ligature.len; 579 unsigned int num_ligs = ligature.len;
436 for (unsigned int i = 0; i < num_ligs; i++) 580 for (unsigned int i = 0; i < num_ligs; i++)
437 { 581 {
438 const Ligature &lig = this+ligature[i]; 582 const Ligature &lig = this+ligature[i];
439 if (lig.apply (c)) 583 if (lig.apply (c)) return TRACE_RETURN (true);
440 return true;
441 } 584 }
442 585
443 return false; 586 return TRACE_RETURN (false);
444 } 587 }
445 588
446 public: 589 public:
447 inline bool sanitize (hb_sanitize_context_t *c) { 590 inline bool sanitize (hb_sanitize_context_t *c) {
448 TRACE_SANITIZE (); 591 TRACE_SANITIZE ();
449 return ligature.sanitize (c, this); 592 return TRACE_RETURN (ligature.sanitize (c, this));
450 } 593 }
451 594
452 private: 595 private:
453 OffsetArrayOf<Ligature> 596 OffsetArrayOf<Ligature>
454 ligature; /* Array LigatureSet tables 597 ligature; /* Array LigatureSet tables
455 * ordered by preference */ 598 * ordered by preference */
456 public: 599 public:
457 DEFINE_SIZE_ARRAY (2, ligature); 600 DEFINE_SIZE_ARRAY (2, ligature);
458 }; 601 };
459 602
460 struct LigatureSubstFormat1 603 struct LigatureSubstFormat1
461 { 604 {
462 friend struct LigatureSubst; 605 friend struct LigatureSubst;
463 606
464 private: 607 private:
608
609 inline void closure (hb_closure_context_t *c) const
610 {
611 TRACE_CLOSURE ();
612 Coverage::Iter iter;
613 for (iter.init (this+coverage); iter.more (); iter.next ()) {
614 if (c->glyphs->has (iter.get_glyph ()))
615 (this+ligatureSet[iter.get_coverage ()]).closure (c);
616 }
617 }
618
619 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
620 {
621 unsigned int index;
622 return (index = (this+coverage) (first)) != NOT_COVERED &&
623 (this+ligatureSet[index]).would_apply (second);
624 }
625
465 inline bool apply (hb_apply_context_t *c) const 626 inline bool apply (hb_apply_context_t *c) const
466 { 627 {
467 TRACE_APPLY (); 628 TRACE_APPLY ();
468 hb_codepoint_t glyph_id = c->buffer->info[c->buffer->idx].codepoint; 629 hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
469 630
470 unsigned int index = (this+coverage) (glyph_id); 631 unsigned int index = (this+coverage) (glyph_id);
471 if (likely (index == NOT_COVERED)) 632 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
472 return false;
473 633
474 const LigatureSet &lig_set = this+ligatureSet[index]; 634 const LigatureSet &lig_set = this+ligatureSet[index];
475 return lig_set.apply (c); 635 return TRACE_RETURN (lig_set.apply (c));
476 } 636 }
477 637
478 inline bool sanitize (hb_sanitize_context_t *c) { 638 inline bool sanitize (hb_sanitize_context_t *c) {
479 TRACE_SANITIZE (); 639 TRACE_SANITIZE ();
480 return coverage.sanitize (c, this) 640 return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
481 » && ligatureSet.sanitize (c, this);
482 } 641 }
483 642
484 private: 643 private:
485 USHORT format; /* Format identifier--format = 1 */ 644 USHORT format; /* Format identifier--format = 1 */
486 OffsetTo<Coverage> 645 OffsetTo<Coverage>
487 coverage; /* Offset to Coverage table--from 646 coverage; /* Offset to Coverage table--from
488 * beginning of Substitution table */ 647 * beginning of Substitution table */
489 OffsetArrayOf<LigatureSet> 648 OffsetArrayOf<LigatureSet>
490 ligatureSet; /* Array LigatureSet tables 649 ligatureSet; /* Array LigatureSet tables
491 * ordered by Coverage Index */ 650 * ordered by Coverage Index */
492 public: 651 public:
493 DEFINE_SIZE_ARRAY (6, ligatureSet); 652 DEFINE_SIZE_ARRAY (6, ligatureSet);
494 }; 653 };
495 654
496 struct LigatureSubst 655 struct LigatureSubst
497 { 656 {
498 friend struct SubstLookupSubTable; 657 friend struct SubstLookupSubTable;
499 658
500 private: 659 private:
660
661 inline void closure (hb_closure_context_t *c) const
662 {
663 TRACE_CLOSURE ();
664 switch (u.format) {
665 case 1: u.format1.closure (c); break;
666 default: break;
667 }
668 }
669
670 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
671 {
672 switch (u.format) {
673 case 1: return u.format1.would_apply (first, second);
674 default:return false;
675 }
676 }
677
501 inline bool apply (hb_apply_context_t *c) const 678 inline bool apply (hb_apply_context_t *c) const
502 { 679 {
503 TRACE_APPLY (); 680 TRACE_APPLY ();
504 switch (u.format) { 681 switch (u.format) {
505 case 1: return u.format1.apply (c); 682 case 1: return TRACE_RETURN (u.format1.apply (c));
506 default:return false; 683 default:return TRACE_RETURN (false);
507 } 684 }
508 } 685 }
509 686
510 inline bool sanitize (hb_sanitize_context_t *c) { 687 inline bool sanitize (hb_sanitize_context_t *c) {
511 TRACE_SANITIZE (); 688 TRACE_SANITIZE ();
512 if (!u.format.sanitize (c)) return false; 689 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
513 switch (u.format) { 690 switch (u.format) {
514 case 1: return u.format1.sanitize (c); 691 case 1: return TRACE_RETURN (u.format1.sanitize (c));
515 default:return true; 692 default:return TRACE_RETURN (true);
516 } 693 }
517 } 694 }
518 695
519 private: 696 private:
520 union { 697 union {
521 USHORT format; /* Format identifier */ 698 USHORT format; /* Format identifier */
522 LigatureSubstFormat1 format1; 699 LigatureSubstFormat1 format1;
523 } u; 700 } u;
524 }; 701 };
525 702
526 703
527 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index); 704 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index);
705 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_ index);
528 706
529 struct ContextSubst : Context 707 struct ContextSubst : Context
530 { 708 {
531 friend struct SubstLookupSubTable; 709 friend struct SubstLookupSubTable;
532 710
533 private: 711 private:
712
713 inline void closure (hb_closure_context_t *c) const
714 {
715 TRACE_CLOSURE ();
716 return Context::closure (c, closure_lookup);
717 }
718
534 inline bool apply (hb_apply_context_t *c) const 719 inline bool apply (hb_apply_context_t *c) const
535 { 720 {
536 TRACE_APPLY (); 721 TRACE_APPLY ();
537 return Context::apply (c, substitute_lookup); 722 return TRACE_RETURN (Context::apply (c, substitute_lookup));
538 } 723 }
539 }; 724 };
540 725
541 struct ChainContextSubst : ChainContext 726 struct ChainContextSubst : ChainContext
542 { 727 {
543 friend struct SubstLookupSubTable; 728 friend struct SubstLookupSubTable;
544 729
545 private: 730 private:
731
732 inline void closure (hb_closure_context_t *c) const
733 {
734 TRACE_CLOSURE ();
735 return ChainContext::closure (c, closure_lookup);
736 }
737
546 inline bool apply (hb_apply_context_t *c) const 738 inline bool apply (hb_apply_context_t *c) const
547 { 739 {
548 TRACE_APPLY (); 740 TRACE_APPLY ();
549 return ChainContext::apply (c, substitute_lookup); 741 return TRACE_RETURN (ChainContext::apply (c, substitute_lookup));
550 } 742 }
551 }; 743 };
552 744
553 745
554 struct ExtensionSubst : Extension 746 struct ExtensionSubst : Extension
555 { 747 {
556 friend struct SubstLookupSubTable; 748 friend struct SubstLookupSubTable;
557 friend struct SubstLookup; 749 friend struct SubstLookup;
558 750
559 private: 751 private:
560 inline const struct SubstLookupSubTable& get_subtable (void) const 752 inline const struct SubstLookupSubTable& get_subtable (void) const
561 { 753 {
562 unsigned int offset = get_offset (); 754 unsigned int offset = get_offset ();
563 if (unlikely (!offset)) return Null(SubstLookupSubTable); 755 if (unlikely (!offset)) return Null(SubstLookupSubTable);
564 return StructAtOffset<SubstLookupSubTable> (this, offset); 756 return StructAtOffset<SubstLookupSubTable> (this, offset);
565 } 757 }
566 758
759 inline void closure (hb_closure_context_t *c) const;
760 inline bool would_apply (hb_codepoint_t glyph_id) const;
761 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const;
762
567 inline bool apply (hb_apply_context_t *c) const; 763 inline bool apply (hb_apply_context_t *c) const;
568 764
569 inline bool sanitize (hb_sanitize_context_t *c); 765 inline bool sanitize (hb_sanitize_context_t *c);
570 766
571 inline bool is_reverse (void) const; 767 inline bool is_reverse (void) const;
572 }; 768 };
573 769
574 770
575 struct ReverseChainSingleSubstFormat1 771 struct ReverseChainSingleSubstFormat1
576 { 772 {
577 friend struct ReverseChainSingleSubst; 773 friend struct ReverseChainSingleSubst;
578 774
579 private: 775 private:
776
777 inline void closure (hb_closure_context_t *c) const
778 {
779 TRACE_CLOSURE ();
780 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag e> > (backtrack);
781
782 unsigned int count;
783
784 count = backtrack.len;
785 for (unsigned int i = 0; i < count; i++)
786 if (!(this+backtrack[i]).intersects (c->glyphs))
787 return;
788
789 count = lookahead.len;
790 for (unsigned int i = 0; i < count; i++)
791 if (!(this+lookahead[i]).intersects (c->glyphs))
792 return;
793
794 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe ad);
795 Coverage::Iter iter;
796 for (iter.init (this+coverage); iter.more (); iter.next ()) {
797 if (c->glyphs->has (iter.get_glyph ()))
798 c->glyphs->add (substitute[iter.get_coverage ()]);
799 }
800 }
801
580 inline bool apply (hb_apply_context_t *c) const 802 inline bool apply (hb_apply_context_t *c) const
581 { 803 {
582 TRACE_APPLY (); 804 TRACE_APPLY ();
583 if (unlikely (c->context_length != NO_CONTEXT)) 805 if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL))
584 return false; /* No chaining to this type */ 806 return TRACE_RETURN (false); /* No chaining to this type */
585 807
586 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepo int); 808 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
587 if (likely (index == NOT_COVERED)) 809 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
588 return false;
589 810
590 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag e> > (backtrack); 811 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag e> > (backtrack);
591 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe ad); 812 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe ad);
592 813
593 if (match_backtrack (c, 814 if (match_backtrack (c,
594 backtrack.len, (USHORT *) backtrack.array, 815 backtrack.len, (USHORT *) backtrack.array,
595 match_coverage, this) && 816 match_coverage, this) &&
596 match_lookahead (c, 817 match_lookahead (c,
597 lookahead.len, (USHORT *) lookahead.array, 818 lookahead.len, (USHORT *) lookahead.array,
598 match_coverage, this, 819 match_coverage, this,
599 1)) 820 1))
600 { 821 {
601 c->buffer->info[c->buffer->idx].codepoint = substitute[index]; 822 c->buffer->cur().codepoint = substitute[index];
602 c->buffer->idx--; /* Reverse! */ 823 c->buffer->idx--; /* Reverse! */
603 return true; 824 return TRACE_RETURN (true);
604 } 825 }
605 826
606 return false; 827 return TRACE_RETURN (false);
607 } 828 }
608 829
609 inline bool sanitize (hb_sanitize_context_t *c) { 830 inline bool sanitize (hb_sanitize_context_t *c) {
610 TRACE_SANITIZE (); 831 TRACE_SANITIZE ();
611 if (!(coverage.sanitize (c, this) 832 if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
612 && backtrack.sanitize (c, this))) 833 return TRACE_RETURN (false);
613 return false;
614 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > ( backtrack); 834 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > ( backtrack);
615 if (!lookahead.sanitize (c, this)) 835 if (!lookahead.sanitize (c, this))
616 return false; 836 return TRACE_RETURN (false);
617 ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); 837 ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
618 return substitute.sanitize (c); 838 return TRACE_RETURN (substitute.sanitize (c));
619 } 839 }
620 840
621 private: 841 private:
622 USHORT format; /* Format identifier--format = 1 */ 842 USHORT format; /* Format identifier--format = 1 */
623 OffsetTo<Coverage> 843 OffsetTo<Coverage>
624 coverage; /* Offset to Coverage table--from 844 coverage; /* Offset to Coverage table--from
625 * beginning of table */ 845 * beginning of table */
626 OffsetArrayOf<Coverage> 846 OffsetArrayOf<Coverage>
627 backtrack; /* Array of coverage tables 847 backtrack; /* Array of coverage tables
628 * in backtracking sequence, in glyph 848 * in backtracking sequence, in glyph
629 * sequence order */ 849 * sequence order */
630 OffsetArrayOf<Coverage> 850 OffsetArrayOf<Coverage>
631 lookaheadX; /* Array of coverage tables 851 lookaheadX; /* Array of coverage tables
632 * in lookahead sequence, in glyph 852 * in lookahead sequence, in glyph
633 * sequence order */ 853 * sequence order */
634 ArrayOf<GlyphID> 854 ArrayOf<GlyphID>
635 substituteX; /* Array of substitute 855 substituteX; /* Array of substitute
636 * GlyphIDs--ordered by Coverage Index * / 856 * GlyphIDs--ordered by Coverage Index * /
637 public: 857 public:
638 DEFINE_SIZE_MIN (10); 858 DEFINE_SIZE_MIN (10);
639 }; 859 };
640 860
641 struct ReverseChainSingleSubst 861 struct ReverseChainSingleSubst
642 { 862 {
643 friend struct SubstLookupSubTable; 863 friend struct SubstLookupSubTable;
644 864
645 private: 865 private:
866
867 inline void closure (hb_closure_context_t *c) const
868 {
869 TRACE_CLOSURE ();
870 switch (u.format) {
871 case 1: u.format1.closure (c); break;
872 default: break;
873 }
874 }
875
646 inline bool apply (hb_apply_context_t *c) const 876 inline bool apply (hb_apply_context_t *c) const
647 { 877 {
648 TRACE_APPLY (); 878 TRACE_APPLY ();
649 switch (u.format) { 879 switch (u.format) {
650 case 1: return u.format1.apply (c); 880 case 1: return TRACE_RETURN (u.format1.apply (c));
651 default:return false; 881 default:return TRACE_RETURN (false);
652 } 882 }
653 } 883 }
654 884
655 inline bool sanitize (hb_sanitize_context_t *c) { 885 inline bool sanitize (hb_sanitize_context_t *c) {
656 TRACE_SANITIZE (); 886 TRACE_SANITIZE ();
657 if (!u.format.sanitize (c)) return false; 887 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
658 switch (u.format) { 888 switch (u.format) {
659 case 1: return u.format1.sanitize (c); 889 case 1: return TRACE_RETURN (u.format1.sanitize (c));
660 default:return true; 890 default:return TRACE_RETURN (true);
661 } 891 }
662 } 892 }
663 893
664 private: 894 private:
665 union { 895 union {
666 USHORT format; /* Format identifier */ 896 USHORT format; /* Format identifier */
667 ReverseChainSingleSubstFormat1 format1; 897 ReverseChainSingleSubstFormat1 format1;
668 } u; 898 } u;
669 }; 899 };
670 900
671 901
672 902
673 /* 903 /*
674 * SubstLookup 904 * SubstLookup
675 */ 905 */
676 906
677 struct SubstLookupSubTable 907 struct SubstLookupSubTable
678 { 908 {
679 friend struct SubstLookup; 909 friend struct SubstLookup;
680 910
681 enum { 911 enum Type {
682 Single = 1, 912 Single = 1,
683 Multiple = 2, 913 Multiple = 2,
684 Alternate = 3, 914 Alternate = 3,
685 Ligature = 4, 915 Ligature = 4,
686 Context = 5, 916 Context = 5,
687 ChainContext = 6, 917 ChainContext = 6,
688 Extension = 7, 918 Extension = 7,
689 ReverseChainSingle = 8 919 ReverseChainSingle = 8
690 }; 920 };
691 921
922 inline void closure (hb_closure_context_t *c,
923 unsigned int lookup_type) const
924 {
925 TRACE_CLOSURE ();
926 switch (lookup_type) {
927 case Single: u.single.closure (c); break;
928 case Multiple: u.multiple.closure (c); break;
929 case Alternate: u.alternate.closure (c); break;
930 case Ligature: u.ligature.closure (c); break;
931 case Context: u.c.closure (c); break;
932 case ChainContext: u.chainContext.closure (c); break;
933 case Extension: u.extension.closure (c); break;
934 case ReverseChainSingle: u.reverseChainContextSingle.closure (c); break;
935 default: break;
936 }
937 }
938
939 inline bool would_apply (hb_codepoint_t glyph_id,
940 unsigned int lookup_type) const
941 {
942 switch (lookup_type) {
943 case Single: return u.single.would_apply (glyph_id);
944 case Multiple: return u.multiple.would_apply (glyph_id);
945 case Alternate: return u.alternate.would_apply (glyph_id);
946 case Extension: return u.extension.would_apply (glyph_id);
947 default: return false;
948 }
949 }
950 inline bool would_apply (hb_codepoint_t first,
951 hb_codepoint_t second,
952 unsigned int lookup_type) const
953 {
954 switch (lookup_type) {
955 case Ligature: return u.ligature.would_apply (first, second);
956 case Extension: return u.extension.would_apply (first, second);
957 default: return false;
958 }
959 }
960
692 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const 961 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const
693 { 962 {
694 TRACE_APPLY (); 963 TRACE_APPLY ();
695 switch (lookup_type) { 964 switch (lookup_type) {
696 case Single:» » return u.single.apply (c); 965 case Single:» » return TRACE_RETURN (u.single.apply (c));
697 case Multiple:» » return u.multiple.apply (c); 966 case Multiple:» » return TRACE_RETURN (u.multiple.apply (c));
698 case Alternate:» » return u.alternate.apply (c); 967 case Alternate:» » return TRACE_RETURN (u.alternate.apply (c));
699 case Ligature:» » return u.ligature.apply (c); 968 case Ligature:» » return TRACE_RETURN (u.ligature.apply (c));
700 case Context:» » return u.c.apply (c); 969 case Context:» » return TRACE_RETURN (u.c.apply (c));
701 case ChainContext:» » return u.chainContext.apply (c); 970 case ChainContext:» » return TRACE_RETURN (u.chainContext.apply (c));
702 case Extension:» » return u.extension.apply (c); 971 case Extension:» » return TRACE_RETURN (u.extension.apply (c));
703 case ReverseChainSingle:» return u.reverseChainContextSingle.apply (c); 972 case ReverseChainSingle:» return TRACE_RETURN (u.reverseChainContextSingle .apply (c));
704 default:return false; 973 default:» » » return TRACE_RETURN (false);
705 } 974 }
706 } 975 }
707 976
708 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { 977 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
709 TRACE_SANITIZE (); 978 TRACE_SANITIZE ();
710 switch (lookup_type) { 979 switch (lookup_type) {
711 case Single:» » return u.single.sanitize (c); 980 case Single:» » return TRACE_RETURN (u.single.sanitize (c));
712 case Multiple:» » return u.multiple.sanitize (c); 981 case Multiple:» » return TRACE_RETURN (u.multiple.sanitize (c));
713 case Alternate:» » return u.alternate.sanitize (c); 982 case Alternate:» » return TRACE_RETURN (u.alternate.sanitize (c));
714 case Ligature:» » return u.ligature.sanitize (c); 983 case Ligature:» » return TRACE_RETURN (u.ligature.sanitize (c));
715 case Context:» » return u.c.sanitize (c); 984 case Context:» » return TRACE_RETURN (u.c.sanitize (c));
716 case ChainContext:» » return u.chainContext.sanitize (c); 985 case ChainContext:» » return TRACE_RETURN (u.chainContext.sanitize (c) );
717 case Extension:» » return u.extension.sanitize (c); 986 case Extension:» » return TRACE_RETURN (u.extension.sanitize (c));
718 case ReverseChainSingle:» return u.reverseChainContextSingle.sanitize (c); 987 case ReverseChainSingle:» return TRACE_RETURN (u.reverseChainContextSingle .sanitize (c));
719 default:return true; 988 default:» » » return TRACE_RETURN (true);
720 } 989 }
721 } 990 }
722 991
723 private: 992 private:
724 union { 993 union {
725 USHORT sub_format; 994 USHORT sub_format;
726 SingleSubst single; 995 SingleSubst single;
727 MultipleSubst multiple; 996 MultipleSubst multiple;
728 AlternateSubst alternate; 997 AlternateSubst alternate;
729 LigatureSubst ligature; 998 LigatureSubst ligature;
(...skipping 16 matching lines...) Expand all
746 { return lookup_type == SubstLookupSubTable::ReverseChainSingle; } 1015 { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
747 1016
748 inline bool is_reverse (void) const 1017 inline bool is_reverse (void) const
749 { 1018 {
750 unsigned int type = get_type (); 1019 unsigned int type = get_type ();
751 if (unlikely (type == SubstLookupSubTable::Extension)) 1020 if (unlikely (type == SubstLookupSubTable::Extension))
752 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse (); 1021 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
753 return lookup_type_is_reverse (type); 1022 return lookup_type_is_reverse (type);
754 } 1023 }
755 1024
756 1025 inline void closure (hb_closure_context_t *c) const
757 inline bool apply_once (hb_face_t *face,
758 » » » hb_buffer_t *buffer,
759 » » » hb_mask_t lookup_mask,
760 » » » unsigned int context_length,
761 » » » unsigned int nesting_level_left) const
762 { 1026 {
763 unsigned int lookup_type = get_type (); 1027 unsigned int lookup_type = get_type ();
764 hb_apply_context_t c[1] = {{0}}; 1028 unsigned int count = get_subtable_count ();
1029 for (unsigned int i = 0; i < count; i++)
1030 get_subtable (i).closure (c, lookup_type);
1031 }
765 1032
766 c->face = face; 1033 inline bool would_apply (hb_codepoint_t glyph_id) const
767 c->buffer = buffer; 1034 {
768 c->direction = buffer->props.direction; 1035 unsigned int lookup_type = get_type ();
769 c->lookup_mask = lookup_mask; 1036 unsigned int count = get_subtable_count ();
770 c->context_length = context_length; 1037 for (unsigned int i = 0; i < count; i++)
771 c->nesting_level_left = nesting_level_left; 1038 if (get_subtable (i).would_apply (glyph_id, lookup_type))
772 c->lookup_props = get_props (); 1039 » return true;
1040 return false;
1041 }
1042 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const
1043 {
1044 unsigned int lookup_type = get_type ();
1045 unsigned int count = get_subtable_count ();
1046 for (unsigned int i = 0; i < count; i++)
1047 if (get_subtable (i).would_apply (first, second, lookup_type))
1048 » return true;
1049 return false;
1050 }
773 1051
774 if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer ->idx], c->lookup_props, &c->property)) 1052 inline bool apply_once (hb_apply_context_t *c) const
1053 {
1054 unsigned int lookup_type = get_type ();
1055
1056 if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->cur(), c->look up_props, &c->property))
775 return false; 1057 return false;
776 1058
777 if (unlikely (lookup_type == SubstLookupSubTable::Extension)) 1059 if (unlikely (lookup_type == SubstLookupSubTable::Extension))
778 { 1060 {
779 /* The spec says all subtables should have the same type. 1061 /* The spec says all subtables should have the same type.
780 * This is specially important if one has a reverse type! 1062 * This is specially important if one has a reverse type!
781 * 1063 *
782 * This is rather slow to do this here for every glyph, 1064 * This is rather slow to do this here for every glyph,
783 * but it's easiest, and who uses extension lookups anyway?!*/ 1065 * but it's easiest, and who uses extension lookups anyway?!*/
1066 unsigned int type = get_subtable(0).u.extension.get_type ();
784 unsigned int count = get_subtable_count (); 1067 unsigned int count = get_subtable_count ();
785 unsigned int type = get_subtable(0).u.extension.get_type ();
786 for (unsigned int i = 1; i < count; i++) 1068 for (unsigned int i = 1; i < count; i++)
787 if (get_subtable(i).u.extension.get_type () != type) 1069 if (get_subtable(i).u.extension.get_type () != type)
788 return false; 1070 return false;
789 } 1071 }
790 1072
791 unsigned int count = get_subtable_count (); 1073 unsigned int count = get_subtable_count ();
792 for (unsigned int i = 0; i < count; i++) 1074 for (unsigned int i = 0; i < count; i++)
793 if (get_subtable (i).apply (c, lookup_type)) 1075 if (get_subtable (i).apply (c, lookup_type))
794 return true; 1076 return true;
795 1077
796 return false; 1078 return false;
797 } 1079 }
798 1080
799 inline bool apply_string (hb_face_t *face, 1081 inline bool apply_string (hb_apply_context_t *c) const
800 » » » hb_buffer_t *buffer,
801 » » » hb_mask_t mask) const
802 { 1082 {
803 bool ret = false; 1083 bool ret = false;
804 1084
805 if (unlikely (!buffer->len)) 1085 if (unlikely (!c->buffer->len))
806 return false; 1086 return false;
807 1087
1088 c->set_lookup (*this);
1089
808 if (likely (!is_reverse ())) 1090 if (likely (!is_reverse ()))
809 { 1091 {
810 /* in/out forward substitution */ 1092 /* in/out forward substitution */
811 » buffer->clear_output (); 1093 » c->buffer->clear_output ();
812 » buffer->idx = 0; 1094 » c->buffer->idx = 0;
813 » while (buffer->idx < buffer->len) 1095 » while (c->buffer->idx < c->buffer->len)
814 { 1096 {
815 » if ((buffer->info[buffer->idx].mask & mask) && 1097 » if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c))
816 » apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
817 ret = true; 1098 ret = true;
818 else 1099 else
819 » buffer->next_glyph (); 1100 » c->buffer->next_glyph ();
820 1101
821 } 1102 }
822 if (ret) 1103 if (ret)
823 » buffer->swap_buffers (); 1104 » c->buffer->swap_buffers ();
824 } 1105 }
825 else 1106 else
826 { 1107 {
827 /* in-place backward substitution */ 1108 /* in-place backward substitution */
828 » buffer->idx = buffer->len - 1; 1109 » c->buffer->idx = c->buffer->len - 1;
829 do 1110 do
830 { 1111 {
831 » if ((buffer->info[buffer->idx].mask & mask) && 1112 » if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c))
832 » apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
833 ret = true; 1113 ret = true;
834 else 1114 else
835 » buffer->idx--; 1115 » c->buffer->idx--;
836 1116
837 } 1117 }
838 » while ((int) buffer->idx >= 0); 1118 » while ((int) c->buffer->idx >= 0);
839 } 1119 }
840 1120
841 return ret; 1121 return ret;
842 } 1122 }
843 1123
844 inline bool sanitize (hb_sanitize_context_t *c) { 1124 inline bool sanitize (hb_sanitize_context_t *c) {
845 TRACE_SANITIZE (); 1125 TRACE_SANITIZE ();
846 if (unlikely (!Lookup::sanitize (c))) return false; 1126 if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
847 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu bTable> > (subTable); 1127 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu bTable> > (subTable);
848 return list.sanitize (c, this, get_type ()); 1128 return TRACE_RETURN (list.sanitize (c, this, get_type ()));
849 } 1129 }
850 }; 1130 };
851 1131
852 typedef OffsetListOf<SubstLookup> SubstLookupList; 1132 typedef OffsetListOf<SubstLookup> SubstLookupList;
853 1133
854 /* 1134 /*
855 * GSUB -- The Glyph Substitution Table 1135 * GSUB -- The Glyph Substitution Table
856 */ 1136 */
857 1137
858 struct GSUB : GSUBGPOS 1138 struct GSUB : GSUBGPOS
859 { 1139 {
860 static const hb_tag_t Tag = HB_OT_TAG_GSUB; 1140 static const hb_tag_t Tag = HB_OT_TAG_GSUB;
861 1141
862 inline const SubstLookup& get_lookup (unsigned int i) const 1142 inline const SubstLookup& get_lookup (unsigned int i) const
863 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); } 1143 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
864 1144
865 inline bool substitute_lookup (hb_face_t *face, 1145 inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_inde x) const
866 » » » » hb_buffer_t *buffer, 1146 { return get_lookup (lookup_index).apply_string (c); }
867 » » » unsigned int lookup_index,
868 » » » » hb_mask_t mask) const
869 { return get_lookup (lookup_index).apply_string (face, buffer, mask); }
870 1147
871 static inline void substitute_start (hb_buffer_t *buffer); 1148 static inline void substitute_start (hb_buffer_t *buffer);
872 static inline void substitute_finish (hb_buffer_t *buffer); 1149 static inline void substitute_finish (hb_buffer_t *buffer);
873 1150
1151 inline void closure_lookup (hb_closure_context_t *c,
1152 unsigned int lookup_index) const
1153 { return get_lookup (lookup_index).closure (c); }
1154
874 inline bool sanitize (hb_sanitize_context_t *c) { 1155 inline bool sanitize (hb_sanitize_context_t *c) {
875 TRACE_SANITIZE (); 1156 TRACE_SANITIZE ();
876 if (unlikely (!GSUBGPOS::sanitize (c))) return false; 1157 if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
877 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL ist); 1158 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL ist);
878 return list.sanitize (c, this); 1159 return TRACE_RETURN (list.sanitize (c, this));
879 } 1160 }
880 public: 1161 public:
881 DEFINE_SIZE_STATIC (10); 1162 DEFINE_SIZE_STATIC (10);
882 }; 1163 };
883 1164
884 1165
885 void 1166 void
886 GSUB::substitute_start (hb_buffer_t *buffer) 1167 GSUB::substitute_start (hb_buffer_t *buffer)
887 { 1168 {
888 HB_BUFFER_ALLOCATE_VAR (buffer, props_cache); 1169 HB_BUFFER_ALLOCATE_VAR (buffer, props_cache);
889 HB_BUFFER_ALLOCATE_VAR (buffer, lig_id); 1170 HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
890 HB_BUFFER_ALLOCATE_VAR (buffer, lig_comp); 1171 HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
891 1172
892 unsigned int count = buffer->len; 1173 unsigned int count = buffer->len;
893 for (unsigned int i = 0; i < count; i++) 1174 for (unsigned int i = 0; i < count; i++)
894 buffer->info[i].props_cache() = buffer->info[i].lig_id() = buffer->info[i].l ig_comp() = 0; 1175 buffer->info[i].props_cache() = buffer->info[i].lig_props() = buffer->info[i ].syllable() = 0;
895 } 1176 }
896 1177
897 void 1178 void
898 GSUB::substitute_finish (hb_buffer_t *buffer) 1179 GSUB::substitute_finish (hb_buffer_t *buffer HB_UNUSED)
899 { 1180 {
900 } 1181 }
901 1182
902 1183
903 /* Out-of-class implementation for methods recursing */ 1184 /* Out-of-class implementation for methods recursing */
904 1185
1186 inline void ExtensionSubst::closure (hb_closure_context_t *c) const
1187 {
1188 get_subtable ().closure (c, get_type ());
1189 }
1190
1191 inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const
1192 {
1193 return get_subtable ().would_apply (glyph_id, get_type ());
1194 }
1195
1196 inline bool ExtensionSubst::would_apply (hb_codepoint_t first, hb_codepoint_t se cond) const
1197 {
1198 return get_subtable ().would_apply (first, second, get_type ());
1199 }
1200
905 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const 1201 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const
906 { 1202 {
907 TRACE_APPLY (); 1203 TRACE_APPLY ();
908 return get_subtable ().apply (c, get_type ()); 1204 return TRACE_RETURN (get_subtable ().apply (c, get_type ()));
909 } 1205 }
910 1206
911 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c) 1207 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c)
912 { 1208 {
913 TRACE_SANITIZE (); 1209 TRACE_SANITIZE ();
914 if (unlikely (!Extension::sanitize (c))) return false; 1210 if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false);
915 unsigned int offset = get_offset (); 1211 unsigned int offset = get_offset ();
916 if (unlikely (!offset)) return true; 1212 if (unlikely (!offset)) return TRACE_RETURN (true);
917 return StructAtOffset<SubstLookupSubTable> (this, offset).sanitize (c, get_typ e ()); 1213 return TRACE_RETURN (StructAtOffset<SubstLookupSubTable> (this, offset).saniti ze (c, get_type ()));
918 } 1214 }
919 1215
920 inline bool ExtensionSubst::is_reverse (void) const 1216 inline bool ExtensionSubst::is_reverse (void) const
921 { 1217 {
922 unsigned int type = get_type (); 1218 unsigned int type = get_type ();
923 if (unlikely (type == SubstLookupSubTable::Extension)) 1219 if (unlikely (type == SubstLookupSubTable::Extension))
924 return CastR<ExtensionSubst> (get_subtable()).is_reverse (); 1220 return CastR<ExtensionSubst> (get_subtable()).is_reverse ();
925 return SubstLookup::lookup_type_is_reverse (type); 1221 return SubstLookup::lookup_type_is_reverse (type);
926 } 1222 }
927 1223
1224 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_ index)
1225 {
1226 const GSUB &gsub = *(c->face->ot_layout->gsub);
1227 const SubstLookup &l = gsub.get_lookup (lookup_index);
1228
1229 if (unlikely (c->nesting_level_left == 0))
1230 return;
1231
1232 c->nesting_level_left--;
1233 l.closure (c);
1234 c->nesting_level_left++;
1235 }
1236
928 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index) 1237 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index)
929 { 1238 {
930 const GSUB &gsub = *(c->face->ot_layout->gsub); 1239 const GSUB &gsub = *(c->face->ot_layout->gsub);
931 const SubstLookup &l = gsub.get_lookup (lookup_index); 1240 const SubstLookup &l = gsub.get_lookup (lookup_index);
932 1241
933 if (unlikely (c->nesting_level_left == 0)) 1242 if (unlikely (c->nesting_level_left == 0))
934 return false; 1243 return false;
935 1244
936 if (unlikely (c->context_length < 1)) 1245 hb_apply_context_t new_c (*c);
937 return false; 1246 new_c.nesting_level_left--;
938 1247 new_c.set_lookup (l);
939 return l.apply_once (c->face, c->buffer, c->lookup_mask, c->context_length, c- >nesting_level_left - 1); 1248 return l.apply_once (&new_c);
940 } 1249 }
941 1250
942 1251
943 1252
944 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ 1253 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */
OLDNEW
« no previous file with comments | « third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh ('k') | third_party/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698