From a9910e258fe2d8f782ccb3594b79f9d150e60e08 Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Wed, 23 Mar 2022 16:09:41 -0700 Subject: [PATCH] [reorg] Move SubstLookup and GSUB into the new layout. --- src/Makefile.sources | 6 + src/OT/Layout/GSUB/ChainContextSubst.hh | 18 ++ src/OT/Layout/GSUB/ContextSubst.hh | 18 ++ src/OT/Layout/GSUB/ExtensionSubst.hh | 22 ++ src/OT/Layout/GSUB/GSUB.hh | 59 ++++ src/OT/Layout/GSUB/SubstLookup.hh | 224 +++++++++++++++ src/OT/Layout/GSUB/SubstLookupSubTable.hh | 77 +++++ src/hb-ot-layout-gsub-table.hh | 332 +--------------------- src/hb-ot-layout.hh | 8 +- src/meson.build | 6 + 10 files changed, 440 insertions(+), 330 deletions(-) create mode 100644 src/OT/Layout/GSUB/ChainContextSubst.hh create mode 100644 src/OT/Layout/GSUB/ContextSubst.hh create mode 100644 src/OT/Layout/GSUB/ExtensionSubst.hh create mode 100644 src/OT/Layout/GSUB/GSUB.hh create mode 100644 src/OT/Layout/GSUB/SubstLookup.hh create mode 100644 src/OT/Layout/GSUB/SubstLookupSubTable.hh diff --git a/src/Makefile.sources b/src/Makefile.sources index 95285643f..20c5188e2 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -104,6 +104,12 @@ HB_BASE_sources = \ OT/Layout/GSUB/Ligature.hh \ OT/Layout/GSUB/ReverseChainSingleSubst.hh \ OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh \ + OT/Layout/GSUB/ContextSubst.hh \ + OT/Layout/GSUB/ChainContextSubst.hh \ + OT/Layout/GSUB/ExtensionSubst.hh \ + OT/Layout/GSUB/SubstLookupSubTable.hh \ + OT/Layout/GSUB/SubstLookup.hh \ + OT/Layout/GSUB/GSUB.hh \ hb-ot-layout-gsubgpos.hh \ hb-ot-layout-jstf-table.hh \ hb-ot-layout.cc \ diff --git a/src/OT/Layout/GSUB/ChainContextSubst.hh b/src/OT/Layout/GSUB/ChainContextSubst.hh new file mode 100644 index 000000000..50fdda933 --- /dev/null +++ b/src/OT/Layout/GSUB/ChainContextSubst.hh @@ -0,0 +1,18 @@ +#ifndef OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH +#define OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH + +// TODO(garretrieger): move to new layout. +#include "hb-ot-layout-gsubgpos.hh" +#include "Common.hh" + +namespace OT { +namespace Layout { +namespace GSUB { + +struct ChainContextSubst : ChainContext {}; + +} +} +} + +#endif /* OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH */ diff --git a/src/OT/Layout/GSUB/ContextSubst.hh b/src/OT/Layout/GSUB/ContextSubst.hh new file mode 100644 index 000000000..948c89b31 --- /dev/null +++ b/src/OT/Layout/GSUB/ContextSubst.hh @@ -0,0 +1,18 @@ +#ifndef OT_LAYOUT_GSUB_CONTEXTSUBST_HH +#define OT_LAYOUT_GSUB_CONTEXTSUBST_HH + +// TODO(garretrieger): move to new layout. +#include "hb-ot-layout-gsubgpos.hh" +#include "Common.hh" + +namespace OT { +namespace Layout { +namespace GSUB { + +struct ContextSubst : Context {}; + +} +} +} + +#endif /* OT_LAYOUT_GSUB_CONTEXTSUBST_HH */ diff --git a/src/OT/Layout/GSUB/ExtensionSubst.hh b/src/OT/Layout/GSUB/ExtensionSubst.hh new file mode 100644 index 000000000..410c98497 --- /dev/null +++ b/src/OT/Layout/GSUB/ExtensionSubst.hh @@ -0,0 +1,22 @@ +#ifndef OT_LAYOUT_GSUB_EXTENSIONSUBST_HH +#define OT_LAYOUT_GSUB_EXTENSIONSUBST_HH + +// TODO(garretrieger): move to new layout. +#include "hb-ot-layout-gsubgpos.hh" +#include "Common.hh" + +namespace OT { +namespace Layout { +namespace GSUB { + +struct ExtensionSubst : Extension +{ + typedef struct SubstLookupSubTable SubTable; + bool is_reverse () const; +}; + +} +} +} + +#endif /* OT_LAYOUT_GSUB_EXTENSIONSUBST_HH */ diff --git a/src/OT/Layout/GSUB/GSUB.hh b/src/OT/Layout/GSUB/GSUB.hh new file mode 100644 index 000000000..cc5c87e5d --- /dev/null +++ b/src/OT/Layout/GSUB/GSUB.hh @@ -0,0 +1,59 @@ +#ifndef OT_LAYOUT_GSUB_GSUB_HH +#define OT_LAYOUT_GSUB_GSUB_HH + +// TODO(garretrieger): move to new layout. +#include "hb-ot-layout-gsubgpos.hh" +#include "Common.hh" +#include "SubstLookup.hh" + +using OT::Layout::GSUB::SubstLookup; + +namespace OT { +// TODO(garretrieger): move this ot layout::GSUB namespace +//namespace Layout { +//namespace GSUB { + +/* + * GSUB -- Glyph Substitution + * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub + */ + +struct GSUB : GSUBGPOS +{ + static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB; + + const SubstLookup& get_lookup (unsigned int i) const + { return static_cast (GSUBGPOS::get_lookup (i)); } + + bool subset (hb_subset_context_t *c) const + { + hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features); + return GSUBGPOS::subset (&l); + } + + bool sanitize (hb_sanitize_context_t *c) const + { return GSUBGPOS::sanitize (c); } + + HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, + hb_face_t *face) const; + + void closure_lookups (hb_face_t *face, + const hb_set_t *glyphs, + hb_set_t *lookup_indexes /* IN/OUT */) const + { GSUBGPOS::closure_lookups (face, glyphs, lookup_indexes); } + + typedef GSUBGPOS::accelerator_t accelerator_t; +}; + + +struct GSUB_accelerator_t : GSUB::accelerator_t { + GSUB_accelerator_t (hb_face_t *face) : GSUB::accelerator_t (face) {} +}; + + + +//} +//} +} + +#endif /* OT_LAYOUT_GSUB_GSUB_HH */ diff --git a/src/OT/Layout/GSUB/SubstLookup.hh b/src/OT/Layout/GSUB/SubstLookup.hh new file mode 100644 index 000000000..3419b5a73 --- /dev/null +++ b/src/OT/Layout/GSUB/SubstLookup.hh @@ -0,0 +1,224 @@ +#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 (c); } + + const SubTable& get_subtable (unsigned int i) const + { return Lookup::get_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 (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); + return dispatch (c); + } + + template + void collect_coverage (set_t *glyphs) const + { + hb_collect_coverage_context_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 glyphs, + hb_array_t substitutes) + { + TRACE_SERIALIZE (this); + if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false); + if (c->push ()->u.single.serialize (c, hb_zip (glyphs, substitutes))) + { + c->add_link (get_subtables ()[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 glyphs, + hb_array_t substitute_len_list, + hb_array_t substitute_glyphs_list) + { + TRACE_SERIALIZE (this); + if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false); + if (c->push ()->u.multiple. + serialize (c, + glyphs, + substitute_len_list, + substitute_glyphs_list)) + { + c->add_link (get_subtables ()[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 glyphs, + hb_array_t alternate_len_list, + hb_array_t alternate_glyphs_list) + { + TRACE_SERIALIZE (this); + if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false); + + if (c->push ()->u.alternate. + serialize (c, + glyphs, + alternate_len_list, + alternate_glyphs_list)) + { + c->add_link (get_subtables ()[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 first_glyphs, + hb_array_t ligature_per_first_glyph_count_list, + hb_array_t ligatures_list, + hb_array_t component_count_list, + hb_array_t 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 ()->u.ligature. + serialize (c, + first_glyphs, + ligature_per_first_glyph_count_list, + ligatures_list, + component_count_list, + component_list)) + { + c->add_link (get_subtables ()[0], c->pop_pack ()); + return_trace (true); + } + c->pop_discard (); + return_trace (false); + } + + template + 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::return_t dispatch (context_t *c, Ts&&... ds) const + { return Lookup::dispatch (c, std::forward (ds)...); } + + bool subset (hb_subset_context_t *c) const + { return Lookup::subset (c); } +}; + + +} +} +} + +#endif /* OT_LAYOUT_GSUB_SUBSTLOOKUP_HH */ diff --git a/src/OT/Layout/GSUB/SubstLookupSubTable.hh b/src/OT/Layout/GSUB/SubstLookupSubTable.hh new file mode 100644 index 000000000..53e963e2a --- /dev/null +++ b/src/OT/Layout/GSUB/SubstLookupSubTable.hh @@ -0,0 +1,77 @@ +#ifndef OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH +#define OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH + +#include "Common.hh" +#include "SingleSubst.hh" +#include "MultipleSubst.hh" +#include "AlternateSubst.hh" +#include "LigatureSubst.hh" +#include "ContextSubst.hh" +#include "ChainContextSubst.hh" +#include "ExtensionSubst.hh" +#include "ReverseChainSingleSubst.hh" + +namespace OT { +namespace Layout { +namespace GSUB { + +struct SubstLookupSubTable +{ + friend struct ::OT::Lookup; + friend struct SubstLookup; + + protected: + union { + SingleSubst single; + MultipleSubst multiple; + AlternateSubst alternate; + LigatureSubst ligature; + ContextSubst context; + ChainContextSubst chainContext; + ExtensionSubst extension; + ReverseChainSingleSubst reverseChainContextSingle; + } u; + public: + DEFINE_SIZE_MIN (0); + + enum Type { + Single = 1, + Multiple = 2, + Alternate = 3, + Ligature = 4, + Context = 5, + ChainContext = 6, + Extension = 7, + ReverseChainSingle = 8 + }; + + template + typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const + { + TRACE_DISPATCH (this, lookup_type); + switch (lookup_type) { + case Single: return_trace (u.single.dispatch (c, std::forward (ds)...)); + case Multiple: return_trace (u.multiple.dispatch (c, std::forward (ds)...)); + case Alternate: return_trace (u.alternate.dispatch (c, std::forward (ds)...)); + case Ligature: return_trace (u.ligature.dispatch (c, std::forward (ds)...)); + case Context: return_trace (u.context.dispatch (c, std::forward (ds)...)); + case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward (ds)...)); + case Extension: return_trace (u.extension.dispatch (c, std::forward (ds)...)); + case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward (ds)...)); + default: return_trace (c->default_return_value ()); + } + } + + bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const + { + hb_intersects_context_t c (glyphs); + return dispatch (&c, lookup_type); + } +}; + + +} +} +} + +#endif /* HB_OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH */ diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 3397ce194..bef381430 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -29,338 +29,14 @@ #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH #define HB_OT_LAYOUT_GSUB_TABLE_HH -#include "hb-ot-layout-gsubgpos.hh" -#include "OT/Layout/GSUB/Common.hh" -#include "OT/Layout/GSUB/SingleSubst.hh" -#include "OT/Layout/GSUB/MultipleSubst.hh" -#include "OT/Layout/GSUB/AlternateSubst.hh" -#include "OT/Layout/GSUB/LigatureSubst.hh" -#include "OT/Layout/GSUB/ReverseChainSingleSubst.hh" +#include "OT/Layout/GSUB/GSUB.hh" namespace OT { -using Layout::GSUB::hb_codepoint_pair_t; -using Layout::GSUB::SingleSubst; -using Layout::GSUB::MultipleSubst; -using Layout::GSUB::AlternateSubst; -using Layout::GSUB::LigatureSubst; -using Layout::GSUB::ReverseChainSingleSubst; - -struct ContextSubst : Context {}; - -struct ChainContextSubst : ChainContext {}; - -struct ExtensionSubst : Extension -{ - typedef struct SubstLookupSubTable SubTable; - bool is_reverse () const; -}; - -/* - * SubstLookup - */ - -struct SubstLookupSubTable -{ - friend struct Lookup; - friend struct SubstLookup; - - enum Type { - Single = 1, - Multiple = 2, - Alternate = 3, - Ligature = 4, - Context = 5, - ChainContext = 6, - Extension = 7, - ReverseChainSingle = 8 - }; - - template - typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const - { - TRACE_DISPATCH (this, lookup_type); - switch (lookup_type) { - case Single: return_trace (u.single.dispatch (c, std::forward (ds)...)); - case Multiple: return_trace (u.multiple.dispatch (c, std::forward (ds)...)); - case Alternate: return_trace (u.alternate.dispatch (c, std::forward (ds)...)); - case Ligature: return_trace (u.ligature.dispatch (c, std::forward (ds)...)); - case Context: return_trace (u.context.dispatch (c, std::forward (ds)...)); - case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward (ds)...)); - case Extension: return_trace (u.extension.dispatch (c, std::forward (ds)...)); - case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward (ds)...)); - default: return_trace (c->default_return_value ()); - } - } - - bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const - { - hb_intersects_context_t c (glyphs); - return dispatch (&c, lookup_type); - } - - protected: - union { - SingleSubst single; - MultipleSubst multiple; - AlternateSubst alternate; - LigatureSubst ligature; - ContextSubst context; - ChainContextSubst chainContext; - ExtensionSubst extension; - ReverseChainSingleSubst reverseChainContextSingle; - } u; - public: - DEFINE_SIZE_MIN (0); -}; - - -struct SubstLookup : Lookup -{ - typedef SubstLookupSubTable SubTable; - - const SubTable& get_subtable (unsigned int i) const - { return Lookup::get_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 (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); - return dispatch (c); - } - - template - void collect_coverage (set_t *glyphs) const - { - hb_collect_coverage_context_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 glyphs, - hb_array_t substitutes) - { - TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false); - if (c->push ()->u.single.serialize (c, hb_zip (glyphs, substitutes))) - { - c->add_link (get_subtables ()[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 glyphs, - hb_array_t substitute_len_list, - hb_array_t substitute_glyphs_list) - { - TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false); - if (c->push ()->u.multiple. - serialize (c, - glyphs, - substitute_len_list, - substitute_glyphs_list)) - { - c->add_link (get_subtables ()[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 glyphs, - hb_array_t alternate_len_list, - hb_array_t alternate_glyphs_list) - { - TRACE_SERIALIZE (this); - if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false); - - if (c->push ()->u.alternate. - serialize (c, - glyphs, - alternate_len_list, - alternate_glyphs_list)) - { - c->add_link (get_subtables ()[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 first_glyphs, - hb_array_t ligature_per_first_glyph_count_list, - hb_array_t ligatures_list, - hb_array_t component_count_list, - hb_array_t 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 ()->u.ligature. - serialize (c, - first_glyphs, - ligature_per_first_glyph_count_list, - ligatures_list, - component_count_list, - component_list)) - { - c->add_link (get_subtables ()[0], c->pop_pack ()); - return_trace (true); - } - c->pop_discard (); - return_trace (false); - } - - template - 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::return_t dispatch (context_t *c, Ts&&... ds) const - { return Lookup::dispatch (c, std::forward (ds)...); } - - bool subset (hb_subset_context_t *c) const - { return Lookup::subset (c); } - - bool sanitize (hb_sanitize_context_t *c) const - { return Lookup::sanitize (c); } -}; - -/* - * GSUB -- Glyph Substitution - * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub - */ - -struct GSUB : GSUBGPOS -{ - static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB; - - const SubstLookup& get_lookup (unsigned int i) const - { return static_cast (GSUBGPOS::get_lookup (i)); } - - bool subset (hb_subset_context_t *c) const - { - hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features); - return GSUBGPOS::subset (&l); - } - - bool sanitize (hb_sanitize_context_t *c) const - { return GSUBGPOS::sanitize (c); } - - HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, - hb_face_t *face) const; - - void closure_lookups (hb_face_t *face, - const hb_set_t *glyphs, - hb_set_t *lookup_indexes /* IN/OUT */) const - { GSUBGPOS::closure_lookups (face, glyphs, lookup_indexes); } - - typedef GSUBGPOS::accelerator_t accelerator_t; -}; - - -struct GSUB_accelerator_t : GSUB::accelerator_t { - GSUB_accelerator_t (hb_face_t *face) : GSUB::accelerator_t (face) {} -}; - +using Layout::GSUB::SubstLookup; +using Layout::GSUB::ExtensionSubst; +// TODO(garretrieger): Move into the new layout directory. /* Out-of-class implementation for methods recursing */ #ifndef HB_NO_OT_LAYOUT diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh index 35e2bd685..ac15458d8 100644 --- a/src/hb-ot-layout.hh +++ b/src/hb-ot-layout.hh @@ -108,13 +108,17 @@ hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer, namespace OT { struct hb_ot_apply_context_t; - struct SubstLookup; struct hb_ot_layout_lookup_accelerator_t; +namespace Layout { +namespace GSUB { + struct SubstLookup; +} +} } HB_INTERNAL void hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, - const OT::SubstLookup &lookup, + const OT::Layout::GSUB::SubstLookup &lookup, const OT::hb_ot_layout_lookup_accelerator_t &accel); diff --git a/src/meson.build b/src/meson.build index abd80f355..affb40fdf 100644 --- a/src/meson.build +++ b/src/meson.build @@ -108,6 +108,12 @@ hb_base_sources = files( 'OT/Layout/GSUB/Ligature.hh', 'OT/Layout/GSUB/ReverseChainSingleSubst.hh', 'OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh', + 'OT/Layout/GSUB/ContextSubst.hh', + 'OT/Layout/GSUB/ChainContextSubst.hh', + 'OT/Layout/GSUB/ExtensionSubst.hh', + 'OT/Layout/GSUB/SubstLookupSubTable.hh', + 'OT/Layout/GSUB/SubstLookup.hh', + 'OT/Layout/GSUB/GSUB.hh', 'hb-ot-layout-gsubgpos.hh', 'hb-ot-layout-jstf-table.hh', 'hb-ot-layout.cc',