forked from joejulian/gio
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:
+6
-1
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user