width.go (1631B)
1 package 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. 6 var 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". 21 func 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. 53 func 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 }