92 lines
2.2 KiB
Go
92 lines
2.2 KiB
Go
|
package canvas
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/base64"
|
||
|
"errors"
|
||
|
"image"
|
||
|
"image/png"
|
||
|
"syscall/js"
|
||
|
|
||
|
"git.kirsle.net/apps/doodle/lib/render"
|
||
|
)
|
||
|
|
||
|
// Texture can hold on to cached image textures.
|
||
|
type Texture struct {
|
||
|
data string // data:image/png URI
|
||
|
image js.Value // DOM image element
|
||
|
canvas js.Value // Warmed up canvas element
|
||
|
ctx2d js.Value // 2D drawing context for the canvas.
|
||
|
width int
|
||
|
height int
|
||
|
}
|
||
|
|
||
|
// StoreTexture caches a texture from a bitmap.
|
||
|
func (e *Engine) StoreTexture(name string, img image.Image) (render.Texturer, error) {
|
||
|
var (
|
||
|
fh = bytes.NewBuffer([]byte{})
|
||
|
imageSize = img.Bounds().Size()
|
||
|
width = imageSize.X
|
||
|
height = imageSize.Y
|
||
|
)
|
||
|
|
||
|
// Encode to PNG format.
|
||
|
if err := png.Encode(fh, img); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
var dataURI = "data:image/png;base64," + base64.StdEncoding.EncodeToString(fh.Bytes())
|
||
|
|
||
|
tex := &Texture{
|
||
|
data: dataURI,
|
||
|
width: width,
|
||
|
height: height,
|
||
|
}
|
||
|
|
||
|
// Preheat a cached Canvas object.
|
||
|
canvas := js.Global().Get("document").Call("createElement", "canvas")
|
||
|
canvas.Set("width", width)
|
||
|
canvas.Set("height", height)
|
||
|
tex.canvas = canvas
|
||
|
|
||
|
ctx2d := canvas.Call("getContext", "2d")
|
||
|
tex.ctx2d = ctx2d
|
||
|
|
||
|
// Load as a JS Image object.
|
||
|
image := js.Global().Call("eval", "new Image()")
|
||
|
image.Call("addEventListener", "load", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||
|
ctx2d.Call("drawImage", image, 0, 0)
|
||
|
return nil
|
||
|
}))
|
||
|
image.Set("src", tex.data)
|
||
|
tex.image = image
|
||
|
|
||
|
// Cache the texture in memory.
|
||
|
e.textures[name] = tex
|
||
|
|
||
|
return tex, nil
|
||
|
}
|
||
|
|
||
|
// Size returns the dimensions of the texture.
|
||
|
func (t *Texture) Size() render.Rect {
|
||
|
return render.NewRect(int32(t.width), int32(t.height))
|
||
|
}
|
||
|
|
||
|
// LoadTexture recalls a cached texture image.
|
||
|
func (e *Engine) LoadTexture(name string) (render.Texturer, error) {
|
||
|
if tex, ok := e.textures[name]; ok {
|
||
|
return tex, nil
|
||
|
}
|
||
|
|
||
|
return nil, errors.New("no bitmap data stored for " + name)
|
||
|
}
|
||
|
|
||
|
// Copy a texturer bitmap onto the canvas.
|
||
|
func (e *Engine) Copy(t render.Texturer, src, dist render.Rect) {
|
||
|
tex := t.(*Texture)
|
||
|
|
||
|
// e.canvas.ctx2d.Call("drawImage", tex.image, dist.X, dist.Y)
|
||
|
e.canvas.ctx2d.Call("drawImage", tex.canvas, dist.X, dist.Y)
|
||
|
|
||
|
}
|