text/wrap.go
Functions
func IsCJKRune
func IsCJKRune(r rune) bool {
return (r >= 0x4E00 && r <= 0x9FFF) || // CJK Unified Ideographs
(r >= 0x3400 && r <= 0x4DBF) || // CJK Extension A
(r >= 0x20000 && r <= 0x2A6DF) || // CJK Extension B
(r >= 0x3040 && r <= 0x309F) || // Hiragana
(r >= 0x30A0 && r <= 0x30FF) || // Katakana
(r >= 0xAC00 && r <= 0xD7AF) || // Hangul Syllables
(r >= 0xFF00 && r <= 0xFFEF) // Fullwidth forms
}
func MeasureText
MeasureText measures the total advance width of text.
The font size is obtained from face.Size().
func MeasureText(text string, face Face) float64 {
if text == "" || face == nil {
return 0
}
glyphs := Shape(text, face)
var width float64
for i := range glyphs {
width += glyphs[i].XAdvance
}
return width
}
func String
String returns the string representation of the wrap mode.
func (m WrapMode) String() string {
switch m {
case WrapNone:
return "None"
case WrapWord:
return "Word"
case WrapChar:
return "Char"
case WrapWordChar:
return "WordChar"
default:
return unknownStr
}
}
func WrapText
WrapText wraps text to fit within maxWidth using the specified face and options.
Hard line breaks (\n, \r\n, \r) are respected — each paragraph is wrapped independently.
The font size is obtained from face.Size().
Returns a slice of wrapped line results.
func WrapText(text string, face Face, maxWidth float64, mode WrapMode) []WrapResult {
if text == "" || maxWidth <= 0 {
return []WrapResult{{Text: text, Start: 0, End: len(text)}}
}
if mode == WrapNone {
return []WrapResult{{Text: text, Start: 0, End: len(text)}}
}
// Normalize line endings and split into paragraphs
normalized := strings.ReplaceAll(text, "\r\n", "\n")
normalized = strings.ReplaceAll(normalized, "\r", "\n")
paragraphs := strings.Split(normalized, "\n")
results := make([]WrapResult, 0, len(paragraphs))
byteOffset := 0
for _, para := range paragraphs {
if para == "" {
// Empty paragraph (blank line) — preserve as empty line
results = append(results, WrapResult{
Text: "",
Start: byteOffset,
End: byteOffset,
})
byteOffset++ // skip the \n
continue
}
// Wrap this paragraph
paraResults := wrapParagraph(para, face, maxWidth, mode)
// Adjust byte offsets relative to original text
for i := range paraResults {
paraResults[i].Start += byteOffset
paraResults[i].End += byteOffset
}
results = append(results, paraResults...)
byteOffset += len(para) + 1 // +1 for the \n separator
}
return results
}
Structs
type WrapResult struct
WrapResult represents a wrapped line of text.
type WrapResult struct {
// Text is the content of this line.
Text string
// Start is the byte offset in the original text.
Start int
// End is the byte offset in the original text.
End int
}
IsCJKRune returns true if the rune is a CJK character.
Used for script-aware text rendering (ADR-027: CJK hinting, bucket bypass)
and line break opportunities.