Cache ruler paints, disable preserveDrawingBuffer outside tests
This commit is contained in:
parent
5e209eca1c
commit
97f4727e26
|
|
@ -1,6 +1,11 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 0.2.2 (2026-03-01)
|
## Unreleased
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
- Cache ruler paints instead of allocating per frame
|
||||||
|
- Only enable `preserveDrawingBuffer` in test mode
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,12 @@ export class SkiaRenderer {
|
||||||
private fontProvider: TypefaceFontProvider | null = null
|
private fontProvider: TypefaceFontProvider | null = null
|
||||||
private fontsLoaded = false
|
private fontsLoaded = false
|
||||||
private imageCache = new Map<string, CKImage>()
|
private imageCache = new Map<string, CKImage>()
|
||||||
|
private rulerBgPaint: Paint
|
||||||
|
private rulerTickPaint: Paint
|
||||||
|
private rulerTextPaint: Paint
|
||||||
|
private rulerHlPaint: Paint
|
||||||
|
private rulerBadgePaint: Paint
|
||||||
|
private rulerLabelPaint: Paint
|
||||||
|
|
||||||
panX = 0
|
panX = 0
|
||||||
panY = 0
|
panY = 0
|
||||||
|
|
@ -201,6 +207,32 @@ export class SkiaRenderer {
|
||||||
this.opacityPaint = new ck.Paint()
|
this.opacityPaint = new ck.Paint()
|
||||||
|
|
||||||
this.textFont = new ck.Font(null, DEFAULT_FONT_SIZE)
|
this.textFont = new ck.Font(null, DEFAULT_FONT_SIZE)
|
||||||
|
|
||||||
|
const bg = RULER_BG_COLOR
|
||||||
|
this.rulerBgPaint = new ck.Paint()
|
||||||
|
this.rulerBgPaint.setColor(ck.Color4f(bg.r, bg.g, bg.b, 1))
|
||||||
|
|
||||||
|
this.rulerTickPaint = new ck.Paint()
|
||||||
|
this.rulerTickPaint.setColor(
|
||||||
|
ck.Color4f(RULER_TICK_COLOR.r, RULER_TICK_COLOR.g, RULER_TICK_COLOR.b, 1)
|
||||||
|
)
|
||||||
|
this.rulerTickPaint.setStrokeWidth(1)
|
||||||
|
this.rulerTickPaint.setAntiAlias(true)
|
||||||
|
|
||||||
|
const tc = RULER_TEXT_COLOR
|
||||||
|
this.rulerTextPaint = new ck.Paint()
|
||||||
|
this.rulerTextPaint.setColor(ck.Color4f(tc.r, tc.g, tc.b, 1))
|
||||||
|
this.rulerTextPaint.setAntiAlias(true)
|
||||||
|
|
||||||
|
this.rulerHlPaint = new ck.Paint()
|
||||||
|
this.rulerHlPaint.setAntiAlias(true)
|
||||||
|
|
||||||
|
this.rulerBadgePaint = new ck.Paint()
|
||||||
|
this.rulerBadgePaint.setAntiAlias(true)
|
||||||
|
|
||||||
|
this.rulerLabelPaint = new ck.Paint()
|
||||||
|
this.rulerLabelPaint.setColor(ck.Color4f(1, 1, 1, 1))
|
||||||
|
this.rulerLabelPaint.setAntiAlias(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
getFontProvider(): TypefaceFontProvider | null {
|
getFontProvider(): TypefaceFontProvider | null {
|
||||||
|
|
@ -2084,9 +2116,9 @@ export class SkiaRenderer {
|
||||||
const vh = this.viewportHeight
|
const vh = this.viewportHeight
|
||||||
if (vw === 0 || vh === 0) return
|
if (vw === 0 || vh === 0) return
|
||||||
|
|
||||||
const bg = RULER_BG_COLOR
|
const bgPaint = this.rulerBgPaint
|
||||||
const bgPaint = new this.ck.Paint()
|
const tickPaint = this.rulerTickPaint
|
||||||
bgPaint.setColor(this.ck.Color4f(bg.r, bg.g, bg.b, 1))
|
const textPaint = this.rulerTextPaint
|
||||||
|
|
||||||
canvas.drawRect(this.ck.LTRBRect(0, 0, vw, R), bgPaint)
|
canvas.drawRect(this.ck.LTRBRect(0, 0, vw, R), bgPaint)
|
||||||
canvas.drawRect(this.ck.LTRBRect(0, R, R, vh), bgPaint)
|
canvas.drawRect(this.ck.LTRBRect(0, R, R, vh), bgPaint)
|
||||||
|
|
@ -2094,25 +2126,8 @@ export class SkiaRenderer {
|
||||||
// Corner square
|
// Corner square
|
||||||
canvas.drawRect(this.ck.LTRBRect(0, 0, R, R), bgPaint)
|
canvas.drawRect(this.ck.LTRBRect(0, 0, R, R), bgPaint)
|
||||||
|
|
||||||
const tickPaint = new this.ck.Paint()
|
|
||||||
tickPaint.setColor(
|
|
||||||
this.ck.Color4f(RULER_TICK_COLOR.r, RULER_TICK_COLOR.g, RULER_TICK_COLOR.b, 1)
|
|
||||||
)
|
|
||||||
tickPaint.setStrokeWidth(1)
|
|
||||||
tickPaint.setAntiAlias(true)
|
|
||||||
|
|
||||||
const textColor = RULER_TEXT_COLOR
|
|
||||||
const textPaint = new this.ck.Paint()
|
|
||||||
textPaint.setColor(this.ck.Color4f(textColor.r, textColor.g, textColor.b, 1))
|
|
||||||
textPaint.setAntiAlias(true)
|
|
||||||
|
|
||||||
const font = this.sizeFont ?? this.textFont
|
const font = this.sizeFont ?? this.textFont
|
||||||
if (!font) {
|
if (!font) return
|
||||||
bgPaint.delete()
|
|
||||||
tickPaint.delete()
|
|
||||||
textPaint.delete()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const step = this.rulerStep()
|
const step = this.rulerStep()
|
||||||
const minorStep = step / 5
|
const minorStep = step / 5
|
||||||
|
|
@ -2205,11 +2220,10 @@ export class SkiaRenderer {
|
||||||
|
|
||||||
// Selection highlight + badges
|
// Selection highlight + badges
|
||||||
if (selNodes.length > 0) {
|
if (selNodes.length > 0) {
|
||||||
const hlPaint = new this.ck.Paint()
|
this.rulerHlPaint.setColor(this.selColor(RULER_HIGHLIGHT_ALPHA))
|
||||||
hlPaint.setColor(this.selColor(RULER_HIGHLIGHT_ALPHA))
|
|
||||||
|
|
||||||
canvas.drawRect(this.ck.LTRBRect(Math.max(R, sx1), 0, sx2, R), hlPaint)
|
canvas.drawRect(this.ck.LTRBRect(Math.max(R, sx1), 0, sx2, R), this.rulerHlPaint)
|
||||||
canvas.drawRect(this.ck.LTRBRect(0, Math.max(R, sy1), R, sy2), hlPaint)
|
canvas.drawRect(this.ck.LTRBRect(0, Math.max(R, sy1), R, sy2), this.rulerHlPaint)
|
||||||
|
|
||||||
this.drawRulerBadge(
|
this.drawRulerBadge(
|
||||||
canvas,
|
canvas,
|
||||||
|
|
@ -2244,12 +2258,7 @@ export class SkiaRenderer {
|
||||||
'vertical'
|
'vertical'
|
||||||
)
|
)
|
||||||
|
|
||||||
hlPaint.delete()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bgPaint.delete()
|
|
||||||
tickPaint.delete()
|
|
||||||
textPaint.delete()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private drawRulerBadge(
|
private drawRulerBadge(
|
||||||
|
|
@ -2267,11 +2276,7 @@ export class SkiaRenderer {
|
||||||
const pad = RULER_BADGE_PADDING
|
const pad = RULER_BADGE_PADDING
|
||||||
const h = RULER_BADGE_HEIGHT
|
const h = RULER_BADGE_HEIGHT
|
||||||
|
|
||||||
const badgePaint = new this.ck.Paint()
|
this.rulerBadgePaint.setColor(this.selColor())
|
||||||
badgePaint.setColor(this.selColor())
|
|
||||||
const labelPaint = new this.ck.Paint()
|
|
||||||
labelPaint.setColor(this.ck.Color4f(1, 1, 1, 1))
|
|
||||||
labelPaint.setAntiAlias(true)
|
|
||||||
|
|
||||||
if (axis === 'horizontal') {
|
if (axis === 'horizontal') {
|
||||||
const bx = x - (textW + pad * 2) / 2
|
const bx = x - (textW + pad * 2) / 2
|
||||||
|
|
@ -2282,9 +2287,9 @@ export class SkiaRenderer {
|
||||||
RULER_BADGE_RADIUS,
|
RULER_BADGE_RADIUS,
|
||||||
RULER_BADGE_RADIUS
|
RULER_BADGE_RADIUS
|
||||||
),
|
),
|
||||||
badgePaint
|
this.rulerBadgePaint
|
||||||
)
|
)
|
||||||
canvas.drawText(label, bx + pad, R * RULER_TEXT_BASELINE, labelPaint, font)
|
canvas.drawText(label, bx + pad, R * RULER_TEXT_BASELINE, this.rulerLabelPaint, font)
|
||||||
} else {
|
} else {
|
||||||
const bw = textW + pad * 2
|
const bw = textW + pad * 2
|
||||||
const bx = (R - h) / 2
|
const bx = (R - h) / 2
|
||||||
|
|
@ -2298,14 +2303,11 @@ export class SkiaRenderer {
|
||||||
RULER_BADGE_RADIUS,
|
RULER_BADGE_RADIUS,
|
||||||
RULER_BADGE_RADIUS
|
RULER_BADGE_RADIUS
|
||||||
),
|
),
|
||||||
badgePaint
|
this.rulerBadgePaint
|
||||||
)
|
)
|
||||||
canvas.drawText(label, -bw / 2 + pad, h / 2 - 3, labelPaint, font)
|
canvas.drawText(label, -bw / 2 + pad, h / 2 - 3, this.rulerLabelPaint, font)
|
||||||
canvas.restore()
|
canvas.restore()
|
||||||
}
|
}
|
||||||
|
|
||||||
badgePaint.delete()
|
|
||||||
labelPaint.delete()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private rulerStep(): number {
|
private rulerStep(): number {
|
||||||
|
|
@ -2339,6 +2341,12 @@ export class SkiaRenderer {
|
||||||
this.sizeFont?.delete()
|
this.sizeFont?.delete()
|
||||||
this.fontMgr?.delete()
|
this.fontMgr?.delete()
|
||||||
this.fontProvider?.delete()
|
this.fontProvider?.delete()
|
||||||
|
this.rulerBgPaint.delete()
|
||||||
|
this.rulerTickPaint.delete()
|
||||||
|
this.rulerTextPaint.delete()
|
||||||
|
this.rulerHlPaint.delete()
|
||||||
|
this.rulerBadgePaint.delete()
|
||||||
|
this.rulerLabelPaint.delete()
|
||||||
this.surface.delete()
|
this.surface.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,12 @@ export function useCanvas(canvasRef: Ref<HTMLCanvasElement | null>, store: Edito
|
||||||
canvas.width = w * dpr
|
canvas.width = w * dpr
|
||||||
canvas.height = h * dpr
|
canvas.height = h * dpr
|
||||||
|
|
||||||
const surface = ck.MakeWebGLCanvasSurface(canvas, undefined, { preserveDrawingBuffer: 1 })
|
const isTest = new URLSearchParams(window.location.search).has('test')
|
||||||
|
const surface = ck.MakeWebGLCanvasSurface(
|
||||||
|
canvas,
|
||||||
|
undefined,
|
||||||
|
isTest ? { preserveDrawingBuffer: 1 } : undefined
|
||||||
|
)
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
console.error('Failed to create WebGL surface')
|
console.error('Failed to create WebGL surface')
|
||||||
return
|
return
|
||||||
|
|
@ -54,6 +59,9 @@ export function useCanvas(canvasRef: Ref<HTMLCanvasElement | null>, store: Edito
|
||||||
canvas.dataset.ready = '1'
|
canvas.dataset.ready = '1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams(window.location.search)
|
||||||
|
const showRulers = !params.has('no-rulers')
|
||||||
|
|
||||||
let rafId = 0
|
let rafId = 0
|
||||||
|
|
||||||
function renderNow() {
|
function renderNow() {
|
||||||
|
|
@ -64,7 +72,7 @@ export function useCanvas(canvasRef: Ref<HTMLCanvasElement | null>, store: Edito
|
||||||
renderer.zoom = store.state.zoom
|
renderer.zoom = store.state.zoom
|
||||||
renderer.viewportWidth = canvasRef.value?.clientWidth ?? 0
|
renderer.viewportWidth = canvasRef.value?.clientWidth ?? 0
|
||||||
renderer.viewportHeight = canvasRef.value?.clientHeight ?? 0
|
renderer.viewportHeight = canvasRef.value?.clientHeight ?? 0
|
||||||
renderer.showRulers = !new URLSearchParams(window.location.search).has('no-rulers')
|
renderer.showRulers = showRulers
|
||||||
renderer.pageColor = store.state.pageColor
|
renderer.pageColor = store.state.pageColor
|
||||||
renderer.pageId = store.state.currentPageId
|
renderer.pageId = store.state.currentPageId
|
||||||
renderer.render(store.graph, store.state.selectedIds, {
|
renderer.render(store.graph, store.state.selectedIds, {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue