image.go raw

   1  // SPDX-License-Identifier: Unlicense OR MIT
   2  
   3  package widget
   4  
   5  import (
   6  	"image"
   7  
   8  	"github.com/p9c/p9/pkg/gel/gio/f32"
   9  	"github.com/p9c/p9/pkg/gel/gio/layout"
  10  	"github.com/p9c/p9/pkg/gel/gio/op"
  11  	"github.com/p9c/p9/pkg/gel/gio/op/paint"
  12  	"github.com/p9c/p9/pkg/gel/gio/unit"
  13  )
  14  
  15  // Image is a widget that displays an image.
  16  type Image struct {
  17  	// Src is the image to display.
  18  	Src paint.ImageOp
  19  	// Fit specifies how to scale the image to the constraints.
  20  	// By default it does not do any scaling.
  21  	Fit Fit
  22  	// Position specifies where to position the image within
  23  	// the constraints.
  24  	Position layout.Direction
  25  	// Scale is the ratio of image pixels to
  26  	// dps. If Scale is zero Image falls back to
  27  	// a scale that match a standard 72 DPI.
  28  	Scale float32
  29  }
  30  
  31  const defaultScale = float32(160.0 / 72.0)
  32  
  33  func (im Image) Layout(gtx layout.Context) layout.Dimensions {
  34  	defer op.Save(gtx.Ops).Load()
  35  
  36  	scale := im.Scale
  37  	if scale == 0 {
  38  		scale = defaultScale
  39  	}
  40  
  41  	size := im.Src.Size()
  42  	wf, hf := float32(size.X), float32(size.Y)
  43  	w, h := gtx.Px(unit.Dp(wf*scale)), gtx.Px(unit.Dp(hf*scale))
  44  
  45  	dims := im.Fit.scale(gtx, im.Position, layout.Dimensions{Size: image.Pt(w, h)})
  46  
  47  	pixelScale := scale * gtx.Metric.PxPerDp
  48  	op.Affine(f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(pixelScale, pixelScale))).Add(gtx.Ops)
  49  
  50  	im.Src.Add(gtx.Ops)
  51  	paint.PaintOp{}.Add(gtx.Ops)
  52  
  53  	return dims
  54  }
  55