Fix charWidths to match Gio's textView PxPerEm calculation

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Greg Pomerantz 2026-05-08 23:37:10 -04:00
parent 96b7c6dc97
commit 87992c3d99
3 changed files with 10 additions and 50 deletions

View File

@ -52,7 +52,7 @@ func EditorLayout(screenWidth, screenHeight unit.Dp) []ui.Element {
// Create StatusBar with mocked filename // Create StatusBar with mocked filename
statusBar := ui.NewStatusBar( statusBar := ui.NewStatusBar(
statusBarRegion, statusBarRegion,
"very_long_filename_that_does_not_fit_on_a_single_line.txt", "very_long_filename_that_does_not_fit_on_a_single_line_and_it_just_keeps_on_going_and_going_and_going_and_going_and_going.txt",
false, // FilenameExp false, // FilenameExp
true, // CutCopy true, // CutCopy
false, // Copy false, // Copy

View File

@ -97,15 +97,11 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) {
// Measure how wide "..." is, then find how many chars fit in availableWidth - ellipsisWidth // Measure how wide "..." is, then find how many chars fit in availableWidth - ellipsisWidth
spaceForText := availableWidth - ellipsisWidth spaceForText := availableWidth - ellipsisWidth
widths := charWidths(gtx, th.Shaper, displayFilename, r.theme.FontSize) widths := charWidths(gtx, th.Shaper, displayFilename, r.theme.FontSize)
if len(widths) > 0 && widths[len(widths)-1] > spaceForText { if len(widths) > 0 && widths[len(widths)-1] > availableWidth {
// Find the largest index where the width fits // Find the largest index where the width fits
for i, w := range widths { for i := len(widths)-1; i >= 0; i-- {
if w <= spaceForText { if widths[i] <= spaceForText {
if i+1 < len(displayFilename) {
displayFilename = displayFilename[:i+1] + "..."
} else {
displayFilename = displayFilename[:i] + "..." displayFilename = displayFilename[:i] + "..."
}
break break
} }
} }
@ -209,54 +205,18 @@ func boolToString(b bool) string {
return "Off" return "Off"
} }
// textWidth measures the total width of a string using the shaper.
func textWidth(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) int {
pixelsPerDp := gtx.Dp(unit.Dp(1))
shp.LayoutString(text.Parameters{PxPerEm: fixed.Int26_6(1024 * pixelsPerDp)}, str)
var minX, maxX fixed.Int26_6
first := true
for {
g, ok := shp.NextGlyph()
if !ok {
break
}
if first {
minX = g.X
maxX = g.X + g.Advance
first = false
} else {
if g.X < minX {
minX = g.X
}
if g.X+g.Advance > maxX {
maxX = g.X + g.Advance
}
}
}
return int(maxX - minX)
}
// charWidths returns the cumulative width after each rune in str. // charWidths returns the cumulative width after each rune in str.
func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) []int { func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) []int {
pixelsPerDp := gtx.Dp(unit.Dp(1)) // Match Gio's textView: PxPerEm = font size in device pixels
shp.LayoutString(text.Parameters{PxPerEm: fixed.Int26_6(1024 * pixelsPerDp)}, str) shp.LayoutString(text.Parameters{PxPerEm: fixed.I(gtx.Sp(size))}, str)
var runeAdvances []fixed.Int26_6 var widths []int
var runeIdx int var cumWidth fixed.Int26_6 = 0
for { for {
g, ok := shp.NextGlyph() g, ok := shp.NextGlyph()
if !ok { if !ok {
break break
} }
if runeIdx < len(str) { cumWidth += g.Advance
runeAdvances = append(runeAdvances, g.Advance)
runeIdx++
}
}
// Accumulate advances and convert from Int26_6 to int (divide by 64)
var widths []int
var cumWidth fixed.Int26_6
for _, adv := range runeAdvances {
cumWidth += adv
widths = append(widths, int(cumWidth>>6)) widths = append(widths, int(cumWidth>>6))
} }
return widths return widths

BIN
pad

Binary file not shown.