1package uniseg
2
3// EastAsianAmbiguousWidth specifies the monospace width for East Asian
4// characters classified as Ambiguous. The default is 1 but some rare fonts
5// render them with a width of 2.
6var EastAsianAmbiguousWidth = 1
7
8// runeWidth returns the monospace width for the given rune. The provided
9// grapheme property is a value mapped by the [graphemeCodePoints] table.
10//
11// Every rune has a width of 1, except for runes with the following properties
12// (evaluated in this order):
13//
14// - Control, CR, LF, Extend, ZWJ: Width of 0
15// - \u2e3a, TWO-EM DASH: Width of 3
16// - \u2e3b, THREE-EM DASH: Width of 4
17// - East-Asian width Fullwidth and Wide: Width of 2 (Ambiguous and Neutral
18// have a width of 1)
19// - Regional Indicator: Width of 2
20// - Extended Pictographic: Width of 2, unless Emoji Presentation is "No".
21func runeWidth(r rune, graphemeProperty int) int {
22 switch graphemeProperty {
23 case prControl, prCR, prLF, prExtend, prZWJ:
24 return 0
25 case prRegionalIndicator:
26 return 2
27 case prExtendedPictographic:
28 if property(emojiPresentation, r) == prEmojiPresentation {
29 return 2
30 }
31 return 1
32 }
33
34 switch r {
35 case 0x2e3a:
36 return 3
37 case 0x2e3b:
38 return 4
39 }
40
41 switch propertyEastAsianWidth(r) {
42 case prW, prF:
43 return 2
44 case prA:
45 return EastAsianAmbiguousWidth
46 }
47
48 return 1
49}
50
51// StringWidth returns the monospace width for the given string, that is, the
52// number of same-size cells to be occupied by the string.
53func StringWidth(s string) (width int) {
54 state := -1
55 for len(s) > 0 {
56 var w int
57 _, s, w, state = FirstGraphemeClusterInString(s, state)
58 width += w
59 }
60 return
61}