mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55:40 +00:00
widget: test firstPos
This commit adds a test to lock in the correct behavior of the firstPos helper method. Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
+8
-4
@@ -76,6 +76,14 @@ func subLayout(line text.Line, start, end combinedPos) text.Layout {
|
|||||||
return line.Layout.Slice(startCluster, endCluster)
|
return line.Layout.Slice(startCluster, endCluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// firstPos returns a combinedPos with *only* the x and y
|
||||||
|
// fields populated. They will be set to the location of the
|
||||||
|
// dot at the beginning of the line, with text alignment taken
|
||||||
|
// into account. For RTL text, this will
|
||||||
|
// be on the right edge of the available space.
|
||||||
|
//
|
||||||
|
// The results can be counterinuitive due to the fact that meaning
|
||||||
|
// of alignment changes depending on the text direction.
|
||||||
func firstPos(line text.Line, alignment text.Alignment, width int) combinedPos {
|
func firstPos(line text.Line, alignment text.Alignment, width int) combinedPos {
|
||||||
p := combinedPos{
|
p := combinedPos{
|
||||||
x: align(alignment, line.Layout.Direction, line.Width, width),
|
x: align(alignment, line.Layout.Direction, line.Width, width),
|
||||||
@@ -88,10 +96,6 @@ func firstPos(line text.Line, alignment text.Alignment, width int) combinedPos {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p1 screenPos) Less(p2 screenPos) bool {
|
|
||||||
return p1.Y < p2.Y || (p1.Y == p2.Y && p1.X < p2.X)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size unit.Sp, txt string) layout.Dimensions {
|
func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size unit.Sp, txt string) layout.Dimensions {
|
||||||
cs := gtx.Constraints
|
cs := gtx.Constraints
|
||||||
textSize := fixed.I(gtx.Sp(size))
|
textSize := fixed.I(gtx.Sp(size))
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package widget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
nsareg "eliasnaur.com/font/noto/sans/arabic/regular"
|
||||||
|
"gioui.org/font/opentype"
|
||||||
|
"gioui.org/text"
|
||||||
|
"golang.org/x/image/font/gofont/goregular"
|
||||||
|
"golang.org/x/image/math/fixed"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFirstPos(t *testing.T) {
|
||||||
|
ltrFace, _ := opentype.Parse(goregular.TTF)
|
||||||
|
rtlFace, _ := opentype.Parse(nsareg.TTF)
|
||||||
|
|
||||||
|
shaper := text.NewCache([]text.FontFace{
|
||||||
|
{
|
||||||
|
Font: text.Font{Typeface: "LTR"},
|
||||||
|
Face: ltrFace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Font: text.Font{Typeface: "RTL"},
|
||||||
|
Face: rtlFace,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
fontSize := 16
|
||||||
|
lineWidth := int(fontSize) * 10
|
||||||
|
ltrText := shaper.LayoutString(text.Font{Typeface: "LTR"}, fixed.I(fontSize), lineWidth, english, "The quick brown fox\njumps over the lazy dog.")
|
||||||
|
rtlText := shaper.LayoutString(text.Font{Typeface: "RTL"}, fixed.I(fontSize), lineWidth, arabic, "الحب سماء لا\nتمط غير الأحلام")
|
||||||
|
|
||||||
|
type testcase struct {
|
||||||
|
name string
|
||||||
|
line text.Line
|
||||||
|
xAlignMap map[text.Alignment]map[int]fixed.Int26_6
|
||||||
|
expected combinedPos
|
||||||
|
}
|
||||||
|
for _, tc := range []testcase{
|
||||||
|
{
|
||||||
|
name: "ltr line 0",
|
||||||
|
line: ltrText[0],
|
||||||
|
xAlignMap: map[text.Alignment]map[int]fixed.Int26_6{
|
||||||
|
text.Start: {
|
||||||
|
lineWidth: 0,
|
||||||
|
lineWidth * 2: 0,
|
||||||
|
},
|
||||||
|
text.Middle: {
|
||||||
|
lineWidth: fixed.I(8),
|
||||||
|
lineWidth * 2: fixed.I(88),
|
||||||
|
},
|
||||||
|
text.End: {
|
||||||
|
lineWidth: fixed.I(16),
|
||||||
|
lineWidth * 2: fixed.I(176),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: combinedPos{
|
||||||
|
x: 0,
|
||||||
|
y: ltrText[0].Ascent.Ceil(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ltr line 1",
|
||||||
|
line: ltrText[1],
|
||||||
|
xAlignMap: map[text.Alignment]map[int]fixed.Int26_6{
|
||||||
|
text.Start: {
|
||||||
|
lineWidth: 0,
|
||||||
|
lineWidth * 2: 0,
|
||||||
|
},
|
||||||
|
text.Middle: {
|
||||||
|
lineWidth: fixed.I(8),
|
||||||
|
lineWidth * 2: fixed.I(88),
|
||||||
|
},
|
||||||
|
text.End: {
|
||||||
|
lineWidth: fixed.I(16),
|
||||||
|
lineWidth * 2: fixed.I(176),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: combinedPos{
|
||||||
|
x: 0,
|
||||||
|
y: ltrText[1].Ascent.Ceil(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rtl line 0",
|
||||||
|
line: rtlText[0],
|
||||||
|
xAlignMap: map[text.Alignment]map[int]fixed.Int26_6{
|
||||||
|
text.End: {
|
||||||
|
lineWidth: rtlText[0].Width,
|
||||||
|
lineWidth * 2: rtlText[0].Width,
|
||||||
|
},
|
||||||
|
text.Middle: {
|
||||||
|
lineWidth: fixed.Int26_6(7827),
|
||||||
|
lineWidth * 2: fixed.Int26_6(12947),
|
||||||
|
},
|
||||||
|
text.Start: {
|
||||||
|
lineWidth: fixed.Int26_6(10195),
|
||||||
|
lineWidth * 2: fixed.Int26_6(20435),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: combinedPos{
|
||||||
|
x: 0,
|
||||||
|
y: rtlText[0].Ascent.Ceil(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rtl line 1",
|
||||||
|
line: rtlText[1],
|
||||||
|
xAlignMap: map[text.Alignment]map[int]fixed.Int26_6{
|
||||||
|
text.End: {
|
||||||
|
lineWidth: rtlText[1].Width,
|
||||||
|
lineWidth * 2: rtlText[1].Width,
|
||||||
|
},
|
||||||
|
text.Middle: {
|
||||||
|
lineWidth: fixed.Int26_6(8184),
|
||||||
|
lineWidth * 2: fixed.Int26_6(13304),
|
||||||
|
},
|
||||||
|
text.Start: {
|
||||||
|
lineWidth: fixed.Int26_6(10232),
|
||||||
|
lineWidth * 2: fixed.Int26_6(20472),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: combinedPos{
|
||||||
|
x: 0,
|
||||||
|
y: rtlText[1].Ascent.Ceil(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
for align, cases := range tc.xAlignMap {
|
||||||
|
for width, expectedX := range cases {
|
||||||
|
t.Run(tc.name+" "+align.String()+" "+strconv.Itoa(width), func(t *testing.T) {
|
||||||
|
actual := firstPos(tc.line, align, width)
|
||||||
|
tc.expected.x = expectedX
|
||||||
|
if tc.expected.x != actual.x {
|
||||||
|
t.Errorf("expected x=%s(%d), got %s(%d)", tc.expected.x, tc.expected.x, actual.x, actual.x)
|
||||||
|
}
|
||||||
|
if tc.expected.y != actual.y {
|
||||||
|
t.Errorf("expected y=%d(%d), got %d(%d)", tc.expected.y, tc.expected.y, actual.y, actual.y)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user