OLD | NEW |
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 Loading... |
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 Loading... |
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 */ |
OLD | NEW |