text,widget: test and fix minWidth alignment

This commit unifies and fixes the shaper's handling of the alignment
minimum width. Previously it was only considered when the text was
a single line, but in hindsight that was clearly a mistake. Now the
maximum width of all shaped lines and the minimum width is used to
set the text alignment.

This commit also fixes an index test in package widget that was
relying on the old (incorrect) alignment behavior.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
Chris Waldon
2022-12-19 10:49:57 -05:00
committed by Elias Naur
parent fe5878bc63
commit c455f0f342
3 changed files with 73 additions and 7 deletions
+8 -5
View File
@@ -480,18 +480,21 @@ func (s *shaperImpl) LayoutRunes(params Parameters, minWidth, maxWidth int, lc s
}
textLines[i] = otLine
}
alignWidth := maxWidth
if len(textLines) == 1 {
alignWidth = max(minWidth, textLines[0].width.Ceil())
}
calculateYOffsets(textLines)
return document{
lines: textLines,
alignment: params.Alignment,
alignWidth: alignWidth,
alignWidth: alignWidth(minWidth, textLines),
}
}
func alignWidth(minWidth int, lines []line) int {
for _, l := range lines {
minWidth = max(minWidth, l.width.Ceil())
}
return minWidth
}
// Shape converts the provided glyphs into a path.
func (s *shaperImpl) Shape(ops *op.Ops, gs []Glyph) clip.PathSpec {
var lastPos f32.Point
+63
View File
@@ -55,6 +55,69 @@ func TestEmptyString(t *testing.T) {
}
}
func TestAlignWidth(t *testing.T) {
lines := []line{
{width: fixed.I(50)},
{width: fixed.I(75)},
{width: fixed.I(25)},
}
for _, minWidth := range []int{0, 50, 100} {
width := alignWidth(minWidth, lines)
if width < minWidth {
t.Errorf("expected width >= %d, got %d", minWidth, width)
}
}
}
func TestShapingAlignWidth(t *testing.T) {
ppem := fixed.I(10)
ltrFace, _ := opentype.Parse(goregular.TTF)
shaper := testShaper(ltrFace)
type testcase struct {
name string
minWidth, maxWidth int
expected int
str string
}
for _, tc := range []testcase{
{
name: "zero min",
maxWidth: 100,
str: "a\nb\nc",
expected: 22,
},
{
name: "min == max",
minWidth: 100,
maxWidth: 100,
str: "a\nb\nc",
expected: 100,
},
{
name: "min < max",
minWidth: 50,
maxWidth: 100,
str: "a\nb\nc",
expected: 50,
},
{
name: "min < max, text > min",
minWidth: 50,
maxWidth: 100,
str: "aphabetic\nb\nc",
expected: 60,
},
} {
t.Run(tc.name, func(t *testing.T) {
lines := shaper.LayoutString(Parameters{PxPerEm: ppem}, tc.minWidth, tc.maxWidth, english, tc.str)
if lines.alignWidth != tc.expected {
t.Errorf("expected line alignWidth to be %d, got %d", tc.expected, lines.alignWidth)
}
})
}
}
// TestNewlineSynthesis ensures that the shaper correctly inserts synthetic glyphs
// representing newline runes.
func TestNewlineSynthesis(t *testing.T) {