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  }