fontisan 0.4.10 → 0.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.adoc +27 -1
- data/Rakefile +53 -39
- data/docs/AFDKO_MIGRATION.adoc +175 -0
- data/docs/FEATURE_PARITY.adoc +263 -0
- data/docs/STITCHER_GUIDE.adoc +100 -6
- data/docs/TTX.adoc +176 -0
- data/docs/UFO_COMPILATION.adoc +281 -3
- data/lib/fontisan/stitcher/partition_strategy/by_block.rb +429 -0
- data/lib/fontisan/stitcher/partition_strategy/by_script.rb +305 -0
- data/lib/fontisan/stitcher/partition_strategy.rb +2 -0
- data/lib/fontisan/stitcher/source.rb +11 -7
- data/lib/fontisan/subset/table_subsetter.rb +227 -11
- data/lib/fontisan/svg/standalone_glyph.rb +129 -0
- data/lib/fontisan/svg.rb +1 -0
- data/lib/fontisan/tasks/fixture_downloader.rb +162 -0
- data/lib/fontisan/tasks.rb +11 -0
- data/lib/fontisan/ufo/cli.rb +34 -21
- data/lib/fontisan/ufo/compile/feature_writers/base.rb +56 -0
- data/lib/fontisan/ufo/compile/feature_writers/curs.rb +72 -0
- data/lib/fontisan/ufo/compile/feature_writers/gdef.rb +90 -0
- data/lib/fontisan/ufo/compile/feature_writers/kern.rb +51 -0
- data/lib/fontisan/ufo/compile/feature_writers/kern2.rb +57 -0
- data/lib/fontisan/ufo/compile/feature_writers/mark.rb +45 -0
- data/lib/fontisan/ufo/compile/feature_writers/mark_family_base.rb +122 -0
- data/lib/fontisan/ufo/compile/feature_writers/mkmk.rb +53 -0
- data/lib/fontisan/ufo/compile/feature_writers.rb +37 -0
- data/lib/fontisan/ufo/compile/filters/propagate_anchors.rb +102 -0
- data/lib/fontisan/ufo/compile/filters/remove_overlaps.rb +94 -0
- data/lib/fontisan/ufo/compile/filters/sort_contours.rb +69 -0
- data/lib/fontisan/ufo/compile/filters/transformations.rb +113 -0
- data/lib/fontisan/ufo/compile/filters.rb +12 -0
- data/lib/fontisan/ufo/compile.rb +1 -0
- data/lib/fontisan/ufo/convert/to_dfont.rb +41 -0
- data/lib/fontisan/ufo/convert/to_otc.rb +37 -0
- data/lib/fontisan/ufo/convert/to_otf.rb +18 -0
- data/lib/fontisan/ufo/convert/to_otf2.rb +20 -0
- data/lib/fontisan/ufo/convert/to_postscript.rb +59 -0
- data/lib/fontisan/ufo/convert/to_ttc.rb +35 -0
- data/lib/fontisan/ufo/convert/to_ttf.rb +21 -0
- data/lib/fontisan/ufo/convert/to_woff.rb +56 -0
- data/lib/fontisan/ufo/convert/to_woff2.rb +45 -0
- data/lib/fontisan/ufo/convert.rb +68 -5
- data/lib/fontisan/ufo/transformation.rb +11 -0
- data/lib/fontisan/version.rb +1 -1
- data/lib/fontisan.rb +1 -0
- metadata +32 -2
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fontisan
|
|
4
|
+
class Stitcher
|
|
5
|
+
module PartitionStrategy
|
|
6
|
+
# Partition codepoints by Unicode Blocks.txt block.
|
|
7
|
+
#
|
|
8
|
+
# Each non-empty Unicode block becomes one partition. If a single
|
|
9
|
+
# block alone exceeds +cap+, raises PartitionCapExceededError —
|
|
10
|
+
# every block is treated as atomic because there is no finer
|
|
11
|
+
# Unicode-defined boundary inside a block. (Callers who need to
|
|
12
|
+
# split a block further must use ByPlane with explicit carve-outs
|
|
13
|
+
# or implement a custom partitioner.)
|
|
14
|
+
#
|
|
15
|
+
# Partition names follow the canonical Unicode block name with
|
|
16
|
+
# spaces replaced by underscores and a +block_+ prefix:
|
|
17
|
+
#
|
|
18
|
+
# "Basic Latin" => :block_basic_latin
|
|
19
|
+
# "CJK Unified Ideographs" => :block_cjk_unified_ideographs
|
|
20
|
+
#
|
|
21
|
+
# Codepoints not covered by any block in {BLOCKS} (unassigned or
|
|
22
|
+
# in a block omitted from this list) fall into +:block_other+.
|
|
23
|
+
class ByBlock < Base
|
|
24
|
+
# Unicode 16.0 block ranges. Source: Unicode Blocks.txt.
|
|
25
|
+
# Covers all assigned blocks in BMP, SMP, SIP, TIP, and SSP.
|
|
26
|
+
# Unassigned planes (4..13) are omitted — codepoints there
|
|
27
|
+
# fall into +:block_other+, which is the right behavior for
|
|
28
|
+
# partitioning fonts that target current Unicode.
|
|
29
|
+
#
|
|
30
|
+
# The data is inlined (rather than loaded from an external
|
|
31
|
+
# file) so the partitioner is self-contained: no YAML load
|
|
32
|
+
# at startup, no data file to ship. If the list ever needs to
|
|
33
|
+
# be data-driven, swap BLOCKS for a CSV/YAML loader behind
|
|
34
|
+
# the same constant — callers don't care about the source
|
|
35
|
+
# (OCP).
|
|
36
|
+
# rubocop:disable Metrics/CollectionLiteralLength
|
|
37
|
+
BLOCKS = {
|
|
38
|
+
# BMP (Plane 0)
|
|
39
|
+
"Basic_Latin" => 0x0000..0x007F,
|
|
40
|
+
"Latin-1_Supplement" => 0x0080..0x00FF,
|
|
41
|
+
"Latin_Extended-A" => 0x0100..0x017F,
|
|
42
|
+
"Latin_Extended-B" => 0x0180..0x024F,
|
|
43
|
+
"IPA_Extensions" => 0x0250..0x02AF,
|
|
44
|
+
"Spacing_Modifier_Letters" => 0x02B0..0x02FF,
|
|
45
|
+
"Combining_Diacritical_Marks" => 0x0300..0x036F,
|
|
46
|
+
"Greek_and_Coptic" => 0x0370..0x03FF,
|
|
47
|
+
"Cyrillic" => 0x0400..0x04FF,
|
|
48
|
+
"Cyrillic_Supplement" => 0x0500..0x052F,
|
|
49
|
+
"Armenian" => 0x0530..0x058F,
|
|
50
|
+
"Hebrew" => 0x0590..0x05FF,
|
|
51
|
+
"Arabic" => 0x0600..0x06FF,
|
|
52
|
+
"Syriac" => 0x0700..0x074F,
|
|
53
|
+
"Arabic_Supplement" => 0x0750..0x077F,
|
|
54
|
+
"Arabic_Extended-A" => 0x08A0..0x08FF,
|
|
55
|
+
"Arabic_Extended-B" => 0x0870..0x089F,
|
|
56
|
+
"Thaana" => 0x0780..0x07BF,
|
|
57
|
+
"NKo" => 0x07C0..0x07FF,
|
|
58
|
+
"Samaritan" => 0x0800..0x083F,
|
|
59
|
+
"Mandaic" => 0x0840..0x085F,
|
|
60
|
+
"Syriac_Supplement" => 0x0860..0x086F,
|
|
61
|
+
"Devanagari" => 0x0900..0x097F,
|
|
62
|
+
"Bengali" => 0x0980..0x09FF,
|
|
63
|
+
"Gurmukhi" => 0x0A00..0x0A7F,
|
|
64
|
+
"Gujarati" => 0x0A80..0x0AFF,
|
|
65
|
+
"Oriya" => 0x0B00..0x0B7F,
|
|
66
|
+
"Tamil" => 0x0B80..0x0BFF,
|
|
67
|
+
"Telugu" => 0x0C00..0x0C7F,
|
|
68
|
+
"Kannada" => 0x0C80..0x0CFF,
|
|
69
|
+
"Malayalam" => 0x0D00..0x0D7F,
|
|
70
|
+
"Sinhala" => 0x0D80..0x0DFF,
|
|
71
|
+
"Thai" => 0x0E00..0x0E7F,
|
|
72
|
+
"Lao" => 0x0E80..0x0EFF,
|
|
73
|
+
"Tibetan" => 0x0F00..0x0FFF,
|
|
74
|
+
"Myanmar" => 0x1000..0x109F,
|
|
75
|
+
"Georgian" => 0x10A0..0x10FF,
|
|
76
|
+
"Hangul_Jamo" => 0x1100..0x11FF,
|
|
77
|
+
"Ethiopic" => 0x1200..0x137F,
|
|
78
|
+
"Ethiopic_Supplement" => 0x1380..0x139F,
|
|
79
|
+
"Cherokee" => 0x13A0..0x13FF,
|
|
80
|
+
"Unified_Canadian_Aboriginal_Syllabics" => 0x1400..0x167F,
|
|
81
|
+
"Ogham" => 0x1680..0x169F,
|
|
82
|
+
"Runic" => 0x16A0..0x16FF,
|
|
83
|
+
"Tagalog" => 0x1700..0x171F,
|
|
84
|
+
"Hanunoo" => 0x1720..0x173F,
|
|
85
|
+
"Buhid" => 0x1740..0x175F,
|
|
86
|
+
"Tagbanwa" => 0x1760..0x177F,
|
|
87
|
+
"Khmer" => 0x1780..0x17FF,
|
|
88
|
+
"Mongolian" => 0x1800..0x18AF,
|
|
89
|
+
"Unified_Canadian_Aboriginal_Syllabics_Extended" => 0x18B0..0x18FF,
|
|
90
|
+
"Limbu" => 0x1900..0x194F,
|
|
91
|
+
"Tai_Le" => 0x1950..0x197F,
|
|
92
|
+
"New_Tai_Lue" => 0x1980..0x19DF,
|
|
93
|
+
"Khmer_Symbols" => 0x19E0..0x19FF,
|
|
94
|
+
"Buginese" => 0x1A00..0x1A1F,
|
|
95
|
+
"Tai_Tham" => 0x1A20..0x1AAF,
|
|
96
|
+
"Combining_Diacritical_Marks_Extended" => 0x1AB0..0x1AFF,
|
|
97
|
+
"Balinese" => 0x1B00..0x1B7F,
|
|
98
|
+
"Sundanese" => 0x1B80..0x1BBF,
|
|
99
|
+
"Batak" => 0x1BC0..0x1BFF,
|
|
100
|
+
"Lepcha" => 0x1C00..0x1C4F,
|
|
101
|
+
"Ol_Chiki" => 0x1C50..0x1C7F,
|
|
102
|
+
"Cyrillic_Extended-C" => 0x1C80..0x1C8F,
|
|
103
|
+
"Georgian_Extended" => 0x1C90..0x1CBF,
|
|
104
|
+
"Sundanese_Supplement" => 0x1CC0..0x1CCF,
|
|
105
|
+
"Vedic_Extensions" => 0x1CD0..0x1CFF,
|
|
106
|
+
"Phonetic_Extensions" => 0x1D00..0x1D7F,
|
|
107
|
+
"Phonetic_Extensions_Supplement" => 0x1D80..0x1DBF,
|
|
108
|
+
"Combining_Diacritical_Marks_Supplement" => 0x1DC0..0x1DFF,
|
|
109
|
+
"Latin_Extended_Additional" => 0x1E00..0x1EFF,
|
|
110
|
+
"Greek_Extended" => 0x1F00..0x1FFF,
|
|
111
|
+
"General_Punctuation" => 0x2000..0x206F,
|
|
112
|
+
"Superscripts_and_Subscripts" => 0x2070..0x209F,
|
|
113
|
+
"Currency_Symbols" => 0x20A0..0x20CF,
|
|
114
|
+
"Combining_Diacritical_Marks_for_Symbols" => 0x20D0..0x20FF,
|
|
115
|
+
"Letterlike_Symbols" => 0x2100..0x214F,
|
|
116
|
+
"Number_Forms" => 0x2150..0x218F,
|
|
117
|
+
"Arrows" => 0x2190..0x21FF,
|
|
118
|
+
"Mathematical_Operators" => 0x2200..0x22FF,
|
|
119
|
+
"Miscellaneous_Technical" => 0x2300..0x23FF,
|
|
120
|
+
"Control_Pictures" => 0x2400..0x243F,
|
|
121
|
+
"Optical_Character_Recognition" => 0x2440..0x245F,
|
|
122
|
+
"Enclosed_Alphanumerics" => 0x2460..0x24FF,
|
|
123
|
+
"Box_Drawing" => 0x2500..0x257F,
|
|
124
|
+
"Block_Elements" => 0x2580..0x259F,
|
|
125
|
+
"Geometric_Shapes" => 0x25A0..0x25FF,
|
|
126
|
+
"Miscellaneous_Symbols" => 0x2600..0x26FF,
|
|
127
|
+
"Dingbats" => 0x2700..0x27BF,
|
|
128
|
+
"Miscellaneous_Mathematical_Symbols-A" => 0x27C0..0x27EF,
|
|
129
|
+
"Supplemental_Arrows-A" => 0x27F0..0x27FF,
|
|
130
|
+
"Braille_Patterns" => 0x2800..0x28FF,
|
|
131
|
+
"Supplemental_Arrows-B" => 0x2900..0x297F,
|
|
132
|
+
"Miscellaneous_Mathematical_Symbols-B" => 0x2980..0x29FF,
|
|
133
|
+
"Supplemental_Mathematical_Operators" => 0x2A00..0x2AFF,
|
|
134
|
+
"Miscellaneous_Symbols_and_Arrows" => 0x2B00..0x2BFF,
|
|
135
|
+
"Glagolitic" => 0x2C00..0x2C5F,
|
|
136
|
+
"Latin_Extended-C" => 0x2C60..0x2C7F,
|
|
137
|
+
"Coptic" => 0x2C80..0x2CFF,
|
|
138
|
+
"Georgian_Supplement" => 0x2D00..0x2D2F,
|
|
139
|
+
"Tifinagh" => 0x2D30..0x2D7F,
|
|
140
|
+
"Ethiopic_Extended" => 0x2D80..0x2DDF,
|
|
141
|
+
"Supplemental_Punctuation" => 0x2E00..0x2E7F,
|
|
142
|
+
"CJK_Radicals_Supplement" => 0x2E80..0x2EFF,
|
|
143
|
+
"Kangxi_Radicals" => 0x2F00..0x2FDF,
|
|
144
|
+
"Ideographic_Description_Characters" => 0x2FF0..0x2FFF,
|
|
145
|
+
"CJK_Symbols_and_Punctuation" => 0x3000..0x303F,
|
|
146
|
+
"Hiragana" => 0x3040..0x309F,
|
|
147
|
+
"Katakana" => 0x30A0..0x30FF,
|
|
148
|
+
"Bopomofo" => 0x3100..0x312F,
|
|
149
|
+
"Hangul_Compatibility_Jamo" => 0x3130..0x318F,
|
|
150
|
+
"Kanbun" => 0x3190..0x319F,
|
|
151
|
+
"Bopomofo_Extended" => 0x31A0..0x31BF,
|
|
152
|
+
"CJK_Strokes" => 0x31C0..0x31EF,
|
|
153
|
+
"Katakana_Phonetic_Extensions" => 0x31F0..0x31FF,
|
|
154
|
+
"Enclosed_CJK_Letters_and_Months" => 0x3200..0x32FF,
|
|
155
|
+
"CJK_Compatibility" => 0x3300..0x33FF,
|
|
156
|
+
"CJK_Unified_Ideographs_Extension_A" => 0x3400..0x4DBF,
|
|
157
|
+
"Yijing_Hexagram_Symbols" => 0x4DC0..0x4DFF,
|
|
158
|
+
"CJK_Unified_Ideographs" => 0x4E00..0x9FFF,
|
|
159
|
+
"Yi_Syllables" => 0xA000..0xA48F,
|
|
160
|
+
"Yi_Radicals" => 0xA490..0xA4CF,
|
|
161
|
+
"Lisu" => 0xA4D0..0xA4FF,
|
|
162
|
+
"Vai" => 0xA500..0xA63F,
|
|
163
|
+
"Cyrillic_Extended-B" => 0xA640..0xA69F,
|
|
164
|
+
"Bamum" => 0xA6A0..0xA6FF,
|
|
165
|
+
"Modifier_Tone_Letters" => 0xA700..0xA71F,
|
|
166
|
+
"Latin_Extended-D" => 0xA720..0xA7FF,
|
|
167
|
+
"Syloti_Nagri" => 0xA800..0xA82F,
|
|
168
|
+
"Common_Indic_Number_Forms" => 0xA830..0xA83F,
|
|
169
|
+
"Phags-pa" => 0xA840..0xA87F,
|
|
170
|
+
"Saurashtra" => 0xA880..0xA8DF,
|
|
171
|
+
"Devanagari_Extended" => 0xA8E0..0xA8FF,
|
|
172
|
+
"Kayah_Li" => 0xA900..0xA92F,
|
|
173
|
+
"Rejang" => 0xA930..0xA95F,
|
|
174
|
+
"Hangul_Jamo_Extended-A" => 0xA960..0xA97F,
|
|
175
|
+
"Javanese" => 0xA980..0xA9DF,
|
|
176
|
+
"Myanmar_Extended-B" => 0xA9E0..0xA9FF,
|
|
177
|
+
"Cham" => 0xAA00..0xAA5F,
|
|
178
|
+
"Myanmar_Extended-A" => 0xAA60..0xAA7F,
|
|
179
|
+
"Tai_Viet" => 0xAA80..0xAADF,
|
|
180
|
+
"Meetei_Mayek_Extensions" => 0xAAE0..0xAAFF,
|
|
181
|
+
"Ethiopic_Extended-A" => 0xAB00..0xAB2F,
|
|
182
|
+
"Latin_Extended-E" => 0xAB30..0xAB6F,
|
|
183
|
+
"Cherokee_Supplement" => 0xAB70..0xABBF,
|
|
184
|
+
"Meetei_Mayek" => 0xABC0..0xABFF,
|
|
185
|
+
"Hangul_Syllables" => 0xAC00..0xD7AF,
|
|
186
|
+
"Hangul_Jamo_Extended-B" => 0xD7B0..0xD7FF,
|
|
187
|
+
"High_Surrogates" => 0xD800..0xDB7F,
|
|
188
|
+
"High_Private_Use_Surrogates" => 0xDB80..0xDBFF,
|
|
189
|
+
"Low_Surrogates" => 0xDC00..0xDFFF,
|
|
190
|
+
"Private_Use_Area" => 0xE000..0xF8FF,
|
|
191
|
+
"CJK_Compatibility_Ideographs" => 0xF900..0xFAFF,
|
|
192
|
+
"Alphabetic_Presentation_Forms" => 0xFB00..0xFB4F,
|
|
193
|
+
"Arabic_Presentation_Forms-A" => 0xFB50..0xFDFF,
|
|
194
|
+
"Variation_Selectors" => 0xFE00..0xFE0F,
|
|
195
|
+
"Vertical_Forms" => 0xFE10..0xFE1F,
|
|
196
|
+
"Combining_Half_Marks" => 0xFE20..0xFE2F,
|
|
197
|
+
"CJK_Compatibility_Forms" => 0xFE30..0xFE4F,
|
|
198
|
+
"Small_Form_Variants" => 0xFE50..0xFE6F,
|
|
199
|
+
"Arabic_Presentation_Forms-B" => 0xFE70..0xFEFF,
|
|
200
|
+
"Halfwidth_and_Fullwidth_Forms" => 0xFF00..0xFFEF,
|
|
201
|
+
"Specials" => 0xFFF0..0xFFFF,
|
|
202
|
+
|
|
203
|
+
# SMP (Plane 1)
|
|
204
|
+
"Linear_B_Syllabary" => 0x10000..0x1003F,
|
|
205
|
+
"Linear_B_Ideograms" => 0x10080..0x100FF,
|
|
206
|
+
"Aegean_Numbers" => 0x10100..0x1013F,
|
|
207
|
+
"Ancient_Greek_Numbers" => 0x10140..0x1018F,
|
|
208
|
+
"Ancient_Symbols" => 0x10190..0x101CF,
|
|
209
|
+
"Phaistos_Disc" => 0x101D0..0x101FF,
|
|
210
|
+
"Lycian" => 0x10280..0x1029F,
|
|
211
|
+
"Carian" => 0x102A0..0x102DF,
|
|
212
|
+
"Coptic_Epact_Numbers" => 0x102E0..0x102FF,
|
|
213
|
+
"Old_Italic" => 0x10300..0x1032F,
|
|
214
|
+
"Gothic" => 0x10330..0x1034F,
|
|
215
|
+
"Old_Permic" => 0x10350..0x1037F,
|
|
216
|
+
"Ugaritic" => 0x10380..0x1039F,
|
|
217
|
+
"Old_Persian" => 0x103A0..0x103DF,
|
|
218
|
+
"Deseret" => 0x10400..0x1044F,
|
|
219
|
+
"Shavian" => 0x10450..0x1047F,
|
|
220
|
+
"Osmanya" => 0x10480..0x104AF,
|
|
221
|
+
"Osage" => 0x104B0..0x104FF,
|
|
222
|
+
"Elbasan" => 0x10500..0x1052F,
|
|
223
|
+
"Caucasian_Albanian" => 0x10530..0x1056F,
|
|
224
|
+
"Vithkuqi" => 0x10570..0x105BF,
|
|
225
|
+
"Linear_A" => 0x10600..0x1077F,
|
|
226
|
+
"Latin_Extended-F" => 0x10780..0x107BF,
|
|
227
|
+
"Cypriot_Syllabary" => 0x10800..0x1083F,
|
|
228
|
+
"Imperial_Aramaic" => 0x10840..0x1085F,
|
|
229
|
+
"Palmyrene" => 0x10860..0x1087F,
|
|
230
|
+
"Nabataean" => 0x10880..0x108AF,
|
|
231
|
+
"Hatran" => 0x108E0..0x108FF,
|
|
232
|
+
"Phoenician" => 0x10900..0x1091F,
|
|
233
|
+
"Lydian" => 0x10920..0x1093F,
|
|
234
|
+
"Meroitic_Hieroglyphs" => 0x10980..0x1099F,
|
|
235
|
+
"Meroitic_Cursive" => 0x109A0..0x109FF,
|
|
236
|
+
"Kharoshthi" => 0x10A00..0x10A5F,
|
|
237
|
+
"Old_South_Arabian" => 0x10A60..0x10A7F,
|
|
238
|
+
"Old_North_Arabian" => 0x10A80..0x10A9F,
|
|
239
|
+
"Manichaean" => 0x10AC0..0x10AFF,
|
|
240
|
+
"Avestan" => 0x10B00..0x10B3F,
|
|
241
|
+
"Inscriptional_Parthian" => 0x10B40..0x10B5F,
|
|
242
|
+
"Inscriptional_Pahlavi" => 0x10B60..0x10B7F,
|
|
243
|
+
"Psalter_Pahlavi" => 0x10B80..0x10BAF,
|
|
244
|
+
"Old_Turkic" => 0x10C00..0x10C4F,
|
|
245
|
+
"Old_Hungarian" => 0x10C80..0x10CFF,
|
|
246
|
+
"Hanifi_Rohingya" => 0x10D00..0x10D3F,
|
|
247
|
+
"Garay" => 0x10D40..0x10D8F,
|
|
248
|
+
"Rumi_Numeral_Symbols" => 0x10E60..0x10E7F,
|
|
249
|
+
"Yezidi" => 0x10E80..0x10EBF,
|
|
250
|
+
"Arabic_Extended-C" => 0x10EC0..0x10EFF,
|
|
251
|
+
"Old_Sogdian" => 0x10F00..0x10F2F,
|
|
252
|
+
"Sogdian" => 0x10F30..0x10F6F,
|
|
253
|
+
"Old_Uyghur" => 0x10F70..0x10FAF,
|
|
254
|
+
"Chorasmian" => 0x10FB0..0x10FBF,
|
|
255
|
+
"Elymaic" => 0x10FE0..0x10FEF,
|
|
256
|
+
"Brahmi" => 0x11000..0x1107F,
|
|
257
|
+
"Kaithi" => 0x11080..0x110CF,
|
|
258
|
+
"Sora_Sompeng" => 0x110D0..0x110FF,
|
|
259
|
+
"Chakma" => 0x11100..0x1114F,
|
|
260
|
+
"Mahajani" => 0x11150..0x1117F,
|
|
261
|
+
"Sharada" => 0x11180..0x111DF,
|
|
262
|
+
"Sinhala_Archaic_Numbers" => 0x111E0..0x111FF,
|
|
263
|
+
"Khojki" => 0x11200..0x1124F,
|
|
264
|
+
"Multani" => 0x11280..0x112AF,
|
|
265
|
+
"Khudawadi" => 0x112B0..0x112FF,
|
|
266
|
+
"Grantha" => 0x11300..0x1137F,
|
|
267
|
+
"Tulu-Tigalari" => 0x11380..0x113FF,
|
|
268
|
+
"Newa" => 0x11400..0x1147F,
|
|
269
|
+
"Tirhuta" => 0x11480..0x114DF,
|
|
270
|
+
"Siddham" => 0x11580..0x115FF,
|
|
271
|
+
"Modi" => 0x11600..0x1165F,
|
|
272
|
+
"Mongolian_Supplement" => 0x11660..0x1167F,
|
|
273
|
+
"Takri" => 0x11680..0x116CF,
|
|
274
|
+
"Myanmar_Extended-C" => 0x116D0..0x116FF,
|
|
275
|
+
"Ahom" => 0x11700..0x1174F,
|
|
276
|
+
"Dogra" => 0x11800..0x1184F,
|
|
277
|
+
"Warang_Citi" => 0x118A0..0x118FF,
|
|
278
|
+
"Dives_Akuru" => 0x11900..0x1195F,
|
|
279
|
+
"Nandinagari" => 0x119A0..0x119FF,
|
|
280
|
+
"Zanabazar_Square" => 0x11A00..0x11A4F,
|
|
281
|
+
"Soyombo" => 0x11A50..0x11AAF,
|
|
282
|
+
"Unified_Canadian_Aboriginal_Syllabics_Extended-A" => 0x11AB0..0x11ABF,
|
|
283
|
+
"Pau_Cin_Hmo" => 0x11AC0..0x11AFF,
|
|
284
|
+
"Bhaiksuki" => 0x11C00..0x11C6F,
|
|
285
|
+
"Marchen" => 0x11C70..0x11CBF,
|
|
286
|
+
"Masaram_Gondi" => 0x11D00..0x11D5F,
|
|
287
|
+
"Gunjala_Gondi" => 0x11D60..0x11DAF,
|
|
288
|
+
"Makasar" => 0x11EE0..0x11EFF,
|
|
289
|
+
"Kawi" => 0x11F00..0x11F5F,
|
|
290
|
+
"Lisu_Supplement" => 0x11FB0..0x11FBF,
|
|
291
|
+
"Tamil_Supplement" => 0x11FC0..0x11FFF,
|
|
292
|
+
"Cuneiform" => 0x12000..0x123FF,
|
|
293
|
+
"Cuneiform_Numbers_and_Punctuation" => 0x12400..0x1247F,
|
|
294
|
+
"Early_Dynastic_Cuneiform" => 0x12480..0x1254F,
|
|
295
|
+
"Cypro-Minoan" => 0x12F90..0x12FFF,
|
|
296
|
+
"Egyptian_Hieroglyphs" => 0x13000..0x1342F,
|
|
297
|
+
"Egyptian_Hieroglyph_Format_Controls" => 0x13430..0x1345F,
|
|
298
|
+
"Egyptian_Hieroglyphs_Extended-A" => 0x13460..0x143FF,
|
|
299
|
+
"Anatolian_Hieroglyphs" => 0x14400..0x1467F,
|
|
300
|
+
"Bamum_Supplement" => 0x16800..0x16A3F,
|
|
301
|
+
"Mro" => 0x16A40..0x16A6F,
|
|
302
|
+
"Tangsa" => 0x16A70..0x16ACF,
|
|
303
|
+
"Bassa_Vah" => 0x16AD0..0x16AFF,
|
|
304
|
+
"Pahawh_Hmong" => 0x16B00..0x16B8F,
|
|
305
|
+
"Medefaidrin" => 0x16E40..0x16E9F,
|
|
306
|
+
"Miao" => 0x16F00..0x16F9F,
|
|
307
|
+
"Ideographic_Symbols_and_Punctuation" => 0x16FE0..0x16FFF,
|
|
308
|
+
"Tangut" => 0x17000..0x187FF,
|
|
309
|
+
"Tangut_Components" => 0x18800..0x18AFF,
|
|
310
|
+
"Khitan_Small_Script" => 0x18B00..0x18CFF,
|
|
311
|
+
"Tangut_Supplement" => 0x18D00..0x18D7F,
|
|
312
|
+
"Kana_Supplement" => 0x1B000..0x1B0FF,
|
|
313
|
+
"Kana_Extended-A" => 0x1B100..0x1B12F,
|
|
314
|
+
"Small_Kana_Extension" => 0x1B130..0x1B16F,
|
|
315
|
+
"Nushu" => 0x1B170..0x1B2FF,
|
|
316
|
+
"Duployan" => 0x1BC00..0x1BC9F,
|
|
317
|
+
"Shorthand_Format_Controls" => 0x1BCA0..0x1BCAF,
|
|
318
|
+
"Znamenny_Musical_Notation" => 0x1CF00..0x1CFCF,
|
|
319
|
+
"Byzantine_Musical_Symbols" => 0x1D000..0x1D0FF,
|
|
320
|
+
"Musical_Symbols" => 0x1D100..0x1D1FF,
|
|
321
|
+
"Ancient_Greek_Musical_Notation" => 0x1D200..0x1D24F,
|
|
322
|
+
"Kaktovik_Numerals" => 0x1D2C0..0x1D2FF,
|
|
323
|
+
"Tai_Xuan_Jing_Symbols" => 0x1D300..0x1D35F,
|
|
324
|
+
"Counting_Rod_Numerals" => 0x1D360..0x1D37F,
|
|
325
|
+
"Mathematical_Alphanumeric_Symbols" => 0x1D400..0x1D7FF,
|
|
326
|
+
"Sutton_SignWriting" => 0x1D800..0x1DAAF,
|
|
327
|
+
"Latin_Extended-G" => 0x1DF00..0x1DFFF,
|
|
328
|
+
"Glagolitic_Supplement" => 0x1E000..0x1E02F,
|
|
329
|
+
"Cyrillic_Extended-D" => 0x1E030..0x1E08F,
|
|
330
|
+
"Nyiakeng_Puachue_Hmong" => 0x1E100..0x1E14F,
|
|
331
|
+
"Toto" => 0x1E290..0x1E2BF,
|
|
332
|
+
"Wancho" => 0x1E2C0..0x1E2FF,
|
|
333
|
+
"Nag_Mundari" => 0x1E4D0..0x1E4FF,
|
|
334
|
+
"Ethiopian_Extended-B" => 0x1E7E0..0x1E7FF,
|
|
335
|
+
"Mende_Kikakui" => 0x1E800..0x1E8DF,
|
|
336
|
+
"Adlam" => 0x1E900..0x1E95F,
|
|
337
|
+
"Indic_Siyaq_Numbers" => 0x1EC70..0x1ECBF,
|
|
338
|
+
"Ottoman_Siyaq_Numbers" => 0x1ED00..0x1ED4F,
|
|
339
|
+
"Arabic_Mathematical_Alphabetic_Symbols" => 0x1EE00..0x1EEFF,
|
|
340
|
+
"Mahjong_Tiles" => 0x1F000..0x1F02F,
|
|
341
|
+
"Domino_Tiles" => 0x1F030..0x1F09F,
|
|
342
|
+
"Playing_Cards" => 0x1F0A0..0x1F0FF,
|
|
343
|
+
"Enclosed_Alphanumeric_Supplement" => 0x1F100..0x1F1FF,
|
|
344
|
+
"Enclosed_Ideographic_Supplement" => 0x1F200..0x1F2FF,
|
|
345
|
+
"Miscellaneous_Symbols_and_Pictographs" => 0x1F300..0x1F5FF,
|
|
346
|
+
"Emoticons" => 0x1F600..0x1F64F,
|
|
347
|
+
"Ornamental_Dingbats" => 0x1F650..0x1F67F,
|
|
348
|
+
"Transport_and_Map_Symbols" => 0x1F680..0x1F6FF,
|
|
349
|
+
"Alchemical_Symbols" => 0x1F700..0x1F77F,
|
|
350
|
+
"Geometric_Shapes_Extended" => 0x1F780..0x1F7FF,
|
|
351
|
+
"Supplemental_Arrows-C" => 0x1F800..0x1F8FF,
|
|
352
|
+
"Supplemental_Symbols_and_Pictographs" => 0x1F900..0x1F9FF,
|
|
353
|
+
"Chess_Symbols" => 0x1FA00..0x1FA6F,
|
|
354
|
+
"Symbols_and_Pictographs_Extended-A" => 0x1FA70..0x1FAFF,
|
|
355
|
+
"Symbols_for_Legacy_Computing" => 0x1FB00..0x1FBFF,
|
|
356
|
+
|
|
357
|
+
# SIP (Plane 2)
|
|
358
|
+
"CJK_Unified_Ideographs_Extension-B" => 0x20000..0x2A6DF,
|
|
359
|
+
"CJK_Unified_Ideographs_Extension-C" => 0x2A700..0x2B73F,
|
|
360
|
+
"CJK_Unified_Ideographs_Extension-D" => 0x2B740..0x2B81F,
|
|
361
|
+
"CJK_Unified_Ideographs_Extension-E" => 0x2B820..0x2CEAF,
|
|
362
|
+
"CJK_Unified_Ideographs_Extension-F" => 0x2CEB0..0x2EBEF,
|
|
363
|
+
"CJK_Unified_Ideographs_Extension-I" => 0x2EBF0..0x2EE5F,
|
|
364
|
+
"CJK_Compatibility_Ideographs_Supplement" => 0x2F800..0x2FA1F,
|
|
365
|
+
|
|
366
|
+
# TIP (Plane 3)
|
|
367
|
+
# Note: Unicode 16.0 also defines Extension-H (U+31350..U+323AF)
|
|
368
|
+
# which overlaps with Extension-G (U+30000..U+313AF). Omitted
|
|
369
|
+
# here to keep the no-overlap invariant clean; codepoints in
|
|
370
|
+
# the Extension-H range fall through to Extension-G, which is
|
|
371
|
+
# correct for every codepoint outside the rare overlap region.
|
|
372
|
+
"CJK_Unified_Ideographs_Extension-G" => 0x30000..0x313AF,
|
|
373
|
+
|
|
374
|
+
# SSP (Plane 14)
|
|
375
|
+
"Tags" => 0xE0000..0xE007F,
|
|
376
|
+
"Variation_Selectors_Supplement" => 0xE0100..0xE01EF,
|
|
377
|
+
}.freeze
|
|
378
|
+
# rubocop:enable Metrics/CollectionLiteralLength
|
|
379
|
+
|
|
380
|
+
# @param cp_map [Hash{Integer=>Object}] codepoint → donor label
|
|
381
|
+
# @param cap [Integer] max codepoints per partition
|
|
382
|
+
# @return [Blueprint]
|
|
383
|
+
def call(cp_map, cap: DEFAULT_CAP)
|
|
384
|
+
grouped = group_by_block(cp_map)
|
|
385
|
+
partitions = grouped.map do |label, entries|
|
|
386
|
+
if entries.size > cap
|
|
387
|
+
raise PartitionCapExceededError.new(
|
|
388
|
+
block_label: label,
|
|
389
|
+
actual: entries.size,
|
|
390
|
+
cap: cap,
|
|
391
|
+
)
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
Partition.new(
|
|
395
|
+
name: partition_name(label),
|
|
396
|
+
cps: entries.map(&:first),
|
|
397
|
+
donor_map: entries.to_h,
|
|
398
|
+
)
|
|
399
|
+
end
|
|
400
|
+
Blueprint.new(partitions: partitions)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
private
|
|
404
|
+
|
|
405
|
+
def group_by_block(cp_map)
|
|
406
|
+
cp_map.each_with_object(Hash.new { |h, k| h[k] = [] }) do |(cp, label), h|
|
|
407
|
+
block_label = find_block_label(cp) || :other
|
|
408
|
+
h[block_label] << [cp, label]
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# Linear scan is fine for ~340 entries at typical partition-time
|
|
413
|
+
# call volumes (once per Stitcher.run). If profiling shows it
|
|
414
|
+
# hot, swap for a sorted [start, end, label] array + binary
|
|
415
|
+
# search — the data structure can change without touching the
|
|
416
|
+
# public API.
|
|
417
|
+
def find_block_label(codepoint)
|
|
418
|
+
BLOCKS.find { |_label, range| range.cover?(codepoint) }&.first
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def partition_name(label)
|
|
422
|
+
return :block_other if label == :other
|
|
423
|
+
|
|
424
|
+
:"block_#{label.downcase}"
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
end
|