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