github.com/Seikaijyu/gio@v0.0.1/widget/icon.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  package widget
     4  
     5  import (
     6  	"image"
     7  	"image/color"
     8  	"image/draw"
     9  
    10  	"github.com/Seikaijyu/gio/internal/f32color"
    11  	"github.com/Seikaijyu/gio/layout"
    12  	"github.com/Seikaijyu/gio/op/clip"
    13  	"github.com/Seikaijyu/gio/op/paint"
    14  	"github.com/Seikaijyu/gio/unit"
    15  
    16  	"golang.org/x/exp/shiny/iconvg"
    17  )
    18  
    19  type Icon struct {
    20  	src []byte
    21  	// Cached values.
    22  	op       paint.ImageOp
    23  	imgSize  int
    24  	imgColor color.NRGBA
    25  }
    26  
    27  const defaultIconSize = unit.Dp(24)
    28  
    29  // NewIcon returns a new Icon from IconVG data.
    30  func NewIcon(data []byte) (*Icon, error) {
    31  	_, err := iconvg.DecodeMetadata(data)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	return &Icon{src: data}, nil
    36  }
    37  
    38  // Layout displays the icon with its size set to the X minimum constraint.
    39  func (ic *Icon) Layout(gtx layout.Context, color color.NRGBA) layout.Dimensions {
    40  	sz := gtx.Constraints.Min.X
    41  	if sz == 0 {
    42  		sz = gtx.Dp(defaultIconSize)
    43  	}
    44  	size := gtx.Constraints.Constrain(image.Pt(sz, sz))
    45  	defer clip.Rect{Max: size}.Push(gtx.Ops).Pop()
    46  
    47  	ico := ic.image(size.X, color)
    48  	ico.Add(gtx.Ops)
    49  	paint.PaintOp{}.Add(gtx.Ops)
    50  	return layout.Dimensions{
    51  		Size: ico.Size(),
    52  	}
    53  }
    54  
    55  func (ic *Icon) image(sz int, color color.NRGBA) paint.ImageOp {
    56  	if sz == ic.imgSize && color == ic.imgColor {
    57  		return ic.op
    58  	}
    59  	m, _ := iconvg.DecodeMetadata(ic.src)
    60  	dx, dy := m.ViewBox.AspectRatio()
    61  	img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: int(float32(sz) * dy / dx)}})
    62  	var ico iconvg.Rasterizer
    63  	ico.SetDstImage(img, img.Bounds(), draw.Src)
    64  	m.Palette[0] = f32color.NRGBAToLinearRGBA(color)
    65  	iconvg.Decode(&ico, ic.src, &iconvg.DecodeOptions{
    66  		Palette: &m.Palette,
    67  	})
    68  	ic.op = paint.NewImageOp(img)
    69  	ic.imgSize = sz
    70  	ic.imgColor = color
    71  	return ic.op
    72  }