widget: fix image scaling

Commit 94d242d broke the widget.Image's Scale field so
that it no longer had any effect on the actual size of
the displayed image. This commit fixes that, as well as
adding tests to confirm that the widget.Image type
scales appropriately with DPI changes and its own Scale
field.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
Chris Waldon
2021-02-27 22:18:09 -05:00
committed by Elias Naur
parent 60db802951
commit 6faed7e724
2 changed files with 72 additions and 1 deletions
+6 -1
View File
@@ -5,6 +5,7 @@ package widget
import (
"image"
"gioui.org/f32"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
@@ -22,10 +23,12 @@ type Image struct {
Scale float32
}
const defaultScale = float32(160.0 / 72.0)
func (im Image) Layout(gtx layout.Context) layout.Dimensions {
scale := im.Scale
if scale == 0 {
scale = 160.0 / 72.0
scale = defaultScale
}
size := im.Src.Size()
wf, hf := float32(size.X), float32(size.Y)
@@ -33,6 +36,8 @@ func (im Image) Layout(gtx layout.Context) layout.Dimensions {
cs := gtx.Constraints
d := cs.Constrain(image.Pt(w, h))
stack := op.Save(gtx.Ops)
pixelScale := scale * gtx.Metric.PxPerDp
op.Affine(f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(pixelScale, pixelScale))).Add(gtx.Ops)
clip.Rect(image.Rectangle{Max: d}).Add(gtx.Ops)
im.Src.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops)
+66
View File
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: Unlicense OR MIT
package widget
import (
"image"
"testing"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/paint"
)
func TestImageScale(t *testing.T) {
var ops op.Ops
gtx := layout.Context{
Ops: &ops,
Constraints: layout.Constraints{
Max: image.Pt(50, 50),
},
}
imgSize := image.Pt(10, 10)
img := image.NewNRGBA(image.Rectangle{Max: imgSize})
imgOp := paint.NewImageOp(img)
// Ensure the default scales correctly.
dims := Image{Src: imgOp}.Layout(gtx)
expectedSize := imgSize
expectedSize.X = int(float32(expectedSize.X) * defaultScale)
expectedSize.Y = int(float32(expectedSize.Y) * defaultScale)
if dims.Size != expectedSize {
t.Fatalf("non-scaled image is wrong size, expected %v, got %v", expectedSize, dims.Size)
}
// Ensure scaling the image via the Scale field works.
currentScale := float32(0.5)
dims = Image{Src: imgOp, Scale: float32(currentScale)}.Layout(gtx)
expectedSize = imgSize
expectedSize.X = int(float32(expectedSize.X) * currentScale)
expectedSize.Y = int(float32(expectedSize.Y) * currentScale)
if dims.Size != expectedSize {
t.Fatalf(".5 scale image is wrong size, expected %v, got %v", expectedSize, dims.Size)
}
// Ensure the image responds to changes in DPI.
currentScale = float32(1)
gtx.Metric.PxPerDp = 2
dims = Image{Src: imgOp, Scale: float32(currentScale)}.Layout(gtx)
expectedSize = imgSize
expectedSize.X = int(float32(expectedSize.X) * currentScale * gtx.Metric.PxPerDp)
expectedSize.Y = int(float32(expectedSize.Y) * currentScale * gtx.Metric.PxPerDp)
if dims.Size != expectedSize {
t.Fatalf("HiDPI non-scaled image is wrong size, expected %v, got %v", expectedSize, dims.Size)
}
// Ensure scaling the image responds to changes in DPI.
currentScale = float32(.5)
gtx.Metric.PxPerDp = 2
dims = Image{Src: imgOp, Scale: float32(currentScale)}.Layout(gtx)
expectedSize = imgSize
expectedSize.X = int(float32(expectedSize.X) * currentScale * gtx.Metric.PxPerDp)
expectedSize.Y = int(float32(expectedSize.Y) * currentScale * gtx.Metric.PxPerDp)
if dims.Size != expectedSize {
t.Fatalf("HiDPI .5 scale image is wrong size, expected %v, got %v", expectedSize, dims.Size)
}
}