| 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 |