Prefer decomposed form if font has GPOS mark feature

Fixes https://github.com/harfbuzz/harfbuzz/issues/653
This commit is contained in:
Behdad Esfahbod 2018-09-23 21:32:18 -04:00
parent d7f21777e6
commit 62d1e0852a
3 changed files with 72 additions and 63 deletions

View File

@ -70,7 +70,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
bool found = (bool) c->unicode->compose (a, b, ab); bool found = (bool) c->unicode->compose (a, b, ab);
if (!found && !c->plan->has_mark) if (!found)
{ {
/* Special-case Hebrew presentation forms that are excluded from /* Special-case Hebrew presentation forms that are excluded from
* standard normalization, but wanted for old fonts. */ * standard normalization, but wanted for old fonts. */

View File

@ -294,6 +294,14 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
_hb_buffer_assert_unicode_vars (buffer); _hb_buffer_assert_unicode_vars (buffer);
hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference; hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_AUTO)
{
if (plan->has_mark)
mode = HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED;
else
mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
}
const hb_ot_shape_normalize_context_t c = { const hb_ot_shape_normalize_context_t c = {
plan, plan,
buffer, buffer,
@ -358,14 +366,27 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
i = end; i = end;
} }
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ)
{
/* For all CGJ, check if it prevented any reordering at all.
* If it did NOT, then make it skippable.
* https://github.com/harfbuzz/harfbuzz/issues/554
*/
for (unsigned int i = 1; i + 1 < buffer->len; i++)
if (buffer->info[i].codepoint == 0x034Fu/*CGJ*/ &&
info_cc(buffer->info[i-1]) <= info_cc(buffer->info[i+1]))
{
_hb_glyph_info_unhide (&buffer->info[i]);
}
}
if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
return;
/* Third round, recompose */ /* Third round, recompose */
if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS ||
mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT)
return;
{
/* As noted in the comment earlier, we don't try to combine /* As noted in the comment earlier, we don't try to combine
* ccc=0 chars with their previous Starter. */ * ccc=0 chars with their previous Starter. */
@ -416,18 +437,5 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
starter = buffer->out_len - 1; starter = buffer->out_len - 1;
} }
buffer->swap_buffers (); buffer->swap_buffers ();
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ)
{
/* For all CGJ, check if it prevented any reordering at all.
* If it did NOT, then make it skippable.
* https://github.com/harfbuzz/harfbuzz/issues/554
*/
for (unsigned int i = 1; i + 1 < buffer->len; i++)
if (buffer->info[i].codepoint == 0x034Fu/*CGJ*/ &&
info_cc(buffer->info[i-1]) <= info_cc(buffer->info[i+1]))
{
_hb_glyph_info_unhide (&buffer->info[i]);
}
} }
} }

View File

@ -38,10 +38,11 @@ struct hb_ot_shape_plan_t;
enum hb_ot_shape_normalization_mode_t { enum hb_ot_shape_normalization_mode_t {
HB_OT_SHAPE_NORMALIZATION_MODE_NONE, HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED, HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* Never composes base-to-base */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* Always fully decomposes and then recompose back */
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, /* Choose decomposed if GPOS mark feature available, compose otherwise. */
HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_AUTO
}; };
HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper, HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,