diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index 375fa1dbd..d136a6644 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -159,7 +159,7 @@ static const struct arabic_state_table_entry { static void -nuke_joiners (const hb_ot_shape_plan_t *plan, +flip_joiners (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); @@ -200,7 +200,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) * work correctly. See https://github.com/harfbuzz/harfbuzz/issues/505 */ - map->add_gsub_pause (nuke_joiners); map->enable_feature (HB_TAG('s','t','c','h')); map->add_gsub_pause (record_stch); @@ -217,14 +216,29 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_gsub_pause (nullptr); } + /* Normally, Unicode says a ZWNJ means "don't ligate". In Arabic script + * however, it says a ZWJ should also mean "don't ligate". So we convert + * a ZWJ to a ZWNJ for GSUB. We want to revert it back to ZWJ before + * GPOS processing though. So we just flip their roles, and flip back + * later. Note that this makes a ZWNJ into ZWJ for GSUB stage, which + * means it would *not* break ligatures. But since ligatures around + * ZWNJ are rare, we don't care. + * + * Since we don't currently have a way to apply a pause before GPOS + * starts, let's just do this dance around a few required GUSB features. */ + map->add_gsub_pause (flip_joiners); + map->add_feature (HB_TAG('r','l','i','g'), F_GLOBAL | F_HAS_FALLBACK); + if (plan->props.script == HB_SCRIPT_ARABIC) map->add_gsub_pause (arabic_fallback_shape); /* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */ map->enable_feature (HB_TAG('r','c','l','t')); map->enable_feature (HB_TAG('c','a','l','t')); - map->add_gsub_pause (nullptr); + + /* And undo here. */ + map->add_gsub_pause (flip_joiners); /* The spec includes 'cswh'. Earlier versions of Windows * used to enable this by default, but testing suggests @@ -381,14 +395,14 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan, static void -nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED, +flip_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) { unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - if (_hb_glyph_info_is_zwj (&info[i])) + if (_hb_glyph_info_is_joiner (&info[i])) _hb_glyph_info_flip_joiners (&info[i]); }