diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh | 148 |
1 files changed, 121 insertions, 27 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh index 2d8488e151..a77f24ec84 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh @@ -33,6 +33,8 @@ #include "hb-ot-layout-gsub-table.hh" +/* Features ordered the same as the entries in shaping_table rows, + * followed by rlig. Don't change. */ static const hb_tag_t arabic_fallback_features[] = { HB_TAG('i','n','i','t'), @@ -42,16 +44,6 @@ static const hb_tag_t arabic_fallback_features[] = HB_TAG('r','l','i','g'), }; -/* Same order as the fallback feature array */ -enum { - FALLBACK_INIT, - FALLBACK_MEDI, - FALLBACK_FINA, - FALLBACK_ISOL, - FALLBACK_RLIG, - ARABIC_NUM_FALLBACK_FEATURES -}; - static OT::SubstLookup * arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font, @@ -80,6 +72,9 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS num_glyphs++; } + if (!num_glyphs) + return NULL; + /* Bubble-sort! * May not be good-enough for presidential candidate interviews, but good-enough for us... */ hb_bubble_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]); @@ -157,6 +152,9 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN } } + if (!num_ligatures) + return NULL; + OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs); OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs); OT::Supplier<OT::GlyphID> ligatures_supplier (ligature_list, num_ligatures); @@ -193,17 +191,108 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan, return arabic_fallback_synthesize_lookup_ligature (plan, font); } +#define ARABIC_FALLBACK_MAX_LOOKUPS 5 + struct arabic_fallback_plan_t { ASSERT_POD (); - hb_mask_t mask_array[ARABIC_NUM_FALLBACK_FEATURES]; - OT::SubstLookup *lookup_array[ARABIC_NUM_FALLBACK_FEATURES]; - hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_NUM_FALLBACK_FEATURES]; + unsigned int num_lookups; + bool free_lookups; + + hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS]; + OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS]; + hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS]; }; static const arabic_fallback_plan_t arabic_fallback_plan_nil = {}; +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256) +#define HB_WITH_WIN1256 +#endif + +#ifdef HB_WITH_WIN1256 +#include "hb-ot-shape-complex-arabic-win1256.hh" +#endif + +struct ManifestLookup { + OT::Tag tag; + OT::OffsetTo<OT::SubstLookup> lookupOffset; +}; +typedef OT::ArrayOf<ManifestLookup> Manifest; + +static bool +arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan, + const hb_ot_shape_plan_t *plan, + hb_font_t *font) +{ +#ifdef HB_WITH_WIN1256 + /* Does this font look like it's Windows-1256-encoded? */ + hb_codepoint_t g; + if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ && + hb_font_get_glyph (font, 0x0644u, 0, &g) && g == 225 /* LAM */ && + hb_font_get_glyph (font, 0x0649u, 0, &g) && g == 236 /* ALEF MAKSURA */ && + hb_font_get_glyph (font, 0x064Au, 0, &g) && g == 237 /* YEH */ && + hb_font_get_glyph (font, 0x0652u, 0, &g) && g == 250 /* SUKUN */)) + return false; + + const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest); + ASSERT_STATIC (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup) + <= ARABIC_FALLBACK_MAX_LOOKUPS); + /* TODO sanitize the table? */ + + unsigned j = 0; + unsigned int count = manifest.len; + for (unsigned int i = 0; i < count; i++) + { + fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].tag); + if (fallback_plan->mask_array[j]) + { + fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset)); + if (fallback_plan->lookup_array[j]) + { + fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]); + j++; + } + } + } + + fallback_plan->num_lookups = j; + fallback_plan->free_lookups = false; + + return j > 0; +#else + return false; +#endif +} + +static bool +arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan, + const hb_ot_shape_plan_t *plan, + hb_font_t *font) +{ + ASSERT_STATIC (ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS); + unsigned int j = 0; + for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++) + { + fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]); + if (fallback_plan->mask_array[j]) + { + fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i); + if (fallback_plan->lookup_array[j]) + { + fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]); + j++; + } + } + } + + fallback_plan->num_lookups = j; + fallback_plan->free_lookups = true; + + return j > 0; +} + static arabic_fallback_plan_t * arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, hb_font_t *font) @@ -212,17 +301,21 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan, if (unlikely (!fallback_plan)) return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil); - for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) - { - 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->accel_array[i].init (*fallback_plan->lookup_array[i]); - } - } + fallback_plan->num_lookups = 0; + fallback_plan->free_lookups = false; + + /* Try synthesizing GSUB table using Unicode Arabic Presentation Forms, + * in case the font has cmap entries for the presentation-forms characters. */ + if (arabic_fallback_plan_init_unicode (fallback_plan, plan, font)) + return fallback_plan; - return fallback_plan; + /* See if this looks like a Windows-1256-encoded font. If it does, use a + * hand-coded GSUB table. */ + if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font)) + return fallback_plan; + + free (fallback_plan); + return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil); } static void @@ -231,11 +324,12 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan) if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil) return; - for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) + for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) if (fallback_plan->lookup_array[i]) { - fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]); - free (fallback_plan->lookup_array[i]); + fallback_plan->accel_array[i].fini (); + if (fallback_plan->free_lookups) + free (fallback_plan->lookup_array[i]); } free (fallback_plan); @@ -247,7 +341,7 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan, hb_buffer_t *buffer) { OT::hb_apply_context_t c (0, font, buffer); - for (unsigned int i = 0; i < ARABIC_NUM_FALLBACK_FEATURES; i++) + for (unsigned int i = 0; i < fallback_plan->num_lookups; i++) if (fallback_plan->lookup_array[i]) { c.set_lookup_mask (fallback_plan->mask_array[i]); hb_ot_layout_substitute_lookup (&c, |