perf(canvas): cache vector stroke paths
This commit is contained in:
parent
197e19b6f4
commit
0b3b620b54
|
|
@ -72,6 +72,8 @@ export class SkiaRenderer {
|
|||
fontsLoaded = false
|
||||
imageCache = new Map<string, CKImage>()
|
||||
vectorPathCache = new Map<string, Path[]>()
|
||||
vectorStrokePathCache = new Map<string, Path[]>()
|
||||
vectorStrokeOutlineCache = new Map<string, Path[]>()
|
||||
fillGeometryCache = new Map<string, Path[]>()
|
||||
strokeGeometryCache = new Map<string, Path[]>()
|
||||
scenePicture: SkPicture | null = null
|
||||
|
|
@ -485,10 +487,16 @@ export class SkiaRenderer {
|
|||
}
|
||||
|
||||
invalidateVectorPath(nodeId: string): void {
|
||||
const old = this.vectorPathCache.get(nodeId)
|
||||
if (old) {
|
||||
for (const cache of [this.vectorPathCache, this.vectorStrokePathCache]) {
|
||||
const old = cache.get(nodeId)
|
||||
if (!old) continue
|
||||
for (const p of old) p.delete()
|
||||
this.vectorPathCache.delete(nodeId)
|
||||
cache.delete(nodeId)
|
||||
}
|
||||
for (const [key, paths] of this.vectorStrokeOutlineCache) {
|
||||
if (!key.startsWith(`${nodeId}|`)) continue
|
||||
for (const p of paths) p.delete()
|
||||
this.vectorStrokeOutlineCache.delete(key)
|
||||
}
|
||||
for (const cache of [this.fillGeometryCache, this.strokeGeometryCache]) {
|
||||
const oldGeom = cache.get(nodeId)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,13 @@ export function destroyRenderer(r: SkiaRenderer): void {
|
|||
|
||||
for (const img of r.imageCache.values()) img.delete()
|
||||
r.imageCache.clear()
|
||||
for (const cache of [r.vectorPathCache, r.fillGeometryCache, r.strokeGeometryCache]) {
|
||||
for (const cache of [
|
||||
r.vectorPathCache,
|
||||
r.vectorStrokePathCache,
|
||||
r.vectorStrokeOutlineCache,
|
||||
r.fillGeometryCache,
|
||||
r.strokeGeometryCache
|
||||
]) {
|
||||
for (const paths of cache.values()) {
|
||||
for (const p of paths) p.delete()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -322,6 +322,8 @@ function drawVectorStrokeGeometry(
|
|||
|
||||
function vectorStrokePaths(r: SkiaRenderer, node: SceneNode): Path[] | null {
|
||||
if (!node.vectorNetwork) return null
|
||||
const cached = r.vectorStrokePathCache.get(node.id)
|
||||
if (cached) return cached
|
||||
|
||||
const paths: Path[] = []
|
||||
for (const segment of node.vectorNetwork.segments) {
|
||||
|
|
@ -350,7 +352,9 @@ function vectorStrokePaths(r: SkiaRenderer, node: SceneNode): Path[] | null {
|
|||
paths.push(path)
|
||||
}
|
||||
|
||||
return paths.length > 0 ? paths : null
|
||||
if (paths.length === 0) return null
|
||||
r.vectorStrokePathCache.set(node.id, paths)
|
||||
return paths
|
||||
}
|
||||
|
||||
function drawVectorPathStrokes(
|
||||
|
|
@ -358,7 +362,8 @@ function drawVectorPathStrokes(
|
|||
canvas: Canvas,
|
||||
vectorPaths: Path[],
|
||||
stroke: SceneNode['strokes'][0],
|
||||
sc: Color
|
||||
sc: Color,
|
||||
outlineCacheKey?: string
|
||||
): void {
|
||||
const dash = stroke.dashPattern
|
||||
if (dash && dash.length > 0) {
|
||||
|
|
@ -384,13 +389,17 @@ function drawVectorPathStrokes(
|
|||
r.fillPaint.setColor(r.ck.Color4f(sc.r, sc.g, sc.b, sc.a))
|
||||
r.fillPaint.setAlphaf(stroke.opacity)
|
||||
r.fillPaint.setShader(null)
|
||||
|
||||
let outlines = outlineCacheKey ? r.vectorStrokeOutlineCache.get(outlineCacheKey) : undefined
|
||||
if (!outlines) {
|
||||
outlines = []
|
||||
for (const vp of vectorPaths) {
|
||||
const outline = vp.copy().stroke(strokeOpts)
|
||||
if (outline) {
|
||||
canvas.drawPath(outline, r.fillPaint)
|
||||
outline.delete()
|
||||
if (outline) outlines.push(outline)
|
||||
}
|
||||
if (outlineCacheKey) r.vectorStrokeOutlineCache.set(outlineCacheKey, outlines)
|
||||
}
|
||||
for (const outline of outlines) canvas.drawPath(outline, r.fillPaint)
|
||||
}
|
||||
|
||||
function drawRegularStroke(
|
||||
|
|
@ -438,7 +447,8 @@ function drawNodeStroke(
|
|||
vectorStroke: Path[] | null
|
||||
): void {
|
||||
if (vectorStroke && stroke.align === 'CENTER' && node.cornerRadius === 0) {
|
||||
drawVectorPathStrokes(r, canvas, vectorStroke, stroke, sc)
|
||||
const outlineKey = `${node.id}|${stroke.weight}|${stroke.cap ?? 'NONE'}|${stroke.join ?? 'MITER'}`
|
||||
drawVectorPathStrokes(r, canvas, vectorStroke, stroke, sc, outlineKey)
|
||||
return
|
||||
}
|
||||
if (!sg) {
|
||||
|
|
@ -498,10 +508,6 @@ export function renderShapeUncached(
|
|||
}
|
||||
drawNodeStroke(r, canvas, node, rect, hasRadius, stroke, color, sg, vectorPaths, vectorStroke)
|
||||
})
|
||||
if (vectorStroke) {
|
||||
for (const path of vectorStroke) path.delete()
|
||||
}
|
||||
|
||||
r.renderEffects(canvas, node, rect, hasRadius, 'front', shadowChild)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue