Path2D now caches the triangulation for filling
This commit is contained in:
parent
804a9c2774
commit
34087abece
17 changed files with 116 additions and 28 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
11
path2d.go
11
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
|
||||
|
|
28
paths.go
28
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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue