Merge commit '9d9e72e94e7914f82ce62a304e7242f79c13edaf'
This commit is contained in:
commit
fb502a2278
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright © 2007,2008,2009,2010 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
* Copyright © 2010,2012,2013 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -1429,7 +1429,18 @@ struct PosLookup : Lookup
|
|||
inline const PosLookupSubTable& get_subtable (unsigned int i) const
|
||||
{ return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
|
||||
|
||||
inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const
|
||||
inline bool is_reverse (void) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inline hb_is_inplace_context_t::return_t is_inplace (hb_is_inplace_context_t *c) const
|
||||
{
|
||||
TRACE_IS_INPLACE (this);
|
||||
return TRACE_RETURN (true);
|
||||
}
|
||||
|
||||
inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
c->set_recurse_func (NULL);
|
||||
|
@ -1461,31 +1472,6 @@ struct PosLookup : Lookup
|
|||
|
||||
static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
|
||||
|
||||
inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (unlikely (!c->buffer->len || !c->lookup_mask))
|
||||
return false;
|
||||
|
||||
c->set_recurse_func (apply_recurse_func);
|
||||
c->set_lookup (*this);
|
||||
|
||||
c->buffer->idx = 0;
|
||||
|
||||
while (c->buffer->idx < c->buffer->len)
|
||||
{
|
||||
if (digest->may_have (c->buffer->cur().codepoint) &&
|
||||
(c->buffer->cur().mask & c->lookup_mask) &&
|
||||
apply_once (c))
|
||||
ret = true;
|
||||
else
|
||||
c->buffer->idx++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename context_t>
|
||||
static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright © 2007,2008,2009,2010 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
* Copyright © 2010,2012,2013 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -37,6 +37,12 @@ namespace OT {
|
|||
|
||||
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 SingleSubstFormat1
|
|||
|
||||
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 SingleSubst
|
|||
|
||||
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 Sequence
|
|||
|
||||
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 @@ typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in
|
|||
|
||||
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 LigatureSet
|
|||
|
||||
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 ExtensionSubst : Extension<ExtensionSubst>
|
|||
|
||||
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 @@ struct SubstLookup : Lookup
|
|||
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);
|
||||
|
@ -1152,7 +1208,7 @@ struct SubstLookup : Lookup
|
|||
return TRACE_RETURN (dispatch (c));
|
||||
}
|
||||
|
||||
inline hb_collect_glyphs_context_t::return_t collect_glyphs_lookup (hb_collect_glyphs_context_t *c) const
|
||||
inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
|
||||
|
@ -1191,54 +1247,6 @@ struct SubstLookup : Lookup
|
|||
}
|
||||
|
||||
static bool apply_recurse_func (hb_apply_context_t *c, unsigned int lookup_index);
|
||||
inline bool apply_string (hb_apply_context_t *c, const hb_set_digest_t *digest) const
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (unlikely (!c->buffer->len || !c->lookup_mask))
|
||||
return false;
|
||||
|
||||
c->set_recurse_func (apply_recurse_func);
|
||||
c->set_lookup (*this);
|
||||
|
||||
if (likely (!is_reverse ()))
|
||||
{
|
||||
/* in/out forward substitution */
|
||||
c->buffer->clear_output ();
|
||||
c->buffer->idx = 0;
|
||||
|
||||
while (c->buffer->idx < c->buffer->len)
|
||||
{
|
||||
if (digest->may_have (c->buffer->cur().codepoint) &&
|
||||
(c->buffer->cur().mask & c->lookup_mask) &&
|
||||
apply_once (c))
|
||||
ret = true;
|
||||
else
|
||||
c->buffer->next_glyph ();
|
||||
}
|
||||
if (ret)
|
||||
c->buffer->swap_buffers ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* in-place backward substitution */
|
||||
c->buffer->remove_output ();
|
||||
c->buffer->idx = c->buffer->len - 1;
|
||||
do
|
||||
{
|
||||
if (digest->may_have (c->buffer->cur().codepoint) &&
|
||||
(c->buffer->cur().mask & c->lookup_mask) &&
|
||||
apply_once (c))
|
||||
ret = true;
|
||||
else
|
||||
c->buffer->idx--;
|
||||
|
||||
}
|
||||
while ((int) c->buffer->idx >= 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
|
||||
unsigned int i)
|
||||
|
|
|
@ -44,6 +44,55 @@ namespace OT {
|
|||
"");
|
||||
|
||||
|
||||
|
||||
#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
|
||||
|
@ -158,7 +207,13 @@ struct hb_collect_glyphs_context_t
|
|||
|
||||
/* 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. */
|
||||
* 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
|
||||
* not how most fonts are built. It's possible to relax that and recurse
|
||||
* with all sets here if it proves to be an issue.
|
||||
*/
|
||||
|
||||
if (output == hb_set_get_empty ())
|
||||
return HB_VOID;
|
||||
|
@ -272,14 +327,12 @@ struct hb_apply_context_t
|
|||
|
||||
hb_apply_context_t (unsigned int table_index_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_,
|
||||
hb_mask_t lookup_mask_,
|
||||
bool auto_zwj_) :
|
||||
hb_buffer_t *buffer_) :
|
||||
table_index (table_index_),
|
||||
font (font_), face (font->face), buffer (buffer_),
|
||||
direction (buffer_->props.direction),
|
||||
lookup_mask (lookup_mask_),
|
||||
auto_zwj (auto_zwj_),
|
||||
lookup_mask (1),
|
||||
auto_zwj (true),
|
||||
recurse_func (NULL),
|
||||
nesting_level_left (MAX_NESTING_LEVEL),
|
||||
lookup_props (0),
|
||||
|
@ -287,6 +340,8 @@ struct hb_apply_context_t
|
|||
has_glyph_classes (gdef.has_glyph_classes ()),
|
||||
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_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
|
||||
inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
|
||||
|
@ -1096,6 +1151,17 @@ static inline bool context_apply_lookup (hb_apply_context_t *c,
|
|||
|
||||
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 +1221,16 @@ struct Rule
|
|||
|
||||
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 +1287,16 @@ struct RuleSet
|
|||
|
||||
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 +1383,16 @@ struct ContextFormat1
|
|||
|
||||
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 +1488,17 @@ struct ContextFormat2
|
|||
|
||||
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 +1740,19 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
|
|||
|
||||
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 +1838,16 @@ struct ChainRule
|
|||
|
||||
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 +1901,16 @@ struct ChainRuleSet
|
|||
|
||||
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 +1994,16 @@ struct ChainContextFormat1
|
|||
|
||||
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 +2128,20 @@ struct ChainContextFormat2
|
|||
|
||||
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);
|
||||
|
|
|
@ -202,12 +202,19 @@ HB_INTERNAL void
|
|||
hb_ot_layout_substitute_start (hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
HB_INTERNAL hb_bool_t
|
||||
hb_ot_layout_substitute_lookup (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int lookup_index,
|
||||
hb_mask_t mask,
|
||||
hb_bool_t auto_zwj);
|
||||
|
||||
struct hb_ot_layout_lookup_accelerator_t;
|
||||
|
||||
namespace OT {
|
||||
struct hb_apply_context_t;
|
||||
struct SubstLookup;
|
||||
}
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
|
||||
const OT::SubstLookup &lookup,
|
||||
const hb_ot_layout_lookup_accelerator_t &accel);
|
||||
|
||||
|
||||
/* Should be called after all the substitute_lookup's are done */
|
||||
HB_INTERNAL void
|
||||
|
@ -220,13 +227,6 @@ HB_INTERNAL void
|
|||
hb_ot_layout_position_start (hb_font_t *font,
|
||||
hb_buffer_t *buffer);
|
||||
|
||||
HB_INTERNAL hb_bool_t
|
||||
hb_ot_layout_position_lookup (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int lookup_index,
|
||||
hb_mask_t mask,
|
||||
hb_bool_t auto_zwj);
|
||||
|
||||
/* Should be called after all the position_lookup's are done */
|
||||
HB_INTERNAL void
|
||||
hb_ot_layout_position_finish (hb_font_t *font,
|
||||
|
@ -244,6 +244,23 @@ namespace OT {
|
|||
struct GPOS;
|
||||
}
|
||||
|
||||
struct hb_ot_layout_lookup_accelerator_t
|
||||
{
|
||||
template <typename TLookup>
|
||||
inline void init (const TLookup &lookup)
|
||||
{
|
||||
digest.init ();
|
||||
lookup.add_coverage (&digest);
|
||||
}
|
||||
|
||||
template <typename TLookup>
|
||||
inline void fini (const TLookup &lookup)
|
||||
{
|
||||
}
|
||||
|
||||
hb_set_digest_t digest;
|
||||
};
|
||||
|
||||
struct hb_ot_layout_t
|
||||
{
|
||||
hb_blob_t *gdef_blob;
|
||||
|
@ -257,8 +274,8 @@ struct hb_ot_layout_t
|
|||
unsigned int gsub_lookup_count;
|
||||
unsigned int gpos_lookup_count;
|
||||
|
||||
hb_set_digest_t *gsub_digests;
|
||||
hb_set_digest_t *gpos_digests;
|
||||
hb_ot_layout_lookup_accelerator_t *gsub_accels;
|
||||
hb_ot_layout_lookup_accelerator_t *gpos_accels;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright © 1998-2004 David Turner and Werner Lemberg
|
||||
* Copyright © 2006 Behdad Esfahbod
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2012 Google, Inc.
|
||||
* Copyright © 2012,2013 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -34,6 +34,8 @@
|
|||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
|
||||
#include "hb-ot-map-private.hh"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -59,26 +61,20 @@ _hb_ot_layout_create (hb_face_t *face)
|
|||
layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
|
||||
layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
|
||||
|
||||
layout->gsub_digests = (hb_set_digest_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_set_digest_t));
|
||||
layout->gpos_digests = (hb_set_digest_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_set_digest_t));
|
||||
layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
|
||||
layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
|
||||
|
||||
if (unlikely ((layout->gsub_lookup_count && !layout->gsub_digests) ||
|
||||
(layout->gpos_lookup_count && !layout->gpos_digests)))
|
||||
if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
|
||||
(layout->gpos_lookup_count && !layout->gpos_accels)))
|
||||
{
|
||||
_hb_ot_layout_destroy (layout);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
|
||||
{
|
||||
layout->gsub_digests[i].init ();
|
||||
layout->gsub->get_lookup (i).add_coverage (&layout->gsub_digests[i]);
|
||||
}
|
||||
layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
|
||||
for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
|
||||
{
|
||||
layout->gpos_digests[i].init ();
|
||||
layout->gpos->get_lookup (i).add_coverage (&layout->gpos_digests[i]);
|
||||
}
|
||||
layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
@ -90,8 +86,13 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
|
|||
hb_blob_destroy (layout->gsub_blob);
|
||||
hb_blob_destroy (layout->gpos_blob);
|
||||
|
||||
free (layout->gsub_digests);
|
||||
free (layout->gpos_digests);
|
||||
for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
|
||||
layout->gsub_accels[i].fini (layout->gsub->get_lookup (i));
|
||||
for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
|
||||
layout->gpos_accels[i].fini (layout->gpos->get_lookup (i));
|
||||
|
||||
free (layout->gsub_accels);
|
||||
free (layout->gpos_accels);
|
||||
|
||||
free (layout);
|
||||
}
|
||||
|
@ -613,13 +614,13 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
|
|||
case HB_OT_TAG_GSUB:
|
||||
{
|
||||
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
|
||||
l.collect_glyphs_lookup (&c);
|
||||
l.collect_glyphs (&c);
|
||||
return;
|
||||
}
|
||||
case HB_OT_TAG_GPOS:
|
||||
{
|
||||
const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
|
||||
l.collect_glyphs_lookup (&c);
|
||||
l.collect_glyphs (&c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -659,7 +660,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
|
|||
|
||||
const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
|
||||
|
||||
return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]);
|
||||
return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -668,22 +669,6 @@ hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
|
|||
OT::GSUB::substitute_start (font, buffer);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_ot_layout_substitute_lookup (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int lookup_index,
|
||||
hb_mask_t mask,
|
||||
hb_bool_t auto_zwj)
|
||||
{
|
||||
if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup_count)) return false;
|
||||
|
||||
OT::hb_apply_context_t c (0, font, buffer, mask, auto_zwj);
|
||||
|
||||
const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_lookup (lookup_index);
|
||||
|
||||
return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_digests[lookup_index]);
|
||||
}
|
||||
|
||||
void
|
||||
hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
|
||||
{
|
||||
|
@ -718,22 +703,6 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
|
|||
OT::GPOS::position_start (font, buffer);
|
||||
}
|
||||
|
||||
hb_bool_t
|
||||
hb_ot_layout_position_lookup (hb_font_t *font,
|
||||
hb_buffer_t *buffer,
|
||||
unsigned int lookup_index,
|
||||
hb_mask_t mask,
|
||||
hb_bool_t auto_zwj)
|
||||
{
|
||||
if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup_count)) return false;
|
||||
|
||||
OT::hb_apply_context_t c (1, font, buffer, mask, auto_zwj);
|
||||
|
||||
const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup (lookup_index);
|
||||
|
||||
return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_digests[lookup_index]);
|
||||
}
|
||||
|
||||
void
|
||||
hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
|
||||
{
|
||||
|
@ -784,3 +753,158 @@ hb_ot_layout_get_size_params (hb_face_t *face,
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parts of different types are implemented here such that they have direct
|
||||
* access to GSUB/GPOS lookups.
|
||||
*/
|
||||
|
||||
|
||||
struct GSUBProxy
|
||||
{
|
||||
static const unsigned int table_index = 0;
|
||||
typedef OT::SubstLookup Lookup;
|
||||
|
||||
GSUBProxy (hb_face_t *face) :
|
||||
table (*hb_ot_layout_from_face (face)->gsub),
|
||||
accels (hb_ot_layout_from_face (face)->gsub_accels) {}
|
||||
|
||||
const OT::GSUB &table;
|
||||
const hb_ot_layout_lookup_accelerator_t *accels;
|
||||
};
|
||||
|
||||
struct GPOSProxy
|
||||
{
|
||||
static const unsigned int table_index = 1;
|
||||
typedef OT::PosLookup Lookup;
|
||||
|
||||
GPOSProxy (hb_face_t *face) :
|
||||
table (*hb_ot_layout_from_face (face)->gpos),
|
||||
accels (hb_ot_layout_from_face (face)->gpos_accels) {}
|
||||
|
||||
const OT::GPOS &table;
|
||||
const hb_ot_layout_lookup_accelerator_t *accels;
|
||||
};
|
||||
|
||||
|
||||
template <typename Lookup>
|
||||
static inline bool apply_once (OT::hb_apply_context_t *c,
|
||||
const Lookup &lookup)
|
||||
{
|
||||
if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
|
||||
return false;
|
||||
return lookup.dispatch (c);
|
||||
}
|
||||
|
||||
template <typename Proxy>
|
||||
static inline bool
|
||||
apply_string (OT::hb_apply_context_t *c,
|
||||
const typename Proxy::Lookup &lookup,
|
||||
const hb_ot_layout_lookup_accelerator_t &accel)
|
||||
{
|
||||
bool ret = false;
|
||||
OT::hb_is_inplace_context_t inplace_c (c->face);
|
||||
bool inplace = lookup.is_inplace (&inplace_c);
|
||||
|
||||
if (unlikely (!c->buffer->len || !c->lookup_mask))
|
||||
return false;
|
||||
|
||||
c->set_lookup (lookup);
|
||||
|
||||
if (likely (!lookup.is_reverse ()))
|
||||
{
|
||||
/* in/out forward substitution/positioning */
|
||||
if (Proxy::table_index == 0)
|
||||
c->buffer->clear_output ();
|
||||
c->buffer->idx = 0;
|
||||
|
||||
while (c->buffer->idx < c->buffer->len)
|
||||
{
|
||||
if (accel.digest.may_have (c->buffer->cur().codepoint) &&
|
||||
(c->buffer->cur().mask & c->lookup_mask) &&
|
||||
apply_once (c, lookup))
|
||||
ret = true;
|
||||
else
|
||||
c->buffer->next_glyph ();
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
if (!inplace)
|
||||
c->buffer->swap_buffers ();
|
||||
else
|
||||
assert (!c->buffer->has_separate_output ());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* in-place backward substitution/positioning */
|
||||
if (Proxy::table_index == 0)
|
||||
c->buffer->remove_output ();
|
||||
c->buffer->idx = c->buffer->len - 1;
|
||||
do
|
||||
{
|
||||
if (accel.digest.may_have (c->buffer->cur().codepoint) &&
|
||||
(c->buffer->cur().mask & c->lookup_mask) &&
|
||||
apply_once (c, lookup))
|
||||
ret = true;
|
||||
else
|
||||
c->buffer->idx--;
|
||||
|
||||
}
|
||||
while ((int) c->buffer->idx >= 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Proxy>
|
||||
inline void hb_ot_map_t::apply (const Proxy &proxy,
|
||||
const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer) const
|
||||
{
|
||||
const unsigned int table_index = proxy.table_index;
|
||||
unsigned int i = 0;
|
||||
OT::hb_apply_context_t c (table_index, font, buffer);
|
||||
c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
|
||||
|
||||
for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
|
||||
const stage_map_t *stage = &stages[table_index][stage_index];
|
||||
for (; i < stage->last_lookup; i++)
|
||||
{
|
||||
unsigned int lookup_index = lookups[table_index][i].index;
|
||||
c.set_lookup_mask (lookups[table_index][i].mask);
|
||||
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
|
||||
apply_string<Proxy> (&c,
|
||||
proxy.table.get_lookup (lookup_index),
|
||||
proxy.accels[lookup_index]);
|
||||
}
|
||||
|
||||
if (stage->pause_func)
|
||||
{
|
||||
buffer->clear_output ();
|
||||
stage->pause_func (plan, font, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
|
||||
{
|
||||
GSUBProxy proxy (font->face);
|
||||
apply (proxy, plan, font, buffer);
|
||||
}
|
||||
|
||||
void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
|
||||
{
|
||||
GPOSProxy proxy (font->face);
|
||||
apply (proxy, plan, font, buffer);
|
||||
}
|
||||
|
||||
HB_INTERNAL void
|
||||
hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
|
||||
const OT::SubstLookup &lookup,
|
||||
const hb_ot_layout_lookup_accelerator_t &accel)
|
||||
{
|
||||
apply_string<GSUBProxy> (c, lookup, accel);
|
||||
}
|
||||
|
|
|
@ -118,10 +118,9 @@ struct hb_ot_map_t
|
|||
}
|
||||
|
||||
HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
|
||||
HB_INTERNAL inline void apply (unsigned int table_index,
|
||||
const struct hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer) const;
|
||||
template <typename Proxy>
|
||||
HB_INTERNAL inline void apply (const Proxy &proxy,
|
||||
const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
|
||||
HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
|
||||
HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
|
||||
|
||||
|
|
|
@ -102,49 +102,6 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
|
|||
info->stage[1] = current_stage[1];
|
||||
}
|
||||
|
||||
inline void hb_ot_map_t::apply (unsigned int table_index,
|
||||
const hb_ot_shape_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
hb_buffer_t *buffer) const
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
|
||||
const stage_map_t *stage = &stages[table_index][stage_index];
|
||||
for (; i < stage->last_lookup; i++)
|
||||
switch (table_index)
|
||||
{
|
||||
case 0:
|
||||
hb_ot_layout_substitute_lookup (font, buffer, lookups[table_index][i].index,
|
||||
lookups[table_index][i].mask,
|
||||
lookups[table_index][i].auto_zwj);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
hb_ot_layout_position_lookup (font, buffer, lookups[table_index][i].index,
|
||||
lookups[table_index][i].mask,
|
||||
lookups[table_index][i].auto_zwj);
|
||||
break;
|
||||
}
|
||||
|
||||
if (stage->pause_func)
|
||||
{
|
||||
buffer->clear_output ();
|
||||
stage->pause_func (plan, font, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
|
||||
{
|
||||
apply (0, plan, font, buffer);
|
||||
}
|
||||
|
||||
void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
|
||||
{
|
||||
apply (1, plan, font, buffer);
|
||||
}
|
||||
|
||||
|
||||
void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
|
||||
{
|
||||
|
|
|
@ -199,7 +199,7 @@ struct arabic_fallback_plan_t
|
|||
|
||||
hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES];
|
||||
OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES];
|
||||
hb_set_digest_t digest_array[ARABIC_NUM_FALLBACK_FEATURES];
|
||||
hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_NUM_FALLBACK_FEATURES];
|
||||
};
|
||||
|
||||
static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
|
||||
|
@ -214,12 +214,11 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
|
|||
|
||||
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
|
||||
{
|
||||
fallback_plan->digest_array[i].init ();
|
||||
fallback_plan->mask_array[i] = plan->map.get_1_mask (arabic_fallback_features[i]);
|
||||
if (fallback_plan->mask_array[i]) {
|
||||
fallback_plan->lookup_array[i] = arabic_fallback_synthesize_lookup (plan, font, i);
|
||||
if (fallback_plan->lookup_array[i])
|
||||
fallback_plan->lookup_array[i]->add_coverage (&fallback_plan->digest_array[i]);
|
||||
fallback_plan->accel_array[i].init (*fallback_plan->lookup_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +233,10 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
|
|||
|
||||
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
|
||||
if (fallback_plan->lookup_array[i])
|
||||
{
|
||||
fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]);
|
||||
free (fallback_plan->lookup_array[i]);
|
||||
}
|
||||
|
||||
free (fallback_plan);
|
||||
}
|
||||
|
@ -244,10 +246,13 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
|
|||
hb_font_t *font,
|
||||
hb_buffer_t *buffer)
|
||||
{
|
||||
OT::hb_apply_context_t c (0, font, buffer);
|
||||
for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++)
|
||||
if (fallback_plan->lookup_array[i]) {
|
||||
OT::hb_apply_context_t c (0, font, buffer, fallback_plan->mask_array[i], true/*auto_zwj*/);
|
||||
fallback_plan->lookup_array[i]->apply_string (&c, &fallback_plan->digest_array[i]);
|
||||
c.set_lookup_mask (fallback_plan->mask_array[i]);
|
||||
hb_ot_layout_substitute_lookup (&c,
|
||||
*fallback_plan->lookup_array[i],
|
||||
fallback_plan->accel_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -420,7 +420,8 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
|
|||
hb_mask_t kern_mask = plan->map.get_1_mask (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
|
||||
HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
|
||||
|
||||
OT::hb_apply_context_t c (1, font, buffer, kern_mask, true/*auto_zwj*/);
|
||||
OT::hb_apply_context_t c (1, font, buffer);
|
||||
c.set_lookup_mask (kern_mask);
|
||||
c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
|
||||
|
||||
for (buffer->idx = 0; buffer->idx < count;)
|
||||
|
|
Loading…
Reference in New Issue