From c3f590bb1eb5e2451b80aa3d10a29c62b32b860d Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Thu, 16 Jun 2022 11:04:13 -0600 Subject: [PATCH 01/19] [arabic] Support legacy PUA shaping Support legacy pre-OpenType Windows 3.1-era fonts, by remapping PUA code points in cmap table and letting our fallback shaper build the GSUB table. Uniscribe applies also mset-like substitution, but our fallback mark positioning gives better results, so this is not implemented. --- src/Makefile.sources | 1 + src/gen-arabic-table.py | 27 +- src/hb-ot-cmap-table.hh | 45 ++- src/hb-ot-os2-table.hh | 4 +- src/hb-ot-shaper-arabic-pua.hh | 289 ++++++++++++++++++ src/hb-ot-shaper-arabic-table.hh | 89 +++++- src/meson.build | 1 + .../data/in-house/fonts/SimpArabicTest.ttf | Bin 0 -> 17168 bytes .../data/in-house/fonts/TradArabicTest.ttf | Bin 0 -> 58132 bytes .../tests/arabic-fallback-shaping.tests | 10 + 10 files changed, 449 insertions(+), 17 deletions(-) create mode 100644 src/hb-ot-shaper-arabic-pua.hh create mode 100644 test/shape/data/in-house/fonts/SimpArabicTest.ttf create mode 100644 test/shape/data/in-house/fonts/TradArabicTest.ttf diff --git a/src/Makefile.sources b/src/Makefile.sources index 5ec46bac1..1be0800a1 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -133,6 +133,7 @@ HB_BASE_sources = \ hb-ot-post-table.hh \ hb-ot-shaper-arabic-fallback.hh \ hb-ot-shaper-arabic-joining-list.hh \ + hb-ot-shaper-arabic-pua.hh \ hb-ot-shaper-arabic-table.hh \ hb-ot-shaper-arabic-win1256.hh \ hb-ot-shaper-arabic.cc \ diff --git a/src/gen-arabic-table.py b/src/gen-arabic-table.py index 1a1123abe..3ea2b850d 100755 --- a/src/gen-arabic-table.py +++ b/src/gen-arabic-table.py @@ -153,6 +153,16 @@ def print_joining_table(f): print ("#undef %s" % (short)) print () +LIGATURES = ( + 0xF2EE, 0xFC08, 0xFC0E, 0xFC12, 0xFC32, 0xFC3F, 0xFC40, 0xFC41, 0xFC42, + 0xFC44, 0xFC4E, 0xFC5E, 0xFC60, 0xFC61, 0xFC62, 0xFC6A, 0xFC6D, 0xFC6F, + 0xFC70, 0xFC73, 0xFC75, 0xFC86, 0xFC8F, 0xFC91, 0xFC94, 0xFC9C, 0xFC9D, + 0xFC9E, 0xFC9F, 0xFCA1, 0xFCA2, 0xFCA3, 0xFCA4, 0xFCA8, 0xFCAA, 0xFCAC, + 0xFCB0, 0xFCC9, 0xFCCA, 0xFCCB, 0xFCCC, 0xFCCD, 0xFCCE, 0xFCCF, 0xFCD0, + 0xFCD1, 0xFCD2, 0xFCD3, 0xFCD5, 0xFCDA, 0xFCDB, 0xFCDC, 0xFCDD, 0xFD30, + 0xFD88, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, +) + def print_shaping_table(f): shapes = {} @@ -166,14 +176,19 @@ def print_shaping_table(f): items = fields[5].split (' ') shape, items = items[0][1:-1], tuple (int (x, 16) for x in items[1:]) + c = int (fields[0], 16) if not shape in ['initial', 'medial', 'isolated', 'final']: continue - c = int (fields[0], 16) if len (items) != 1: - # We only care about lam-alef ligatures - if len (items) != 2 or items[0] != 0x0644 or items[1] not in [0x0622, 0x0623, 0x0625, 0x0627]: + # Mark ligatures start with space and are in visual order, so we + # remove the space and reverse the items. + if items[0] == 0x0020: + items = items[:0:-1] + shape = None + # We only care about a subset of ligatures + if c not in LIGATURES or len (items) != 2: continue # Save ligature @@ -213,10 +228,14 @@ def print_shaping_table(f): for pair in ligatures.keys (): for shape in ligatures[pair]: c = ligatures[pair][shape] - if shape == 'isolated': + if shape is None: + liga = pair + elif shape == 'isolated': liga = (shapes[pair[0]]['initial'], shapes[pair[1]]['final']) elif shape == 'final': liga = (shapes[pair[0]]['medial'], shapes[pair[1]]['final']) + elif shape == 'initial': + liga = (shapes[pair[0]]['initial'], shapes[pair[1]]['medial']) else: raise Exception ("Unexpected shape", shape) if liga[0] not in ligas: diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index 4fd2b9be4..ac96f9c84 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -27,6 +27,8 @@ #ifndef HB_OT_CMAP_TABLE_HH #define HB_OT_CMAP_TABLE_HH +#include "hb-ot-os2-table.hh" +#include "hb-ot-shaper-arabic-pua.hh" #include "hb-open-type.hh" #include "hb-set.hh" @@ -1502,6 +1504,21 @@ struct SubtableUnicodesCache { }; +static inline hb_codepoint_t +_hb_remap_symbol_pua (hb_codepoint_t codepoint) +{ + if (codepoint <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * https://docs.microsoft.com/en-us/typography/opentype/spec/recom + * under "Non-Standard (Symbol) Fonts". */ + return 0xF000u + codepoint; + } + return 0; +} + struct cmap { static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap; @@ -1725,7 +1742,19 @@ struct cmap this->get_glyph_data = subtable; if (unlikely (symbol)) - this->get_glyph_funcZ = get_glyph_from_symbol; + { + switch ((unsigned) face->table.OS2->get_font_page ()) { + default: + this->get_glyph_funcZ = get_glyph_from_symbol; + break; + case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: + this->get_glyph_funcZ = get_glyph_from_symbol; + break; + case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: + this->get_glyph_funcZ = get_glyph_from_symbol; + break; + } + } else { switch (subtable->u.format) { @@ -1807,6 +1836,7 @@ struct cmap typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph); + typedef hb_codepoint_t (*hb_pua_remap_func_t) (hb_codepoint_t); template HB_INTERNAL static bool get_glyph_from (const void *obj, @@ -1817,7 +1847,7 @@ struct cmap return typed_obj->get_glyph (codepoint, glyph); } - template + template HB_INTERNAL static bool get_glyph_from_symbol (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph) @@ -1826,15 +1856,8 @@ struct cmap if (likely (typed_obj->get_glyph (codepoint, glyph))) return true; - if (codepoint <= 0x00FFu) - { - /* For symbol-encoded OpenType fonts, we duplicate the - * U+F000..F0FF range at U+0000..U+00FF. That's what - * Windows seems to do, and that's hinted about at: - * https://docs.microsoft.com/en-us/typography/opentype/spec/recom - * under "Non-Standard (Symbol) Fonts". */ - return typed_obj->get_glyph (0xF000u + codepoint, glyph); - } + if (hb_codepoint_t c = remap (codepoint)) + return typed_obj->get_glyph (c, glyph); return false; } diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh index f0035e2f0..3473afef5 100644 --- a/src/hb-ot-os2-table.hh +++ b/src/hb-ot-os2-table.hh @@ -224,9 +224,11 @@ struct OS2 *max_cp = hb_min (0xFFFFu, codepoints->get_max ()); } - /* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 */ + /* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 + * https://docs.microsoft.com/en-us/typography/legacy/legacy_arabic_fonts */ enum font_page_t { + FONT_PAGE_NONE = 0, FONT_PAGE_HEBREW = 0xB100, /* Hebrew Windows 3.1 font page */ FONT_PAGE_SIMP_ARABIC = 0xB200, /* Simplified Arabic Windows 3.1 font page */ FONT_PAGE_TRAD_ARABIC = 0xB300, /* Traditional Arabic Windows 3.1 font page */ diff --git a/src/hb-ot-shaper-arabic-pua.hh b/src/hb-ot-shaper-arabic-pua.hh new file mode 100644 index 000000000..98cd266e9 --- /dev/null +++ b/src/hb-ot-shaper-arabic-pua.hh @@ -0,0 +1,289 @@ + +#ifndef HB_OT_SHAPER_ARABIC_PUA_HH +#define HB_OT_SHAPER_ARABIC_PUA_HH + +static const uint16_t _arabic_table_pua1[][128] = { + { /* 0x0000u..0x007Fu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0xF120u, 0xF121u, 0xF122u, 0x0000u, 0x0000u, 0xF125u, 0x0000u, 0x0000u, + 0xF128u, 0xF129u, 0xF12Au, 0xF12Bu, 0xF15Eu, 0xF12Du, 0xF12Eu, 0xF12Fu, + 0xF1B0u, 0xF1B1u, 0xF1B2u, 0xF1B3u, 0xF1B4u, 0xF1B5u, 0xF1B6u, 0xF1B7u, + 0xF1B8u, 0xF1B9u, 0xF13Au, 0xF13Bu, 0x0000u, 0xF13Du, 0x0000u, 0xF13Fu, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0xF15Bu, 0xF15Cu, 0xF15Du, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0x0080u..0x00FFu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0xF123u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0xF124u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF126u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF127u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0x0600u..0x067Fu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF12Cu, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0xF13Bu, 0x0000u, 0x0000u, 0x0000u, 0xF13Fu, + 0x0000u, 0xF1ADu, 0xF145u, 0xF143u, 0xF1BBu, 0xF147u, 0xF1BAu, 0xF141u, + 0xF14Au, 0xF1A9u, 0xF14Cu, 0xF14Eu, 0xF151u, 0xF154u, 0xF157u, 0xF158u, + 0xF159u, 0xF15Au, 0xF160u, 0xF162u, 0xF164u, 0xF166u, 0xF168u, 0xF169u, + 0xF16Au, 0xF16Eu, 0xF172u, 0xF100u, 0xF100u, 0xF100u, 0xF100u, 0xF100u, + 0xF15Fu, 0xF175u, 0xF178u, 0xF17Au, 0xF17Cu, 0xF17Eu, 0xF1E1u, 0xF1A4u, + 0xF1A5u, 0xF1ACu, 0xF1A8u, 0xF1C7u, 0xF1C8u, 0xF1CBu, 0xF1C4u, 0xF1C5u, + 0xF1CAu, 0xF1C9u, 0xF1C6u, 0xF100u, 0xF100u, 0xF100u, 0xF100u, 0xF100u, + 0xF100u, 0xF100u, 0xF100u, 0xF100u, 0xF100u, 0xF100u, 0xF100u, 0x0000u, + 0xF130u, 0xF131u, 0xF132u, 0xF133u, 0xF134u, 0xF135u, 0xF136u, 0xF137u, + 0xF138u, 0xF139u, 0x0000u, 0xF15Eu, 0xF15Eu, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0x2000u..0x207Fu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF10Cu, 0xF10Du, 0xF10Eu, 0xF10Fu, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0xF13Cu, 0xF13Eu, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0xFE80u..0xFEFFu */ + 0x0000u, 0xF145u, 0xF146u, 0xF143u, 0xF144u, 0xF1BBu, 0xF1BBu, 0xF147u, + 0xF148u, 0xF1BAu, 0xF1AFu, 0xF1AEu, 0xF1AEu, 0xF141u, 0xF142u, 0xF14Au, + 0xF14Au, 0xF149u, 0xF149u, 0xF1A9u, 0xF1AAu, 0xF14Cu, 0xF14Cu, 0xF14Bu, + 0xF14Bu, 0xF14Eu, 0xF14Eu, 0xF14Du, 0xF14Du, 0xF151u, 0xF150u, 0xF14Fu, + 0xF14Fu, 0xF154u, 0xF153u, 0xF152u, 0xF152u, 0xF157u, 0xF156u, 0xF155u, + 0xF155u, 0xF158u, 0xF158u, 0xF159u, 0xF159u, 0xF15Au, 0xF15Au, 0xF160u, + 0xF160u, 0xF162u, 0xF162u, 0xF161u, 0xF161u, 0xF164u, 0xF164u, 0xF163u, + 0xF163u, 0xF166u, 0xF166u, 0xF165u, 0xF165u, 0xF168u, 0xF168u, 0xF167u, + 0xF167u, 0xF169u, 0xF169u, 0xF169u, 0xF169u, 0xF16Au, 0xF16Au, 0xF16Au, + 0xF16Au, 0xF16Eu, 0xF16Du, 0xF16Bu, 0xF16Cu, 0xF172u, 0xF171u, 0xF16Fu, + 0xF170u, 0xF175u, 0xF175u, 0xF173u, 0xF174u, 0xF178u, 0xF178u, 0xF176u, + 0xF177u, 0xF17Au, 0xF17Au, 0xF179u, 0xF179u, 0xF17Cu, 0xF17Cu, 0xF17Bu, + 0xF17Bu, 0xF17Eu, 0xF17Eu, 0xF17Du, 0xF17Du, 0xF1E1u, 0xF1E1u, 0xF17Fu, + 0xF17Fu, 0xF1A4u, 0xF1A3u, 0xF1A1u, 0xF1A2u, 0xF1A5u, 0xF1A5u, 0xF1ACu, + 0xF1ABu, 0xF1A8u, 0xF1A7u, 0xF1A6u, 0xF1A6u, 0xF1C0u, 0xF1C1u, 0xF1BEu, + 0xF1BFu, 0xF1C2u, 0xF1C3u, 0xF1BDu, 0xF1BCu, 0x0000u, 0x0000u, 0x0000u, + }, +}; + +static inline hb_codepoint_t +_hb_remap_arabic_pua1(hb_codepoint_t codepoint) +{ + if (hb_in_range (codepoint, 0x0000u, 0x007Fu)) return _arabic_table_pua1[0][codepoint]; + if (hb_in_range (codepoint, 0x0080u, 0x00FFu)) return _arabic_table_pua1[1][codepoint - 0x0080u]; + if (hb_in_range (codepoint, 0x0600u, 0x067Fu)) return _arabic_table_pua1[2][codepoint - 0x0600u]; + if (hb_in_range (codepoint, 0x2000u, 0x207Fu)) return _arabic_table_pua1[3][codepoint - 0x2000u]; + if (hb_in_range (codepoint, 0xFE80u, 0xFEFFu)) return _arabic_table_pua1[4][codepoint - 0xFE80u]; + return 0; +} + +static const uint16_t _arabic_table_pua2[][128] = { + { /* 0x0000u..0x007Fu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0xF220u, 0xF221u, 0xF222u, 0x0000u, 0x0000u, 0xF225u, 0x0000u, 0x0000u, + 0xF228u, 0xF229u, 0xF22Au, 0xF22Bu, 0xF25Eu, 0xF22Du, 0xF22Eu, 0xF22Fu, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0xF23Au, 0xF23Bu, 0x0000u, 0xF23Du, 0x0000u, 0xF23Fu, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0xF25Bu, 0x0000u, 0xF25Du, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0x0080u..0x00FFu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0xF223u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0xF224u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF226u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF227u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0x0600u..0x067Fu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF22Cu, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0xF23Bu, 0x0000u, 0x0000u, 0x0000u, 0xF23Fu, + 0x0000u, 0xF2D5u, 0xF245u, 0xF243u, 0xF2DAu, 0xF247u, 0xF2D9u, 0xF241u, + 0xF24Cu, 0xF2D1u, 0xF250u, 0xF254u, 0xF258u, 0xF260u, 0xF264u, 0xF265u, + 0xF267u, 0xF269u, 0xF26Bu, 0xF270u, 0xF274u, 0xF278u, 0xF27Eu, 0xF2A2u, + 0xF2A3u, 0xF2AAu, 0xF2AEu, 0xF200u, 0xF200u, 0xF200u, 0xF200u, 0xF200u, + 0xF25Fu, 0xF2B2u, 0xF2B6u, 0xF2BAu, 0xF2BEu, 0xF2C2u, 0xF2C6u, 0xF2CAu, + 0xF2CBu, 0xF2D4u, 0xF2D0u, 0xF2E7u, 0xF2E8u, 0xF2EBu, 0xF2E4u, 0xF2E5u, + 0xF2EAu, 0xF2E9u, 0xF2E6u, 0xF200u, 0xF200u, 0xF200u, 0xF200u, 0xF200u, + 0xF200u, 0xF200u, 0xF200u, 0xF200u, 0xF200u, 0xF200u, 0xF200u, 0x0000u, + 0xF230u, 0xF231u, 0xF232u, 0xF233u, 0xF234u, 0xF235u, 0xF236u, 0xF237u, + 0xF238u, 0xF239u, 0x0000u, 0xF25Eu, 0xF25Eu, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0x2000u..0x207Fu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF20Cu, 0xF20Du, 0xF20Eu, 0xF20Fu, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF23Cu, 0xF23Eu, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0xFBD0u..0xFC4Fu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0xF202u, 0x0000u, 0xF21Du, 0x0000u, 0x0000u, 0x0000u, 0xF203u, 0x0000u, + 0xF21Eu, 0x0000u, 0xF204u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0xF29Fu, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF212u, + 0xF213u, 0xF214u, 0xF205u, 0x0000u, 0xF21Cu, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF206u, 0x0000u, + }, + { /* 0xFC50u..0xFCCFu */ + 0xF21Fu, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF2EFu, 0x0000u, + 0xF2ECu, 0xF2EDu, 0xF2F0u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0xF215u, 0x0000u, 0x0000u, 0xF292u, 0x0000u, 0x0000u, + 0xF216u, 0x0000u, 0x0000u, 0xF293u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF295u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0xF217u, 0x0000u, 0x0000u, 0xF294u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF280u, 0xF281u, 0xF282u, 0xF296u, + 0x0000u, 0xF283u, 0xF284u, 0xF285u, 0xF297u, 0x0000u, 0x0000u, 0x0000u, + 0xF29Au, 0x0000u, 0xF29Bu, 0x0000u, 0xF29Cu, 0x0000u, 0x0000u, 0x0000u, + 0xF218u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0xF286u, 0xF287u, 0xF288u, 0xF29Du, 0xF21Au, 0xF289u, 0xF28Au, + }, + { /* 0xFCD0u..0xFD4Fu */ + 0xF28Bu, 0xF29Eu, 0xF28Du, 0xF28Eu, 0x0000u, 0xF298u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0xF28Fu, 0xF290u, 0xF291u, 0xF299u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0xF219u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0xF27Bu, 0xF27Du, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0xFD50u..0xFDCFu */ + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0xF210u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + }, + { /* 0xFE80u..0xFEFFu */ + 0x0000u, 0xF245u, 0xF246u, 0xF243u, 0xF244u, 0xF2DAu, 0xF2DBu, 0xF247u, + 0xF248u, 0xF2D9u, 0xF2D8u, 0xF2D6u, 0xF2D7u, 0xF241u, 0xF242u, 0xF24Cu, + 0xF24Bu, 0xF249u, 0xF24Au, 0xF2D1u, 0xF2D2u, 0xF250u, 0xF24Fu, 0xF24Du, + 0xF24Eu, 0xF254u, 0xF253u, 0xF251u, 0xF252u, 0xF258u, 0xF257u, 0xF255u, + 0xF256u, 0xF260u, 0xF25Cu, 0xF259u, 0xF25Au, 0xF264u, 0xF263u, 0xF261u, + 0xF262u, 0xF265u, 0xF266u, 0xF267u, 0xF268u, 0xF269u, 0xF26Au, 0xF26Bu, + 0xF26Cu, 0xF270u, 0xF26Fu, 0xF26Du, 0xF26Eu, 0xF274u, 0xF273u, 0xF271u, + 0xF272u, 0xF278u, 0xF277u, 0xF275u, 0xF276u, 0xF27Eu, 0xF27Cu, 0xF279u, + 0xF27Au, 0xF2A2u, 0xF2A1u, 0xF27Fu, 0xF2F1u, 0xF2A6u, 0xF2A5u, 0xF2A3u, + 0xF2A4u, 0xF2AAu, 0xF2A9u, 0xF2A7u, 0xF2A8u, 0xF2AEu, 0xF2ADu, 0xF2ABu, + 0xF2ACu, 0xF2B2u, 0xF2B1u, 0xF2AFu, 0xF2B0u, 0xF2B6u, 0xF2B5u, 0xF2B3u, + 0xF2B4u, 0xF2BAu, 0xF2B9u, 0xF2B7u, 0xF2B8u, 0xF2BEu, 0xF2BDu, 0xF2BBu, + 0xF2BCu, 0xF2C2u, 0xF2C1u, 0xF2BFu, 0xF2C0u, 0xF2C6u, 0xF2C5u, 0xF2C3u, + 0xF2C4u, 0xF2CAu, 0xF2C9u, 0xF2C7u, 0xF2C8u, 0xF2CBu, 0xF2CCu, 0xF2D4u, + 0xF2D3u, 0xF2D0u, 0xF2CFu, 0xF2CDu, 0xF2CEu, 0xF2E0u, 0xF2E1u, 0xF2DEu, + 0xF2DFu, 0xF2E2u, 0xF2E3u, 0xF2DCu, 0xF2DDu, 0x0000u, 0x0000u, 0x0000u, + }, +}; + +static inline hb_codepoint_t +_hb_remap_arabic_pua2(hb_codepoint_t codepoint) +{ + if (hb_in_range (codepoint, 0x0000u, 0x007Fu)) return _arabic_table_pua2[0][codepoint]; + if (hb_in_range (codepoint, 0x0080u, 0x00FFu)) return _arabic_table_pua2[1][codepoint - 0x0080u]; + if (hb_in_range (codepoint, 0x0600u, 0x067Fu)) return _arabic_table_pua2[2][codepoint - 0x0600u]; + if (hb_in_range (codepoint, 0x2000u, 0x207Fu)) return _arabic_table_pua2[3][codepoint - 0x2000u]; + if (hb_in_range (codepoint, 0xFBD0u, 0xFC4Fu)) return _arabic_table_pua2[4][codepoint - 0xFBD0u]; + if (hb_in_range (codepoint, 0xFC50u, 0xFCCFu)) return _arabic_table_pua2[5][codepoint - 0xFC50u]; + if (hb_in_range (codepoint, 0xFCD0u, 0xFD4Fu)) return _arabic_table_pua2[6][codepoint - 0xFCD0u]; + if (hb_in_range (codepoint, 0xFD50u, 0xFDCFu)) return _arabic_table_pua2[7][codepoint - 0xFD50u]; + if (hb_in_range (codepoint, 0xFE80u, 0xFEFFu)) return _arabic_table_pua2[8][codepoint - 0xFE80u]; + return 0; +} + +#endif /* HB_OT_SHAPER_ARABIC_PUA_HH */ diff --git a/src/hb-ot-shaper-arabic-table.hh b/src/hb-ot-shaper-arabic-table.hh index 73b4b84fc..4c6aecfd8 100644 --- a/src/hb-ot-shaper-arabic-table.hh +++ b/src/hb-ot-shaper-arabic-table.hh @@ -418,21 +418,108 @@ static const struct ligature_set_t { struct ligature_pairs_t { uint16_t second; uint16_t ligature; - } ligatures[4]; + } ligatures[14]; } ligature_table[] = { + { 0x0651u, { + { 0x064Cu, 0xFC5Eu }, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */ + { 0x064Eu, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */ + { 0x064Fu, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */ + { 0x0650u, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */ + }}, + { 0xFE91u, { + { 0xFEE2u, 0xFC08u }, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */ + { 0xFEE4u, 0xFC9Fu }, /* ARABIC LIGATURE BEH WITH MEEM INITIAL FORM */ + { 0xFEA0u, 0xFC9Cu }, /* ARABIC LIGATURE BEH WITH JEEM INITIAL FORM */ + { 0xFEA4u, 0xFC9Du }, /* ARABIC LIGATURE BEH WITH HAH INITIAL FORM */ + { 0xFEA8u, 0xFC9Eu }, /* ARABIC LIGATURE BEH WITH KHAH INITIAL FORM */ + }}, + { 0xFE92u, { + { 0xFEAEu, 0xFC6Au }, /* ARABIC LIGATURE BEH WITH REH FINAL FORM */ + { 0xFEE6u, 0xFC6Du }, /* ARABIC LIGATURE BEH WITH NOON FINAL FORM */ + { 0xFEF2u, 0xFC6Fu }, /* ARABIC LIGATURE BEH WITH YEH FINAL FORM */ + }}, + { 0xFE97u, { + { 0xFEE2u, 0xFC0Eu }, /* ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM */ + { 0xFEE4u, 0xFCA4u }, /* ARABIC LIGATURE TEH WITH MEEM INITIAL FORM */ + { 0xFEA0u, 0xFCA1u }, /* ARABIC LIGATURE TEH WITH JEEM INITIAL FORM */ + { 0xFEA4u, 0xFCA2u }, /* ARABIC LIGATURE TEH WITH HAH INITIAL FORM */ + { 0xFEA8u, 0xFCA3u }, /* ARABIC LIGATURE TEH WITH KHAH INITIAL FORM */ + }}, + { 0xFE98u, { + { 0xFEAEu, 0xFC70u }, /* ARABIC LIGATURE TEH WITH REH FINAL FORM */ + { 0xFEE6u, 0xFC73u }, /* ARABIC LIGATURE TEH WITH NOON FINAL FORM */ + { 0xFEF2u, 0xFC75u }, /* ARABIC LIGATURE TEH WITH YEH FINAL FORM */ + }}, + { 0xFE9Bu, { + { 0xFEE2u, 0xFC12u }, /* ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM */ + }}, + { 0xFE9Fu, { + { 0xFEE4u, 0xFCA8u }, /* ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM */ + }}, + { 0xFEA3u, { + { 0xFEE4u, 0xFCAAu }, /* ARABIC LIGATURE HAH WITH MEEM INITIAL FORM */ + }}, + { 0xFEA7u, { + { 0xFEE4u, 0xFCACu }, /* ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM */ + }}, + { 0xFEB3u, { + { 0xFEE4u, 0xFCB0u }, /* ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM */ + }}, + { 0xFEB7u, { + { 0xFEE4u, 0xFD30u }, /* ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM */ + }}, + { 0xFED3u, { + { 0xFEF2u, 0xFC32u }, /* ARABIC LIGATURE FEH WITH YEH ISOLATED FORM */ + }}, { 0xFEDFu, { + { 0xFE9Eu, 0xFC3Fu }, /* ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM */ + { 0xFEA0u, 0xFCC9u }, /* ARABIC LIGATURE LAM WITH JEEM INITIAL FORM */ + { 0xFEA2u, 0xFC40u }, /* ARABIC LIGATURE LAM WITH HAH ISOLATED FORM */ + { 0xFEA4u, 0xFCCAu }, /* ARABIC LIGATURE LAM WITH HAH INITIAL FORM */ + { 0xFEA6u, 0xFC41u }, /* ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM */ + { 0xFEA8u, 0xFCCBu }, /* ARABIC LIGATURE LAM WITH KHAH INITIAL FORM */ + { 0xFEE2u, 0xFC42u }, /* ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM */ + { 0xFEE4u, 0xFCCCu }, /* ARABIC LIGATURE LAM WITH MEEM INITIAL FORM */ + { 0xFEF2u, 0xFC44u }, /* ARABIC LIGATURE LAM WITH YEH ISOLATED FORM */ + { 0xFEECu, 0xFCCDu }, /* ARABIC LIGATURE LAM WITH HEH INITIAL FORM */ { 0xFE82u, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */ { 0xFE84u, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */ { 0xFE88u, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */ { 0xFE8Eu, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */ }}, { 0xFEE0u, { + { 0xFEF0u, 0xFC86u }, /* ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM */ { 0xFE82u, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */ { 0xFE84u, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */ { 0xFE88u, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */ { 0xFE8Eu, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */ }}, + { 0xFEE3u, { + { 0xFEA0u, 0xFCCEu }, /* ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM */ + { 0xFEA4u, 0xFCCFu }, /* ARABIC LIGATURE MEEM WITH HAH INITIAL FORM */ + { 0xFEA8u, 0xFCD0u }, /* ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM */ + { 0xFEE4u, 0xFCD1u }, /* ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM */ + }}, + { 0xFEE7u, { + { 0xFEE2u, 0xFC4Eu }, /* ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM */ + { 0xFEE4u, 0xFCD5u }, /* ARABIC LIGATURE NOON WITH MEEM INITIAL FORM */ + { 0xFEA0u, 0xFCD2u }, /* ARABIC LIGATURE NOON WITH JEEM INITIAL FORM */ + { 0xFEA4u, 0xFCD3u }, /* ARABIC LIGATURE NOON WITH HAH INITIAL FORM */ + }}, + { 0xFEE8u, { + { 0xFEF2u, 0xFC8Fu }, /* ARABIC LIGATURE NOON WITH YEH FINAL FORM */ + }}, + { 0xFEF3u, { + { 0xFEA0u, 0xFCDAu }, /* ARABIC LIGATURE YEH WITH JEEM INITIAL FORM */ + { 0xFEA4u, 0xFCDBu }, /* ARABIC LIGATURE YEH WITH HAH INITIAL FORM */ + { 0xFEA8u, 0xFCDCu }, /* ARABIC LIGATURE YEH WITH KHAH INITIAL FORM */ + { 0xFEE4u, 0xFCDDu }, /* ARABIC LIGATURE YEH WITH MEEM INITIAL FORM */ + }}, + { 0xFEF4u, { + { 0xFEAEu, 0xFC91u }, /* ARABIC LIGATURE YEH WITH REH FINAL FORM */ + { 0xFEE6u, 0xFC94u }, /* ARABIC LIGATURE YEH WITH NOON FINAL FORM */ + }}, }; diff --git a/src/meson.build b/src/meson.build index bca289dc5..b7c11cdf6 100644 --- a/src/meson.build +++ b/src/meson.build @@ -137,6 +137,7 @@ hb_base_sources = files( 'hb-ot-post-table.hh', 'hb-ot-shaper-arabic-fallback.hh', 'hb-ot-shaper-arabic-joining-list.hh', + 'hb-ot-shaper-arabic-pua.hh', 'hb-ot-shaper-arabic-table.hh', 'hb-ot-shaper-arabic-win1256.hh', 'hb-ot-shaper-arabic.cc', diff --git a/test/shape/data/in-house/fonts/SimpArabicTest.ttf b/test/shape/data/in-house/fonts/SimpArabicTest.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d560f6a385fedbb4ea2a8251802cd3cd8eece445 GIT binary patch literal 17168 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 literal 0 HcmV?d00001 diff --git a/test/shape/data/in-house/fonts/TradArabicTest.ttf b/test/shape/data/in-house/fonts/TradArabicTest.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a82ed35759c35a0c6a8e6cf25274d260d7d4ea84 GIT binary patch literal 58132 zcmdqK4}25XkvP8lcJ;Jguh*;9O6x_)Ldfz)Q4}GBEQBxy;~3*Oj^jFx<2sIU9LIq; z4l%AnsY_jsa+Fd^2??cyq$%Yn$8nTWN(rG!C`T#HaWu!5UoIuNG);49{xnBZnlG_e zzj-S=!44P~OqpeRcN9IL+XfyJ#o-rh!v;&xHgzy4R-z4KZ=p0sQsT)P9df;Ko{_gJ5S z@4tsFudRL2Bk~XPUWMO2LQ%}`9_YAdp1+^ZSu`IljrgGZ$Q;5YpKbMH}9)^X!SL&#Wf-f7^Z`EkZPlA>Osu(^-m z*E4}G6t#QsGIlQgEy@D4h+4h_VC1GhnNw6Nk_WH3(C4g*xurjzd4@WZO2feKx7Y!@ zx2Y0xHT_|Fv%F0`$UaAf1~+C!`a1`dAR9%cUWctK{b{^wkyD4vZ5`EY8Q9p?RL$UK zc|3KDY|OsY?yTbg^+BrD^6ymV;70#DJoj~K846RC%xzQ)Y)zKAR5kM?)xqwd7BhEH z^I`i9vxq8YlT;!4Gqn%>H`Rq!QmfE&l!x6(e;>9j>`v-5Y`yT^4WH*=I{@1z*q(yz zEd2ufhWz#~R2|z!Er-uC<`zn|{3-PeeSqo)II8H^fF8F}H_-=-7ts@`b~s)K$2od= z>KOg!)N!jsEwHvxwXnZy*#5KU?^_B}C)w9iM=ay12LP98gZti5lLSg!g zsb|hVKX^U!9jb@<1y%9MXCzgN4yLM^flqc->P6U&bKj#DS^q>W8oqB?pZcZcUsAuw zc$k`(v771{+_&tdb#lzImue!%*_EjmEqTy>7urNPKCrQ;Qile&3tkJq$4;tla3gKZ z^g^4Tw^?3J?Hb(B%c-r=DZ>q<+bUsC$?vsLsJQX5XQ{$gZQl$UKpHn#oN)&u~-^@J%}tP1T?m zQca&+x0C9^e_?!lx zGt$RX@1R;5qgu*5t@>Re4{gTCH`3>&2GS+R}B<|N4 z_hr1x@5{V3^HzZsex3CXVh6l_AikRI%f2uB$JzZ-Olp!=*>Y^9wlCNowe7UMWcxr? zz_MaQ&97x+atF>TC3K!*6y$U=#IPZI97LO-Me=_RL|Bw zSpWOauWp##aP+RvH?ocU8~@MU>fOb6FS`3oQ>5vZrln0U&AWNtp5{B7|LLBbd#2pe zb`=~|KMrtcaoZabEolYzEP0WuMsLptPz7DT= z0RxBOD26?Zt?(iTqm$#4@^zhD6DLy5C!`%ixqfQ#WG3Hq~ zZ=an0g`OY# z`~v*hYYOAjJh7ZuMOf3arJ{8=VlE`wSS%)$EH;ZPo-}zb);tLN0_EYL7*L~;?gl=a z<5kXAR2kw`msN0yN{R6U-gRgOvP-PHSHics$-P~>0;pu-p1XZ^e`{MO>ysTwWf4Lc z3k5m9Ql|OK74L&_6=CLt;fa;2%H;89cldQdkhHJf|Kgf>gSYPwcv@m=0>vWjWp$zl zv5EMUSnG|Ux5}DaG39P|flx8SXuPf35(=}dKEI+4qo~U-xEzu9RR*!VZ!yR1^kJ-( zIe8kL^>|-4_Q)2boq9@keY86kD~KWaB*raPZ?P8buBjb&uT<^}vi_Muc~Q|95)1R} zFR`lZ*EI{9!%qX#lL~$OHoFWRryNusRYP>}K+{+Tny)~GCL#?B4MmzXA6ktjtwRo^ zFD4D{R896tH#!3i50{YUGJn9%MPq@Cm}8~B+5vb$lIY^8a;kFDY?Cyv!ztBlWIuIA-xP?n$mFo;|}jUGpV< zdxyrL*fRR{-HVfV<$59x#3B~6+yGtXS)4$Z2sLjcx)3^~36uUmC=X*rq-R+nP&R?X z&8�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 Date: Sat, 14 Aug 2021 02:39:46 +0200 Subject: [PATCH 02/19] WIP: manually add data entries for PUA ligatures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just a test, I’m not entirely convinced we should do this. --- src/gen-arabic-table.py | 9 ++++++++- src/hb-ot-shaper-arabic-table.hh | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/gen-arabic-table.py b/src/gen-arabic-table.py index 3ea2b850d..7bb49693b 100755 --- a/src/gen-arabic-table.py +++ b/src/gen-arabic-table.py @@ -161,6 +161,7 @@ LIGATURES = ( 0xFCB0, 0xFCC9, 0xFCCA, 0xFCCB, 0xFCCC, 0xFCCD, 0xFCCE, 0xFCCF, 0xFCD0, 0xFCD1, 0xFCD2, 0xFCD3, 0xFCD5, 0xFCDA, 0xFCDB, 0xFCDC, 0xFCDD, 0xFD30, 0xFD88, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, + 0xF201, 0xF211, 0xF2EE, ) def print_shaping_table(f): @@ -168,7 +169,13 @@ def print_shaping_table(f): shapes = {} ligatures = {} names = {} - for line in f: + lines = f.readlines() + lines += [ + "F201;PUA ARABIC LIGATURE LELLAH ISOLATED FORM;Lo;0;AL; 0644 0644 0647;;;;N;;;;;", + "F211;PUA ARABIC LIGATURE LAM WITH MEEM WITH JEEM INITIAL FORM;Lo;0;AL; 0644 0645 062C;;;;N;;;;;", + "F2EE;PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM;Lo;0;AL; 0020 064B 0651;;;;N;;;;;", + ] + for line in lines: fields = [x.strip () for x in line.split (';')] if fields[5][0:1] != '<': diff --git a/src/hb-ot-shaper-arabic-table.hh b/src/hb-ot-shaper-arabic-table.hh index 4c6aecfd8..b0b65e0a3 100644 --- a/src/hb-ot-shaper-arabic-table.hh +++ b/src/hb-ot-shaper-arabic-table.hh @@ -426,6 +426,7 @@ static const struct ligature_set_t { { 0x064Eu, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */ { 0x064Fu, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */ { 0x0650u, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */ + { 0x064Bu, 0xF2EEu }, /* PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM */ }}, { 0xFE91u, { { 0xFEE2u, 0xFC08u }, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */ From 189e8c326e8421f2e59f10d9ab7355d2c3114147 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 18 Jun 2022 13:28:54 +0200 Subject: [PATCH 03/19] [ft] Remap legacy Arabic PUA codepoints Similar to what ot font finctions does, to support Support legacy pre-OpenType Windows 3.1-era fonts. --- src/hb-ft.cc | 29 ++++++++++++++----- .../tests/arabic-fallback-shaping.tests | 20 ++++++------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index abb2328aa..2da90a2e3 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -37,6 +37,8 @@ #include "hb-font.hh" #include "hb-machinery.hh" #include "hb-cache.hh" +#include "hb-ot-os2-table.hh" +#include "hb-ot-shaper-arabic-pua.hh" #include FT_ADVANCES_H #include FT_MULTIPLE_MASTERS_H @@ -298,7 +300,7 @@ hb_ft_font_unlock_face (hb_font_t *font) static hb_bool_t -hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, +hb_ft_get_nominal_glyph (hb_font_t *font, void *font_data, hb_codepoint_t unicode, hb_codepoint_t *glyph, @@ -310,14 +312,25 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, if (unlikely (!g)) { - if (unlikely (ft_font->symbol) && unicode <= 0x00FFu) + if (unlikely (ft_font->symbol)) { - /* For symbol-encoded OpenType fonts, we duplicate the - * U+F000..F0FF range at U+0000..U+00FF. That's what - * Windows seems to do, and that's hinted about at: - * https://docs.microsoft.com/en-us/typography/opentype/spec/recom - * under "Non-Standard (Symbol) Fonts". */ - g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); + switch ((unsigned) font->face->table.OS2->get_font_page ()) { + default: + if (unicode <= 0x00FFu) + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * https://docs.microsoft.com/en-us/typography/opentype/spec/recom + * under "Non-Standard (Symbol) Fonts". */ + g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); + break; + case OT::OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: + g = FT_Get_Char_Index (ft_font->ft_face, _hb_remap_arabic_pua1 (unicode)); + break; + case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: + g = FT_Get_Char_Index (ft_font->ft_face, _hb_remap_arabic_pua2 (unicode)); + break; + } if (!g) return false; } diff --git a/test/shape/data/in-house/tests/arabic-fallback-shaping.tests b/test/shape/data/in-house/tests/arabic-fallback-shaping.tests index 9bec506eb..c3a0e984f 100644 --- a/test/shape/data/in-house/tests/arabic-fallback-shaping.tests +++ b/test/shape/data/in-house/tests/arabic-fallback-shaping.tests @@ -1,11 +1,11 @@ ../fonts/df768b9c257e0c9c35786c47cae15c46571d56be.ttf;;U+0633,U+064F,U+0644,U+064E,U+0651,U+0627,U+0651,U+0650,U+0645,U+062A,U+06CC;[uni06CC.fina=10+1655|uni062A.medi=9+868|uni0645.init=8+1098|uni0650=2@148,0+0|uni0651=2@187,736+0|uni064E=2@883,1259+0|uni0651=2@922,736+0|uni06440627.fina=2+1470|uni064F=0@629,-10+0|uni0633.init=0+1585] -../fonts/SimpArabicTest.ttf;--font-funcs=ot;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[daggerdbl=31+584|c142=30+276|twosuperior=28@130,0+0|bracketleft=28+515|c=27+240|quotedblbase=26+216|J=25+289|parenright=24+391|twosuperior=22@166,-236+0|Eacute=22+587|logicalnot=20@127,-87+0|dagger=20+509|registered=18@137,-97+0|bracketleft=18+515|logicalnot=15@-7,261+0|plusminus=15@-49,-97+0|c=15+240|quotedblbase=14+216|J=13+289|parenright=12+391|guilsinglleft=11+599|quotedblbase=10+216|quotedblbase=9+216|J=8+289|parenright=7+391|parenright=6+391|twosuperior=4@165,-316+0|daggerdbl=4+584|registered=2@276,-102+0|j=2+793|twosuperior=0@-11,-196+0|R=0+232] -../fonts/SimpArabicTest.ttf;--font-funcs=ot;U+0020,U+0644,U+0627,U+0020,U+0644,U+0623,U+0020,U+0644,U+064E,U+0623,U+064E,U+0020,U+0623,U+064E,U+0646,U+062A;[U=15+693|DEL=14+227|logicalnot=12@17,307+0|L=12+289|parenright=11+391|logicalnot=7@41,267+0|logicalnot=7@378,267+0|brokenbar=7+674|parenright=6+391|brokenbar=4+674|parenright=3+391|yen=1+709|parenright=0+391] -../fonts/SimpArabicTest.ttf;--font-funcs=ot;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[asterisk=0+269|plus=1+408|comma=2+509|hyphen=3+509|period=4+573|slash=5+572|zero=6+572|one=7+300|parenright=8+391|two=9+300|three=10+551|four=11+572|five=12+283|seven=13+268|eight=14+372|C=15+268|D=16+295|E=17+175|F=18+572|G=19+175|H=20+485|d=21+329|f=22+329|six=23+322|plus=24+408] -../fonts/SimpArabicTest.ttf;--font-funcs=ot;U+061F,U+003F,U+0640;[H=0+485|H=1+485|h=2+171] -../fonts/SimpArabicTest.ttf;--font-funcs=ot;U+0628,U+0644,U+0627,U+0020,U+0628,U+0644,U+0625;[ordfeminine=5+674|R=4+232|parenright=3+391|yen=1+709|R=0+232] -../fonts/TradArabicTest.ttf;--font-funcs=ot;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[fnmeem=31+1069|midya=30+499|kasrah2=28@151,0+0|inhaa=28+1341|fnra=27+702|inlam=26+358|alef=25+444|righttoleftspace=24+468|kasrah2=22@110,-604+0|fnnoon=22+1259|fathah2=18@-145,-168+0|sukun2=18@760,-166+0|f29b=18+1497|fathah2=15@-168,56+0|shaddah2=15@-51,-416+0|fnra=15+702|inlam=14+358|alef=13+444|righttoleftspace=12+468|fnha=11+776|midlam=10+403|inlam=9+358|alef=8+444|righttoleftspace=7+468|righttoleftspace=6+468|kasrah2=4@15,-1102+0|fnmeem=4+1069|sukun2=2@220,-386+0|midseen=2+1163|kasrah2=0@-324,-403+0|inbaa=0+389] -../fonts/TradArabicTest.ttf;--font-funcs=ot;U+0020,U+0644,U+0627,U+0020,U+0644,U+0623,U+0020,U+0644,U+064E,U+0623,U+064E,U+0020,U+0623,U+064E,U+0646,U+062A;[fntaa=15+1808|innoon=14+389|fathah2=12@-279,883+0|hamzahonalef=12+479|righttoleftspace=11+468|fathah2=7@-190,862+0|fathah2=7@468,862+0|hamzahonlamelef=7+1316|righttoleftspace=6+468|hamzahonlamelef=4+1316|righttoleftspace=3+468|lamelef=1+1316|righttoleftspace=0+468] -../fonts/TradArabicTest.ttf;--font-funcs=ot;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[greater=0+481|question=1+559|at=2+849|A=3+849|percentarabic=4+1353|C=5+927|D=6+1196|E=7+855|righttoleftspace=8+468|F=9+855|G=10+884|H=11+1083|commaarabic=12+755|K=13+649|L=14+704|W=15+450|semicolonarabic=16+755|.notdef=17+745|Z=18+1128|.notdef=19+745|questionarabic=20+845|x=21+739|z=22+739|J=23+753|question=24+559] -../fonts/TradArabicTest.ttf;--font-funcs=ot;U+061F,U+003F,U+0640;[questionarabic=0+845|questionarabic=1+845|tatweelnarrow=2+378] -../fonts/TradArabicTest.ttf;--font-funcs=ot;U+0644,U+0645,U+0020,U+0628,U+0645,U+0627;[fnalef=5+468|f296=3+897|righttoleftspace=2+468|f205=0+903] +../fonts/SimpArabicTest.ttf;;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[daggerdbl=31+584|c142=30+276|twosuperior=28@130,0+0|bracketleft=28+515|c=27+240|quotedblbase=26+216|J=25+289|parenright=24+391|twosuperior=22@166,-236+0|Eacute=22+587|logicalnot=20@127,-87+0|dagger=20+509|registered=18@137,-97+0|bracketleft=18+515|logicalnot=15@-7,261+0|plusminus=15@-49,-97+0|c=15+240|quotedblbase=14+216|J=13+289|parenright=12+391|guilsinglleft=11+599|quotedblbase=10+216|quotedblbase=9+216|J=8+289|parenright=7+391|parenright=6+391|twosuperior=4@165,-316+0|daggerdbl=4+584|registered=2@276,-102+0|j=2+793|twosuperior=0@-11,-196+0|R=0+232] +../fonts/SimpArabicTest.ttf;;U+0020,U+0644,U+0627,U+0020,U+0644,U+0623,U+0020,U+0644,U+064E,U+0623,U+064E,U+0020,U+0623,U+064E,U+0646,U+062A;[U=15+693|DEL=14+227|logicalnot=12@17,307+0|L=12+289|parenright=11+391|logicalnot=7@41,267+0|logicalnot=7@378,267+0|brokenbar=7+674|parenright=6+391|brokenbar=4+674|parenright=3+391|yen=1+709|parenright=0+391] +../fonts/SimpArabicTest.ttf;;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[asterisk=0+269|plus=1+408|comma=2+509|hyphen=3+509|period=4+573|slash=5+572|zero=6+572|one=7+300|parenright=8+391|two=9+300|three=10+551|four=11+572|five=12+283|seven=13+268|eight=14+372|C=15+268|D=16+295|E=17+175|F=18+572|G=19+175|H=20+485|d=21+329|f=22+329|six=23+322|plus=24+408] +../fonts/SimpArabicTest.ttf;;U+061F,U+003F,U+0640;[H=0+485|H=1+485|h=2+171] +../fonts/SimpArabicTest.ttf;;U+0628,U+0644,U+0627,U+0020,U+0628,U+0644,U+0625;[ordfeminine=5+674|R=4+232|parenright=3+391|yen=1+709|R=0+232] +../fonts/TradArabicTest.ttf;;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[fnmeem=31+1069|midya=30+499|kasrah2=28@151,0+0|inhaa=28+1341|fnra=27+702|inlam=26+358|alef=25+444|righttoleftspace=24+468|kasrah2=22@110,-604+0|fnnoon=22+1259|fathah2=18@-145,-168+0|sukun2=18@760,-166+0|f29b=18+1497|fathah2=15@-168,56+0|shaddah2=15@-51,-416+0|fnra=15+702|inlam=14+358|alef=13+444|righttoleftspace=12+468|fnha=11+776|midlam=10+403|inlam=9+358|alef=8+444|righttoleftspace=7+468|righttoleftspace=6+468|kasrah2=4@15,-1102+0|fnmeem=4+1069|sukun2=2@220,-386+0|midseen=2+1163|kasrah2=0@-324,-403+0|inbaa=0+389] +../fonts/TradArabicTest.ttf;;U+0020,U+0644,U+0627,U+0020,U+0644,U+0623,U+0020,U+0644,U+064E,U+0623,U+064E,U+0020,U+0623,U+064E,U+0646,U+062A;[fntaa=15+1808|innoon=14+389|fathah2=12@-279,883+0|hamzahonalef=12+479|righttoleftspace=11+468|fathah2=7@-190,862+0|fathah2=7@468,862+0|hamzahonlamelef=7+1316|righttoleftspace=6+468|hamzahonlamelef=4+1316|righttoleftspace=3+468|lamelef=1+1316|righttoleftspace=0+468] +../fonts/TradArabicTest.ttf;;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[greater=0+481|question=1+559|at=2+849|A=3+849|percentarabic=4+1353|C=5+927|D=6+1196|E=7+855|righttoleftspace=8+468|F=9+855|G=10+884|H=11+1083|commaarabic=12+755|K=13+649|L=14+704|W=15+450|semicolonarabic=16+755|.notdef=17+745|Z=18+1128|.notdef=19+745|questionarabic=20+845|x=21+739|z=22+739|J=23+753|question=24+559] +../fonts/TradArabicTest.ttf;;U+061F,U+003F,U+0640;[questionarabic=0+845|questionarabic=1+845|tatweelnarrow=2+378] +../fonts/TradArabicTest.ttf;;U+0644,U+0645,U+0020,U+0628,U+0645,U+0627;[fnalef=5+468|f296=3+897|righttoleftspace=2+468|f205=0+903] From dfc5e5a27dce6e95c523fcb6ad997f18e771801c Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 18 Jun 2022 14:00:30 +0200 Subject: [PATCH 04/19] [test] Skip glyph positions for test failing on CI We are not interested in glyph positioning for this test, and the FreeType version on some CI machines is giving some different glyph advances here. --- test/shape/data/in-house/tests/arabic-fallback-shaping.tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/shape/data/in-house/tests/arabic-fallback-shaping.tests b/test/shape/data/in-house/tests/arabic-fallback-shaping.tests index c3a0e984f..9581d5986 100644 --- a/test/shape/data/in-house/tests/arabic-fallback-shaping.tests +++ b/test/shape/data/in-house/tests/arabic-fallback-shaping.tests @@ -1,5 +1,5 @@ ../fonts/df768b9c257e0c9c35786c47cae15c46571d56be.ttf;;U+0633,U+064F,U+0644,U+064E,U+0651,U+0627,U+0651,U+0650,U+0645,U+062A,U+06CC;[uni06CC.fina=10+1655|uni062A.medi=9+868|uni0645.init=8+1098|uni0650=2@148,0+0|uni0651=2@187,736+0|uni064E=2@883,1259+0|uni0651=2@922,736+0|uni06440627.fina=2+1470|uni064F=0@629,-10+0|uni0633.init=0+1585] -../fonts/SimpArabicTest.ttf;;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[daggerdbl=31+584|c142=30+276|twosuperior=28@130,0+0|bracketleft=28+515|c=27+240|quotedblbase=26+216|J=25+289|parenright=24+391|twosuperior=22@166,-236+0|Eacute=22+587|logicalnot=20@127,-87+0|dagger=20+509|registered=18@137,-97+0|bracketleft=18+515|logicalnot=15@-7,261+0|plusminus=15@-49,-97+0|c=15+240|quotedblbase=14+216|J=13+289|parenright=12+391|guilsinglleft=11+599|quotedblbase=10+216|quotedblbase=9+216|J=8+289|parenright=7+391|parenright=6+391|twosuperior=4@165,-316+0|daggerdbl=4+584|registered=2@276,-102+0|j=2+793|twosuperior=0@-11,-196+0|R=0+232] +../fonts/SimpArabicTest.ttf;--no-positions;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[daggerdbl=31|c142=30|twosuperior=28|bracketleft=28|c=27|quotedblbase=26|J=25|parenright=24|twosuperior=22|Eacute=22|logicalnot=20|dagger=20|registered=18|bracketleft=18|logicalnot=15|plusminus=15|c=15|quotedblbase=14|J=13|parenright=12|guilsinglleft=11|quotedblbase=10|quotedblbase=9|J=8|parenright=7|parenright=6|twosuperior=4|daggerdbl=4|registered=2|j=2|twosuperior=0|R=0] ../fonts/SimpArabicTest.ttf;;U+0020,U+0644,U+0627,U+0020,U+0644,U+0623,U+0020,U+0644,U+064E,U+0623,U+064E,U+0020,U+0623,U+064E,U+0646,U+062A;[U=15+693|DEL=14+227|logicalnot=12@17,307+0|L=12+289|parenright=11+391|logicalnot=7@41,267+0|logicalnot=7@378,267+0|brokenbar=7+674|parenright=6+391|brokenbar=4+674|parenright=3+391|yen=1+709|parenright=0+391] ../fonts/SimpArabicTest.ttf;;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[asterisk=0+269|plus=1+408|comma=2+509|hyphen=3+509|period=4+573|slash=5+572|zero=6+572|one=7+300|parenright=8+391|two=9+300|three=10+551|four=11+572|five=12+283|seven=13+268|eight=14+372|C=15+268|D=16+295|E=17+175|F=18+572|G=19+175|H=20+485|d=21+329|f=22+329|six=23+322|plus=24+408] ../fonts/SimpArabicTest.ttf;;U+061F,U+003F,U+0640;[H=0+485|H=1+485|h=2+171] From 6e29060af2e4490e67e24ec2ef5172541275a855 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 18 Jun 2022 15:34:40 +0200 Subject: [PATCH 05/19] [arabic] Add mapping files for the PUA encoding Unused right now. --- src/ArabicPUA1.txt | 250 ++++++++++++++++++++++++++++++++++++++ src/ArabicPUA2.txt | 295 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 545 insertions(+) create mode 100644 src/ArabicPUA1.txt create mode 100644 src/ArabicPUA2.txt diff --git a/src/ArabicPUA1.txt b/src/ArabicPUA1.txt new file mode 100644 index 000000000..a74ef266f --- /dev/null +++ b/src/ArabicPUA1.txt @@ -0,0 +1,250 @@ +# +# Name: Legacy Simplified Arabic encoding +# +# Format: Three tab-separated columns +# Column #1 is the PUA code (in hex as 0xXXXX) +# Column #2 is the Unicode (in hex as 0xXXXX) +# Column #3 is the Unicode name (follows a comment sign, '#') +# +# The entries are in PUA order +# +0xF100 0x063B # ARABIC LETTER KEHEH WITH TWO DOTS ABOVE +0xF100 0x063C # ARABIC LETTER KEHEH WITH THREE DOTS BELOW +0xF100 0x063D # ARABIC LETTER FARSI YEH WITH INVERTED V +0xF100 0x063E # ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE +0xF100 0x063F # ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE +0xF100 0x0653 # ARABIC MADDAH ABOVE +0xF100 0x0654 # ARABIC HAMZA ABOVE +0xF100 0x0655 # ARABIC HAMZA BELOW +0xF100 0x0656 # ARABIC SUBSCRIPT ALEF +0xF100 0x0657 # ARABIC INVERTED DAMMA +0xF100 0x0658 # ARABIC MARK NOON GHUNNA +0xF100 0x0659 # ARABIC ZWARAKAY +0xF100 0x065A # ARABIC VOWEL SIGN SMALL V ABOVE +0xF100 0x065B # ARABIC VOWEL SIGN INVERTED SMALL V ABOVE +0xF100 0x065C # ARABIC VOWEL SIGN DOT BELOW +0xF100 0x065D # ARABIC REVERSED DAMMA +0xF100 0x065E # ARABIC FATHA WITH TWO DOTS +0xF10C 0x200C # ZERO WIDTH NON-JOINER +0xF10D 0x200D # ZERO WIDTH JOINER +0xF10E 0x200E # LEFT-TO-RIGHT MARK +0xF10F 0x200F # RIGHT-TO-LEFT MARK +0xF120 0x0020 # SPACE +0xF121 0x0021 # EXCLAMATION MARK +0xF122 0x0022 # QUOTATION MARK +0xF123 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +0xF124 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +0xF125 0x0025 # PERCENT SIGN +0xF126 0x00D7 # MULTIPLICATION SIGN +0xF127 0x00F7 # DIVISION SIGN +0xF128 0x0028 # LEFT PARENTHESIS +0xF129 0x0029 # RIGHT PARENTHESIS +0xF12A 0x002A # ASTERISK +0xF12B 0x002B # PLUS SIGN +0xF12C 0x060C # ARABIC COMMA +0xF12D 0x002D # HYPHEN-MINUS +0xF12E 0x002E # FULL STOP +0xF12F 0x002F # SOLIDUS +0xF130 0x0660 # ARABIC-INDIC DIGIT ZERO +0xF131 0x0661 # ARABIC-INDIC DIGIT ONE +0xF132 0x0662 # ARABIC-INDIC DIGIT TWO +0xF133 0x0663 # ARABIC-INDIC DIGIT THREE +0xF134 0x0664 # ARABIC-INDIC DIGIT FOUR +0xF135 0x0665 # ARABIC-INDIC DIGIT FIVE +0xF136 0x0666 # ARABIC-INDIC DIGIT SIX +0xF137 0x0667 # ARABIC-INDIC DIGIT SEVEN +0xF138 0x0668 # ARABIC-INDIC DIGIT EIGHT +0xF139 0x0669 # ARABIC-INDIC DIGIT NINE +0xF13A 0x003A # COLON +0xF13B 0x003B # SEMICOLON +0xF13B 0x061B # ARABIC SEMICOLON +0xF13C 0x2018 # LEFT SINGLE QUOTATION MARK +0xF13D 0x003D # EQUALS SIGN +0xF13E 0x2019 # RIGHT SINGLE QUOTATION MARK +0xF13F 0x003F # QUESTION MARK +0xF13F 0x061F # ARABIC QUESTION MARK +0xF141 0x0627 # ARABIC LETTER ALEF +0xF141 0xFE8D # ARABIC LETTER ALEF ISOLATED FORM +0xF142 0xFE8E # ARABIC LETTER ALEF FINAL FORM +0xF143 0x0623 # ARABIC LETTER ALEF WITH HAMZA ABOVE +0xF143 0xFE83 # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM +0xF144 0xFE84 # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM +0xF145 0x0622 # ARABIC LETTER ALEF WITH MADDA ABOVE +0xF145 0xFE81 # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM +0xF146 0xFE82 # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM +0xF147 0x0625 # ARABIC LETTER ALEF WITH HAMZA BELOW +0xF147 0xFE87 # ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM +0xF148 0xFE88 # ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM +0xF149 0xFE91 # ARABIC LETTER BEH INITIAL FORM +0xF149 0xFE92 # ARABIC LETTER BEH MEDIAL FORM +0xF14A 0x0628 # ARABIC LETTER BEH +0xF14A 0xFE8F # ARABIC LETTER BEH ISOLATED FORM +0xF14A 0xFE90 # ARABIC LETTER BEH FINAL FORM +0xF14B 0xFE97 # ARABIC LETTER TEH INITIAL FORM +0xF14B 0xFE98 # ARABIC LETTER TEH MEDIAL FORM +0xF14C 0x062A # ARABIC LETTER TEH +0xF14C 0xFE95 # ARABIC LETTER TEH ISOLATED FORM +0xF14C 0xFE96 # ARABIC LETTER TEH FINAL FORM +0xF14D 0xFE9B # ARABIC LETTER THEH INITIAL FORM +0xF14D 0xFE9C # ARABIC LETTER THEH MEDIAL FORM +0xF14E 0x062B # ARABIC LETTER THEH +0xF14E 0xFE99 # ARABIC LETTER THEH ISOLATED FORM +0xF14E 0xFE9A # ARABIC LETTER THEH FINAL FORM +0xF14F 0xFE9F # ARABIC LETTER JEEM INITIAL FORM +0xF14F 0xFEA0 # ARABIC LETTER JEEM MEDIAL FORM +0xF150 0xFE9E # ARABIC LETTER JEEM FINAL FORM +0xF151 0x062C # ARABIC LETTER JEEM +0xF151 0xFE9D # ARABIC LETTER JEEM ISOLATED FORM +0xF152 0xFEA3 # ARABIC LETTER HAH INITIAL FORM +0xF152 0xFEA4 # ARABIC LETTER HAH MEDIAL FORM +0xF153 0xFEA2 # ARABIC LETTER HAH FINAL FORM +0xF154 0x062D # ARABIC LETTER HAH +0xF154 0xFEA1 # ARABIC LETTER HAH ISOLATED FORM +0xF155 0xFEA7 # ARABIC LETTER KHAH INITIAL FORM +0xF155 0xFEA8 # ARABIC LETTER KHAH MEDIAL FORM +0xF156 0xFEA6 # ARABIC LETTER KHAH FINAL FORM +0xF157 0x062E # ARABIC LETTER KHAH +0xF157 0xFEA5 # ARABIC LETTER KHAH ISOLATED FORM +0xF158 0x062F # ARABIC LETTER DAL +0xF158 0xFEA9 # ARABIC LETTER DAL ISOLATED FORM +0xF158 0xFEAA # ARABIC LETTER DAL FINAL FORM +0xF159 0x0630 # ARABIC LETTER THAL +0xF159 0xFEAB # ARABIC LETTER THAL ISOLATED FORM +0xF159 0xFEAC # ARABIC LETTER THAL FINAL FORM +0xF15A 0x0631 # ARABIC LETTER REH +0xF15A 0xFEAD # ARABIC LETTER REH ISOLATED FORM +0xF15A 0xFEAE # ARABIC LETTER REH FINAL FORM +0xF15B 0x005B # LEFT SQUARE BRACKET +0xF15C 0x005C # REVERSE SOLIDUS +0xF15D 0x005D # RIGHT SQUARE BRACKET +0xF15E 0x002C # COMMA +0xF15E 0x066B # ARABIC DECIMAL SEPARATOR +0xF15E 0x066C # ARABIC THOUSANDS SEPARATOR +0xF15F 0x0640 # ARABIC TATWEEL +0xF160 0x0632 # ARABIC LETTER ZAIN +0xF160 0xFEAF # ARABIC LETTER ZAIN ISOLATED FORM +0xF160 0xFEB0 # ARABIC LETTER ZAIN FINAL FORM +0xF161 0xFEB3 # ARABIC LETTER SEEN INITIAL FORM +0xF161 0xFEB4 # ARABIC LETTER SEEN MEDIAL FORM +0xF162 0x0633 # ARABIC LETTER SEEN +0xF162 0xFEB1 # ARABIC LETTER SEEN ISOLATED FORM +0xF162 0xFEB2 # ARABIC LETTER SEEN FINAL FORM +0xF163 0xFEB7 # ARABIC LETTER SHEEN INITIAL FORM +0xF163 0xFEB8 # ARABIC LETTER SHEEN MEDIAL FORM +0xF164 0x0634 # ARABIC LETTER SHEEN +0xF164 0xFEB5 # ARABIC LETTER SHEEN ISOLATED FORM +0xF164 0xFEB6 # ARABIC LETTER SHEEN FINAL FORM +0xF165 0xFEBB # ARABIC LETTER SAD INITIAL FORM +0xF165 0xFEBC # ARABIC LETTER SAD MEDIAL FORM +0xF166 0x0635 # ARABIC LETTER SAD +0xF166 0xFEB9 # ARABIC LETTER SAD ISOLATED FORM +0xF166 0xFEBA # ARABIC LETTER SAD FINAL FORM +0xF167 0xFEBF # ARABIC LETTER DAD INITIAL FORM +0xF167 0xFEC0 # ARABIC LETTER DAD MEDIAL FORM +0xF168 0x0636 # ARABIC LETTER DAD +0xF168 0xFEBD # ARABIC LETTER DAD ISOLATED FORM +0xF168 0xFEBE # ARABIC LETTER DAD FINAL FORM +0xF169 0x0637 # ARABIC LETTER TAH +0xF169 0xFEC1 # ARABIC LETTER TAH ISOLATED FORM +0xF169 0xFEC2 # ARABIC LETTER TAH FINAL FORM +0xF169 0xFEC3 # ARABIC LETTER TAH INITIAL FORM +0xF169 0xFEC4 # ARABIC LETTER TAH MEDIAL FORM +0xF16A 0x0638 # ARABIC LETTER ZAH +0xF16A 0xFEC5 # ARABIC LETTER ZAH ISOLATED FORM +0xF16A 0xFEC6 # ARABIC LETTER ZAH FINAL FORM +0xF16A 0xFEC7 # ARABIC LETTER ZAH INITIAL FORM +0xF16A 0xFEC8 # ARABIC LETTER ZAH MEDIAL FORM +0xF16B 0xFECB # ARABIC LETTER AIN INITIAL FORM +0xF16C 0xFECC # ARABIC LETTER AIN MEDIAL FORM +0xF16D 0xFECA # ARABIC LETTER AIN FINAL FORM +0xF16E 0x0639 # ARABIC LETTER AIN +0xF16E 0xFEC9 # ARABIC LETTER AIN ISOLATED FORM +0xF16F 0xFECF # ARABIC LETTER GHAIN INITIAL FORM +0xF170 0xFED0 # ARABIC LETTER GHAIN MEDIAL FORM +0xF171 0xFECE # ARABIC LETTER GHAIN FINAL FORM +0xF172 0x063A # ARABIC LETTER GHAIN +0xF172 0xFECD # ARABIC LETTER GHAIN ISOLATED FORM +0xF173 0xFED3 # ARABIC LETTER FEH INITIAL FORM +0xF174 0xFED4 # ARABIC LETTER FEH MEDIAL FORM +0xF175 0x0641 # ARABIC LETTER FEH +0xF175 0xFED1 # ARABIC LETTER FEH ISOLATED FORM +0xF175 0xFED2 # ARABIC LETTER FEH FINAL FORM +0xF176 0xFED7 # ARABIC LETTER QAF INITIAL FORM +0xF177 0xFED8 # ARABIC LETTER QAF MEDIAL FORM +0xF178 0x0642 # ARABIC LETTER QAF +0xF178 0xFED5 # ARABIC LETTER QAF ISOLATED FORM +0xF178 0xFED6 # ARABIC LETTER QAF FINAL FORM +0xF179 0xFEDB # ARABIC LETTER KAF INITIAL FORM +0xF179 0xFEDC # ARABIC LETTER KAF MEDIAL FORM +0xF17A 0x0643 # ARABIC LETTER KAF +0xF17A 0xFED9 # ARABIC LETTER KAF ISOLATED FORM +0xF17A 0xFEDA # ARABIC LETTER KAF FINAL FORM +0xF17B 0xFEDF # ARABIC LETTER LAM INITIAL FORM +0xF17B 0xFEE0 # ARABIC LETTER LAM MEDIAL FORM +0xF17C 0x0644 # ARABIC LETTER LAM +0xF17C 0xFEDD # ARABIC LETTER LAM ISOLATED FORM +0xF17C 0xFEDE # ARABIC LETTER LAM FINAL FORM +0xF17D 0xFEE3 # ARABIC LETTER MEEM INITIAL FORM +0xF17D 0xFEE4 # ARABIC LETTER MEEM MEDIAL FORM +0xF17E 0x0645 # ARABIC LETTER MEEM +0xF17E 0xFEE1 # ARABIC LETTER MEEM ISOLATED FORM +0xF17E 0xFEE2 # ARABIC LETTER MEEM FINAL FORM +0xF17F 0xFEE7 # ARABIC LETTER NOON INITIAL FORM +0xF17F 0xFEE8 # ARABIC LETTER NOON MEDIAL FORM +0xF1A1 0xFEEB # ARABIC LETTER HEH INITIAL FORM +0xF1A2 0xFEEC # ARABIC LETTER HEH MEDIAL FORM +0xF1A3 0xFEEA # ARABIC LETTER HEH FINAL FORM +0xF1A4 0x0647 # ARABIC LETTER HEH +0xF1A4 0xFEE9 # ARABIC LETTER HEH ISOLATED FORM +0xF1A5 0x0648 # ARABIC LETTER WAW +0xF1A5 0xFEED # ARABIC LETTER WAW ISOLATED FORM +0xF1A5 0xFEEE # ARABIC LETTER WAW FINAL FORM +0xF1A6 0xFEF3 # ARABIC LETTER YEH INITIAL FORM +0xF1A6 0xFEF4 # ARABIC LETTER YEH MEDIAL FORM +0xF1A7 0xFEF2 # ARABIC LETTER YEH FINAL FORM +0xF1A8 0x064A # ARABIC LETTER YEH +0xF1A8 0xFEF1 # ARABIC LETTER YEH ISOLATED FORM +0xF1A9 0x0629 # ARABIC LETTER TEH MARBUTA +0xF1A9 0xFE93 # ARABIC LETTER TEH MARBUTA ISOLATED FORM +0xF1AA 0xFE94 # ARABIC LETTER TEH MARBUTA FINAL FORM +0xF1AB 0xFEF0 # ARABIC LETTER ALEF MAKSURA FINAL FORM +0xF1AC 0x0649 # ARABIC LETTER ALEF MAKSURA +0xF1AC 0xFEEF # ARABIC LETTER ALEF MAKSURA ISOLATED FORM +0xF1AD 0x0621 # ARABIC LETTER HAMZA +0xF1AE 0xFE8B # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM +0xF1AE 0xFE8C # ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM +0xF1AF 0xFE8A # ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM +0xF1B0 0x0030 # DIGIT ZERO +0xF1B1 0x0031 # DIGIT ONE +0xF1B2 0x0032 # DIGIT TWO +0xF1B3 0x0033 # DIGIT THREE +0xF1B4 0x0034 # DIGIT FOUR +0xF1B5 0x0035 # DIGIT FIVE +0xF1B6 0x0036 # DIGIT SIX +0xF1B7 0x0037 # DIGIT SEVEN +0xF1B8 0x0038 # DIGIT EIGHT +0xF1B9 0x0039 # DIGIT NINE +0xF1BA 0x0626 # ARABIC LETTER YEH WITH HAMZA ABOVE +0xF1BA 0xFE89 # ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM +0xF1BB 0x0624 # ARABIC LETTER WAW WITH HAMZA ABOVE +0xF1BB 0xFE85 # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM +0xF1BB 0xFE86 # ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM +0xF1BC 0xFEFC # ARABIC LIGATURE LAM WITH ALEF FINAL FORM +0xF1BD 0xFEFB # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM +0xF1BE 0xFEF7 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM +0xF1BF 0xFEF8 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM +0xF1C0 0xFEF5 # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM +0xF1C1 0xFEF6 # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM +0xF1C2 0xFEF9 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM +0xF1C3 0xFEFA # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM +0xF1C4 0x064E # ARABIC FATHA +0xF1C5 0x064F # ARABIC DAMMA +0xF1C6 0x0652 # ARABIC SUKUN +0xF1C7 0x064B # ARABIC FATHATAN +0xF1C8 0x064C # ARABIC DAMMATAN +0xF1C9 0x0651 # ARABIC SHADDA +0xF1CA 0x0650 # ARABIC KASRA +0xF1CB 0x064D # ARABIC KASRATAN +0xF1E1 0x0646 # ARABIC LETTER NOON +0xF1E1 0xFEE5 # ARABIC LETTER NOON ISOLATED FORM +0xF1E1 0xFEE6 # ARABIC LETTER NOON FINAL FORM diff --git a/src/ArabicPUA2.txt b/src/ArabicPUA2.txt new file mode 100644 index 000000000..e14b383c9 --- /dev/null +++ b/src/ArabicPUA2.txt @@ -0,0 +1,295 @@ +# +# Name: Legacy Traditional Arabic encoding +# +# Format: Three tab-separated columns +# Column #1 is the PUA code (in hex as 0xXXXX) +# Column #2 is the Unicode (in hex as 0xXXXX) +# Column #3 is the Unicode name (follows a comment sign, '#') +# +# The entries are in PUA order +# +0xF200 0x063B # ARABIC LETTER KEHEH WITH TWO DOTS ABOVE +0xF200 0x063C # ARABIC LETTER KEHEH WITH THREE DOTS BELOW +0xF200 0x063D # ARABIC LETTER FARSI YEH WITH INVERTED V +0xF200 0x063E # ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE +0xF200 0x063F # ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE +0xF200 0x0653 # ARABIC MADDAH ABOVE +0xF200 0x0654 # ARABIC HAMZA ABOVE +0xF200 0x0655 # ARABIC HAMZA BELOW +0xF200 0x0656 # ARABIC SUBSCRIPT ALEF +0xF200 0x0657 # ARABIC INVERTED DAMMA +0xF200 0x0658 # ARABIC MARK NOON GHUNNA +0xF200 0x0659 # ARABIC ZWARAKAY +0xF200 0x065A # ARABIC VOWEL SIGN SMALL V ABOVE +0xF200 0x065B # ARABIC VOWEL SIGN INVERTED SMALL V ABOVE +0xF200 0x065C # ARABIC VOWEL SIGN DOT BELOW +0xF200 0x065D # ARABIC REVERSED DAMMA +0xF200 0x065E # ARABIC FATHA WITH TWO DOTS +0xF202 0xFC08 # ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM +0xF203 0xFC0E # ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM +0xF204 0xFC12 # ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM +0xF205 0xFC42 # ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM +0xF206 0xFC4E # ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM +0xF20C 0x200C # ZERO WIDTH NON-JOINER +0xF20D 0x200D # ZERO WIDTH JOINER +0xF20E 0x200E # LEFT-TO-RIGHT MARK +0xF20F 0x200F # RIGHT-TO-LEFT MARK +0xF210 0xFD88 # ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM +0xF212 0xFC3F # ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM +0xF213 0xFC40 # ARABIC LIGATURE LAM WITH HAH ISOLATED FORM +0xF214 0xFC41 # ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM +0xF215 0xFC6A # ARABIC LIGATURE BEH WITH REH FINAL FORM +0xF216 0xFC70 # ARABIC LIGATURE TEH WITH REH FINAL FORM +0xF217 0xFC91 # ARABIC LIGATURE YEH WITH REH FINAL FORM +0xF218 0xFCB0 # ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM +0xF219 0xFD30 # ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM +0xF21A 0xFCCD # ARABIC LIGATURE LAM WITH HEH INITIAL FORM +0xF21C 0xFC44 # ARABIC LIGATURE LAM WITH YEH ISOLATED FORM +0xF21D 0xFC0A # ARABIC LIGATURE BEH WITH YEH ISOLATED FORM +0xF21E 0xFC10 # ARABIC LIGATURE TEH WITH YEH ISOLATED FORM +0xF21F 0xFC50 # ARABIC LIGATURE NOON WITH YEH ISOLATED FORM +0xF220 0x0020 # SPACE +0xF221 0x0021 # EXCLAMATION MARK +0xF222 0x0022 # QUOTATION MARK +0xF223 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +0xF224 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +0xF225 0x0025 # PERCENT SIGN +0xF226 0x00D7 # MULTIPLICATION SIGN +0xF227 0x00F7 # DIVISION SIGN +0xF228 0x0028 # LEFT PARENTHESIS +0xF229 0x0029 # RIGHT PARENTHESIS +0xF22A 0x002A # ASTERISK +0xF22B 0x002B # PLUS SIGN +0xF22C 0x060C # ARABIC COMMA +0xF22D 0x002D # HYPHEN-MINUS +0xF22E 0x002E # FULL STOP +0xF22F 0x002F # SOLIDUS +0xF230 0x0660 # ARABIC-INDIC DIGIT ZERO +0xF231 0x0661 # ARABIC-INDIC DIGIT ONE +0xF232 0x0662 # ARABIC-INDIC DIGIT TWO +0xF233 0x0663 # ARABIC-INDIC DIGIT THREE +0xF234 0x0664 # ARABIC-INDIC DIGIT FOUR +0xF235 0x0665 # ARABIC-INDIC DIGIT FIVE +0xF236 0x0666 # ARABIC-INDIC DIGIT SIX +0xF237 0x0667 # ARABIC-INDIC DIGIT SEVEN +0xF238 0x0668 # ARABIC-INDIC DIGIT EIGHT +0xF239 0x0669 # ARABIC-INDIC DIGIT NINE +0xF23A 0x003A # COLON +0xF23B 0x003B # SEMICOLON +0xF23B 0x061B # ARABIC SEMICOLON +0xF23C 0x201C # LEFT DOUBLE QUOTATION MARK +0xF23D 0x003D # EQUALS SIGN +0xF23E 0x201D # RIGHT DOUBLE QUOTATION MARK +0xF23F 0x003F # QUESTION MARK +0xF23F 0x061F # ARABIC QUESTION MARK +0xF241 0x0627 # ARABIC LETTER ALEF +0xF241 0xFE8D # ARABIC LETTER ALEF ISOLATED FORM +0xF242 0xFE8E # ARABIC LETTER ALEF FINAL FORM +0xF243 0x0623 # ARABIC LETTER ALEF WITH HAMZA ABOVE +0xF243 0xFE83 # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM +0xF244 0xFE84 # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM +0xF245 0x0622 # ARABIC LETTER ALEF WITH MADDA ABOVE +0xF245 0xFE81 # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM +0xF246 0xFE82 # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM +0xF247 0x0625 # ARABIC LETTER ALEF WITH HAMZA BELOW +0xF247 0xFE87 # ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM +0xF248 0xFE88 # ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM +0xF249 0xFE91 # ARABIC LETTER BEH INITIAL FORM +0xF24A 0xFE92 # ARABIC LETTER BEH MEDIAL FORM +0xF24B 0xFE90 # ARABIC LETTER BEH FINAL FORM +0xF24C 0x0628 # ARABIC LETTER BEH +0xF24C 0xFE8F # ARABIC LETTER BEH ISOLATED FORM +0xF24D 0xFE97 # ARABIC LETTER TEH INITIAL FORM +0xF24E 0xFE98 # ARABIC LETTER TEH MEDIAL FORM +0xF24F 0xFE96 # ARABIC LETTER TEH FINAL FORM +0xF250 0x062A # ARABIC LETTER TEH +0xF250 0xFE95 # ARABIC LETTER TEH ISOLATED FORM +0xF251 0xFE9B # ARABIC LETTER THEH INITIAL FORM +0xF252 0xFE9C # ARABIC LETTER THEH MEDIAL FORM +0xF253 0xFE9A # ARABIC LETTER THEH FINAL FORM +0xF254 0x062B # ARABIC LETTER THEH +0xF254 0xFE99 # ARABIC LETTER THEH ISOLATED FORM +0xF255 0xFE9F # ARABIC LETTER JEEM INITIAL FORM +0xF256 0xFEA0 # ARABIC LETTER JEEM MEDIAL FORM +0xF257 0xFE9E # ARABIC LETTER JEEM FINAL FORM +0xF258 0x062C # ARABIC LETTER JEEM +0xF258 0xFE9D # ARABIC LETTER JEEM ISOLATED FORM +0xF259 0xFEA3 # ARABIC LETTER HAH INITIAL FORM +0xF25A 0xFEA4 # ARABIC LETTER HAH MEDIAL FORM +0xF25B 0x005B # LEFT SQUARE BRACKET +0xF25C 0xFEA2 # ARABIC LETTER HAH FINAL FORM +0xF25D 0x005D # RIGHT SQUARE BRACKET +0xF25E 0x002C # COMMA +0xF25E 0x066B # ARABIC DECIMAL SEPARATOR +0xF25E 0x066C # ARABIC THOUSANDS SEPARATOR +0xF25F 0x0640 # ARABIC TATWEEL +0xF260 0x062D # ARABIC LETTER HAH +0xF260 0xFEA1 # ARABIC LETTER HAH ISOLATED FORM +0xF261 0xFEA7 # ARABIC LETTER KHAH INITIAL FORM +0xF262 0xFEA8 # ARABIC LETTER KHAH MEDIAL FORM +0xF263 0xFEA6 # ARABIC LETTER KHAH FINAL FORM +0xF264 0x062E # ARABIC LETTER KHAH +0xF264 0xFEA5 # ARABIC LETTER KHAH ISOLATED FORM +0xF265 0x062F # ARABIC LETTER DAL +0xF265 0xFEA9 # ARABIC LETTER DAL ISOLATED FORM +0xF266 0xFEAA # ARABIC LETTER DAL FINAL FORM +0xF267 0x0630 # ARABIC LETTER THAL +0xF267 0xFEAB # ARABIC LETTER THAL ISOLATED FORM +0xF268 0xFEAC # ARABIC LETTER THAL FINAL FORM +0xF269 0x0631 # ARABIC LETTER REH +0xF269 0xFEAD # ARABIC LETTER REH ISOLATED FORM +0xF26A 0xFEAE # ARABIC LETTER REH FINAL FORM +0xF26B 0x0632 # ARABIC LETTER ZAIN +0xF26B 0xFEAF # ARABIC LETTER ZAIN ISOLATED FORM +0xF26C 0xFEB0 # ARABIC LETTER ZAIN FINAL FORM +0xF26D 0xFEB3 # ARABIC LETTER SEEN INITIAL FORM +0xF26E 0xFEB4 # ARABIC LETTER SEEN MEDIAL FORM +0xF26F 0xFEB2 # ARABIC LETTER SEEN FINAL FORM +0xF270 0x0633 # ARABIC LETTER SEEN +0xF270 0xFEB1 # ARABIC LETTER SEEN ISOLATED FORM +0xF271 0xFEB7 # ARABIC LETTER SHEEN INITIAL FORM +0xF272 0xFEB8 # ARABIC LETTER SHEEN MEDIAL FORM +0xF273 0xFEB6 # ARABIC LETTER SHEEN FINAL FORM +0xF274 0x0634 # ARABIC LETTER SHEEN +0xF274 0xFEB5 # ARABIC LETTER SHEEN ISOLATED FORM +0xF275 0xFEBB # ARABIC LETTER SAD INITIAL FORM +0xF276 0xFEBC # ARABIC LETTER SAD MEDIAL FORM +0xF277 0xFEBA # ARABIC LETTER SAD FINAL FORM +0xF278 0x0635 # ARABIC LETTER SAD +0xF278 0xFEB9 # ARABIC LETTER SAD ISOLATED FORM +0xF279 0xFEBF # ARABIC LETTER DAD INITIAL FORM +0xF27A 0xFEC0 # ARABIC LETTER DAD MEDIAL FORM +0xF27B 0xFD3E # ORNATE LEFT PARENTHESIS +0xF27C 0xFEBE # ARABIC LETTER DAD FINAL FORM +0xF27D 0xFD3F # ORNATE RIGHT PARENTHESIS +0xF27E 0x0636 # ARABIC LETTER DAD +0xF27E 0xFEBD # ARABIC LETTER DAD ISOLATED FORM +0xF27F 0xFEC3 # ARABIC LETTER TAH INITIAL FORM +0xF280 0xFC9C # ARABIC LIGATURE BEH WITH JEEM INITIAL FORM +0xF281 0xFC9D # ARABIC LIGATURE BEH WITH HAH INITIAL FORM +0xF282 0xFC9E # ARABIC LIGATURE BEH WITH KHAH INITIAL FORM +0xF283 0xFCA1 # ARABIC LIGATURE TEH WITH JEEM INITIAL FORM +0xF284 0xFCA2 # ARABIC LIGATURE TEH WITH HAH INITIAL FORM +0xF285 0xFCA3 # ARABIC LIGATURE TEH WITH KHAH INITIAL FORM +0xF286 0xFCC9 # ARABIC LIGATURE LAM WITH JEEM INITIAL FORM +0xF287 0xFCCA # ARABIC LIGATURE LAM WITH HAH INITIAL FORM +0xF288 0xFCCB # ARABIC LIGATURE LAM WITH KHAH INITIAL FORM +0xF289 0xFCCE # ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM +0xF28A 0xFCCF # ARABIC LIGATURE MEEM WITH HAH INITIAL FORM +0xF28B 0xFCD0 # ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM +0xF28D 0xFCD2 # ARABIC LIGATURE NOON WITH JEEM INITIAL FORM +0xF28E 0xFCD3 # ARABIC LIGATURE NOON WITH HAH INITIAL FORM +0xF28F 0xFCDA # ARABIC LIGATURE YEH WITH JEEM INITIAL FORM +0xF290 0xFCDB # ARABIC LIGATURE YEH WITH HAH INITIAL FORM +0xF291 0xFCDC # ARABIC LIGATURE YEH WITH KHAH INITIAL FORM +0xF292 0xFC6D # ARABIC LIGATURE BEH WITH NOON FINAL FORM +0xF293 0xFC73 # ARABIC LIGATURE TEH WITH NOON FINAL FORM +0xF294 0xFC94 # ARABIC LIGATURE YEH WITH NOON FINAL FORM +0xF295 0xFC86 # ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM +0xF296 0xFC9F # ARABIC LIGATURE BEH WITH MEEM INITIAL FORM +0xF297 0xFCA4 # ARABIC LIGATURE TEH WITH MEEM INITIAL FORM +0xF298 0xFCD5 # ARABIC LIGATURE NOON WITH MEEM INITIAL FORM +0xF299 0xFCDD # ARABIC LIGATURE YEH WITH MEEM INITIAL FORM +0xF29A 0xFCA8 # ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM +0xF29B 0xFCAA # ARABIC LIGATURE HAH WITH MEEM INITIAL FORM +0xF29C 0xFCAC # ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM +0xF29D 0xFCCC # ARABIC LIGATURE LAM WITH MEEM INITIAL FORM +0xF29E 0xFCD1 # ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM +0xF29F 0xFC32 # ARABIC LIGATURE FEH WITH YEH ISOLATED FORM +0xF2A1 0xFEC2 # ARABIC LETTER TAH FINAL FORM +0xF2A2 0x0637 # ARABIC LETTER TAH +0xF2A2 0xFEC1 # ARABIC LETTER TAH ISOLATED FORM +0xF2A3 0x0638 # ARABIC LETTER ZAH +0xF2A3 0xFEC7 # ARABIC LETTER ZAH INITIAL FORM +0xF2A4 0xFEC8 # ARABIC LETTER ZAH MEDIAL FORM +0xF2A5 0xFEC6 # ARABIC LETTER ZAH FINAL FORM +0xF2A6 0xFEC5 # ARABIC LETTER ZAH ISOLATED FORM +0xF2A7 0xFECB # ARABIC LETTER AIN INITIAL FORM +0xF2A8 0xFECC # ARABIC LETTER AIN MEDIAL FORM +0xF2A9 0xFECA # ARABIC LETTER AIN FINAL FORM +0xF2AA 0x0639 # ARABIC LETTER AIN +0xF2AA 0xFEC9 # ARABIC LETTER AIN ISOLATED FORM +0xF2AB 0xFECF # ARABIC LETTER GHAIN INITIAL FORM +0xF2AC 0xFED0 # ARABIC LETTER GHAIN MEDIAL FORM +0xF2AD 0xFECE # ARABIC LETTER GHAIN FINAL FORM +0xF2AE 0x063A # ARABIC LETTER GHAIN +0xF2AE 0xFECD # ARABIC LETTER GHAIN ISOLATED FORM +0xF2AF 0xFED3 # ARABIC LETTER FEH INITIAL FORM +0xF2B0 0xFED4 # ARABIC LETTER FEH MEDIAL FORM +0xF2B1 0xFED2 # ARABIC LETTER FEH FINAL FORM +0xF2B2 0x0641 # ARABIC LETTER FEH +0xF2B2 0xFED1 # ARABIC LETTER FEH ISOLATED FORM +0xF2B3 0xFED7 # ARABIC LETTER QAF INITIAL FORM +0xF2B4 0xFED8 # ARABIC LETTER QAF MEDIAL FORM +0xF2B5 0xFED6 # ARABIC LETTER QAF FINAL FORM +0xF2B6 0x0642 # ARABIC LETTER QAF +0xF2B6 0xFED5 # ARABIC LETTER QAF ISOLATED FORM +0xF2B7 0xFEDB # ARABIC LETTER KAF INITIAL FORM +0xF2B8 0xFEDC # ARABIC LETTER KAF MEDIAL FORM +0xF2B9 0xFEDA # ARABIC LETTER KAF FINAL FORM +0xF2BA 0x0643 # ARABIC LETTER KAF +0xF2BA 0xFED9 # ARABIC LETTER KAF ISOLATED FORM +0xF2BB 0xFEDF # ARABIC LETTER LAM INITIAL FORM +0xF2BC 0xFEE0 # ARABIC LETTER LAM MEDIAL FORM +0xF2BD 0xFEDE # ARABIC LETTER LAM FINAL FORM +0xF2BE 0x0644 # ARABIC LETTER LAM +0xF2BE 0xFEDD # ARABIC LETTER LAM ISOLATED FORM +0xF2BF 0xFEE3 # ARABIC LETTER MEEM INITIAL FORM +0xF2C0 0xFEE4 # ARABIC LETTER MEEM MEDIAL FORM +0xF2C1 0xFEE2 # ARABIC LETTER MEEM FINAL FORM +0xF2C2 0x0645 # ARABIC LETTER MEEM +0xF2C2 0xFEE1 # ARABIC LETTER MEEM ISOLATED FORM +0xF2C3 0xFEE7 # ARABIC LETTER NOON INITIAL FORM +0xF2C4 0xFEE8 # ARABIC LETTER NOON MEDIAL FORM +0xF2C5 0xFEE6 # ARABIC LETTER NOON FINAL FORM +0xF2C6 0x0646 # ARABIC LETTER NOON +0xF2C6 0xFEE5 # ARABIC LETTER NOON ISOLATED FORM +0xF2C7 0xFEEB # ARABIC LETTER HEH INITIAL FORM +0xF2C8 0xFEEC # ARABIC LETTER HEH MEDIAL FORM +0xF2C9 0xFEEA # ARABIC LETTER HEH FINAL FORM +0xF2CA 0x0647 # ARABIC LETTER HEH +0xF2CA 0xFEE9 # ARABIC LETTER HEH ISOLATED FORM +0xF2CB 0x0648 # ARABIC LETTER WAW +0xF2CB 0xFEED # ARABIC LETTER WAW ISOLATED FORM +0xF2CC 0xFEEE # ARABIC LETTER WAW FINAL FORM +0xF2CD 0xFEF3 # ARABIC LETTER YEH INITIAL FORM +0xF2CE 0xFEF4 # ARABIC LETTER YEH MEDIAL FORM +0xF2CF 0xFEF2 # ARABIC LETTER YEH FINAL FORM +0xF2D0 0x064A # ARABIC LETTER YEH +0xF2D0 0xFEF1 # ARABIC LETTER YEH ISOLATED FORM +0xF2D1 0x0629 # ARABIC LETTER TEH MARBUTA +0xF2D1 0xFE93 # ARABIC LETTER TEH MARBUTA ISOLATED FORM +0xF2D2 0xFE94 # ARABIC LETTER TEH MARBUTA FINAL FORM +0xF2D3 0xFEF0 # ARABIC LETTER ALEF MAKSURA FINAL FORM +0xF2D4 0x0649 # ARABIC LETTER ALEF MAKSURA +0xF2D4 0xFEEF # ARABIC LETTER ALEF MAKSURA ISOLATED FORM +0xF2D5 0x0621 # ARABIC LETTER HAMZA +0xF2D6 0xFE8B # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM +0xF2D7 0xFE8C # ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM +0xF2D8 0xFE8A # ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM +0xF2D9 0x0626 # ARABIC LETTER YEH WITH HAMZA ABOVE +0xF2D9 0xFE89 # ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM +0xF2DA 0x0624 # ARABIC LETTER WAW WITH HAMZA ABOVE +0xF2DA 0xFE85 # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM +0xF2DB 0xFE86 # ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM +0xF2DC 0xFEFB # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM +0xF2DD 0xFEFC # ARABIC LIGATURE LAM WITH ALEF FINAL FORM +0xF2DE 0xFEF7 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM +0xF2DF 0xFEF8 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM +0xF2E0 0xFEF5 # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM +0xF2E1 0xFEF6 # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM +0xF2E2 0xFEF9 # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM +0xF2E3 0xFEFA # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM +0xF2E4 0x064E # ARABIC FATHA +0xF2E5 0x064F # ARABIC DAMMA +0xF2E6 0x0652 # ARABIC SUKUN +0xF2E7 0x064B # ARABIC FATHATAN +0xF2E8 0x064C # ARABIC DAMMATAN +0xF2E9 0x0651 # ARABIC SHADDA +0xF2EA 0x0650 # ARABIC KASRA +0xF2EB 0x064D # ARABIC KASRATAN +0xF2EC 0xFC60 # ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM +0xF2ED 0xFC61 # ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM +0xF2EF 0xFC5E # ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM +0xF2F0 0xFC62 # ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM +0xF2F1 0xFEC4 # ARABIC LETTER TAH MEDIAL FORM From 7f362196c5b7ed2856e310f41999092e07d82281 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Sat, 18 Jun 2022 20:28:43 +0200 Subject: [PATCH 06/19] [arabic] Split ligature array Generate marks and 3-component ligatures in separate arrays. The new arrays are unused currently. --- src/gen-arabic-table.py | 102 +++++++++++++++++++++++++------ src/hb-ot-shaper-arabic-table.hh | 42 ++++++++++--- 2 files changed, 117 insertions(+), 27 deletions(-) diff --git a/src/gen-arabic-table.py b/src/gen-arabic-table.py index 7bb49693b..0be00faa7 100755 --- a/src/gen-arabic-table.py +++ b/src/gen-arabic-table.py @@ -195,7 +195,7 @@ def print_shaping_table(f): items = items[:0:-1] shape = None # We only care about a subset of ligatures - if c not in LIGATURES or len (items) != 2: + if c not in LIGATURES: continue # Save ligature @@ -231,24 +231,45 @@ def print_shaping_table(f): print ("#define SHAPING_TABLE_LAST 0x%04Xu" % max_u) print () - ligas = {} - for pair in ligatures.keys (): - for shape in ligatures[pair]: - c = ligatures[pair][shape] - if shape is None: - liga = pair - elif shape == 'isolated': - liga = (shapes[pair[0]]['initial'], shapes[pair[1]]['final']) - elif shape == 'final': - liga = (shapes[pair[0]]['medial'], shapes[pair[1]]['final']) - elif shape == 'initial': - liga = (shapes[pair[0]]['initial'], shapes[pair[1]]['medial']) + ligas_2 = {} + ligas_3 = {} + ligas_mark_2 = {} + for key in ligatures.keys (): + for shape in ligatures[key]: + c = ligatures[key][shape] + if len(key) == 3: + if shape == 'isolated': + liga = (shapes[key[0]]['initial'], shapes[key[1]]['medial'], shapes[key[2]]['final']) + elif shape == 'final': + liga = (shapes[key[0]]['medial'], shapes[key[1]]['medial'], shapes[key[2]]['final']) + elif shape == 'initial': + liga = (shapes[key[0]]['initial'], shapes[key[1]]['medial'], shapes[key[2]]['medial']) + else: + raise Exception ("Unexpected shape", shape) + if liga[0] not in ligas_3: + ligas_3[liga[0]] = [] + ligas_3[liga[0]].append ((liga[1], liga[2], c)) + elif len(key) == 2: + if shape is None: + liga = key + if liga[0] not in ligas_mark_2: + ligas_mark_2[liga[0]] = [] + ligas_mark_2[liga[0]].append ((liga[1], c)) + continue + elif shape == 'isolated': + liga = (shapes[key[0]]['initial'], shapes[key[1]]['final']) + elif shape == 'final': + liga = (shapes[key[0]]['medial'], shapes[key[1]]['final']) + elif shape == 'initial': + liga = (shapes[key[0]]['initial'], shapes[key[1]]['medial']) + else: + raise Exception ("Unexpected shape", shape) + if liga[0] not in ligas_2: + ligas_2[liga[0]] = [] + ligas_2[liga[0]].append ((liga[1], c)) else: - raise Exception ("Unexpected shape", shape) - if liga[0] not in ligas: - ligas[liga[0]] = [] - ligas[liga[0]].append ((liga[1], c)) - max_i = max (len (ligas[l]) for l in ligas) + raise Exception ("Unexpected number of ligature components", key) + max_i = max (len (ligas_2[l]) for l in ligas_2) print () print ("static const struct ligature_set_t {") print (" uint16_t first;") @@ -258,16 +279,57 @@ def print_shaping_table(f): print (" } ligatures[%d];" % max_i) print ("} ligature_table[] =") print ("{") - for first in sorted (ligas.keys ()): + for first in sorted (ligas_2.keys ()): print (" { 0x%04Xu, {" % (first)) - for liga in ligas[first]: + for liga in ligas_2[first]: print (" { 0x%04Xu, 0x%04Xu }, /* %s */" % (liga[0], liga[1], names[liga[1]])) print (" }},") print ("};") print () + max_i = max (len (ligas_mark_2[l]) for l in ligas_mark_2) + print () + print ("static const struct ligature_mark_set_t {") + print (" uint16_t first;") + print (" struct ligature_pairs_t {") + print (" uint16_t second;") + print (" uint16_t ligature;") + print (" } ligatures[%d];" % max_i) + print ("} ligature_mark_table[] =") + print ("{") + for first in sorted (ligas_mark_2.keys ()): + + print (" { 0x%04Xu, {" % (first)) + for liga in ligas_mark_2[first]: + print (" { 0x%04Xu, 0x%04Xu }, /* %s */" % (liga[0], liga[1], names[liga[1]])) + print (" }},") + + print ("};") + print () + + max_i = max (len (ligas_3[l]) for l in ligas_3) + print () + print ("static const struct ligature_3_set_t {") + print (" uint16_t first;") + print (" struct ligature_triplets_t {") + print (" uint16_t second;") + print (" uint16_t third;") + print (" uint16_t ligature;") + print (" } ligatures[%d];" % max_i) + print ("} ligature_3_table[] =") + print ("{") + for first in sorted (ligas_3.keys ()): + + print (" { 0x%04Xu, {" % (first)) + for liga in ligas_3[first]: + print (" { 0x%04Xu, 0x%04Xu, 0x%04Xu}, /* %s */" % (liga[0], liga[1], liga[2], names[liga[2]])) + print (" }},") + + print ("};") + print () + print ("/* == Start of generated table == */") diff --git a/src/hb-ot-shaper-arabic-table.hh b/src/hb-ot-shaper-arabic-table.hh index b0b65e0a3..a817e4123 100644 --- a/src/hb-ot-shaper-arabic-table.hh +++ b/src/hb-ot-shaper-arabic-table.hh @@ -421,13 +421,6 @@ static const struct ligature_set_t { } ligatures[14]; } ligature_table[] = { - { 0x0651u, { - { 0x064Cu, 0xFC5Eu }, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */ - { 0x064Eu, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */ - { 0x064Fu, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */ - { 0x0650u, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */ - { 0x064Bu, 0xF2EEu }, /* PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM */ - }}, { 0xFE91u, { { 0xFEE2u, 0xFC08u }, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */ { 0xFEE4u, 0xFC9Fu }, /* ARABIC LIGATURE BEH WITH MEEM INITIAL FORM */ @@ -524,6 +517,41 @@ static const struct ligature_set_t { }; +static const struct ligature_mark_set_t { + uint16_t first; + struct ligature_pairs_t { + uint16_t second; + uint16_t ligature; + } ligatures[5]; +} ligature_mark_table[] = +{ + { 0x0651u, { + { 0x064Cu, 0xFC5Eu }, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */ + { 0x064Eu, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */ + { 0x064Fu, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */ + { 0x0650u, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */ + { 0x064Bu, 0xF2EEu }, /* PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM */ + }}, +}; + + +static const struct ligature_3_set_t { + uint16_t first; + struct ligature_triplets_t { + uint16_t second; + uint16_t third; + uint16_t ligature; + } ligatures[3]; +} ligature_3_table[] = +{ + { 0xFEDFu, { + { 0xFEE4u, 0xFEA4u, 0xFD88u}, /* ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM */ + { 0xFEE0u, 0xFEEAu, 0xF201u}, /* PUA ARABIC LIGATURE LELLAH ISOLATED FORM */ + { 0xFEE4u, 0xFEA0u, 0xF211u}, /* PUA ARABIC LIGATURE LAM WITH MEEM WITH JEEM INITIAL FORM */ + }}, +}; + + #endif /* HB_OT_SHAPER_ARABIC_TABLE_HH */ /* == End of generated table == */ From 16c23713523f3c55bf24caabccb816becc8cc5af Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 13:25:46 -0600 Subject: [PATCH 07/19] [arabick-fallback] Apply mark ligatures --- src/hb-ot-shaper-arabic-fallback.hh | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index 491bc8901..0667898b7 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -34,14 +34,19 @@ /* Features ordered the same as the entries in shaping_table rows, - * followed by rlig. Don't change. */ + * followed by rlig. Don't change. + * + * We currently support one subtable per lookup, and one lookup + * per feature. But we allow duplicate features, so we use that! + */ static const hb_tag_t arabic_fallback_features[] = { HB_TAG('i','n','i','t'), HB_TAG('m','e','d','i'), HB_TAG('f','i','n','a'), HB_TAG('i','s','o','l'), - HB_TAG('r','l','i','g'), + HB_TAG('r','l','i','g'), // Main ligatures + HB_TAG('r','l','i','g'), // Mark ligatures }; static OT::SubstLookup * @@ -95,9 +100,12 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS return ret && !c.in_error () ? c.copy () : nullptr; } +template static OT::SubstLookup * arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font) + hb_font_t *font, + const T &ligature_table, + unsigned lookup_flags) { OT::HBGlyphID16 first_glyphs[ARRAY_LENGTH_CONST (ligature_table)]; unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)]; @@ -161,7 +169,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN hb_serialize_context_t c (buf, sizeof (buf)); OT::SubstLookup *lookup = c.start_serialize (); bool ret = lookup->serialize_ligature (&c, - OT::LookupFlag::IgnoreMarks, + lookup_flags, hb_sorted_array (first_glyphs, num_first_glyphs), hb_array (ligature_per_first_glyph_count_list, num_first_glyphs), hb_array (ligature_list, num_ligatures), @@ -180,10 +188,16 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan, if (feature_index < 4) return arabic_fallback_synthesize_lookup_single (plan, font, feature_index); else - return arabic_fallback_synthesize_lookup_ligature (plan, font); + { + switch (feature_index) { + case 4: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_table, OT::LookupFlag::IgnoreMarks); + case 5: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_mark_table, 0); + } + } + assert (false); } -#define ARABIC_FALLBACK_MAX_LOOKUPS 5 +#define ARABIC_FALLBACK_MAX_LOOKUPS ARRAY_LENGTH_CONST (arabic_fallback_features) struct arabic_fallback_plan_t { @@ -262,7 +276,7 @@ arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan, const hb_ot_shape_plan_t *plan, hb_font_t *font) { - static_assert ((ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), ""); + static_assert ((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++) { From 8978a18f31ca297e342cbac9caab486bbe2597d3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 13:25:46 -0600 Subject: [PATCH 08/19] [arabick-fallback] Apply mark ligatures --- test/shape/data/in-house/tests/arabic-fallback-shaping.tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/shape/data/in-house/tests/arabic-fallback-shaping.tests b/test/shape/data/in-house/tests/arabic-fallback-shaping.tests index 9581d5986..eb5d30583 100644 --- a/test/shape/data/in-house/tests/arabic-fallback-shaping.tests +++ b/test/shape/data/in-house/tests/arabic-fallback-shaping.tests @@ -4,7 +4,7 @@ ../fonts/SimpArabicTest.ttf;;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[asterisk=0+269|plus=1+408|comma=2+509|hyphen=3+509|period=4+573|slash=5+572|zero=6+572|one=7+300|parenright=8+391|two=9+300|three=10+551|four=11+572|five=12+283|seven=13+268|eight=14+372|C=15+268|D=16+295|E=17+175|F=18+572|G=19+175|H=20+485|d=21+329|f=22+329|six=23+322|plus=24+408] ../fonts/SimpArabicTest.ttf;;U+061F,U+003F,U+0640;[H=0+485|H=1+485|h=2+171] ../fonts/SimpArabicTest.ttf;;U+0628,U+0644,U+0627,U+0020,U+0628,U+0644,U+0625;[ordfeminine=5+674|R=4+232|parenright=3+391|yen=1+709|R=0+232] -../fonts/TradArabicTest.ttf;;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[fnmeem=31+1069|midya=30+499|kasrah2=28@151,0+0|inhaa=28+1341|fnra=27+702|inlam=26+358|alef=25+444|righttoleftspace=24+468|kasrah2=22@110,-604+0|fnnoon=22+1259|fathah2=18@-145,-168+0|sukun2=18@760,-166+0|f29b=18+1497|fathah2=15@-168,56+0|shaddah2=15@-51,-416+0|fnra=15+702|inlam=14+358|alef=13+444|righttoleftspace=12+468|fnha=11+776|midlam=10+403|inlam=9+358|alef=8+444|righttoleftspace=7+468|righttoleftspace=6+468|kasrah2=4@15,-1102+0|fnmeem=4+1069|sukun2=2@220,-386+0|midseen=2+1163|kasrah2=0@-324,-403+0|inbaa=0+389] +../fonts/TradArabicTest.ttf;;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[fnmeem=31+1069|midya=30+499|kasrah2=28@151,0+0|inhaa=28+1341|fnra=27+702|inlam=26+358|alef=25+444|righttoleftspace=24+468|kasrah2=22@110,-604+0|fnnoon=22+1259|fathah2=18@-145,-168+0|sukun2=18@760,-166+0|f29b=18+1497|fahtanonshaddah2=15@-51,-416+0|fnra=15+702|inlam=14+358|alef=13+444|righttoleftspace=12+468|fnha=11+776|midlam=10+403|inlam=9+358|alef=8+444|righttoleftspace=7+468|righttoleftspace=6+468|kasrah2=4@15,-1102+0|fnmeem=4+1069|sukun2=2@220,-386+0|midseen=2+1163|kasrah2=0@-324,-403+0|inbaa=0+389] ../fonts/TradArabicTest.ttf;;U+0020,U+0644,U+0627,U+0020,U+0644,U+0623,U+0020,U+0644,U+064E,U+0623,U+064E,U+0020,U+0623,U+064E,U+0646,U+062A;[fntaa=15+1808|innoon=14+389|fathah2=12@-279,883+0|hamzahonalef=12+479|righttoleftspace=11+468|fathah2=7@-190,862+0|fathah2=7@468,862+0|hamzahonlamelef=7+1316|righttoleftspace=6+468|hamzahonlamelef=4+1316|righttoleftspace=3+468|lamelef=1+1316|righttoleftspace=0+468] ../fonts/TradArabicTest.ttf;;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[greater=0+481|question=1+559|at=2+849|A=3+849|percentarabic=4+1353|C=5+927|D=6+1196|E=7+855|righttoleftspace=8+468|F=9+855|G=10+884|H=11+1083|commaarabic=12+755|K=13+649|L=14+704|W=15+450|semicolonarabic=16+755|.notdef=17+745|Z=18+1128|.notdef=19+745|questionarabic=20+845|x=21+739|z=22+739|J=23+753|question=24+559] ../fonts/TradArabicTest.ttf;;U+061F,U+003F,U+0640;[questionarabic=0+845|questionarabic=1+845|tatweelnarrow=2+378] From d86effa4a68138bb813fae056aebbb90d1af6b23 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 13:41:30 -0600 Subject: [PATCH 09/19] [arabic-fallback] Rename; towards supporting 3-letter ligatures --- src/gen-arabic-table.py | 13 ++- src/hb-ot-shaper-arabic-fallback.hh | 2 +- src/hb-ot-shaper-arabic-table.hh | 137 ++++++++++++++-------------- 3 files changed, 75 insertions(+), 77 deletions(-) diff --git a/src/gen-arabic-table.py b/src/gen-arabic-table.py index 0be00faa7..8278d7d69 100755 --- a/src/gen-arabic-table.py +++ b/src/gen-arabic-table.py @@ -274,7 +274,7 @@ def print_shaping_table(f): print ("static const struct ligature_set_t {") print (" uint16_t first;") print (" struct ligature_pairs_t {") - print (" uint16_t second;") + print (" uint16_t components[1];") print (" uint16_t ligature;") print (" } ligatures[%d];" % max_i) print ("} ligature_table[] =") @@ -283,7 +283,7 @@ def print_shaping_table(f): print (" { 0x%04Xu, {" % (first)) for liga in ligas_2[first]: - print (" { 0x%04Xu, 0x%04Xu }, /* %s */" % (liga[0], liga[1], names[liga[1]])) + print (" { {0x%04Xu}, 0x%04Xu }, /* %s */" % (liga[0], liga[1], names[liga[1]])) print (" }},") print ("};") @@ -294,7 +294,7 @@ def print_shaping_table(f): print ("static const struct ligature_mark_set_t {") print (" uint16_t first;") print (" struct ligature_pairs_t {") - print (" uint16_t second;") + print (" uint16_t components[1];") print (" uint16_t ligature;") print (" } ligatures[%d];" % max_i) print ("} ligature_mark_table[] =") @@ -303,7 +303,7 @@ def print_shaping_table(f): print (" { 0x%04Xu, {" % (first)) for liga in ligas_mark_2[first]: - print (" { 0x%04Xu, 0x%04Xu }, /* %s */" % (liga[0], liga[1], names[liga[1]])) + print (" { {0x%04Xu}, 0x%04Xu }, /* %s */" % (liga[0], liga[1], names[liga[1]])) print (" }},") print ("};") @@ -314,8 +314,7 @@ def print_shaping_table(f): print ("static const struct ligature_3_set_t {") print (" uint16_t first;") print (" struct ligature_triplets_t {") - print (" uint16_t second;") - print (" uint16_t third;") + print (" uint16_t components[2];") print (" uint16_t ligature;") print (" } ligatures[%d];" % max_i) print ("} ligature_3_table[] =") @@ -324,7 +323,7 @@ def print_shaping_table(f): print (" { 0x%04Xu, {" % (first)) for liga in ligas_3[first]: - print (" { 0x%04Xu, 0x%04Xu, 0x%04Xu}, /* %s */" % (liga[0], liga[1], liga[2], names[liga[2]])) + print (" { {0x%04Xu, 0x%04Xu}, 0x%04Xu}, /* %s */" % (liga[0], liga[1], liga[2], names[liga[2]])) print (" }},") print ("};") diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index 0667898b7..fc7b8a4a8 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -143,7 +143,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++) { - hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].second; + hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].components[0]; hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].ligature; hb_codepoint_t second_glyph, ligature_glyph; if (!second_u || diff --git a/src/hb-ot-shaper-arabic-table.hh b/src/hb-ot-shaper-arabic-table.hh index a817e4123..fd3d8645d 100644 --- a/src/hb-ot-shaper-arabic-table.hh +++ b/src/hb-ot-shaper-arabic-table.hh @@ -416,103 +416,103 @@ static const uint16_t shaping_table[][4] = static const struct ligature_set_t { uint16_t first; struct ligature_pairs_t { - uint16_t second; + uint16_t components[1]; uint16_t ligature; } ligatures[14]; } ligature_table[] = { { 0xFE91u, { - { 0xFEE2u, 0xFC08u }, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */ - { 0xFEE4u, 0xFC9Fu }, /* ARABIC LIGATURE BEH WITH MEEM INITIAL FORM */ - { 0xFEA0u, 0xFC9Cu }, /* ARABIC LIGATURE BEH WITH JEEM INITIAL FORM */ - { 0xFEA4u, 0xFC9Du }, /* ARABIC LIGATURE BEH WITH HAH INITIAL FORM */ - { 0xFEA8u, 0xFC9Eu }, /* ARABIC LIGATURE BEH WITH KHAH INITIAL FORM */ + { {0xFEE2u}, 0xFC08u }, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */ + { {0xFEE4u}, 0xFC9Fu }, /* ARABIC LIGATURE BEH WITH MEEM INITIAL FORM */ + { {0xFEA0u}, 0xFC9Cu }, /* ARABIC LIGATURE BEH WITH JEEM INITIAL FORM */ + { {0xFEA4u}, 0xFC9Du }, /* ARABIC LIGATURE BEH WITH HAH INITIAL FORM */ + { {0xFEA8u}, 0xFC9Eu }, /* ARABIC LIGATURE BEH WITH KHAH INITIAL FORM */ }}, { 0xFE92u, { - { 0xFEAEu, 0xFC6Au }, /* ARABIC LIGATURE BEH WITH REH FINAL FORM */ - { 0xFEE6u, 0xFC6Du }, /* ARABIC LIGATURE BEH WITH NOON FINAL FORM */ - { 0xFEF2u, 0xFC6Fu }, /* ARABIC LIGATURE BEH WITH YEH FINAL FORM */ + { {0xFEAEu}, 0xFC6Au }, /* ARABIC LIGATURE BEH WITH REH FINAL FORM */ + { {0xFEE6u}, 0xFC6Du }, /* ARABIC LIGATURE BEH WITH NOON FINAL FORM */ + { {0xFEF2u}, 0xFC6Fu }, /* ARABIC LIGATURE BEH WITH YEH FINAL FORM */ }}, { 0xFE97u, { - { 0xFEE2u, 0xFC0Eu }, /* ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM */ - { 0xFEE4u, 0xFCA4u }, /* ARABIC LIGATURE TEH WITH MEEM INITIAL FORM */ - { 0xFEA0u, 0xFCA1u }, /* ARABIC LIGATURE TEH WITH JEEM INITIAL FORM */ - { 0xFEA4u, 0xFCA2u }, /* ARABIC LIGATURE TEH WITH HAH INITIAL FORM */ - { 0xFEA8u, 0xFCA3u }, /* ARABIC LIGATURE TEH WITH KHAH INITIAL FORM */ + { {0xFEE2u}, 0xFC0Eu }, /* ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM */ + { {0xFEE4u}, 0xFCA4u }, /* ARABIC LIGATURE TEH WITH MEEM INITIAL FORM */ + { {0xFEA0u}, 0xFCA1u }, /* ARABIC LIGATURE TEH WITH JEEM INITIAL FORM */ + { {0xFEA4u}, 0xFCA2u }, /* ARABIC LIGATURE TEH WITH HAH INITIAL FORM */ + { {0xFEA8u}, 0xFCA3u }, /* ARABIC LIGATURE TEH WITH KHAH INITIAL FORM */ }}, { 0xFE98u, { - { 0xFEAEu, 0xFC70u }, /* ARABIC LIGATURE TEH WITH REH FINAL FORM */ - { 0xFEE6u, 0xFC73u }, /* ARABIC LIGATURE TEH WITH NOON FINAL FORM */ - { 0xFEF2u, 0xFC75u }, /* ARABIC LIGATURE TEH WITH YEH FINAL FORM */ + { {0xFEAEu}, 0xFC70u }, /* ARABIC LIGATURE TEH WITH REH FINAL FORM */ + { {0xFEE6u}, 0xFC73u }, /* ARABIC LIGATURE TEH WITH NOON FINAL FORM */ + { {0xFEF2u}, 0xFC75u }, /* ARABIC LIGATURE TEH WITH YEH FINAL FORM */ }}, { 0xFE9Bu, { - { 0xFEE2u, 0xFC12u }, /* ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM */ + { {0xFEE2u}, 0xFC12u }, /* ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM */ }}, { 0xFE9Fu, { - { 0xFEE4u, 0xFCA8u }, /* ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM */ + { {0xFEE4u}, 0xFCA8u }, /* ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM */ }}, { 0xFEA3u, { - { 0xFEE4u, 0xFCAAu }, /* ARABIC LIGATURE HAH WITH MEEM INITIAL FORM */ + { {0xFEE4u}, 0xFCAAu }, /* ARABIC LIGATURE HAH WITH MEEM INITIAL FORM */ }}, { 0xFEA7u, { - { 0xFEE4u, 0xFCACu }, /* ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM */ + { {0xFEE4u}, 0xFCACu }, /* ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM */ }}, { 0xFEB3u, { - { 0xFEE4u, 0xFCB0u }, /* ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM */ + { {0xFEE4u}, 0xFCB0u }, /* ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM */ }}, { 0xFEB7u, { - { 0xFEE4u, 0xFD30u }, /* ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM */ + { {0xFEE4u}, 0xFD30u }, /* ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM */ }}, { 0xFED3u, { - { 0xFEF2u, 0xFC32u }, /* ARABIC LIGATURE FEH WITH YEH ISOLATED FORM */ + { {0xFEF2u}, 0xFC32u }, /* ARABIC LIGATURE FEH WITH YEH ISOLATED FORM */ }}, { 0xFEDFu, { - { 0xFE9Eu, 0xFC3Fu }, /* ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM */ - { 0xFEA0u, 0xFCC9u }, /* ARABIC LIGATURE LAM WITH JEEM INITIAL FORM */ - { 0xFEA2u, 0xFC40u }, /* ARABIC LIGATURE LAM WITH HAH ISOLATED FORM */ - { 0xFEA4u, 0xFCCAu }, /* ARABIC LIGATURE LAM WITH HAH INITIAL FORM */ - { 0xFEA6u, 0xFC41u }, /* ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM */ - { 0xFEA8u, 0xFCCBu }, /* ARABIC LIGATURE LAM WITH KHAH INITIAL FORM */ - { 0xFEE2u, 0xFC42u }, /* ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM */ - { 0xFEE4u, 0xFCCCu }, /* ARABIC LIGATURE LAM WITH MEEM INITIAL FORM */ - { 0xFEF2u, 0xFC44u }, /* ARABIC LIGATURE LAM WITH YEH ISOLATED FORM */ - { 0xFEECu, 0xFCCDu }, /* ARABIC LIGATURE LAM WITH HEH INITIAL FORM */ - { 0xFE82u, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */ - { 0xFE84u, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */ - { 0xFE88u, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */ - { 0xFE8Eu, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */ + { {0xFE9Eu}, 0xFC3Fu }, /* ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM */ + { {0xFEA0u}, 0xFCC9u }, /* ARABIC LIGATURE LAM WITH JEEM INITIAL FORM */ + { {0xFEA2u}, 0xFC40u }, /* ARABIC LIGATURE LAM WITH HAH ISOLATED FORM */ + { {0xFEA4u}, 0xFCCAu }, /* ARABIC LIGATURE LAM WITH HAH INITIAL FORM */ + { {0xFEA6u}, 0xFC41u }, /* ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM */ + { {0xFEA8u}, 0xFCCBu }, /* ARABIC LIGATURE LAM WITH KHAH INITIAL FORM */ + { {0xFEE2u}, 0xFC42u }, /* ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM */ + { {0xFEE4u}, 0xFCCCu }, /* ARABIC LIGATURE LAM WITH MEEM INITIAL FORM */ + { {0xFEF2u}, 0xFC44u }, /* ARABIC LIGATURE LAM WITH YEH ISOLATED FORM */ + { {0xFEECu}, 0xFCCDu }, /* ARABIC LIGATURE LAM WITH HEH INITIAL FORM */ + { {0xFE82u}, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */ + { {0xFE84u}, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */ + { {0xFE88u}, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */ + { {0xFE8Eu}, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */ }}, { 0xFEE0u, { - { 0xFEF0u, 0xFC86u }, /* ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM */ - { 0xFE82u, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */ - { 0xFE84u, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */ - { 0xFE88u, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */ - { 0xFE8Eu, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */ + { {0xFEF0u}, 0xFC86u }, /* ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM */ + { {0xFE82u}, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */ + { {0xFE84u}, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */ + { {0xFE88u}, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */ + { {0xFE8Eu}, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */ }}, { 0xFEE3u, { - { 0xFEA0u, 0xFCCEu }, /* ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM */ - { 0xFEA4u, 0xFCCFu }, /* ARABIC LIGATURE MEEM WITH HAH INITIAL FORM */ - { 0xFEA8u, 0xFCD0u }, /* ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM */ - { 0xFEE4u, 0xFCD1u }, /* ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM */ + { {0xFEA0u}, 0xFCCEu }, /* ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM */ + { {0xFEA4u}, 0xFCCFu }, /* ARABIC LIGATURE MEEM WITH HAH INITIAL FORM */ + { {0xFEA8u}, 0xFCD0u }, /* ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM */ + { {0xFEE4u}, 0xFCD1u }, /* ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM */ }}, { 0xFEE7u, { - { 0xFEE2u, 0xFC4Eu }, /* ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM */ - { 0xFEE4u, 0xFCD5u }, /* ARABIC LIGATURE NOON WITH MEEM INITIAL FORM */ - { 0xFEA0u, 0xFCD2u }, /* ARABIC LIGATURE NOON WITH JEEM INITIAL FORM */ - { 0xFEA4u, 0xFCD3u }, /* ARABIC LIGATURE NOON WITH HAH INITIAL FORM */ + { {0xFEE2u}, 0xFC4Eu }, /* ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM */ + { {0xFEE4u}, 0xFCD5u }, /* ARABIC LIGATURE NOON WITH MEEM INITIAL FORM */ + { {0xFEA0u}, 0xFCD2u }, /* ARABIC LIGATURE NOON WITH JEEM INITIAL FORM */ + { {0xFEA4u}, 0xFCD3u }, /* ARABIC LIGATURE NOON WITH HAH INITIAL FORM */ }}, { 0xFEE8u, { - { 0xFEF2u, 0xFC8Fu }, /* ARABIC LIGATURE NOON WITH YEH FINAL FORM */ + { {0xFEF2u}, 0xFC8Fu }, /* ARABIC LIGATURE NOON WITH YEH FINAL FORM */ }}, { 0xFEF3u, { - { 0xFEA0u, 0xFCDAu }, /* ARABIC LIGATURE YEH WITH JEEM INITIAL FORM */ - { 0xFEA4u, 0xFCDBu }, /* ARABIC LIGATURE YEH WITH HAH INITIAL FORM */ - { 0xFEA8u, 0xFCDCu }, /* ARABIC LIGATURE YEH WITH KHAH INITIAL FORM */ - { 0xFEE4u, 0xFCDDu }, /* ARABIC LIGATURE YEH WITH MEEM INITIAL FORM */ + { {0xFEA0u}, 0xFCDAu }, /* ARABIC LIGATURE YEH WITH JEEM INITIAL FORM */ + { {0xFEA4u}, 0xFCDBu }, /* ARABIC LIGATURE YEH WITH HAH INITIAL FORM */ + { {0xFEA8u}, 0xFCDCu }, /* ARABIC LIGATURE YEH WITH KHAH INITIAL FORM */ + { {0xFEE4u}, 0xFCDDu }, /* ARABIC LIGATURE YEH WITH MEEM INITIAL FORM */ }}, { 0xFEF4u, { - { 0xFEAEu, 0xFC91u }, /* ARABIC LIGATURE YEH WITH REH FINAL FORM */ - { 0xFEE6u, 0xFC94u }, /* ARABIC LIGATURE YEH WITH NOON FINAL FORM */ + { {0xFEAEu}, 0xFC91u }, /* ARABIC LIGATURE YEH WITH REH FINAL FORM */ + { {0xFEE6u}, 0xFC94u }, /* ARABIC LIGATURE YEH WITH NOON FINAL FORM */ }}, }; @@ -520,17 +520,17 @@ static const struct ligature_set_t { static const struct ligature_mark_set_t { uint16_t first; struct ligature_pairs_t { - uint16_t second; + uint16_t components[1]; uint16_t ligature; } ligatures[5]; } ligature_mark_table[] = { { 0x0651u, { - { 0x064Cu, 0xFC5Eu }, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */ - { 0x064Eu, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */ - { 0x064Fu, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */ - { 0x0650u, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */ - { 0x064Bu, 0xF2EEu }, /* PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM */ + { {0x064Cu}, 0xFC5Eu }, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */ + { {0x064Eu}, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */ + { {0x064Fu}, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */ + { {0x0650u}, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */ + { {0x064Bu}, 0xF2EEu }, /* PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM */ }}, }; @@ -538,16 +538,15 @@ static const struct ligature_mark_set_t { static const struct ligature_3_set_t { uint16_t first; struct ligature_triplets_t { - uint16_t second; - uint16_t third; + uint16_t components[2]; uint16_t ligature; } ligatures[3]; } ligature_3_table[] = { { 0xFEDFu, { - { 0xFEE4u, 0xFEA4u, 0xFD88u}, /* ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM */ - { 0xFEE0u, 0xFEEAu, 0xF201u}, /* PUA ARABIC LIGATURE LELLAH ISOLATED FORM */ - { 0xFEE4u, 0xFEA0u, 0xF211u}, /* PUA ARABIC LIGATURE LAM WITH MEEM WITH JEEM INITIAL FORM */ + { {0xFEE4u, 0xFEA4u}, 0xFD88u}, /* ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM */ + { {0xFEE0u, 0xFEEAu}, 0xF201u}, /* PUA ARABIC LIGATURE LELLAH ISOLATED FORM */ + { {0xFEE4u, 0xFEA0u}, 0xF211u}, /* PUA ARABIC LIGATURE LAM WITH MEEM WITH JEEM INITIAL FORM */ }}, }; From 15dd34b51587a8c00b449960e76d18d1add89ff6 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 13:47:00 -0600 Subject: [PATCH 10/19] [arabic-fallback] Another minor rename towards supporting 3-letter ligatures --- src/hb-ot-shaper-arabic-fallback.hh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index fc7b8a4a8..f79f9f884 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -112,10 +112,11 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)]; unsigned int num_first_glyphs = 0; - /* We know that all our ligatures are 2-component */ + /* We know that all our ligatures have the same number of components. */ OT::HBGlyphID16 ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)]; unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)]; - OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */]; + OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * + ARRAY_LENGTH_CONST (ligature_table[0].ligatures[0].components)]; unsigned int num_ligatures = 0; /* Populate arrays */ @@ -141,10 +142,10 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN { unsigned int first_glyph_idx = first_glyphs_indirection[i]; - for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++) + for (unsigned int ligature_idx = 0; ligature_idx < ARRAY_LENGTH (ligature_table[0].ligatures); ligature_idx++) { - hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].components[0]; - hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].ligature; + hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[0]; + hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].ligature; hb_codepoint_t second_glyph, ligature_glyph; if (!second_u || !hb_font_get_glyph (font, second_u, 0, &second_glyph) || From 08715d75e07a3672e1e0e1159e58ec6a1c55d68e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 14:04:56 -0600 Subject: [PATCH 11/19] [arabic-fallback] Another baby-step --- src/hb-ot-shaper-arabic-fallback.hh | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index f79f9f884..e96ae8f88 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -144,19 +144,24 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN for (unsigned int ligature_idx = 0; ligature_idx < ARRAY_LENGTH (ligature_table[0].ligatures); ligature_idx++) { - hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[0]; hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].ligature; - hb_codepoint_t second_glyph, ligature_glyph; - if (!second_u || - !hb_font_get_glyph (font, second_u, 0, &second_glyph) || - !hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph)) + hb_codepoint_t ligature_glyph; + if (!hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph)) continue; + hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[0]; + hb_codepoint_t second_glyph; + if (!second_u || + !hb_font_get_glyph (font, second_u, 0, &second_glyph)) + continue; + + component_list[num_ligatures] = second_glyph; + component_count_list[num_ligatures] = 2; + + ligature_list[num_ligatures] = ligature_glyph; + ligature_per_first_glyph_count_list[i]++; - ligature_list[num_ligatures] = ligature_glyph; - component_count_list[num_ligatures] = 2; - component_list[num_ligatures] = second_glyph; num_ligatures++; } } From 9684d2d8aa86b5dade7a87f1cbea245904e20872 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 14:07:48 -0600 Subject: [PATCH 12/19] [arabic-fallback] More baby steps --- src/hb-ot-shaper-arabic-fallback.hh | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index e96ae8f88..8c513be78 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -118,6 +118,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * ARRAY_LENGTH_CONST (ligature_table[0].ligatures[0].components)]; unsigned int num_ligatures = 0; + unsigned int num_components = 0; /* Populate arrays */ @@ -149,15 +150,18 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN if (!hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph)) continue; - hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[0]; - hb_codepoint_t second_glyph; - if (!second_u || - !hb_font_get_glyph (font, second_u, 0, &second_glyph)) + const auto &components = ligature_table[first_glyph_idx].ligatures[ligature_idx].components; + unsigned component_count = ARRAY_LENGTH_CONST (components); + + hb_codepoint_t component_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[0]; + hb_codepoint_t component_glyph; + if (!component_u || + !hb_font_get_glyph (font, component_u, 0, &component_glyph)) continue; - component_list[num_ligatures] = second_glyph; - component_count_list[num_ligatures] = 2; + component_list[num_components++] = component_glyph; + component_count_list[num_ligatures] = 1 + component_count; ligature_list[num_ligatures] = ligature_glyph; ligature_per_first_glyph_count_list[i]++; From 20e9f0b1d2efe86b632dcfda067244c578c0e20f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 14:12:30 -0600 Subject: [PATCH 13/19] [arabic-fallback] Add the component loop Should be able to support 3-letter ligatures now. Hooking up next. --- src/hb-ot-shaper-arabic-fallback.hh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index 8c513be78..8c7d187e0 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -153,13 +153,16 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN const auto &components = ligature_table[first_glyph_idx].ligatures[ligature_idx].components; unsigned component_count = ARRAY_LENGTH_CONST (components); - hb_codepoint_t component_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[0]; - hb_codepoint_t component_glyph; - if (!component_u || - !hb_font_get_glyph (font, component_u, 0, &component_glyph)) - continue; + for (unsigned i = 0; i < component_count; i++) + { + hb_codepoint_t component_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[i]; + hb_codepoint_t component_glyph; + if (!component_u || + !hb_font_get_glyph (font, component_u, 0, &component_glyph)) + continue; - component_list[num_components++] = component_glyph; + component_list[num_components++] = component_glyph; + } component_count_list[num_ligatures] = 1 + component_count; ligature_list[num_ligatures] = ligature_glyph; From 1db6fddb24f6bb27d5d13890ea233859db7960a7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 14:34:46 -0600 Subject: [PATCH 14/19] [arabic-fallback.hh] Hook up 3-letter ligatures --- src/hb-null.hh | 2 +- src/hb-ot-shaper-arabic-fallback.hh | 10 ++++++---- .../data/in-house/tests/arabic-fallback-shaping.tests | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/hb-null.hh b/src/hb-null.hh index 623a01ec1..78eb6474d 100644 --- a/src/hb-null.hh +++ b/src/hb-null.hh @@ -37,7 +37,7 @@ /* Global nul-content Null pool. Enlarge as necessary. */ -#define HB_NULL_POOL_SIZE 384 +#define HB_NULL_POOL_SIZE 448 /* Use SFINAE to sniff whether T has min_size; in which case return the larger * of sizeof(T) and T::null_size, otherwise return sizeof(T). diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index 8c7d187e0..f7ae1327b 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -45,7 +45,8 @@ static const hb_tag_t arabic_fallback_features[] = HB_TAG('m','e','d','i'), HB_TAG('f','i','n','a'), HB_TAG('i','s','o','l'), - HB_TAG('r','l','i','g'), // Main ligatures + HB_TAG('r','l','i','g'), // 3-letter ligatures + HB_TAG('r','l','i','g'), // 2-letter ligatures HB_TAG('r','l','i','g'), // Mark ligatures }; @@ -187,7 +188,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN hb_array (ligature_per_first_glyph_count_list, num_first_glyphs), hb_array (ligature_list, num_ligatures), hb_array (component_count_list, num_ligatures), - hb_array (component_list, num_ligatures)); + hb_array (component_list, num_components)); c.end_serialize (); return ret && !c.in_error () ? c.copy () : nullptr; @@ -203,8 +204,9 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan, else { switch (feature_index) { - case 4: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_table, OT::LookupFlag::IgnoreMarks); - case 5: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_mark_table, 0); + case 4: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_3_table, OT::LookupFlag::IgnoreMarks); + case 5: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_table, OT::LookupFlag::IgnoreMarks); + case 6: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_mark_table, 0); } } assert (false); diff --git a/test/shape/data/in-house/tests/arabic-fallback-shaping.tests b/test/shape/data/in-house/tests/arabic-fallback-shaping.tests index eb5d30583..ac087899c 100644 --- a/test/shape/data/in-house/tests/arabic-fallback-shaping.tests +++ b/test/shape/data/in-house/tests/arabic-fallback-shaping.tests @@ -4,7 +4,7 @@ ../fonts/SimpArabicTest.ttf;;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[asterisk=0+269|plus=1+408|comma=2+509|hyphen=3+509|period=4+573|slash=5+572|zero=6+572|one=7+300|parenright=8+391|two=9+300|three=10+551|four=11+572|five=12+283|seven=13+268|eight=14+372|C=15+268|D=16+295|E=17+175|F=18+572|G=19+175|H=20+485|d=21+329|f=22+329|six=23+322|plus=24+408] ../fonts/SimpArabicTest.ttf;;U+061F,U+003F,U+0640;[H=0+485|H=1+485|h=2+171] ../fonts/SimpArabicTest.ttf;;U+0628,U+0644,U+0627,U+0020,U+0628,U+0644,U+0625;[ordfeminine=5+674|R=4+232|parenright=3+391|yen=1+709|R=0+232] -../fonts/TradArabicTest.ttf;;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[fnmeem=31+1069|midya=30+499|kasrah2=28@151,0+0|inhaa=28+1341|fnra=27+702|inlam=26+358|alef=25+444|righttoleftspace=24+468|kasrah2=22@110,-604+0|fnnoon=22+1259|fathah2=18@-145,-168+0|sukun2=18@760,-166+0|f29b=18+1497|fahtanonshaddah2=15@-51,-416+0|fnra=15+702|inlam=14+358|alef=13+444|righttoleftspace=12+468|fnha=11+776|midlam=10+403|inlam=9+358|alef=8+444|righttoleftspace=7+468|righttoleftspace=6+468|kasrah2=4@15,-1102+0|fnmeem=4+1069|sukun2=2@220,-386+0|midseen=2+1163|kasrah2=0@-324,-403+0|inbaa=0+389] +../fonts/TradArabicTest.ttf;;U+0628,U+0650,U+0633,U+0652,U+0645,U+0650,U+0020,U+0020,U+0627,U+0644,U+0644,U+0647,U+0020,U+0627,U+0644,U+0631,U+0651,U+064E,U+062D,U+0652,U+0645,U+064E,U+0646,U+0650,U+0020,U+0627,U+0644,U+0631,U+062D,U+0650,U+064A,U+0645;[fnmeem=31+1069|midya=30+499|kasrah2=28@151,0+0|inhaa=28+1341|fnra=27+702|inlam=26+358|alef=25+444|righttoleftspace=24+468|kasrah2=22@110,-604+0|fnnoon=22+1259|fathah2=18@-145,-168+0|sukun2=18@760,-166+0|f29b=18+1497|fahtanonshaddah2=15@-51,-416+0|fnra=15+702|inlam=14+358|alef=13+444|righttoleftspace=12+468|Allah=9+1513|alef=8+444|righttoleftspace=7+468|righttoleftspace=6+468|kasrah2=4@15,-1102+0|fnmeem=4+1069|sukun2=2@220,-386+0|midseen=2+1163|kasrah2=0@-324,-403+0|inbaa=0+389] ../fonts/TradArabicTest.ttf;;U+0020,U+0644,U+0627,U+0020,U+0644,U+0623,U+0020,U+0644,U+064E,U+0623,U+064E,U+0020,U+0623,U+064E,U+0646,U+062A;[fntaa=15+1808|innoon=14+389|fathah2=12@-279,883+0|hamzahonalef=12+479|righttoleftspace=11+468|fathah2=7@-190,862+0|fathah2=7@468,862+0|hamzahonlamelef=7+1316|righttoleftspace=6+468|hamzahonlamelef=4+1316|righttoleftspace=3+468|lamelef=1+1316|righttoleftspace=0+468] ../fonts/TradArabicTest.ttf;;U+0021,U+0022,U+00AB,U+00BB,U+0025,U+00D7,U+00F7,U+0028,U+0020,U+0029,U+002A,U+002B,U+060C,U+002E,U+002F,U+003A,U+061B,U+2018,U+003D,U+2019,U+061F,U+005B,U+005D,U+002D,U+0022;[greater=0+481|question=1+559|at=2+849|A=3+849|percentarabic=4+1353|C=5+927|D=6+1196|E=7+855|righttoleftspace=8+468|F=9+855|G=10+884|H=11+1083|commaarabic=12+755|K=13+649|L=14+704|W=15+450|semicolonarabic=16+755|.notdef=17+745|Z=18+1128|.notdef=19+745|questionarabic=20+845|x=21+739|z=22+739|J=23+753|question=24+559] ../fonts/TradArabicTest.ttf;;U+061F,U+003F,U+0640;[questionarabic=0+845|questionarabic=1+845|tatweelnarrow=2+378] From 41a079bdec091e40e8afe36db4ef647cc3bde195 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 18 Jun 2022 14:47:10 -0600 Subject: [PATCH 15/19] [arabic-fallback] Make win1256 code build again Humm. Untested. --- src/hb-ot-shaper-arabic-fallback.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index f7ae1327b..d2736b8f9 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -45,9 +45,9 @@ static const hb_tag_t arabic_fallback_features[] = HB_TAG('m','e','d','i'), HB_TAG('f','i','n','a'), HB_TAG('i','s','o','l'), - HB_TAG('r','l','i','g'), // 3-letter ligatures - HB_TAG('r','l','i','g'), // 2-letter ligatures - HB_TAG('r','l','i','g'), // Mark ligatures + HB_TAG('r','l','i','g'), + HB_TAG('r','l','i','g'), + HB_TAG('r','l','i','g'), }; static OT::SubstLookup * @@ -258,7 +258,7 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUS return false; const Manifest &manifest = reinterpret_cast (arabic_win1256_gsub_lookups.manifest); - static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) == + static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) <= ARABIC_FALLBACK_MAX_LOOKUPS * sizeof (ManifestLookup), ""); unsigned j = 0; From 55350377b0d26c06f152f0cd30c3911fd6060b85 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 19 Jun 2022 10:13:31 -0600 Subject: [PATCH 16/19] [cmap/ft] Only map 0xF000 range if font_page is NONE --- src/hb-ft.cc | 4 +++- src/hb-ot-cmap-table.hh | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 2da90a2e3..74ac6853b 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -315,7 +315,7 @@ hb_ft_get_nominal_glyph (hb_font_t *font, if (unlikely (ft_font->symbol)) { switch ((unsigned) font->face->table.OS2->get_font_page ()) { - default: + case OT::OS2::font_page_t::FONT_PAGE_NONE: if (unicode <= 0x00FFu) /* For symbol-encoded OpenType fonts, we duplicate the * U+F000..F0FF range at U+0000..U+00FF. That's what @@ -330,6 +330,8 @@ hb_ft_get_nominal_glyph (hb_font_t *font, case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: g = FT_Get_Char_Index (ft_font->ft_face, _hb_remap_arabic_pua2 (unicode)); break; + default: + break; } if (!g) return false; diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index ac96f9c84..a21ae49eb 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -1744,7 +1744,7 @@ struct cmap if (unlikely (symbol)) { switch ((unsigned) face->table.OS2->get_font_page ()) { - default: + case OS2::font_page_t::FONT_PAGE_NONE: this->get_glyph_funcZ = get_glyph_from_symbol; break; case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: @@ -1753,6 +1753,9 @@ struct cmap case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: this->get_glyph_funcZ = get_glyph_from_symbol; break; + default: + this->get_glyph_funcZ = get_glyph_from; + break; } } else From 4520911429dae90dc1342fadf1112967839e5899 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 19 Jun 2022 10:36:24 -0600 Subject: [PATCH 17/19] [arabic-fallback] Fix warning --- src/hb-ot-shaper-arabic-fallback.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hb-ot-shaper-arabic-fallback.hh b/src/hb-ot-shaper-arabic-fallback.hh index d2736b8f9..b9f92f72d 100644 --- a/src/hb-ot-shaper-arabic-fallback.hh +++ b/src/hb-ot-shaper-arabic-fallback.hh @@ -210,6 +210,7 @@ arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan, } } assert (false); + return nullptr; } #define ARABIC_FALLBACK_MAX_LOOKUPS ARRAY_LENGTH_CONST (arabic_fallback_features) From 769896291176936d01c79a56bce3b33eb64e2776 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 19 Jun 2022 10:41:45 -0600 Subject: [PATCH 18/19] [arabic-fallback] Disable PUA shaping under HB_NO_OT_SHAPER_ARABIC_FALLBACK --- src/hb-ft.cc | 2 ++ src/hb-ot-cmap-table.hh | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 74ac6853b..04df8c2e9 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -324,12 +324,14 @@ hb_ft_get_nominal_glyph (hb_font_t *font, * under "Non-Standard (Symbol) Fonts". */ g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); break; +#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK case OT::OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: g = FT_Get_Char_Index (ft_font->ft_face, _hb_remap_arabic_pua1 (unicode)); break; case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: g = FT_Get_Char_Index (ft_font->ft_face, _hb_remap_arabic_pua2 (unicode)); break; +#endif default: break; } diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index a21ae49eb..5fcc12886 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -1747,12 +1747,14 @@ struct cmap case OS2::font_page_t::FONT_PAGE_NONE: this->get_glyph_funcZ = get_glyph_from_symbol; break; +#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: this->get_glyph_funcZ = get_glyph_from_symbol; break; case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: this->get_glyph_funcZ = get_glyph_from_symbol; break; +#endif default: this->get_glyph_funcZ = get_glyph_from; break; From 8c27c51c27c760a54350bf18ddfae34aaa19d89e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 19 Jun 2022 10:47:38 -0600 Subject: [PATCH 19/19] [arabic-pua] Rename symbols --- src/hb-ft.cc | 4 ++-- src/hb-ot-cmap-table.hh | 8 ++++---- src/hb-ot-shaper-arabic-pua.hh | 36 +++++++++++++++++----------------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 04df8c2e9..84a426e81 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -326,10 +326,10 @@ hb_ft_get_nominal_glyph (hb_font_t *font, break; #ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK case OT::OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: - g = FT_Get_Char_Index (ft_font->ft_face, _hb_remap_arabic_pua1 (unicode)); + g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_simp_map (unicode)); break; case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: - g = FT_Get_Char_Index (ft_font->ft_face, _hb_remap_arabic_pua2 (unicode)); + g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_trad_map (unicode)); break; #endif default: diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index 5fcc12886..69b430fb7 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -1505,7 +1505,7 @@ struct SubtableUnicodesCache { }; static inline hb_codepoint_t -_hb_remap_symbol_pua (hb_codepoint_t codepoint) +_hb_symbol_pua_map (hb_codepoint_t codepoint) { if (codepoint <= 0x00FFu) { @@ -1745,14 +1745,14 @@ struct cmap { switch ((unsigned) face->table.OS2->get_font_page ()) { case OS2::font_page_t::FONT_PAGE_NONE: - this->get_glyph_funcZ = get_glyph_from_symbol; + this->get_glyph_funcZ = get_glyph_from_symbol; break; #ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC: - this->get_glyph_funcZ = get_glyph_from_symbol; + this->get_glyph_funcZ = get_glyph_from_symbol; break; case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC: - this->get_glyph_funcZ = get_glyph_from_symbol; + this->get_glyph_funcZ = get_glyph_from_symbol; break; #endif default: diff --git a/src/hb-ot-shaper-arabic-pua.hh b/src/hb-ot-shaper-arabic-pua.hh index 98cd266e9..d35377606 100644 --- a/src/hb-ot-shaper-arabic-pua.hh +++ b/src/hb-ot-shaper-arabic-pua.hh @@ -2,7 +2,7 @@ #ifndef HB_OT_SHAPER_ARABIC_PUA_HH #define HB_OT_SHAPER_ARABIC_PUA_HH -static const uint16_t _arabic_table_pua1[][128] = { +static const uint16_t _arabic_table_pua_simp[][128] = { { /* 0x0000u..0x007Fu */ 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, @@ -96,17 +96,17 @@ static const uint16_t _arabic_table_pua1[][128] = { }; static inline hb_codepoint_t -_hb_remap_arabic_pua1(hb_codepoint_t codepoint) +_hb_arabic_pua_simp_map (hb_codepoint_t codepoint) { - if (hb_in_range (codepoint, 0x0000u, 0x007Fu)) return _arabic_table_pua1[0][codepoint]; - if (hb_in_range (codepoint, 0x0080u, 0x00FFu)) return _arabic_table_pua1[1][codepoint - 0x0080u]; - if (hb_in_range (codepoint, 0x0600u, 0x067Fu)) return _arabic_table_pua1[2][codepoint - 0x0600u]; - if (hb_in_range (codepoint, 0x2000u, 0x207Fu)) return _arabic_table_pua1[3][codepoint - 0x2000u]; - if (hb_in_range (codepoint, 0xFE80u, 0xFEFFu)) return _arabic_table_pua1[4][codepoint - 0xFE80u]; + if (hb_in_range (codepoint, 0x0000u, 0x007Fu)) return _arabic_table_pua_simp[0][codepoint]; + if (hb_in_range (codepoint, 0x0080u, 0x00FFu)) return _arabic_table_pua_simp[1][codepoint - 0x0080u]; + if (hb_in_range (codepoint, 0x0600u, 0x067Fu)) return _arabic_table_pua_simp[2][codepoint - 0x0600u]; + if (hb_in_range (codepoint, 0x2000u, 0x207Fu)) return _arabic_table_pua_simp[3][codepoint - 0x2000u]; + if (hb_in_range (codepoint, 0xFE80u, 0xFEFFu)) return _arabic_table_pua_simp[4][codepoint - 0xFE80u]; return 0; } -static const uint16_t _arabic_table_pua2[][128] = { +static const uint16_t _arabic_table_pua_trad[][128] = { { /* 0x0000u..0x007Fu */ 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, @@ -272,17 +272,17 @@ static const uint16_t _arabic_table_pua2[][128] = { }; static inline hb_codepoint_t -_hb_remap_arabic_pua2(hb_codepoint_t codepoint) +_hb_arabic_pua_trad_map (hb_codepoint_t codepoint) { - if (hb_in_range (codepoint, 0x0000u, 0x007Fu)) return _arabic_table_pua2[0][codepoint]; - if (hb_in_range (codepoint, 0x0080u, 0x00FFu)) return _arabic_table_pua2[1][codepoint - 0x0080u]; - if (hb_in_range (codepoint, 0x0600u, 0x067Fu)) return _arabic_table_pua2[2][codepoint - 0x0600u]; - if (hb_in_range (codepoint, 0x2000u, 0x207Fu)) return _arabic_table_pua2[3][codepoint - 0x2000u]; - if (hb_in_range (codepoint, 0xFBD0u, 0xFC4Fu)) return _arabic_table_pua2[4][codepoint - 0xFBD0u]; - if (hb_in_range (codepoint, 0xFC50u, 0xFCCFu)) return _arabic_table_pua2[5][codepoint - 0xFC50u]; - if (hb_in_range (codepoint, 0xFCD0u, 0xFD4Fu)) return _arabic_table_pua2[6][codepoint - 0xFCD0u]; - if (hb_in_range (codepoint, 0xFD50u, 0xFDCFu)) return _arabic_table_pua2[7][codepoint - 0xFD50u]; - if (hb_in_range (codepoint, 0xFE80u, 0xFEFFu)) return _arabic_table_pua2[8][codepoint - 0xFE80u]; + if (hb_in_range (codepoint, 0x0000u, 0x007Fu)) return _arabic_table_pua_trad[0][codepoint]; + if (hb_in_range (codepoint, 0x0080u, 0x00FFu)) return _arabic_table_pua_trad[1][codepoint - 0x0080u]; + if (hb_in_range (codepoint, 0x0600u, 0x067Fu)) return _arabic_table_pua_trad[2][codepoint - 0x0600u]; + if (hb_in_range (codepoint, 0x2000u, 0x207Fu)) return _arabic_table_pua_trad[3][codepoint - 0x2000u]; + if (hb_in_range (codepoint, 0xFBD0u, 0xFC4Fu)) return _arabic_table_pua_trad[4][codepoint - 0xFBD0u]; + if (hb_in_range (codepoint, 0xFC50u, 0xFCCFu)) return _arabic_table_pua_trad[5][codepoint - 0xFC50u]; + if (hb_in_range (codepoint, 0xFCD0u, 0xFD4Fu)) return _arabic_table_pua_trad[6][codepoint - 0xFCD0u]; + if (hb_in_range (codepoint, 0xFD50u, 0xFDCFu)) return _arabic_table_pua_trad[7][codepoint - 0xFD50u]; + if (hb_in_range (codepoint, 0xFE80u, 0xFEFFu)) return _arabic_table_pua_trad[8][codepoint - 0xFE80u]; return 0; }