diff --git a/CHANGELOG.md b/CHANGELOG.md index d24d9ca70..0b830c06e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,9 +21,11 @@ This can also be enabled programmatically with `warnings.simplefilter('default', * [`Templates`](https://py-pdf.github.io/fpdf2/fpdf/Templates.html) can now be also defined in JSON files. * support to optionally set `wrapmode` in templates (default `"WORD"` can optionally be set to `"CHAR"` to support wrapping on characters for scripts like Chinese or Japanese) - _cf._ [#1159](https://github.com/py-pdf/fpdf2/issues/1159) * support for quadratic and cubic Bézier curves with [`FPDF.bezier()`](https://py-pdf.github.io/fpdf2/fpdf/Shapes.html#fpdf.fpdf.FPDF.bezier) +* feature to identify the Unicode script of the input text and break it into fragments when different scripts are used, improving text shaping results ### Fixed * [`fpdf.drawing.DeviceCMYK`](https://py-pdf.github.io/fpdf2/fpdf/drawing.html#fpdf.drawing.DeviceCMYK) objects can now be passed to [`FPDF.set_draw_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_draw_color), [`FPDF.set_fill_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_fill_color) and [`FPDF.set_text_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_text_color) without raising a `ValueError`: [documentation](https://py-pdf.github.io/fpdf2/Text.html#text-formatting). -* individual `/Resources` directories are now properly created for each document page. This change ensures better compliance with the PDF specification but results in a slight increase in the size of PDF documents. You can still use the old behavior by setting `FPDF().single_resources_object = True`. +* individual `/Resources` directories are now properly created for each document page. This change ensures better compliance with the PDF specification but results in a slight increase in the size of PDF documents. You can still use the old behavior by setting `FPDF().single_resources_object = True` +* line size calculation for fragments when text shaping is used ### Changed * [`FPDF.table()`](https://py-pdf.github.io/fpdf2/Tables.html) now raises an error when a single row is too high to be rendered on a single page ### Deprecated diff --git a/fpdf/fonts.py b/fpdf/fonts.py index 6d93a796d..1c9a18b73 100644 --- a/fpdf/fonts.py +++ b/fpdf/fonts.py @@ -270,9 +270,7 @@ def shaped_text_width(self, text, font_size_pt, text_shaping_parms): text_width = 0 for pos in glyph_positions: text_width += ( - round(self.scale * (pos.x_advance + pos.x_offset) + 0.001) - * font_size_pt - * 0.001 + round(self.scale * pos.x_advance + 0.001) * font_size_pt * 0.001 ) return (len(glyph_positions), text_width) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index ef376ca00..b5fec6094 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -116,6 +116,7 @@ class Image: from .syntax import DestinationXYZ, PDFArray, PDFDate from .table import Table, draw_box_borders from .text_region import TextRegionMixin, TextColumns +from .unicode_script import UnicodeScript, get_unicode_script from .util import get_scale_factor, Padding # Public global variables: @@ -3379,7 +3380,7 @@ def get_fallback_font(self, char, style=""): def _parse_chars(self, text: str, markdown: bool) -> Iterator[Fragment]: "Split text into fragments" - if not markdown and (not self.is_ttf_font or not self._fallback_font_ids): + if not markdown and not self.is_ttf_font: yield Fragment(text, self._get_current_graphics_state(), self.k) return txt_frag, in_bold, in_italics, in_underline = ( @@ -3389,9 +3390,10 @@ def _parse_chars(self, text: str, markdown: bool) -> Iterator[Fragment]: bool(self.underline), ) current_fallback_font = None + current_text_script = None def frag(): - nonlocal txt_frag, current_fallback_font + nonlocal txt_frag, current_fallback_font, current_text_script gstate = self._get_current_graphics_state() gstate["font_style"] = ("B" if in_bold else "") + ( "I" if in_italics else "" @@ -3406,6 +3408,7 @@ def frag(): ) gstate["current_font"] = self.fonts[current_fallback_font] current_fallback_font = None + current_text_script = None fragment = Fragment( txt_frag, gstate, @@ -3426,6 +3429,16 @@ def frag(): self.MARKDOWN_UNDERLINE_MARKER, ) half_marker = text[0] + text_script = get_unicode_script(text[0]) + if text_script not in ( + UnicodeScript.COMMON, + UnicodeScript.UNKNOWN, + current_text_script, + ): + if txt_frag and current_text_script: + yield frag() + current_text_script = text_script + # Check that previous & next characters are not identical to the marker: if markdown: if ( @@ -5132,6 +5145,8 @@ def output( DeprecationWarning, stacklevel=get_stack_level(), ) + # Clear cache of cached functions to free up memory after output + get_unicode_script.cache_clear() # Finish document if necessary: if not self.buffer: if self.page == 0: diff --git a/fpdf/unicode_script.py b/fpdf/unicode_script.py new file mode 100644 index 000000000..18f858a9f --- /dev/null +++ b/fpdf/unicode_script.py @@ -0,0 +1,2383 @@ +""" +The hardcoded information on this module was loaded from the Unicode file Scripts-15.1.0.txt +https://www.unicode.org/Public/UNIDATA/Scripts.txt +Python's standard "unicodedata" library doesn't offer this table. +""" + +from enum import IntEnum +from functools import lru_cache + + +class UnicodeScript(IntEnum): + COMMON = 0 + LATIN = 1 + GREEK = 2 + CYRILLIC = 3 + ARMENIAN = 4 + HEBREW = 5 + ARABIC = 6 + SYRIAC = 7 + THAANA = 8 + DEVANAGARI = 9 + BENGALI = 10 + GURMUKHI = 11 + GUJARATI = 12 + ORIYA = 13 + TAMIL = 14 + TELUGU = 15 + KANNADA = 16 + MALAYALAM = 17 + SINHALA = 18 + THAI = 19 + LAO = 20 + TIBETAN = 21 + MYANMAR = 22 + GEORGIAN = 23 + HANGUL = 24 + ETHIOPIC = 25 + CHEROKEE = 26 + CANADIAN_ABORIGINAL = 27 + OGHAM = 28 + RUNIC = 29 + KHMER = 30 + MONGOLIAN = 31 + HIRAGANA = 32 + KATAKANA = 33 + BOPOMOFO = 34 + HAN = 35 + YI = 36 + OLD_ITALIC = 37 + GOTHIC = 38 + DESERET = 39 + INHERITED = 40 + TAGALOG = 41 + HANUNOO = 42 + BUHID = 43 + TAGBANWA = 44 + LIMBU = 45 + TAI_LE = 46 + LINEAR_B = 47 + UGARITIC = 48 + SHAVIAN = 49 + OSMANYA = 50 + CYPRIOT = 51 + BRAILLE = 52 + BUGINESE = 53 + COPTIC = 54 + NEW_TAI_LUE = 55 + GLAGOLITIC = 56 + TIFINAGH = 57 + SYLOTI_NAGRI = 58 + OLD_PERSIAN = 59 + KHAROSHTHI = 60 + BALINESE = 61 + CUNEIFORM = 62 + PHOENICIAN = 63 + PHAGS_PA = 64 + NKO = 65 + SUNDANESE = 66 + LEPCHA = 67 + OL_CHIKI = 68 + VAI = 69 + SAURASHTRA = 70 + KAYAH_LI = 71 + REJANG = 72 + LYCIAN = 73 + CARIAN = 74 + LYDIAN = 75 + CHAM = 76 + TAI_THAM = 77 + TAI_VIET = 78 + AVESTAN = 79 + EGYPTIAN_HIEROGLYPHS = 80 + SAMARITAN = 81 + LISU = 82 + BAMUM = 83 + JAVANESE = 84 + MEETEI_MAYEK = 85 + IMPERIAL_ARAMAIC = 86 + OLD_SOUTH_ARABIAN = 87 + INSCRIPTIONAL_PARTHIAN = 88 + INSCRIPTIONAL_PAHLAVI = 89 + OLD_TURKIC = 90 + KAITHI = 91 + BATAK = 92 + BRAHMI = 93 + MANDAIC = 94 + CHAKMA = 95 + MEROITIC_CURSIVE = 96 + MEROITIC_HIEROGLYPHS = 97 + MIAO = 98 + SHARADA = 99 + SORA_SOMPENG = 100 + TAKRI = 101 + CAUCASIAN_ALBANIAN = 102 + BASSA_VAH = 103 + DUPLOYAN = 104 + ELBASAN = 105 + GRANTHA = 106 + PAHAWH_HMONG = 107 + KHOJKI = 108 + LINEAR_A = 109 + MAHAJANI = 110 + MANICHAEAN = 111 + MENDE_KIKAKUI = 112 + MODI = 113 + MRO = 114 + OLD_NORTH_ARABIAN = 115 + NABATAEAN = 116 + PALMYRENE = 117 + PAU_CIN_HAU = 118 + OLD_PERMIC = 119 + PSALTER_PAHLAVI = 120 + SIDDHAM = 121 + KHUDAWADI = 122 + TIRHUTA = 123 + WARANG_CITI = 124 + AHOM = 125 + ANATOLIAN_HIEROGLYPHS = 126 + HATRAN = 127 + MULTANI = 128 + OLD_HUNGARIAN = 129 + SIGNWRITING = 130 + ADLAM = 131 + BHAIKSUKI = 132 + MARCHEN = 133 + NEWA = 134 + OSAGE = 135 + TANGUT = 136 + MASARAM_GONDI = 137 + NUSHU = 138 + SOYOMBO = 139 + ZANABAZAR_SQUARE = 140 + DOGRA = 141 + GUNJALA_GONDI = 142 + MAKASAR = 143 + MEDEFAIDRIN = 144 + HANIFI_ROHINGYA = 145 + SOGDIAN = 146 + OLD_SOGDIAN = 147 + ELYMAIC = 148 + NANDINAGARI = 149 + NYIAKENG_PUACHUE_HMONG = 150 + WANCHO = 151 + CHORASMIAN = 152 + DIVES_AKURU = 153 + KHITAN_SMALL_SCRIPT = 154 + YEZIDI = 155 + CYPRO_MINOAN = 156 + OLD_UYGHUR = 157 + TANGSA = 158 + TOTO = 159 + VITHKUQI = 160 + KAWI = 161 + NAG_MUNDARI = 162 + UNKNOWN = 999 + + +UNICODE_RANGE_TO_SCRIPT = ( + (0, 31, 0), + (32, 32, 0), + (33, 35, 0), + (36, 36, 0), + (37, 39, 0), + (40, 40, 0), + (41, 41, 0), + (42, 42, 0), + (43, 43, 0), + (44, 44, 0), + (45, 45, 0), + (46, 47, 0), + (48, 57, 0), + (58, 59, 0), + (60, 62, 0), + (63, 64, 0), + (65, 90, 1), + (91, 91, 0), + (92, 92, 0), + (93, 93, 0), + (94, 94, 0), + (95, 95, 0), + (96, 96, 0), + (97, 122, 1), + (123, 123, 0), + (124, 124, 0), + (125, 125, 0), + (126, 126, 0), + (127, 159, 0), + (160, 160, 0), + (161, 161, 0), + (162, 165, 0), + (166, 166, 0), + (167, 167, 0), + (168, 168, 0), + (169, 169, 0), + (170, 170, 1), + (171, 171, 0), + (172, 172, 0), + (173, 173, 0), + (174, 174, 0), + (175, 175, 0), + (176, 176, 0), + (177, 177, 0), + (178, 179, 0), + (180, 180, 0), + (181, 181, 0), + (182, 183, 0), + (184, 184, 0), + (185, 185, 0), + (186, 186, 1), + (187, 187, 0), + (188, 190, 0), + (191, 191, 0), + (192, 214, 1), + (215, 215, 0), + (216, 246, 1), + (247, 247, 0), + (248, 442, 1), + (443, 443, 1), + (444, 447, 1), + (448, 451, 1), + (452, 659, 1), + (660, 660, 1), + (661, 687, 1), + (688, 696, 1), + (697, 705, 0), + (706, 709, 0), + (710, 721, 0), + (722, 735, 0), + (736, 740, 1), + (741, 745, 0), + (746, 747, 34), + (748, 748, 0), + (749, 749, 0), + (750, 750, 0), + (751, 767, 0), + (768, 879, 40), + (880, 883, 2), + (884, 884, 0), + (885, 885, 2), + (886, 887, 2), + (890, 890, 2), + (891, 893, 2), + (894, 894, 0), + (895, 895, 2), + (900, 900, 2), + (901, 901, 0), + (902, 902, 2), + (903, 903, 0), + (904, 906, 2), + (908, 908, 2), + (910, 929, 2), + (931, 993, 2), + (994, 1007, 54), + (1008, 1013, 2), + (1014, 1014, 2), + (1015, 1023, 2), + (1024, 1153, 3), + (1154, 1154, 3), + (1155, 1156, 3), + (1157, 1158, 40), + (1159, 1159, 3), + (1160, 1161, 3), + (1162, 1327, 3), + (1329, 1366, 4), + (1369, 1369, 4), + (1370, 1375, 4), + (1376, 1416, 4), + (1417, 1417, 4), + (1418, 1418, 4), + (1421, 1422, 4), + (1423, 1423, 4), + (1425, 1469, 5), + (1470, 1470, 5), + (1471, 1471, 5), + (1472, 1472, 5), + (1473, 1474, 5), + (1475, 1475, 5), + (1476, 1477, 5), + (1478, 1478, 5), + (1479, 1479, 5), + (1488, 1514, 5), + (1519, 1522, 5), + (1523, 1524, 5), + (1536, 1540, 6), + (1541, 1541, 0), + (1542, 1544, 6), + (1545, 1546, 6), + (1547, 1547, 6), + (1548, 1548, 0), + (1549, 1549, 6), + (1550, 1551, 6), + (1552, 1562, 6), + (1563, 1563, 0), + (1564, 1564, 6), + (1565, 1566, 6), + (1567, 1567, 0), + (1568, 1599, 6), + (1600, 1600, 0), + (1601, 1610, 6), + (1611, 1621, 40), + (1622, 1631, 6), + (1632, 1641, 6), + (1642, 1645, 6), + (1646, 1647, 6), + (1648, 1648, 40), + (1649, 1747, 6), + (1748, 1748, 6), + (1749, 1749, 6), + (1750, 1756, 6), + (1757, 1757, 0), + (1758, 1758, 6), + (1759, 1764, 6), + (1765, 1766, 6), + (1767, 1768, 6), + (1769, 1769, 6), + (1770, 1773, 6), + (1774, 1775, 6), + (1776, 1785, 6), + (1786, 1788, 6), + (1789, 1790, 6), + (1791, 1791, 6), + (1792, 1805, 7), + (1807, 1807, 7), + (1808, 1808, 7), + (1809, 1809, 7), + (1810, 1839, 7), + (1840, 1866, 7), + (1869, 1871, 7), + (1872, 1919, 6), + (1920, 1957, 8), + (1958, 1968, 8), + (1969, 1969, 8), + (1984, 1993, 65), + (1994, 2026, 65), + (2027, 2035, 65), + (2036, 2037, 65), + (2038, 2038, 65), + (2039, 2041, 65), + (2042, 2042, 65), + (2045, 2045, 65), + (2046, 2047, 65), + (2048, 2069, 81), + (2070, 2073, 81), + (2074, 2074, 81), + (2075, 2083, 81), + (2084, 2084, 81), + (2085, 2087, 81), + (2088, 2088, 81), + (2089, 2093, 81), + (2096, 2110, 81), + (2112, 2136, 94), + (2137, 2139, 94), + (2142, 2142, 94), + (2144, 2154, 7), + (2160, 2183, 6), + (2184, 2184, 6), + (2185, 2190, 6), + (2192, 2193, 6), + (2200, 2207, 6), + (2208, 2248, 6), + (2249, 2249, 6), + (2250, 2273, 6), + (2274, 2274, 0), + (2275, 2303, 6), + (2304, 2306, 9), + (2307, 2307, 9), + (2308, 2361, 9), + (2362, 2362, 9), + (2363, 2363, 9), + (2364, 2364, 9), + (2365, 2365, 9), + (2366, 2368, 9), + (2369, 2376, 9), + (2377, 2380, 9), + (2381, 2381, 9), + (2382, 2383, 9), + (2384, 2384, 9), + (2385, 2388, 40), + (2389, 2391, 9), + (2392, 2401, 9), + (2402, 2403, 9), + (2404, 2405, 0), + (2406, 2415, 9), + (2416, 2416, 9), + (2417, 2417, 9), + (2418, 2431, 9), + (2432, 2432, 10), + (2433, 2433, 10), + (2434, 2435, 10), + (2437, 2444, 10), + (2447, 2448, 10), + (2451, 2472, 10), + (2474, 2480, 10), + (2482, 2482, 10), + (2486, 2489, 10), + (2492, 2492, 10), + (2493, 2493, 10), + (2494, 2496, 10), + (2497, 2500, 10), + (2503, 2504, 10), + (2507, 2508, 10), + (2509, 2509, 10), + (2510, 2510, 10), + (2519, 2519, 10), + (2524, 2525, 10), + (2527, 2529, 10), + (2530, 2531, 10), + (2534, 2543, 10), + (2544, 2545, 10), + (2546, 2547, 10), + (2548, 2553, 10), + (2554, 2554, 10), + (2555, 2555, 10), + (2556, 2556, 10), + (2557, 2557, 10), + (2558, 2558, 10), + (2561, 2562, 11), + (2563, 2563, 11), + (2565, 2570, 11), + (2575, 2576, 11), + (2579, 2600, 11), + (2602, 2608, 11), + (2610, 2611, 11), + (2613, 2614, 11), + (2616, 2617, 11), + (2620, 2620, 11), + (2622, 2624, 11), + (2625, 2626, 11), + (2631, 2632, 11), + (2635, 2637, 11), + (2641, 2641, 11), + (2649, 2652, 11), + (2654, 2654, 11), + (2662, 2671, 11), + (2672, 2673, 11), + (2674, 2676, 11), + (2677, 2677, 11), + (2678, 2678, 11), + (2689, 2690, 12), + (2691, 2691, 12), + (2693, 2701, 12), + (2703, 2705, 12), + (2707, 2728, 12), + (2730, 2736, 12), + (2738, 2739, 12), + (2741, 2745, 12), + (2748, 2748, 12), + (2749, 2749, 12), + (2750, 2752, 12), + (2753, 2757, 12), + (2759, 2760, 12), + (2761, 2761, 12), + (2763, 2764, 12), + (2765, 2765, 12), + (2768, 2768, 12), + (2784, 2785, 12), + (2786, 2787, 12), + (2790, 2799, 12), + (2800, 2800, 12), + (2801, 2801, 12), + (2809, 2809, 12), + (2810, 2815, 12), + (2817, 2817, 13), + (2818, 2819, 13), + (2821, 2828, 13), + (2831, 2832, 13), + (2835, 2856, 13), + (2858, 2864, 13), + (2866, 2867, 13), + (2869, 2873, 13), + (2876, 2876, 13), + (2877, 2877, 13), + (2878, 2878, 13), + (2879, 2879, 13), + (2880, 2880, 13), + (2881, 2884, 13), + (2887, 2888, 13), + (2891, 2892, 13), + (2893, 2893, 13), + (2901, 2902, 13), + (2903, 2903, 13), + (2908, 2909, 13), + (2911, 2913, 13), + (2914, 2915, 13), + (2918, 2927, 13), + (2928, 2928, 13), + (2929, 2929, 13), + (2930, 2935, 13), + (2946, 2946, 14), + (2947, 2947, 14), + (2949, 2954, 14), + (2958, 2960, 14), + (2962, 2965, 14), + (2969, 2970, 14), + (2972, 2972, 14), + (2974, 2975, 14), + (2979, 2980, 14), + (2984, 2986, 14), + (2990, 3001, 14), + (3006, 3007, 14), + (3008, 3008, 14), + (3009, 3010, 14), + (3014, 3016, 14), + (3018, 3020, 14), + (3021, 3021, 14), + (3024, 3024, 14), + (3031, 3031, 14), + (3046, 3055, 14), + (3056, 3058, 14), + (3059, 3064, 14), + (3065, 3065, 14), + (3066, 3066, 14), + (3072, 3072, 15), + (3073, 3075, 15), + (3076, 3076, 15), + (3077, 3084, 15), + (3086, 3088, 15), + (3090, 3112, 15), + (3114, 3129, 15), + (3132, 3132, 15), + (3133, 3133, 15), + (3134, 3136, 15), + (3137, 3140, 15), + (3142, 3144, 15), + (3146, 3149, 15), + (3157, 3158, 15), + (3160, 3162, 15), + (3165, 3165, 15), + (3168, 3169, 15), + (3170, 3171, 15), + (3174, 3183, 15), + (3191, 3191, 15), + (3192, 3198, 15), + (3199, 3199, 15), + (3200, 3200, 16), + (3201, 3201, 16), + (3202, 3203, 16), + (3204, 3204, 16), + (3205, 3212, 16), + (3214, 3216, 16), + (3218, 3240, 16), + (3242, 3251, 16), + (3253, 3257, 16), + (3260, 3260, 16), + (3261, 3261, 16), + (3262, 3262, 16), + (3263, 3263, 16), + (3264, 3268, 16), + (3270, 3270, 16), + (3271, 3272, 16), + (3274, 3275, 16), + (3276, 3277, 16), + (3285, 3286, 16), + (3293, 3294, 16), + (3296, 3297, 16), + (3298, 3299, 16), + (3302, 3311, 16), + (3313, 3314, 16), + (3315, 3315, 16), + (3328, 3329, 17), + (3330, 3331, 17), + (3332, 3340, 17), + (3342, 3344, 17), + (3346, 3386, 17), + (3387, 3388, 17), + (3389, 3389, 17), + (3390, 3392, 17), + (3393, 3396, 17), + (3398, 3400, 17), + (3402, 3404, 17), + (3405, 3405, 17), + (3406, 3406, 17), + (3407, 3407, 17), + (3412, 3414, 17), + (3415, 3415, 17), + (3416, 3422, 17), + (3423, 3425, 17), + (3426, 3427, 17), + (3430, 3439, 17), + (3440, 3448, 17), + (3449, 3449, 17), + (3450, 3455, 17), + (3457, 3457, 18), + (3458, 3459, 18), + (3461, 3478, 18), + (3482, 3505, 18), + (3507, 3515, 18), + (3517, 3517, 18), + (3520, 3526, 18), + (3530, 3530, 18), + (3535, 3537, 18), + (3538, 3540, 18), + (3542, 3542, 18), + (3544, 3551, 18), + (3558, 3567, 18), + (3570, 3571, 18), + (3572, 3572, 18), + (3585, 3632, 19), + (3633, 3633, 19), + (3634, 3635, 19), + (3636, 3642, 19), + (3647, 3647, 0), + (3648, 3653, 19), + (3654, 3654, 19), + (3655, 3662, 19), + (3663, 3663, 19), + (3664, 3673, 19), + (3674, 3675, 19), + (3713, 3714, 20), + (3716, 3716, 20), + (3718, 3722, 20), + (3724, 3747, 20), + (3749, 3749, 20), + (3751, 3760, 20), + (3761, 3761, 20), + (3762, 3763, 20), + (3764, 3772, 20), + (3773, 3773, 20), + (3776, 3780, 20), + (3782, 3782, 20), + (3784, 3790, 20), + (3792, 3801, 20), + (3804, 3807, 20), + (3840, 3840, 21), + (3841, 3843, 21), + (3844, 3858, 21), + (3859, 3859, 21), + (3860, 3860, 21), + (3861, 3863, 21), + (3864, 3865, 21), + (3866, 3871, 21), + (3872, 3881, 21), + (3882, 3891, 21), + (3892, 3892, 21), + (3893, 3893, 21), + (3894, 3894, 21), + (3895, 3895, 21), + (3896, 3896, 21), + (3897, 3897, 21), + (3898, 3898, 21), + (3899, 3899, 21), + (3900, 3900, 21), + (3901, 3901, 21), + (3902, 3903, 21), + (3904, 3911, 21), + (3913, 3948, 21), + (3953, 3966, 21), + (3967, 3967, 21), + (3968, 3972, 21), + (3973, 3973, 21), + (3974, 3975, 21), + (3976, 3980, 21), + (3981, 3991, 21), + (3993, 4028, 21), + (4030, 4037, 21), + (4038, 4038, 21), + (4039, 4044, 21), + (4046, 4047, 21), + (4048, 4052, 21), + (4053, 4056, 0), + (4057, 4058, 21), + (4096, 4138, 22), + (4139, 4140, 22), + (4141, 4144, 22), + (4145, 4145, 22), + (4146, 4151, 22), + (4152, 4152, 22), + (4153, 4154, 22), + (4155, 4156, 22), + (4157, 4158, 22), + (4159, 4159, 22), + (4160, 4169, 22), + (4170, 4175, 22), + (4176, 4181, 22), + (4182, 4183, 22), + (4184, 4185, 22), + (4186, 4189, 22), + (4190, 4192, 22), + (4193, 4193, 22), + (4194, 4196, 22), + (4197, 4198, 22), + (4199, 4205, 22), + (4206, 4208, 22), + (4209, 4212, 22), + (4213, 4225, 22), + (4226, 4226, 22), + (4227, 4228, 22), + (4229, 4230, 22), + (4231, 4236, 22), + (4237, 4237, 22), + (4238, 4238, 22), + (4239, 4239, 22), + (4240, 4249, 22), + (4250, 4252, 22), + (4253, 4253, 22), + (4254, 4255, 22), + (4256, 4293, 23), + (4295, 4295, 23), + (4301, 4301, 23), + (4304, 4346, 23), + (4347, 4347, 0), + (4348, 4348, 23), + (4349, 4351, 23), + (4352, 4607, 24), + (4608, 4680, 25), + (4682, 4685, 25), + (4688, 4694, 25), + (4696, 4696, 25), + (4698, 4701, 25), + (4704, 4744, 25), + (4746, 4749, 25), + (4752, 4784, 25), + (4786, 4789, 25), + (4792, 4798, 25), + (4800, 4800, 25), + (4802, 4805, 25), + (4808, 4822, 25), + (4824, 4880, 25), + (4882, 4885, 25), + (4888, 4954, 25), + (4957, 4959, 25), + (4960, 4968, 25), + (4969, 4988, 25), + (4992, 5007, 25), + (5008, 5017, 25), + (5024, 5109, 26), + (5112, 5117, 26), + (5120, 5120, 27), + (5121, 5740, 27), + (5741, 5741, 27), + (5742, 5742, 27), + (5743, 5759, 27), + (5760, 5760, 28), + (5761, 5786, 28), + (5787, 5787, 28), + (5788, 5788, 28), + (5792, 5866, 29), + (5867, 5869, 0), + (5870, 5872, 29), + (5873, 5880, 29), + (5888, 5905, 41), + (5906, 5908, 41), + (5909, 5909, 41), + (5919, 5919, 41), + (5920, 5937, 42), + (5938, 5939, 42), + (5940, 5940, 42), + (5941, 5942, 0), + (5952, 5969, 43), + (5970, 5971, 43), + (5984, 5996, 44), + (5998, 6000, 44), + (6002, 6003, 44), + (6016, 6067, 30), + (6068, 6069, 30), + (6070, 6070, 30), + (6071, 6077, 30), + (6078, 6085, 30), + (6086, 6086, 30), + (6087, 6088, 30), + (6089, 6099, 30), + (6100, 6102, 30), + (6103, 6103, 30), + (6104, 6106, 30), + (6107, 6107, 30), + (6108, 6108, 30), + (6109, 6109, 30), + (6112, 6121, 30), + (6128, 6137, 30), + (6144, 6145, 31), + (6146, 6147, 0), + (6148, 6148, 31), + (6149, 6149, 0), + (6150, 6150, 31), + (6151, 6154, 31), + (6155, 6157, 31), + (6158, 6158, 31), + (6159, 6159, 31), + (6160, 6169, 31), + (6176, 6210, 31), + (6211, 6211, 31), + (6212, 6264, 31), + (6272, 6276, 31), + (6277, 6278, 31), + (6279, 6312, 31), + (6313, 6313, 31), + (6314, 6314, 31), + (6320, 6389, 27), + (6400, 6430, 45), + (6432, 6434, 45), + (6435, 6438, 45), + (6439, 6440, 45), + (6441, 6443, 45), + (6448, 6449, 45), + (6450, 6450, 45), + (6451, 6456, 45), + (6457, 6459, 45), + (6464, 6464, 45), + (6468, 6469, 45), + (6470, 6479, 45), + (6480, 6509, 46), + (6512, 6516, 46), + (6528, 6571, 55), + (6576, 6601, 55), + (6608, 6617, 55), + (6618, 6618, 55), + (6622, 6623, 55), + (6624, 6655, 30), + (6656, 6678, 53), + (6679, 6680, 53), + (6681, 6682, 53), + (6683, 6683, 53), + (6686, 6687, 53), + (6688, 6740, 77), + (6741, 6741, 77), + (6742, 6742, 77), + (6743, 6743, 77), + (6744, 6750, 77), + (6752, 6752, 77), + (6753, 6753, 77), + (6754, 6754, 77), + (6755, 6756, 77), + (6757, 6764, 77), + (6765, 6770, 77), + (6771, 6780, 77), + (6783, 6783, 77), + (6784, 6793, 77), + (6800, 6809, 77), + (6816, 6822, 77), + (6823, 6823, 77), + (6824, 6829, 77), + (6832, 6845, 40), + (6846, 6846, 40), + (6847, 6862, 40), + (6912, 6915, 61), + (6916, 6916, 61), + (6917, 6963, 61), + (6964, 6964, 61), + (6965, 6965, 61), + (6966, 6970, 61), + (6971, 6971, 61), + (6972, 6972, 61), + (6973, 6977, 61), + (6978, 6978, 61), + (6979, 6980, 61), + (6981, 6988, 61), + (6992, 7001, 61), + (7002, 7008, 61), + (7009, 7018, 61), + (7019, 7027, 61), + (7028, 7036, 61), + (7037, 7038, 61), + (7040, 7041, 66), + (7042, 7042, 66), + (7043, 7072, 66), + (7073, 7073, 66), + (7074, 7077, 66), + (7078, 7079, 66), + (7080, 7081, 66), + (7082, 7082, 66), + (7083, 7085, 66), + (7086, 7087, 66), + (7088, 7097, 66), + (7098, 7103, 66), + (7104, 7141, 92), + (7142, 7142, 92), + (7143, 7143, 92), + (7144, 7145, 92), + (7146, 7148, 92), + (7149, 7149, 92), + (7150, 7150, 92), + (7151, 7153, 92), + (7154, 7155, 92), + (7164, 7167, 92), + (7168, 7203, 67), + (7204, 7211, 67), + (7212, 7219, 67), + (7220, 7221, 67), + (7222, 7223, 67), + (7227, 7231, 67), + (7232, 7241, 67), + (7245, 7247, 67), + (7248, 7257, 68), + (7258, 7287, 68), + (7288, 7293, 68), + (7294, 7295, 68), + (7296, 7304, 3), + (7312, 7354, 23), + (7357, 7359, 23), + (7360, 7367, 66), + (7376, 7378, 40), + (7379, 7379, 0), + (7380, 7392, 40), + (7393, 7393, 0), + (7394, 7400, 40), + (7401, 7404, 0), + (7405, 7405, 40), + (7406, 7411, 0), + (7412, 7412, 40), + (7413, 7414, 0), + (7415, 7415, 0), + (7416, 7417, 40), + (7418, 7418, 0), + (7424, 7461, 1), + (7462, 7466, 2), + (7467, 7467, 3), + (7468, 7516, 1), + (7517, 7521, 2), + (7522, 7525, 1), + (7526, 7530, 2), + (7531, 7543, 1), + (7544, 7544, 3), + (7545, 7578, 1), + (7579, 7614, 1), + (7615, 7615, 2), + (7616, 7679, 40), + (7680, 7935, 1), + (7936, 7957, 2), + (7960, 7965, 2), + (7968, 8005, 2), + (8008, 8013, 2), + (8016, 8023, 2), + (8025, 8025, 2), + (8027, 8027, 2), + (8029, 8029, 2), + (8031, 8061, 2), + (8064, 8116, 2), + (8118, 8124, 2), + (8125, 8125, 2), + (8126, 8126, 2), + (8127, 8129, 2), + (8130, 8132, 2), + (8134, 8140, 2), + (8141, 8143, 2), + (8144, 8147, 2), + (8150, 8155, 2), + (8157, 8159, 2), + (8160, 8172, 2), + (8173, 8175, 2), + (8178, 8180, 2), + (8182, 8188, 2), + (8189, 8190, 2), + (8192, 8202, 0), + (8203, 8203, 0), + (8204, 8205, 40), + (8206, 8207, 0), + (8208, 8213, 0), + (8214, 8215, 0), + (8216, 8216, 0), + (8217, 8217, 0), + (8218, 8218, 0), + (8219, 8220, 0), + (8221, 8221, 0), + (8222, 8222, 0), + (8223, 8223, 0), + (8224, 8231, 0), + (8232, 8232, 0), + (8233, 8233, 0), + (8234, 8238, 0), + (8239, 8239, 0), + (8240, 8248, 0), + (8249, 8249, 0), + (8250, 8250, 0), + (8251, 8254, 0), + (8255, 8256, 0), + (8257, 8259, 0), + (8260, 8260, 0), + (8261, 8261, 0), + (8262, 8262, 0), + (8263, 8273, 0), + (8274, 8274, 0), + (8275, 8275, 0), + (8276, 8276, 0), + (8277, 8286, 0), + (8287, 8287, 0), + (8288, 8292, 0), + (8294, 8303, 0), + (8304, 8304, 0), + (8305, 8305, 1), + (8308, 8313, 0), + (8314, 8316, 0), + (8317, 8317, 0), + (8318, 8318, 0), + (8319, 8319, 1), + (8320, 8329, 0), + (8330, 8332, 0), + (8333, 8333, 0), + (8334, 8334, 0), + (8336, 8348, 1), + (8352, 8384, 0), + (8400, 8412, 40), + (8413, 8416, 40), + (8417, 8417, 40), + (8418, 8420, 40), + (8421, 8432, 40), + (8448, 8449, 0), + (8450, 8450, 0), + (8451, 8454, 0), + (8455, 8455, 0), + (8456, 8457, 0), + (8458, 8467, 0), + (8468, 8468, 0), + (8469, 8469, 0), + (8470, 8471, 0), + (8472, 8472, 0), + (8473, 8477, 0), + (8478, 8483, 0), + (8484, 8484, 0), + (8485, 8485, 0), + (8486, 8486, 2), + (8487, 8487, 0), + (8488, 8488, 0), + (8489, 8489, 0), + (8490, 8491, 1), + (8492, 8493, 0), + (8494, 8494, 0), + (8495, 8497, 0), + (8498, 8498, 1), + (8499, 8500, 0), + (8501, 8504, 0), + (8505, 8505, 0), + (8506, 8507, 0), + (8508, 8511, 0), + (8512, 8516, 0), + (8517, 8521, 0), + (8522, 8522, 0), + (8523, 8523, 0), + (8524, 8525, 0), + (8526, 8526, 1), + (8527, 8527, 0), + (8528, 8543, 0), + (8544, 8578, 1), + (8579, 8580, 1), + (8581, 8584, 1), + (8585, 8585, 0), + (8586, 8587, 0), + (8592, 8596, 0), + (8597, 8601, 0), + (8602, 8603, 0), + (8604, 8607, 0), + (8608, 8608, 0), + (8609, 8610, 0), + (8611, 8611, 0), + (8612, 8613, 0), + (8614, 8614, 0), + (8615, 8621, 0), + (8622, 8622, 0), + (8623, 8653, 0), + (8654, 8655, 0), + (8656, 8657, 0), + (8658, 8658, 0), + (8659, 8659, 0), + (8660, 8660, 0), + (8661, 8691, 0), + (8692, 8959, 0), + (8960, 8967, 0), + (8968, 8968, 0), + (8969, 8969, 0), + (8970, 8970, 0), + (8971, 8971, 0), + (8972, 8991, 0), + (8992, 8993, 0), + (8994, 9000, 0), + (9001, 9001, 0), + (9002, 9002, 0), + (9003, 9083, 0), + (9084, 9084, 0), + (9085, 9114, 0), + (9115, 9139, 0), + (9140, 9179, 0), + (9180, 9185, 0), + (9186, 9254, 0), + (9280, 9290, 0), + (9312, 9371, 0), + (9372, 9449, 0), + (9450, 9471, 0), + (9472, 9654, 0), + (9655, 9655, 0), + (9656, 9664, 0), + (9665, 9665, 0), + (9666, 9719, 0), + (9720, 9727, 0), + (9728, 9838, 0), + (9839, 9839, 0), + (9840, 10087, 0), + (10088, 10088, 0), + (10089, 10089, 0), + (10090, 10090, 0), + (10091, 10091, 0), + (10092, 10092, 0), + (10093, 10093, 0), + (10094, 10094, 0), + (10095, 10095, 0), + (10096, 10096, 0), + (10097, 10097, 0), + (10098, 10098, 0), + (10099, 10099, 0), + (10100, 10100, 0), + (10101, 10101, 0), + (10102, 10131, 0), + (10132, 10175, 0), + (10176, 10180, 0), + (10181, 10181, 0), + (10182, 10182, 0), + (10183, 10213, 0), + (10214, 10214, 0), + (10215, 10215, 0), + (10216, 10216, 0), + (10217, 10217, 0), + (10218, 10218, 0), + (10219, 10219, 0), + (10220, 10220, 0), + (10221, 10221, 0), + (10222, 10222, 0), + (10223, 10223, 0), + (10224, 10239, 0), + (10240, 10495, 52), + (10496, 10626, 0), + (10627, 10627, 0), + (10628, 10628, 0), + (10629, 10629, 0), + (10630, 10630, 0), + (10631, 10631, 0), + (10632, 10632, 0), + (10633, 10633, 0), + (10634, 10634, 0), + (10635, 10635, 0), + (10636, 10636, 0), + (10637, 10637, 0), + (10638, 10638, 0), + (10639, 10639, 0), + (10640, 10640, 0), + (10641, 10641, 0), + (10642, 10642, 0), + (10643, 10643, 0), + (10644, 10644, 0), + (10645, 10645, 0), + (10646, 10646, 0), + (10647, 10647, 0), + (10648, 10648, 0), + (10649, 10711, 0), + (10712, 10712, 0), + (10713, 10713, 0), + (10714, 10714, 0), + (10715, 10715, 0), + (10716, 10747, 0), + (10748, 10748, 0), + (10749, 10749, 0), + (10750, 11007, 0), + (11008, 11055, 0), + (11056, 11076, 0), + (11077, 11078, 0), + (11079, 11084, 0), + (11085, 11123, 0), + (11126, 11157, 0), + (11159, 11263, 0), + (11264, 11359, 56), + (11360, 11387, 1), + (11388, 11389, 1), + (11390, 11391, 1), + (11392, 11492, 54), + (11493, 11498, 54), + (11499, 11502, 54), + (11503, 11505, 54), + (11506, 11507, 54), + (11513, 11516, 54), + (11517, 11517, 54), + (11518, 11519, 54), + (11520, 11557, 23), + (11559, 11559, 23), + (11565, 11565, 23), + (11568, 11623, 57), + (11631, 11631, 57), + (11632, 11632, 57), + (11647, 11647, 57), + (11648, 11670, 25), + (11680, 11686, 25), + (11688, 11694, 25), + (11696, 11702, 25), + (11704, 11710, 25), + (11712, 11718, 25), + (11720, 11726, 25), + (11728, 11734, 25), + (11736, 11742, 25), + (11744, 11775, 3), + (11776, 11777, 0), + (11778, 11778, 0), + (11779, 11779, 0), + (11780, 11780, 0), + (11781, 11781, 0), + (11782, 11784, 0), + (11785, 11785, 0), + (11786, 11786, 0), + (11787, 11787, 0), + (11788, 11788, 0), + (11789, 11789, 0), + (11790, 11798, 0), + (11799, 11799, 0), + (11800, 11801, 0), + (11802, 11802, 0), + (11803, 11803, 0), + (11804, 11804, 0), + (11805, 11805, 0), + (11806, 11807, 0), + (11808, 11808, 0), + (11809, 11809, 0), + (11810, 11810, 0), + (11811, 11811, 0), + (11812, 11812, 0), + (11813, 11813, 0), + (11814, 11814, 0), + (11815, 11815, 0), + (11816, 11816, 0), + (11817, 11817, 0), + (11818, 11822, 0), + (11823, 11823, 0), + (11824, 11833, 0), + (11834, 11835, 0), + (11836, 11839, 0), + (11840, 11840, 0), + (11841, 11841, 0), + (11842, 11842, 0), + (11843, 11855, 0), + (11856, 11857, 0), + (11858, 11860, 0), + (11861, 11861, 0), + (11862, 11862, 0), + (11863, 11863, 0), + (11864, 11864, 0), + (11865, 11865, 0), + (11866, 11866, 0), + (11867, 11867, 0), + (11868, 11868, 0), + (11869, 11869, 0), + (11904, 11929, 35), + (11931, 12019, 35), + (12032, 12245, 35), + (12272, 12287, 0), + (12288, 12288, 0), + (12289, 12291, 0), + (12292, 12292, 0), + (12293, 12293, 35), + (12294, 12294, 0), + (12295, 12295, 35), + (12296, 12296, 0), + (12297, 12297, 0), + (12298, 12298, 0), + (12299, 12299, 0), + (12300, 12300, 0), + (12301, 12301, 0), + (12302, 12302, 0), + (12303, 12303, 0), + (12304, 12304, 0), + (12305, 12305, 0), + (12306, 12307, 0), + (12308, 12308, 0), + (12309, 12309, 0), + (12310, 12310, 0), + (12311, 12311, 0), + (12312, 12312, 0), + (12313, 12313, 0), + (12314, 12314, 0), + (12315, 12315, 0), + (12316, 12316, 0), + (12317, 12317, 0), + (12318, 12319, 0), + (12320, 12320, 0), + (12321, 12329, 35), + (12330, 12333, 40), + (12334, 12335, 24), + (12336, 12336, 0), + (12337, 12341, 0), + (12342, 12343, 0), + (12344, 12346, 35), + (12347, 12347, 35), + (12348, 12348, 0), + (12349, 12349, 0), + (12350, 12351, 0), + (12353, 12438, 32), + (12441, 12442, 40), + (12443, 12444, 0), + (12445, 12446, 32), + (12447, 12447, 32), + (12448, 12448, 0), + (12449, 12538, 33), + (12539, 12539, 0), + (12540, 12540, 0), + (12541, 12542, 33), + (12543, 12543, 33), + (12549, 12591, 34), + (12593, 12686, 24), + (12688, 12689, 0), + (12690, 12693, 0), + (12694, 12703, 0), + (12704, 12735, 34), + (12736, 12771, 0), + (12783, 12783, 0), + (12784, 12799, 33), + (12800, 12830, 24), + (12832, 12841, 0), + (12842, 12871, 0), + (12872, 12879, 0), + (12880, 12880, 0), + (12881, 12895, 0), + (12896, 12926, 24), + (12927, 12927, 0), + (12928, 12937, 0), + (12938, 12976, 0), + (12977, 12991, 0), + (12992, 13007, 0), + (13008, 13054, 33), + (13055, 13055, 0), + (13056, 13143, 33), + (13144, 13311, 0), + (13312, 19903, 35), + (19904, 19967, 0), + (19968, 40959, 35), + (40960, 40980, 36), + (40981, 40981, 36), + (40982, 42124, 36), + (42128, 42182, 36), + (42192, 42231, 82), + (42232, 42237, 82), + (42238, 42239, 82), + (42240, 42507, 69), + (42508, 42508, 69), + (42509, 42511, 69), + (42512, 42527, 69), + (42528, 42537, 69), + (42538, 42539, 69), + (42560, 42605, 3), + (42606, 42606, 3), + (42607, 42607, 3), + (42608, 42610, 3), + (42611, 42611, 3), + (42612, 42621, 3), + (42622, 42622, 3), + (42623, 42623, 3), + (42624, 42651, 3), + (42652, 42653, 3), + (42654, 42655, 3), + (42656, 42725, 83), + (42726, 42735, 83), + (42736, 42737, 83), + (42738, 42743, 83), + (42752, 42774, 0), + (42775, 42783, 0), + (42784, 42785, 0), + (42786, 42863, 1), + (42864, 42864, 1), + (42865, 42887, 1), + (42888, 42888, 0), + (42889, 42890, 0), + (42891, 42894, 1), + (42895, 42895, 1), + (42896, 42954, 1), + (42960, 42961, 1), + (42963, 42963, 1), + (42965, 42969, 1), + (42994, 42996, 1), + (42997, 42998, 1), + (42999, 42999, 1), + (43000, 43001, 1), + (43002, 43002, 1), + (43003, 43007, 1), + (43008, 43009, 58), + (43010, 43010, 58), + (43011, 43013, 58), + (43014, 43014, 58), + (43015, 43018, 58), + (43019, 43019, 58), + (43020, 43042, 58), + (43043, 43044, 58), + (43045, 43046, 58), + (43047, 43047, 58), + (43048, 43051, 58), + (43052, 43052, 58), + (43056, 43061, 0), + (43062, 43063, 0), + (43064, 43064, 0), + (43065, 43065, 0), + (43072, 43123, 64), + (43124, 43127, 64), + (43136, 43137, 70), + (43138, 43187, 70), + (43188, 43203, 70), + (43204, 43205, 70), + (43214, 43215, 70), + (43216, 43225, 70), + (43232, 43249, 9), + (43250, 43255, 9), + (43256, 43258, 9), + (43259, 43259, 9), + (43260, 43260, 9), + (43261, 43262, 9), + (43263, 43263, 9), + (43264, 43273, 71), + (43274, 43301, 71), + (43302, 43309, 71), + (43310, 43310, 0), + (43311, 43311, 71), + (43312, 43334, 72), + (43335, 43345, 72), + (43346, 43347, 72), + (43359, 43359, 72), + (43360, 43388, 24), + (43392, 43394, 84), + (43395, 43395, 84), + (43396, 43442, 84), + (43443, 43443, 84), + (43444, 43445, 84), + (43446, 43449, 84), + (43450, 43451, 84), + (43452, 43453, 84), + (43454, 43456, 84), + (43457, 43469, 84), + (43471, 43471, 0), + (43472, 43481, 84), + (43486, 43487, 84), + (43488, 43492, 22), + (43493, 43493, 22), + (43494, 43494, 22), + (43495, 43503, 22), + (43504, 43513, 22), + (43514, 43518, 22), + (43520, 43560, 76), + (43561, 43566, 76), + (43567, 43568, 76), + (43569, 43570, 76), + (43571, 43572, 76), + (43573, 43574, 76), + (43584, 43586, 76), + (43587, 43587, 76), + (43588, 43595, 76), + (43596, 43596, 76), + (43597, 43597, 76), + (43600, 43609, 76), + (43612, 43615, 76), + (43616, 43631, 22), + (43632, 43632, 22), + (43633, 43638, 22), + (43639, 43641, 22), + (43642, 43642, 22), + (43643, 43643, 22), + (43644, 43644, 22), + (43645, 43645, 22), + (43646, 43647, 22), + (43648, 43695, 78), + (43696, 43696, 78), + (43697, 43697, 78), + (43698, 43700, 78), + (43701, 43702, 78), + (43703, 43704, 78), + (43705, 43709, 78), + (43710, 43711, 78), + (43712, 43712, 78), + (43713, 43713, 78), + (43714, 43714, 78), + (43739, 43740, 78), + (43741, 43741, 78), + (43742, 43743, 78), + (43744, 43754, 85), + (43755, 43755, 85), + (43756, 43757, 85), + (43758, 43759, 85), + (43760, 43761, 85), + (43762, 43762, 85), + (43763, 43764, 85), + (43765, 43765, 85), + (43766, 43766, 85), + (43777, 43782, 25), + (43785, 43790, 25), + (43793, 43798, 25), + (43808, 43814, 25), + (43816, 43822, 25), + (43824, 43866, 1), + (43867, 43867, 0), + (43868, 43871, 1), + (43872, 43876, 1), + (43877, 43877, 2), + (43878, 43880, 1), + (43881, 43881, 1), + (43882, 43883, 0), + (43888, 43967, 26), + (43968, 44002, 85), + (44003, 44004, 85), + (44005, 44005, 85), + (44006, 44007, 85), + (44008, 44008, 85), + (44009, 44010, 85), + (44011, 44011, 85), + (44012, 44012, 85), + (44013, 44013, 85), + (44016, 44025, 85), + (44032, 55203, 24), + (55216, 55238, 24), + (55243, 55291, 24), + (63744, 64109, 35), + (64112, 64217, 35), + (64256, 64262, 1), + (64275, 64279, 4), + (64285, 64285, 5), + (64286, 64286, 5), + (64287, 64296, 5), + (64297, 64297, 5), + (64298, 64310, 5), + (64312, 64316, 5), + (64318, 64318, 5), + (64320, 64321, 5), + (64323, 64324, 5), + (64326, 64335, 5), + (64336, 64433, 6), + (64434, 64450, 6), + (64467, 64829, 6), + (64830, 64830, 0), + (64831, 64831, 0), + (64832, 64847, 6), + (64848, 64911, 6), + (64914, 64967, 6), + (64975, 64975, 6), + (65008, 65019, 6), + (65020, 65020, 6), + (65021, 65023, 6), + (65024, 65039, 40), + (65040, 65046, 0), + (65047, 65047, 0), + (65048, 65048, 0), + (65049, 65049, 0), + (65056, 65069, 40), + (65070, 65071, 3), + (65072, 65072, 0), + (65073, 65074, 0), + (65075, 65076, 0), + (65077, 65077, 0), + (65078, 65078, 0), + (65079, 65079, 0), + (65080, 65080, 0), + (65081, 65081, 0), + (65082, 65082, 0), + (65083, 65083, 0), + (65084, 65084, 0), + (65085, 65085, 0), + (65086, 65086, 0), + (65087, 65087, 0), + (65088, 65088, 0), + (65089, 65089, 0), + (65090, 65090, 0), + (65091, 65091, 0), + (65092, 65092, 0), + (65093, 65094, 0), + (65095, 65095, 0), + (65096, 65096, 0), + (65097, 65100, 0), + (65101, 65103, 0), + (65104, 65106, 0), + (65108, 65111, 0), + (65112, 65112, 0), + (65113, 65113, 0), + (65114, 65114, 0), + (65115, 65115, 0), + (65116, 65116, 0), + (65117, 65117, 0), + (65118, 65118, 0), + (65119, 65121, 0), + (65122, 65122, 0), + (65123, 65123, 0), + (65124, 65126, 0), + (65128, 65128, 0), + (65129, 65129, 0), + (65130, 65131, 0), + (65136, 65140, 6), + (65142, 65276, 6), + (65279, 65279, 0), + (65281, 65283, 0), + (65284, 65284, 0), + (65285, 65287, 0), + (65288, 65288, 0), + (65289, 65289, 0), + (65290, 65290, 0), + (65291, 65291, 0), + (65292, 65292, 0), + (65293, 65293, 0), + (65294, 65295, 0), + (65296, 65305, 0), + (65306, 65307, 0), + (65308, 65310, 0), + (65311, 65312, 0), + (65313, 65338, 1), + (65339, 65339, 0), + (65340, 65340, 0), + (65341, 65341, 0), + (65342, 65342, 0), + (65343, 65343, 0), + (65344, 65344, 0), + (65345, 65370, 1), + (65371, 65371, 0), + (65372, 65372, 0), + (65373, 65373, 0), + (65374, 65374, 0), + (65375, 65375, 0), + (65376, 65376, 0), + (65377, 65377, 0), + (65378, 65378, 0), + (65379, 65379, 0), + (65380, 65381, 0), + (65382, 65391, 33), + (65392, 65392, 0), + (65393, 65437, 33), + (65438, 65439, 0), + (65440, 65470, 24), + (65474, 65479, 24), + (65482, 65487, 24), + (65490, 65495, 24), + (65498, 65500, 24), + (65504, 65505, 0), + (65506, 65506, 0), + (65507, 65507, 0), + (65508, 65508, 0), + (65509, 65510, 0), + (65512, 65512, 0), + (65513, 65516, 0), + (65517, 65518, 0), + (65529, 65531, 0), + (65532, 65533, 0), + (65536, 65547, 47), + (65549, 65574, 47), + (65576, 65594, 47), + (65596, 65597, 47), + (65599, 65613, 47), + (65616, 65629, 47), + (65664, 65786, 47), + (65792, 65794, 0), + (65799, 65843, 0), + (65847, 65855, 0), + (65856, 65908, 2), + (65909, 65912, 2), + (65913, 65929, 2), + (65930, 65931, 2), + (65932, 65934, 2), + (65936, 65948, 0), + (65952, 65952, 2), + (66000, 66044, 0), + (66045, 66045, 40), + (66176, 66204, 73), + (66208, 66256, 74), + (66272, 66272, 40), + (66273, 66299, 0), + (66304, 66335, 37), + (66336, 66339, 37), + (66349, 66351, 37), + (66352, 66368, 38), + (66369, 66369, 38), + (66370, 66377, 38), + (66378, 66378, 38), + (66384, 66421, 119), + (66422, 66426, 119), + (66432, 66461, 48), + (66463, 66463, 48), + (66464, 66499, 59), + (66504, 66511, 59), + (66512, 66512, 59), + (66513, 66517, 59), + (66560, 66639, 39), + (66640, 66687, 49), + (66688, 66717, 50), + (66720, 66729, 50), + (66736, 66771, 135), + (66776, 66811, 135), + (66816, 66855, 105), + (66864, 66915, 102), + (66927, 66927, 102), + (66928, 66938, 160), + (66940, 66954, 160), + (66956, 66962, 160), + (66964, 66965, 160), + (66967, 66977, 160), + (66979, 66993, 160), + (66995, 67001, 160), + (67003, 67004, 160), + (67072, 67382, 109), + (67392, 67413, 109), + (67424, 67431, 109), + (67456, 67461, 1), + (67463, 67504, 1), + (67506, 67514, 1), + (67584, 67589, 51), + (67592, 67592, 51), + (67594, 67637, 51), + (67639, 67640, 51), + (67644, 67644, 51), + (67647, 67647, 51), + (67648, 67669, 86), + (67671, 67671, 86), + (67672, 67679, 86), + (67680, 67702, 117), + (67703, 67704, 117), + (67705, 67711, 117), + (67712, 67742, 116), + (67751, 67759, 116), + (67808, 67826, 127), + (67828, 67829, 127), + (67835, 67839, 127), + (67840, 67861, 63), + (67862, 67867, 63), + (67871, 67871, 63), + (67872, 67897, 75), + (67903, 67903, 75), + (67968, 67999, 97), + (68000, 68023, 96), + (68028, 68029, 96), + (68030, 68031, 96), + (68032, 68047, 96), + (68050, 68095, 96), + (68096, 68096, 60), + (68097, 68099, 60), + (68101, 68102, 60), + (68108, 68111, 60), + (68112, 68115, 60), + (68117, 68119, 60), + (68121, 68149, 60), + (68152, 68154, 60), + (68159, 68159, 60), + (68160, 68168, 60), + (68176, 68184, 60), + (68192, 68220, 87), + (68221, 68222, 87), + (68223, 68223, 87), + (68224, 68252, 115), + (68253, 68255, 115), + (68288, 68295, 111), + (68296, 68296, 111), + (68297, 68324, 111), + (68325, 68326, 111), + (68331, 68335, 111), + (68336, 68342, 111), + (68352, 68405, 79), + (68409, 68415, 79), + (68416, 68437, 88), + (68440, 68447, 88), + (68448, 68466, 89), + (68472, 68479, 89), + (68480, 68497, 120), + (68505, 68508, 120), + (68521, 68527, 120), + (68608, 68680, 90), + (68736, 68786, 129), + (68800, 68850, 129), + (68858, 68863, 129), + (68864, 68899, 145), + (68900, 68903, 145), + (68912, 68921, 145), + (69216, 69246, 6), + (69248, 69289, 155), + (69291, 69292, 155), + (69293, 69293, 155), + (69296, 69297, 155), + (69373, 69375, 6), + (69376, 69404, 147), + (69405, 69414, 147), + (69415, 69415, 147), + (69424, 69445, 146), + (69446, 69456, 146), + (69457, 69460, 146), + (69461, 69465, 146), + (69488, 69505, 157), + (69506, 69509, 157), + (69510, 69513, 157), + (69552, 69572, 152), + (69573, 69579, 152), + (69600, 69622, 148), + (69632, 69632, 93), + (69633, 69633, 93), + (69634, 69634, 93), + (69635, 69687, 93), + (69688, 69702, 93), + (69703, 69709, 93), + (69714, 69733, 93), + (69734, 69743, 93), + (69744, 69744, 93), + (69745, 69746, 93), + (69747, 69748, 93), + (69749, 69749, 93), + (69759, 69759, 93), + (69760, 69761, 91), + (69762, 69762, 91), + (69763, 69807, 91), + (69808, 69810, 91), + (69811, 69814, 91), + (69815, 69816, 91), + (69817, 69818, 91), + (69819, 69820, 91), + (69821, 69821, 91), + (69822, 69825, 91), + (69826, 69826, 91), + (69837, 69837, 91), + (69840, 69864, 100), + (69872, 69881, 100), + (69888, 69890, 95), + (69891, 69926, 95), + (69927, 69931, 95), + (69932, 69932, 95), + (69933, 69940, 95), + (69942, 69951, 95), + (69952, 69955, 95), + (69956, 69956, 95), + (69957, 69958, 95), + (69959, 69959, 95), + (69968, 70002, 110), + (70003, 70003, 110), + (70004, 70005, 110), + (70006, 70006, 110), + (70016, 70017, 99), + (70018, 70018, 99), + (70019, 70066, 99), + (70067, 70069, 99), + (70070, 70078, 99), + (70079, 70080, 99), + (70081, 70084, 99), + (70085, 70088, 99), + (70089, 70092, 99), + (70093, 70093, 99), + (70094, 70094, 99), + (70095, 70095, 99), + (70096, 70105, 99), + (70106, 70106, 99), + (70107, 70107, 99), + (70108, 70108, 99), + (70109, 70111, 99), + (70113, 70132, 18), + (70144, 70161, 108), + (70163, 70187, 108), + (70188, 70190, 108), + (70191, 70193, 108), + (70194, 70195, 108), + (70196, 70196, 108), + (70197, 70197, 108), + (70198, 70199, 108), + (70200, 70205, 108), + (70206, 70206, 108), + (70207, 70208, 108), + (70209, 70209, 108), + (70272, 70278, 128), + (70280, 70280, 128), + (70282, 70285, 128), + (70287, 70301, 128), + (70303, 70312, 128), + (70313, 70313, 128), + (70320, 70366, 122), + (70367, 70367, 122), + (70368, 70370, 122), + (70371, 70378, 122), + (70384, 70393, 122), + (70400, 70401, 106), + (70402, 70403, 106), + (70405, 70412, 106), + (70415, 70416, 106), + (70419, 70440, 106), + (70442, 70448, 106), + (70450, 70451, 106), + (70453, 70457, 106), + (70459, 70459, 40), + (70460, 70460, 106), + (70461, 70461, 106), + (70462, 70463, 106), + (70464, 70464, 106), + (70465, 70468, 106), + (70471, 70472, 106), + (70475, 70477, 106), + (70480, 70480, 106), + (70487, 70487, 106), + (70493, 70497, 106), + (70498, 70499, 106), + (70502, 70508, 106), + (70512, 70516, 106), + (70656, 70708, 134), + (70709, 70711, 134), + (70712, 70719, 134), + (70720, 70721, 134), + (70722, 70724, 134), + (70725, 70725, 134), + (70726, 70726, 134), + (70727, 70730, 134), + (70731, 70735, 134), + (70736, 70745, 134), + (70746, 70747, 134), + (70749, 70749, 134), + (70750, 70750, 134), + (70751, 70753, 134), + (70784, 70831, 123), + (70832, 70834, 123), + (70835, 70840, 123), + (70841, 70841, 123), + (70842, 70842, 123), + (70843, 70846, 123), + (70847, 70848, 123), + (70849, 70849, 123), + (70850, 70851, 123), + (70852, 70853, 123), + (70854, 70854, 123), + (70855, 70855, 123), + (70864, 70873, 123), + (71040, 71086, 121), + (71087, 71089, 121), + (71090, 71093, 121), + (71096, 71099, 121), + (71100, 71101, 121), + (71102, 71102, 121), + (71103, 71104, 121), + (71105, 71127, 121), + (71128, 71131, 121), + (71132, 71133, 121), + (71168, 71215, 113), + (71216, 71218, 113), + (71219, 71226, 113), + (71227, 71228, 113), + (71229, 71229, 113), + (71230, 71230, 113), + (71231, 71232, 113), + (71233, 71235, 113), + (71236, 71236, 113), + (71248, 71257, 113), + (71264, 71276, 31), + (71296, 71338, 101), + (71339, 71339, 101), + (71340, 71340, 101), + (71341, 71341, 101), + (71342, 71343, 101), + (71344, 71349, 101), + (71350, 71350, 101), + (71351, 71351, 101), + (71352, 71352, 101), + (71353, 71353, 101), + (71360, 71369, 101), + (71424, 71450, 125), + (71453, 71455, 125), + (71456, 71457, 125), + (71458, 71461, 125), + (71462, 71462, 125), + (71463, 71467, 125), + (71472, 71481, 125), + (71482, 71483, 125), + (71484, 71486, 125), + (71487, 71487, 125), + (71488, 71494, 125), + (71680, 71723, 141), + (71724, 71726, 141), + (71727, 71735, 141), + (71736, 71736, 141), + (71737, 71738, 141), + (71739, 71739, 141), + (71840, 71903, 124), + (71904, 71913, 124), + (71914, 71922, 124), + (71935, 71935, 124), + (71936, 71942, 153), + (71945, 71945, 153), + (71948, 71955, 153), + (71957, 71958, 153), + (71960, 71983, 153), + (71984, 71989, 153), + (71991, 71992, 153), + (71995, 71996, 153), + (71997, 71997, 153), + (71998, 71998, 153), + (71999, 71999, 153), + (72000, 72000, 153), + (72001, 72001, 153), + (72002, 72002, 153), + (72003, 72003, 153), + (72004, 72006, 153), + (72016, 72025, 153), + (72096, 72103, 149), + (72106, 72144, 149), + (72145, 72147, 149), + (72148, 72151, 149), + (72154, 72155, 149), + (72156, 72159, 149), + (72160, 72160, 149), + (72161, 72161, 149), + (72162, 72162, 149), + (72163, 72163, 149), + (72164, 72164, 149), + (72192, 72192, 140), + (72193, 72202, 140), + (72203, 72242, 140), + (72243, 72248, 140), + (72249, 72249, 140), + (72250, 72250, 140), + (72251, 72254, 140), + (72255, 72262, 140), + (72263, 72263, 140), + (72272, 72272, 139), + (72273, 72278, 139), + (72279, 72280, 139), + (72281, 72283, 139), + (72284, 72329, 139), + (72330, 72342, 139), + (72343, 72343, 139), + (72344, 72345, 139), + (72346, 72348, 139), + (72349, 72349, 139), + (72350, 72354, 139), + (72368, 72383, 27), + (72384, 72440, 118), + (72448, 72457, 9), + (72704, 72712, 132), + (72714, 72750, 132), + (72751, 72751, 132), + (72752, 72758, 132), + (72760, 72765, 132), + (72766, 72766, 132), + (72767, 72767, 132), + (72768, 72768, 132), + (72769, 72773, 132), + (72784, 72793, 132), + (72794, 72812, 132), + (72816, 72817, 133), + (72818, 72847, 133), + (72850, 72871, 133), + (72873, 72873, 133), + (72874, 72880, 133), + (72881, 72881, 133), + (72882, 72883, 133), + (72884, 72884, 133), + (72885, 72886, 133), + (72960, 72966, 137), + (72968, 72969, 137), + (72971, 73008, 137), + (73009, 73014, 137), + (73018, 73018, 137), + (73020, 73021, 137), + (73023, 73029, 137), + (73030, 73030, 137), + (73031, 73031, 137), + (73040, 73049, 137), + (73056, 73061, 142), + (73063, 73064, 142), + (73066, 73097, 142), + (73098, 73102, 142), + (73104, 73105, 142), + (73107, 73108, 142), + (73109, 73109, 142), + (73110, 73110, 142), + (73111, 73111, 142), + (73112, 73112, 142), + (73120, 73129, 142), + (73440, 73458, 143), + (73459, 73460, 143), + (73461, 73462, 143), + (73463, 73464, 143), + (73472, 73473, 161), + (73474, 73474, 161), + (73475, 73475, 161), + (73476, 73488, 161), + (73490, 73523, 161), + (73524, 73525, 161), + (73526, 73530, 161), + (73534, 73535, 161), + (73536, 73536, 161), + (73537, 73537, 161), + (73538, 73538, 161), + (73539, 73551, 161), + (73552, 73561, 161), + (73648, 73648, 82), + (73664, 73684, 14), + (73685, 73692, 14), + (73693, 73696, 14), + (73697, 73713, 14), + (73727, 73727, 14), + (73728, 74649, 62), + (74752, 74862, 62), + (74864, 74868, 62), + (74880, 75075, 62), + (77712, 77808, 156), + (77809, 77810, 156), + (77824, 78895, 80), + (78896, 78911, 80), + (78912, 78912, 80), + (78913, 78918, 80), + (78919, 78933, 80), + (82944, 83526, 126), + (92160, 92728, 83), + (92736, 92766, 114), + (92768, 92777, 114), + (92782, 92783, 114), + (92784, 92862, 158), + (92864, 92873, 158), + (92880, 92909, 103), + (92912, 92916, 103), + (92917, 92917, 103), + (92928, 92975, 107), + (92976, 92982, 107), + (92983, 92987, 107), + (92988, 92991, 107), + (92992, 92995, 107), + (92996, 92996, 107), + (92997, 92997, 107), + (93008, 93017, 107), + (93019, 93025, 107), + (93027, 93047, 107), + (93053, 93071, 107), + (93760, 93823, 144), + (93824, 93846, 144), + (93847, 93850, 144), + (93952, 94026, 98), + (94031, 94031, 98), + (94032, 94032, 98), + (94033, 94087, 98), + (94095, 94098, 98), + (94099, 94111, 98), + (94176, 94176, 136), + (94177, 94177, 138), + (94178, 94178, 35), + (94179, 94179, 35), + (94180, 94180, 154), + (94192, 94193, 35), + (94208, 100343, 136), + (100352, 101119, 136), + (101120, 101589, 154), + (101632, 101640, 136), + (110576, 110579, 33), + (110581, 110587, 33), + (110589, 110590, 33), + (110592, 110592, 33), + (110593, 110879, 32), + (110880, 110882, 33), + (110898, 110898, 32), + (110928, 110930, 32), + (110933, 110933, 33), + (110948, 110951, 33), + (110960, 111355, 138), + (113664, 113770, 104), + (113776, 113788, 104), + (113792, 113800, 104), + (113808, 113817, 104), + (113820, 113820, 104), + (113821, 113822, 104), + (113823, 113823, 104), + (113824, 113827, 0), + (118528, 118573, 40), + (118576, 118598, 40), + (118608, 118723, 0), + (118784, 119029, 0), + (119040, 119078, 0), + (119081, 119140, 0), + (119141, 119142, 0), + (119143, 119145, 40), + (119146, 119148, 0), + (119149, 119154, 0), + (119155, 119162, 0), + (119163, 119170, 40), + (119171, 119172, 0), + (119173, 119179, 40), + (119180, 119209, 0), + (119210, 119213, 40), + (119214, 119274, 0), + (119296, 119361, 2), + (119362, 119364, 2), + (119365, 119365, 2), + (119488, 119507, 0), + (119520, 119539, 0), + (119552, 119638, 0), + (119648, 119672, 0), + (119808, 119892, 0), + (119894, 119964, 0), + (119966, 119967, 0), + (119970, 119970, 0), + (119973, 119974, 0), + (119977, 119980, 0), + (119982, 119993, 0), + (119995, 119995, 0), + (119997, 120003, 0), + (120005, 120069, 0), + (120071, 120074, 0), + (120077, 120084, 0), + (120086, 120092, 0), + (120094, 120121, 0), + (120123, 120126, 0), + (120128, 120132, 0), + (120134, 120134, 0), + (120138, 120144, 0), + (120146, 120485, 0), + (120488, 120512, 0), + (120513, 120513, 0), + (120514, 120538, 0), + (120539, 120539, 0), + (120540, 120570, 0), + (120571, 120571, 0), + (120572, 120596, 0), + (120597, 120597, 0), + (120598, 120628, 0), + (120629, 120629, 0), + (120630, 120654, 0), + (120655, 120655, 0), + (120656, 120686, 0), + (120687, 120687, 0), + (120688, 120712, 0), + (120713, 120713, 0), + (120714, 120744, 0), + (120745, 120745, 0), + (120746, 120770, 0), + (120771, 120771, 0), + (120772, 120779, 0), + (120782, 120831, 0), + (120832, 121343, 130), + (121344, 121398, 130), + (121399, 121402, 130), + (121403, 121452, 130), + (121453, 121460, 130), + (121461, 121461, 130), + (121462, 121475, 130), + (121476, 121476, 130), + (121477, 121478, 130), + (121479, 121483, 130), + (121499, 121503, 130), + (121505, 121519, 130), + (122624, 122633, 1), + (122634, 122634, 1), + (122635, 122654, 1), + (122661, 122666, 1), + (122880, 122886, 56), + (122888, 122904, 56), + (122907, 122913, 56), + (122915, 122916, 56), + (122918, 122922, 56), + (122928, 122989, 3), + (123023, 123023, 3), + (123136, 123180, 150), + (123184, 123190, 150), + (123191, 123197, 150), + (123200, 123209, 150), + (123214, 123214, 150), + (123215, 123215, 150), + (123536, 123565, 159), + (123566, 123566, 159), + (123584, 123627, 151), + (123628, 123631, 151), + (123632, 123641, 151), + (123647, 123647, 151), + (124112, 124138, 162), + (124139, 124139, 162), + (124140, 124143, 162), + (124144, 124153, 162), + (124896, 124902, 25), + (124904, 124907, 25), + (124909, 124910, 25), + (124912, 124926, 25), + (124928, 125124, 112), + (125127, 125135, 112), + (125136, 125142, 112), + (125184, 125251, 131), + (125252, 125258, 131), + (125259, 125259, 131), + (125264, 125273, 131), + (125278, 125279, 131), + (126065, 126123, 0), + (126124, 126124, 0), + (126125, 126127, 0), + (126128, 126128, 0), + (126129, 126132, 0), + (126209, 126253, 0), + (126254, 126254, 0), + (126255, 126269, 0), + (126464, 126467, 6), + (126469, 126495, 6), + (126497, 126498, 6), + (126500, 126500, 6), + (126503, 126503, 6), + (126505, 126514, 6), + (126516, 126519, 6), + (126521, 126521, 6), + (126523, 126523, 6), + (126530, 126530, 6), + (126535, 126535, 6), + (126537, 126537, 6), + (126539, 126539, 6), + (126541, 126543, 6), + (126545, 126546, 6), + (126548, 126548, 6), + (126551, 126551, 6), + (126553, 126553, 6), + (126555, 126555, 6), + (126557, 126557, 6), + (126559, 126559, 6), + (126561, 126562, 6), + (126564, 126564, 6), + (126567, 126570, 6), + (126572, 126578, 6), + (126580, 126583, 6), + (126585, 126588, 6), + (126590, 126590, 6), + (126592, 126601, 6), + (126603, 126619, 6), + (126625, 126627, 6), + (126629, 126633, 6), + (126635, 126651, 6), + (126704, 126705, 6), + (126976, 127019, 0), + (127024, 127123, 0), + (127136, 127150, 0), + (127153, 127167, 0), + (127169, 127183, 0), + (127185, 127221, 0), + (127232, 127244, 0), + (127245, 127405, 0), + (127462, 127487, 0), + (127488, 127488, 32), + (127489, 127490, 0), + (127504, 127547, 0), + (127552, 127560, 0), + (127568, 127569, 0), + (127584, 127589, 0), + (127744, 127994, 0), + (127995, 127999, 0), + (128000, 128727, 0), + (128732, 128748, 0), + (128752, 128764, 0), + (128768, 128886, 0), + (128891, 128985, 0), + (128992, 129003, 0), + (129008, 129008, 0), + (129024, 129035, 0), + (129040, 129095, 0), + (129104, 129113, 0), + (129120, 129159, 0), + (129168, 129197, 0), + (129200, 129201, 0), + (129280, 129619, 0), + (129632, 129645, 0), + (129648, 129660, 0), + (129664, 129672, 0), + (129680, 129725, 0), + (129727, 129733, 0), + (129742, 129755, 0), + (129760, 129768, 0), + (129776, 129784, 0), + (129792, 129938, 0), + (129940, 129994, 0), + (130032, 130041, 0), + (131072, 173791, 35), + (173824, 177977, 35), + (177984, 178205, 35), + (178208, 183969, 35), + (183984, 191456, 35), + (191472, 192093, 35), + (194560, 195101, 35), + (196608, 201546, 35), + (201552, 205743, 35), + (917505, 917505, 0), + (917536, 917631, 0), + (917760, 917999, 40), +) + + +@lru_cache(maxsize=None) +def get_unicode_script(char: str) -> UnicodeScript: + chr_search = ord(char) + for range_start, range_end, script_code in UNICODE_RANGE_TO_SCRIPT: + if range_start <= chr_search <= range_end: + return UnicodeScript(script_code) + if chr_search < range_start: + break + return UnicodeScript(999) # default to Unknown diff --git a/test/text_shaping/KhmerOS.ttf b/test/text_shaping/KhmerOS.ttf new file mode 100644 index 000000000..7aa5bdcd5 Binary files /dev/null and b/test/text_shaping/KhmerOS.ttf differ diff --git a/test/text_shaping/bidi_arabic_lorem_ipsum.pdf b/test/text_shaping/bidi_arabic_lorem_ipsum.pdf index 3e1aa0286..caeff86de 100644 Binary files a/test/text_shaping/bidi_arabic_lorem_ipsum.pdf and b/test/text_shaping/bidi_arabic_lorem_ipsum.pdf differ diff --git a/test/text_shaping/bidi_paragraph_direction.pdf b/test/text_shaping/bidi_paragraph_direction.pdf index 79007fad7..d179208de 100644 Binary files a/test/text_shaping/bidi_paragraph_direction.pdf and b/test/text_shaping/bidi_paragraph_direction.pdf differ diff --git a/test/text_shaping/multilingual_string.pdf b/test/text_shaping/multilingual_string.pdf new file mode 100644 index 000000000..4eb195ca8 Binary files /dev/null and b/test/text_shaping/multilingual_string.pdf differ diff --git a/test/text_shaping/test_text_shaping.py b/test/text_shaping/test_text_shaping.py index 748b4a01a..be9333521 100644 --- a/test/text_shaping/test_text_shaping.py +++ b/test/text_shaping/test_text_shaping.py @@ -1,6 +1,7 @@ from pathlib import Path from fpdf import FPDF +from fpdf.unicode_script import get_unicode_script, UnicodeScript from test.conftest import assert_pdf_equal HERE = Path(__file__).resolve().parent @@ -183,3 +184,184 @@ def test_text_shaping_and_offset_rendering(tmp_path): pdf.cell(col_width, line_height, f"Cell ({i})") pdf.cell(col_width, line_height, f"Cell ({i})") assert_pdf_equal(pdf, HERE / "text_shaping_and_offset_rendering.pdf", tmp_path) + + +def test_multilingual_string(tmp_path): + pdf = FPDF() + pdf.add_page() + pdf.add_font(family="KhmerOS", fname=HERE / "KhmerOS.ttf") + pdf.set_font("KhmerOS", size=30) + pdf.set_text_shaping(True) + pdf.cell(text="Khmer: សួស្តី ពិភពលោក") + assert_pdf_equal(pdf, HERE / "multilingual_string.pdf", tmp_path) + + +def test_unicode_script_codes(): + char_list = ( + "\x03", + "E", + "Ͳ", + "Ѧ", + "Ւ", + "ֲ", + "\u0601", + "܋", + "ޔ", + "ं", + "ঀ", + "ਁ", + "ઁ", + "ଁ", + "ஂ", + "ఀ", + "ಀ", + "ഁ", + "ඁ", + "พ", + "ຂ", + "ༀ", + "ဦ", + "Ⴔ", + "ᆙ", + "ለ", + "Ꭴ", + "᐀", + "\u1680", + "ᚲ", + "ឨ", + "᠀", + "を", + "ケ", + "˫", + "⺁", + "ꀑ", + "𐌒", + "𐌿", + "𐐱", + "̬", + "ᜃ", + "ᜬ", + "ᝈ", + "ᝡ", + "ᤌ", + "ᥢ", + "𐀁", + "𐎝", + "𐑷", + "𐒒", + "𐠂", + "⣫", + "ᨏ", + "ϯ", + "ᦐ", + "Ⰺ", + "ⵎ", + "ꠀ", + "𐎧", + "𐨀", + "ᬀ", + "𒉑", + "𐤀", + "ꡪ", + "߂", + "ᮁ", + "ᰙ", + "᱘", + "ꗵ", + "ꢁ", + "꤈", + "ꤲ", + "𐊌", + "𐊧", + "𐤯", + "ꨤ", + "ᩂ", + "ꪑ", + "𐬏", + "𓆊", + "ࠍ", + "ꓧ", + "ꛆ", + "ꦁ", + "ꫪ", + "𐡄", + "𐩶", + "𐭂", + "𐭦", + "𐰞", + "𑂁", + "ᯣ", + "𑀀", + "ࡍ", + "𑄂", + "𐦪", + "𐦈", + "𖼴", + "𑆁", + "𑃝", + "𑚛", + "𐕘", + "𖫝", + "𛱨", + "𐔑", + "𑌁", + "𖬫", + "𑈇", + "𐙤", + "𑅙", + "𐫀", + "𞠒", + "𑘑", + "𖩍", + "𐪁", + "𐢜", + "𐡰", + "𑫘", + "𐍒", + "𐮅", + "𑖤", + "𑋒", + "𑒆", + "𑣅", + "𑜄", + "𔕘", + "𐣥", + "𑊅", + "𐲑", + "𝣣", + "𞥂", + "𑰈", + "𑱰", + "𑐩", + "𐒵", + "𖿠", + "𑴄", + "𖿡", + "𑩐", + "𑨀", + "𑠇", + "𑵢", + "𑻧", + "𖹻", + "𐴞", + "𐼾", + "𐼅", + "𐿴", + "𑦤", + "𞄥", + "𞋄", + "𐾷", + "𑤁", + "𖿤", + "𐺟", + "𒿬", + "𐽷", + "𖪼", + "𞊞", + "𐕸", + "\U00011f00", + "\U0001e4d5", + ) + for index, char in enumerate(char_list): + assert get_unicode_script(char) == UnicodeScript(index) + get_unicode_script.cache_clear()