diff --git a/internal/ui/render.go b/internal/ui/render.go index b356768..fd30d07 100644 --- a/internal/ui/render.go +++ b/internal/ui/render.go @@ -2,6 +2,7 @@ package ui import ( "image" + "log" "gioui.org/layout" "gioui.org/op" @@ -92,11 +93,13 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) { // Truncate filename only if it doesn't fit displayFilename := sb.Filename availableWidth := int(reg.W - unit.Dp(8) - unit.Dp(40)) // left margin + right icons in DP - ellipsisWidth := textWidth(gtx, th.Shaper, "...", r.theme.FontSize) + ellipsisWidths := charWidths(gtx, th.Shaper, "...", r.theme.FontSize) + ellipsisWidth := ellipsisWidths[len(ellipsisWidths)-1] // Measure how wide "..." is, then find how many chars fit in availableWidth - ellipsisWidth spaceForText := availableWidth - ellipsisWidth widths := charWidths(gtx, th.Shaper, displayFilename, r.theme.FontSize) - if len(widths) > 0 && widths[len(widths)-1] > availableWidth { + log.Printf("drawStatusBar: filename=%q availableWidth=%d ellipsisWidth=%d spaceForText=%d widths=%v", displayFilename, availableWidth, ellipsisWidth, spaceForText, widths) + if len(widths) > 0 && widths[len(widths)-1] > spaceForText { // Find the largest index where the width fits for i, w := range widths { if w <= spaceForText { @@ -109,6 +112,7 @@ func (r *Renderer) drawStatusBar(gtx layout.Context, sb StatusBar) { } } } + log.Printf("drawStatusBar: final filename=%q", displayFilename) // Position filename at (reg.X + 8, filenameLineY) call1 := op.Offset(image.Point{X: int(reg.X + unit.Dp(8)), Y: int(filenameLineY)}).Push(gtx.Ops) @@ -210,38 +214,54 @@ func boolToString(b bool) string { // 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 { - shp.LayoutString(text.Parameters{PxPerEm: 1024}, str) - var lastX fixed.Int26_6 + 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 } - x := g.X + g.Advance - if x > lastX { - lastX = x + 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(lastX) + return int(maxX - minX) } // charWidths returns the cumulative width after each rune in str. func charWidths(gtx layout.Context, shp *text.Shaper, str string, size unit.Sp) []int { - shp.LayoutString(text.Parameters{PxPerEm: 1024}, str) - var widths []int - var cumX fixed.Int26_6 + pixelsPerDp := gtx.Dp(unit.Dp(1)) + shp.LayoutString(text.Parameters{PxPerEm: fixed.Int26_6(1024 * pixelsPerDp)}, str) + var runeAdvances []fixed.Int26_6 var runeIdx int for { g, ok := shp.NextGlyph() if !ok { break } - cumX = g.X + g.Advance - // Each glyph corresponds to one rune in our simple ASCII case if runeIdx < len(str) { - widths = append(widths, int(cumX)) + 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)) + } + log.Printf("charWidths: runeAdvances=%v widths=%v", runeAdvances, widths) return widths } diff --git a/pad b/pad index 538de64..aac5f44 100755 Binary files a/pad and b/pad differ