[OTLayout] Add is_inplace() method to GSUB
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index 3b6635b..4844709 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -37,6 +37,12 @@
struct SingleSubstFormat1
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -115,6 +121,12 @@
struct SingleSubstFormat2
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -251,6 +263,13 @@
struct Sequence
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ /* For len==0 we don't do anything, so it's harmless. */
+ return TRACE_RETURN (substitute.len <= 1);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -315,6 +334,18 @@
struct MultipleSubstFormat1
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ /* Some tools generate MultipleSubst with each substitute having length 1!
+ * So, check them. */
+ unsigned int count = sequence.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+sequence[i]).is_inplace (c))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -440,6 +471,12 @@
struct AlternateSubstFormat1
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -760,6 +797,12 @@
struct LigatureSubstFormat1
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ return TRACE_RETURN (false);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -908,6 +951,12 @@
struct ReverseChainSingleSubstFormat1
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -1145,6 +1194,13 @@
return lookup_type_is_reverse (type);
}
+ inline hb_is_inplace_context_t::return_t is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ c->set_recurse_func (dispatch_recurse_func<hb_is_inplace_context_t>);
+ return TRACE_RETURN (dispatch (c));
+ }
+
inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index f46b378..f502ec1 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -44,6 +44,55 @@
"");
+
+#ifndef HB_DEBUG_IS_INPLACE
+#define HB_DEBUG_IS_INPLACE (HB_DEBUG+0)
+#endif
+
+#define TRACE_IS_INPLACE(this) \
+ hb_auto_trace_t<HB_DEBUG_IS_INPLACE, bool> trace \
+ (&c->debug_depth, c->get_name (), this, HB_FUNC, \
+ "");
+
+struct hb_is_inplace_context_t
+{
+ inline const char *get_name (void) { return "IS_INPLACE"; }
+ static const unsigned int max_debug_depth = HB_DEBUG_IS_INPLACE;
+ typedef bool return_t;
+ typedef return_t (*recurse_func_t) (hb_is_inplace_context_t *c, unsigned int lookup_index);
+ template <typename T>
+ inline return_t dispatch (const T &obj) { return obj.is_inplace (this); }
+ static return_t default_return_value (void) { return true; }
+ bool stop_sublookup_iteration (return_t r) const { return !r; }
+
+ return_t recurse (unsigned int lookup_index)
+ {
+ if (unlikely (nesting_level_left == 0 || !recurse_func))
+ return default_return_value ();
+
+ nesting_level_left--;
+ bool ret = recurse_func (this, lookup_index);
+ nesting_level_left++;
+ return ret;
+ }
+
+ hb_face_t *face;
+ recurse_func_t recurse_func;
+ unsigned int nesting_level_left;
+ unsigned int debug_depth;
+
+ hb_is_inplace_context_t (hb_face_t *face_,
+ unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
+ face (face_),
+ 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_CLOSURE
#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
#endif
@@ -1096,6 +1145,17 @@
struct Rule
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
+ unsigned int count = lookupCount;
+ for (unsigned int i = 0; i < count; i++)
+ if (!c->recurse (lookupRecord[i].lookupListIndex))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
{
TRACE_CLOSURE (this);
@@ -1155,6 +1215,16 @@
struct RuleSet
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ unsigned int num_rules = rule.len;
+ for (unsigned int i = 0; i < num_rules; i++)
+ if (!(this+rule[i]).is_inplace (c))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
{
TRACE_CLOSURE (this);
@@ -1211,6 +1281,16 @@
struct ContextFormat1
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ unsigned int count = ruleSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+ruleSet[i]).is_inplace (c))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -1297,6 +1377,16 @@
struct ContextFormat2
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ unsigned int count = ruleSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+ruleSet[i]).is_inplace (c))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -1392,6 +1482,17 @@
struct ContextFormat3
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
+ unsigned int count = lookupCount;
+ for (unsigned int i = 0; i < count; i++)
+ if (!c->recurse (lookupRecord[i].lookupListIndex))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -1633,6 +1734,19 @@
struct ChainRule
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
+ const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
+ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+ unsigned int count = lookup.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!c->recurse (lookup.array[i].lookupListIndex))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
{
TRACE_CLOSURE (this);
@@ -1718,6 +1832,16 @@
struct ChainRuleSet
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ unsigned int num_rules = rule.len;
+ for (unsigned int i = 0; i < num_rules; i++)
+ if (!(this+rule[i]).is_inplace (c))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
{
TRACE_CLOSURE (this);
@@ -1771,6 +1895,16 @@
struct ChainContextFormat1
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ unsigned int count = ruleSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+ruleSet[i]).is_inplace (c))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -1854,6 +1988,16 @@
struct ChainContextFormat2
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ unsigned int count = ruleSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+ruleSet[i]).is_inplace (c))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
@@ -1978,6 +2122,20 @@
struct ChainContextFormat3
{
+ inline bool is_inplace (hb_is_inplace_context_t *c) const
+ {
+ TRACE_IS_INPLACE (this);
+ const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+ const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+ const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+
+ unsigned int count = lookup.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!c->recurse (lookup.array[i].lookupListIndex))
+ return TRACE_RETURN (false);
+ return TRACE_RETURN (true);
+ }
+
inline void closure (hb_closure_context_t *c) const
{
TRACE_CLOSURE (this);
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 4866c41..b016542 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -189,6 +189,23 @@
}
+
+/*
+ * GSUBGPOS
+ */
+
+/* Always returns true for GPOS, but make writing code easier. */
+HB_INTERNAL bool
+hb_ot_layout_lookup_is_inplace (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int lookup_index);
+
+
+
+/*
+ * GSUB
+ */
+
HB_INTERNAL hb_bool_t
hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
unsigned int lookup_index,
@@ -215,6 +232,11 @@
hb_buffer_t *buffer);
+
+/*
+ * GPOS
+ */
+
/* Should be called before all the position_lookup's are done. Resets positions to zero. */
HB_INTERNAL void
hb_ot_layout_position_start (hb_font_t *font,
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 3b7ea47..a9c02aa 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -652,6 +652,33 @@
/*
+ * GSUBGPOS
+ */
+
+bool
+hb_ot_layout_lookup_is_inplace (hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int lookup_index)
+{
+ OT::hb_is_inplace_context_t c (face);
+
+ switch (table_tag)
+ {
+ case HB_OT_TAG_GSUB:
+ {
+ const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
+ return l.is_inplace (&c);
+ }
+
+ default:
+ case HB_OT_TAG_GPOS:
+ {
+ return true;
+ }
+ }
+}
+
+/*
* OT::GSUB
*/
@@ -727,6 +754,7 @@
l.closure (&c);
}
+
/*
* OT::GPOS
*/