225 lines
7.5 KiB
C++
225 lines
7.5 KiB
C++
#ifndef OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
|
|
#define OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
|
|
|
|
#include "Common.hh"
|
|
#include "SubstLookupSubTable.hh"
|
|
|
|
namespace OT {
|
|
namespace Layout {
|
|
namespace GSUB {
|
|
|
|
struct SubstLookup : Lookup
|
|
{
|
|
typedef SubstLookupSubTable SubTable;
|
|
|
|
bool sanitize (hb_sanitize_context_t *c) const
|
|
{ return Lookup::sanitize<SubTable> (c); }
|
|
|
|
const SubTable& get_subtable (unsigned int i) const
|
|
{ return Lookup::get_subtable<SubTable> (i); }
|
|
|
|
static inline bool lookup_type_is_reverse (unsigned int lookup_type)
|
|
{ return lookup_type == SubTable::ReverseChainSingle; }
|
|
|
|
bool is_reverse () const
|
|
{
|
|
unsigned int type = get_type ();
|
|
if (unlikely (type == SubTable::Extension))
|
|
return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
|
|
return lookup_type_is_reverse (type);
|
|
}
|
|
|
|
bool may_have_non_1to1 () const
|
|
{
|
|
hb_have_non_1to1_context_t c;
|
|
return dispatch (&c);
|
|
}
|
|
|
|
bool apply (hb_ot_apply_context_t *c) const
|
|
{
|
|
TRACE_APPLY (this);
|
|
return_trace (dispatch (c));
|
|
}
|
|
|
|
bool intersects (const hb_set_t *glyphs) const
|
|
{
|
|
hb_intersects_context_t c (glyphs);
|
|
return dispatch (&c);
|
|
}
|
|
|
|
hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
|
|
{
|
|
if (!c->should_visit_lookup (this_index))
|
|
return hb_closure_context_t::default_return_value ();
|
|
|
|
c->set_recurse_func (dispatch_closure_recurse_func);
|
|
|
|
hb_closure_context_t::return_t ret = dispatch (c);
|
|
|
|
c->flush ();
|
|
|
|
return ret;
|
|
}
|
|
|
|
hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
|
|
{
|
|
if (c->is_lookup_visited (this_index))
|
|
return hb_closure_lookups_context_t::default_return_value ();
|
|
|
|
c->set_lookup_visited (this_index);
|
|
if (!intersects (c->glyphs))
|
|
{
|
|
c->set_lookup_inactive (this_index);
|
|
return hb_closure_lookups_context_t::default_return_value ();
|
|
}
|
|
|
|
c->set_recurse_func (dispatch_closure_lookups_recurse_func);
|
|
|
|
hb_closure_lookups_context_t::return_t ret = dispatch (c);
|
|
return ret;
|
|
}
|
|
|
|
hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
|
|
{
|
|
c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
|
|
return dispatch (c);
|
|
}
|
|
|
|
template <typename set_t>
|
|
void collect_coverage (set_t *glyphs) const
|
|
{
|
|
hb_collect_coverage_context_t<set_t> c (glyphs);
|
|
dispatch (&c);
|
|
}
|
|
|
|
bool would_apply (hb_would_apply_context_t *c,
|
|
const hb_ot_layout_lookup_accelerator_t *accel) const
|
|
{
|
|
if (unlikely (!c->len)) return false;
|
|
if (!accel->may_have (c->glyphs[0])) return false;
|
|
return dispatch (c);
|
|
}
|
|
|
|
static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
|
|
|
|
bool serialize_single (hb_serialize_context_t *c,
|
|
uint32_t lookup_props,
|
|
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
|
hb_array_t<const HBGlyphID16> substitutes)
|
|
{
|
|
TRACE_SERIALIZE (this);
|
|
if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
|
|
if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
|
|
{
|
|
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
|
|
return_trace (true);
|
|
}
|
|
c->pop_discard ();
|
|
return_trace (false);
|
|
}
|
|
|
|
bool serialize_multiple (hb_serialize_context_t *c,
|
|
uint32_t lookup_props,
|
|
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
|
hb_array_t<const unsigned int> substitute_len_list,
|
|
hb_array_t<const HBGlyphID16> substitute_glyphs_list)
|
|
{
|
|
TRACE_SERIALIZE (this);
|
|
if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
|
|
if (c->push<SubTable> ()->u.multiple.
|
|
serialize (c,
|
|
glyphs,
|
|
substitute_len_list,
|
|
substitute_glyphs_list))
|
|
{
|
|
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
|
|
return_trace (true);
|
|
}
|
|
c->pop_discard ();
|
|
return_trace (false);
|
|
}
|
|
|
|
bool serialize_alternate (hb_serialize_context_t *c,
|
|
uint32_t lookup_props,
|
|
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
|
hb_array_t<const unsigned int> alternate_len_list,
|
|
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
|
{
|
|
TRACE_SERIALIZE (this);
|
|
if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
|
|
|
|
if (c->push<SubTable> ()->u.alternate.
|
|
serialize (c,
|
|
glyphs,
|
|
alternate_len_list,
|
|
alternate_glyphs_list))
|
|
{
|
|
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
|
|
return_trace (true);
|
|
}
|
|
c->pop_discard ();
|
|
return_trace (false);
|
|
}
|
|
|
|
bool serialize_ligature (hb_serialize_context_t *c,
|
|
uint32_t lookup_props,
|
|
hb_sorted_array_t<const HBGlyphID16> first_glyphs,
|
|
hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
|
|
hb_array_t<const HBGlyphID16> ligatures_list,
|
|
hb_array_t<const unsigned int> component_count_list,
|
|
hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
|
|
{
|
|
TRACE_SERIALIZE (this);
|
|
if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
|
|
if (c->push<SubTable> ()->u.ligature.
|
|
serialize (c,
|
|
first_glyphs,
|
|
ligature_per_first_glyph_count_list,
|
|
ligatures_list,
|
|
component_count_list,
|
|
component_list))
|
|
{
|
|
c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
|
|
return_trace (true);
|
|
}
|
|
c->pop_discard ();
|
|
return_trace (false);
|
|
}
|
|
|
|
template <typename context_t>
|
|
static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
|
|
|
|
static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
|
|
|
|
static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
|
|
{
|
|
if (!c->should_visit_lookup (lookup_index))
|
|
return hb_empty_t ();
|
|
|
|
hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
|
|
|
|
/* While in theory we should flush here, it will cause timeouts because a recursive
|
|
* lookup can keep growing the glyph set. Skip, and outer loop will retry up to
|
|
* HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
|
|
//c->flush ();
|
|
|
|
return ret;
|
|
}
|
|
|
|
HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
|
|
|
|
template <typename context_t, typename ...Ts>
|
|
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
|
{ return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
|
|
|
|
bool subset (hb_subset_context_t *c) const
|
|
{ return Lookup::subset<SubTable> (c); }
|
|
};
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* OT_LAYOUT_GSUB_SUBSTLOOKUP_HH */
|