Merge commit '9d9e72e94e7914f82ce62a304e7242f79c13edaf'

This commit is contained in:
Behdad Esfahbod 2013-05-23 15:54:52 -04:00
commit fb502a2278
9 changed files with 462 additions and 201 deletions

View File

@ -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);

View File

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

View File

@ -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);

View File

@ -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;
};

View File

@ -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);
}

View File

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

View File

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

View File

@ -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]);
}
}

View File

@ -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;)