[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
This commit is contained in:
Behdad Esfahbod 2014-06-04 16:57:42 -04:00
parent b5be231720
commit 832a6f99b3
7 changed files with 39 additions and 9 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +1,2 @@
context-matching.tests
indic-pref-blocking.tests