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

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

Issue 10915172: harfbuzz-ng roll (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
3 * Copyright © 2010,2012 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
(...skipping 14 matching lines...) Expand all
25 * Red Hat Author(s): Behdad Esfahbod 25 * Red Hat Author(s): Behdad Esfahbod
26 * Google Author(s): Behdad Esfahbod 26 * Google Author(s): Behdad Esfahbod
27 */ 27 */
28 28
29 #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH 29 #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
30 #define HB_OT_LAYOUT_GSUB_TABLE_HH 30 #define HB_OT_LAYOUT_GSUB_TABLE_HH
31 31
32 #include "hb-ot-layout-gsubgpos-private.hh" 32 #include "hb-ot-layout-gsubgpos-private.hh"
33 33
34 34
35 namespace OT {
36
35 37
36 struct SingleSubstFormat1 38 struct SingleSubstFormat1
37 { 39 {
38 friend struct SingleSubst; 40 friend struct SingleSubst;
39 41
40 private: 42 private:
41 43
42 inline void closure (hb_closure_context_t *c) const 44 inline void closure (hb_closure_context_t *c) const
43 { 45 {
44 TRACE_CLOSURE (); 46 TRACE_CLOSURE ();
45 Coverage::Iter iter; 47 Coverage::Iter iter;
46 for (iter.init (this+coverage); iter.more (); iter.next ()) { 48 for (iter.init (this+coverage); iter.more (); iter.next ()) {
47 hb_codepoint_t glyph_id = iter.get_glyph (); 49 hb_codepoint_t glyph_id = iter.get_glyph ();
48 if (c->glyphs->has (glyph_id)) 50 if (c->glyphs->has (glyph_id))
49 c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF); 51 c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF);
50 } 52 }
51 } 53 }
52 54
53 inline bool would_apply (hb_codepoint_t glyph_id) const 55 inline const Coverage &get_coverage (void) const
54 { 56 {
55 return (this+coverage) (glyph_id) != NOT_COVERED; 57 return this+coverage;
56 } 58 }
57 59
58 inline bool apply (hb_apply_context_t *c) const 60 inline bool apply (hb_apply_context_t *c) const
59 { 61 {
60 TRACE_APPLY (); 62 TRACE_APPLY ();
61 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; 63 hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
62 unsigned int index = (this+coverage) (glyph_id); 64 unsigned int index = (this+coverage) (glyph_id);
63 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); 65 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
64 66
65 /* According to the Adobe Annotated OpenType Suite, result is always 67 /* According to the Adobe Annotated OpenType Suite, result is always
66 * limited to 16bit. */ 68 * limited to 16bit. */
67 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF; 69 glyph_id = (glyph_id + deltaGlyphID) & 0xFFFF;
68 c->replace_glyph (glyph_id); 70 c->replace_glyph (glyph_id);
69 71
70 return TRACE_RETURN (true); 72 return TRACE_RETURN (true);
71 } 73 }
72 74
75 inline bool serialize (hb_serialize_context_t *c,
76 Supplier<GlyphID> &glyphs,
77 unsigned int num_glyphs,
78 int delta)
79 {
80 TRACE_SERIALIZE ();
81 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
82 if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs ))) return TRACE_RETURN (false);
83 deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
84 return TRACE_RETURN (true);
85 }
86
73 inline bool sanitize (hb_sanitize_context_t *c) { 87 inline bool sanitize (hb_sanitize_context_t *c) {
74 TRACE_SANITIZE (); 88 TRACE_SANITIZE ();
75 return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c )); 89 return TRACE_RETURN (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c ));
76 } 90 }
77 91
78 private: 92 protected:
79 USHORT format; /* Format identifier--format = 1 */ 93 USHORT format; /* Format identifier--format = 1 */
80 OffsetTo<Coverage> 94 OffsetTo<Coverage>
81 coverage; /* Offset to Coverage table--from 95 coverage; /* Offset to Coverage table--from
82 * beginning of Substitution table */ 96 * beginning of Substitution table */
83 SHORT deltaGlyphID; /* Add to original GlyphID to get 97 SHORT deltaGlyphID; /* Add to original GlyphID to get
84 * substitute GlyphID */ 98 * substitute GlyphID */
85 public: 99 public:
86 DEFINE_SIZE_STATIC (6); 100 DEFINE_SIZE_STATIC (6);
87 }; 101 };
88 102
89 struct SingleSubstFormat2 103 struct SingleSubstFormat2
90 { 104 {
91 friend struct SingleSubst; 105 friend struct SingleSubst;
92 106
93 private: 107 private:
94 108
95 inline void closure (hb_closure_context_t *c) const 109 inline void closure (hb_closure_context_t *c) const
96 { 110 {
97 TRACE_CLOSURE (); 111 TRACE_CLOSURE ();
98 Coverage::Iter iter; 112 Coverage::Iter iter;
99 for (iter.init (this+coverage); iter.more (); iter.next ()) { 113 for (iter.init (this+coverage); iter.more (); iter.next ()) {
100 if (c->glyphs->has (iter.get_glyph ())) 114 if (c->glyphs->has (iter.get_glyph ()))
101 c->glyphs->add (substitute[iter.get_coverage ()]); 115 c->glyphs->add (substitute[iter.get_coverage ()]);
102 } 116 }
103 } 117 }
104 118
105 inline bool would_apply (hb_codepoint_t glyph_id) const 119 inline const Coverage &get_coverage (void) const
106 { 120 {
107 return (this+coverage) (glyph_id) != NOT_COVERED; 121 return this+coverage;
108 } 122 }
109 123
110 inline bool apply (hb_apply_context_t *c) const 124 inline bool apply (hb_apply_context_t *c) const
111 { 125 {
112 TRACE_APPLY (); 126 TRACE_APPLY ();
113 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; 127 hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
114 unsigned int index = (this+coverage) (glyph_id); 128 unsigned int index = (this+coverage) (glyph_id);
115 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); 129 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
116 130
117 if (unlikely (index >= substitute.len)) return TRACE_RETURN (false); 131 if (unlikely (index >= substitute.len)) return TRACE_RETURN (false);
118 132
119 glyph_id = substitute[index]; 133 glyph_id = substitute[index];
120 c->replace_glyph (glyph_id); 134 c->replace_glyph (glyph_id);
121 135
122 return TRACE_RETURN (true); 136 return TRACE_RETURN (true);
123 } 137 }
124 138
139 inline bool serialize (hb_serialize_context_t *c,
140 Supplier<GlyphID> &glyphs,
141 Supplier<GlyphID> &substitutes,
142 unsigned int num_glyphs)
143 {
144 TRACE_SERIALIZE ();
145 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
146 if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return TR ACE_RETURN (false);
147 if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs ))) return TRACE_RETURN (false);
148 return TRACE_RETURN (true);
149 }
150
125 inline bool sanitize (hb_sanitize_context_t *c) { 151 inline bool sanitize (hb_sanitize_context_t *c) {
126 TRACE_SANITIZE (); 152 TRACE_SANITIZE ();
127 return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c)) ; 153 return TRACE_RETURN (coverage.sanitize (c, this) && substitute.sanitize (c)) ;
128 } 154 }
129 155
130 private: 156 protected:
131 USHORT format; /* Format identifier--format = 2 */ 157 USHORT format; /* Format identifier--format = 2 */
132 OffsetTo<Coverage> 158 OffsetTo<Coverage>
133 coverage; /* Offset to Coverage table--from 159 coverage; /* Offset to Coverage table--from
134 * beginning of Substitution table */ 160 * beginning of Substitution table */
135 ArrayOf<GlyphID> 161 ArrayOf<GlyphID>
136 substitute; /* Array of substitute 162 substitute; /* Array of substitute
137 * GlyphIDs--ordered by Coverage Index * / 163 * GlyphIDs--ordered by Coverage Index * /
138 public: 164 public:
139 DEFINE_SIZE_ARRAY (6, substitute); 165 DEFINE_SIZE_ARRAY (6, substitute);
140 }; 166 };
141 167
142 struct SingleSubst 168 struct SingleSubst
143 { 169 {
144 friend struct SubstLookupSubTable; 170 friend struct SubstLookupSubTable;
171 friend struct SubstLookup;
145 172
146 private: 173 private:
147 174
148 inline void closure (hb_closure_context_t *c) const 175 inline void closure (hb_closure_context_t *c) const
149 { 176 {
150 TRACE_CLOSURE (); 177 TRACE_CLOSURE ();
151 switch (u.format) { 178 switch (u.format) {
152 case 1: u.format1.closure (c); break; 179 case 1: u.format1.closure (c); break;
153 case 2: u.format2.closure (c); break; 180 case 2: u.format2.closure (c); break;
154 default: break; 181 default: break;
155 } 182 }
156 } 183 }
157 184
158 inline bool would_apply (hb_codepoint_t glyph_id) const 185 inline const Coverage &get_coverage (void) const
159 { 186 {
160 switch (u.format) { 187 switch (u.format) {
161 case 1: return u.format1.would_apply (glyph_id); 188 case 1: return u.format1.get_coverage ();
162 case 2: return u.format2.would_apply (glyph_id); 189 case 2: return u.format2.get_coverage ();
163 default:return false; 190 default:return Null(Coverage);
164 } 191 }
165 } 192 }
166 193
167 inline bool apply (hb_apply_context_t *c) const 194 inline bool apply (hb_apply_context_t *c) const
168 { 195 {
169 TRACE_APPLY (); 196 TRACE_APPLY ();
170 switch (u.format) { 197 switch (u.format) {
171 case 1: return TRACE_RETURN (u.format1.apply (c)); 198 case 1: return TRACE_RETURN (u.format1.apply (c));
172 case 2: return TRACE_RETURN (u.format2.apply (c)); 199 case 2: return TRACE_RETURN (u.format2.apply (c));
173 default:return TRACE_RETURN (false); 200 default:return TRACE_RETURN (false);
174 } 201 }
175 } 202 }
176 203
204 inline bool serialize (hb_serialize_context_t *c,
205 Supplier<GlyphID> &glyphs,
206 Supplier<GlyphID> &substitutes,
207 unsigned int num_glyphs)
208 {
209 TRACE_SERIALIZE ();
210 if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
211 unsigned int format = 2;
212 int delta;
213 if (num_glyphs) {
214 format = 1;
215 /* TODO(serialize) check for wrap-around */
216 delta = substitutes[0] - glyphs[0];
217 for (unsigned int i = 1; i < num_glyphs; i++)
218 if (delta != substitutes[i] - glyphs[i]) {
219 format = 2;
220 break;
221 }
222 }
223 u.format.set (format);
224 switch (u.format) {
225 case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs, del ta));
226 case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, substitutes, nu m_glyphs));
227 default:return TRACE_RETURN (false);
228 }
229 }
230
177 inline bool sanitize (hb_sanitize_context_t *c) { 231 inline bool sanitize (hb_sanitize_context_t *c) {
178 TRACE_SANITIZE (); 232 TRACE_SANITIZE ();
179 if (!u.format.sanitize (c)) return TRACE_RETURN (false); 233 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
180 switch (u.format) { 234 switch (u.format) {
181 case 1: return TRACE_RETURN (u.format1.sanitize (c)); 235 case 1: return TRACE_RETURN (u.format1.sanitize (c));
182 case 2: return TRACE_RETURN (u.format2.sanitize (c)); 236 case 2: return TRACE_RETURN (u.format2.sanitize (c));
183 default:return TRACE_RETURN (true); 237 default:return TRACE_RETURN (true);
184 } 238 }
185 } 239 }
186 240
187 private: 241 protected:
188 union { 242 union {
189 USHORT format; /* Format identifier */ 243 USHORT format; /* Format identifier */
190 SingleSubstFormat1 format1; 244 SingleSubstFormat1 format1;
191 SingleSubstFormat2 format2; 245 SingleSubstFormat2 format2;
192 } u; 246 } u;
193 }; 247 };
194 248
195 249
196 struct Sequence 250 struct Sequence
197 { 251 {
198 friend struct MultipleSubstFormat1; 252 friend struct MultipleSubstFormat1;
199 253
200 private: 254 private:
201 255
202 inline void closure (hb_closure_context_t *c) const 256 inline void closure (hb_closure_context_t *c) const
203 { 257 {
204 TRACE_CLOSURE (); 258 TRACE_CLOSURE ();
205 unsigned int count = substitute.len; 259 unsigned int count = substitute.len;
206 for (unsigned int i = 0; i < count; i++) 260 for (unsigned int i = 0; i < count; i++)
207 c->glyphs->add (substitute[i]); 261 c->glyphs->add (substitute[i]);
208 } 262 }
209 263
210 inline bool apply (hb_apply_context_t *c) const 264 inline bool apply (hb_apply_context_t *c) const
211 { 265 {
212 TRACE_APPLY (); 266 TRACE_APPLY ();
213 if (unlikely (!substitute.len)) return TRACE_RETURN (false); 267 if (unlikely (!substitute.len)) return TRACE_RETURN (false);
214 268
215 unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ? HB_OT _LAYOUT_GLYPH_CLASS_BASE_GLYPH : 0; 269 unsigned int klass = c->property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE ? HB_OT _LAYOUT_GLYPH_CLASS_BASE_GLYPH : 0;
216 c->replace_glyphs_be16 (1, substitute.len, (const char *) substitute.array, klass); 270 unsigned int count = substitute.len;
271 for (unsigned int i = 0; i < count; i++) {
272 set_lig_props_for_component (c->buffer->cur(), i);
273 c->output_glyph (substitute.array[i], klass);
274 }
275 c->buffer->skip_glyph ();
217 276
218 return TRACE_RETURN (true); 277 return TRACE_RETURN (true);
219 } 278 }
220 279
280 inline bool serialize (hb_serialize_context_t *c,
281 Supplier<GlyphID> &glyphs,
282 unsigned int num_glyphs)
283 {
284 TRACE_SERIALIZE ();
285 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
286 if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return TRACE_R ETURN (false);
287 return TRACE_RETURN (true);
288 }
289
221 public: 290 public:
222 inline bool sanitize (hb_sanitize_context_t *c) { 291 inline bool sanitize (hb_sanitize_context_t *c) {
223 TRACE_SANITIZE (); 292 TRACE_SANITIZE ();
224 return TRACE_RETURN (substitute.sanitize (c)); 293 return TRACE_RETURN (substitute.sanitize (c));
225 } 294 }
226 295
227 private: 296 protected:
228 ArrayOf<GlyphID> 297 ArrayOf<GlyphID>
229 substitute; /* String of GlyphIDs to substitute */ 298 substitute; /* String of GlyphIDs to substitute */
230 public: 299 public:
231 DEFINE_SIZE_ARRAY (2, substitute); 300 DEFINE_SIZE_ARRAY (2, substitute);
232 }; 301 };
233 302
234 struct MultipleSubstFormat1 303 struct MultipleSubstFormat1
235 { 304 {
236 friend struct MultipleSubst; 305 friend struct MultipleSubst;
237 306
238 private: 307 private:
239 308
240 inline void closure (hb_closure_context_t *c) const 309 inline void closure (hb_closure_context_t *c) const
241 { 310 {
242 TRACE_CLOSURE (); 311 TRACE_CLOSURE ();
243 Coverage::Iter iter; 312 Coverage::Iter iter;
244 for (iter.init (this+coverage); iter.more (); iter.next ()) { 313 for (iter.init (this+coverage); iter.more (); iter.next ()) {
245 if (c->glyphs->has (iter.get_glyph ())) 314 if (c->glyphs->has (iter.get_glyph ()))
246 (this+sequence[iter.get_coverage ()]).closure (c); 315 (this+sequence[iter.get_coverage ()]).closure (c);
247 } 316 }
248 } 317 }
249 318
250 inline bool would_apply (hb_codepoint_t glyph_id) const 319 inline const Coverage &get_coverage (void) const
251 { 320 {
252 return (this+coverage) (glyph_id) != NOT_COVERED; 321 return this+coverage;
253 } 322 }
254 323
255 inline bool apply (hb_apply_context_t *c) const 324 inline bool apply (hb_apply_context_t *c) const
256 { 325 {
257 TRACE_APPLY (); 326 TRACE_APPLY ();
258 327
259 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); 328 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
260 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); 329 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
261 330
262 return TRACE_RETURN ((this+sequence[index]).apply (c)); 331 return TRACE_RETURN ((this+sequence[index]).apply (c));
263 } 332 }
264 333
334 inline bool serialize (hb_serialize_context_t *c,
335 Supplier<GlyphID> &glyphs,
336 Supplier<unsigned int> &substitute_len_list,
337 unsigned int num_glyphs,
338 Supplier<GlyphID> &substitute_glyphs_list)
339 {
340 TRACE_SERIALIZE ();
341 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
342 if (unlikely (!sequence.serialize (c, num_glyphs))) return TRACE_RETURN (fal se);
343 for (unsigned int i = 0; i < num_glyphs; i++)
344 if (unlikely (!sequence[i].serialize (c, this).serialize (c,
345 substitute_glyph s_list,
346 substitute_len_l ist[i]))) return TRACE_RETURN (false);
347 substitute_len_list.advance (num_glyphs);
348 if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs ))) return TRACE_RETURN (false);
349 return TRACE_RETURN (true);
350 }
351
265 inline bool sanitize (hb_sanitize_context_t *c) { 352 inline bool sanitize (hb_sanitize_context_t *c) {
266 TRACE_SANITIZE (); 353 TRACE_SANITIZE ();
267 return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, th is)); 354 return TRACE_RETURN (coverage.sanitize (c, this) && sequence.sanitize (c, th is));
268 } 355 }
269 356
270 private: 357 protected:
271 USHORT format; /* Format identifier--format = 1 */ 358 USHORT format; /* Format identifier--format = 1 */
272 OffsetTo<Coverage> 359 OffsetTo<Coverage>
273 coverage; /* Offset to Coverage table--from 360 coverage; /* Offset to Coverage table--from
274 * beginning of Substitution table */ 361 * beginning of Substitution table */
275 OffsetArrayOf<Sequence> 362 OffsetArrayOf<Sequence>
276 sequence; /* Array of Sequence tables 363 sequence; /* Array of Sequence tables
277 * ordered by Coverage Index */ 364 * ordered by Coverage Index */
278 public: 365 public:
279 DEFINE_SIZE_ARRAY (6, sequence); 366 DEFINE_SIZE_ARRAY (6, sequence);
280 }; 367 };
281 368
282 struct MultipleSubst 369 struct MultipleSubst
283 { 370 {
284 friend struct SubstLookupSubTable; 371 friend struct SubstLookupSubTable;
372 friend struct SubstLookup;
285 373
286 private: 374 private:
287 375
288 inline void closure (hb_closure_context_t *c) const 376 inline void closure (hb_closure_context_t *c) const
289 { 377 {
290 TRACE_CLOSURE (); 378 TRACE_CLOSURE ();
291 switch (u.format) { 379 switch (u.format) {
292 case 1: u.format1.closure (c); break; 380 case 1: u.format1.closure (c); break;
293 default: break; 381 default: break;
294 } 382 }
295 } 383 }
296 384
297 inline bool would_apply (hb_codepoint_t glyph_id) const 385 inline const Coverage &get_coverage (void) const
298 { 386 {
299 switch (u.format) { 387 switch (u.format) {
300 case 1: return u.format1.would_apply (glyph_id); 388 case 1: return u.format1.get_coverage ();
301 default:return false; 389 default:return Null(Coverage);
302 } 390 }
303 } 391 }
304 392
305 inline bool apply (hb_apply_context_t *c) const 393 inline bool apply (hb_apply_context_t *c) const
306 { 394 {
307 TRACE_APPLY (); 395 TRACE_APPLY ();
308 switch (u.format) { 396 switch (u.format) {
309 case 1: return TRACE_RETURN (u.format1.apply (c)); 397 case 1: return TRACE_RETURN (u.format1.apply (c));
310 default:return TRACE_RETURN (false); 398 default:return TRACE_RETURN (false);
311 } 399 }
312 } 400 }
313 401
402 inline bool serialize (hb_serialize_context_t *c,
403 Supplier<GlyphID> &glyphs,
404 Supplier<unsigned int> &substitute_len_list,
405 unsigned int num_glyphs,
406 Supplier<GlyphID> &substitute_glyphs_list)
407 {
408 TRACE_SERIALIZE ();
409 if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
410 unsigned int format = 1;
411 u.format.set (format);
412 switch (u.format) {
413 case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, substitute_len_ list, num_glyphs, substitute_glyphs_list));
414 default:return TRACE_RETURN (false);
415 }
416 }
417
314 inline bool sanitize (hb_sanitize_context_t *c) { 418 inline bool sanitize (hb_sanitize_context_t *c) {
315 TRACE_SANITIZE (); 419 TRACE_SANITIZE ();
316 if (!u.format.sanitize (c)) return TRACE_RETURN (false); 420 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
317 switch (u.format) { 421 switch (u.format) {
318 case 1: return TRACE_RETURN (u.format1.sanitize (c)); 422 case 1: return TRACE_RETURN (u.format1.sanitize (c));
319 default:return TRACE_RETURN (true); 423 default:return TRACE_RETURN (true);
320 } 424 }
321 } 425 }
322 426
323 private: 427 protected:
324 union { 428 union {
325 USHORT format; /* Format identifier */ 429 USHORT format; /* Format identifier */
326 MultipleSubstFormat1 format1; 430 MultipleSubstFormat1 format1;
327 } u; 431 } u;
328 }; 432 };
329 433
330 434
331 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in 435 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in
332 * arbitrary order */ 436 * arbitrary order */
333 437
(...skipping 10 matching lines...) Expand all
344 for (iter.init (this+coverage); iter.more (); iter.next ()) { 448 for (iter.init (this+coverage); iter.more (); iter.next ()) {
345 if (c->glyphs->has (iter.get_glyph ())) { 449 if (c->glyphs->has (iter.get_glyph ())) {
346 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; 450 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
347 unsigned int count = alt_set.len; 451 unsigned int count = alt_set.len;
348 for (unsigned int i = 0; i < count; i++) 452 for (unsigned int i = 0; i < count; i++)
349 c->glyphs->add (alt_set[i]); 453 c->glyphs->add (alt_set[i]);
350 } 454 }
351 } 455 }
352 } 456 }
353 457
354 inline bool would_apply (hb_codepoint_t glyph_id) const 458 inline const Coverage &get_coverage (void) const
355 { 459 {
356 return (this+coverage) (glyph_id) != NOT_COVERED; 460 return this+coverage;
357 } 461 }
358 462
359 inline bool apply (hb_apply_context_t *c) const 463 inline bool apply (hb_apply_context_t *c) const
360 { 464 {
361 TRACE_APPLY (); 465 TRACE_APPLY ();
362 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; 466 hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
363 467
364 unsigned int index = (this+coverage) (glyph_id); 468 unsigned int index = (this+coverage) (glyph_id);
365 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); 469 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
366 470
(...skipping 10 matching lines...) Expand all
377 481
378 if (unlikely (alt_index > alt_set.len || alt_index == 0)) return TRACE_RETUR N (false); 482 if (unlikely (alt_index > alt_set.len || alt_index == 0)) return TRACE_RETUR N (false);
379 483
380 glyph_id = alt_set[alt_index - 1]; 484 glyph_id = alt_set[alt_index - 1];
381 485
382 c->replace_glyph (glyph_id); 486 c->replace_glyph (glyph_id);
383 487
384 return TRACE_RETURN (true); 488 return TRACE_RETURN (true);
385 } 489 }
386 490
491 inline bool serialize (hb_serialize_context_t *c,
492 Supplier<GlyphID> &glyphs,
493 Supplier<unsigned int> &alternate_len_list,
494 unsigned int num_glyphs,
495 Supplier<GlyphID> &alternate_glyphs_list)
496 {
497 TRACE_SERIALIZE ();
498 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
499 if (unlikely (!alternateSet.serialize (c, num_glyphs))) return TRACE_RETURN (false);
500 for (unsigned int i = 0; i < num_glyphs; i++)
501 if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
502 alternate_gl yphs_list,
503 alternate_le n_list[i]))) return TRACE_RETURN (false);
504 alternate_len_list.advance (num_glyphs);
505 if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs ))) return TRACE_RETURN (false);
506 return TRACE_RETURN (true);
507 }
508
387 inline bool sanitize (hb_sanitize_context_t *c) { 509 inline bool sanitize (hb_sanitize_context_t *c) {
388 TRACE_SANITIZE (); 510 TRACE_SANITIZE ();
389 return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c , this)); 511 return TRACE_RETURN (coverage.sanitize (c, this) && alternateSet.sanitize (c , this));
390 } 512 }
391 513
392 private: 514 protected:
393 USHORT format; /* Format identifier--format = 1 */ 515 USHORT format; /* Format identifier--format = 1 */
394 OffsetTo<Coverage> 516 OffsetTo<Coverage>
395 coverage; /* Offset to Coverage table--from 517 coverage; /* Offset to Coverage table--from
396 * beginning of Substitution table */ 518 * beginning of Substitution table */
397 OffsetArrayOf<AlternateSet> 519 OffsetArrayOf<AlternateSet>
398 alternateSet; /* Array of AlternateSet tables 520 alternateSet; /* Array of AlternateSet tables
399 * ordered by Coverage Index */ 521 * ordered by Coverage Index */
400 public: 522 public:
401 DEFINE_SIZE_ARRAY (6, alternateSet); 523 DEFINE_SIZE_ARRAY (6, alternateSet);
402 }; 524 };
403 525
404 struct AlternateSubst 526 struct AlternateSubst
405 { 527 {
406 friend struct SubstLookupSubTable; 528 friend struct SubstLookupSubTable;
529 friend struct SubstLookup;
407 530
408 private: 531 private:
409 532
410 inline void closure (hb_closure_context_t *c) const 533 inline void closure (hb_closure_context_t *c) const
411 { 534 {
412 TRACE_CLOSURE (); 535 TRACE_CLOSURE ();
413 switch (u.format) { 536 switch (u.format) {
414 case 1: u.format1.closure (c); break; 537 case 1: u.format1.closure (c); break;
415 default: break; 538 default: break;
416 } 539 }
417 } 540 }
418 541
419 inline bool would_apply (hb_codepoint_t glyph_id) const 542 inline const Coverage &get_coverage (void) const
420 { 543 {
421 switch (u.format) { 544 switch (u.format) {
422 case 1: return u.format1.would_apply (glyph_id); 545 case 1: return u.format1.get_coverage ();
423 default:return false; 546 default:return Null(Coverage);
424 } 547 }
425 } 548 }
426 549
427 inline bool apply (hb_apply_context_t *c) const 550 inline bool apply (hb_apply_context_t *c) const
428 { 551 {
429 TRACE_APPLY (); 552 TRACE_APPLY ();
430 switch (u.format) { 553 switch (u.format) {
431 case 1: return TRACE_RETURN (u.format1.apply (c)); 554 case 1: return TRACE_RETURN (u.format1.apply (c));
432 default:return TRACE_RETURN (false); 555 default:return TRACE_RETURN (false);
433 } 556 }
434 } 557 }
435 558
559 inline bool serialize (hb_serialize_context_t *c,
560 Supplier<GlyphID> &glyphs,
561 Supplier<unsigned int> &alternate_len_list,
562 unsigned int num_glyphs,
563 Supplier<GlyphID> &alternate_glyphs_list)
564 {
565 TRACE_SERIALIZE ();
566 if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
567 unsigned int format = 1;
568 u.format.set (format);
569 switch (u.format) {
570 case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, alternate_len_l ist, num_glyphs, alternate_glyphs_list));
571 default:return TRACE_RETURN (false);
572 }
573 }
574
436 inline bool sanitize (hb_sanitize_context_t *c) { 575 inline bool sanitize (hb_sanitize_context_t *c) {
437 TRACE_SANITIZE (); 576 TRACE_SANITIZE ();
438 if (!u.format.sanitize (c)) return TRACE_RETURN (false); 577 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
439 switch (u.format) { 578 switch (u.format) {
440 case 1: return TRACE_RETURN (u.format1.sanitize (c)); 579 case 1: return TRACE_RETURN (u.format1.sanitize (c));
441 default:return TRACE_RETURN (true); 580 default:return TRACE_RETURN (true);
442 } 581 }
443 } 582 }
444 583
445 private: 584 protected:
446 union { 585 union {
447 USHORT format; /* Format identifier */ 586 USHORT format; /* Format identifier */
448 AlternateSubstFormat1 format1; 587 AlternateSubstFormat1 format1;
449 } u; 588 } u;
450 }; 589 };
451 590
452 591
453 struct Ligature 592 struct Ligature
454 { 593 {
455 friend struct LigatureSet; 594 friend struct LigatureSet;
456 595
457 private: 596 private:
458 597
459 inline void closure (hb_closure_context_t *c) const 598 inline void closure (hb_closure_context_t *c) const
460 { 599 {
461 TRACE_CLOSURE (); 600 TRACE_CLOSURE ();
462 unsigned int count = component.len; 601 unsigned int count = component.len;
463 for (unsigned int i = 1; i < count; i++) 602 for (unsigned int i = 1; i < count; i++)
464 if (!c->glyphs->has (component[i])) 603 if (!c->glyphs->has (component[i]))
465 return; 604 return;
466 c->glyphs->add (ligGlyph); 605 c->glyphs->add (ligGlyph);
467 } 606 }
468 607
469 inline bool would_apply (hb_codepoint_t second) const 608 inline bool would_apply (hb_would_apply_context_t *c) const
470 { 609 {
471 return component.len == 2 && component[1] == second; 610 if (c->len != component.len)
611 return false;
612
613 for (unsigned int i = 1; i < c->len; i++)
614 if (likely (c->glyphs[i] != component[i]))
615 » return false;
616
617 return true;
472 } 618 }
473 619
474 inline bool apply (hb_apply_context_t *c) const 620 inline bool apply (hb_apply_context_t *c) const
475 { 621 {
476 TRACE_APPLY (); 622 TRACE_APPLY ();
477 unsigned int count = component.len; 623 unsigned int count = component.len;
478 if (unlikely (count < 2)) return TRACE_RETURN (false); 624 if (unlikely (count < 1)) return TRACE_RETURN (false);
479 625
480 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buff er->idx, count - 1); 626 unsigned int end_offset;
481 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); 627 bool is_mark_ligature;
628 unsigned int total_component_count;
482 629
483 bool first_was_mark = (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); 630 if (likely (!match_input (c, count,
484 bool found_non_mark = false; 631 » » » &component[1],
632 » » » match_glyph,
633 » » » NULL,
634 » » » &end_offset,
635 » » » &is_mark_ligature,
636 » » » &total_component_count)))
637 return TRACE_RETURN (false);
485 638
486 for (unsigned int i = 1; i < count; i++) 639 /* Deal, we are forming the ligature. */
487 { 640 c->buffer->merge_clusters (c->buffer->idx, c->buffer->idx + end_offset);
488 unsigned int property;
489 641
490 if (!skippy_iter.next (&property)) return TRACE_RETURN (false); 642 ligate_input (c,
491 643 » » count,
492 found_non_mark |= !(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK); 644 » » &component[1],
493 645 » » ligGlyph,
494 if (likely (c->buffer->info[skippy_iter.idx].codepoint != component[i])) r eturn TRACE_RETURN (false); 646 » » match_glyph,
495 } 647 » » NULL,
496 648 » » is_mark_ligature,
497 unsigned int klass = first_was_mark && found_non_mark ? HB_OT_LAYOUT_GLYPH_C LASS_LIGATURE : 0; 649 » » total_component_count);
498
499 /* Allocate new ligature id */
500 unsigned int lig_id = allocate_lig_id (c->buffer);
501 set_lig_props (c->buffer->cur(), lig_id, 0);
502
503 if (skippy_iter.idx < c->buffer->idx + count) /* No input glyphs skipped */
504 {
505 c->replace_glyphs_be16 (count, 1, (const char *) &ligGlyph, klass);
506 }
507 else
508 {
509 c->replace_glyph (ligGlyph);
510
511 /* Now we must do a second loop to copy the skipped glyphs to
512 » `out' and assign component values to it. We start with the
513 » glyph after the first component. Glyphs between component
514 » i and i+1 belong to component i. Together with the lig_id
515 » value it is later possible to check whether a specific
516 » component value really belongs to a given ligature. */
517
518 for (unsigned int i = 1; i < count; i++)
519 {
520 » while (c->should_mark_skip_current_glyph ())
521 » {
522 » set_lig_props (c->buffer->cur(), lig_id, i);
523 » c->replace_glyph (c->buffer->cur().codepoint);
524 » }
525
526 » /* Skip the base glyph */
527 » c->buffer->idx++;
528 }
529 }
530 650
531 return TRACE_RETURN (true); 651 return TRACE_RETURN (true);
532 } 652 }
533 653
654 inline bool serialize (hb_serialize_context_t *c,
655 GlyphID ligature,
656 Supplier<GlyphID> &components, /* Starting from second */
657 unsigned int num_components /* Including first componen t */)
658 {
659 TRACE_SERIALIZE ();
660 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
661 ligGlyph = ligature;
662 if (unlikely (!component.serialize (c, components, num_components))) return TRACE_RETURN (false);
663 return TRACE_RETURN (true);
664 }
665
534 public: 666 public:
535 inline bool sanitize (hb_sanitize_context_t *c) { 667 inline bool sanitize (hb_sanitize_context_t *c) {
536 TRACE_SANITIZE (); 668 TRACE_SANITIZE ();
537 return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c)); 669 return TRACE_RETURN (ligGlyph.sanitize (c) && component.sanitize (c));
538 } 670 }
539 671
540 private: 672 protected:
541 GlyphID ligGlyph; /* GlyphID of ligature to substitute */ 673 GlyphID ligGlyph; /* GlyphID of ligature to substitute */
542 HeadlessArrayOf<GlyphID> 674 HeadlessArrayOf<GlyphID>
543 component; /* Array of component GlyphIDs--start 675 component; /* Array of component GlyphIDs--start
544 * with the second component--ordered 676 * with the second component--ordered
545 * in writing direction */ 677 * in writing direction */
546 public: 678 public:
547 DEFINE_SIZE_ARRAY (4, component); 679 DEFINE_SIZE_ARRAY (4, component);
548 }; 680 };
549 681
550 struct LigatureSet 682 struct LigatureSet
551 { 683 {
552 friend struct LigatureSubstFormat1; 684 friend struct LigatureSubstFormat1;
553 685
554 private: 686 private:
555 687
556 inline void closure (hb_closure_context_t *c) const 688 inline void closure (hb_closure_context_t *c) const
557 { 689 {
558 TRACE_CLOSURE (); 690 TRACE_CLOSURE ();
559 unsigned int num_ligs = ligature.len; 691 unsigned int num_ligs = ligature.len;
560 for (unsigned int i = 0; i < num_ligs; i++) 692 for (unsigned int i = 0; i < num_ligs; i++)
561 (this+ligature[i]).closure (c); 693 (this+ligature[i]).closure (c);
562 } 694 }
563 695
564 inline bool would_apply (hb_codepoint_t second) const 696 inline bool would_apply (hb_would_apply_context_t *c) const
565 { 697 {
566 unsigned int num_ligs = ligature.len; 698 unsigned int num_ligs = ligature.len;
567 for (unsigned int i = 0; i < num_ligs; i++) 699 for (unsigned int i = 0; i < num_ligs; i++)
568 { 700 {
569 const Ligature &lig = this+ligature[i]; 701 const Ligature &lig = this+ligature[i];
570 if (lig.would_apply (second)) 702 if (lig.would_apply (c))
571 return true; 703 return true;
572 } 704 }
573 return false; 705 return false;
574 } 706 }
575 707
576 inline bool apply (hb_apply_context_t *c) const 708 inline bool apply (hb_apply_context_t *c) const
577 { 709 {
578 TRACE_APPLY (); 710 TRACE_APPLY ();
579 unsigned int num_ligs = ligature.len; 711 unsigned int num_ligs = ligature.len;
580 for (unsigned int i = 0; i < num_ligs; i++) 712 for (unsigned int i = 0; i < num_ligs; i++)
581 { 713 {
582 const Ligature &lig = this+ligature[i]; 714 const Ligature &lig = this+ligature[i];
583 if (lig.apply (c)) return TRACE_RETURN (true); 715 if (lig.apply (c)) return TRACE_RETURN (true);
584 } 716 }
585 717
586 return TRACE_RETURN (false); 718 return TRACE_RETURN (false);
587 } 719 }
588 720
721 inline bool serialize (hb_serialize_context_t *c,
722 Supplier<GlyphID> &ligatures,
723 Supplier<unsigned int> &component_count_list,
724 unsigned int num_ligatures,
725 Supplier<GlyphID> &component_list /* Starting from seco nd for each ligature */)
726 {
727 TRACE_SERIALIZE ();
728 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
729 if (unlikely (!ligature.serialize (c, num_ligatures))) return TRACE_RETURN ( false);
730 for (unsigned int i = 0; i < num_ligatures; i++)
731 if (unlikely (!ligature[i].serialize (c, this).serialize (c,
732 ligatures[i],
733 component_list,
734 component_count_ list[i]))) return TRACE_RETURN (false);
735 ligatures.advance (num_ligatures);
736 component_count_list.advance (num_ligatures);
737 return TRACE_RETURN (true);
738 }
739
589 public: 740 public:
590 inline bool sanitize (hb_sanitize_context_t *c) { 741 inline bool sanitize (hb_sanitize_context_t *c) {
591 TRACE_SANITIZE (); 742 TRACE_SANITIZE ();
592 return TRACE_RETURN (ligature.sanitize (c, this)); 743 return TRACE_RETURN (ligature.sanitize (c, this));
593 } 744 }
594 745
595 private: 746 protected:
596 OffsetArrayOf<Ligature> 747 OffsetArrayOf<Ligature>
597 ligature; /* Array LigatureSet tables 748 ligature; /* Array LigatureSet tables
598 * ordered by preference */ 749 * ordered by preference */
599 public: 750 public:
600 DEFINE_SIZE_ARRAY (2, ligature); 751 DEFINE_SIZE_ARRAY (2, ligature);
601 }; 752 };
602 753
603 struct LigatureSubstFormat1 754 struct LigatureSubstFormat1
604 { 755 {
605 friend struct LigatureSubst; 756 friend struct LigatureSubst;
606 757
607 private: 758 private:
608 759
609 inline void closure (hb_closure_context_t *c) const 760 inline void closure (hb_closure_context_t *c) const
610 { 761 {
611 TRACE_CLOSURE (); 762 TRACE_CLOSURE ();
612 Coverage::Iter iter; 763 Coverage::Iter iter;
613 for (iter.init (this+coverage); iter.more (); iter.next ()) { 764 for (iter.init (this+coverage); iter.more (); iter.next ()) {
614 if (c->glyphs->has (iter.get_glyph ())) 765 if (c->glyphs->has (iter.get_glyph ()))
615 (this+ligatureSet[iter.get_coverage ()]).closure (c); 766 (this+ligatureSet[iter.get_coverage ()]).closure (c);
616 } 767 }
617 } 768 }
618 769
619 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const 770 inline const Coverage &get_coverage (void) const
620 { 771 {
621 unsigned int index; 772 return this+coverage;
622 return (index = (this+coverage) (first)) != NOT_COVERED && 773 }
623 » (this+ligatureSet[index]).would_apply (second); 774
775 inline bool would_apply (hb_would_apply_context_t *c) const
776 {
777 return (this+ligatureSet[(this+coverage) (c->glyphs[0])]).would_apply (c);
624 } 778 }
625 779
626 inline bool apply (hb_apply_context_t *c) const 780 inline bool apply (hb_apply_context_t *c) const
627 { 781 {
628 TRACE_APPLY (); 782 TRACE_APPLY ();
629 hb_codepoint_t glyph_id = c->buffer->cur().codepoint; 783 hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
630 784
631 unsigned int index = (this+coverage) (glyph_id); 785 unsigned int index = (this+coverage) (glyph_id);
632 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); 786 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
633 787
634 const LigatureSet &lig_set = this+ligatureSet[index]; 788 const LigatureSet &lig_set = this+ligatureSet[index];
635 return TRACE_RETURN (lig_set.apply (c)); 789 return TRACE_RETURN (lig_set.apply (c));
636 } 790 }
637 791
792 inline bool serialize (hb_serialize_context_t *c,
793 Supplier<GlyphID> &first_glyphs,
794 Supplier<unsigned int> &ligature_per_first_glyph_count_ list,
795 unsigned int num_first_glyphs,
796 Supplier<GlyphID> &ligatures_list,
797 Supplier<unsigned int> &component_count_list,
798 Supplier<GlyphID> &component_list /* Starting from seco nd for each ligature */)
799 {
800 TRACE_SERIALIZE ();
801 if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
802 if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return TRACE_RE TURN (false);
803 for (unsigned int i = 0; i < num_first_glyphs; i++)
804 if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
805 ligatures_lis t,
806 component_cou nt_list,
807 ligature_per_ first_glyph_count_list[i],
808 component_lis t))) return TRACE_RETURN (false);
809 ligature_per_first_glyph_count_list.advance (num_first_glyphs);
810 if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_ first_glyphs))) return TRACE_RETURN (false);
811 return TRACE_RETURN (true);
812 }
813
638 inline bool sanitize (hb_sanitize_context_t *c) { 814 inline bool sanitize (hb_sanitize_context_t *c) {
639 TRACE_SANITIZE (); 815 TRACE_SANITIZE ();
640 return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this)); 816 return TRACE_RETURN (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
641 } 817 }
642 818
643 private: 819 protected:
644 USHORT format; /* Format identifier--format = 1 */ 820 USHORT format; /* Format identifier--format = 1 */
645 OffsetTo<Coverage> 821 OffsetTo<Coverage>
646 coverage; /* Offset to Coverage table--from 822 coverage; /* Offset to Coverage table--from
647 * beginning of Substitution table */ 823 * beginning of Substitution table */
648 OffsetArrayOf<LigatureSet> 824 OffsetArrayOf<LigatureSet>
649 ligatureSet; /* Array LigatureSet tables 825 ligatureSet; /* Array LigatureSet tables
650 * ordered by Coverage Index */ 826 * ordered by Coverage Index */
651 public: 827 public:
652 DEFINE_SIZE_ARRAY (6, ligatureSet); 828 DEFINE_SIZE_ARRAY (6, ligatureSet);
653 }; 829 };
654 830
655 struct LigatureSubst 831 struct LigatureSubst
656 { 832 {
657 friend struct SubstLookupSubTable; 833 friend struct SubstLookupSubTable;
834 friend struct SubstLookup;
658 835
659 private: 836 private:
660 837
661 inline void closure (hb_closure_context_t *c) const 838 inline void closure (hb_closure_context_t *c) const
662 { 839 {
663 TRACE_CLOSURE (); 840 TRACE_CLOSURE ();
664 switch (u.format) { 841 switch (u.format) {
665 case 1: u.format1.closure (c); break; 842 case 1: u.format1.closure (c); break;
666 default: break; 843 default: break;
667 } 844 }
668 } 845 }
669 846
670 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const 847 inline const Coverage &get_coverage (void) const
671 { 848 {
672 switch (u.format) { 849 switch (u.format) {
673 case 1: return u.format1.would_apply (first, second); 850 case 1: return u.format1.get_coverage ();
851 default:return Null(Coverage);
852 }
853 }
854
855 inline bool would_apply (hb_would_apply_context_t *c) const
856 {
857 switch (u.format) {
858 case 1: return u.format1.would_apply (c);
674 default:return false; 859 default:return false;
675 } 860 }
676 } 861 }
677 862
678 inline bool apply (hb_apply_context_t *c) const 863 inline bool apply (hb_apply_context_t *c) const
679 { 864 {
680 TRACE_APPLY (); 865 TRACE_APPLY ();
681 switch (u.format) { 866 switch (u.format) {
682 case 1: return TRACE_RETURN (u.format1.apply (c)); 867 case 1: return TRACE_RETURN (u.format1.apply (c));
683 default:return TRACE_RETURN (false); 868 default:return TRACE_RETURN (false);
684 } 869 }
685 } 870 }
686 871
872 inline bool serialize (hb_serialize_context_t *c,
873 Supplier<GlyphID> &first_glyphs,
874 Supplier<unsigned int> &ligature_per_first_glyph_count_ list,
875 unsigned int num_first_glyphs,
876 Supplier<GlyphID> &ligatures_list,
877 Supplier<unsigned int> &component_count_list,
878 Supplier<GlyphID> &component_list /* Starting from seco nd for each ligature */)
879 {
880 TRACE_SERIALIZE ();
881 if (unlikely (!c->extend_min (u.format))) return TRACE_RETURN (false);
882 unsigned int format = 1;
883 u.format.set (format);
884 switch (u.format) {
885 case 1: return TRACE_RETURN (u.format1.serialize (c, first_glyphs, ligature_ per_first_glyph_count_list, num_first_glyphs,
886 ligatures_list, component_ count_list, component_list));
887 default:return TRACE_RETURN (false);
888 }
889 }
890
687 inline bool sanitize (hb_sanitize_context_t *c) { 891 inline bool sanitize (hb_sanitize_context_t *c) {
688 TRACE_SANITIZE (); 892 TRACE_SANITIZE ();
689 if (!u.format.sanitize (c)) return TRACE_RETURN (false); 893 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
690 switch (u.format) { 894 switch (u.format) {
691 case 1: return TRACE_RETURN (u.format1.sanitize (c)); 895 case 1: return TRACE_RETURN (u.format1.sanitize (c));
692 default:return TRACE_RETURN (true); 896 default:return TRACE_RETURN (true);
693 } 897 }
694 } 898 }
695 899
696 private: 900 protected:
697 union { 901 union {
698 USHORT format; /* Format identifier */ 902 USHORT format; /* Format identifier */
699 LigatureSubstFormat1 format1; 903 LigatureSubstFormat1 format1;
700 } u; 904 } u;
701 }; 905 };
702 906
703 907
704 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index); 908 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); 909 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_ index);
706 910
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 954
751 private: 955 private:
752 inline const struct SubstLookupSubTable& get_subtable (void) const 956 inline const struct SubstLookupSubTable& get_subtable (void) const
753 { 957 {
754 unsigned int offset = get_offset (); 958 unsigned int offset = get_offset ();
755 if (unlikely (!offset)) return Null(SubstLookupSubTable); 959 if (unlikely (!offset)) return Null(SubstLookupSubTable);
756 return StructAtOffset<SubstLookupSubTable> (this, offset); 960 return StructAtOffset<SubstLookupSubTable> (this, offset);
757 } 961 }
758 962
759 inline void closure (hb_closure_context_t *c) const; 963 inline void closure (hb_closure_context_t *c) const;
760 inline bool would_apply (hb_codepoint_t glyph_id) const; 964
761 inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const; 965 inline const Coverage &get_coverage (void) const;
966
967 inline bool would_apply (hb_would_apply_context_t *c) const;
762 968
763 inline bool apply (hb_apply_context_t *c) const; 969 inline bool apply (hb_apply_context_t *c) const;
764 970
765 inline bool sanitize (hb_sanitize_context_t *c); 971 inline bool sanitize (hb_sanitize_context_t *c);
766 972
767 inline bool is_reverse (void) const; 973 inline bool is_reverse (void) const;
768 }; 974 };
769 975
770 976
771 struct ReverseChainSingleSubstFormat1 977 struct ReverseChainSingleSubstFormat1
(...skipping 20 matching lines...) Expand all
792 return; 998 return;
793 999
794 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe ad); 1000 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe ad);
795 Coverage::Iter iter; 1001 Coverage::Iter iter;
796 for (iter.init (this+coverage); iter.more (); iter.next ()) { 1002 for (iter.init (this+coverage); iter.more (); iter.next ()) {
797 if (c->glyphs->has (iter.get_glyph ())) 1003 if (c->glyphs->has (iter.get_glyph ()))
798 c->glyphs->add (substitute[iter.get_coverage ()]); 1004 c->glyphs->add (substitute[iter.get_coverage ()]);
799 } 1005 }
800 } 1006 }
801 1007
1008 inline const Coverage &get_coverage (void) const
1009 {
1010 return this+coverage;
1011 }
1012
802 inline bool apply (hb_apply_context_t *c) const 1013 inline bool apply (hb_apply_context_t *c) const
803 { 1014 {
804 TRACE_APPLY (); 1015 TRACE_APPLY ();
805 if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL)) 1016 if (unlikely (c->nesting_level_left != MAX_NESTING_LEVEL))
806 return TRACE_RETURN (false); /* No chaining to this type */ 1017 return TRACE_RETURN (false); /* No chaining to this type */
807 1018
808 unsigned int index = (this+coverage) (c->buffer->cur().codepoint); 1019 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
809 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); 1020 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
810 1021
811 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag e> > (backtrack); 1022 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag e> > (backtrack);
812 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe ad); 1023 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe ad);
813 1024
814 if (match_backtrack (c, 1025 if (match_backtrack (c,
815 backtrack.len, (USHORT *) backtrack.array, 1026 backtrack.len, (USHORT *) backtrack.array,
816 match_coverage, this) && 1027 match_coverage, this) &&
817 match_lookahead (c, 1028 match_lookahead (c,
818 lookahead.len, (USHORT *) lookahead.array, 1029 lookahead.len, (USHORT *) lookahead.array,
819 match_coverage, this, 1030 match_coverage, this,
820 1)) 1031 1))
821 { 1032 {
822 c->buffer->cur().codepoint = substitute[index]; 1033 c->replace_glyph_inplace (substitute[index]);
823 c->buffer->idx--; /* Reverse! */ 1034 c->buffer->idx--; /* Reverse! */
824 return TRACE_RETURN (true); 1035 return TRACE_RETURN (true);
825 } 1036 }
826 1037
827 return TRACE_RETURN (false); 1038 return TRACE_RETURN (false);
828 } 1039 }
829 1040
830 inline bool sanitize (hb_sanitize_context_t *c) { 1041 inline bool sanitize (hb_sanitize_context_t *c) {
831 TRACE_SANITIZE (); 1042 TRACE_SANITIZE ();
832 if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this))) 1043 if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
833 return TRACE_RETURN (false); 1044 return TRACE_RETURN (false);
834 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > ( backtrack); 1045 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > ( backtrack);
835 if (!lookahead.sanitize (c, this)) 1046 if (!lookahead.sanitize (c, this))
836 return TRACE_RETURN (false); 1047 return TRACE_RETURN (false);
837 ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); 1048 ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
838 return TRACE_RETURN (substitute.sanitize (c)); 1049 return TRACE_RETURN (substitute.sanitize (c));
839 } 1050 }
840 1051
841 private: 1052 protected:
842 USHORT format; /* Format identifier--format = 1 */ 1053 USHORT format; /* Format identifier--format = 1 */
843 OffsetTo<Coverage> 1054 OffsetTo<Coverage>
844 coverage; /* Offset to Coverage table--from 1055 coverage; /* Offset to Coverage table--from
845 * beginning of table */ 1056 * beginning of table */
846 OffsetArrayOf<Coverage> 1057 OffsetArrayOf<Coverage>
847 backtrack; /* Array of coverage tables 1058 backtrack; /* Array of coverage tables
848 * in backtracking sequence, in glyph 1059 * in backtracking sequence, in glyph
849 * sequence order */ 1060 * sequence order */
850 OffsetArrayOf<Coverage> 1061 OffsetArrayOf<Coverage>
851 lookaheadX; /* Array of coverage tables 1062 lookaheadX; /* Array of coverage tables
(...skipping 14 matching lines...) Expand all
866 1077
867 inline void closure (hb_closure_context_t *c) const 1078 inline void closure (hb_closure_context_t *c) const
868 { 1079 {
869 TRACE_CLOSURE (); 1080 TRACE_CLOSURE ();
870 switch (u.format) { 1081 switch (u.format) {
871 case 1: u.format1.closure (c); break; 1082 case 1: u.format1.closure (c); break;
872 default: break; 1083 default: break;
873 } 1084 }
874 } 1085 }
875 1086
1087 inline const Coverage &get_coverage (void) const
1088 {
1089 switch (u.format) {
1090 case 1: return u.format1.get_coverage ();
1091 default:return Null(Coverage);
1092 }
1093 }
1094
876 inline bool apply (hb_apply_context_t *c) const 1095 inline bool apply (hb_apply_context_t *c) const
877 { 1096 {
878 TRACE_APPLY (); 1097 TRACE_APPLY ();
879 switch (u.format) { 1098 switch (u.format) {
880 case 1: return TRACE_RETURN (u.format1.apply (c)); 1099 case 1: return TRACE_RETURN (u.format1.apply (c));
881 default:return TRACE_RETURN (false); 1100 default:return TRACE_RETURN (false);
882 } 1101 }
883 } 1102 }
884 1103
885 inline bool sanitize (hb_sanitize_context_t *c) { 1104 inline bool sanitize (hb_sanitize_context_t *c) {
886 TRACE_SANITIZE (); 1105 TRACE_SANITIZE ();
887 if (!u.format.sanitize (c)) return TRACE_RETURN (false); 1106 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
888 switch (u.format) { 1107 switch (u.format) {
889 case 1: return TRACE_RETURN (u.format1.sanitize (c)); 1108 case 1: return TRACE_RETURN (u.format1.sanitize (c));
890 default:return TRACE_RETURN (true); 1109 default:return TRACE_RETURN (true);
891 } 1110 }
892 } 1111 }
893 1112
894 private: 1113 protected:
895 union { 1114 union {
896 USHORT format; /* Format identifier */ 1115 USHORT format; /* Format identifier */
897 ReverseChainSingleSubstFormat1 format1; 1116 ReverseChainSingleSubstFormat1 format1;
898 } u; 1117 } u;
899 }; 1118 };
900 1119
901 1120
902 1121
903 /* 1122 /*
904 * SubstLookup 1123 * SubstLookup
(...skipping 16 matching lines...) Expand all
921 1140
922 inline void closure (hb_closure_context_t *c, 1141 inline void closure (hb_closure_context_t *c,
923 unsigned int lookup_type) const 1142 unsigned int lookup_type) const
924 { 1143 {
925 TRACE_CLOSURE (); 1144 TRACE_CLOSURE ();
926 switch (lookup_type) { 1145 switch (lookup_type) {
927 case Single: u.single.closure (c); break; 1146 case Single: u.single.closure (c); break;
928 case Multiple: u.multiple.closure (c); break; 1147 case Multiple: u.multiple.closure (c); break;
929 case Alternate: u.alternate.closure (c); break; 1148 case Alternate: u.alternate.closure (c); break;
930 case Ligature: u.ligature.closure (c); break; 1149 case Ligature: u.ligature.closure (c); break;
931 case Context:» » u.c.closure (c); break; 1150 case Context:» » u.context.closure (c); break;
932 case ChainContext: u.chainContext.closure (c); break; 1151 case ChainContext: u.chainContext.closure (c); break;
933 case Extension: u.extension.closure (c); break; 1152 case Extension: u.extension.closure (c); break;
934 case ReverseChainSingle: u.reverseChainContextSingle.closure (c); break; 1153 case ReverseChainSingle: u.reverseChainContextSingle.closure (c); break;
935 default: break; 1154 default: break;
936 } 1155 }
937 } 1156 }
938 1157
939 inline bool would_apply (hb_codepoint_t glyph_id, 1158 inline const Coverage &get_coverage (unsigned int lookup_type) const
1159 {
1160 switch (lookup_type) {
1161 case Single:» » return u.single.get_coverage ();
1162 case Multiple:» » return u.multiple.get_coverage ();
1163 case Alternate:» » return u.alternate.get_coverage ();
1164 case Ligature:» » return u.ligature.get_coverage ();
1165 case Context:» » return u.context.get_coverage ();
1166 case ChainContext:» » return u.chainContext.get_coverage ();
1167 case Extension:» » return u.extension.get_coverage ();
1168 case ReverseChainSingle:» return u.reverseChainContextSingle.get_coverage ();
1169 default:» » » return Null(Coverage);
1170 }
1171 }
1172
1173 inline bool would_apply (hb_would_apply_context_t *c,
940 unsigned int lookup_type) const 1174 unsigned int lookup_type) const
941 { 1175 {
1176 TRACE_WOULD_APPLY ();
1177 if (get_coverage (lookup_type).get_coverage (c->glyphs[0]) == NOT_COVERED) r eturn false;
1178 if (c->len == 1) {
1179 switch (lookup_type) {
1180 case Single:
1181 case Multiple:
1182 case Alternate:
1183 case ReverseChainSingle:
1184 return true;
1185 }
1186 }
1187
1188 /* Only need to look further for lookups that support substitutions
1189 * of input longer than 1. */
942 switch (lookup_type) { 1190 switch (lookup_type) {
943 case Single:» » return u.single.would_apply (glyph_id); 1191 case Ligature:» » return u.ligature.would_apply (c);
944 case Multiple:» » return u.multiple.would_apply (glyph_id); 1192 case Context:» » return u.context.would_apply (c);
945 case Alternate:» » return u.alternate.would_apply (glyph_id); 1193 case ChainContext:» » return u.chainContext.would_apply (c);
946 case Extension:» » return u.extension.would_apply (glyph_id); 1194 case Extension:» » return u.extension.would_apply (c);
947 default: return false; 1195 default: return false;
948 } 1196 }
949 } 1197 }
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 1198
961 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const 1199 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const
962 { 1200 {
963 TRACE_APPLY (); 1201 TRACE_APPLY ();
964 switch (lookup_type) { 1202 switch (lookup_type) {
965 case Single: return TRACE_RETURN (u.single.apply (c)); 1203 case Single: return TRACE_RETURN (u.single.apply (c));
966 case Multiple: return TRACE_RETURN (u.multiple.apply (c)); 1204 case Multiple: return TRACE_RETURN (u.multiple.apply (c));
967 case Alternate: return TRACE_RETURN (u.alternate.apply (c)); 1205 case Alternate: return TRACE_RETURN (u.alternate.apply (c));
968 case Ligature: return TRACE_RETURN (u.ligature.apply (c)); 1206 case Ligature: return TRACE_RETURN (u.ligature.apply (c));
969 case Context:» » return TRACE_RETURN (u.c.apply (c)); 1207 case Context:» » return TRACE_RETURN (u.context.apply (c));
970 case ChainContext: return TRACE_RETURN (u.chainContext.apply (c)); 1208 case ChainContext: return TRACE_RETURN (u.chainContext.apply (c));
971 case Extension: return TRACE_RETURN (u.extension.apply (c)); 1209 case Extension: return TRACE_RETURN (u.extension.apply (c));
972 case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle .apply (c)); 1210 case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle .apply (c));
973 default: return TRACE_RETURN (false); 1211 default: return TRACE_RETURN (false);
974 } 1212 }
975 } 1213 }
976 1214
977 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) { 1215 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
978 TRACE_SANITIZE (); 1216 TRACE_SANITIZE ();
1217 if (!u.header.sub_format.sanitize (c))
1218 return TRACE_RETURN (false);
979 switch (lookup_type) { 1219 switch (lookup_type) {
980 case Single: return TRACE_RETURN (u.single.sanitize (c)); 1220 case Single: return TRACE_RETURN (u.single.sanitize (c));
981 case Multiple: return TRACE_RETURN (u.multiple.sanitize (c)); 1221 case Multiple: return TRACE_RETURN (u.multiple.sanitize (c));
982 case Alternate: return TRACE_RETURN (u.alternate.sanitize (c)); 1222 case Alternate: return TRACE_RETURN (u.alternate.sanitize (c));
983 case Ligature: return TRACE_RETURN (u.ligature.sanitize (c)); 1223 case Ligature: return TRACE_RETURN (u.ligature.sanitize (c));
984 case Context:» » return TRACE_RETURN (u.c.sanitize (c)); 1224 case Context:» » return TRACE_RETURN (u.context.sanitize (c));
985 case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c) ); 1225 case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c) );
986 case Extension: return TRACE_RETURN (u.extension.sanitize (c)); 1226 case Extension: return TRACE_RETURN (u.extension.sanitize (c));
987 case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle .sanitize (c)); 1227 case ReverseChainSingle: return TRACE_RETURN (u.reverseChainContextSingle .sanitize (c));
988 default: return TRACE_RETURN (true); 1228 default: return TRACE_RETURN (true);
989 } 1229 }
990 } 1230 }
991 1231
992 private: 1232 protected:
993 union { 1233 union {
994 USHORT» » » sub_format; 1234 struct {
1235 USHORT» » » sub_format;
1236 } header;
995 SingleSubst single; 1237 SingleSubst single;
996 MultipleSubst multiple; 1238 MultipleSubst multiple;
997 AlternateSubst alternate; 1239 AlternateSubst alternate;
998 LigatureSubst ligature; 1240 LigatureSubst ligature;
999 ContextSubst» » » c; 1241 ContextSubst» » » context;
1000 ChainContextSubst chainContext; 1242 ChainContextSubst chainContext;
1001 ExtensionSubst extension; 1243 ExtensionSubst extension;
1002 ReverseChainSingleSubst reverseChainContextSingle; 1244 ReverseChainSingleSubst reverseChainContextSingle;
1003 } u; 1245 } u;
1004 public: 1246 public:
1005 DEFINE_SIZE_UNION (2, sub_format); 1247 DEFINE_SIZE_UNION (2, header.sub_format);
1006 }; 1248 };
1007 1249
1008 1250
1009 struct SubstLookup : Lookup 1251 struct SubstLookup : Lookup
1010 { 1252 {
1011 inline const SubstLookupSubTable& get_subtable (unsigned int i) const 1253 inline const SubstLookupSubTable& get_subtable (unsigned int i) const
1012 { return this+CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; } 1254 { return this+CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i]; }
1013 1255
1014 inline static bool lookup_type_is_reverse (unsigned int lookup_type) 1256 inline static bool lookup_type_is_reverse (unsigned int lookup_type)
1015 { return lookup_type == SubstLookupSubTable::ReverseChainSingle; } 1257 { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
1016 1258
1017 inline bool is_reverse (void) const 1259 inline bool is_reverse (void) const
1018 { 1260 {
1019 unsigned int type = get_type (); 1261 unsigned int type = get_type ();
1020 if (unlikely (type == SubstLookupSubTable::Extension)) 1262 if (unlikely (type == SubstLookupSubTable::Extension))
1021 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse (); 1263 return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
1022 return lookup_type_is_reverse (type); 1264 return lookup_type_is_reverse (type);
1023 } 1265 }
1024 1266
1025 inline void closure (hb_closure_context_t *c) const 1267 inline void closure (hb_closure_context_t *c) const
1026 { 1268 {
1027 unsigned int lookup_type = get_type (); 1269 unsigned int lookup_type = get_type ();
1028 unsigned int count = get_subtable_count (); 1270 unsigned int count = get_subtable_count ();
1029 for (unsigned int i = 0; i < count; i++) 1271 for (unsigned int i = 0; i < count; i++)
1030 get_subtable (i).closure (c, lookup_type); 1272 get_subtable (i).closure (c, lookup_type);
1031 } 1273 }
1032 1274
1033 inline bool would_apply (hb_codepoint_t glyph_id) const 1275 template <typename set_t>
1276 inline void add_coverage (set_t *glyphs) const
1034 { 1277 {
1278 const Coverage *last = NULL;
1279 unsigned int count = get_subtable_count ();
1280 for (unsigned int i = 0; i < count; i++) {
1281 const Coverage *c = &get_subtable (i).get_coverage (get_type ());
1282 if (c != last) {
1283 c->add_coverage (glyphs);
1284 last = c;
1285 }
1286 }
1287 }
1288
1289 inline bool would_apply (hb_would_apply_context_t *c, const hb_set_digest_t *d igest) const
1290 {
1291 if (unlikely (!c->len)) return false;
1292 if (!digest->may_have (c->glyphs[0])) return false;
1035 unsigned int lookup_type = get_type (); 1293 unsigned int lookup_type = get_type ();
1036 unsigned int count = get_subtable_count (); 1294 unsigned int count = get_subtable_count ();
1037 for (unsigned int i = 0; i < count; i++) 1295 for (unsigned int i = 0; i < count; i++)
1038 if (get_subtable (i).would_apply (glyph_id, lookup_type)) 1296 if (get_subtable (i).would_apply (c, lookup_type))
1039 return true; 1297 return true;
1040 return false; 1298 return false;
1041 } 1299 }
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 }
1051 1300
1052 inline bool apply_once (hb_apply_context_t *c) const 1301 inline bool apply_once (hb_apply_context_t *c) const
1053 { 1302 {
1054 unsigned int lookup_type = get_type (); 1303 unsigned int lookup_type = get_type ();
1055 1304
1056 if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->cur(), c->look up_props, &c->property)) 1305 if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props, &c->proper ty))
1057 return false; 1306 return false;
1058 1307
1059 if (unlikely (lookup_type == SubstLookupSubTable::Extension))
1060 {
1061 /* The spec says all subtables should have the same type.
1062 * This is specially important if one has a reverse type!
1063 *
1064 * This is rather slow to do this here for every glyph,
1065 * but it's easiest, and who uses extension lookups anyway?!*/
1066 unsigned int type = get_subtable(0).u.extension.get_type ();
1067 unsigned int count = get_subtable_count ();
1068 for (unsigned int i = 1; i < count; i++)
1069 if (get_subtable(i).u.extension.get_type () != type)
1070 return false;
1071 }
1072
1073 unsigned int count = get_subtable_count (); 1308 unsigned int count = get_subtable_count ();
1074 for (unsigned int i = 0; i < count; i++) 1309 for (unsigned int i = 0; i < count; i++)
1075 if (get_subtable (i).apply (c, lookup_type)) 1310 if (get_subtable (i).apply (c, lookup_type))
1076 return true; 1311 return true;
1077 1312
1078 return false; 1313 return false;
1079 } 1314 }
1080 1315
1081 inline bool apply_string (hb_apply_context_t *c) const 1316 inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest ) const
1082 { 1317 {
1083 bool ret = false; 1318 bool ret = false;
1084 1319
1085 if (unlikely (!c->buffer->len)) 1320 if (unlikely (!c->buffer->len || !c->lookup_mask))
1086 return false; 1321 return false;
1087 1322
1088 c->set_lookup (*this); 1323 c->set_lookup (*this);
1089 1324
1090 if (likely (!is_reverse ())) 1325 if (likely (!is_reverse ()))
1091 { 1326 {
1092 /* in/out forward substitution */ 1327 /* in/out forward substitution */
1093 c->buffer->clear_output (); 1328 c->buffer->clear_output ();
1094 c->buffer->idx = 0; 1329 c->buffer->idx = 0;
1330
1095 while (c->buffer->idx < c->buffer->len) 1331 while (c->buffer->idx < c->buffer->len)
1096 { 1332 {
1097 » if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c)) 1333 » if ((c->buffer->cur().mask & c->lookup_mask) &&
1334 » digest->may_have (c->buffer->cur().codepoint) &&
1335 » apply_once (c))
1098 ret = true; 1336 ret = true;
1099 else 1337 else
1100 c->buffer->next_glyph (); 1338 c->buffer->next_glyph ();
1101
1102 } 1339 }
1103 if (ret) 1340 if (ret)
1104 c->buffer->swap_buffers (); 1341 c->buffer->swap_buffers ();
1105 } 1342 }
1106 else 1343 else
1107 { 1344 {
1108 /* in-place backward substitution */ 1345 /* in-place backward substitution */
1109 c->buffer->idx = c->buffer->len - 1; 1346 c->buffer->idx = c->buffer->len - 1;
1110 do 1347 do
1111 { 1348 {
1112 » if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c)) 1349 » if ((c->buffer->cur().mask & c->lookup_mask) &&
1350 » digest->may_have (c->buffer->cur().codepoint) &&
1351 » apply_once (c))
1113 ret = true; 1352 ret = true;
1114 else 1353 else
1115 c->buffer->idx--; 1354 c->buffer->idx--;
1116 1355
1117 } 1356 }
1118 while ((int) c->buffer->idx >= 0); 1357 while ((int) c->buffer->idx >= 0);
1119 } 1358 }
1120 1359
1121 return ret; 1360 return ret;
1122 } 1361 }
1123 1362
1124 inline bool sanitize (hb_sanitize_context_t *c) { 1363 private:
1364 inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
1365 » » » » » » unsigned int i)
1366 { return CastR<OffsetArrayOf<SubstLookupSubTable> > (subTable)[i].serialize (c , this); }
1367 public:
1368
1369 inline bool serialize_single (hb_serialize_context_t *c,
1370 » » » » uint32_t lookup_props,
1371 » » » Supplier<GlyphID> &glyphs,
1372 » » » Supplier<GlyphID> &substitutes,
1373 » » » unsigned int num_glyphs)
1374 {
1375 TRACE_SERIALIZE ();
1376 if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_pro ps, 1))) return TRACE_RETURN (false);
1377 return TRACE_RETURN (serialize_subtable (c, 0).u.single.serialize (c, glyphs , substitutes, num_glyphs));
1378 }
1379
1380 inline bool serialize_multiple (hb_serialize_context_t *c,
1381 » » » » uint32_t lookup_props,
1382 » » » » Supplier<GlyphID> &glyphs,
1383 » » » » Supplier<unsigned int> &substitute_len_list,
1384 » » » » unsigned int num_glyphs,
1385 » » » » Supplier<GlyphID> &substitute_glyphs_list)
1386 {
1387 TRACE_SERIALIZE ();
1388 if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_p rops, 1))) return TRACE_RETURN (false);
1389 return TRACE_RETURN (serialize_subtable (c, 0).u.multiple.serialize (c, glyp hs, substitute_len_list, num_glyphs,
1390 » » » » » » » » » substit ute_glyphs_list));
1391 }
1392
1393 inline bool serialize_alternate (hb_serialize_context_t *c,
1394 » » » » uint32_t lookup_props,
1395 » » » » Supplier<GlyphID> &glyphs,
1396 » » » » Supplier<unsigned int> &alternate_len_list,
1397 » » » » unsigned int num_glyphs,
1398 » » » » Supplier<GlyphID> &alternate_glyphs_list)
1399 {
1400 TRACE_SERIALIZE ();
1401 if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_ props, 1))) return TRACE_RETURN (false);
1402 return TRACE_RETURN (serialize_subtable (c, 0).u.alternate.serialize (c, gly phs, alternate_len_list, num_glyphs,
1403 » » » » » » » » » altern ate_glyphs_list));
1404 }
1405
1406 inline bool serialize_ligature (hb_serialize_context_t *c,
1407 » » » » uint32_t lookup_props,
1408 » » » » Supplier<GlyphID> &first_glyphs,
1409 » » » » Supplier<unsigned int> &ligature_per_first_gly ph_count_list,
1410 » » » » unsigned int num_first_glyphs,
1411 » » » » Supplier<GlyphID> &ligatures_list,
1412 » » » » Supplier<unsigned int> &component_count_list,
1413 » » » » Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
1414 {
1415 TRACE_SERIALIZE ();
1416 if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_p rops, 1))) return TRACE_RETURN (false);
1417 return TRACE_RETURN (serialize_subtable (c, 0).u.ligature.serialize (c, firs t_glyphs, ligature_per_first_glyph_count_list, num_first_glyphs,
1418 » » » » » » » » » ligatur es_list, component_count_list, component_list));
1419 }
1420
1421 inline bool sanitize (hb_sanitize_context_t *c)
1422 {
1125 TRACE_SANITIZE (); 1423 TRACE_SANITIZE ();
1126 if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false); 1424 if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
1127 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu bTable> > (subTable); 1425 OffsetArrayOf<SubstLookupSubTable> &list = CastR<OffsetArrayOf<SubstLookupSu bTable> > (subTable);
1128 return TRACE_RETURN (list.sanitize (c, this, get_type ())); 1426 if (unlikely (!list.sanitize (c, this, get_type ()))) return TRACE_RETURN (f alse);
1427
1428 if (unlikely (get_type () == SubstLookupSubTable::Extension))
1429 {
1430 /* The spec says all subtables of an Extension lookup should
1431 * have the same type. This is specially important if one has
1432 * a reverse type!
1433 *
1434 * We just check that they are all either forward, or reverse. */
1435 unsigned int type = get_subtable (0).u.extension.get_type ();
1436 unsigned int count = get_subtable_count ();
1437 for (unsigned int i = 1; i < count; i++)
1438 if (get_subtable (i).u.extension.get_type () != type)
1439 » return TRACE_RETURN (false);
1440 }
1441 return TRACE_RETURN (true);
1129 } 1442 }
1130 }; 1443 };
1131 1444
1132 typedef OffsetListOf<SubstLookup> SubstLookupList; 1445 typedef OffsetListOf<SubstLookup> SubstLookupList;
1133 1446
1134 /* 1447 /*
1135 * GSUB -- The Glyph Substitution Table 1448 * GSUB -- The Glyph Substitution Table
1136 */ 1449 */
1137 1450
1138 struct GSUB : GSUBGPOS 1451 struct GSUB : GSUBGPOS
1139 { 1452 {
1140 static const hb_tag_t Tag = HB_OT_TAG_GSUB; 1453 static const hb_tag_t Tag = HB_OT_TAG_GSUB;
1141 1454
1142 inline const SubstLookup& get_lookup (unsigned int i) const 1455 inline const SubstLookup& get_lookup (unsigned int i) const
1143 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); } 1456 { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
1144 1457
1145 inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_inde x) const 1458 template <typename set_t>
1146 { return get_lookup (lookup_index).apply_string (c); } 1459 inline void add_coverage (set_t *glyphs, unsigned int lookup_index) const
1460 { get_lookup (lookup_index).add_coverage (glyphs); }
1147 1461
1148 static inline void substitute_start (hb_buffer_t *buffer); 1462 static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
1149 static inline void substitute_finish (hb_buffer_t *buffer); 1463 static inline void substitute_finish (hb_font_t *font, hb_buffer_t *buffer);
1150 1464
1151 inline void closure_lookup (hb_closure_context_t *c, 1465 inline void closure_lookup (hb_closure_context_t *c,
1152 unsigned int lookup_index) const 1466 unsigned int lookup_index) const
1153 { return get_lookup (lookup_index).closure (c); } 1467 { return get_lookup (lookup_index).closure (c); }
1154 1468
1155 inline bool sanitize (hb_sanitize_context_t *c) { 1469 inline bool sanitize (hb_sanitize_context_t *c) {
1156 TRACE_SANITIZE (); 1470 TRACE_SANITIZE ();
1157 if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false); 1471 if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
1158 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL ist); 1472 OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupL ist);
1159 return TRACE_RETURN (list.sanitize (c, this)); 1473 return TRACE_RETURN (list.sanitize (c, this));
1160 } 1474 }
1161 public: 1475 public:
1162 DEFINE_SIZE_STATIC (10); 1476 DEFINE_SIZE_STATIC (10);
1163 }; 1477 };
1164 1478
1165 1479
1166 void 1480 void
1167 GSUB::substitute_start (hb_buffer_t *buffer) 1481 GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
1168 { 1482 {
1169 HB_BUFFER_ALLOCATE_VAR (buffer, props_cache); 1483 HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
1170 HB_BUFFER_ALLOCATE_VAR (buffer, lig_props); 1484 HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
1171 HB_BUFFER_ALLOCATE_VAR (buffer, syllable); 1485 HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
1172 1486
1487 const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
1173 unsigned int count = buffer->len; 1488 unsigned int count = buffer->len;
1174 for (unsigned int i = 0; i < count; i++) 1489 for (unsigned int i = 0; i < count; i++) {
1175 buffer->info[i].props_cache() = buffer->info[i].lig_props() = buffer->info[i ].syllable() = 0; 1490 buffer->info[i].lig_props() = buffer->info[i].syllable() = 0;
1491 buffer->info[i].glyph_props() = gdef.get_glyph_props (buffer->info[i].codepo int);
1492 }
1176 } 1493 }
1177 1494
1178 void 1495 void
1179 GSUB::substitute_finish (hb_buffer_t *buffer HB_UNUSED) 1496 GSUB::substitute_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSE D)
1180 { 1497 {
1181 } 1498 }
1182 1499
1183 1500
1184 /* Out-of-class implementation for methods recursing */ 1501 /* Out-of-class implementation for methods recursing */
1185 1502
1186 inline void ExtensionSubst::closure (hb_closure_context_t *c) const 1503 inline void ExtensionSubst::closure (hb_closure_context_t *c) const
1187 { 1504 {
1188 get_subtable ().closure (c, get_type ()); 1505 get_subtable ().closure (c, get_type ());
1189 } 1506 }
1190 1507
1191 inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const 1508 inline const Coverage & ExtensionSubst::get_coverage (void) const
1192 { 1509 {
1193 return get_subtable ().would_apply (glyph_id, get_type ()); 1510 return get_subtable ().get_coverage (get_type ());
1194 } 1511 }
1195 1512
1196 inline bool ExtensionSubst::would_apply (hb_codepoint_t first, hb_codepoint_t se cond) const 1513 inline bool ExtensionSubst::would_apply (hb_would_apply_context_t *c) const
1197 { 1514 {
1198 return get_subtable ().would_apply (first, second, get_type ()); 1515 return get_subtable ().would_apply (c, get_type ());
1199 } 1516 }
1200 1517
1201 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const 1518 inline bool ExtensionSubst::apply (hb_apply_context_t *c) const
1202 { 1519 {
1203 TRACE_APPLY (); 1520 TRACE_APPLY ();
1204 return TRACE_RETURN (get_subtable ().apply (c, get_type ())); 1521 return TRACE_RETURN (get_subtable ().apply (c, get_type ()));
1205 } 1522 }
1206 1523
1207 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c) 1524 inline bool ExtensionSubst::sanitize (hb_sanitize_context_t *c)
1208 { 1525 {
1209 TRACE_SANITIZE (); 1526 TRACE_SANITIZE ();
1210 if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false); 1527 if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false);
1211 unsigned int offset = get_offset (); 1528 unsigned int offset = get_offset ();
1212 if (unlikely (!offset)) return TRACE_RETURN (true); 1529 if (unlikely (!offset)) return TRACE_RETURN (true);
1213 return TRACE_RETURN (StructAtOffset<SubstLookupSubTable> (this, offset).saniti ze (c, get_type ())); 1530 return TRACE_RETURN (StructAtOffset<SubstLookupSubTable> (this, offset).saniti ze (c, get_type ()));
1214 } 1531 }
1215 1532
1216 inline bool ExtensionSubst::is_reverse (void) const 1533 inline bool ExtensionSubst::is_reverse (void) const
1217 { 1534 {
1218 unsigned int type = get_type (); 1535 unsigned int type = get_type ();
1219 if (unlikely (type == SubstLookupSubTable::Extension)) 1536 if (unlikely (type == SubstLookupSubTable::Extension))
1220 return CastR<ExtensionSubst> (get_subtable()).is_reverse (); 1537 return CastR<ExtensionSubst> (get_subtable()).is_reverse ();
1221 return SubstLookup::lookup_type_is_reverse (type); 1538 return SubstLookup::lookup_type_is_reverse (type);
1222 } 1539 }
1223 1540
1224 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_ index) 1541 static inline void closure_lookup (hb_closure_context_t *c, unsigned int lookup_ index)
1225 { 1542 {
1226 const GSUB &gsub = *(c->face->ot_layout->gsub); 1543 const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
1227 const SubstLookup &l = gsub.get_lookup (lookup_index); 1544 const SubstLookup &l = gsub.get_lookup (lookup_index);
1228 1545
1229 if (unlikely (c->nesting_level_left == 0)) 1546 if (unlikely (c->nesting_level_left == 0))
1230 return; 1547 return;
1231 1548
1232 c->nesting_level_left--; 1549 c->nesting_level_left--;
1233 l.closure (c); 1550 l.closure (c);
1234 c->nesting_level_left++; 1551 c->nesting_level_left++;
1235 } 1552 }
1236 1553
1237 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index) 1554 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup _index)
1238 { 1555 {
1239 const GSUB &gsub = *(c->face->ot_layout->gsub); 1556 const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
1240 const SubstLookup &l = gsub.get_lookup (lookup_index); 1557 const SubstLookup &l = gsub.get_lookup (lookup_index);
1241 1558
1242 if (unlikely (c->nesting_level_left == 0)) 1559 if (unlikely (c->nesting_level_left == 0))
1243 return false; 1560 return false;
1244 1561
1245 hb_apply_context_t new_c (*c); 1562 hb_apply_context_t new_c (*c);
1246 new_c.nesting_level_left--; 1563 new_c.nesting_level_left--;
1247 new_c.set_lookup (l); 1564 new_c.set_lookup (l);
1248 return l.apply_once (&new_c); 1565 return l.apply_once (&new_c);
1249 } 1566 }
1250 1567
1251 1568
1569 } // namespace OT
1570
1252 1571
1253 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ 1572 #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