1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
/* Grapheme clusters (UAX #29, Unicode 15.1): text/text.h. One pass, the
* rules in order; three pieces of state for the rules that look further
* back than one character (GB9c, GB11, GB12-13). */
#include "text.h"
void vega_graphemes(const uint32_t *codes, size_t count, uint8_t *breaks) {
breaks[0] = count > 0; /* GB1 */
/* conjunct: 1 after a consonant and extends, 2 once a linker came too
* (GB9c); pictograph: 1 after a pictograph and extends, 2 after its ZWJ
* (GB11); regional: indicators in a row (GB12, GB13). */
unsigned conjunct = 0, pictograph = 0, regional = 0, before = 0;
for (size_t i = 0; i < count; ++i) {
uint8_t property = vega_grapheme(codes[i]);
unsigned now = property & 15, incb = property >> 4;
bool pictographic = vega_extended_pictographic(codes[i]);
if (i) {
bool join;
if (before == VEGA_GCB_CR && now == VEGA_GCB_LF) join = true; /* GB3 */
else if (before == VEGA_GCB_CONTROL || before == VEGA_GCB_CR || before == VEGA_GCB_LF) join = false; /* GB4 */
else if (now == VEGA_GCB_CONTROL || now == VEGA_GCB_CR || now == VEGA_GCB_LF) join = false; /* GB5 */
else if (before == VEGA_GCB_L && (now == VEGA_GCB_L || now == VEGA_GCB_V || now == VEGA_GCB_LV || now == VEGA_GCB_LVT))
join = true; /* GB6 */
else if ((before == VEGA_GCB_LV || before == VEGA_GCB_V) && (now == VEGA_GCB_V || now == VEGA_GCB_T))
join = true; /* GB7 */
else if ((before == VEGA_GCB_LVT || before == VEGA_GCB_T) && now == VEGA_GCB_T) join = true; /* GB8 */
else if (now == VEGA_GCB_EXTEND || now == VEGA_GCB_ZWJ) join = true; /* GB9 */
else if (now == VEGA_GCB_SPACING_MARK) join = true; /* GB9a */
else if (before == VEGA_GCB_PREPEND) join = true; /* GB9b */
else if (conjunct == 2 && incb == VEGA_INCB_CONSONANT) join = true; /* GB9c */
else if (pictograph == 2 && pictographic) join = true; /* GB11 */
else if (before == VEGA_GCB_RI && now == VEGA_GCB_RI && regional % 2) join = true; /* GB12, GB13 */
else join = false; /* GB999 */
breaks[i] = !join;
}
conjunct = incb == VEGA_INCB_CONSONANT ? 1
: conjunct && incb == VEGA_INCB_LINKER ? 2
: conjunct && incb == VEGA_INCB_EXTEND ? conjunct : 0;
pictograph = pictographic ? 1
: pictograph == 1 && now == VEGA_GCB_EXTEND ? 1
: pictograph == 1 && now == VEGA_GCB_ZWJ ? 2 : 0;
regional = now == VEGA_GCB_RI ? regional + 1 : 0;
before = now;
}
breaks[count] = count > 0; /* GB2 */
}
|