From b20767c702eb025913ab3f46fcaef881a12bbfe7 Mon Sep 17 00:00:00 2001 From: zach Date: Tue, 19 May 2026 10:04:04 +0200 Subject: [PATCH] hopefully increase drawing performance --- Drawers/Drawing.qml | 197 +++++---------------------------------- Drawers/DrawingInput.qml | 13 ++- Drawers/Interactions.qml | 36 +++---- 3 files changed, 49 insertions(+), 197 deletions(-) diff --git a/Drawers/Drawing.qml b/Drawers/Drawing.qml index 6a30ff2..9d7bf63 100644 --- a/Drawers/Drawing.qml +++ b/Drawers/Drawing.qml @@ -3,184 +3,33 @@ import QtQuick Canvas { id: root - property rect dirtyRect: Qt.rect(0, 0, 0, 0) - property bool frameQueued: false - property bool fullRepaintPending: true - property point lastPoint: Qt.point(0, 0) - property real minPointDistance: 2.0 property color penColor: "white" property real penWidth: 4 - property var pendingSegments: [] - property bool strokeActive: false - property var strokes: [] + property var points: [] - function appendPoint(x, y) { - if (!strokeActive || strokes.length === 0) + function clear(): void { + var ctx = getContext('2d'); + root.points = []; + ctx.reset(); + root.requestPaint(); + } + + renderStrategy: Canvas.Cooperative + + onPaint: { + if (points.length < 2) return; - const dx = x - lastPoint.x; - const dy = y - lastPoint.y; - - if ((dx * dx + dy * dy) < (minPointDistance * minPointDistance)) - return; - const x1 = lastPoint.x; - const y1 = lastPoint.y; - const x2 = x; - const y2 = y; - - strokes[strokes.length - 1].push(Qt.point(x2, y2)); - - pendingSegments.push({ - dot: false, - x1: x1, - y1: y1, - x2: x2, - y2: y2 - }); - - lastPoint = Qt.point(x2, y2); - queueDirty(segmentDirtyRect(x1, y1, x2, y2)); - } - - function beginStroke(x, y) { - const p = Qt.point(x, y); - strokes.push([p]); - lastPoint = p; - strokeActive = true; - - pendingSegments.push({ - dot: true, - x: x, - y: y - }); - - queueDirty(pointDirtyRect(x, y)); - } - - function clear() { - strokes = []; - pendingSegments = []; - dirtyRect = Qt.rect(0, 0, 0, 0); - fullRepaintPending = true; - markDirty(Qt.rect(0, 0, width, height)); - } - - function drawDot(ctx, x, y) { - ctx.beginPath(); - ctx.arc(x, y, penWidth / 2, 0, Math.PI * 2); - ctx.fill(); - } - - function drawSegment(ctx, x1, y1, x2, y2) { - ctx.beginPath(); - ctx.moveTo(x1, y1); - ctx.lineTo(x2, y2); - ctx.stroke(); - } - - function endStroke() { - strokeActive = false; - } - - function pointDirtyRect(x, y) { - const pad = penWidth + 2; - return Qt.rect(x - pad, y - pad, pad * 2, pad * 2); - } - - function queueDirty(r) { - dirtyRect = unionRects(dirtyRect, r); - - if (frameQueued) - return; - frameQueued = true; - - requestAnimationFrame(function () { - frameQueued = false; - - if (dirtyRect.width > 0 && dirtyRect.height > 0) { - markDirty(dirtyRect); - dirtyRect = Qt.rect(0, 0, 0, 0); - } - }); - } - - function replayAll(ctx) { - ctx.clearRect(0, 0, width, height); - - for (const stroke of strokes) { - if (!stroke || stroke.length === 0) - continue; - if (stroke.length === 1) { - const p = stroke[0]; - drawDot(ctx, p.x, p.y); - continue; - } - - ctx.beginPath(); - ctx.moveTo(stroke[0].x, stroke[0].y); - for (let i = 1; i < stroke.length; ++i) - ctx.lineTo(stroke[i].x, stroke[i].y); - ctx.stroke(); - } - } - - function requestFullRepaint() { - fullRepaintPending = true; - markDirty(Qt.rect(0, 0, width, height)); - } - - function segmentDirtyRect(x1, y1, x2, y2) { - const pad = penWidth + 2; - const left = Math.min(x1, x2) - pad; - const top = Math.min(y1, y2) - pad; - const right = Math.max(x1, x2) + pad; - const bottom = Math.max(y1, y2) + pad; - return Qt.rect(left, top, right - left, bottom - top); - } - - function unionRects(a, b) { - if (a.width <= 0 || a.height <= 0) - return b; - if (b.width <= 0 || b.height <= 0) - return a; - - const left = Math.min(a.x, b.x); - const top = Math.min(a.y, b.y); - const right = Math.max(a.x + a.width, b.x + b.width); - const bottom = Math.max(a.y + a.height, b.y + b.height); - - return Qt.rect(left, top, right - left, bottom - top); - } - - anchors.fill: parent - contextType: "2d" - renderStrategy: Canvas.Threaded - renderTarget: Canvas.Image - - onHeightChanged: requestFullRepaint() - onPaint: region => { - const ctx = getContext("2d"); - + var ctx = root.getContext('2d'); + ctx.save(); + ctx.lineWidth = root.penWidth; + ctx.strokeStyle = root.penColor; ctx.lineCap = "round"; - ctx.lineJoin = "round"; - ctx.lineWidth = penWidth; - ctx.strokeStyle = penColor; - ctx.fillStyle = penColor; - - if (fullRepaintPending) { - fullRepaintPending = false; - replayAll(ctx); - pendingSegments = []; - return; - } - - for (const seg of pendingSegments) { - if (seg.dot) - drawDot(ctx, seg.x, seg.y); - else - drawSegment(ctx, seg.x1, seg.y1, seg.x2, seg.y2); - } - - pendingSegments = []; + ctx.beginPath(); + ctx.moveTo(points[0].x, points[0].y); + for (var i = 1; i < points.length; i++) + ctx.lineTo(points[i].x, points[i].y); + ctx.stroke(); + points = points.slice(points.length - 2); + ctx.restore(); } - onWidthChanged: requestFullRepaint() } diff --git a/Drawers/DrawingInput.qml b/Drawers/DrawingInput.qml index c8f2c18..3fdcd33 100644 --- a/Drawers/DrawingInput.qml +++ b/Drawers/DrawingInput.qml @@ -30,8 +30,11 @@ CustomMouseArea { const x = event.x; const y = event.y; - if (event.buttons & Qt.LeftButton) - root.drawing.appendPoint(x, y); + if (root.visibilities.isDrawing && (event.buttons & Qt.LeftButton)) { + root.drawing.points.push(Qt.point(x, y)); + console.log(root.drawing.points); + root.drawing.requestPaint(); + } if (root.inLeftPanel(root.popout, x, y)) { root.z = -2; @@ -44,7 +47,8 @@ CustomMouseArea { if (root.visibilities.isDrawing && (event.buttons & Qt.LeftButton)) { root.panels.drawing.expanded = false; - root.drawing.beginStroke(x, y); + root.drawing.points.push(Qt.point(x, y)); + root.drawing.requestPaint(); return; } @@ -52,7 +56,6 @@ CustomMouseArea { root.drawing.clear(); } onReleased: { - if (root.visibilities.isDrawing) - root.drawing.endStroke(); + root.drawing.points = []; } } diff --git a/Drawers/Interactions.qml b/Drawers/Interactions.qml index c3abfe8..f7fcdf0 100644 --- a/Drawers/Interactions.qml +++ b/Drawers/Interactions.qml @@ -78,7 +78,7 @@ CustomMouseArea { const dragY = y - dragStart.y; if (root.visibilities.isDrawing && !root.inLeftPanel(root.panels.drawing, x, y)) { - root.input.z = 2; + // root.input.z = 2; root.panels.drawing.expanded = false; } @@ -96,25 +96,25 @@ CustomMouseArea { if (dragY < -10) visibilities.dock = true; - if (panels.sidebar.width === 0) { - const showOsd = inRightPanel(panels.osdWrapper, x, y); + if (panels.sidebar.width === 0) { + const showOsd = inRightPanel(panels.osdWrapper, x, y); - if (showOsd) { - osdShortcutActive = false; - root.panels.osd.hovered = true; - } - } else { - const outOfSidebar = x < width - panels.sidebar.width; - const showOsd = outOfSidebar && inRightPanel(panels.osdWrapper, x, y); - - if (!osdShortcutActive) { - visibilities.osd = showOsd; - root.panels.osd.hovered = showOsd; - } else if (showOsd) { - osdShortcutActive = false; - root.panels.osd.hovered = true; - } + if (showOsd) { + osdShortcutActive = false; + root.panels.osd.hovered = true; } + } else { + const outOfSidebar = x < width - panels.sidebar.width; + const showOsd = outOfSidebar && inRightPanel(panels.osdWrapper, x, y); + + if (!osdShortcutActive) { + visibilities.osd = showOsd; + root.panels.osd.hovered = showOsd; + } else if (showOsd) { + osdShortcutActive = false; + root.panels.osd.hovered = true; + } + } if (Config.dock.enable && !Config.dock.hoverToReveal && !visibilities.dock && !visibilities.launcher && inBottomPanel(panels.dock, x, y)) visibilities.dock = true;