detached cee25ed

test(vulkan): cover clipped, clamped, square and rotated hint draws

commit
cee25ed447b54217b537e2368bb78d10be018933
author
brice · · 2026-10-21 08:22 UTC
parent
0647966
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
2/2
1 file · +53 -0
M internal/adapters/vulkan/position_hint_test.go +53 -0
@@ -107,3 +107,56 @@ func TestPositionHintRoundedOrient(t *testing.T) {
107107 require.Equal(t, roundRect(image.Rect(int(d.pc.rect[0]), int(d.pc.rect[1]), int(d.pc.rect[2]), int(d.pc.rect[3]))), d.round)
108108 }
109109 }
110+
111+func TestHintRoundDraws(t *testing.T) {
112+ bounds := image.Rect(0, 0, 100, 100)
113+ for _, tc := range []struct {
114+ name string
115+ rect image.Rectangle
116+ radius int
117+ wantDraws int
118+ wantRadius float32
119+ }{
120+ {"inside", image.Rect(10, 10, 50, 40), 6, 1, 6},
121+ {"clipped fully off output", image.Rect(200, 200, 240, 230), 6, 0, 0},
122+ {"clipped by bounds", image.Rect(90, 90, 130, 130), 6, 1, 6},
123+ {"tiny pill clamps the radius", image.Rect(10, 10, 16, 14), 100, 1, 2},
124+ {"zero radius is a plain fill", image.Rect(10, 10, 50, 40), 0, 1, 0},
125+ {"negative radius is a plain fill", image.Rect(10, 10, 50, 40), -3, 1, 0},
126+ } {
127+ t.Run(tc.name, func(t *testing.T) {
128+ w := sceneWalk{r: &Renderer{width: 100, height: 100}, alpha: 1, bounds: bounds}
129+ w.hintRound(tc.rect, tc.radius, [3]uint8{1, 2, 3})
130+ require.Len(t, w.draws, tc.wantDraws)
131+ for _, d := range w.draws {
132+ if tc.wantRadius == 0 {
133+ require.Zero(t, d.pc.misc[1]&flagRounded)
134+ continue
135+ }
136+ require.NotZero(t, d.pc.misc[1]&flagRounded)
137+ require.Equal(t, roundRect(tc.rect), d.round, "the clip is the requested rect")
138+ require.Equal(t, tc.wantRadius, math.Float32frombits(d.radii[0]))
139+ }
140+ })
141+ }
142+}
143+
144+func TestPositionHintRoundedRotatedOrient(t *testing.T) {
145+ for transform := ports.BufferTransform(1); transform < 8; transform++ {
146+ r := &Renderer{width: 640, height: 480}
147+ sw, sh := r.sceneSize(transform)
148+ s := ports.Scene{OutputWidth: sw, OutputHeight: sh, Scale: 1, Transform: transform, PositionHint: hintGrid(2, 2)}
149+ ds := r.draws(s, nil, newDamage(&target{}, s, image.Rect(0, 0, sw, sh)))
150+ require.Len(t, ds, 1+4)
151+ sceneRects := make([]image.Rectangle, len(ds))
152+ for i, d := range ds {
153+ sceneRects[i] = image.Rect(int(d.pc.rect[0]), int(d.pc.rect[1]), int(d.pc.rect[2]), int(d.pc.rect[3]))
154+ }
155+ r.orient(ds, transform)
156+ for i, d := range ds {
157+ want := transform.RectToBuffer(sceneRects[i], sw, sh)
158+ require.Equal(t, roundRect(want), d.round, "transform %d draw %d", transform, i)
159+ require.NotZero(t, d.pc.misc[1]&flagRounded)
160+ }
161+ }
162+}
@@ -107,3 +107,56 @@ func TestPositionHintRoundedOrient(t *testing.T) {
107 require.Equal(t, roundRect(image.Rect(int(d.pc.rect[0]), int(d.pc.rect[1]), int(d.pc.rect[2]), int(d.pc.rect[3]))), d.round)107 require.Equal(t, roundRect(image.Rect(int(d.pc.rect[0]), int(d.pc.rect[1]), int(d.pc.rect[2]), int(d.pc.rect[3]))), d.round)
108 }108 }
109 }109 }
110+
111+func TestHintRoundDraws(t *testing.T) {
112+ bounds := image.Rect(0, 0, 100, 100)
113+ for _, tc := range []struct {
114+ name string
115+ rect image.Rectangle
116+ radius int
117+ wantDraws int
118+ wantRadius float32
119+ }{
120+ {"inside", image.Rect(10, 10, 50, 40), 6, 1, 6},
121+ {"clipped fully off output", image.Rect(200, 200, 240, 230), 6, 0, 0},
122+ {"clipped by bounds", image.Rect(90, 90, 130, 130), 6, 1, 6},
123+ {"tiny pill clamps the radius", image.Rect(10, 10, 16, 14), 100, 1, 2},
124+ {"zero radius is a plain fill", image.Rect(10, 10, 50, 40), 0, 1, 0},
125+ {"negative radius is a plain fill", image.Rect(10, 10, 50, 40), -3, 1, 0},
126+ } {
127+ t.Run(tc.name, func(t *testing.T) {
128+ w := sceneWalk{r: &Renderer{width: 100, height: 100}, alpha: 1, bounds: bounds}
129+ w.hintRound(tc.rect, tc.radius, [3]uint8{1, 2, 3})
130+ require.Len(t, w.draws, tc.wantDraws)
131+ for _, d := range w.draws {
132+ if tc.wantRadius == 0 {
133+ require.Zero(t, d.pc.misc[1]&flagRounded)
134+ continue
135+ }
136+ require.NotZero(t, d.pc.misc[1]&flagRounded)
137+ require.Equal(t, roundRect(tc.rect), d.round, "the clip is the requested rect")
138+ require.Equal(t, tc.wantRadius, math.Float32frombits(d.radii[0]))
139+ }
140+ })
141+ }
142+}
143+
144+func TestPositionHintRoundedRotatedOrient(t *testing.T) {
145+ for transform := ports.BufferTransform(1); transform < 8; transform++ {
146+ r := &Renderer{width: 640, height: 480}
147+ sw, sh := r.sceneSize(transform)
148+ s := ports.Scene{OutputWidth: sw, OutputHeight: sh, Scale: 1, Transform: transform, PositionHint: hintGrid(2, 2)}
149+ ds := r.draws(s, nil, newDamage(&target{}, s, image.Rect(0, 0, sw, sh)))
150+ require.Len(t, ds, 1+4)
151+ sceneRects := make([]image.Rectangle, len(ds))
152+ for i, d := range ds {
153+ sceneRects[i] = image.Rect(int(d.pc.rect[0]), int(d.pc.rect[1]), int(d.pc.rect[2]), int(d.pc.rect[3]))
154+ }
155+ r.orient(ds, transform)
156+ for i, d := range ds {
157+ want := transform.RectToBuffer(sceneRects[i], sw, sh)
158+ require.Equal(t, roundRect(want), d.round, "transform %d draw %d", transform, i)
159+ require.NotZero(t, d.pc.misc[1]&flagRounded)
160+ }
161+ }
162+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 24

Tags 10

↑↓ moveenter openesc close