[graphics/krita] libs/ui/tool: Nuke caching

Emmet O'Neill <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit a8d4b36a4f19923e80779815556a68bf244c9b4d by Emmet O'Neill, on behalf of Dat Le.
Committed on 13/08/2026 at 23:16.
Pushed by emmetoneill into branch 'master'.

Nuke caching

M  +11   -42   libs/ui/tool/KisAsyncColorSamplerHelper.cpp
M  +1    -3    libs/ui/tool/KisAsyncColorSamplerHelper.h
M  +4    -4    libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.cpp
M  +3    -4    libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.h

https://invent.kde.org/graphics/krita/-/commit/a8d4b36a4f19923e80779815556a68bf244c9b4d

diff --git a/libs/ui/tool/KisAsyncColorSamplerHelper.cpp b/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
index 24a970e82bd..4ad99c522a6 100644
--- a/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
+++ b/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
@@ -83,7 +83,6 @@ struct KisAsyncColorSamplerHelper::Private
     QPainterPath cacheCrosshairPath;
     int cacheCirclePreviewDiameter;
     bool canvasPreviewFetchingStarted {false};
-    QRect oldCanvasPixelRect;
     bool zoomPreviewHasPainted {false};
 
     QColor currentColor;
@@ -415,7 +414,6 @@ void KisAsyncColorSamplerHelper::deactivate()
     m_d->cacheCanvasPreviewImage = QImage();
     m_d->cacheCanvasPreviewRect = QRect();
     m_d->canvasPreviewFetchingStarted = false;
-    m_d->oldCanvasPixelRect = QRect();
     m_d->zoomPreviewHasPainted = false;
 
     m_d->isActive = false;
@@ -710,15 +708,11 @@ void KisAsyncColorSamplerHelper::paintCircleCrosshair(QPainter &gc, const QRectF
     qreal luminance = KisPaintingTweaks::luminosityCoarse(currentColor);
     if (luminance < 0.5) crosshairColor = Qt::white;
 
-    qreal dpr = gc.device()->devicePixelRatioF();
-    qreal penWidth = 1.0 * dpr;
-    QPen pen = QPen(crosshairColor, penWidth);
-
     gc.save();
 
     gc.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
     gc.setCompositionMode(QPainter::CompositionMode_SourceOver);
-    gc.setPen(pen);
+    gc.setPen(crosshairColor);
 
     QTransform tf;
     tf.translate(viewRectF.center().x(), viewRectF.center().y());
@@ -728,7 +722,7 @@ void KisAsyncColorSamplerHelper::paintCircleCrosshair(QPainter &gc, const QRectF
     gc.restore();
 }
 
-QImage KisAsyncColorSamplerHelper::cacheCanvasImage(QRect &canvasPixelRect) {
+QImage KisAsyncColorSamplerHelper::fetchCanvasPreview(QRect &canvasPixelRect) {
     KisImageWSP canvasImage = m_d->canvas->image();
 
     if (!canvasImage->bounds().intersects(canvasPixelRect)) {
@@ -736,40 +730,15 @@ QImage KisAsyncColorSamplerHelper::cacheCanvasImage(QRect &canvasPixelRect) {
         return QImage();
     }
 
-    // If already cached the whole canvas, just use it from now on
-    if (m_d->cacheCanvasPreviewRect == canvasImage->bounds()) {
-        return m_d->cacheCanvasPreviewImage;
-    }
-
-    if (m_d->cacheCanvasPreviewRect.isEmpty() || !m_d->cacheCanvasPreviewRect.contains(canvasPixelRect)) {
-        // Cache an area larger than the needed preview area to avoid rapid small dynamic allocations
-        // And also avoid frequent preview delay from repeatedly fetching canvas image asynchronously
-        qreal cacheScale = 1;
-
-        QRect cacheCanvasRect = canvasPixelRect;
-        cacheCanvasRect.setSize(canvasPixelRect.size() * cacheScale);
-        cacheCanvasRect.moveCenter(canvasPixelRect.center());
-
-        // if cache requirement is larger than canvas, then just copy whole canvas
-        if (cacheCanvasRect.width() >= canvasImage->width() || cacheCanvasRect.height() >= canvasImage->height()) {
-            cacheCanvasRect = canvasImage->bounds();
-        }
-
-        // If not already have a job fetching canvas image, then do it
-        // TODO: There's probably a better way to do this
-        if (!m_d->canvasPreviewFetchingStarted) {
-            m_d->canvasPreviewFetchingStarted = true;
-            m_d->strokesFacade()->addJob(m_d->strokeId,
-                new KisColorSamplerStrokeStrategy::GenerateCanvasZoomPreviewData(m_d->canvas, cacheCanvasRect, canvasImage->colorSpace()->profile()));
-        }
-
-        // Return the last valid canvas preview while we wait to fetch new canvas cache async
-        if (!m_d->oldCanvasPixelRect.isNull()) canvasPixelRect = m_d->oldCanvasPixelRect;
-        return m_d->cacheCanvasPreviewImage;
+    // If not already have a job fetching canvas image, then do it
+    if (!m_d->canvasPreviewFetchingStarted) {
+        m_d->canvasPreviewFetchingStarted = true;
+        m_d->strokesFacade()->addJob(m_d->strokeId,
+            new KisColorSamplerStrokeStrategy::GenerateCanvasZoomPreviewData(m_d->canvas, canvasPixelRect));
     }
 
-    canvasPixelRect.translate(-m_d->cacheCanvasPreviewRect.topLeft());
-    m_d->oldCanvasPixelRect = canvasPixelRect;
+    // Render the last frame if available
+    if (!m_d->cacheCanvasPreviewRect.isNull()) canvasPixelRect = m_d->cacheCanvasPreviewRect;
 
     return m_d->cacheCanvasPreviewImage;
 }
@@ -787,7 +756,7 @@ bool KisAsyncColorSamplerHelper::paintCircleCanvasPreview(QPainter &gc, const QR
     // Make sure the center is the pixel currently sampled because standardizing may change the shape
     canvasPixelRect.moveCenter(image->documentToImagePixelFloored(zoomDocRectF.center()));
 
-    QImage cachedImage = cacheCanvasImage(canvasPixelRect);
+    QImage cachedImage = fetchCanvasPreview(canvasPixelRect);
     // If cachedImage and canvasPixelRect is null, painting is not needed
     // If cachedImage is null and canvasPixelRect is not null, painting was deferred
     if (cachedImage.isNull()) return canvasPixelRect.isNull();
@@ -862,8 +831,8 @@ void KisAsyncColorSamplerHelper::paintCircleReferenceImagePreview(QPainter &gc,
 }
 
 void KisAsyncColorSamplerHelper::slotCanvasZoomPreviewUpdated(const QImage &canvasImage, QRect canvasRect) {
-    m_d->cacheCanvasPreviewImage = canvasImage;
     m_d->cacheCanvasPreviewRect = canvasRect;
+    m_d->cacheCanvasPreviewImage = canvasImage;
 
     m_d->canvasPreviewFetchingStarted = false;
 
diff --git a/libs/ui/tool/KisAsyncColorSamplerHelper.h b/libs/ui/tool/KisAsyncColorSamplerHelper.h
index 528d7797566..8f4ed364dfb 100644
--- a/libs/ui/tool/KisAsyncColorSamplerHelper.h
+++ b/libs/ui/tool/KisAsyncColorSamplerHelper.h
@@ -87,9 +87,7 @@ private:
     bool paintCircleCanvasPreview(QPainter &gc, const QRectF &viewRectF, const QRectF &zoomDocRectF, const QPainterPath &clip);
     void paintCircleReferenceImagePreview(QPainter &gc, const QRectF &viewRectF, const QRectF &zoomDocRectF, const QPainterPath &clip);
 
-    // Returns a QImage that should either contain the canvasPixelRect + caching, or the whole canvas if canvasPixelRect + caching > canvas size.
-    // Also modify the input rect to point to the same position relative to the returned image
-    QImage cacheCanvasImage(QRect &canvasPixelRect);
+    QImage fetchCanvasPreview(QRect &canvasPixelRect);
 
     struct Private;
     QScopedPointer<Private> m_d;
diff --git a/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.cpp b/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.cpp
index b3719928b7a..dbf9aec6fb6 100644
--- a/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.cpp
+++ b/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.cpp
@@ -59,13 +59,13 @@ void KisColorSamplerStrokeStrategy::doStrokeCallback(KisStrokeJobData *data)
         }
     } else if (previewData) {
         KisPaintDeviceSP dev = previewData->canvas->image()->projection();
-        KisPaintDeviceSP tmp = new KisPaintDevice(dev->colorSpace());
+        KisPaintDeviceSP tmpDev = new KisPaintDevice(dev->colorSpace());
 
-        tmp->makeCloneFromRough(dev, previewData->canvasPixelRect);
+        tmpDev->makeCloneFrom(dev, previewData->canvasPixelRect);
 
-        QImage image = previewData->canvas->displayColorConverter()->convertImageToDisplayColorSpace(tmp, previewData->canvasPixelRect, true);
+        QImage image = previewData->canvas->displayColorConverter()->convertImageToDisplayColorSpace(tmpDev, previewData->canvasPixelRect, true);
 
-        Q_EMIT sigCanvasZoomPreviewUpdated(image, previewData->canvasPixelRect);
+        Q_EMIT sigCanvasZoomPreviewUpdated(image, QRect(QPoint(0,0), previewData->canvasPixelRect.size()));
     }
 }
 
diff --git a/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.h b/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.h
index bdf761473a1..4b4117e915d 100644
--- a/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.h
+++ b/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.h
@@ -49,18 +49,17 @@ public:
 
     class GenerateCanvasZoomPreviewData : public KisStrokeJobData {
     public:
-        GenerateCanvasZoomPreviewData(KisCanvas2* _canvas, const QRect &_canvasPixelRect, const KoColorProfile *_colorProfile)
-            : canvas(_canvas), canvasPixelRect(_canvasPixelRect), colorProfile(_colorProfile)
+        GenerateCanvasZoomPreviewData(KisCanvas2* _canvas, const QRect &_canvasPixelRect)
+            : canvas(_canvas), canvasPixelRect(_canvasPixelRect)
         {}
 
         KisStrokeJobData* createLodClone(int levelOfDetail) override {
             Q_UNUSED(levelOfDetail);
-            return new GenerateCanvasZoomPreviewData(canvas, canvasPixelRect, colorProfile);
+            return new GenerateCanvasZoomPreviewData(canvas, canvasPixelRect);
         }
 
         KisCanvas2 *canvas;
         QRect canvasPixelRect;
-        const KoColorProfile *colorProfile;
     };
 public:
     KisColorSamplerStrokeStrategy(int radius, int blend, int lod = 0);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.