diff --git a/backend/backendbase/base.go b/backend/backendbase/base.go index dbcc77e..cc9f225 100644 --- a/backend/backendbase/base.go +++ b/backend/backendbase/base.go @@ -18,7 +18,7 @@ type Backend interface { LoadRadialGradient(data Gradient) RadialGradient Clear(pts [4]Vec) - Fill(style *FillStyle, pts []Vec, canOverlap bool) + Fill(style *FillStyle, pts []Vec, tf Mat, canOverlap bool) DrawImage(dimg Image, sx, sy, sw, sh float64, pts [4]Vec, alpha float64) FillImageMask(style *FillStyle, mask *image.Alpha, pts [4]Vec) // pts must have four points diff --git a/backend/goglbackend/clip.go b/backend/goglbackend/clip.go index 497b11f..daed7c2 100644 --- a/backend/goglbackend/clip.go +++ b/backend/goglbackend/clip.go @@ -39,6 +39,7 @@ func (b *GoGLBackend) Clip(pts []backendbase.Vec) { gl.UseProgram(b.shd.ID) gl.Uniform4f(b.shd.Color, 1, 1, 1, 1) gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) gl.Uniform1f(b.shd.GlobalAlpha, 1) gl.Uniform1i(b.shd.UseAlphaTex, 0) gl.Uniform1i(b.shd.Func, shdFuncSolid) diff --git a/backend/goglbackend/fill.go b/backend/goglbackend/fill.go index 73ba77d..1b17bed 100644 --- a/backend/goglbackend/fill.go +++ b/backend/goglbackend/fill.go @@ -35,6 +35,7 @@ func (b *GoGLBackend) Clear(pts [4]backendbase.Vec) { gl.UseProgram(b.shd.ID) gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) gl.Uniform4f(b.shd.Color, 0, 0, 0, 0) gl.Uniform1f(b.shd.GlobalAlpha, 1) gl.Uniform1i(b.shd.UseAlphaTex, 0) @@ -85,7 +86,7 @@ func extent(pts []backendbase.Vec) (min, max backendbase.Vec) { return } -func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, canOverlap bool) { +func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, tf backendbase.Mat, canOverlap bool) { b.activate() if style.Blur > 0 { @@ -115,7 +116,7 @@ func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, gl.BufferData(gl.ARRAY_BUFFER, len(b.ptsBuf)*4, unsafe.Pointer(&b.ptsBuf[0]), gl.STREAM_DRAW) if !canOverlap || style.Color.A >= 255 { - vertex, _ := b.useShader(style, false, 0) + vertex, _ := b.useShader(style, mat3(tf), false, 0) gl.StencilFunc(gl.EQUAL, 0, 0xFF) gl.EnableVertexAttribArray(vertex) @@ -132,6 +133,8 @@ func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, gl.UseProgram(b.shd.ID) gl.Uniform4f(b.shd.Color, 0, 0, 0, 0) gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + m3 := mat3(tf) + gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &m3[0]) gl.Uniform1f(b.shd.GlobalAlpha, 1) gl.Uniform1i(b.shd.UseAlphaTex, 0) gl.Uniform1i(b.shd.Func, shdFuncSolid) @@ -145,7 +148,7 @@ func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, gl.StencilFunc(gl.EQUAL, 1, 0xFF) - vertex, _ := b.useShader(style, false, 0) + vertex, _ := b.useShader(style, mat3identity, false, 0) gl.EnableVertexAttribArray(vertex) gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil) @@ -190,7 +193,7 @@ func (b *GoGLBackend) FillImageMask(style *backendbase.FillStyle, mask *image.Al gl.BindBuffer(gl.ARRAY_BUFFER, b.buf) - vertex, alphaTexCoord := b.useShader(style, true, 1) + vertex, alphaTexCoord := b.useShader(style, mat3identity, true, 1) gl.EnableVertexAttribArray(vertex) gl.EnableVertexAttribArray(alphaTexCoord) @@ -267,6 +270,7 @@ func (b *GoGLBackend) drawBlurred(size float64, min, max backendbase.Vec) { gl.UseProgram(b.shd.ID) gl.Uniform1i(b.shd.Image, 0) gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) gl.Uniform1i(b.shd.UseAlphaTex, 0) gl.Uniform1i(b.shd.Func, shdFuncBoxBlur) diff --git a/backend/goglbackend/gogl.go b/backend/goglbackend/gogl.go index 25bb2c2..e6338bd 100644 --- a/backend/goglbackend/gogl.go +++ b/backend/goglbackend/gogl.go @@ -258,9 +258,10 @@ func (b *GoGLBackendOffscreen) AsImage() backendbase.Image { return &b.offscrImg } -func (b *GoGLBackend) useShader(style *backendbase.FillStyle, useAlpha bool, alphaTexSlot int32) (vertexLoc, alphaTexCoordLoc uint32) { +func (b *GoGLBackend) useShader(style *backendbase.FillStyle, tf [9]float32, useAlpha bool, alphaTexSlot int32) (vertexLoc, alphaTexCoordLoc uint32) { gl.UseProgram(b.shd.ID) gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &tf[0]) if useAlpha { gl.Uniform1i(b.shd.UseAlphaTex, 1) gl.Uniform1i(b.shd.AlphaTex, alphaTexSlot) @@ -382,3 +383,18 @@ func (b *GoGLBackend) enableTextureRenderTarget(offscr *offscreenBuffer) { gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) } + +func mat3(m backendbase.Mat) (m3 [9]float32) { + m3[0] = float32(m[0]) + m3[1] = float32(m[1]) + m3[2] = 0 + m3[3] = float32(m[2]) + m3[4] = float32(m[3]) + m3[5] = 0 + m3[6] = float32(m[4]) + m3[7] = float32(m[5]) + m3[8] = 1 + return +} + +var mat3identity = [9]float32{1, 0, 0, 0, 1, 0, 0, 0, 1} diff --git a/backend/goglbackend/imagedata.go b/backend/goglbackend/imagedata.go index cb08b53..2027a05 100644 --- a/backend/goglbackend/imagedata.go +++ b/backend/goglbackend/imagedata.go @@ -88,6 +88,7 @@ func (b *GoGLBackend) PutImageData(img *image.RGBA, x, y int) { gl.UseProgram(b.shd.ID) gl.Uniform1i(b.shd.Image, 0) gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) gl.Uniform1f(b.shd.GlobalAlpha, 1) gl.Uniform1i(b.shd.UseAlphaTex, 0) gl.Uniform1i(b.shd.Func, shdFuncImage) diff --git a/backend/goglbackend/images.go b/backend/goglbackend/images.go index 1e65f59..5199eef 100644 --- a/backend/goglbackend/images.go +++ b/backend/goglbackend/images.go @@ -190,6 +190,7 @@ func (b *GoGLBackend) DrawImage(dimg backendbase.Image, sx, sy, sw, sh float64, gl.UseProgram(b.shd.ID) gl.Uniform1i(b.shd.Image, 0) gl.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + gl.UniformMatrix3fv(b.shd.Matrix, 1, false, &mat3identity[0]) gl.Uniform1f(b.shd.GlobalAlpha, float32(alpha)) gl.Uniform1i(b.shd.UseAlphaTex, 0) gl.Uniform1i(b.shd.Func, shdFuncImage) diff --git a/backend/goglbackend/shaders.go b/backend/goglbackend/shaders.go index ae29d70..3541189 100755 --- a/backend/goglbackend/shaders.go +++ b/backend/goglbackend/shaders.go @@ -4,13 +4,16 @@ var unifiedVS = ` attribute vec2 vertex, texCoord; uniform vec2 canvasSize; +uniform mat3 matrix; varying vec2 v_cp, v_tc; void main() { - v_tc = texCoord; - v_cp = vertex; - vec2 glp = vertex * 2.0 / canvasSize - 1.0; + v_tc = texCoord; + vec3 v = matrix * vec3(vertex.xy, 1.0); + vec2 tf = v.xy / v.z; + v_cp = tf; + vec2 glp = tf * 2.0 / canvasSize - 1.0; gl_Position = vec4(glp.x, -glp.y, 0.0, 1.0); } ` @@ -129,6 +132,7 @@ type unifiedShader struct { TexCoord uint32 CanvasSize int32 + Matrix int32 Color int32 GlobalAlpha int32 diff --git a/backend/softwarebackend/fill.go b/backend/softwarebackend/fill.go index e56f9e8..bc56088 100644 --- a/backend/softwarebackend/fill.go +++ b/backend/softwarebackend/fill.go @@ -19,9 +19,22 @@ func (b *SoftwareBackend) Clear(pts [4]backendbase.Vec) { }) } -func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, canOverlap bool) { +func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, tf backendbase.Mat, canOverlap bool) { ffn := fillFunc(style) + var triBuf [500]backendbase.Vec + if tf != backendbase.MatIdentity { + ptsOld := pts + if len(pts) < len(triBuf) { + pts = triBuf[:len(pts)] + } else { + pts = make([]backendbase.Vec, len(pts)) + } + for i, pt := range ptsOld { + pts[i] = pt.MulMat(tf) + } + } + if style.Blur > 0 { b.activateBlurTarget() b.fillTriangles(pts, ffn) diff --git a/backend/xmobilebackend/clip.go b/backend/xmobilebackend/clip.go index ff39eae..b9d66b0 100755 --- a/backend/xmobilebackend/clip.go +++ b/backend/xmobilebackend/clip.go @@ -39,6 +39,7 @@ func (b *XMobileBackend) Clip(pts []backendbase.Vec) { b.glctx.UseProgram(b.shd.ID) b.glctx.Uniform4f(b.shd.Color, 1, 1, 1, 1) b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + b.glctx.UniformMatrix3fv(b.shd.Matrix, mat3identity[:]) b.glctx.Uniform1f(b.shd.GlobalAlpha, 1) b.glctx.Uniform1i(b.shd.UseAlphaTex, 0) b.glctx.Uniform1i(b.shd.Func, shdFuncSolid) diff --git a/backend/xmobilebackend/fill.go b/backend/xmobilebackend/fill.go index e7fae06..e76646d 100755 --- a/backend/xmobilebackend/fill.go +++ b/backend/xmobilebackend/fill.go @@ -35,6 +35,7 @@ func (b *XMobileBackend) Clear(pts [4]backendbase.Vec) { b.glctx.UseProgram(b.shd.ID) b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + b.glctx.UniformMatrix3fv(b.shd.Matrix, mat3identity[:]) b.glctx.Uniform4f(b.shd.Color, 0, 0, 0, 0) b.glctx.Uniform1f(b.shd.GlobalAlpha, 1) b.glctx.Uniform1i(b.shd.UseAlphaTex, 0) @@ -85,7 +86,7 @@ func extent(pts []backendbase.Vec) (min, max backendbase.Vec) { return } -func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, canOverlap bool) { +func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Vec, tf backendbase.Mat, canOverlap bool) { b.activate() if style.Blur > 0 { @@ -115,7 +116,7 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Ve b.glctx.BufferData(gl.ARRAY_BUFFER, byteSlice(unsafe.Pointer(&b.ptsBuf[0]), len(b.ptsBuf)*4), gl.STREAM_DRAW) if !canOverlap || style.Color.A >= 255 { - vertex, _ := b.useShader(style, false, 0) + vertex, _ := b.useShader(style, mat3(tf), false, 0) b.glctx.StencilFunc(gl.EQUAL, 0, 0xFF) b.glctx.EnableVertexAttribArray(vertex) @@ -132,6 +133,8 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Ve b.glctx.UseProgram(b.shd.ID) b.glctx.Uniform4f(b.shd.Color, 0, 0, 0, 0) b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + m3 := mat3(tf) + b.glctx.UniformMatrix3fv(b.shd.Matrix, m3[:]) b.glctx.Uniform1f(b.shd.GlobalAlpha, 1) b.glctx.Uniform1i(b.shd.UseAlphaTex, 0) b.glctx.Uniform1i(b.shd.Func, shdFuncSolid) @@ -145,7 +148,7 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts []backendbase.Ve b.glctx.StencilFunc(gl.EQUAL, 1, 0xFF) - vertex, _ := b.useShader(style, false, 0) + vertex, _ := b.useShader(style, mat3identity, false, 0) b.glctx.EnableVertexAttribArray(vertex) b.glctx.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, 0) @@ -190,7 +193,7 @@ func (b *XMobileBackend) FillImageMask(style *backendbase.FillStyle, mask *image b.glctx.BindBuffer(gl.ARRAY_BUFFER, b.buf) - vertex, alphaTexCoord := b.useShader(style, true, 1) + vertex, alphaTexCoord := b.useShader(style, mat3identity, true, 1) b.glctx.EnableVertexAttribArray(vertex) b.glctx.EnableVertexAttribArray(alphaTexCoord) @@ -267,6 +270,7 @@ func (b *XMobileBackend) drawBlurred(size float64, min, max backendbase.Vec) { b.glctx.UseProgram(b.shd.ID) b.glctx.Uniform1i(b.shd.Image, 0) b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + b.glctx.UniformMatrix3fv(b.shd.Matrix, mat3identity[:]) b.glctx.Uniform1i(b.shd.UseAlphaTex, 0) b.glctx.Uniform1i(b.shd.Func, shdFuncBoxBlur) diff --git a/backend/xmobilebackend/imagedata.go b/backend/xmobilebackend/imagedata.go index 4e71591..effa4d0 100755 --- a/backend/xmobilebackend/imagedata.go +++ b/backend/xmobilebackend/imagedata.go @@ -88,6 +88,7 @@ func (b *XMobileBackend) PutImageData(img *image.RGBA, x, y int) { b.glctx.UseProgram(b.shd.ID) b.glctx.Uniform1i(b.shd.Image, 0) b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + b.glctx.UniformMatrix3fv(b.shd.Matrix, mat3identity[:]) b.glctx.Uniform1f(b.shd.GlobalAlpha, 1) b.glctx.Uniform1i(b.shd.UseAlphaTex, 0) b.glctx.Uniform1i(b.shd.Func, shdFuncImage) diff --git a/backend/xmobilebackend/images.go b/backend/xmobilebackend/images.go index 816709b..3ad6f55 100755 --- a/backend/xmobilebackend/images.go +++ b/backend/xmobilebackend/images.go @@ -192,6 +192,7 @@ func (b *XMobileBackend) DrawImage(dimg backendbase.Image, sx, sy, sw, sh float6 b.glctx.UseProgram(b.shd.ID) b.glctx.Uniform1i(b.shd.Image, 0) b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + b.glctx.UniformMatrix3fv(b.shd.Matrix, mat3identity[:]) b.glctx.Uniform1f(b.shd.GlobalAlpha, float32(alpha)) b.glctx.Uniform1i(b.shd.UseAlphaTex, 0) b.glctx.Uniform1i(b.shd.Func, shdFuncImage) diff --git a/backend/xmobilebackend/shaders.go b/backend/xmobilebackend/shaders.go index 124eb8f..9fc8795 100755 --- a/backend/xmobilebackend/shaders.go +++ b/backend/xmobilebackend/shaders.go @@ -8,13 +8,16 @@ var unifiedVS = ` attribute vec2 vertex, texCoord; uniform vec2 canvasSize; +uniform mat3 matrix; varying vec2 v_cp, v_tc; void main() { - v_tc = texCoord; - v_cp = vertex; - vec2 glp = vertex * 2.0 / canvasSize - 1.0; + v_tc = texCoord; + vec3 v = matrix * vec3(vertex.xy, 1.0); + vec2 tf = v.xy / v.z; + v_cp = tf; + vec2 glp = tf * 2.0 / canvasSize - 1.0; gl_Position = vec4(glp.x, -glp.y, 0.0, 1.0); } ` @@ -133,6 +136,7 @@ type unifiedShader struct { TexCoord gl.Attrib CanvasSize gl.Uniform + Matrix gl.Uniform Color gl.Uniform GlobalAlpha gl.Uniform diff --git a/backend/xmobilebackend/xmobile.go b/backend/xmobilebackend/xmobile.go index bdcd7c4..07e7350 100755 --- a/backend/xmobilebackend/xmobile.go +++ b/backend/xmobilebackend/xmobile.go @@ -251,9 +251,10 @@ func (b *XMobileBackendOffscreen) AsImage() backendbase.Image { return &b.offscrImg } -func (b *XMobileBackend) useShader(style *backendbase.FillStyle, useAlpha bool, alphaTexSlot int) (vertexLoc, alphaTexCoordLoc gl.Attrib) { +func (b *XMobileBackend) useShader(style *backendbase.FillStyle, tf [9]float32, useAlpha bool, alphaTexSlot int) (vertexLoc, alphaTexCoordLoc gl.Attrib) { b.glctx.UseProgram(b.shd.ID) b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh)) + b.glctx.UniformMatrix3fv(b.shd.Matrix, tf[:]) if useAlpha { b.glctx.Uniform1i(b.shd.UseAlphaTex, 1) b.glctx.Uniform1i(b.shd.AlphaTex, alphaTexSlot) @@ -376,6 +377,21 @@ func (b *XMobileBackend) enableTextureRenderTarget(offscr *offscreenBuffer) { b.glctx.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) } +func mat3(m backendbase.Mat) (m3 [9]float32) { + m3[0] = float32(m[0]) + m3[1] = float32(m[1]) + m3[2] = 0 + m3[3] = float32(m[2]) + m3[4] = float32(m[3]) + m3[5] = 0 + m3[6] = float32(m[4]) + m3[7] = float32(m[5]) + m3[8] = 1 + return +} + +var mat3identity = [9]float32{1, 0, 0, 0, 1, 0, 0, 0, 1} + func byteSlice(ptr unsafe.Pointer, size int) []byte { var buf []byte sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf)) diff --git a/path2d.go b/path2d.go index 3319a01..115704d 100644 --- a/path2d.go +++ b/path2d.go @@ -13,6 +13,9 @@ type Path2D struct { p []pathPoint move backendbase.Vec cwSum float64 + + standalone bool + fillCache []backendbase.Vec } type pathPoint struct { @@ -34,7 +37,11 @@ const ( // NewPath2D creates a new Path2D and returns it func (cv *Canvas) NewPath2D() *Path2D { - return &Path2D{cv: cv, p: make([]pathPoint, 0, 20)} + return &Path2D{cv: cv, p: make([]pathPoint, 0, 20), standalone: true} +} + +func (p *Path2D) clearCache() { + p.fillCache = nil } // func (p *Path2D) AddPath(p2 *Path2D) { @@ -45,6 +52,7 @@ func (p *Path2D) MoveTo(x, y float64) { if len(p.p) > 0 && isSamePoint(p.p[len(p.p)-1].pos, backendbase.Vec{x, y}, 0.1) { return } + p.clearCache() p.p = append(p.p, pathPoint{pos: backendbase.Vec{x, y}, flags: pathMove | pathIsConvex}) p.cwSum = 0 p.move = backendbase.Vec{x, y} @@ -60,6 +68,7 @@ func (p *Path2D) lineTo(x, y float64, checkSelfIntersection bool) { if count > 0 && isSamePoint(p.p[len(p.p)-1].pos, backendbase.Vec{x, y}, 0.1) { return } + p.clearCache() if count == 0 { p.MoveTo(x, y) return diff --git a/paths.go b/paths.go index d6ab3b0..cb63c2d 100644 --- a/paths.go +++ b/paths.go @@ -110,7 +110,7 @@ func (cv *Canvas) strokePath(path *Path2D, inv backendbase.Mat, doInv bool) { cv.drawShadow(tris, nil, true) stl := cv.backendFillStyle(&cv.state.stroke, 1) - cv.b.Fill(&stl, tris, true) + cv.b.Fill(&stl, tris, backendbase.MatIdentity, true) } func (cv *Canvas) strokeTris(path *Path2D, inv backendbase.Mat, doInv bool, target []backendbase.Vec) []backendbase.Vec { @@ -381,13 +381,25 @@ func (cv *Canvas) fillPath(path *Path2D, tf backendbase.Mat) { return } + var tris []backendbase.Vec var triBuf [500]backendbase.Vec - tris := triBuf[:0] + if path.standalone && path.fillCache != nil { + tris = path.fillCache + } else { + if path.standalone { + tris = make([]backendbase.Vec, 0, 500) + } else { + tris = triBuf[:0] + } + runSubPaths(path.p, true, func(sp []pathPoint) bool { + tris = appendSubPathTriangles(tris, backendbase.MatIdentity, sp) + return false + }) + if path.standalone { + path.fillCache = tris + } + } - runSubPaths(path.p, true, func(sp []pathPoint) bool { - tris = appendSubPathTriangles(tris, tf, sp) - return false - }) if len(tris) == 0 { return } @@ -395,7 +407,7 @@ func (cv *Canvas) fillPath(path *Path2D, tf backendbase.Mat) { cv.drawShadow(tris, nil, false) stl := cv.backendFillStyle(&cv.state.fill, 1) - cv.b.Fill(&stl, tris, false) + cv.b.Fill(&stl, tris, tf, false) } func appendSubPathTriangles(tris []backendbase.Vec, mat backendbase.Mat, path []pathPoint) []backendbase.Vec { @@ -504,7 +516,7 @@ func (cv *Canvas) FillRect(x, y, w, h float64) { cv.drawShadow(data[:], nil, false) stl := cv.backendFillStyle(&cv.state.fill, 1) - cv.b.Fill(&stl, data[:], false) + cv.b.Fill(&stl, data[:], backendbase.MatIdentity, false) } // ClearRect sets the color of the rectangle to transparent black diff --git a/shadows.go b/shadows.go index f996744..765e023 100644 --- a/shadows.go +++ b/shadows.go @@ -38,6 +38,6 @@ func (cv *Canvas) drawShadow(pts []backendbase.Vec, mask *image.Alpha, canOverla copy(quad[:], cv.shadowBuf) cv.b.FillImageMask(&style, mask, quad) } else { - cv.b.Fill(&style, cv.shadowBuf, canOverlap) + cv.b.Fill(&style, cv.shadowBuf, backendbase.MatIdentity, canOverlap) } }