提交 832a6f99 编写于 作者: B Behdad Esfahbod

[indic] Don't reorder reph/pref if ligature was expanded

Normally if you want to, say, conditionally prevent a 'pref', you
would use blocking contextual matching.  Some designers instead
form the 'pref' form, then undo it in context.  To detect that
we now also remember glyphs that went through MultipleSubst.

In the only place that this is used, Uniscribe seems to only care
about the "last" transformation between Ligature and Multiple
substitions.  Ie. if you ligate, expand, and ligate again, it
moves the pref, but if you ligate and expand it doesn't.  That's
why we clear the MULTIPLIED bit when setting LIGATED.

Micro-test added.  Test: U+0D2F,0D4D,0D30 with font from:

[1]
https://code.google.com/a/google.com/p/noto-alpha/issues/detail?id=186#c29
上级 b5be2317
......@@ -295,7 +295,7 @@ struct Sequence
for (unsigned int i = 0; i < count; i++) {
_hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
c->output_glyph (substitute.array[i], klass);
c->output_glyph_for_component (substitute.array[i], klass);
}
c->buffer->skip_glyph ();
......
......@@ -567,13 +567,25 @@ struct hb_apply_context_t
inline void _set_glyph_props (hb_codepoint_t glyph_index,
unsigned int class_guess = 0,
bool ligature = false) const
bool ligature = false,
bool component = false) const
{
unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
if (ligature)
{
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
/* In the only place that the MULTIPLIED bit is used, Uniscribe
* seems to only care about the "last" transformation between
* Ligature and Multiple substitions. Ie. if you ligate, expand,
* and ligate again, it forgives the multiplication and acts as
* if only ligation happened. As such, clear MULTIPLIED bit.
*/
add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
}
if (component)
add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
if (likely (has_glyph_classes))
_hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
else if (class_guess)
......@@ -596,10 +608,10 @@ struct hb_apply_context_t
_set_glyph_props (glyph_index, class_guess, true);
buffer->replace_glyph (glyph_index);
}
inline void output_glyph (hb_codepoint_t glyph_index,
unsigned int class_guess) const
inline void output_glyph_for_component (hb_codepoint_t glyph_index,
unsigned int class_guess) const
{
_set_glyph_props (glyph_index, class_guess);
_set_glyph_props (glyph_index, class_guess, false, true);
buffer->output_glyph (glyph_index);
}
};
......
......@@ -50,9 +50,11 @@ typedef enum
/* The following are used internally; not derived from GDEF. */
HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u,
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u,
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED = 0x40u,
HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED
HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
} hb_ot_layout_glyph_class_mask_t;
......@@ -381,6 +383,18 @@ _hb_glyph_info_ligated (const hb_glyph_info_t *info)
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
}
static inline bool
_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
{
return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
}
static inline bool
_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
{
return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
}
/* Allocation / deallocation. */
static inline void
......
......@@ -1446,7 +1446,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
if (start + 1 < end &&
info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
((info[start].indic_category() == OT_Repha) ^
_hb_glyph_info_ligated (&info[start])))
_hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
{
unsigned int new_reph_pos;
reph_position_t reph_pos = indic_plan->config->reph_pos;
......@@ -1599,7 +1599,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan,
* If pref len is longer than one, then only reorder if it ligated. If
* pref len is one, only reorder if it didn't ligate with other things. */
if (_hb_glyph_info_substituted (&info[i]) &&
((pref_len == 1) ^ _hb_glyph_info_ligated (&info[i])))
((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
{
/*
* 2. Try to find a target position the same way as for pre-base matra.
......
......@@ -34,7 +34,10 @@ CLEANFILES += \
hb_test_tools.py[co] \
$(NULL)
TESTS = tests/context-matching.tests
TESTS = \
tests/context-matching.tests \
tests/indic-pref-blocking.tests \
$(NULL)
TEST_EXTENSIONS = \
.tests \
......
context-matching.tests
indic-pref-blocking.tests
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册