allsorts_subset_browser/unicode/mcc.rs
1use unicode_canonical_combining_class::get_canonical_combining_class;
2
3/// An enumeration of the Unicode
4/// [Canonical_Combining_Class values](http://www.unicode.org/reports/tr44/#Canonical_Combining_Class_Values),
5/// with the following modifications:
6///
7/// * Remove: `CCC84`, `CCC91`, `CCC103`.
8/// * Add: `CCC3`, `CCC4`, `CCC5`.
9#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
10pub enum ModifiedCombiningClass {
11 NotReordered = 0,
12 Overlay = 1,
13 CCC3 = 3,
14 CCC4 = 4,
15 CCC5 = 5,
16 HanReading = 6,
17 Nukta = 7,
18 KanaVoicing = 8,
19 Virama = 9,
20 CCC10 = 10,
21 CCC11 = 11,
22 CCC12 = 12,
23 CCC13 = 13,
24 CCC14 = 14,
25 CCC15 = 15,
26 CCC16 = 16,
27 CCC17 = 17,
28 CCC18 = 18,
29 CCC19 = 19,
30 CCC20 = 20,
31 CCC21 = 21,
32 CCC22 = 22,
33 CCC23 = 23,
34 CCC24 = 24,
35 CCC25 = 25,
36 CCC26 = 26,
37 CCC27 = 27,
38 CCC28 = 28,
39 CCC29 = 29,
40 CCC30 = 30,
41 CCC31 = 31,
42 CCC32 = 32,
43 CCC33 = 33,
44 CCC34 = 34,
45 CCC35 = 35,
46 CCC36 = 36,
47 CCC107 = 107,
48 CCC118 = 118,
49 CCC122 = 122,
50 CCC129 = 129,
51 CCC130 = 130,
52 CCC132 = 132,
53 AttachedBelow = 202,
54 AttachedAbove = 214,
55 AttachedAboveRight = 216,
56 BelowLeft = 218,
57 Below = 220,
58 BelowRight = 222,
59 Left = 224,
60 Right = 226,
61 AboveLeft = 228,
62 Above = 230,
63 AboveRight = 232,
64 DoubleBelow = 233,
65 DoubleAbove = 234,
66 IotaSubscript = 240,
67}
68
69const X: ModifiedCombiningClass = ModifiedCombiningClass::NotReordered;
70use ModifiedCombiningClass::*;
71const MODIFIED_COMBINING_CLASS: &'static [ModifiedCombiningClass; 256] = &[
72 NotReordered, // NotReordered
73 Overlay, // Overlay
74 X, // CCC2
75 X, // CCC3
76 X, // CCC4
77 X, // CCC5
78 HanReading, // HanReading
79 Nukta, // Nukta
80 KanaVoicing, // KanaVoicing
81 Virama, // Virama
82 // Hebrew
83 // Reordered in accordance with the SBL Hebrew Font User Manual:
84 // https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf.
85 CCC22, // CCC10
86 CCC15, // CCC11
87 CCC16, // CCC12
88 CCC17, // CCC13
89 CCC23, // CCC14
90 CCC18, // CCC15
91 CCC19, // CCC16
92 CCC20, // CCC17
93 CCC21, // CCC18
94 CCC14, // CCC19
95 CCC24, // CCC20
96 CCC12, // CCC21
97 CCC25, // CCC22
98 CCC13, // CCC23
99 CCC10, // CCC24
100 CCC11, // CCC25
101 CCC26, // CCC26
102 // Arabic
103 CCC27, // CCC27
104 CCC28, // CCC28
105 CCC29, // CCC29
106 CCC30, // CCC30
107 CCC31, // CCC31
108 CCC32, // CCC32
109 CCC33, // CCC33
110 CCC34, // CCC34
111 CCC35, // CCC35
112 // Syriac
113 CCC36, // CCC36
114 X, // CCC37
115 X, // CCC38
116 X, // CCC39
117 X, // CCC40
118 X, // CCC41
119 X, // CCC42
120 X, // CCC43
121 X, // CCC44
122 X, // CCC45
123 X, // CCC46
124 X, // CCC47
125 X, // CCC48
126 X, // CCC49
127 X, // CCC50
128 X, // CCC51
129 X, // CCC52
130 X, // CCC53
131 X, // CCC54
132 X, // CCC55
133 X, // CCC56
134 X, // CCC57
135 X, // CCC58
136 X, // CCC59
137 X, // CCC60
138 X, // CCC61
139 X, // CCC62
140 X, // CCC63
141 X, // CCC64
142 X, // CCC65
143 X, // CCC66
144 X, // CCC67
145 X, // CCC68
146 X, // CCC69
147 X, // CCC70
148 X, // CCC71
149 X, // CCC72
150 X, // CCC73
151 X, // CCC74
152 X, // CCC75
153 X, // CCC76
154 X, // CCC77
155 X, // CCC78
156 X, // CCC79
157 X, // CCC80
158 X, // CCC81
159 X, // CCC82
160 X, // CCC83
161 // Telugu
162 // Map `CCC84` and `CCC91` to the otherwise unassigned `CCC4` and `CCC5` values. If
163 // left as-is, the Telugu length marks U+0C55 and U+0C56 have the undesirable effect
164 // of being reordered after a Halant.
165 //
166 // Test case: `"\u{0C15}\u{0C4D}\u{0C56}"` should not produce a dotted circle.
167 CCC4, // CCC84
168 X, // CCC85
169 X, // CCC86
170 X, // CCC87
171 X, // CCC88
172 X, // CCC89
173 X, // CCC90
174 CCC5, // CCC91
175 X, // CCC92
176 X, // CCC93
177 X, // CCC94
178 X, // CCC95
179 X, // CCC96
180 X, // CCC97
181 X, // CCC98
182 X, // CCC99
183 X, // CCC100
184 X, // CCC101
185 X, // CCC102
186 // Thai
187 // Map `CCC103` to the otherwise unassigned `CCC3` value. If left as-is, the Thai marks
188 // U+0E38 and U+0E39 have the undesirable effect of being reordered after a Phinthu.
189 CCC3, // CCC103
190 X, // CCC104
191 X, // CCC105
192 X, // CCC106
193 CCC107, // CCC107
194 X, // CCC108
195 X, // CCC109
196 X, // CCC110
197 X, // CCC111
198 X, // CCC112
199 X, // CCC113
200 X, // CCC114
201 X, // CCC115
202 X, // CCC116
203 X, // CCC117
204 // Lao
205 CCC118, // CCC118
206 X, // CCC119
207 X, // CCC120
208 X, // CCC121
209 CCC122, // CCC122
210 X, // CCC123
211 X, // CCC124
212 X, // CCC125
213 X, // CCC126
214 X, // CCC127
215 X, // CCC128
216 // Tibetan
217 CCC129, // CCC129
218 CCC130, // CCC130
219 X, // CCC131
220 CCC132, // CCC132
221 X, // CCC133
222 X, // CCC134
223 X, // CCC135
224 X, // CCC136
225 X, // CCC137
226 X, // CCC138
227 X, // CCC139
228 X, // CCC140
229 X, // CCC141
230 X, // CCC142
231 X, // CCC143
232 X, // CCC144
233 X, // CCC145
234 X, // CCC146
235 X, // CCC147
236 X, // CCC148
237 X, // CCC149
238 X, // CCC150
239 X, // CCC151
240 X, // CCC152
241 X, // CCC153
242 X, // CCC154
243 X, // CCC155
244 X, // CCC156
245 X, // CCC157
246 X, // CCC158
247 X, // CCC159
248 X, // CCC160
249 X, // CCC161
250 X, // CCC162
251 X, // CCC163
252 X, // CCC164
253 X, // CCC165
254 X, // CCC166
255 X, // CCC167
256 X, // CCC168
257 X, // CCC169
258 X, // CCC170
259 X, // CCC171
260 X, // CCC172
261 X, // CCC173
262 X, // CCC174
263 X, // CCC175
264 X, // CCC176
265 X, // CCC177
266 X, // CCC178
267 X, // CCC179
268 X, // CCC180
269 X, // CCC181
270 X, // CCC182
271 X, // CCC183
272 X, // CCC184
273 X, // CCC185
274 X, // CCC186
275 X, // CCC187
276 X, // CCC188
277 X, // CCC189
278 X, // CCC190
279 X, // CCC191
280 X, // CCC192
281 X, // CCC193
282 X, // CCC194
283 X, // CCC195
284 X, // CCC196
285 X, // CCC197
286 X, // CCC198
287 X, // CCC199
288 X, // CCC200
289 X, // CCC201
290 AttachedBelow, // AttachedBelow
291 X, // CCC203
292 X, // CCC204
293 X, // CCC205
294 X, // CCC206
295 X, // CCC207
296 X, // CCC208
297 X, // CCC209
298 X, // CCC210
299 X, // CCC211
300 X, // CCC212
301 X, // CCC213
302 AttachedAbove, // AttachedAbove
303 X, // CCC215
304 AttachedAboveRight, // AttachedAboveRight
305 X, // CCC217
306 BelowLeft, // BelowLeft
307 X, // CCC219
308 Below, // Below
309 X, // CCC221
310 BelowRight, // BelowRight
311 X, // CCC223
312 Left, // Left
313 X, // CCC225
314 Right, // Right
315 X, // CCC227
316 AboveLeft, // AboveLeft
317 X, // CCC229
318 Above, // Above
319 X, // CCC231
320 AboveRight, // AboveRight
321 DoubleBelow, // DoubleBelow
322 DoubleAbove, // DoubleAbove
323 X, // CCC235
324 X, // CCC236
325 X, // CCC237
326 X, // CCC238
327 X, // CCC239
328 IotaSubscript, // IotaSubscript
329 X, // CCC241
330 X, // CCC242
331 X, // CCC243
332 X, // CCC244
333 X, // CCC245
334 X, // CCC246
335 X, // CCC247
336 X, // CCC248
337 X, // CCC249
338 X, // CCC250
339 X, // CCC251
340 X, // CCC252
341 X, // CCC253
342 X, // CCC254
343 X, // CCC255
344];
345
346/// Returns the modified combining class value of a `char`. Retrieves the _canonical_ combining
347/// class value, then maps it to its corresponding _modified_ value.
348pub fn modified_combining_class(c: char) -> ModifiedCombiningClass {
349 if c <= '\u{02FF}' {
350 // Fast path, primarily for Latin. None of the code points in:
351 // U+0000..U+007F | Basic Latin
352 // U+0080..U+00FF | Latin-1 Supplement
353 // U+0100..U+017F | Latin Extended-A
354 // U+0180..U+024F | Latin Extended-B
355 // U+0250..U+02AF | IPA Extensions
356 // U+02B0..U+02FF | Spacing Modifier Letters
357 // are reordering marks.
358 ModifiedCombiningClass::NotReordered
359 } else {
360 MODIFIED_COMBINING_CLASS[get_canonical_combining_class(c) as usize]
361 }
362}
363
364/// Sorts sub-slices of non-starter `char`s (i.e. `char`s with non-zero combining class values) by
365/// their modified combining class values. This sort is stable.
366pub fn sort_by_modified_combining_class(cs: &mut [char]) {
367 for css in
368 cs.split_mut(|&c| modified_combining_class(c) == ModifiedCombiningClass::NotReordered)
369 {
370 css.sort_by_key(|&c| modified_combining_class(c));
371 }
372}