mirror of https://github.com/anoshenko/rui.git
Canvas refactoring
This commit is contained in:
parent
b26525e892
commit
8200f98d0d
48
appWasm.go
48
appWasm.go
|
@ -4,6 +4,8 @@ package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"encoding/base64"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
)
|
)
|
||||||
|
@ -112,10 +114,46 @@ func (app *wasmApp) createSession() Session {
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *wasmApp) init() {
|
func (app *wasmApp) init(params AppParams) {
|
||||||
|
|
||||||
|
app.params = params
|
||||||
|
|
||||||
document := js.Global().Get("document")
|
document := js.Global().Get("document")
|
||||||
body := document.Call("querySelector", "body")
|
body := document.Call("querySelector", "body")
|
||||||
|
head := document.Call("querySelector", "head")
|
||||||
|
|
||||||
|
meta := document.Call("createElement", "meta")
|
||||||
|
meta.Set("name", "viewport")
|
||||||
|
meta.Set("content", "width=device-width")
|
||||||
|
head.Call("appendChild", meta)
|
||||||
|
|
||||||
|
meta = document.Call("createElement", "base")
|
||||||
|
meta.Set("target", "_blank")
|
||||||
|
meta.Set("rel", "noopener")
|
||||||
|
head.Call("appendChild", meta)
|
||||||
|
|
||||||
|
if params.Icon != "" {
|
||||||
|
if image, ok := resources.images[params.Icon]; ok && image.fs != nil {
|
||||||
|
dataType := map[string]string{
|
||||||
|
".svg": "data:image/svg+xml",
|
||||||
|
".png": "data:image/png",
|
||||||
|
".jpg": "data:image/jpg",
|
||||||
|
".jpeg": "data:image/jpg",
|
||||||
|
".gif": "data:image/gif",
|
||||||
|
}
|
||||||
|
ext := strings.ToLower(filepath.Ext(params.Icon))
|
||||||
|
if prefix, ok := dataType[ext]; ok {
|
||||||
|
if data, err := image.fs.ReadFile(image.path); err == nil {
|
||||||
|
meta = document.Call("createElement", "link")
|
||||||
|
meta.Set("rel", "icon")
|
||||||
|
meta.Set("href", prefix+";base64,"+base64.StdEncoding.EncodeToString(data))
|
||||||
|
head.Call("appendChild", meta)
|
||||||
|
} else {
|
||||||
|
DebugLog(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
script := document.Call("createElement", "script")
|
script := document.Call("createElement", "script")
|
||||||
script.Set("type", "text/javascript")
|
script.Set("type", "text/javascript")
|
||||||
|
@ -156,6 +194,11 @@ func (app *wasmApp) init() {
|
||||||
div.Set("download", "")
|
div.Set("download", "")
|
||||||
div.Set("style", "display: none;")
|
div.Set("style", "display: none;")
|
||||||
body.Call("appendChild", div)
|
body.Call("appendChild", div)
|
||||||
|
|
||||||
|
if params.TitleColor != 0 {
|
||||||
|
app.brige.runFunc("setTitleColor", params.TitleColor.cssString())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartApp - create the new wasmApp and start it
|
// StartApp - create the new wasmApp and start it
|
||||||
|
@ -168,11 +211,10 @@ func StartApp(addr string, createContentFunc func(Session) SessionContent, param
|
||||||
}
|
}
|
||||||
|
|
||||||
app := new(wasmApp)
|
app := new(wasmApp)
|
||||||
app.params = params
|
|
||||||
app.createContentFunc = createContentFunc
|
app.createContentFunc = createContentFunc
|
||||||
app.brige = createWasmBrige()
|
app.brige = createWasmBrige()
|
||||||
|
|
||||||
app.init()
|
app.init(params)
|
||||||
<-app.close
|
<-app.close
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1796,3 +1796,16 @@ function getPropertyValue(answerID, elementId, name) {
|
||||||
function appendStyles(styles) {
|
function appendStyles(styles) {
|
||||||
document.querySelector('style').textContent += styles
|
document.querySelector('style').textContent += styles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCanvasContext(elementId) {
|
||||||
|
const canvas = document.getElementById(elementId)
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
//var gradient;
|
||||||
|
//var path;
|
||||||
|
//var img;
|
||||||
|
ctx.canvas.width = dpr * canvas.clientWidth;
|
||||||
|
ctx.canvas.height = dpr * canvas.clientHeight;
|
||||||
|
ctx.scale(dpr, dpr);
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
543
canvas.go
543
canvas.go
|
@ -1,7 +1,7 @@
|
||||||
package rui
|
package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -290,42 +290,24 @@ type Canvas interface {
|
||||||
// in the rectangle (dstX, dstY, dstWidth, dstHeight), scaling in height and width if necessary
|
// in the rectangle (dstX, dstY, dstWidth, dstHeight), scaling in height and width if necessary
|
||||||
DrawImageFragment(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight float64, image Image)
|
DrawImageFragment(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight float64, image Image)
|
||||||
|
|
||||||
finishDraw() string
|
finishDraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
type canvasData struct {
|
type canvasData struct {
|
||||||
view CanvasView
|
view CanvasView
|
||||||
script strings.Builder
|
session Session
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCanvas(view CanvasView) Canvas {
|
func newCanvas(view CanvasView) Canvas {
|
||||||
canvas := new(canvasData)
|
canvas := new(canvasData)
|
||||||
canvas.view = view
|
canvas.view = view
|
||||||
canvas.script.Grow(4096)
|
canvas.session = view.Session()
|
||||||
canvas.script.WriteString(`const canvas = document.getElementById('`)
|
canvas.session.cavnasStart(view.htmlID())
|
||||||
canvas.script.WriteString(view.htmlID())
|
|
||||||
canvas.script.WriteString(`');
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
const dpr = window.devicePixelRatio || 1;
|
|
||||||
var gradient;
|
|
||||||
var path;
|
|
||||||
var img;
|
|
||||||
ctx.canvas.width = dpr * canvas.clientWidth;
|
|
||||||
ctx.canvas.height = dpr * canvas.clientHeight;
|
|
||||||
ctx.scale(dpr, dpr);`)
|
|
||||||
/*
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(view.canvasWidth(), 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(`;
|
|
||||||
ctx.canvas.height = dpr * `)
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(view.canvasHeight(), 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(";\nctx.scale(dpr, dpr);")
|
|
||||||
*/
|
|
||||||
return canvas
|
return canvas
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) finishDraw() string {
|
func (canvas *canvasData) finishDraw() {
|
||||||
canvas.script.WriteString("\n")
|
canvas.session.cavnasFinish()
|
||||||
return canvas.script.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) View() CanvasView {
|
func (canvas *canvasData) View() CanvasView {
|
||||||
|
@ -347,162 +329,102 @@ func (canvas *canvasData) Height() float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) Save() {
|
func (canvas *canvasData) Save() {
|
||||||
canvas.script.WriteString("\nctx.save();")
|
canvas.session.callCanvasFunc("save")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) Restore() {
|
func (canvas *canvasData) Restore() {
|
||||||
canvas.script.WriteString("\nctx.restore();")
|
canvas.session.callCanvasFunc("restore")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) ClipRect(x, y, width, height float64) {
|
func (canvas *canvasData) ClipRect(x, y, width, height float64) {
|
||||||
canvas.script.WriteString("\nctx.beginPath();\nctx.rect(")
|
canvas.session.callCanvasFunc("beginPath")
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
canvas.session.callCanvasFunc("rect", x, y, width, height)
|
||||||
canvas.script.WriteRune(',')
|
canvas.session.callCanvasFunc("clip")
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(width, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(height, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");\nctx.clip();")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) ClipPath(path Path) {
|
func (canvas *canvasData) ClipPath(path Path) {
|
||||||
canvas.script.WriteString(path.scriptText())
|
path.create(canvas.session)
|
||||||
canvas.script.WriteString("\nctx.clip();")
|
canvas.session.callCanvasFunc("clip")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetScale(x, y float64) {
|
func (canvas *canvasData) SetScale(x, y float64) {
|
||||||
canvas.script.WriteString("\nctx.scale(")
|
canvas.session.callCanvasFunc("scale", x, y)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetTranslation(x, y float64) {
|
func (canvas *canvasData) SetTranslation(x, y float64) {
|
||||||
canvas.script.WriteString("\nctx.translate(")
|
canvas.session.callCanvasFunc("translate", x, y)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetRotation(angle float64) {
|
func (canvas *canvasData) SetRotation(angle float64) {
|
||||||
canvas.script.WriteString("\nctx.rotate(")
|
canvas.session.callCanvasFunc("rotate", angle)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(angle, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetTransformation(xScale, yScale, xSkew, ySkew, dx, dy float64) {
|
func (canvas *canvasData) SetTransformation(xScale, yScale, xSkew, ySkew, dx, dy float64) {
|
||||||
canvas.script.WriteString("\nctx.transform(")
|
canvas.session.callCanvasFunc("transform", xScale, ySkew, xSkew, yScale, dx, dy)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(xScale, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(ySkew, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(xSkew, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(yScale, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(dx, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(dy, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) ResetTransformation() {
|
func (canvas *canvasData) ResetTransformation() {
|
||||||
canvas.script.WriteString("\nctx.resetTransform();\nctx.scale(dpr, dpr);")
|
canvas.session.callCanvasFunc("resetTransform")
|
||||||
|
canvas.session.callCanvasFunc("scale", canvas.session.PixelRatio(), canvas.session.PixelRatio())
|
||||||
|
//canvas.session.callCanvasFunc("scale", angle)
|
||||||
|
// TODO canvas.script.WriteString("\nctx.resetTransform();\nctx.scale(dpr, dpr);")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetSolidColorFillStyle(color Color) {
|
func (canvas *canvasData) SetSolidColorFillStyle(color Color) {
|
||||||
canvas.script.WriteString("\nctx.fillStyle = \"")
|
canvas.session.updateCanvasProperty("fillStyle", color.cssString())
|
||||||
canvas.script.WriteString(color.cssString())
|
|
||||||
canvas.script.WriteString(`";`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetSolidColorStrokeStyle(color Color) {
|
func (canvas *canvasData) SetSolidColorStrokeStyle(color Color) {
|
||||||
canvas.script.WriteString("\nctx.strokeStyle = \"")
|
canvas.session.updateCanvasProperty("strokeStyle", color.cssString())
|
||||||
canvas.script.WriteString(color.cssString())
|
|
||||||
canvas.script.WriteString(`";`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) setLinearGradient(x0, y0 float64, color0 Color, x1, y1 float64, color1 Color, stopPoints []GradientPoint) {
|
func (canvas *canvasData) createLinearGradient(x0, y0 float64, color0 Color, x1, y1 float64, color1 Color, stopPoints []GradientPoint) any {
|
||||||
canvas.script.WriteString("\ngradient = ctx.createLinearGradient(")
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x0, 'g', -1, 64))
|
gradient := canvas.session.createCanvasVar("createLinearGradient", x0, y0, x1, y1)
|
||||||
canvas.script.WriteRune(',')
|
canvas.session.callCanvasVarFunc(gradient, "addColorStop", 0, color0.cssString())
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y0, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x1, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y1, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");\ngradient.addColorStop(0, '")
|
|
||||||
canvas.script.WriteString(color0.cssString())
|
|
||||||
canvas.script.WriteString("');")
|
|
||||||
|
|
||||||
for _, point := range stopPoints {
|
for _, point := range stopPoints {
|
||||||
if point.Offset >= 0 && point.Offset <= 1 {
|
if point.Offset >= 0 && point.Offset <= 1 {
|
||||||
canvas.script.WriteString("\ngradient.addColorStop(")
|
canvas.session.callCanvasVarFunc(gradient, "addColorStop", point.Offset, point.Color.cssString())
|
||||||
canvas.script.WriteString(strconv.FormatFloat(point.Offset, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(", '")
|
|
||||||
canvas.script.WriteString(point.Color.cssString())
|
|
||||||
canvas.script.WriteString("');")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.script.WriteString("\ngradient.addColorStop(1, '")
|
canvas.session.callCanvasVarFunc(gradient, "addColorStop", 1, color1.cssString())
|
||||||
canvas.script.WriteString(color1.cssString())
|
return gradient
|
||||||
canvas.script.WriteString("');")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetLinearGradientFillStyle(x0, y0 float64, color0 Color, x1, y1 float64, color1 Color, stopPoints []GradientPoint) {
|
func (canvas *canvasData) SetLinearGradientFillStyle(x0, y0 float64, color0 Color, x1, y1 float64, color1 Color, stopPoints []GradientPoint) {
|
||||||
canvas.setLinearGradient(x0, y0, color0, x1, y1, color1, stopPoints)
|
gradient := canvas.createLinearGradient(x0, y0, color0, x1, y1, color1, stopPoints)
|
||||||
canvas.script.WriteString("\nctx.fillStyle = gradient;")
|
canvas.session.updateCanvasProperty("fillStyle", gradient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetLinearGradientStrokeStyle(x0, y0 float64, color0 Color, x1, y1 float64, color1 Color, stopPoints []GradientPoint) {
|
func (canvas *canvasData) SetLinearGradientStrokeStyle(x0, y0 float64, color0 Color, x1, y1 float64, color1 Color, stopPoints []GradientPoint) {
|
||||||
canvas.setLinearGradient(x0, y0, color0, x1, y1, color1, stopPoints)
|
gradient := canvas.createLinearGradient(x0, y0, color0, x1, y1, color1, stopPoints)
|
||||||
canvas.script.WriteString("\nctx.strokeStyle = gradient;")
|
canvas.session.updateCanvasProperty("strokeStyle", gradient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) setRadialGradient(x0, y0, r0 float64, color0 Color, x1, y1, r1 float64, color1 Color, stopPoints []GradientPoint) {
|
func (canvas *canvasData) createRadialGradient(x0, y0, r0 float64, color0 Color, x1, y1, r1 float64, color1 Color, stopPoints []GradientPoint) any {
|
||||||
canvas.script.WriteString("\ngradient = ctx.createRadialGradient(")
|
gradient := canvas.session.createCanvasVar("createRadialGradient", x0, y0, r0, x1, y1, r1)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x0, 'g', -1, 64))
|
canvas.session.callCanvasVarFunc(gradient, "addColorStop", 0, color0.cssString())
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y0, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(r0, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x1, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y1, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(r1, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");\ngradient.addColorStop(0, '")
|
|
||||||
canvas.script.WriteString(color0.cssString())
|
|
||||||
canvas.script.WriteString("');")
|
|
||||||
|
|
||||||
for _, point := range stopPoints {
|
for _, point := range stopPoints {
|
||||||
if point.Offset >= 0 && point.Offset <= 1 {
|
if point.Offset >= 0 && point.Offset <= 1 {
|
||||||
canvas.script.WriteString("\ngradient.addColorStop(")
|
canvas.session.callCanvasVarFunc(gradient, "addColorStop", point.Offset, point.Color.cssString())
|
||||||
canvas.script.WriteString(strconv.FormatFloat(point.Offset, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(", '")
|
|
||||||
canvas.script.WriteString(point.Color.cssString())
|
|
||||||
canvas.script.WriteString("');")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.script.WriteString("\ngradient.addColorStop(1, '")
|
canvas.session.callCanvasVarFunc(gradient, "addColorStop", 1, color1.cssString())
|
||||||
canvas.script.WriteString(color1.cssString())
|
return gradient
|
||||||
canvas.script.WriteString("');")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetRadialGradientFillStyle(x0, y0, r0 float64, color0 Color, x1, y1, r1 float64, color1 Color, stopPoints []GradientPoint) {
|
func (canvas *canvasData) SetRadialGradientFillStyle(x0, y0, r0 float64, color0 Color, x1, y1, r1 float64, color1 Color, stopPoints []GradientPoint) {
|
||||||
canvas.setRadialGradient(x0, y0, r0, color0, x1, y1, r1, color1, stopPoints)
|
gradient := canvas.createRadialGradient(x0, y0, r0, color0, x1, y1, r1, color1, stopPoints)
|
||||||
canvas.script.WriteString("\nctx.fillStyle = gradient;")
|
canvas.session.updateCanvasProperty("fillStyle", gradient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetRadialGradientStrokeStyle(x0, y0, r0 float64, color0 Color, x1, y1, r1 float64, color1 Color, stopPoints []GradientPoint) {
|
func (canvas *canvasData) SetRadialGradientStrokeStyle(x0, y0, r0 float64, color0 Color, x1, y1, r1 float64, color1 Color, stopPoints []GradientPoint) {
|
||||||
canvas.setRadialGradient(x0, y0, r0, color0, x1, y1, r1, color1, stopPoints)
|
gradient := canvas.createRadialGradient(x0, y0, r0, color0, x1, y1, r1, color1, stopPoints)
|
||||||
canvas.script.WriteString("\nctx.strokeStyle = gradient;")
|
canvas.session.updateCanvasProperty("strokeStyle", gradient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetImageFillStyle(image Image, repeat int) {
|
func (canvas *canvasData) SetImageFillStyle(image Image, repeat int) {
|
||||||
|
@ -528,89 +450,70 @@ func (canvas *canvasData) SetImageFillStyle(image Image, repeat int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.script.WriteString("\nimg = images.get('")
|
canvas.session.callCanvasImageFunc(image.URL(), "fillStyle", "createPattern", repeatText)
|
||||||
canvas.script.WriteString(image.URL())
|
|
||||||
canvas.script.WriteString("');\nif (img) {\nctx.fillStyle = ctx.createPattern(img,'")
|
|
||||||
canvas.script.WriteString(repeatText)
|
|
||||||
canvas.script.WriteString("');\n}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetLineWidth(width float64) {
|
func (canvas *canvasData) SetLineWidth(width float64) {
|
||||||
if width > 0 {
|
if width > 0 {
|
||||||
canvas.script.WriteString("\nctx.lineWidth = '")
|
canvas.session.updateCanvasProperty("lineWidth", width)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(width, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString("';")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetLineJoin(join int) {
|
func (canvas *canvasData) SetLineJoin(join int) {
|
||||||
switch join {
|
switch join {
|
||||||
case MiterJoin:
|
case MiterJoin:
|
||||||
canvas.script.WriteString("\nctx.lineJoin = 'miter';")
|
canvas.session.updateCanvasProperty("lineJoin", "miter")
|
||||||
|
|
||||||
case RoundJoin:
|
case RoundJoin:
|
||||||
canvas.script.WriteString("\nctx.lineJoin = 'round';")
|
canvas.session.updateCanvasProperty("lineJoin", "round")
|
||||||
|
|
||||||
case BevelJoin:
|
case BevelJoin:
|
||||||
canvas.script.WriteString("\nctx.lineJoin = 'bevel';")
|
canvas.session.updateCanvasProperty("lineJoin", "bevel")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetLineCap(cap int) {
|
func (canvas *canvasData) SetLineCap(cap int) {
|
||||||
switch cap {
|
switch cap {
|
||||||
case ButtCap:
|
case ButtCap:
|
||||||
canvas.script.WriteString("\nctx.lineCap = 'butt';")
|
canvas.session.updateCanvasProperty("lineCap", "butt")
|
||||||
|
|
||||||
case RoundCap:
|
case RoundCap:
|
||||||
canvas.script.WriteString("\nctx.lineCap = 'round';")
|
canvas.session.updateCanvasProperty("lineCap", "round")
|
||||||
|
|
||||||
case SquareCap:
|
case SquareCap:
|
||||||
canvas.script.WriteString("\nctx.lineCap = 'square';")
|
canvas.session.updateCanvasProperty("lineCap", "square")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetLineDash(dash []float64, offset float64) {
|
func (canvas *canvasData) SetLineDash(dash []float64, offset float64) {
|
||||||
canvas.script.WriteString("\nctx.setLineDash([")
|
canvas.session.callCanvasFunc("setLineDash", dash)
|
||||||
for i, d := range dash {
|
|
||||||
if i > 0 {
|
|
||||||
canvas.script.WriteString(",")
|
|
||||||
}
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(d, 'g', -1, 64))
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.script.WriteString("]);")
|
|
||||||
if offset >= 0 {
|
if offset >= 0 {
|
||||||
canvas.script.WriteString("\nctx.lineDashOffset = '")
|
canvas.session.updateCanvasProperty("lineDashOffset", offset)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(offset, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString("';")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) writeFont(name string, script *strings.Builder) {
|
/*
|
||||||
names := strings.Split(name, ",")
|
func (canvas *canvasData) convertFont(name string) string {
|
||||||
lead := " "
|
buffer := allocStringBuilder()
|
||||||
for _, font := range names {
|
defer freeStringBuilder(buffer)
|
||||||
font = strings.Trim(font, " \n\"'")
|
|
||||||
script.WriteString(lead)
|
for i, font := range strings.Split(name, ",") {
|
||||||
lead = ","
|
font = strings.Trim(font, " \n\"'")
|
||||||
if strings.Contains(font, " ") {
|
if i > 0 {
|
||||||
script.WriteRune('"')
|
buffer.WriteRune(',')
|
||||||
script.WriteString(font)
|
}
|
||||||
script.WriteRune('"')
|
if strings.Contains(font, " ") {
|
||||||
} else {
|
buffer.WriteRune('"')
|
||||||
script.WriteString(font)
|
buffer.WriteString(font)
|
||||||
|
buffer.WriteRune('"')
|
||||||
|
} else {
|
||||||
|
buffer.WriteString(font)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return buffer.String()
|
||||||
}
|
}
|
||||||
script.WriteString("';")
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
func (canvas *canvasData) SetFont(name string, size SizeUnit) {
|
|
||||||
canvas.script.WriteString("\nctx.font = '")
|
|
||||||
canvas.script.WriteString(size.cssString("1rem", canvas.View().Session()))
|
|
||||||
canvas.writeFont(name, &canvas.script)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (canvas *canvasData) fontWithParams(name string, size SizeUnit, params FontParams) string {
|
func (canvas *canvasData) fontWithParams(name string, size SizeUnit, params FontParams) string {
|
||||||
buffer := allocStringBuilder()
|
buffer := allocStringBuilder()
|
||||||
defer freeStringBuilder(buffer)
|
defer freeStringBuilder(buffer)
|
||||||
|
@ -672,135 +575,76 @@ func (canvas *canvasData) fontWithParams(name string, size SizeUnit, params Font
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) setFontWithParams(name string, size SizeUnit, params FontParams, script *strings.Builder) {
|
func (canvas *canvasData) SetFont(name string, size SizeUnit) {
|
||||||
script.WriteString("\nctx.font = '")
|
canvas.session.updateCanvasProperty("font", canvas.fontWithParams(name, size, FontParams{}))
|
||||||
if params.Italic {
|
|
||||||
script.WriteString("italic ")
|
|
||||||
}
|
|
||||||
if params.SmallCaps {
|
|
||||||
script.WriteString("small-caps ")
|
|
||||||
}
|
|
||||||
if params.Weight > 0 && params.Weight <= 9 {
|
|
||||||
switch params.Weight {
|
|
||||||
case 4:
|
|
||||||
script.WriteString("normal ")
|
|
||||||
case 7:
|
|
||||||
script.WriteString("bold ")
|
|
||||||
default:
|
|
||||||
script.WriteString(strconv.Itoa(params.Weight * 100))
|
|
||||||
script.WriteRune(' ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
script.WriteString(size.cssString("1rem", canvas.View().Session()))
|
|
||||||
switch params.LineHeight.Type {
|
|
||||||
case Auto:
|
|
||||||
|
|
||||||
case SizeInPercent:
|
|
||||||
if params.LineHeight.Value != 100 {
|
|
||||||
script.WriteString("/")
|
|
||||||
script.WriteString(strconv.FormatFloat(params.LineHeight.Value/100, 'g', -1, 64))
|
|
||||||
}
|
|
||||||
|
|
||||||
case SizeInFraction:
|
|
||||||
if params.LineHeight.Value != 1 {
|
|
||||||
script.WriteString("/")
|
|
||||||
script.WriteString(strconv.FormatFloat(params.LineHeight.Value, 'g', -1, 64))
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
script.WriteString("/")
|
|
||||||
script.WriteString(params.LineHeight.cssString("", canvas.View().Session()))
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.writeFont(name, script)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetFontWithParams(name string, size SizeUnit, params FontParams) {
|
func (canvas *canvasData) SetFontWithParams(name string, size SizeUnit, params FontParams) {
|
||||||
canvas.setFontWithParams(name, size, params, &canvas.script)
|
canvas.session.updateCanvasProperty("font", canvas.fontWithParams(name, size, params))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) TextMetrics(text string, fontName string, fontSize SizeUnit, fontParams FontParams) TextMetrics {
|
func (canvas *canvasData) TextMetrics(text string, fontName string, fontSize SizeUnit, fontParams FontParams) TextMetrics {
|
||||||
view := canvas.View()
|
return canvas.session.canvasTextMetrics(canvas.view.htmlID(), canvas.fontWithParams(fontName, fontSize, fontParams), text)
|
||||||
return view.Session().canvasTextMetrics(view.htmlID(), canvas.fontWithParams(fontName, fontSize, fontParams), text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetTextBaseline(baseline int) {
|
func (canvas *canvasData) SetTextBaseline(baseline int) {
|
||||||
switch baseline {
|
switch baseline {
|
||||||
case AlphabeticBaseline:
|
case AlphabeticBaseline:
|
||||||
canvas.script.WriteString("\nctx.textBaseline = 'alphabetic';")
|
canvas.session.updateCanvasProperty("textBaseline", "alphabetic")
|
||||||
case TopBaseline:
|
case TopBaseline:
|
||||||
canvas.script.WriteString("\nctx.textBaseline = 'top';")
|
canvas.session.updateCanvasProperty("textBaseline", "top")
|
||||||
case MiddleBaseline:
|
case MiddleBaseline:
|
||||||
canvas.script.WriteString("\nctx.textBaseline = 'middle';")
|
canvas.session.updateCanvasProperty("textBaseline", "middle")
|
||||||
case BottomBaseline:
|
case BottomBaseline:
|
||||||
canvas.script.WriteString("\nctx.textBaseline = 'bottom';")
|
canvas.session.updateCanvasProperty("textBaseline", "bottom")
|
||||||
case HangingBaseline:
|
case HangingBaseline:
|
||||||
canvas.script.WriteString("\nctx.textBaseline = 'hanging';")
|
canvas.session.updateCanvasProperty("textBaseline", "hanging")
|
||||||
case IdeographicBaseline:
|
case IdeographicBaseline:
|
||||||
canvas.script.WriteString("\nctx.textBaseline = 'ideographic';")
|
canvas.session.updateCanvasProperty("textBaseline", "ideographic")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetTextAlign(align int) {
|
func (canvas *canvasData) SetTextAlign(align int) {
|
||||||
switch align {
|
switch align {
|
||||||
case LeftAlign:
|
case LeftAlign:
|
||||||
canvas.script.WriteString("\nctx.textAlign = 'left';")
|
canvas.session.updateCanvasProperty("textAlign", "left")
|
||||||
case RightAlign:
|
case RightAlign:
|
||||||
canvas.script.WriteString("\nctx.textAlign = 'right';")
|
canvas.session.updateCanvasProperty("textAlign", "right")
|
||||||
case CenterAlign:
|
case CenterAlign:
|
||||||
canvas.script.WriteString("\nctx.textAlign = 'center';")
|
canvas.session.updateCanvasProperty("textAlign", "center")
|
||||||
case StartAlign:
|
case StartAlign:
|
||||||
canvas.script.WriteString("\nctx.textAlign = 'start';")
|
canvas.session.updateCanvasProperty("textAlign", "start")
|
||||||
case EndAlign:
|
case EndAlign:
|
||||||
canvas.script.WriteString("\nctx.textAlign = 'end';")
|
canvas.session.updateCanvasProperty("textAlign", "end")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) SetShadow(offsetX, offsetY, blur float64, color Color) {
|
func (canvas *canvasData) SetShadow(offsetX, offsetY, blur float64, color Color) {
|
||||||
if color.Alpha() > 0 && blur >= 0 {
|
if color.Alpha() > 0 && blur >= 0 {
|
||||||
canvas.script.WriteString("\nctx.shadowColor = '")
|
canvas.session.updateCanvasProperty("shadowColor", color.cssString())
|
||||||
canvas.script.WriteString(color.cssString())
|
canvas.session.updateCanvasProperty("shadowOffsetX", offsetX)
|
||||||
canvas.script.WriteString("';\nctx.shadowOffsetX = ")
|
canvas.session.updateCanvasProperty("shadowOffsetY", offsetY)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(offsetX, 'g', -1, 64))
|
canvas.session.updateCanvasProperty("shadowBlur", blur)
|
||||||
canvas.script.WriteString(";\nctx.shadowOffsetY = ")
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(offsetY, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(";\nctx.shadowBlur = ")
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(blur, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(";")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) ResetShadow() {
|
func (canvas *canvasData) ResetShadow() {
|
||||||
canvas.script.WriteString("\nctx.shadowColor = 'rgba(0,0,0,0)';\nctx.shadowOffsetX = 0;\nctx.shadowOffsetY = 0;\nctx.shadowBlur = 0;")
|
canvas.session.updateCanvasProperty("shadowColor", "rgba(0,0,0,0)")
|
||||||
}
|
canvas.session.updateCanvasProperty("shadowOffsetX", 0)
|
||||||
|
canvas.session.updateCanvasProperty("shadowOffsetY", 0)
|
||||||
func (canvas *canvasData) writeRectArgs(x, y, width, height float64) {
|
canvas.session.updateCanvasProperty("shadowBlur", 0)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(width, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(height, 'g', -1, 64))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) ClearRect(x, y, width, height float64) {
|
func (canvas *canvasData) ClearRect(x, y, width, height float64) {
|
||||||
canvas.script.WriteString("\nctx.clearRect(")
|
canvas.session.callCanvasFunc("clearRect", x, y, width, height)
|
||||||
canvas.writeRectArgs(x, y, width, height)
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) FillRect(x, y, width, height float64) {
|
func (canvas *canvasData) FillRect(x, y, width, height float64) {
|
||||||
canvas.script.WriteString("\nctx.fillRect(")
|
canvas.session.callCanvasFunc("fillRect", x, y, width, height)
|
||||||
canvas.writeRectArgs(x, y, width, height)
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) StrokeRect(x, y, width, height float64) {
|
func (canvas *canvasData) StrokeRect(x, y, width, height float64) {
|
||||||
canvas.script.WriteString("\nctx.strokeRect(")
|
canvas.session.callCanvasFunc("strokeRect", x, y, width, height)
|
||||||
canvas.writeRectArgs(x, y, width, height)
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) FillAndStrokeRect(x, y, width, height float64) {
|
func (canvas *canvasData) FillAndStrokeRect(x, y, width, height float64) {
|
||||||
|
@ -808,7 +652,7 @@ func (canvas *canvasData) FillAndStrokeRect(x, y, width, height float64) {
|
||||||
canvas.StrokeRect(x, y, width, height)
|
canvas.StrokeRect(x, y, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) writeRoundedRect(x, y, width, height, r float64) {
|
func (canvas *canvasData) createRoundedRect(x, y, width, height, r float64) {
|
||||||
left := strconv.FormatFloat(x, 'g', -1, 64)
|
left := strconv.FormatFloat(x, 'g', -1, 64)
|
||||||
top := strconv.FormatFloat(y, 'g', -1, 64)
|
top := strconv.FormatFloat(y, 'g', -1, 64)
|
||||||
right := strconv.FormatFloat(x+width, 'g', -1, 64)
|
right := strconv.FormatFloat(x+width, 'g', -1, 64)
|
||||||
|
@ -818,104 +662,65 @@ func (canvas *canvasData) writeRoundedRect(x, y, width, height, r float64) {
|
||||||
rightR := strconv.FormatFloat(x+width-r, 'g', -1, 64)
|
rightR := strconv.FormatFloat(x+width-r, 'g', -1, 64)
|
||||||
bottomR := strconv.FormatFloat(y+height-r, 'g', -1, 64)
|
bottomR := strconv.FormatFloat(y+height-r, 'g', -1, 64)
|
||||||
radius := strconv.FormatFloat(r, 'g', -1, 64)
|
radius := strconv.FormatFloat(r, 'g', -1, 64)
|
||||||
canvas.script.WriteString("\nctx.beginPath();\nctx.moveTo(")
|
|
||||||
canvas.script.WriteString(left)
|
canvas.session.callCanvasFunc("beginPath")
|
||||||
canvas.script.WriteRune(',')
|
canvas.session.callCanvasFunc("moveTo", left, topR)
|
||||||
canvas.script.WriteString(topR)
|
canvas.session.callCanvasFunc("arc", leftR, topR, radius, math.Pi, math.Pi*3/2)
|
||||||
canvas.script.WriteString(");\nctx.arc(")
|
canvas.session.callCanvasFunc("lineTo", rightR, top)
|
||||||
canvas.script.WriteString(leftR)
|
canvas.session.callCanvasFunc("arc", rightR, topR, radius, math.Pi*3/2, math.Pi*2)
|
||||||
canvas.script.WriteRune(',')
|
canvas.session.callCanvasFunc("lineTo", right, bottomR)
|
||||||
canvas.script.WriteString(topR)
|
canvas.session.callCanvasFunc("arc", rightR, bottomR, radius, 0, math.Pi/2)
|
||||||
canvas.script.WriteRune(',')
|
canvas.session.callCanvasFunc("lineTo", leftR, bottom)
|
||||||
canvas.script.WriteString(radius)
|
canvas.session.callCanvasFunc("arc", leftR, bottomR, radius, math.Pi/2, math.Pi)
|
||||||
canvas.script.WriteString(",Math.PI,Math.PI*3/2);\nctx.lineTo(")
|
canvas.session.callCanvasFunc("closePath")
|
||||||
canvas.script.WriteString(rightR)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(top)
|
|
||||||
canvas.script.WriteString(");\nctx.arc(")
|
|
||||||
canvas.script.WriteString(rightR)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(topR)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(radius)
|
|
||||||
canvas.script.WriteString(",Math.PI*3/2,Math.PI*2);\nctx.lineTo(")
|
|
||||||
canvas.script.WriteString(right)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(bottomR)
|
|
||||||
canvas.script.WriteString(");\nctx.arc(")
|
|
||||||
canvas.script.WriteString(rightR)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(bottomR)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(radius)
|
|
||||||
canvas.script.WriteString(",0,Math.PI/2);\nctx.lineTo(")
|
|
||||||
canvas.script.WriteString(leftR)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(bottom)
|
|
||||||
canvas.script.WriteString(");\nctx.arc(")
|
|
||||||
canvas.script.WriteString(leftR)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(bottomR)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(radius)
|
|
||||||
canvas.script.WriteString(",Math.PI/2,Math.PI);\nctx.closePath();")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) FillRoundedRect(x, y, width, height, r float64) {
|
func (canvas *canvasData) FillRoundedRect(x, y, width, height, r float64) {
|
||||||
canvas.writeRoundedRect(x, y, width, height, r)
|
canvas.createRoundedRect(x, y, width, height, r)
|
||||||
canvas.script.WriteString("\nctx.fill();")
|
canvas.session.callCanvasFunc("fill")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) StrokeRoundedRect(x, y, width, height, r float64) {
|
func (canvas *canvasData) StrokeRoundedRect(x, y, width, height, r float64) {
|
||||||
canvas.writeRoundedRect(x, y, width, height, r)
|
canvas.createRoundedRect(x, y, width, height, r)
|
||||||
canvas.script.WriteString("\nctx.stroke();")
|
canvas.session.callCanvasFunc("stroke")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) FillAndStrokeRoundedRect(x, y, width, height, r float64) {
|
func (canvas *canvasData) FillAndStrokeRoundedRect(x, y, width, height, r float64) {
|
||||||
canvas.writeRoundedRect(x, y, width, height, r)
|
canvas.createRoundedRect(x, y, width, height, r)
|
||||||
canvas.script.WriteString("\nctx.fill();\nctx.stroke();")
|
canvas.session.callCanvasFunc("fill")
|
||||||
|
canvas.session.callCanvasFunc("stroke")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) writeEllipse(x, y, radiusX, radiusY, rotation float64) {
|
func (canvas *canvasData) createEllipse(x, y, radiusX, radiusY, rotation float64) {
|
||||||
yText := strconv.FormatFloat(y, 'g', -1, 64)
|
canvas.session.callCanvasFunc("beginPath")
|
||||||
canvas.script.WriteString("\nctx.beginPath();\nctx.moveTo(")
|
canvas.session.callCanvasFunc("moveTo", x+radiusX, y)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x+radiusX, 'g', -1, 64))
|
canvas.session.callCanvasFunc("ellipse", x, y, radiusX, radiusY, rotation, 0, math.Pi*2)
|
||||||
canvas.script.WriteRune(',')
|
//canvas.session.callCanvasFunc("closePath")
|
||||||
canvas.script.WriteString(yText)
|
|
||||||
canvas.script.WriteString(");\nctx.ellipse(")
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(yText)
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(radiusX, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(radiusY, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(rotation, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(",0,Math.PI*2);")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) FillEllipse(x, y, radiusX, radiusY, rotation float64) {
|
func (canvas *canvasData) FillEllipse(x, y, radiusX, radiusY, rotation float64) {
|
||||||
if radiusX >= 0 && radiusY >= 0 {
|
if radiusX >= 0 && radiusY >= 0 {
|
||||||
canvas.writeEllipse(x, y, radiusX, radiusY, rotation)
|
canvas.createEllipse(x, y, radiusX, radiusY, rotation)
|
||||||
canvas.script.WriteString("\nctx.fill();")
|
canvas.session.callCanvasFunc("fill")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) StrokeEllipse(x, y, radiusX, radiusY, rotation float64) {
|
func (canvas *canvasData) StrokeEllipse(x, y, radiusX, radiusY, rotation float64) {
|
||||||
if radiusX >= 0 && radiusY >= 0 {
|
if radiusX >= 0 && radiusY >= 0 {
|
||||||
canvas.writeEllipse(x, y, radiusX, radiusY, rotation)
|
canvas.createEllipse(x, y, radiusX, radiusY, rotation)
|
||||||
canvas.script.WriteString("\nctx.stroke();")
|
canvas.session.callCanvasFunc("stroke")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) FillAndStrokeEllipse(x, y, radiusX, radiusY, rotation float64) {
|
func (canvas *canvasData) FillAndStrokeEllipse(x, y, radiusX, radiusY, rotation float64) {
|
||||||
if radiusX >= 0 && radiusY >= 0 {
|
if radiusX >= 0 && radiusY >= 0 {
|
||||||
canvas.writeEllipse(x, y, radiusX, radiusY, rotation)
|
canvas.createEllipse(x, y, radiusX, radiusY, rotation)
|
||||||
canvas.script.WriteString("\nctx.fill();\nctx.stroke();")
|
canvas.session.callCanvasFunc("fill")
|
||||||
|
canvas.session.callCanvasFunc("stroke")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func (canvas *canvasData) writePointArgs(x, y float64) {
|
func (canvas *canvasData) writePointArgs(x, y float64) {
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
||||||
canvas.script.WriteRune(',')
|
canvas.script.WriteRune(',')
|
||||||
|
@ -947,101 +752,59 @@ func (canvas *canvasData) writeStringArgs(text string, script *strings.Builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func (canvas *canvasData) FillText(x, y float64, text string) {
|
func (canvas *canvasData) FillText(x, y float64, text string) {
|
||||||
canvas.script.WriteString("\nctx.fillText('")
|
canvas.session.callCanvasFunc("fillText", text, x, y)
|
||||||
canvas.writeStringArgs(text, &canvas.script)
|
|
||||||
canvas.script.WriteString(`',`)
|
|
||||||
canvas.writePointArgs(x, y)
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) StrokeText(x, y float64, text string) {
|
func (canvas *canvasData) StrokeText(x, y float64, text string) {
|
||||||
canvas.script.WriteString("\nctx.strokeText('")
|
canvas.session.callCanvasFunc("strokeText", text, x, y)
|
||||||
canvas.writeStringArgs(text, &canvas.script)
|
|
||||||
canvas.script.WriteString(`',`)
|
|
||||||
canvas.writePointArgs(x, y)
|
|
||||||
canvas.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) FillPath(path Path) {
|
func (canvas *canvasData) FillPath(path Path) {
|
||||||
canvas.script.WriteString(path.scriptText())
|
path.create(canvas.session)
|
||||||
canvas.script.WriteString("\nctx.fill();")
|
canvas.session.callCanvasFunc("fill")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) StrokePath(path Path) {
|
func (canvas *canvasData) StrokePath(path Path) {
|
||||||
canvas.script.WriteString(path.scriptText())
|
path.create(canvas.session)
|
||||||
canvas.script.WriteString("\nctx.stroke();")
|
canvas.session.callCanvasFunc("stroke")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) FillAndStrokePath(path Path) {
|
func (canvas *canvasData) FillAndStrokePath(path Path) {
|
||||||
canvas.script.WriteString(path.scriptText())
|
path.create(canvas.session)
|
||||||
canvas.script.WriteString("\nctx.fill();\nctx.stroke();")
|
canvas.session.callCanvasFunc("fill")
|
||||||
|
canvas.session.callCanvasFunc("stroke")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) DrawLine(x0, y0, x1, y1 float64) {
|
func (canvas *canvasData) DrawLine(x0, y0, x1, y1 float64) {
|
||||||
canvas.script.WriteString("\nctx.beginPath();\nctx.moveTo(")
|
canvas.session.callCanvasFunc("beginPath")
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x0, 'g', -1, 64))
|
canvas.session.callCanvasFunc("moveTo", x0, y0)
|
||||||
canvas.script.WriteRune(',')
|
canvas.session.callCanvasFunc("lineTo", x1, y1)
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y0, 'g', -1, 64))
|
canvas.session.callCanvasFunc("stroke")
|
||||||
canvas.script.WriteString(");\nctx.lineTo(")
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x1, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y1, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");\nctx.stroke();")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) DrawImage(x, y float64, image Image) {
|
func (canvas *canvasData) DrawImage(x, y float64, image Image) {
|
||||||
if image == nil || image.LoadingStatus() != ImageReady {
|
if image == nil || image.LoadingStatus() != ImageReady {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
canvas.script.WriteString("\nimg = images.get('")
|
|
||||||
canvas.script.WriteString(image.URL())
|
canvas.session.callCanvasImageFunc(image.URL(), "", "drawImage", x, y)
|
||||||
canvas.script.WriteString("');\nif (img) {\nctx.drawImage(img,")
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");\n}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) DrawImageInRect(x, y, width, height float64, image Image) {
|
func (canvas *canvasData) DrawImageInRect(x, y, width, height float64, image Image) {
|
||||||
if image == nil || image.LoadingStatus() != ImageReady {
|
if image == nil || image.LoadingStatus() != ImageReady {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
canvas.script.WriteString("\nimg = images.get('")
|
|
||||||
canvas.script.WriteString(image.URL())
|
canvas.session.callCanvasImageFunc(image.URL(), "", "drawImage", x, y, width, height)
|
||||||
canvas.script.WriteString("');\nif (img) {\nctx.drawImage(img,")
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(width, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(height, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");\n}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (canvas *canvasData) DrawImageFragment(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight float64, image Image) {
|
func (canvas *canvasData) DrawImageFragment(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight float64, image Image) {
|
||||||
if image == nil || image.LoadingStatus() != ImageReady {
|
if image == nil || image.LoadingStatus() != ImageReady {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
canvas.script.WriteString("\nimg = images.get('")
|
|
||||||
canvas.script.WriteString(image.URL())
|
canvas.session.callCanvasImageFunc(image.URL(), "", "drawImage", srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight)
|
||||||
canvas.script.WriteString("');\nif (img) {\nctx.drawImage(img,")
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(srcX, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(srcY, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(srcWidth, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(srcHeight, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(dstX, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(dstY, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(dstWidth, 'g', -1, 64))
|
|
||||||
canvas.script.WriteRune(',')
|
|
||||||
canvas.script.WriteString(strconv.FormatFloat(dstHeight, 'g', -1, 64))
|
|
||||||
canvas.script.WriteString(");\n}")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ func (canvasView *canvasViewData) Redraw() {
|
||||||
if canvasView.drawer != nil {
|
if canvasView.drawer != nil {
|
||||||
canvasView.drawer(canvas)
|
canvasView.drawer(canvas)
|
||||||
}
|
}
|
||||||
canvasView.session.runScript(canvas.finishDraw())
|
canvas.finishDraw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
63
imageView.go
63
imageView.go
|
@ -1,7 +1,10 @@
|
||||||
package rui
|
package rui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -129,12 +132,10 @@ func (imageView *imageViewData) set(tag string, value any) bool {
|
||||||
if text, ok := value.(string); ok {
|
if text, ok := value.(string); ok {
|
||||||
imageView.properties[Source] = text
|
imageView.properties[Source] = text
|
||||||
if imageView.created {
|
if imageView.created {
|
||||||
src := text
|
src, srcset := imageView.src(text)
|
||||||
if src != "" && src[0] == '@' {
|
|
||||||
src, _ = imageProperty(imageView, Source, imageView.session)
|
|
||||||
}
|
|
||||||
imageView.session.updateProperty(imageView.htmlID(), "src", src)
|
imageView.session.updateProperty(imageView.htmlID(), "src", src)
|
||||||
if srcset := imageView.srcSet(src); srcset != "" {
|
|
||||||
|
if srcset != "" {
|
||||||
imageView.session.updateProperty(imageView.htmlID(), "srcset", srcset)
|
imageView.session.updateProperty(imageView.htmlID(), "srcset", srcset)
|
||||||
} else {
|
} else {
|
||||||
imageView.session.removeProperty(imageView.htmlID(), "srcset")
|
imageView.session.removeProperty(imageView.htmlID(), "srcset")
|
||||||
|
@ -214,29 +215,51 @@ func (imageView *imageViewData) htmlTag() string {
|
||||||
return "img"
|
return "img"
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func (imageView *imageViewData) src(src string) (string, string) {
|
||||||
func (imageView *imageViewData) closeHTMLTag() bool {
|
if src != "" && src[0] == '@' {
|
||||||
return false
|
if image, ok := imageView.Session().ImageConstant(src[1:]); ok {
|
||||||
|
src = image
|
||||||
|
} else {
|
||||||
|
src = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if src != "" {
|
||||||
|
srcset := imageView.srcSet(src)
|
||||||
|
if runtime.GOOS == "js" {
|
||||||
|
if image, ok := resources.images[src]; ok && image.fs != nil {
|
||||||
|
dataType := map[string]string{
|
||||||
|
".svg": "data:image/svg+xml",
|
||||||
|
".png": "data:image/png",
|
||||||
|
".jpg": "data:image/jpg",
|
||||||
|
".jpeg": "data:image/jpg",
|
||||||
|
".gif": "data:image/gif",
|
||||||
|
}
|
||||||
|
ext := strings.ToLower(filepath.Ext(src))
|
||||||
|
if prefix, ok := dataType[ext]; ok {
|
||||||
|
if data, err := image.fs.ReadFile(image.path); err == nil {
|
||||||
|
return prefix + ";base64," + base64.StdEncoding.EncodeToString(data), ""
|
||||||
|
} else {
|
||||||
|
DebugLog(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return src, srcset
|
||||||
|
}
|
||||||
|
return "", ""
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
func (imageView *imageViewData) htmlProperties(self View, buffer *strings.Builder) {
|
func (imageView *imageViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||||
|
|
||||||
imageView.viewData.htmlProperties(self, buffer)
|
imageView.viewData.htmlProperties(self, buffer)
|
||||||
|
|
||||||
if imageResource, ok := imageProperty(imageView, Source, imageView.Session()); ok && imageResource != "" {
|
if imageResource, ok := imageProperty(imageView, Source, imageView.Session()); ok && imageResource != "" {
|
||||||
if imageResource[0] == '@' {
|
if src, srcset := imageView.src(imageResource); src != "" {
|
||||||
if image, ok := imageView.Session().ImageConstant(imageResource[1:]); ok {
|
|
||||||
imageResource = image
|
|
||||||
} else {
|
|
||||||
imageResource = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if imageResource != "" {
|
|
||||||
buffer.WriteString(` src="`)
|
buffer.WriteString(` src="`)
|
||||||
buffer.WriteString(imageResource)
|
buffer.WriteString(src)
|
||||||
buffer.WriteString(`"`)
|
buffer.WriteString(`"`)
|
||||||
if srcset := imageView.srcSet(imageResource); srcset != "" {
|
if srcset != "" {
|
||||||
buffer.WriteString(` srcset="`)
|
buffer.WriteString(` srcset="`)
|
||||||
buffer.WriteString(srcset)
|
buffer.WriteString(srcset)
|
||||||
buffer.WriteString(`"`)
|
buffer.WriteString(`"`)
|
||||||
|
|
110
path.go
110
path.go
|
@ -1,10 +1,5 @@
|
||||||
package rui
|
package rui
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Path is a path interface
|
// Path is a path interface
|
||||||
type Path interface {
|
type Path interface {
|
||||||
// Reset erases the Path
|
// Reset erases the Path
|
||||||
|
@ -63,134 +58,79 @@ type Path interface {
|
||||||
// If the shape has already been closed or has only one point, this function does nothing.
|
// If the shape has already been closed or has only one point, this function does nothing.
|
||||||
Close()
|
Close()
|
||||||
|
|
||||||
scriptText() string
|
create(session Session)
|
||||||
|
}
|
||||||
|
|
||||||
|
type pathElement struct {
|
||||||
|
funcName string
|
||||||
|
args []any
|
||||||
}
|
}
|
||||||
|
|
||||||
type pathData struct {
|
type pathData struct {
|
||||||
script strings.Builder
|
elements []pathElement
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPath creates a new empty Path
|
// NewPath creates a new empty Path
|
||||||
func NewPath() Path {
|
func NewPath() Path {
|
||||||
path := new(pathData)
|
path := new(pathData)
|
||||||
path.script.Grow(4096)
|
path.Reset()
|
||||||
path.script.WriteString("\nctx.beginPath();")
|
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) Reset() {
|
func (path *pathData) Reset() {
|
||||||
path.script.Reset()
|
path.elements = []pathElement{
|
||||||
path.script.WriteString("\nctx.beginPath();")
|
pathElement{funcName: "beginPath", args: []any{}},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) MoveTo(x, y float64) {
|
func (path *pathData) MoveTo(x, y float64) {
|
||||||
path.script.WriteString("\nctx.moveTo(")
|
path.elements = append(path.elements, pathElement{funcName: "moveTo", args: []any{x, y}})
|
||||||
path.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
path.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) LineTo(x, y float64) {
|
func (path *pathData) LineTo(x, y float64) {
|
||||||
path.script.WriteString("\nctx.lineTo(")
|
path.elements = append(path.elements, pathElement{funcName: "lineTo", args: []any{x, y}})
|
||||||
path.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
path.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) ArcTo(x0, y0, x1, y1, radius float64) {
|
func (path *pathData) ArcTo(x0, y0, x1, y1, radius float64) {
|
||||||
if radius > 0 {
|
if radius > 0 {
|
||||||
path.script.WriteString("\nctx.arcTo(")
|
path.elements = append(path.elements, pathElement{funcName: "arcTo", args: []any{x0, y0, x1, y1, radius}})
|
||||||
path.script.WriteString(strconv.FormatFloat(x0, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(y0, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(x1, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(y1, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(radius, 'g', -1, 64))
|
|
||||||
path.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) Arc(x, y, radius, startAngle, endAngle float64, clockwise bool) {
|
func (path *pathData) Arc(x, y, radius, startAngle, endAngle float64, clockwise bool) {
|
||||||
if radius > 0 {
|
if radius > 0 {
|
||||||
path.script.WriteString("\nctx.arc(")
|
|
||||||
path.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(radius, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(startAngle, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(endAngle, 'g', -1, 64))
|
|
||||||
if !clockwise {
|
if !clockwise {
|
||||||
path.script.WriteString(",true);")
|
path.elements = append(path.elements, pathElement{funcName: "arc", args: []any{x, y, radius, startAngle, endAngle, true}})
|
||||||
} else {
|
} else {
|
||||||
path.script.WriteString(");")
|
path.elements = append(path.elements, pathElement{funcName: "arc", args: []any{x, y, radius, startAngle, endAngle}})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) BezierCurveTo(cp0x, cp0y, cp1x, cp1y, x, y float64) {
|
func (path *pathData) BezierCurveTo(cp0x, cp0y, cp1x, cp1y, x, y float64) {
|
||||||
path.script.WriteString("\nctx.bezierCurveTo(")
|
path.elements = append(path.elements, pathElement{funcName: "bezierCurveTo", args: []any{cp0x, cp0y, cp1x, cp1y, x, y}})
|
||||||
path.script.WriteString(strconv.FormatFloat(cp0x, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(cp0y, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(cp1x, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(cp1y, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
path.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) QuadraticCurveTo(cpx, cpy, x, y float64) {
|
func (path *pathData) QuadraticCurveTo(cpx, cpy, x, y float64) {
|
||||||
path.script.WriteString("\nctx.quadraticCurveTo(")
|
path.elements = append(path.elements, pathElement{funcName: "quadraticCurveTo", args: []any{cpx, cpy, x, y}})
|
||||||
path.script.WriteString(strconv.FormatFloat(cpx, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(cpy, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
path.script.WriteString(");")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) Ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle float64, clockwise bool) {
|
func (path *pathData) Ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle float64, clockwise bool) {
|
||||||
if radiusX > 0 && radiusY > 0 {
|
if radiusX > 0 && radiusY > 0 {
|
||||||
path.script.WriteString("\nctx.ellipse(")
|
|
||||||
path.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(radiusX, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(radiusY, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(rotation, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(startAngle, 'g', -1, 64))
|
|
||||||
path.script.WriteRune(',')
|
|
||||||
path.script.WriteString(strconv.FormatFloat(endAngle, 'g', -1, 64))
|
|
||||||
if !clockwise {
|
if !clockwise {
|
||||||
path.script.WriteString(",true);")
|
path.elements = append(path.elements, pathElement{funcName: "ellipse", args: []any{x, y, radiusX, radiusY, rotation, startAngle, endAngle, true}})
|
||||||
} else {
|
} else {
|
||||||
path.script.WriteString(");")
|
path.elements = append(path.elements, pathElement{funcName: "ellipse", args: []any{x, y, radiusX, radiusY, rotation, startAngle, endAngle}})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) Close() {
|
func (path *pathData) Close() {
|
||||||
path.script.WriteString("\nctx.close();")
|
path.elements = append(path.elements, pathElement{funcName: "close", args: []any{}})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (path *pathData) scriptText() string {
|
func (path *pathData) create(session Session) {
|
||||||
return path.script.String()
|
for _, element := range path.elements {
|
||||||
|
session.callCanvasFunc(element.funcName, element.args...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ func scanEmbedImagesDir(fs *embed.FS, dir, prefix string) {
|
||||||
} else {
|
} else {
|
||||||
ext := strings.ToLower(filepath.Ext(name))
|
ext := strings.ToLower(filepath.Ext(name))
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".png", ".jpg", ".jpeg", ".svg":
|
case ".png", ".jpg", ".jpeg", ".svg", ".gif", ".bmp":
|
||||||
registerImage(fs, path, prefix+name)
|
registerImage(fs, path, prefix+name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
57
session.go
57
session.go
|
@ -18,6 +18,13 @@ type webBrige interface {
|
||||||
removeProperty(htmlID, property string)
|
removeProperty(htmlID, property string)
|
||||||
readMessage() (string, bool)
|
readMessage() (string, bool)
|
||||||
writeMessage(text string) bool
|
writeMessage(text string) bool
|
||||||
|
cavnasStart(htmlID string)
|
||||||
|
callCanvasFunc(funcName string, args ...any)
|
||||||
|
callCanvasVarFunc(v any, funcName string, args ...any)
|
||||||
|
callCanvasImageFunc(url string, property string, funcName string, args ...any)
|
||||||
|
createCanvasVar(funcName string, args ...any) any
|
||||||
|
updateCanvasProperty(property string, value any)
|
||||||
|
cavnasFinish()
|
||||||
canvasTextMetrics(htmlID, font, text string) TextMetrics
|
canvasTextMetrics(htmlID, font, text string) TextMetrics
|
||||||
htmlPropertyValue(htmlID, name string) string
|
htmlPropertyValue(htmlID, name string) string
|
||||||
answerReceived(answer DataObject)
|
answerReceived(answer DataObject)
|
||||||
|
@ -115,6 +122,13 @@ type Session interface {
|
||||||
runScript(script string)
|
runScript(script string)
|
||||||
startUpdateScript(htmlID string) bool
|
startUpdateScript(htmlID string) bool
|
||||||
finishUpdateScript(htmlID string)
|
finishUpdateScript(htmlID string)
|
||||||
|
cavnasStart(htmlID string)
|
||||||
|
callCanvasFunc(funcName string, args ...any)
|
||||||
|
createCanvasVar(funcName string, args ...any) any
|
||||||
|
callCanvasVarFunc(v any, funcName string, args ...any)
|
||||||
|
callCanvasImageFunc(url string, property string, funcName string, args ...any)
|
||||||
|
updateCanvasProperty(property string, value any)
|
||||||
|
cavnasFinish()
|
||||||
canvasTextMetrics(htmlID, font, text string) TextMetrics
|
canvasTextMetrics(htmlID, font, text string) TextMetrics
|
||||||
htmlPropertyValue(htmlID, name string) string
|
htmlPropertyValue(htmlID, name string) string
|
||||||
handleAnswer(data DataObject)
|
handleAnswer(data DataObject)
|
||||||
|
@ -395,6 +409,49 @@ func (session *sessionData) finishUpdateScript(htmlID string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) cavnasStart(htmlID string) {
|
||||||
|
if session.brige != nil {
|
||||||
|
session.brige.cavnasStart(htmlID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) callCanvasFunc(funcName string, args ...any) {
|
||||||
|
if session.brige != nil {
|
||||||
|
session.brige.callCanvasFunc(funcName, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) updateCanvasProperty(property string, value any) {
|
||||||
|
if session.brige != nil {
|
||||||
|
session.brige.updateCanvasProperty(property, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) createCanvasVar(funcName string, args ...any) any {
|
||||||
|
if session.brige != nil {
|
||||||
|
return session.brige.createCanvasVar(funcName, args...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) callCanvasVarFunc(v any, funcName string, args ...any) {
|
||||||
|
if session.brige != nil && v != nil {
|
||||||
|
session.brige.callCanvasVarFunc(v, funcName, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) callCanvasImageFunc(url string, property string, funcName string, args ...any) {
|
||||||
|
if session.brige != nil {
|
||||||
|
session.brige.callCanvasImageFunc(url, property, funcName, args...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *sessionData) cavnasFinish() {
|
||||||
|
if session.brige != nil {
|
||||||
|
session.brige.cavnasFinish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (session *sessionData) runScript(script string) {
|
func (session *sessionData) runScript(script string) {
|
||||||
if session.brige != nil {
|
if session.brige != nil {
|
||||||
session.brige.writeMessage(script)
|
session.brige.writeMessage(script)
|
||||||
|
|
139
webBrige.go
139
webBrige.go
|
@ -13,13 +13,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type wsBrige struct {
|
type wsBrige struct {
|
||||||
conn *websocket.Conn
|
conn *websocket.Conn
|
||||||
answer map[int]chan DataObject
|
answer map[int]chan DataObject
|
||||||
answerID int
|
answerID int
|
||||||
answerMutex sync.Mutex
|
answerMutex sync.Mutex
|
||||||
closed bool
|
closed bool
|
||||||
buffer strings.Builder
|
buffer strings.Builder
|
||||||
updateScripts map[string]*strings.Builder
|
canvasBuffer strings.Builder
|
||||||
|
canvasVarNumber int
|
||||||
|
updateScripts map[string]*strings.Builder
|
||||||
|
}
|
||||||
|
|
||||||
|
type canvasVar struct {
|
||||||
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
var upgrader = websocket.Upgrader{
|
||||||
|
@ -119,6 +125,21 @@ func (brige *wsBrige) argToString(arg any) (string, bool) {
|
||||||
case float64:
|
case float64:
|
||||||
return fmt.Sprintf("%g", arg), true
|
return fmt.Sprintf("%g", arg), true
|
||||||
|
|
||||||
|
case []float64:
|
||||||
|
buffer := allocStringBuilder()
|
||||||
|
defer freeStringBuilder(buffer)
|
||||||
|
lead := '['
|
||||||
|
for _, val := range arg {
|
||||||
|
buffer.WriteRune(lead)
|
||||||
|
lead = ','
|
||||||
|
buffer.WriteString(fmt.Sprintf("%g", val))
|
||||||
|
}
|
||||||
|
buffer.WriteRune(']')
|
||||||
|
return buffer.String(), true
|
||||||
|
|
||||||
|
case canvasVar:
|
||||||
|
return arg.name, true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if n, ok := isInt(arg); ok {
|
if n, ok := isInt(arg); ok {
|
||||||
return fmt.Sprintf("%d", n), true
|
return fmt.Sprintf("%d", n), true
|
||||||
|
@ -203,6 +224,110 @@ func (brige *wsBrige) removeProperty(htmlID, property string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (brige *wsBrige) cavnasStart(htmlID string) {
|
||||||
|
brige.canvasBuffer.Reset()
|
||||||
|
brige.canvasBuffer.WriteString(`const ctx = getCanvasContext('`)
|
||||||
|
brige.canvasBuffer.WriteString(htmlID)
|
||||||
|
brige.canvasBuffer.WriteString(`');`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (brige *wsBrige) callCanvasFunc(funcName string, args ...any) {
|
||||||
|
brige.canvasBuffer.WriteString("\nctx.")
|
||||||
|
brige.canvasBuffer.WriteString(funcName)
|
||||||
|
brige.canvasBuffer.WriteRune('(')
|
||||||
|
for i, arg := range args {
|
||||||
|
if i > 0 {
|
||||||
|
brige.canvasBuffer.WriteString(", ")
|
||||||
|
}
|
||||||
|
argText, _ := brige.argToString(arg)
|
||||||
|
brige.canvasBuffer.WriteString(argText)
|
||||||
|
}
|
||||||
|
brige.canvasBuffer.WriteString(");")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (brige *wsBrige) updateCanvasProperty(property string, value any) {
|
||||||
|
brige.canvasBuffer.WriteString("\nctx.")
|
||||||
|
brige.canvasBuffer.WriteString(property)
|
||||||
|
brige.canvasBuffer.WriteString(" = ")
|
||||||
|
argText, _ := brige.argToString(value)
|
||||||
|
brige.canvasBuffer.WriteString(argText)
|
||||||
|
brige.canvasBuffer.WriteString(";")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (brige *wsBrige) createCanvasVar(funcName string, args ...any) any {
|
||||||
|
brige.canvasVarNumber++
|
||||||
|
result := canvasVar{name: fmt.Sprintf("v%d", brige.canvasVarNumber)}
|
||||||
|
brige.canvasBuffer.WriteString("\nvar ")
|
||||||
|
brige.canvasBuffer.WriteString(result.name)
|
||||||
|
brige.canvasBuffer.WriteString(" = ctx.")
|
||||||
|
brige.canvasBuffer.WriteString(funcName)
|
||||||
|
brige.canvasBuffer.WriteRune('(')
|
||||||
|
for i, arg := range args {
|
||||||
|
if i > 0 {
|
||||||
|
brige.canvasBuffer.WriteString(", ")
|
||||||
|
}
|
||||||
|
argText, _ := brige.argToString(arg)
|
||||||
|
brige.canvasBuffer.WriteString(argText)
|
||||||
|
}
|
||||||
|
brige.canvasBuffer.WriteString(");")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (brige *wsBrige) callCanvasVarFunc(v any, funcName string, args ...any) {
|
||||||
|
varName, ok := v.(canvasVar)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
brige.canvasBuffer.WriteString("\n")
|
||||||
|
brige.canvasBuffer.WriteString(varName.name)
|
||||||
|
brige.canvasBuffer.WriteRune('.')
|
||||||
|
brige.canvasBuffer.WriteString(funcName)
|
||||||
|
brige.canvasBuffer.WriteRune('(')
|
||||||
|
for i, arg := range args {
|
||||||
|
if i > 0 {
|
||||||
|
brige.canvasBuffer.WriteString(", ")
|
||||||
|
}
|
||||||
|
argText, _ := brige.argToString(arg)
|
||||||
|
brige.canvasBuffer.WriteString(argText)
|
||||||
|
}
|
||||||
|
brige.canvasBuffer.WriteString(");")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (brige *wsBrige) callCanvasImageFunc(url string, property string, funcName string, args ...any) {
|
||||||
|
|
||||||
|
brige.canvasBuffer.WriteString("\nimg = images.get('")
|
||||||
|
brige.canvasBuffer.WriteString(url)
|
||||||
|
brige.canvasBuffer.WriteString("');\nif (img) {\n")
|
||||||
|
if property != "" {
|
||||||
|
brige.canvasBuffer.WriteString("ctx.")
|
||||||
|
brige.canvasBuffer.WriteString(property)
|
||||||
|
brige.canvasBuffer.WriteString(" = ")
|
||||||
|
}
|
||||||
|
brige.canvasBuffer.WriteString("ctx.")
|
||||||
|
brige.canvasBuffer.WriteString(funcName)
|
||||||
|
brige.canvasBuffer.WriteString("(img")
|
||||||
|
for _, arg := range args {
|
||||||
|
brige.canvasBuffer.WriteString(", ")
|
||||||
|
argText, _ := brige.argToString(arg)
|
||||||
|
brige.canvasBuffer.WriteString(argText)
|
||||||
|
}
|
||||||
|
brige.canvasBuffer.WriteString(");\n}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (brige *wsBrige) cavnasFinish() {
|
||||||
|
brige.canvasBuffer.WriteString("\n")
|
||||||
|
script := brige.canvasBuffer.String()
|
||||||
|
if ProtocolInDebugLog {
|
||||||
|
DebugLog("Run script:")
|
||||||
|
DebugLog(script)
|
||||||
|
}
|
||||||
|
if brige.conn == nil {
|
||||||
|
ErrorLog("No connection")
|
||||||
|
} else if err := brige.conn.WriteMessage(websocket.TextMessage, []byte(script)); err != nil {
|
||||||
|
ErrorLog(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (brige *wsBrige) readMessage() (string, bool) {
|
func (brige *wsBrige) readMessage() (string, bool) {
|
||||||
_, p, err := brige.conn.ReadMessage()
|
_, p, err := brige.conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue