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