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}