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,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 20 matching lines...) Expand all Loading... |
31 | 31 |
32 #include "hb-buffer-private.hh" | 32 #include "hb-buffer-private.hh" |
33 #include "hb-ot-layout-gdef-table.hh" | 33 #include "hb-ot-layout-gdef-table.hh" |
34 #include "hb-set-private.hh" | 34 #include "hb-set-private.hh" |
35 | 35 |
36 | 36 |
37 namespace OT { | 37 namespace OT { |
38 | 38 |
39 | 39 |
40 | 40 |
41 #define TRACE_PROCESS(this) \ | 41 #define TRACE_DISPATCH(this) \ |
42 hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t
> trace \ | 42 hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t
> trace \ |
43 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ | 43 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ |
44 ""); | 44 ""); |
45 | 45 |
46 | 46 |
47 #ifndef HB_DEBUG_CLOSURE | 47 #ifndef HB_DEBUG_CLOSURE |
48 #define HB_DEBUG_CLOSURE (HB_DEBUG+0) | 48 #define HB_DEBUG_CLOSURE (HB_DEBUG+0) |
49 #endif | 49 #endif |
50 | 50 |
51 #define TRACE_CLOSURE(this) \ | 51 #define TRACE_CLOSURE(this) \ |
52 hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \ | 52 hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \ |
53 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ | 53 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ |
54 ""); | 54 ""); |
55 | 55 |
56 struct hb_closure_context_t | 56 struct hb_closure_context_t |
57 { | 57 { |
58 inline const char *get_name (void) { return "CLOSURE"; } | 58 inline const char *get_name (void) { return "CLOSURE"; } |
59 static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE; | 59 static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE; |
60 typedef hb_void_t return_t; | 60 typedef hb_void_t return_t; |
61 typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int look
up_index); | 61 typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int look
up_index); |
62 template <typename T> | 62 template <typename T> |
63 inline return_t process (const T &obj) { obj.closure (this); return HB_VOID; } | 63 inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID;
} |
64 static return_t default_return_value (void) { return HB_VOID; } | 64 static return_t default_return_value (void) { return HB_VOID; } |
65 bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return fals
e; } | 65 bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } |
66 return_t recurse (unsigned int lookup_index) | 66 return_t recurse (unsigned int lookup_index) |
67 { | 67 { |
68 if (unlikely (nesting_level_left == 0 || !recurse_func)) | 68 if (unlikely (nesting_level_left == 0 || !recurse_func)) |
69 return default_return_value (); | 69 return default_return_value (); |
70 | 70 |
71 nesting_level_left--; | 71 nesting_level_left--; |
72 recurse_func (this, lookup_index); | 72 recurse_func (this, lookup_index); |
73 nesting_level_left++; | 73 nesting_level_left++; |
74 return HB_VOID; | 74 return HB_VOID; |
75 } | 75 } |
(...skipping 26 matching lines...) Expand all Loading... |
102 hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \ | 102 hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \ |
103 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ | 103 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ |
104 "%d glyphs", c->len); | 104 "%d glyphs", c->len); |
105 | 105 |
106 struct hb_would_apply_context_t | 106 struct hb_would_apply_context_t |
107 { | 107 { |
108 inline const char *get_name (void) { return "WOULD_APPLY"; } | 108 inline const char *get_name (void) { return "WOULD_APPLY"; } |
109 static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY; | 109 static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY; |
110 typedef bool return_t; | 110 typedef bool return_t; |
111 template <typename T> | 111 template <typename T> |
112 inline return_t process (const T &obj) { return obj.would_apply (this); } | 112 inline return_t dispatch (const T &obj) { return obj.would_apply (this); } |
113 static return_t default_return_value (void) { return false; } | 113 static return_t default_return_value (void) { return false; } |
114 bool stop_sublookup_iteration (const return_t r) const { return r; } | 114 bool stop_sublookup_iteration (return_t r) const { return r; } |
115 | 115 |
116 hb_face_t *face; | 116 hb_face_t *face; |
117 const hb_codepoint_t *glyphs; | 117 const hb_codepoint_t *glyphs; |
118 unsigned int len; | 118 unsigned int len; |
119 bool zero_context; | 119 bool zero_context; |
120 unsigned int debug_depth; | 120 unsigned int debug_depth; |
121 | 121 |
122 hb_would_apply_context_t (hb_face_t *face_, | 122 hb_would_apply_context_t (hb_face_t *face_, |
123 const hb_codepoint_t *glyphs_, | 123 const hb_codepoint_t *glyphs_, |
124 unsigned int len_, | 124 unsigned int len_, |
(...skipping 16 matching lines...) Expand all Loading... |
141 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ | 141 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ |
142 ""); | 142 ""); |
143 | 143 |
144 struct hb_collect_glyphs_context_t | 144 struct hb_collect_glyphs_context_t |
145 { | 145 { |
146 inline const char *get_name (void) { return "COLLECT_GLYPHS"; } | 146 inline const char *get_name (void) { return "COLLECT_GLYPHS"; } |
147 static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS; | 147 static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS; |
148 typedef hb_void_t return_t; | 148 typedef hb_void_t return_t; |
149 typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned i
nt lookup_index); | 149 typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned i
nt lookup_index); |
150 template <typename T> | 150 template <typename T> |
151 inline return_t process (const T &obj) { obj.collect_glyphs (this); return HB_
VOID; } | 151 inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB
_VOID; } |
152 static return_t default_return_value (void) { return HB_VOID; } | 152 static return_t default_return_value (void) { return HB_VOID; } |
153 bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return fals
e; } | 153 bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } |
154 return_t recurse (unsigned int lookup_index) | 154 return_t recurse (unsigned int lookup_index) |
155 { | 155 { |
156 if (unlikely (nesting_level_left == 0 || !recurse_func)) | 156 if (unlikely (nesting_level_left == 0 || !recurse_func)) |
157 return default_return_value (); | 157 return default_return_value (); |
158 | 158 |
159 /* Note that GPOS sets recurse_func to NULL already, so it doesn't get | 159 /* Note that GPOS sets recurse_func to NULL already, so it doesn't get |
160 * past the previous check. For GSUB, we only want to collect the output | 160 * past the previous check. For GSUB, we only want to collect the output |
161 * glyphs in the recursion. If output is not requested, we can go home now.
*/ | 161 * glyphs in the recursion. If output is not requested, we can go home now.
*/ |
162 | 162 |
163 if (output == hb_set_get_empty ()) | 163 if (output == hb_set_get_empty ()) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 }; | 207 }; |
208 | 208 |
209 | 209 |
210 | 210 |
211 struct hb_get_coverage_context_t | 211 struct hb_get_coverage_context_t |
212 { | 212 { |
213 inline const char *get_name (void) { return "GET_COVERAGE"; } | 213 inline const char *get_name (void) { return "GET_COVERAGE"; } |
214 static const unsigned int max_debug_depth = 0; | 214 static const unsigned int max_debug_depth = 0; |
215 typedef const Coverage &return_t; | 215 typedef const Coverage &return_t; |
216 template <typename T> | 216 template <typename T> |
217 inline return_t process (const T &obj) { return obj.get_coverage (); } | 217 inline return_t dispatch (const T &obj) { return obj.get_coverage (); } |
218 static return_t default_return_value (void) { return Null(Coverage); } | 218 static return_t default_return_value (void) { return Null(Coverage); } |
219 | 219 |
220 hb_get_coverage_context_t (void) : | 220 hb_get_coverage_context_t (void) : |
221 debug_depth (0) {} | 221 debug_depth (0) {} |
222 | 222 |
223 unsigned int debug_depth; | 223 unsigned int debug_depth; |
224 }; | 224 }; |
225 | 225 |
226 | 226 |
227 | 227 |
228 #ifndef HB_DEBUG_APPLY | 228 #ifndef HB_DEBUG_APPLY |
229 #define HB_DEBUG_APPLY (HB_DEBUG+0) | 229 #define HB_DEBUG_APPLY (HB_DEBUG+0) |
230 #endif | 230 #endif |
231 | 231 |
232 #define TRACE_APPLY(this) \ | 232 #define TRACE_APPLY(this) \ |
233 hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \ | 233 hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \ |
234 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ | 234 (&c->debug_depth, c->get_name (), this, HB_FUNC, \ |
235 "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); | 235 "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint); |
236 | 236 |
237 struct hb_apply_context_t | 237 struct hb_apply_context_t |
238 { | 238 { |
239 inline const char *get_name (void) { return "APPLY"; } | 239 inline const char *get_name (void) { return "APPLY"; } |
240 static const unsigned int max_debug_depth = HB_DEBUG_APPLY; | 240 static const unsigned int max_debug_depth = HB_DEBUG_APPLY; |
241 typedef bool return_t; | 241 typedef bool return_t; |
242 typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup
_index); | 242 typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup
_index); |
243 template <typename T> | 243 template <typename T> |
244 inline return_t process (const T &obj) { return obj.apply (this); } | 244 inline return_t dispatch (const T &obj) { return obj.apply (this); } |
245 static return_t default_return_value (void) { return false; } | 245 static return_t default_return_value (void) { return false; } |
246 bool stop_sublookup_iteration (const return_t r) const { return r; } | 246 bool stop_sublookup_iteration (return_t r) const { return r; } |
247 return_t recurse (unsigned int lookup_index) | 247 return_t recurse (unsigned int lookup_index) |
248 { | 248 { |
249 if (unlikely (nesting_level_left == 0 || !recurse_func)) | 249 if (unlikely (nesting_level_left == 0 || !recurse_func)) |
250 return default_return_value (); | 250 return default_return_value (); |
251 | 251 |
252 nesting_level_left--; | 252 nesting_level_left--; |
253 bool ret = recurse_func (this, lookup_index); | 253 bool ret = recurse_func (this, lookup_index); |
254 nesting_level_left++; | 254 nesting_level_left++; |
255 return ret; | 255 return ret; |
256 } | 256 } |
257 | 257 |
| 258 unsigned int table_index; /* GSUB/GPOS */ |
258 hb_font_t *font; | 259 hb_font_t *font; |
259 hb_face_t *face; | 260 hb_face_t *face; |
260 hb_buffer_t *buffer; | 261 hb_buffer_t *buffer; |
261 hb_direction_t direction; | 262 hb_direction_t direction; |
262 hb_mask_t lookup_mask; | 263 hb_mask_t lookup_mask; |
| 264 bool auto_zwj; |
263 recurse_func_t recurse_func; | 265 recurse_func_t recurse_func; |
264 unsigned int nesting_level_left; | 266 unsigned int nesting_level_left; |
265 unsigned int lookup_props; | 267 unsigned int lookup_props; |
266 unsigned int property; /* propety of first glyph */ | |
267 const GDEF &gdef; | 268 const GDEF &gdef; |
268 bool has_glyph_classes; | 269 bool has_glyph_classes; |
269 unsigned int debug_depth; | 270 unsigned int debug_depth; |
270 | 271 |
271 | 272 |
272 hb_apply_context_t (hb_font_t *font_, | 273 hb_apply_context_t (unsigned int table_index_, |
| 274 » » hb_font_t *font_, |
273 hb_buffer_t *buffer_, | 275 hb_buffer_t *buffer_, |
274 » » hb_mask_t lookup_mask_) : | 276 » » hb_mask_t lookup_mask_, |
| 277 » » bool auto_zwj_) : |
| 278 » » » table_index (table_index_), |
275 font (font_), face (font->face), buffer (buffer_), | 279 font (font_), face (font->face), buffer (buffer_), |
276 direction (buffer_->props.direction), | 280 direction (buffer_->props.direction), |
277 lookup_mask (lookup_mask_), | 281 lookup_mask (lookup_mask_), |
| 282 auto_zwj (auto_zwj_), |
278 recurse_func (NULL), | 283 recurse_func (NULL), |
279 nesting_level_left (MAX_NESTING_LEVEL), | 284 nesting_level_left (MAX_NESTING_LEVEL), |
280 » » » lookup_props (0), property (0), | 285 » » » lookup_props (0), |
281 gdef (*hb_ot_layout_from_face (face)->gdef), | 286 gdef (*hb_ot_layout_from_face (face)->gdef), |
282 has_glyph_classes (gdef.has_glyph_classes ()), | 287 has_glyph_classes (gdef.has_glyph_classes ()), |
283 debug_depth (0) {} | 288 debug_depth (0) {} |
284 | 289 |
285 void set_recurse_func (recurse_func_t func) { recurse_func = func; } | 290 inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } |
286 void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_pro
ps_; } | 291 inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = loo
kup_props_; } |
287 void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } | 292 inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); } |
288 | 293 |
289 struct mark_skipping_forward_iterator_t | 294 struct matcher_t |
290 { | 295 { |
291 inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_, | 296 inline matcher_t (void) : |
292 » » » » » unsigned int start_index_, | 297 » lookup_props (0), |
293 » » » » » unsigned int num_items_, | 298 » ignore_zwnj (false), |
294 » » » » » bool context_match = false) | 299 » ignore_zwj (false), |
295 { | 300 » mask (-1), |
296 c = c_; | 301 #define arg1(arg) (arg) /* Remove the macro to see why it's needed! */ |
297 idx = start_index_; | 302 » syllable arg1(0), |
298 num_items = num_items_; | 303 #undef arg1 |
299 mask = context_match ? -1 : c->lookup_mask; | 304 » match_func (NULL), |
300 syllable = context_match ? 0 : c->buffer->cur().syllable (); | 305 » match_data (NULL) {}; |
301 end = c->buffer->len; | 306 |
302 } | 307 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value,
const void *data); |
303 inline bool has_no_chance (void) const | 308 |
304 { | 309 inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_
; } |
305 return unlikely (num_items && idx + num_items >= end); | 310 inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } |
306 } | 311 inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = l
ookup_props_; } |
307 inline void reject (void) | 312 inline void set_mask (hb_mask_t mask_) { mask = mask_; } |
308 { | 313 inline void set_syllable (uint8_t syllable_) { syllable = syllable_; } |
309 num_items++; | 314 inline void set_match_func (match_func_t match_func_, |
310 } | 315 » » » » const void *match_data_) |
311 inline bool next (unsigned int *property_out, | 316 { match_func = match_func_; match_data = match_data_; } |
312 » » unsigned int lookup_props) | 317 |
| 318 enum may_match_t { |
| 319 MATCH_NO, |
| 320 MATCH_YES, |
| 321 MATCH_MAYBE |
| 322 }; |
| 323 |
| 324 inline may_match_t may_match (const hb_glyph_info_t &info, |
| 325 » » » » const USHORT *glyph_data) const |
| 326 { |
| 327 if (!(info.mask & mask) || |
| 328 » (syllable && syllable != info.syllable ())) |
| 329 » return MATCH_NO; |
| 330 |
| 331 if (match_func) |
| 332 return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES
: MATCH_NO; |
| 333 |
| 334 return MATCH_MAYBE; |
| 335 } |
| 336 |
| 337 enum may_skip_t { |
| 338 SKIP_NO, |
| 339 SKIP_YES, |
| 340 SKIP_MAYBE |
| 341 }; |
| 342 |
| 343 inline may_skip_t |
| 344 may_skip (const hb_apply_context_t *c, |
| 345 » const hb_glyph_info_t &info) const |
| 346 { |
| 347 unsigned int property; |
| 348 |
| 349 property = info.glyph_props(); |
| 350 |
| 351 if (!c->match_properties (info.codepoint, property, lookup_props)) |
| 352 » return SKIP_YES; |
| 353 |
| 354 if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && |
| 355 » » (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && |
| 356 » » (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && |
| 357 » » !is_a_ligature (info))) |
| 358 » return SKIP_MAYBE; |
| 359 |
| 360 return SKIP_NO; |
| 361 } |
| 362 |
| 363 protected: |
| 364 unsigned int lookup_props; |
| 365 bool ignore_zwnj; |
| 366 bool ignore_zwj; |
| 367 hb_mask_t mask; |
| 368 uint8_t syllable; |
| 369 match_func_t match_func; |
| 370 const void *match_data; |
| 371 }; |
| 372 |
| 373 struct skipping_forward_iterator_t |
| 374 { |
| 375 inline skipping_forward_iterator_t (hb_apply_context_t *c_, |
| 376 » » » » » unsigned int start_index_, |
| 377 » » » » » unsigned int num_items_, |
| 378 » » » » » bool context_match = false) : |
| 379 » » » » » idx (start_index_), |
| 380 » » » » » c (c_), |
| 381 » » » » » match_glyph_data (NULL), |
| 382 » » » » » num_items (num_items_), |
| 383 » » » » » end (c->buffer->len) |
| 384 { |
| 385 matcher.set_lookup_props (c->lookup_props); |
| 386 /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ |
| 387 matcher.set_ignore_zwnj (context_match || c->table_index == 1); |
| 388 /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if ask
ed to. */ |
| 389 matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zw
j); |
| 390 if (!context_match) |
| 391 » matcher.set_mask (c->lookup_mask); |
| 392 matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().sy
llable () : 0); |
| 393 } |
| 394 inline void set_lookup_props (unsigned int lookup_props) { matcher.set_looku
p_props (lookup_props); } |
| 395 inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syl
lable); } |
| 396 inline void set_match_func (matcher_t::match_func_t match_func, |
| 397 » » » » const void *match_data, |
| 398 » » » » const USHORT glyph_data[]) |
| 399 { |
| 400 matcher.set_match_func (match_func, match_data); |
| 401 match_glyph_data = glyph_data; |
| 402 } |
| 403 |
| 404 inline bool has_no_chance (void) const { return unlikely (num_items && idx +
num_items >= end); } |
| 405 inline void reject (void) { num_items++; match_glyph_data--; } |
| 406 inline bool next (void) |
313 { | 407 { |
314 assert (num_items > 0); | 408 assert (num_items > 0); |
315 do | 409 while (!has_no_chance ()) |
316 { | 410 { |
317 » if (has_no_chance ()) | 411 » idx++; |
| 412 » const hb_glyph_info_t &info = c->buffer->info[idx]; |
| 413 |
| 414 » matcher_t::may_skip_t skip = matcher.may_skip (c, info); |
| 415 » if (unlikely (skip == matcher_t::SKIP_YES)) |
| 416 » continue; |
| 417 |
| 418 » matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data
); |
| 419 » if (match == matcher_t::MATCH_YES || |
| 420 » (match == matcher_t::MATCH_MAYBE && |
| 421 » skip == matcher_t::SKIP_NO)) |
| 422 » { |
| 423 » num_items--; |
| 424 » match_glyph_data++; |
| 425 » return true; |
| 426 » } |
| 427 |
| 428 » if (skip == matcher_t::SKIP_NO) |
318 return false; | 429 return false; |
319 » idx++; | 430 } |
320 } while (c->should_skip_mark (&c->buffer->info[idx], lookup_props, propert
y_out)); | 431 return false; |
321 num_items--; | |
322 return (c->buffer->info[idx].mask & mask) && (!syllable || syllable == c->
buffer->info[idx].syllable ()); | |
323 } | |
324 inline bool next (unsigned int *property_out = NULL) | |
325 { | |
326 return next (property_out, c->lookup_props); | |
327 } | 432 } |
328 | 433 |
329 unsigned int idx; | 434 unsigned int idx; |
330 protected: | 435 protected: |
331 hb_apply_context_t *c; | 436 hb_apply_context_t *c; |
| 437 matcher_t matcher; |
| 438 const USHORT *match_glyph_data; |
| 439 |
332 unsigned int num_items; | 440 unsigned int num_items; |
333 hb_mask_t mask; | |
334 uint8_t syllable; | |
335 unsigned int end; | 441 unsigned int end; |
336 }; | 442 }; |
337 | 443 |
338 struct mark_skipping_backward_iterator_t | 444 struct skipping_backward_iterator_t |
339 { | 445 { |
340 inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_, | 446 inline skipping_backward_iterator_t (hb_apply_context_t *c_, |
341 » » » » » unsigned int start_index_, | 447 » » » » » unsigned int start_index_, |
342 » » » » » unsigned int num_items_, | 448 » » » » » unsigned int num_items_, |
343 » » » » » hb_mask_t mask_ = 0, | 449 » » » » » bool context_match = false) : |
344 » » » » » bool match_syllable_ = true) | 450 » » » » » idx (start_index_), |
345 { | 451 » » » » » c (c_), |
346 c = c_; | 452 » » » » » match_glyph_data (NULL), |
347 idx = start_index_; | 453 » » » » » num_items (num_items_) |
348 num_items = num_items_; | 454 { |
349 mask = mask_ ? mask_ : c->lookup_mask; | 455 matcher.set_lookup_props (c->lookup_props); |
350 syllable = match_syllable_ ? c->buffer->cur().syllable () : 0; | 456 /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ |
351 } | 457 matcher.set_ignore_zwnj (context_match || c->table_index == 1); |
352 inline bool has_no_chance (void) const | 458 /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if ask
ed to. */ |
353 { | 459 matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zw
j); |
354 return unlikely (idx < num_items); | 460 if (!context_match) |
355 } | 461 » matcher.set_mask (c->lookup_mask); |
356 inline void reject (void) | 462 matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().sy
llable () : 0); |
357 { | 463 } |
358 num_items++; | 464 inline void set_lookup_props (unsigned int lookup_props) { matcher.set_looku
p_props (lookup_props); } |
359 } | 465 inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syl
lable); } |
360 inline bool prev (unsigned int *property_out, | 466 inline void set_match_func (matcher_t::match_func_t match_func, |
361 » » unsigned int lookup_props) | 467 » » » » const void *match_data, |
| 468 » » » » const USHORT glyph_data[]) |
| 469 { |
| 470 matcher.set_match_func (match_func, match_data); |
| 471 match_glyph_data = glyph_data; |
| 472 } |
| 473 |
| 474 inline bool has_no_chance (void) const { return unlikely (idx < num_items);
} |
| 475 inline void reject (void) { num_items++; } |
| 476 inline bool prev (void) |
362 { | 477 { |
363 assert (num_items > 0); | 478 assert (num_items > 0); |
364 do | 479 while (!has_no_chance ()) |
365 { | 480 { |
366 » if (has_no_chance ()) | 481 » idx--; |
| 482 » const hb_glyph_info_t &info = c->buffer->out_info[idx]; |
| 483 |
| 484 » matcher_t::may_skip_t skip = matcher.may_skip (c, info); |
| 485 |
| 486 » if (unlikely (skip == matcher_t::SKIP_YES)) |
| 487 » continue; |
| 488 |
| 489 » matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data
); |
| 490 » if (match == matcher_t::MATCH_YES || |
| 491 » (match == matcher_t::MATCH_MAYBE && |
| 492 » skip == matcher_t::SKIP_NO)) |
| 493 » { |
| 494 » num_items--; |
| 495 » match_glyph_data++; |
| 496 » return true; |
| 497 » } |
| 498 |
| 499 » if (skip == matcher_t::SKIP_NO) |
367 return false; | 500 return false; |
368 » idx--; | 501 } |
369 } while (c->should_skip_mark (&c->buffer->out_info[idx], lookup_props, pro
perty_out)); | 502 return false; |
370 num_items--; | |
371 return (c->buffer->out_info[idx].mask & mask) && (!syllable || syllable ==
c->buffer->out_info[idx].syllable ()); | |
372 } | |
373 inline bool prev (unsigned int *property_out = NULL) | |
374 { | |
375 return prev (property_out, c->lookup_props); | |
376 } | 503 } |
377 | 504 |
378 unsigned int idx; | 505 unsigned int idx; |
379 protected: | 506 protected: |
380 hb_apply_context_t *c; | 507 hb_apply_context_t *c; |
| 508 matcher_t matcher; |
| 509 const USHORT *match_glyph_data; |
| 510 |
381 unsigned int num_items; | 511 unsigned int num_items; |
382 hb_mask_t mask; | |
383 uint8_t syllable; | |
384 }; | 512 }; |
385 | 513 |
386 inline bool | 514 inline bool |
387 match_properties_mark (hb_codepoint_t glyph, | 515 match_properties_mark (hb_codepoint_t glyph, |
388 unsigned int glyph_props, | 516 unsigned int glyph_props, |
389 unsigned int lookup_props) const | 517 unsigned int lookup_props) const |
390 { | 518 { |
391 /* If using mark filtering sets, the high short of | 519 /* If using mark filtering sets, the high short of |
392 * lookup_props has the set index. | 520 * lookup_props has the set index. |
393 */ | 521 */ |
(...skipping 22 matching lines...) Expand all Loading... |
416 return false; | 544 return false; |
417 | 545 |
418 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) | 546 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) |
419 return match_properties_mark (glyph, glyph_props, lookup_props); | 547 return match_properties_mark (glyph, glyph_props, lookup_props); |
420 | 548 |
421 return true; | 549 return true; |
422 } | 550 } |
423 | 551 |
424 inline bool | 552 inline bool |
425 check_glyph_property (hb_glyph_info_t *info, | 553 check_glyph_property (hb_glyph_info_t *info, |
426 » » » unsigned int lookup_props, | 554 » » » unsigned int lookup_props) const |
427 » » » unsigned int *property_out) const | |
428 { | 555 { |
429 unsigned int property; | 556 unsigned int property; |
430 | 557 |
431 property = info->glyph_props(); | 558 property = info->glyph_props(); |
432 *property_out = property; | |
433 | 559 |
434 return match_properties (info->codepoint, property, lookup_props); | 560 return match_properties (info->codepoint, property, lookup_props); |
435 } | 561 } |
436 | 562 |
437 inline bool | |
438 should_skip_mark (hb_glyph_info_t *info, | |
439 unsigned int lookup_props, | |
440 unsigned int *property_out) const | |
441 { | |
442 unsigned int property; | |
443 | |
444 property = info->glyph_props(); | |
445 if (property_out) | |
446 *property_out = property; | |
447 | |
448 /* If it's a mark, skip it if we don't accept it. */ | |
449 if (unlikely (property & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) | |
450 return !match_properties (info->codepoint, property, lookup_props); | |
451 | |
452 /* If not a mark, don't skip. */ | |
453 return false; | |
454 } | |
455 | |
456 | |
457 inline bool should_mark_skip_current_glyph (void) const | |
458 { | |
459 return should_skip_mark (&buffer->cur(), lookup_props, NULL); | |
460 } | |
461 | |
462 inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) c
onst | 563 inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) c
onst |
463 { | 564 { |
464 if (likely (has_glyph_classes)) | 565 if (likely (has_glyph_classes)) |
465 buffer->cur().glyph_props() = gdef.get_glyph_props (glyph_index); | 566 buffer->cur().glyph_props() = gdef.get_glyph_props (glyph_index); |
466 else if (class_guess) | 567 else if (class_guess) |
467 buffer->cur().glyph_props() = class_guess; | 568 buffer->cur().glyph_props() = class_guess; |
468 } | 569 } |
469 | 570 |
470 inline void output_glyph (hb_codepoint_t glyph_index, | 571 inline void output_glyph (hb_codepoint_t glyph_index, |
471 unsigned int class_guess = 0) const | 572 unsigned int class_guess = 0) const |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 unsigned int count, /* Including the first glyph
(not matched) */ | 696 unsigned int count, /* Including the first glyph
(not matched) */ |
596 const USHORT input[], /* Array of input values--
start with second glyph */ | 697 const USHORT input[], /* Array of input values--
start with second glyph */ |
597 match_func_t match_func, | 698 match_func_t match_func, |
598 const void *match_data, | 699 const void *match_data, |
599 unsigned int *end_offset = NULL, | 700 unsigned int *end_offset = NULL, |
600 bool *p_is_mark_ligature = NULL, | 701 bool *p_is_mark_ligature = NULL, |
601 unsigned int *p_total_component_count = NULL) | 702 unsigned int *p_total_component_count = NULL) |
602 { | 703 { |
603 TRACE_APPLY (NULL); | 704 TRACE_APPLY (NULL); |
604 | 705 |
605 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer
->idx, count - 1); | 706 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx
, count - 1); |
| 707 skippy_iter.set_match_func (match_func, match_data, input); |
606 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); | 708 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
607 | 709 |
608 /* | 710 /* |
609 * This is perhaps the trickiest part of OpenType... Remarks: | 711 * This is perhaps the trickiest part of OpenType... Remarks: |
610 * | 712 * |
611 * - If all components of the ligature were marks, we call this a mark ligatur
e. | 713 * - If all components of the ligature were marks, we call this a mark ligatur
e. |
612 * | 714 * |
613 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categori
ze | 715 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categori
ze |
614 * it as a ligature glyph. | 716 * it as a ligature glyph. |
615 * | 717 * |
616 * - Ligatures cannot be formed across glyphs attached to different components | 718 * - Ligatures cannot be formed across glyphs attached to different components |
617 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and | 719 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and |
618 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. | 720 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. |
619 * However, it would be wrong to ligate that SHADDA,FATHA sequence.o | 721 * However, it would be wrong to ligate that SHADDA,FATHA sequence.o |
620 * There is an exception to this: If a ligature tries ligating with marks th
at | 722 * There is an exception to this: If a ligature tries ligating with marks th
at |
621 * belong to it itself, go ahead, assuming that the font designer knows what | 723 * belong to it itself, go ahead, assuming that the font designer knows what |
622 * they are doing (otherwise it can break Indic stuff when a matra wants to | 724 * they are doing (otherwise it can break Indic stuff when a matra wants to |
623 * ligate with a conjunct...) | 725 * ligate with a conjunct...) |
624 */ | 726 */ |
625 | 727 |
626 bool is_mark_ligature = !!(c->property & HB_OT_LAYOUT_GLYPH_PROPS_MARK); | 728 bool is_mark_ligature = !!(c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH
_PROPS_MARK); |
627 | 729 |
628 unsigned int total_component_count = 0; | 730 unsigned int total_component_count = 0; |
629 total_component_count += get_lig_num_comps (c->buffer->cur()); | 731 total_component_count += get_lig_num_comps (c->buffer->cur()); |
630 | 732 |
631 unsigned int first_lig_id = get_lig_id (c->buffer->cur()); | 733 unsigned int first_lig_id = get_lig_id (c->buffer->cur()); |
632 unsigned int first_lig_comp = get_lig_comp (c->buffer->cur()); | 734 unsigned int first_lig_comp = get_lig_comp (c->buffer->cur()); |
633 | 735 |
634 for (unsigned int i = 1; i < count; i++) | 736 for (unsigned int i = 1; i < count; i++) |
635 { | 737 { |
636 unsigned int property; | 738 if (!skippy_iter.next ()) return TRACE_RETURN (false); |
637 | |
638 if (!skippy_iter.next (&property)) return TRACE_RETURN (false); | |
639 | |
640 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i
- 1], match_data))) return TRACE_RETURN (false); | |
641 | 739 |
642 unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); | 740 unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); |
643 unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx])
; | 741 unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx])
; |
644 | 742 |
645 if (first_lig_id && first_lig_comp) { | 743 if (first_lig_id && first_lig_comp) { |
646 /* If first component was attached to a previous ligature component, | 744 /* If first component was attached to a previous ligature component, |
647 * all subsequent components should be attached to the same ligature | 745 * all subsequent components should be attached to the same ligature |
648 * component, otherwise we shouldn't ligate them. */ | 746 * component, otherwise we shouldn't ligate them. */ |
649 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) | 747 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) |
650 return TRACE_RETURN (false); | 748 return TRACE_RETURN (false); |
651 } else { | 749 } else { |
652 /* If first component was NOT attached to a previous ligature component, | 750 /* If first component was NOT attached to a previous ligature component, |
653 * all subsequent components should also NOT be attached to any ligature | 751 * all subsequent components should also NOT be attached to any ligature |
654 * component, unless they are attached to the first component itself! */ | 752 * component, unless they are attached to the first component itself! */ |
655 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) | 753 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) |
656 return TRACE_RETURN (false); | 754 return TRACE_RETURN (false); |
657 } | 755 } |
658 | 756 |
659 is_mark_ligature = is_mark_ligature && (property & HB_OT_LAYOUT_GLYPH_PROPS_
MARK); | 757 is_mark_ligature = is_mark_ligature && (c->buffer->info[skippy_iter.idx].gly
ph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); |
660 total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]
); | 758 total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]
); |
661 } | 759 } |
662 | 760 |
663 if (end_offset) | 761 if (end_offset) |
664 *end_offset = skippy_iter.idx - c->buffer->idx + 1; | 762 *end_offset = skippy_iter.idx - c->buffer->idx + 1; |
665 | 763 |
666 if (p_is_mark_ligature) | 764 if (p_is_mark_ligature) |
667 *p_is_mark_ligature = is_mark_ligature; | 765 *p_is_mark_ligature = is_mark_ligature; |
668 | 766 |
669 if (p_total_component_count) | 767 if (p_total_component_count) |
670 *p_total_component_count = total_component_count; | 768 *p_total_component_count = total_component_count; |
671 | 769 |
672 return TRACE_RETURN (true); | 770 return TRACE_RETURN (true); |
673 } | 771 } |
674 static inline void ligate_input (hb_apply_context_t *c, | 772 static inline void ligate_input (hb_apply_context_t *c, |
675 unsigned int count, /* Including the first glyp
h (not matched) */ | 773 unsigned int count, /* Including the first glyp
h (not matched) */ |
676 » » » » const USHORT input[] HB_UNUSED, /* Array of inp
ut values--start with second glyph */ | 774 » » » » const USHORT input[], /* Array of input values-
-start with second glyph */ |
| 775 » » » » match_func_t match_func, |
| 776 » » » » const void *match_data, |
677 hb_codepoint_t lig_glyph, | 777 hb_codepoint_t lig_glyph, |
678 match_func_t match_func HB_UNUSED, | |
679 const void *match_data HB_UNUSED, | |
680 bool is_mark_ligature, | 778 bool is_mark_ligature, |
681 unsigned int total_component_count) | 779 unsigned int total_component_count) |
682 { | 780 { |
| 781 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx
, count - 1); |
| 782 skippy_iter.set_match_func (match_func, match_data, input); |
| 783 if (skippy_iter.has_no_chance ()) return; |
| 784 |
683 /* | 785 /* |
684 * - If it *is* a mark ligature, we don't allocate a new ligature id, and leav
e | 786 * - If it *is* a mark ligature, we don't allocate a new ligature id, and leav
e |
685 * the ligature to keep its old ligature id. This will allow it to attach t
o | 787 * the ligature to keep its old ligature id. This will allow it to attach t
o |
686 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HE
H, | 788 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HE
H, |
687 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a | 789 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a |
688 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligatu
re | 790 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligatu
re |
689 * later, we don't want them to lose their ligature id/component, otherwise | 791 * later, we don't want them to lose their ligature id/component, otherwise |
690 * GPOS will fail to correctly position the mark ligature on top of the | 792 * GPOS will fail to correctly position the mark ligature on top of the |
691 * LAM,LAM,HEH ligature. See: | 793 * LAM,LAM,HEH ligature. See: |
692 * https://bugzilla.gnome.org/show_bug.cgi?id=676343 | 794 * https://bugzilla.gnome.org/show_bug.cgi?id=676343 |
(...skipping 20 matching lines...) Expand all Loading... |
713 unsigned int last_lig_id = get_lig_id (c->buffer->cur()); | 815 unsigned int last_lig_id = get_lig_id (c->buffer->cur()); |
714 unsigned int last_num_components = get_lig_num_comps (c->buffer->cur()); | 816 unsigned int last_num_components = get_lig_num_comps (c->buffer->cur()); |
715 unsigned int components_so_far = last_num_components; | 817 unsigned int components_so_far = last_num_components; |
716 | 818 |
717 if (!is_mark_ligature) | 819 if (!is_mark_ligature) |
718 set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count)
; | 820 set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count)
; |
719 c->replace_glyph (lig_glyph, klass); | 821 c->replace_glyph (lig_glyph, klass); |
720 | 822 |
721 for (unsigned int i = 1; i < count; i++) | 823 for (unsigned int i = 1; i < count; i++) |
722 { | 824 { |
723 while (c->should_mark_skip_current_glyph ()) | 825 if (!skippy_iter.next ()) return; |
| 826 |
| 827 while (c->buffer->idx < skippy_iter.idx) |
724 { | 828 { |
725 if (!is_mark_ligature) { | 829 if (!is_mark_ligature) { |
726 unsigned int new_lig_comp = components_so_far - last_num_components + | 830 unsigned int new_lig_comp = components_so_far - last_num_components + |
727 MIN (MAX (get_lig_comp (c->buffer->cur()), 1
u), last_num_components); | 831 MIN (MAX (get_lig_comp (c->buffer->cur()), 1
u), last_num_components); |
728 set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp); | 832 set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp); |
729 } | 833 } |
730 c->buffer->next_glyph (); | 834 c->buffer->next_glyph (); |
731 } | 835 } |
732 | 836 |
733 last_lig_id = get_lig_id (c->buffer->cur()); | 837 last_lig_id = get_lig_id (c->buffer->cur()); |
(...skipping 18 matching lines...) Expand all Loading... |
752 } | 856 } |
753 | 857 |
754 static inline bool match_backtrack (hb_apply_context_t *c, | 858 static inline bool match_backtrack (hb_apply_context_t *c, |
755 unsigned int count, | 859 unsigned int count, |
756 const USHORT backtrack[], | 860 const USHORT backtrack[], |
757 match_func_t match_func, | 861 match_func_t match_func, |
758 const void *match_data) | 862 const void *match_data) |
759 { | 863 { |
760 TRACE_APPLY (NULL); | 864 TRACE_APPLY (NULL); |
761 | 865 |
762 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffe
r->backtrack_len (), count, true); | 866 hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->ba
cktrack_len (), count, true); |
763 if (skippy_iter.has_no_chance ()) | 867 skippy_iter.set_match_func (match_func, match_data, backtrack); |
764 return TRACE_RETURN (false); | 868 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
765 | 869 |
766 for (unsigned int i = 0; i < count; i++) | 870 for (unsigned int i = 0; i < count; i++) |
767 { | |
768 if (!skippy_iter.prev ()) | 871 if (!skippy_iter.prev ()) |
769 return TRACE_RETURN (false); | 872 return TRACE_RETURN (false); |
770 | 873 |
771 if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, bac
ktrack[i], match_data))) | |
772 return TRACE_RETURN (false); | |
773 } | |
774 | |
775 return TRACE_RETURN (true); | 874 return TRACE_RETURN (true); |
776 } | 875 } |
777 | 876 |
778 static inline bool match_lookahead (hb_apply_context_t *c, | 877 static inline bool match_lookahead (hb_apply_context_t *c, |
779 unsigned int count, | 878 unsigned int count, |
780 const USHORT lookahead[], | 879 const USHORT lookahead[], |
781 match_func_t match_func, | 880 match_func_t match_func, |
782 const void *match_data, | 881 const void *match_data, |
783 unsigned int offset) | 882 unsigned int offset) |
784 { | 883 { |
785 TRACE_APPLY (NULL); | 884 TRACE_APPLY (NULL); |
786 | 885 |
787 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer
->idx + offset - 1, count, true); | 886 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx
+ offset - 1, count, true); |
788 if (skippy_iter.has_no_chance ()) | 887 skippy_iter.set_match_func (match_func, match_data, lookahead); |
789 return TRACE_RETURN (false); | 888 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); |
790 | 889 |
791 for (unsigned int i = 0; i < count; i++) | 890 for (unsigned int i = 0; i < count; i++) |
792 { | |
793 if (!skippy_iter.next ()) | 891 if (!skippy_iter.next ()) |
794 return TRACE_RETURN (false); | 892 return TRACE_RETURN (false); |
795 | 893 |
796 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahe
ad[i], match_data))) | |
797 return TRACE_RETURN (false); | |
798 } | |
799 | |
800 return TRACE_RETURN (true); | 894 return TRACE_RETURN (true); |
801 } | 895 } |
802 | 896 |
803 | 897 |
804 | 898 |
805 struct LookupRecord | 899 struct LookupRecord |
806 { | 900 { |
807 inline bool sanitize (hb_sanitize_context_t *c) { | 901 inline bool sanitize (hb_sanitize_context_t *c) { |
808 TRACE_SANITIZE (this); | 902 TRACE_SANITIZE (this); |
809 return TRACE_RETURN (c->check_struct (this)); | 903 return TRACE_RETURN (c->check_struct (this)); |
(...skipping 12 matching lines...) Expand all Loading... |
822 static inline void recurse_lookups (context_t *c, | 916 static inline void recurse_lookups (context_t *c, |
823 unsigned int lookupCount, | 917 unsigned int lookupCount, |
824 const LookupRecord lookupRecord[] /* Array o
f LookupRecords--in design order */) | 918 const LookupRecord lookupRecord[] /* Array o
f LookupRecords--in design order */) |
825 { | 919 { |
826 for (unsigned int i = 0; i < lookupCount; i++) | 920 for (unsigned int i = 0; i < lookupCount; i++) |
827 c->recurse (lookupRecord->lookupListIndex); | 921 c->recurse (lookupRecord->lookupListIndex); |
828 } | 922 } |
829 | 923 |
830 static inline bool apply_lookup (hb_apply_context_t *c, | 924 static inline bool apply_lookup (hb_apply_context_t *c, |
831 unsigned int count, /* Including the first glyp
h */ | 925 unsigned int count, /* Including the first glyp
h */ |
| 926 const USHORT input[], /* Array of input values-
-start with second glyph */ |
| 927 match_func_t match_func, |
| 928 const void *match_data, |
832 unsigned int lookupCount, | 929 unsigned int lookupCount, |
833 const LookupRecord lookupRecord[] /* Array of L
ookupRecords--in design order */) | 930 const LookupRecord lookupRecord[] /* Array of L
ookupRecords--in design order */) |
834 { | 931 { |
835 TRACE_APPLY (NULL); | 932 TRACE_APPLY (NULL); |
836 | 933 |
837 unsigned int end = c->buffer->len; | 934 unsigned int end = c->buffer->len; |
838 if (unlikely (count == 0 || c->buffer->idx + count > end)) | 935 if (unlikely (count == 0 || c->buffer->idx + count > end)) |
839 return TRACE_RETURN (false); | 936 return TRACE_RETURN (false); |
840 | 937 |
841 /* TODO We don't support lookupRecord arrays that are not increasing: | 938 /* TODO We don't support lookupRecord arrays that are not increasing: |
842 * Should be easy for in_place ones at least. */ | 939 * Should be easy for in_place ones at least. */ |
843 | 940 |
844 /* Note: If sublookup is reverse, it will underflow after the first loop | 941 /* Note: If sublookup is reverse, it will underflow after the first loop |
845 * and we jump out of it. Not entirely disastrous. So we don't check | 942 * and we jump out of it. Not entirely disastrous. So we don't check |
846 * for reverse lookup here. | 943 * for reverse lookup here. |
847 */ | 944 */ |
848 for (unsigned int i = 0; i < count; /* NOP */) | 945 |
| 946 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx
, count - 1); |
| 947 skippy_iter.set_match_func (match_func, match_data, input); |
| 948 uint8_t syllable = c->buffer->cur().syllable(); |
| 949 |
| 950 unsigned int i = 0; |
| 951 if (lookupCount && 0 == lookupRecord->sequenceIndex) |
849 { | 952 { |
850 if (unlikely (c->buffer->idx == end)) | 953 unsigned int old_pos = c->buffer->idx; |
851 return TRACE_RETURN (true); | 954 |
852 while (c->should_mark_skip_current_glyph ()) | 955 /* Apply a lookup */ |
| 956 bool done = c->recurse (lookupRecord->lookupListIndex); |
| 957 |
| 958 lookupRecord++; |
| 959 lookupCount--; |
| 960 /* Err, this is wrong if the lookup jumped over some glyphs */ |
| 961 i += c->buffer->idx - old_pos; |
| 962 |
| 963 if (!done) |
| 964 goto not_applied; |
| 965 else |
853 { | 966 { |
854 /* No lookup applied for this index */ | 967 /* Reinitialize iterator. */ |
| 968 hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1
, count - i); |
| 969 tmp.set_syllable (syllable); |
| 970 skippy_iter = tmp; |
| 971 } |
| 972 } |
| 973 else |
| 974 { |
| 975 not_applied: |
| 976 /* No lookup applied for this index */ |
| 977 c->buffer->next_glyph (); |
| 978 i++; |
| 979 } |
| 980 while (i < count) |
| 981 { |
| 982 if (!skippy_iter.next ()) return TRACE_RETURN (true); |
| 983 while (c->buffer->idx < skippy_iter.idx) |
855 c->buffer->next_glyph (); | 984 c->buffer->next_glyph (); |
856 if (unlikely (c->buffer->idx == end)) | |
857 return TRACE_RETURN (true); | |
858 } | |
859 | 985 |
860 if (lookupCount && i == lookupRecord->sequenceIndex) | 986 if (lookupCount && i == lookupRecord->sequenceIndex) |
861 { | 987 { |
862 unsigned int old_pos = c->buffer->idx; | 988 unsigned int old_pos = c->buffer->idx; |
863 | 989 |
864 /* Apply a lookup */ | 990 /* Apply a lookup */ |
865 bool done = c->recurse (lookupRecord->lookupListIndex); | 991 bool done = c->recurse (lookupRecord->lookupListIndex); |
866 | 992 |
867 lookupRecord++; | 993 lookupRecord++; |
868 lookupCount--; | 994 lookupCount--; |
869 /* Err, this is wrong if the lookup jumped over some glyphs */ | 995 /* Err, this is wrong if the lookup jumped over some glyphs */ |
870 i += c->buffer->idx - old_pos; | 996 i += c->buffer->idx - old_pos; |
871 if (unlikely (c->buffer->idx == end)) | |
872 return TRACE_RETURN (true); | |
873 | 997 |
874 if (!done) | 998 if (!done) |
875 » goto not_applied; | 999 » goto not_applied2; |
| 1000 else |
| 1001 { |
| 1002 /* Reinitialize iterator. */ |
| 1003 » hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx -
1, count - i); |
| 1004 » tmp.set_syllable (syllable); |
| 1005 » skippy_iter = tmp; |
| 1006 } |
876 } | 1007 } |
877 else | 1008 else |
878 { | 1009 { |
879 not_applied: | 1010 not_applied2: |
880 /* No lookup applied for this index */ | 1011 /* No lookup applied for this index */ |
881 c->buffer->next_glyph (); | 1012 c->buffer->next_glyph (); |
882 i++; | 1013 i++; |
883 } | 1014 } |
884 } | 1015 } |
885 | 1016 |
886 return TRACE_RETURN (true); | 1017 return TRACE_RETURN (true); |
887 } | 1018 } |
888 | 1019 |
889 | 1020 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 unsigned int inputCount, /* Including t
he first glyph (not matched) */ | 1082 unsigned int inputCount, /* Including t
he first glyph (not matched) */ |
952 const USHORT input[], /* Array of input
values--start with second glyph */ | 1083 const USHORT input[], /* Array of input
values--start with second glyph */ |
953 unsigned int lookupCount, | 1084 unsigned int lookupCount, |
954 const LookupRecord lookupRecord[], | 1085 const LookupRecord lookupRecord[], |
955 ContextApplyLookupContext &lookup_conte
xt) | 1086 ContextApplyLookupContext &lookup_conte
xt) |
956 { | 1087 { |
957 return match_input (c, | 1088 return match_input (c, |
958 inputCount, input, | 1089 inputCount, input, |
959 lookup_context.funcs.match, lookup_context.match_data) | 1090 lookup_context.funcs.match, lookup_context.match_data) |
960 && apply_lookup (c, | 1091 && apply_lookup (c, |
961 » » inputCount, | 1092 » » inputCount, input, |
| 1093 » » lookup_context.funcs.match, lookup_context.match_data, |
962 lookupCount, lookupRecord); | 1094 lookupCount, lookupRecord); |
963 } | 1095 } |
964 | 1096 |
965 struct Rule | 1097 struct Rule |
966 { | 1098 { |
967 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &loo
kup_context) const | 1099 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &loo
kup_context) const |
968 { | 1100 { |
969 TRACE_CLOSURE (this); | 1101 TRACE_CLOSURE (this); |
970 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, inp
ut[0].static_size * (inputCount ? inputCount - 1 : 0)); | 1102 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, inp
ut[0].static_size * (inputCount ? inputCount - 1 : 0)); |
971 context_closure_lookup (c, | 1103 context_closure_lookup (c, |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1346 * table in glyph sequence order */ | 1478 * table in glyph sequence order */ |
1347 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in | 1479 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in |
1348 * design order */ | 1480 * design order */ |
1349 public: | 1481 public: |
1350 DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX); | 1482 DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX); |
1351 }; | 1483 }; |
1352 | 1484 |
1353 struct Context | 1485 struct Context |
1354 { | 1486 { |
1355 template <typename context_t> | 1487 template <typename context_t> |
1356 inline typename context_t::return_t process (context_t *c) const | 1488 inline typename context_t::return_t dispatch (context_t *c) const |
1357 { | 1489 { |
1358 TRACE_PROCESS (this); | 1490 TRACE_DISPATCH (this); |
1359 switch (u.format) { | 1491 switch (u.format) { |
1360 case 1: return TRACE_RETURN (c->process (u.format1)); | 1492 case 1: return TRACE_RETURN (c->dispatch (u.format1)); |
1361 case 2: return TRACE_RETURN (c->process (u.format2)); | 1493 case 2: return TRACE_RETURN (c->dispatch (u.format2)); |
1362 case 3: return TRACE_RETURN (c->process (u.format3)); | 1494 case 3: return TRACE_RETURN (c->dispatch (u.format3)); |
1363 default:return TRACE_RETURN (c->default_return_value ()); | 1495 default:return TRACE_RETURN (c->default_return_value ()); |
1364 } | 1496 } |
1365 } | 1497 } |
1366 | 1498 |
1367 inline bool sanitize (hb_sanitize_context_t *c) { | 1499 inline bool sanitize (hb_sanitize_context_t *c) { |
1368 TRACE_SANITIZE (this); | 1500 TRACE_SANITIZE (this); |
1369 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 1501 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
1370 switch (u.format) { | 1502 switch (u.format) { |
1371 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 1503 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
1372 case 2: return TRACE_RETURN (u.format2.sanitize (c)); | 1504 case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1487 lookup_context.funcs.match, lookup_context.match_data[1], | 1619 lookup_context.funcs.match, lookup_context.match_data[1], |
1488 &lookahead_offset) | 1620 &lookahead_offset) |
1489 && match_backtrack (c, | 1621 && match_backtrack (c, |
1490 backtrackCount, backtrack, | 1622 backtrackCount, backtrack, |
1491 lookup_context.funcs.match, lookup_context.match_data[
0]) | 1623 lookup_context.funcs.match, lookup_context.match_data[
0]) |
1492 && match_lookahead (c, | 1624 && match_lookahead (c, |
1493 lookaheadCount, lookahead, | 1625 lookaheadCount, lookahead, |
1494 lookup_context.funcs.match, lookup_context.match_data[
2], | 1626 lookup_context.funcs.match, lookup_context.match_data[
2], |
1495 lookahead_offset) | 1627 lookahead_offset) |
1496 && apply_lookup (c, | 1628 && apply_lookup (c, |
1497 » » inputCount, | 1629 » » inputCount, input, |
| 1630 » » lookup_context.funcs.match, lookup_context.match_data[1], |
1498 lookupCount, lookupRecord); | 1631 lookupCount, lookupRecord); |
1499 } | 1632 } |
1500 | 1633 |
1501 struct ChainRule | 1634 struct ChainRule |
1502 { | 1635 { |
1503 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext
&lookup_context) const | 1636 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext
&lookup_context) const |
1504 { | 1637 { |
1505 TRACE_CLOSURE (this); | 1638 TRACE_CLOSURE (this); |
1506 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> >
(backtrack); | 1639 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> >
(backtrack); |
1507 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); | 1640 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1961 ArrayOf<LookupRecord> | 2094 ArrayOf<LookupRecord> |
1962 lookupX; /* Array of LookupRecords--in | 2095 lookupX; /* Array of LookupRecords--in |
1963 * design order) */ | 2096 * design order) */ |
1964 public: | 2097 public: |
1965 DEFINE_SIZE_MIN (10); | 2098 DEFINE_SIZE_MIN (10); |
1966 }; | 2099 }; |
1967 | 2100 |
1968 struct ChainContext | 2101 struct ChainContext |
1969 { | 2102 { |
1970 template <typename context_t> | 2103 template <typename context_t> |
1971 inline typename context_t::return_t process (context_t *c) const | 2104 inline typename context_t::return_t dispatch (context_t *c) const |
1972 { | 2105 { |
1973 TRACE_PROCESS (this); | 2106 TRACE_DISPATCH (this); |
1974 switch (u.format) { | 2107 switch (u.format) { |
1975 case 1: return TRACE_RETURN (c->process (u.format1)); | 2108 case 1: return TRACE_RETURN (c->dispatch (u.format1)); |
1976 case 2: return TRACE_RETURN (c->process (u.format2)); | 2109 case 2: return TRACE_RETURN (c->dispatch (u.format2)); |
1977 case 3: return TRACE_RETURN (c->process (u.format3)); | 2110 case 3: return TRACE_RETURN (c->dispatch (u.format3)); |
1978 default:return TRACE_RETURN (c->default_return_value ()); | 2111 default:return TRACE_RETURN (c->default_return_value ()); |
1979 } | 2112 } |
1980 } | 2113 } |
1981 | 2114 |
1982 inline bool sanitize (hb_sanitize_context_t *c) { | 2115 inline bool sanitize (hb_sanitize_context_t *c) { |
1983 TRACE_SANITIZE (this); | 2116 TRACE_SANITIZE (this); |
1984 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 2117 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
1985 switch (u.format) { | 2118 switch (u.format) { |
1986 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 2119 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
1987 case 2: return TRACE_RETURN (u.format2.sanitize (c)); | 2120 case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2041 | 2174 |
2042 template <typename X> | 2175 template <typename X> |
2043 inline const X& get_subtable (void) const | 2176 inline const X& get_subtable (void) const |
2044 { | 2177 { |
2045 unsigned int offset = get_offset (); | 2178 unsigned int offset = get_offset (); |
2046 if (unlikely (!offset)) return Null(typename T::LookupSubTable); | 2179 if (unlikely (!offset)) return Null(typename T::LookupSubTable); |
2047 return StructAtOffset<typename T::LookupSubTable> (this, offset); | 2180 return StructAtOffset<typename T::LookupSubTable> (this, offset); |
2048 } | 2181 } |
2049 | 2182 |
2050 template <typename context_t> | 2183 template <typename context_t> |
2051 inline typename context_t::return_t process (context_t *c) const | 2184 inline typename context_t::return_t dispatch (context_t *c) const |
2052 { | 2185 { |
2053 return get_subtable<typename T::LookupSubTable> ().process (c, get_type ()); | 2186 return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ())
; |
2054 } | 2187 } |
2055 | 2188 |
2056 inline bool sanitize_self (hb_sanitize_context_t *c) { | 2189 inline bool sanitize_self (hb_sanitize_context_t *c) { |
2057 TRACE_SANITIZE (this); | 2190 TRACE_SANITIZE (this); |
2058 if (!u.format.sanitize (c)) return TRACE_RETURN (false); | 2191 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
2059 switch (u.format) { | 2192 switch (u.format) { |
2060 case 1: return TRACE_RETURN (u.format1.sanitize (c)); | 2193 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
2061 default:return TRACE_RETURN (true); | 2194 default:return TRACE_RETURN (true); |
2062 } | 2195 } |
2063 } | 2196 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2137 lookupList; /* LookupList table */ | 2270 lookupList; /* LookupList table */ |
2138 public: | 2271 public: |
2139 DEFINE_SIZE_STATIC (10); | 2272 DEFINE_SIZE_STATIC (10); |
2140 }; | 2273 }; |
2141 | 2274 |
2142 | 2275 |
2143 } /* namespace OT */ | 2276 } /* namespace OT */ |
2144 | 2277 |
2145 | 2278 |
2146 #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */ | 2279 #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */ |
OLD | NEW |