github.com/gop9/olt@v0.0.0-20200202132135-d956aad50b08/gio/op/paint/paint.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package paint 4 5 import ( 6 "encoding/binary" 7 "image" 8 "image/color" 9 "image/draw" 10 "math" 11 12 "github.com/gop9/olt/gio/f32" 13 "github.com/gop9/olt/gio/internal/opconst" 14 "github.com/gop9/olt/gio/op" 15 ) 16 17 // ImageOp sets the material to an image. 18 type ImageOp struct { 19 uniform bool 20 color color.RGBA 21 src *image.RGBA 22 23 // handle is a key to uniquely identify this ImageOp 24 // in a map of cached textures. 25 handle interface{} 26 } 27 28 // ColorOp sets the material to a constant color. 29 type ColorOp struct { 30 Color color.RGBA 31 } 32 33 // PaintOp draws the current material, respecting the 34 // clip path and transformation. 35 type PaintOp struct { 36 Rect f32.Rectangle 37 } 38 39 func NewImageOp(src image.Image) ImageOp { 40 switch src := src.(type) { 41 case *image.Uniform: 42 col := color.RGBAModel.Convert(src.C).(color.RGBA) 43 return ImageOp{ 44 uniform: true, 45 color: col, 46 } 47 case *image.RGBA: 48 bounds := src.Bounds() 49 if bounds.Min == (image.Point{}) && src.Stride == bounds.Dx()*4 { 50 return ImageOp{ 51 src: src, 52 handle: new(int), 53 } 54 } 55 } 56 57 sz := src.Bounds().Size() 58 // Copy the image into a GPU friendly format. 59 dst := image.NewRGBA(image.Rectangle{ 60 Max: sz, 61 }) 62 draw.Draw(dst, src.Bounds(), src, image.Point{}, draw.Src) 63 return ImageOp{ 64 src: dst, 65 handle: new(int), 66 } 67 } 68 69 func (i ImageOp) Size() image.Point { 70 if i.src == nil { 71 return image.Point{} 72 } 73 return i.src.Bounds().Size() 74 } 75 76 func (i ImageOp) Add(o *op.Ops) { 77 if i.uniform { 78 ColorOp{ 79 Color: i.color, 80 }.Add(o) 81 return 82 } 83 data := o.Write(opconst.TypeImageLen, i.src, i.handle) 84 data[0] = byte(opconst.TypeImage) 85 } 86 87 func (c ColorOp) Add(o *op.Ops) { 88 data := o.Write(opconst.TypeColorLen) 89 data[0] = byte(opconst.TypeColor) 90 data[1] = c.Color.R 91 data[2] = c.Color.G 92 data[3] = c.Color.B 93 data[4] = c.Color.A 94 } 95 96 func (d PaintOp) Add(o *op.Ops) { 97 data := o.Write(opconst.TypePaintLen) 98 data[0] = byte(opconst.TypePaint) 99 bo := binary.LittleEndian 100 bo.PutUint32(data[1:], math.Float32bits(d.Rect.Min.X)) 101 bo.PutUint32(data[5:], math.Float32bits(d.Rect.Min.Y)) 102 bo.PutUint32(data[9:], math.Float32bits(d.Rect.Max.X)) 103 bo.PutUint32(data[13:], math.Float32bits(d.Rect.Max.Y)) 104 }