Source File
width.go
Belonging Package
golang.org/x/text/width
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate stringer -type=Kind
//go:generate go run gen.go gen_common.go gen_trieval.go
// Package width provides functionality for handling different widths in text.
//
// Wide characters behave like ideographs; they tend to allow line breaks after
// each character and remain upright in vertical text layout. Narrow characters
// are kept together in words or runs that are rotated sideways in vertical text
// layout.
//
// For more information, see https://unicode.org/reports/tr11/.
package width // import "golang.org/x/text/width"
import (
)
// TODO
// 1) Reduce table size by compressing blocks.
// 2) API proposition for computing display length
// (approximation, fixed pitch only).
// 3) Implement display length.
// Kind indicates the type of width property as defined in https://unicode.org/reports/tr11/.
type Kind int
const (
// Neutral characters do not occur in legacy East Asian character sets.
Neutral Kind = iota
// EastAsianAmbiguous characters that can be sometimes wide and sometimes
// narrow and require additional information not contained in the character
// code to further resolve their width.
EastAsianAmbiguous
// EastAsianWide characters are wide in its usual form. They occur only in
// the context of East Asian typography. These runes may have explicit
// halfwidth counterparts.
EastAsianWide
// EastAsianNarrow characters are narrow in its usual form. They often have
// fullwidth counterparts.
EastAsianNarrow
// Note: there exist Narrow runes that do not have fullwidth or wide
// counterparts, despite what the definition says (e.g. U+27E6).
// EastAsianFullwidth characters have a compatibility decompositions of type
// wide that map to a narrow counterpart.
EastAsianFullwidth
// EastAsianHalfwidth characters have a compatibility decomposition of type
// narrow that map to a wide or ambiguous counterpart, plus U+20A9 ₩ WON
// SIGN.
EastAsianHalfwidth
// Note: there exist runes that have a halfwidth counterparts but that are
// classified as Ambiguous, rather than wide (e.g. U+2190).
)
// TODO: the generated tries need to return size 1 for invalid runes for the
// width to be computed correctly (each byte should render width 1)
var trie = newWidthTrie(0)
// Lookup reports the Properties of the first rune in b and the number of bytes
// of its UTF-8 encoding.
func ( []byte) ( Properties, int) {
, := trie.lookup()
return Properties{elem(), [-1]},
}
// LookupString reports the Properties of the first rune in s and the number of
// bytes of its UTF-8 encoding.
func ( string) ( Properties, int) {
, := trie.lookupString()
return Properties{elem(), [-1]},
}
// LookupRune reports the Properties of rune r.
func ( rune) Properties {
var [4]byte
:= utf8.EncodeRune([:], )
, := trie.lookup([:])
:= byte()
if >= utf8.RuneSelf {
= 0x80 + byte(&0x3f)
}
return Properties{elem(), }
}
// Properties provides access to width properties of a rune.
type Properties struct {
elem elem
last byte
}
func ( elem) () Kind {
return Kind( >> typeShift)
}
// Kind returns the Kind of a rune as defined in Unicode TR #11.
// See https://unicode.org/reports/tr11/ for more details.
func ( Properties) () Kind {
return .elem.kind()
}
// Folded returns the folded variant of a rune or 0 if the rune is canonical.
func ( Properties) () rune {
if .elem&tagNeedsFold != 0 {
:= inverseData[byte(.elem)]
[[0]] ^= .last
, := utf8.DecodeRune([1 : 1+[0]])
return
}
return 0
}
// Narrow returns the narrow variant of a rune or 0 if the rune is already
// narrow or doesn't have a narrow variant.
func ( Properties) () rune {
if := .elem.kind(); byte(.elem) != 0 && ( == EastAsianFullwidth || == EastAsianWide || == EastAsianAmbiguous) {
:= inverseData[byte(.elem)]
[[0]] ^= .last
, := utf8.DecodeRune([1 : 1+[0]])
return
}
return 0
}
// Wide returns the wide variant of a rune or 0 if the rune is already
// wide or doesn't have a wide variant.
func ( Properties) () rune {
if := .elem.kind(); byte(.elem) != 0 && ( == EastAsianHalfwidth || == EastAsianNarrow) {
:= inverseData[byte(.elem)]
[[0]] ^= .last
, := utf8.DecodeRune([1 : 1+[0]])
return
}
return 0
}
// TODO for Properties:
// - Add Fullwidth/Halfwidth or Inverted methods for computing variants
// mapping.
// - Add width information (including information on non-spacing runes).
// Transformer implements the transform.Transformer interface.
type Transformer struct {
t transform.SpanningTransformer
}
// Reset implements the transform.Transformer interface.
func ( Transformer) () { .t.Reset() }
// Transform implements the transform.Transformer interface.
func ( Transformer) (, []byte, bool) (, int, error) {
return .t.Transform(, , )
}
// Span implements the transform.SpanningTransformer interface.
func ( Transformer) ( []byte, bool) ( int, error) {
return .t.Span(, )
}
// Bytes returns a new byte slice with the result of applying t to b.
func ( Transformer) ( []byte) []byte {
, _, _ = transform.Bytes(, )
return
}
// String returns a string with the result of applying t to s.
func ( Transformer) ( string) string {
, _, _ = transform.String(, )
return
}
var (
// Fold is a transform that maps all runes to their canonical width.
//
// Note that the NFKC and NFKD transforms in golang.org/x/text/unicode/norm
// provide a more generic folding mechanism.
Fold Transformer = Transformer{foldTransform{}}
// Widen is a transform that maps runes to their wide variant, if
// available.
Widen Transformer = Transformer{wideTransform{}}
// Narrow is a transform that maps runes to their narrow variant, if
// available.
Narrow Transformer = Transformer{narrowTransform{}}
)
// TODO: Consider the following options:
// - Treat Ambiguous runes that have a halfwidth counterpart as wide, or some
// generalized variant of this.
// - Consider a wide Won character to be the default width (or some generalized
// variant of this).
// - Filter the set of characters that gets converted (the preferred approach is
// to allow applying filters to transforms).
![]() |
The pages are generated with Golds v0.6.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |