[graphics/krita] libs/ui/tool: Fix wrap around mode

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

Fix wrap around mode

M  +6    -6    libs/ui/tool/KisAsyncColorSamplerHelper.cpp
M  +12   -7    libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.cpp
M  +9    -7    libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.h

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

diff --git a/libs/ui/tool/KisAsyncColorSamplerHelper.cpp b/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
index a32f4e3d161..7beb9bcd046 100644
--- a/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
+++ b/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
@@ -83,7 +83,7 @@ struct KisAsyncColorSamplerHelper::Private
     QImage cacheCanvasPreviewImage;
     QPainterPath cacheCrosshairPath;
     int cacheCirclePreviewDiameter;
-    QWeakPointer<boost::none_t> canvasPreviewFetchingCookie;
+    QWeakPointer<boost::none_t> canvasPreviewFetchCookie;
     bool zoomPreviewHasPainted {false};
 
     QColor currentColor;
@@ -494,18 +494,18 @@ void KisAsyncColorSamplerHelper::prepareZoomPreview(const QRectF &docRect) {
     // Make sure the center is the pixel currently sampled because standardizing may change the shape
     canvasPixelRect.moveCenter(image->documentToImagePixelFloored(zoomDocRectF.center()));
 
-    if (!image->bounds().intersects(canvasPixelRect)) {
+    if (!image->bounds().intersects(canvasPixelRect) && !image->wrapAroundModeActive()) {
         m_d->cacheCanvasPreviewRect = QRect();
         m_d->cacheCanvasPreviewImage = QImage();
         return;
     }
 
     // If not already have a job fetching canvas image, then do it
-    if (!m_d->canvasPreviewFetchingCookie && m_d->cacheCanvasPreviewRect != canvasPixelRect) {
+    if (!m_d->canvasPreviewFetchCookie && m_d->cacheCanvasPreviewRect != canvasPixelRect) {
         KisColorSamplerStrokeStrategy::GenerateCanvasZoomPreviewData *data =
             new KisColorSamplerStrokeStrategy::GenerateCanvasZoomPreviewData(image->projection(), canvasPixelRect, m_d->canvas->displayColorConverter());
 
-        m_d->canvasPreviewFetchingCookie = data->cookie();
+        m_d->canvasPreviewFetchCookie = data->cookie();
 
         m_d->strokesFacade()->addJob(m_d->strokeId, data);
     }
@@ -711,7 +711,7 @@ void KisAsyncColorSamplerHelper::paintCircle(QPainter &gc,
 
     // If canvas preview image is null and it's being fetched (which means canvas preview is needed),
     // don't paint preview until it's done to avoid flickering
-    bool shouldPaintPreview = !(m_d->cacheCanvasPreviewImage.isNull() && m_d->canvasPreviewFetchingCookie);
+    bool shouldPaintPreview = !(m_d->cacheCanvasPreviewImage.isNull() && m_d->canvasPreviewFetchCookie);
 
     // But if zoom preview has already been painted, keeps painting to avoid flickering
     if (m_d->circleZoomPreviewEnabled && (shouldPaintPreview || m_d->zoomPreviewHasPainted)) {
@@ -756,7 +756,7 @@ void KisAsyncColorSamplerHelper::paintCircleCrosshair(QPainter &gc, const QRectF
 }
 
 void KisAsyncColorSamplerHelper::paintCircleCanvasPreview(QPainter &gc, const QRectF &viewRectF, const QPainterPath &clip) {
-    QRect canvasPixelRect = QRect(QPoint(0,0), m_d->cacheCanvasPreviewRect.size());
+    QRect canvasPixelRect = m_d->cacheCanvasPreviewRect;
     QImage cachedImage = m_d->cacheCanvasPreviewImage;
 
     if (cachedImage.isNull()) return;
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 f846bcdcb9a..d60f92eaf10 100644
--- a/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.cpp
+++ b/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.cpp
@@ -19,8 +19,6 @@ struct KisColorSamplerStrokeStrategy::Private
     int blend = 100;
 
     boost::optional<KoColor> lastSelectedColor;
-
-    QSharedPointer<boost::none_t> strokeCookie = nullptr;
 };
 
 KisColorSamplerStrokeStrategy::KisColorSamplerStrokeStrategy(int radius, int blend, int lod)
@@ -59,10 +57,17 @@ void KisColorSamplerStrokeStrategy::doStrokeCallback(KisStrokeJobData *data)
             Q_EMIT sigFinalColorSelected(*m_d->lastSelectedColor);
         }
     } else if (previewData) {
-        KisPaintDeviceSP tmpDev = new KisPaintDevice(previewData->canvasDev->colorSpace());
-        tmpDev->makeCloneFrom(previewData->canvasDev, previewData->canvasPixelRect);
+        bool oldWrapAroundModeSupport = previewData->canvasDev->supportsWraproundMode();
+        previewData->canvasDev->setSupportsWraparoundMode(true);
+
+        KisPaintDeviceSP tmpDev = previewData->canvasDev->createThumbnailDevice(
+            previewData->canvasPixelRect.width(), previewData->canvasPixelRect.height(), previewData->canvasPixelRect);
+
+        previewData->canvasDev->setSupportsWraparoundMode(oldWrapAroundModeSupport);
+
+        QRect effectiveRect = QRect(QPoint(0,0), previewData->canvasPixelRect.size());
 
-        QImage image = previewData->colorConverter->convertImageToDisplayColorSpace(tmpDev, previewData->canvasPixelRect, true);
+        QImage image = previewData->colorConverter->convertImageToDisplayColorSpace(tmpDev, effectiveRect, true);
 
         if (previewData->levelOfDetail > 0) {
             KisLodTransform transform(previewData->levelOfDetail);
@@ -70,10 +75,10 @@ void KisColorSamplerStrokeStrategy::doStrokeCallback(KisStrokeJobData *data)
 
             image = image.scaled(QSize(scale * image.width(), scale * image.height()));
 
-            previewData->canvasPixelRect = transform.mapInverted(previewData->canvasPixelRect);
+            effectiveRect = transform.mapInverted(effectiveRect);
         }
 
-        Q_EMIT sigCanvasZoomPreviewUpdated(image, previewData->canvasPixelRect);
+        Q_EMIT sigCanvasZoomPreviewUpdated(image, effectiveRect);
     }
 }
 
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 90280926a72..00011c71604 100644
--- a/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.h
+++ b/libs/ui/tool/strokes/kis_color_sampler_stroke_strategy.h
@@ -51,29 +51,31 @@ public:
     public:
         GenerateCanvasZoomPreviewData(KisPaintDeviceSP _canvasDev, const QRect &_canvasPixelRect, KisDisplayColorConverter *_colorConverter,
                                       int _levelOfDetail = 0, QSharedPointer<boost::none_t> _cookie = nullptr)
-            : canvasDev(_canvasDev), canvasPixelRect(_canvasPixelRect), colorConverter(_colorConverter), levelOfDetail(_levelOfDetail), fetchingCookie(_cookie)
+            : canvasDev(_canvasDev), canvasPixelRect(_canvasPixelRect), colorConverter(_colorConverter), levelOfDetail(_levelOfDetail), strokeCookie(_cookie)
         {}
 
         KisStrokeJobData* createLodClone(int levelOfDetail) override {
             KisLodTransform transform(levelOfDetail);
             QRect lodPixelRect = transform.map(canvasPixelRect);
-            GenerateCanvasZoomPreviewData *newData = new GenerateCanvasZoomPreviewData(canvasDev, lodPixelRect, colorConverter, levelOfDetail);
-            // When Lod is involved, swap the cookie to the new Lod clone to track execution, the original object seems to leaks
-            newData->fetchingCookie.swap(fetchingCookie);
+            GenerateCanvasZoomPreviewData *newData =
+                new GenerateCanvasZoomPreviewData(canvasDev, lodPixelRect, colorConverter, levelOfDetail);
+            // When Lod is involved, swap the cookie to the new Lod clone to track execution
+            // The original object seems to leaks
+            newData->strokeCookie.swap(strokeCookie);
 
             return newData;
         }
 
         QWeakPointer<boost::none_t> cookie() {
-            fetchingCookie.reset(new boost::none_t(boost::none));
-            return fetchingCookie;
+            strokeCookie.reset(new boost::none_t(boost::none));
+            return strokeCookie;
         }
 
         KisPaintDeviceSP canvasDev;
         QRect canvasPixelRect;
         KisDisplayColorConverter *colorConverter;
         int levelOfDetail;
-        QSharedPointer<boost::none_t> fetchingCookie;
+        QSharedPointer<boost::none_t> strokeCookie;
     };
 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.