< prev index next >

src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos-private.hh

Print this page

        

*** 27,53 **** */ #ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH #define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH #include "hb-buffer-private.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-set-private.hh" namespace OT { - #ifndef HB_DEBUG_CLOSURE - #define HB_DEBUG_CLOSURE (HB_DEBUG+0) - #endif - - #define TRACE_CLOSURE(this) \ - hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - struct hb_closure_context_t : hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE> { inline const char *get_name (void) { return "CLOSURE"; } typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index); --- 27,46 ---- */ #ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH #define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH + #include "hb-private.hh" + #include "hb-debug.hh" #include "hb-buffer-private.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-set-private.hh" namespace OT { struct hb_closure_context_t : hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE> { inline const char *get_name (void) { return "CLOSURE"; } typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
*** 75,102 **** hb_closure_context_t (hb_face_t *face_, hb_set_t *glyphs_, unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), glyphs (glyphs_), ! recurse_func (NULL), nesting_level_left (nesting_level_left_), debug_depth (0) {} void set_recurse_func (recurse_func_t func) { recurse_func = func; } }; - - #ifndef HB_DEBUG_WOULD_APPLY - #define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0) - #endif - - #define TRACE_WOULD_APPLY(this) \ - hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - "%d glyphs", c->len); - struct hb_would_apply_context_t : hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY> { inline const char *get_name (void) { return "WOULD_APPLY"; } template <typename T> --- 68,85 ---- hb_closure_context_t (hb_face_t *face_, hb_set_t *glyphs_, unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), glyphs (glyphs_), ! recurse_func (nullptr), nesting_level_left (nesting_level_left_), debug_depth (0) {} void set_recurse_func (recurse_func_t func) { recurse_func = func; } }; struct hb_would_apply_context_t : hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY> { inline const char *get_name (void) { return "WOULD_APPLY"; } template <typename T>
*** 120,139 **** zero_context (zero_context_), debug_depth (0) {} }; - - #ifndef HB_DEBUG_COLLECT_GLYPHS - #define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0) - #endif - - #define TRACE_COLLECT_GLYPHS(this) \ - hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - struct hb_collect_glyphs_context_t : hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS> { inline const char *get_name (void) { return "COLLECT_GLYPHS"; } typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index); --- 103,112 ----
*** 144,154 **** return_t recurse (unsigned int lookup_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) return default_return_value (); ! /* Note that GPOS sets recurse_func to NULL already, so it doesn't get * past the previous check. For GSUB, we only want to collect the output * glyphs in the recursion. If output is not requested, we can go home now. * * Note further, that the above is not exactly correct. A recursed lookup * is allowed to match input that is not matched in the context, but that's --- 117,127 ---- return_t recurse (unsigned int lookup_index) { if (unlikely (nesting_level_left == 0 || !recurse_func)) return default_return_value (); ! /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get * past the previous check. For GSUB, we only want to collect the output * glyphs in the recursion. If output is not requested, we can go home now. * * Note further, that the above is not exactly correct. A recursed lookup * is allowed to match input that is not matched in the context, but that's
*** 158,168 **** if (output == hb_set_get_empty ()) return HB_VOID; /* Return if new lookup was recursed to before. */ ! if (recursed_lookups.has (lookup_index)) return HB_VOID; hb_set_t *old_before = before; hb_set_t *old_input = input; hb_set_t *old_after = after; --- 131,141 ---- if (output == hb_set_get_empty ()) return HB_VOID; /* Return if new lookup was recursed to before. */ ! if (recursed_lookups->has (lookup_index)) return HB_VOID; hb_set_t *old_before = before; hb_set_t *old_input = input; hb_set_t *old_after = after;
*** 174,230 **** before = old_before; input = old_input; after = old_after; ! recursed_lookups.add (lookup_index); return HB_VOID; } hb_face_t *face; hb_set_t *before; hb_set_t *input; hb_set_t *after; hb_set_t *output; recurse_func_t recurse_func; ! hb_set_t recursed_lookups; unsigned int nesting_level_left; unsigned int debug_depth; hb_collect_glyphs_context_t (hb_face_t *face_, ! hb_set_t *glyphs_before, /* OUT. May be NULL */ ! hb_set_t *glyphs_input, /* OUT. May be NULL */ ! hb_set_t *glyphs_after, /* OUT. May be NULL */ ! hb_set_t *glyphs_output, /* OUT. May be NULL */ unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), before (glyphs_before ? glyphs_before : hb_set_get_empty ()), input (glyphs_input ? glyphs_input : hb_set_get_empty ()), after (glyphs_after ? glyphs_after : hb_set_get_empty ()), output (glyphs_output ? glyphs_output : hb_set_get_empty ()), ! recurse_func (NULL), ! recursed_lookups (), nesting_level_left (nesting_level_left_), debug_depth (0) { ! recursed_lookups.init (); } ~hb_collect_glyphs_context_t (void) { ! recursed_lookups.fini (); } void set_recurse_func (recurse_func_t func) { recurse_func = func; } }; - #ifndef HB_DEBUG_GET_COVERAGE - #define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0) - #endif - /* XXX Can we remove this? */ template <typename set_t> struct hb_add_coverage_context_t : hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE> --- 147,199 ---- before = old_before; input = old_input; after = old_after; ! recursed_lookups->add (lookup_index); return HB_VOID; } hb_face_t *face; hb_set_t *before; hb_set_t *input; hb_set_t *after; hb_set_t *output; recurse_func_t recurse_func; ! hb_set_t *recursed_lookups; unsigned int nesting_level_left; unsigned int debug_depth; hb_collect_glyphs_context_t (hb_face_t *face_, ! hb_set_t *glyphs_before, /* OUT. May be nullptr */ ! hb_set_t *glyphs_input, /* OUT. May be nullptr */ ! hb_set_t *glyphs_after, /* OUT. May be nullptr */ ! hb_set_t *glyphs_output, /* OUT. May be nullptr */ unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), before (glyphs_before ? glyphs_before : hb_set_get_empty ()), input (glyphs_input ? glyphs_input : hb_set_get_empty ()), after (glyphs_after ? glyphs_after : hb_set_get_empty ()), output (glyphs_output ? glyphs_output : hb_set_get_empty ()), ! recurse_func (nullptr), ! recursed_lookups (nullptr), nesting_level_left (nesting_level_left_), debug_depth (0) { ! recursed_lookups = hb_set_create (); } ~hb_collect_glyphs_context_t (void) { ! hb_set_destroy (recursed_lookups); } void set_recurse_func (recurse_func_t func) { recurse_func = func; } }; /* XXX Can we remove this? */ template <typename set_t> struct hb_add_coverage_context_t : hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
*** 247,267 **** set_t *set; unsigned int debug_depth; }; - - #ifndef HB_DEBUG_APPLY - #define HB_DEBUG_APPLY (HB_DEBUG+0) - #endif - - #define TRACE_APPLY(this) \ - hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - "idx %d gid %u lookup %d", \ - c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index); - struct hb_apply_context_t : hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY> { struct matcher_t { --- 216,225 ----
*** 271,282 **** ignore_zwj (false), mask (-1), #define arg1(arg) (arg) /* Remove the macro to see why it's needed! */ syllable arg1(0), #undef arg1 ! match_func (NULL), ! match_data (NULL) {}; typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data); inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; } inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } --- 229,240 ---- ignore_zwj (false), mask (-1), #define arg1(arg) (arg) /* Remove the macro to see why it's needed! */ syllable arg1(0), #undef arg1 ! match_func (nullptr), ! match_data (nullptr) {}; typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data); inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; } inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
*** 317,327 **** const hb_glyph_info_t &info) const { if (!c->check_glyph_property (&info, lookup_props)) return SKIP_YES; ! if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_fvs (&info) && (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && (ignore_zwj || !_hb_glyph_info_is_zwj (&info)))) return SKIP_MAYBE; return SKIP_NO; --- 275,285 ---- const hb_glyph_info_t &info) const { if (!c->check_glyph_property (&info, lookup_props)) return SKIP_YES; ! if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) && (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && (ignore_zwj || !_hb_glyph_info_is_zwj (&info)))) return SKIP_MAYBE; return SKIP_NO;
*** 340,356 **** struct skipping_iterator_t { inline void init (hb_apply_context_t *c_, bool context_match = false) { c = c_; ! match_glyph_data = NULL, ! matcher.set_match_func (NULL, NULL); matcher.set_lookup_props (c->lookup_props); /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ ! matcher.set_ignore_zwnj (context_match || c->table_index == 1); /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ ! matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj); matcher.set_mask (context_match ? -1 : c->lookup_mask); } inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); --- 298,314 ---- struct skipping_iterator_t { inline void init (hb_apply_context_t *c_, bool context_match = false) { c = c_; ! match_glyph_data = nullptr; ! matcher.set_match_func (nullptr, nullptr); matcher.set_lookup_props (c->lookup_props); /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ ! matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj)); /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ ! matcher.set_ignore_zwj (c->table_index == 1 || (context_match || c->auto_zwj)); matcher.set_mask (context_match ? -1 : c->lookup_mask); } inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props);
*** 372,381 **** --- 330,346 ---- matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0); } inline void reject (void) { num_items++; match_glyph_data--; } + inline matcher_t::may_skip_t + may_skip (const hb_apply_context_t *c, + const hb_glyph_info_t &info) const + { + return matcher.may_skip (c, info); + } + inline bool next (void) { assert (num_items > 0); while (idx + num_items < end) {
*** 455,503 **** bool ret = recurse_func (this, lookup_index); nesting_level_left++; return ret; } ! unsigned int table_index; /* GSUB/GPOS */ hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; - hb_direction_t direction; - hb_mask_t lookup_mask; - bool auto_zwj; recurse_func_t recurse_func; - unsigned int nesting_level_left; - unsigned int lookup_props; const GDEF &gdef; - bool has_glyph_classes; const VariationStore &var_store; ! skipping_iterator_t iter_input, iter_context; unsigned int lookup_index; unsigned int debug_depth; hb_apply_context_t (unsigned int table_index_, hb_font_t *font_, hb_buffer_t *buffer_) : ! table_index (table_index_), font (font_), face (font->face), buffer (buffer_), ! direction (buffer_->props.direction), ! lookup_mask (1), ! auto_zwj (true), ! recurse_func (NULL), ! nesting_level_left (HB_MAX_NESTING_LEVEL), ! lookup_props (0), gdef (*hb_ot_layout_from_face (face)->gdef), - has_glyph_classes (gdef.has_glyph_classes ()), var_store (gdef.get_var_store ()), ! iter_input (), ! iter_context (), lookup_index ((unsigned int) -1), ! debug_depth (0) {} inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; --- 420,473 ---- bool ret = recurse_func (this, lookup_index); nesting_level_left++; return ret; } ! skipping_iterator_t iter_input, iter_context; ! hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; recurse_func_t recurse_func; const GDEF &gdef; const VariationStore &var_store; ! ! hb_direction_t direction; ! hb_mask_t lookup_mask; ! unsigned int table_index; /* GSUB/GPOS */ unsigned int lookup_index; + unsigned int lookup_props; + unsigned int nesting_level_left; unsigned int debug_depth; + bool auto_zwnj; + bool auto_zwj; + bool has_glyph_classes; + hb_apply_context_t (unsigned int table_index_, hb_font_t *font_, hb_buffer_t *buffer_) : ! iter_input (), iter_context (), font (font_), face (font->face), buffer (buffer_), ! recurse_func (nullptr), gdef (*hb_ot_layout_from_face (face)->gdef), var_store (gdef.get_var_store ()), ! direction (buffer_->props.direction), ! lookup_mask (1), ! table_index (table_index_), lookup_index ((unsigned int) -1), ! lookup_props (0), ! nesting_level_left (HB_MAX_NESTING_LEVEL), ! debug_depth (0), ! auto_zwnj (true), ! auto_zwj (true), ! has_glyph_classes (gdef.has_glyph_classes ()) {} inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } + inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; } inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_;
*** 705,718 **** const USHORT input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data, unsigned int *end_offset, unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], ! bool *p_is_mark_ligature = NULL, ! unsigned int *p_total_component_count = NULL) { ! TRACE_APPLY (NULL); if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false); hb_buffer_t *buffer = c->buffer; --- 675,688 ---- const USHORT input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data, unsigned int *end_offset, unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], ! bool *p_is_mark_ligature = nullptr, ! unsigned int *p_total_component_count = nullptr) { ! TRACE_APPLY (nullptr); if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false); hb_buffer_t *buffer = c->buffer;
*** 729,770 **** * it as a ligature glyph. * * - Ligatures cannot be formed across glyphs attached to different components * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. ! * However, it would be wrong to ligate that SHADDA,FATHA sequence.o ! * There is an exception to this: If a ligature tries ligating with marks that ! * belong to it itself, go ahead, assuming that the font designer knows what ! * they are doing (otherwise it can break Indic stuff when a matra wants to ! * ligate with a conjunct...) */ bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur()); unsigned int total_component_count = 0; total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur()); unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { if (!skippy_iter.next ()) return_trace (false); match_positions[i] = skippy_iter.idx; unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]); unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]); ! if (first_lig_id && first_lig_comp) { /* If first component was attached to a previous ligature component, * all subsequent components should be attached to the same ligature ! * component, otherwise we shouldn't ligate them. */ if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) return_trace (false); ! } else { /* If first component was NOT attached to a previous ligature component, * all subsequent components should also NOT be attached to any ligature * component, unless they are attached to the first component itself! */ if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) return_trace (false); --- 699,782 ---- * it as a ligature glyph. * * - Ligatures cannot be formed across glyphs attached to different components * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. ! * However, it would be wrong to ligate that SHADDA,FATHA sequence. ! * There are a couple of exceptions to this: ! * ! * o If a ligature tries ligating with marks that belong to it itself, go ahead, ! * assuming that the font designer knows what they are doing (otherwise it can ! * break Indic stuff when a matra wants to ligate with a conjunct, ! * ! * o If two marks want to ligate and they belong to different components of the ! * same ligature glyph, and said ligature glyph is to be ignored according to ! * mark-filtering rules, then allow. ! * https://github.com/behdad/harfbuzz/issues/545 */ bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur()); unsigned int total_component_count = 0; total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur()); unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); + enum { + LIGBASE_NOT_CHECKED, + LIGBASE_MAY_NOT_SKIP, + LIGBASE_MAY_SKIP + } ligbase = LIGBASE_NOT_CHECKED; + match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { if (!skippy_iter.next ()) return_trace (false); match_positions[i] = skippy_iter.idx; unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]); unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]); ! if (first_lig_id && first_lig_comp) ! { /* If first component was attached to a previous ligature component, * all subsequent components should be attached to the same ligature ! * component, otherwise we shouldn't ligate them... */ if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) + { + /* ...unless, we are attached to a base ligature and that base + * ligature is ignorable. */ + if (ligbase == LIGBASE_NOT_CHECKED) + { + bool found = false; + const hb_glyph_info_t *out = buffer->out_info; + unsigned int j = buffer->out_len; + while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id) + { + if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0) + { + j--; + found = true; + break; + } + j--; + } + + if (found && skippy_iter.may_skip (c, out[j]) == hb_apply_context_t::matcher_t::SKIP_YES) + ligbase = LIGBASE_MAY_SKIP; + else + ligbase = LIGBASE_MAY_NOT_SKIP; + } + + if (ligbase == LIGBASE_MAY_NOT_SKIP) return_trace (false); ! } ! } ! else ! { /* If first component was NOT attached to a previous ligature component, * all subsequent components should also NOT be attached to any ligature * component, unless they are attached to the first component itself! */ if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id)) return_trace (false);
*** 790,800 **** unsigned int match_length, hb_codepoint_t lig_glyph, bool is_mark_ligature, unsigned int total_component_count) { ! TRACE_APPLY (NULL); hb_buffer_t *buffer = c->buffer; buffer->merge_clusters (buffer->idx, buffer->idx + match_length); --- 802,812 ---- unsigned int match_length, hb_codepoint_t lig_glyph, bool is_mark_ligature, unsigned int total_component_count) { ! TRACE_APPLY (nullptr); hb_buffer_t *buffer = c->buffer; buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
*** 884,925 **** static inline bool match_backtrack (hb_apply_context_t *c, unsigned int count, const USHORT backtrack[], match_func_t match_func, ! const void *match_data) { ! TRACE_APPLY (NULL); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; skippy_iter.reset (c->buffer->backtrack_len (), count); skippy_iter.set_match_func (match_func, match_data, backtrack); for (unsigned int i = 0; i < count; i++) if (!skippy_iter.prev ()) return_trace (false); return_trace (true); } static inline bool match_lookahead (hb_apply_context_t *c, unsigned int count, const USHORT lookahead[], match_func_t match_func, const void *match_data, ! unsigned int offset) { ! TRACE_APPLY (NULL); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; skippy_iter.reset (c->buffer->idx + offset - 1, count); skippy_iter.set_match_func (match_func, match_data, lookahead); for (unsigned int i = 0; i < count; i++) if (!skippy_iter.next ()) return_trace (false); return_trace (true); } --- 896,943 ---- static inline bool match_backtrack (hb_apply_context_t *c, unsigned int count, const USHORT backtrack[], match_func_t match_func, ! const void *match_data, ! unsigned int *match_start) { ! TRACE_APPLY (nullptr); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; skippy_iter.reset (c->buffer->backtrack_len (), count); skippy_iter.set_match_func (match_func, match_data, backtrack); for (unsigned int i = 0; i < count; i++) if (!skippy_iter.prev ()) return_trace (false); + *match_start = skippy_iter.idx; + return_trace (true); } static inline bool match_lookahead (hb_apply_context_t *c, unsigned int count, const USHORT lookahead[], match_func_t match_func, const void *match_data, ! unsigned int offset, ! unsigned int *end_index) { ! TRACE_APPLY (nullptr); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; skippy_iter.reset (c->buffer->idx + offset - 1, count); skippy_iter.set_match_func (match_func, match_data, lookahead); for (unsigned int i = 0; i < count; i++) if (!skippy_iter.next ()) return_trace (false); + *end_index = skippy_iter.idx + 1; + return_trace (true); }
*** 954,967 **** unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */ unsigned int match_length) { ! TRACE_APPLY (NULL); hb_buffer_t *buffer = c->buffer; ! unsigned int end; /* All positions are distance from beginning of *output* buffer. * Adjust. */ { unsigned int bl = buffer->backtrack_len (); --- 972,985 ---- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */ unsigned int match_length) { ! TRACE_APPLY (nullptr); hb_buffer_t *buffer = c->buffer; ! int end; /* All positions are distance from beginning of *output* buffer. * Adjust. */ { unsigned int bl = buffer->backtrack_len ();
*** 994,1007 **** int delta = new_len - orig_len; if (!delta) continue; ! /* Recursed lookup changed buffer len. Adjust. */ ! end = int (end) + delta; ! if (end <= match_positions[idx]) { /* End might end up being smaller than match_positions[idx] if the recursed * lookup ended up removing many items, more than we have had matched. * Just never rewind end back and get out of here. * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */ --- 1012,1047 ---- int delta = new_len - orig_len; if (!delta) continue; ! /* Recursed lookup changed buffer len. Adjust. ! * ! * TODO: ! * ! * Right now, if buffer length increased by n, we assume n new glyphs ! * were added right after the current position, and if buffer length ! * was decreased by n, we assume n match positions after the current ! * one where removed. The former (buffer length increased) case is ! * fine, but the decrease case can be improved in at least two ways, ! * both of which are significant: ! * ! * - If recursed-to lookup is MultipleSubst and buffer length ! * decreased, then it's current match position that was deleted, ! * NOT the one after it. ! * ! * - If buffer length was decreased by n, it does not necessarily ! * mean that n match positions where removed, as there might ! * have been marks and default-ignorables in the sequence. We ! * should instead drop match positions between current-position ! * and current-position + n instead. ! * ! * It should be possible to construct tests for both of these cases. ! */ ! end += delta; ! if (end <= int (match_positions[idx])) { /* End might end up being smaller than match_positions[idx] if the recursed * lookup ended up removing many items, more than we have had matched. * Just never rewind end back and get out of here. * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
*** 1116,1129 **** unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; return match_input (c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data, &match_length, match_positions) ! && apply_lookup (c, inputCount, match_positions, lookupCount, lookupRecord, ! match_length); } struct Rule { inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const --- 1156,1170 ---- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; return match_input (c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data, &match_length, match_positions) ! && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length), ! apply_lookup (c, inputCount, match_positions, lookupCount, lookupRecord, ! match_length)); } struct Rule { inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
*** 1162,1176 **** public: inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); ! return inputCount.sanitize (c) ! && lookupCount.sanitize (c) ! && c->check_range (inputZ, ! inputZ[0].static_size * inputCount ! + lookupRecordX[0].static_size * lookupCount); } protected: USHORT inputCount; /* Total number of glyphs in input * glyph sequence--includes the first --- 1203,1217 ---- public: inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); ! return_trace (inputCount.sanitize (c) && ! lookupCount.sanitize (c) && ! c->check_range (inputZ, ! inputZ[0].static_size * inputCount + ! lookupRecordX[0].static_size * lookupCount)); } protected: USHORT inputCount; /* Total number of glyphs in input * glyph sequence--includes the first
*** 1249,1259 **** const Coverage &cov = (this+coverage); struct ContextClosureLookupContext lookup_context = { {intersects_glyph}, ! NULL }; unsigned int count = ruleSet.len; for (unsigned int i = 0; i < count; i++) if (cov.intersects_coverage (c->glyphs, i)) { --- 1290,1300 ---- const Coverage &cov = (this+coverage); struct ContextClosureLookupContext lookup_context = { {intersects_glyph}, ! nullptr }; unsigned int count = ruleSet.len; for (unsigned int i = 0; i < count; i++) if (cov.intersects_coverage (c->glyphs, i)) {
*** 1267,1277 **** TRACE_COLLECT_GLYPHS (this); (this+coverage).add_coverage (c->input); struct ContextCollectGlyphsLookupContext lookup_context = { {collect_glyph}, ! NULL }; unsigned int count = ruleSet.len; for (unsigned int i = 0; i < count; i++) (this+ruleSet[i]).collect_glyphs (c, lookup_context); --- 1308,1318 ---- TRACE_COLLECT_GLYPHS (this); (this+coverage).add_coverage (c->input); struct ContextCollectGlyphsLookupContext lookup_context = { {collect_glyph}, ! nullptr }; unsigned int count = ruleSet.len; for (unsigned int i = 0; i < count; i++) (this+ruleSet[i]).collect_glyphs (c, lookup_context);
*** 1282,1292 **** TRACE_WOULD_APPLY (this); const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])]; struct ContextApplyLookupContext lookup_context = { {match_glyph}, ! NULL }; return_trace (rule_set.would_apply (c, lookup_context)); } inline const Coverage &get_coverage (void) const --- 1323,1333 ---- TRACE_WOULD_APPLY (this); const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])]; struct ContextApplyLookupContext lookup_context = { {match_glyph}, ! nullptr }; return_trace (rule_set.would_apply (c, lookup_context)); } inline const Coverage &get_coverage (void) const
*** 1302,1312 **** return_trace (false); const RuleSet &rule_set = this+ruleSet[index]; struct ContextApplyLookupContext lookup_context = { {match_glyph}, ! NULL }; return_trace (rule_set.apply (c, lookup_context)); } inline bool sanitize (hb_sanitize_context_t *c) const --- 1343,1353 ---- return_trace (false); const RuleSet &rule_set = this+ruleSet[index]; struct ContextApplyLookupContext lookup_context = { {match_glyph}, ! nullptr }; return_trace (rule_set.apply (c, lookup_context)); } inline bool sanitize (hb_sanitize_context_t *c) const
*** 1637,1663 **** const USHORT lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], ChainContextApplyLookupContext &lookup_context) { ! unsigned int match_length = 0; unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; return match_input (c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data[1], &match_length, match_positions) && match_backtrack (c, backtrackCount, backtrack, ! lookup_context.funcs.match, lookup_context.match_data[0]) && match_lookahead (c, lookaheadCount, lookahead, lookup_context.funcs.match, lookup_context.match_data[2], ! match_length) ! && apply_lookup (c, inputCount, match_positions, lookupCount, lookupRecord, ! match_length); } struct ChainRule { inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const --- 1678,1706 ---- const USHORT lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], ChainContextApplyLookupContext &lookup_context) { ! unsigned int start_index = 0, match_length = 0, end_index = 0; unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; return match_input (c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data[1], &match_length, match_positions) && match_backtrack (c, backtrackCount, backtrack, ! lookup_context.funcs.match, lookup_context.match_data[0], ! &start_index) && match_lookahead (c, lookaheadCount, lookahead, lookup_context.funcs.match, lookup_context.match_data[2], ! match_length, &end_index) ! && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index), ! apply_lookup (c, inputCount, match_positions, lookupCount, lookupRecord, ! match_length)); } struct ChainRule { inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
*** 1805,1815 **** TRACE_CLOSURE (this); const Coverage &cov = (this+coverage); struct ChainContextClosureLookupContext lookup_context = { {intersects_glyph}, ! {NULL, NULL, NULL} }; unsigned int count = ruleSet.len; for (unsigned int i = 0; i < count; i++) if (cov.intersects_coverage (c->glyphs, i)) { --- 1848,1858 ---- TRACE_CLOSURE (this); const Coverage &cov = (this+coverage); struct ChainContextClosureLookupContext lookup_context = { {intersects_glyph}, ! {nullptr, nullptr, nullptr} }; unsigned int count = ruleSet.len; for (unsigned int i = 0; i < count; i++) if (cov.intersects_coverage (c->glyphs, i)) {
*** 1823,1833 **** TRACE_COLLECT_GLYPHS (this); (this+coverage).add_coverage (c->input); struct ChainContextCollectGlyphsLookupContext lookup_context = { {collect_glyph}, ! {NULL, NULL, NULL} }; unsigned int count = ruleSet.len; for (unsigned int i = 0; i < count; i++) (this+ruleSet[i]).collect_glyphs (c, lookup_context); --- 1866,1876 ---- TRACE_COLLECT_GLYPHS (this); (this+coverage).add_coverage (c->input); struct ChainContextCollectGlyphsLookupContext lookup_context = { {collect_glyph}, ! {nullptr, nullptr, nullptr} }; unsigned int count = ruleSet.len; for (unsigned int i = 0; i < count; i++) (this+ruleSet[i]).collect_glyphs (c, lookup_context);
*** 1838,1848 **** TRACE_WOULD_APPLY (this); const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])]; struct ChainContextApplyLookupContext lookup_context = { {match_glyph}, ! {NULL, NULL, NULL} }; return_trace (rule_set.would_apply (c, lookup_context)); } inline const Coverage &get_coverage (void) const --- 1881,1891 ---- TRACE_WOULD_APPLY (this); const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])]; struct ChainContextApplyLookupContext lookup_context = { {match_glyph}, ! {nullptr, nullptr, nullptr} }; return_trace (rule_set.would_apply (c, lookup_context)); } inline const Coverage &get_coverage (void) const
*** 1857,1867 **** if (likely (index == NOT_COVERED)) return_trace (false); const ChainRuleSet &rule_set = this+ruleSet[index]; struct ChainContextApplyLookupContext lookup_context = { {match_glyph}, ! {NULL, NULL, NULL} }; return_trace (rule_set.apply (c, lookup_context)); } inline bool sanitize (hb_sanitize_context_t *c) const --- 1900,1910 ---- if (likely (index == NOT_COVERED)) return_trace (false); const ChainRuleSet &rule_set = this+ruleSet[index]; struct ChainContextApplyLookupContext lookup_context = { {match_glyph}, ! {nullptr, nullptr, nullptr} }; return_trace (rule_set.apply (c, lookup_context)); } inline bool sanitize (hb_sanitize_context_t *c) const
*** 2311,2321 **** scriptList; /* ScriptList table */ OffsetTo<FeatureList> featureList; /* FeatureList table */ OffsetTo<LookupList> lookupList; /* LookupList table */ ! OffsetTo<FeatureVariations, ULONG> featureVars; /* Offset to Feature Variations table--from beginning of table * (may be NULL). Introduced * in version 0x00010001. */ public: --- 2354,2364 ---- scriptList; /* ScriptList table */ OffsetTo<FeatureList> featureList; /* FeatureList table */ OffsetTo<LookupList> lookupList; /* LookupList table */ ! LOffsetTo<FeatureVariations> featureVars; /* Offset to Feature Variations table--from beginning of table * (may be NULL). Introduced * in version 0x00010001. */ public:
< prev index next >