package ui import "strings" // findOptimalFit tries to find the optimal (largest) fit for the interval [0..n] by doing a binary search. func findOptimalFit(n int, fits func(i int) bool) int { if n < 0 || fits(n) { return n } min, max := 0, n for { if min == max { if min == 0 && !fits(min) { return -1 } return min } middle := (max + min + 1) / 2 if fits(middle) { min = middle } else { max = middle - 1 } } } // findSpaces creates a slice with indices where spaces can be found in string s func findSpaces(s string) []int { var spaces []int offset := 0 for { space := strings.Index(s[offset:], " ") if space == -1 { return spaces } offset += space spaces = append(spaces, offset) offset++ } } func fitTextEllipsis(font Font, text string, availableWidth float32) string { if font.WidthOf(text) <= availableWidth { return text } ellipsis := "..." availableWidth -= font.WidthOf(ellipsis) cut := findOptimalFit(len(text), func(i int) bool { return font.WidthOf(text[:i]) <= availableWidth }) if cut == -1 { return "" } return text[:cut] + ellipsis } // fitTextWord tries to fit as much of string s in width space. func fitTextWord(font Font, s string, availableWidth float32) string { if font.WidthOf(s) < availableWidth { return s } spaces := findSpaces(s) split := findOptimalFit(len(spaces)-1, func(i int) bool { return font.WidthOf(s[:spaces[i]]) <= availableWidth }) if split == -1 { return s } return s[:spaces[split]] }