diff --git a/example/go.mod b/example/go.mod index 085344ee..9f02214c 100644 --- a/example/go.mod +++ b/example/go.mod @@ -6,5 +6,6 @@ require ( gioui.org v0.0.0-20191017122224-5c0f1ed95466 github.com/google/go-github/v24 v24.0.1 golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 + golang.org/x/image v0.0.0-20190802002840-cff245a6509b golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 ) diff --git a/example/gophers/main.go b/example/gophers/main.go index bc134cd6..dbcb6d34 100644 --- a/example/gophers/main.go +++ b/example/gophers/main.go @@ -20,7 +20,6 @@ import ( "gioui.org/io/key" "gioui.org/io/system" "gioui.org/layout" - "gioui.org/op/paint" "gioui.org/unit" "github.com/google/go-github/v24/github" @@ -195,7 +194,7 @@ func (a *App) fetchContributors() { go func() { a, err := fetchImage(avatar) if a != nil { - u.avatar = paint.NewImageOp(a) + u.avatar = a } userErrs <- err }() @@ -210,7 +209,7 @@ func (a *App) fetchContributors() { } // Drop users with no avatar or name. for i := len(users) - 1; i >= 0; i-- { - if u := users[i]; u.name == "" || u.avatar.Size() == (image.Point{}) { + if u := users[i]; u.name == "" || u.avatar.Bounds().Size() == (image.Point{}) { users = append(users[:i], users[i+1:]...) } } diff --git a/example/gophers/ui.go b/example/gophers/ui.go index 485c395a..668d09c6 100644 --- a/example/gophers/ui.go +++ b/example/gophers/ui.go @@ -27,6 +27,8 @@ import ( "github.com/google/go-github/v24/github" "golang.org/x/exp/shiny/materialdesign/icons" + + "golang.org/x/image/draw" ) type UI struct { @@ -52,10 +54,11 @@ type userPage struct { } type user struct { - name string - login string - company string - avatar paint.ImageOp + name string + login string + company string + avatar image.Image + avatarOp paint.ImageOp } var theme *material.Theme @@ -172,7 +175,7 @@ func (up *userPage) commit(gtx *layout.Context, index int) { cc := clipCircle{} cc.Layout(gtx, func() { gtx.Constraints = layout.RigidConstraints(gtx.Constraints.Constrain(image.Point{X: sz, Y: sz})) - theme.Image(u.avatar).Layout(gtx) + u.layoutAvatar(gtx) }) }) c2 := f.Flex(gtx, 1, func() { @@ -268,9 +271,10 @@ func (u *UI) user(gtx *layout.Context, index int) { cc := clipCircle{} in.Layout(gtx, func() { cc.Layout(gtx, func() { - sz := image.Point{X: gtx.Px(unit.Dp(48)), Y: gtx.Px(unit.Dp(48))} + dim := gtx.Px(unit.Dp(48)) + sz := image.Point{X: dim, Y: dim} gtx.Constraints = layout.RigidConstraints(gtx.Constraints.Constrain(sz)) - theme.Image(user.avatar).Layout(gtx) + user.layoutAvatar(gtx) }) }) }) @@ -310,6 +314,18 @@ func (u *UI) user(gtx *layout.Context, index int) { elem.Layout(gtx, c1) } +func (u *user) layoutAvatar(gtx *layout.Context) { + sz := gtx.Constraints.Width.Min + if u.avatarOp.Size().X != sz { + img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: sz}}) + draw.ApproxBiLinear.Scale(img, img.Bounds(), u.avatar, u.avatar.Bounds(), draw.Src, nil) + u.avatarOp = paint.NewImageOp(img) + } + img := theme.Image(u.avatarOp) + img.Scale = float32(sz) / float32(gtx.Px(unit.Dp(float32(sz)))) + img.Layout(gtx) +} + type fill struct { col color.RGBA }