[graphics/krita] libs/ui: Add zoom preview scale setting, WIP zoom on reference image
Emmet O'Neill <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 4350486875166a6d9b7dd7e98b8a160fc8c7c022 by Emmet O'Neill, on behalf of Le Tien Dat.
Committed on 13/08/2026 at 23:16.
Pushed by emmetoneill into branch 'master'.
Add zoom preview scale setting, WIP zoom on reference image
M +10 -0 libs/ui/dialogs/kis_dlg_preferences.cc
M +1 -0 libs/ui/dialogs/kis_dlg_preferences.h
M +46 -17 libs/ui/forms/wdggeneralsettings.ui
M +13 -0 libs/ui/kis_config.cc
M +3 -0 libs/ui/kis_config.h
M +58 -12 libs/ui/tool/KisAsyncColorSamplerHelper.cpp
https://invent.kde.org/graphics/krita/-/commit/4350486875166a6d9b7dd7e98b8a160fc8c7c022
diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc
index 5bbab4f626c..fb5aefd2e1a 100644
--- a/libs/ui/dialogs/kis_dlg_preferences.cc
+++ b/libs/ui/dialogs/kis_dlg_preferences.cc
@@ -329,6 +329,10 @@ GeneralTab::GeneralTab(QWidget *_parent, const char *_name)
m_chkColorSamplerPreviewExtraCircles->setChecked(cfg.colorSamplerPreviewCircleExtraCirclesEnabled());
+ m_ssbColorSamplerZoomPreviewScale->setRange(100, 500);
+ m_ssbColorSamplerZoomPreviewScale->setSingleStep(25);
+ m_ssbColorSamplerZoomPreviewScale->setValue(cfg.colorSamplerZoomPreviewScale());
+
KisSpinBoxI18nHelper::setText(m_ssbColorSamplerPreviewThickness, i18nc("{n} is the number value, % is the percent sign", "{n}%"));
@@ -788,6 +792,7 @@ void GeneralTab::setDefault()
m_ssbColorSamplerPreviewThickness->setValue(cfg.colorSamplerPreviewCircleThickness(true));
m_nmbColorSamplerPreviewSize->setValue(cfg.colorSamplerPreviewCircleDiameter(true));
m_chkColorSamplerPreviewOutlineEnabled->setChecked(cfg.colorSamplerPreviewCircleOutlineEnabled(true));
+ m_ssbColorSamplerZoomPreviewScale->setValue(cfg.colorSamplerZoomPreviewScale(true));
chkShowRootLayer->setChecked(cfg.showRootLayer(true));
@@ -971,6 +976,10 @@ bool GeneralTab::colorSamplerPreviewCircleExtraCirclesEnabled() const
return m_chkColorSamplerPreviewExtraCircles->isChecked();
}
+qreal GeneralTab::colorSamplerZoomPreviewScale() const
+{
+ return m_ssbColorSamplerZoomPreviewScale->value();
+}
KisConfig::SessionOnStartup GeneralTab::sessionOnStartup() const
{
@@ -3062,6 +3071,7 @@ bool KisDlgPreferences::editPreferences(std::optional<PageDesc>page)
cfg.setColorSamplerPreviewCircleThickness(m_general->colorSamplerPreviewCircleThickness());
cfg.setColorSamplerPreviewCircleOutlineEnabled(m_general->colorSamplerPreviewCircleOutlineEnabled());
cfg.setColorSamplerPreviewCircleExtraCirclesEnabled(m_general->colorSamplerPreviewCircleExtraCirclesEnabled());
+ cfg.setColorSamplerZoomPreviewScale(m_general->colorSamplerZoomPreviewScale());
cfg.setShowRootLayer(m_general->showRootLayer());
cfg.setShowOutlineWhilePainting(m_general->showOutlineWhilePainting());
diff --git a/libs/ui/dialogs/kis_dlg_preferences.h b/libs/ui/dialogs/kis_dlg_preferences.h
index 881a8b2bed3..6421afc9877 100644
--- a/libs/ui/dialogs/kis_dlg_preferences.h
+++ b/libs/ui/dialogs/kis_dlg_preferences.h
@@ -73,6 +73,7 @@ public:
qreal colorSamplerPreviewCircleThickness() const;
bool colorSamplerPreviewCircleOutlineEnabled() const;
bool colorSamplerPreviewCircleExtraCirclesEnabled() const;
+ qreal colorSamplerZoomPreviewScale() const;
KisConfig::SessionOnStartup sessionOnStartup() const;
KisConfig::IconsInMenu iconsInMenu() const;
diff --git a/libs/ui/forms/wdggeneralsettings.ui b/libs/ui/forms/wdggeneralsettings.ui
index 4f42fdca340..a4f1feb0ef6 100644
--- a/libs/ui/forms/wdggeneralsettings.ui
+++ b/libs/ui/forms/wdggeneralsettings.ui
@@ -10,8 +10,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>1699</width>
- <height>663</height>
+ <width>1573</width>
+ <height>665</height>
</rect>
</property>
<property name="sizePolicy">
@@ -42,7 +42,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
- <number>5</number>
+ <number>3</number>
</property>
<property name="movable">
<bool>false</bool>
@@ -973,6 +973,12 @@
</item>
<item row="5" column="0" colspan="2">
<widget class="QFrame" name="m_frmColorSamplerCircleSettings">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@@ -980,16 +986,6 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="m_frmColorSamplerCircleSettingsLayout">
- <item row="1" column="0">
- <widget class="QLabel" name="m_lblColorSamplerPreviewSize">
- <property name="text">
- <string>Diameter:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="KisSliderSpinBox" name="m_nmbColorSamplerPreviewSize"/>
- </item>
<item row="0" column="0" colspan="2">
<widget class="KisColorSamplerPreviewPreview" name="m_lblColorSamplerPreviewSizePreview">
<property name="sizePolicy">
@@ -1006,6 +1002,16 @@
</property>
</widget>
</item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="m_lblColorSamplerPreviewSize">
+ <property name="text">
+ <string>Diameter:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="KisSliderSpinBox" name="m_nmbColorSamplerPreviewSize"/>
+ </item>
<item row="2" column="0">
<widget class="QLabel" name="m_lblColorSamplerPreviewThickness">
<property name="text">
@@ -1016,20 +1022,43 @@
<item row="2" column="1">
<widget class="KisDoubleSliderSpinBox" name="m_ssbColorSamplerPreviewThickness"/>
</item>
- <item row="3" column="1">
+ <item row="3" column="0">
+ <widget class="QLabel" name="m_lblZoomPreviewScale">
+ <property name="text">
+ <string>Zoom Preview Scale:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
<widget class="QCheckBox" name="m_chkColorSamplerPreviewOutlineEnabled">
<property name="text">
<string>Enable Outline</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="5" column="1">
<widget class="QCheckBox" name="m_chkColorSamplerPreviewExtraCircles">
<property name="text">
<string>Extra Comparison Space</string>
</property>
</widget>
</item>
+ <item row="3" column="1">
+ <widget class="KisSliderSpinBox" name="m_ssbColorSamplerZoomPreviewScale">
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ <property name="minimum">
+ <number>100</number>
+ </property>
+ <property name="maximum">
+ <number>500</number>
+ </property>
+ <property name="singleStep">
+ <number>25</number>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
@@ -1341,8 +1370,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>1675</width>
- <height>624</height>
+ <width>1552</width>
+ <height>786</height>
</rect>
</property>
<property name="sizePolicy">
diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc
index 6b31920841b..155aa177014 100644
--- a/libs/ui/kis_config.cc
+++ b/libs/ui/kis_config.cc
@@ -569,6 +569,19 @@ void KisConfig::setColorSamplerPreviewCircleThickness(qreal thickness)
m_cfg.writeEntry("colorSamplerPreviewCircleThickness", thickness);
}
+
+qreal KisConfig::colorSamplerZoomPreviewScale(bool defaultValue) const {
+ qreal def = 200;
+ if (!defaultValue) {
+ return m_cfg.readEntry("colorSamplerZoomPreviewScale", def);
+ }
+ return def;
+}
+
+void KisConfig::setColorSamplerZoomPreviewScale(qreal scale) {
+ m_cfg.writeEntry("colorSamplerZoomPreviewScale", scale);
+}
+
bool KisConfig::colorSamplerPreviewCircleOutlineEnabled(bool defaultValue) const
{
bool def = true;
diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h
index 78b01aac01e..323bba25eab 100644
--- a/libs/ui/kis_config.h
+++ b/libs/ui/kis_config.h
@@ -153,6 +153,9 @@ public:
qreal colorSamplerPreviewCircleThickness(bool defaultValue = false) const;
void setColorSamplerPreviewCircleThickness(qreal thickness);
+ qreal colorSamplerZoomPreviewScale(bool defaultValue = false) const;
+ void setColorSamplerZoomPreviewScale(qreal scale);
+
bool colorSamplerPreviewCircleOutlineEnabled(bool defaultValue = false) const;
void setColorSamplerPreviewCircleOutlineEnabled(bool enabled);
diff --git a/libs/ui/tool/KisAsyncColorSamplerHelper.cpp b/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
index 39bb2e00b51..bfea94c4bbd 100644
--- a/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
+++ b/libs/ui/tool/KisAsyncColorSamplerHelper.cpp
@@ -68,8 +68,8 @@ struct KisAsyncColorSamplerHelper::Private
qreal circlePreviewThickness {0.12};
bool circlePreviewOutlineEnabled {true};
bool circlePreviewExtraCircles {true};
+ qreal circleZoomPreviewScale {2};
QRectF previewDocRect;
- QPointF docPoint;
QPainterPath cacheInnerPath;
QColor currentColor;
@@ -220,6 +220,7 @@ void KisAsyncColorSamplerHelper::activate(bool sampleCurrentLayer, bool pickFgCo
m_d->circlePreviewThickness = cfg.colorSamplerPreviewCircleThickness()/100.0; // saved in percentages
m_d->circlePreviewOutlineEnabled = cfg.colorSamplerPreviewCircleOutlineEnabled();
m_d->circlePreviewExtraCircles = cfg.colorSamplerPreviewCircleExtraCirclesEnabled();
+ m_d->circleZoomPreviewScale = cfg.colorSamplerZoomPreviewScale()/100.0; // saved in percentages
m_d->activationDelayTimer.start();
}
@@ -344,7 +345,6 @@ void KisAsyncColorSamplerHelper::endAction()
QRectF KisAsyncColorSamplerHelper::colorPreviewDocRect(const QPointF &docPoint)
{
- m_d->docPoint = docPoint;
if (!m_d->showPreview) return QRectF();
KisConfig cfg(true);
@@ -536,22 +536,68 @@ void KisAsyncColorSamplerHelper::paintCircle(QPainter &gc,
}
}
+ // When sampler leave the canvas, cache won't update so always need to clear the center
+ // TODO: Check why zoom still show after leaving canvas
+ cachePainter.setPen(Qt::NoPen);
+ cachePainter.setCompositionMode(QPainter::CompositionMode_Clear);
+ cachePainter.drawPath(tf.map(m_d->cacheInnerPath));
+
+ QRectF sampleDocRectF = m_d->previewDocRect;
+ sampleDocRectF.setHeight(sampleDocRectF.height() / m_d->circleZoomPreviewScale);
+ sampleDocRectF.setWidth(sampleDocRectF.width() / m_d->circleZoomPreviewScale);
+ sampleDocRectF.moveCenter(m_d->previewDocRect.center());
+ QRectF canvasSampleRectF = m_d->canvas->image()->documentToPixel(sampleDocRectF);
+
dbgUI << "View rect: " << viewRectF;
- QRectF docRectF = m_d->converter().viewToDocument(viewRectF);
- QRectF docSampleRectF = QRectF(m_d->docPoint.x() - docRectF.width()/4, m_d->docPoint.y() - docRectF.height()/4, docRectF.width()/2, docRectF.height()/2);
- QRectF canvasSampleRectF = m_d->canvas->image()->documentToPixel(docSampleRectF);
- dbgUI << "Doc point: " << m_d->docPoint;
- dbgUI << "Doc view rect: " << docRectF;
- dbgUI << "Canvas point: " << canvasSampleRectF.topLeft();
- // Copy a piece of canvas image with size = (cacheRect document size) / (zoom preview scale)
- QImage cacheCanvasImage = m_d->canvas->image()->convertToQImage(canvasSampleRectF.toRect(), nullptr);
+ dbgUI << "Preview doc rect: " << m_d->previewDocRect;
+ dbgUI << "Sample doc rect: " << sampleDocRectF;
+ dbgUI << "Canvas sample rect: " << canvasSampleRectF;
+ dbgUI << "Sample doc point: " << sampleDocRectF.center();
+
+ QImage cacheCanvasImage;
+ bool sampledRefImage = false;
+
+ // Check if doc coord is on canvas or reference image
+ KisDocument *doc = m_d->canvas->viewManager()->document();
+ if (doc) {
+ KisReferenceImagesLayerSP refLayer = doc->referenceImagesLayer();
+ if (refLayer) {
+ for(int i=0;i<refLayer->referenceImages().count();i++) {
+ KisReferenceImage *refImage = refLayer->referenceImages().at(i);
+ QPolygonF outline = refImage->outline().toFillPolygon().translated(refImage->position());
+ if (outline.containsPoint(sampleDocRectF.center(), Qt::OddEvenFill)) {
+ dbgUI << "Sampling on reference image no " << i;
+ // TODO: Figure out how to convert shape coordinate to pixel coordinate
+ // Just need to divide by scale. How to find the scale though
+ QImage image = refImage->getImage();
+ QRectF refRectF = refImage->documentToShape(sampleDocRectF);
+ dbgUI << "Shape coordinate: " << refRectF;
+ QPointF topLeft = refRectF.topLeft();
+ topLeft.setX(topLeft.x() * image.width());
+ topLeft.setY(topLeft.y() * image.height());
+ QPointF bottomRight = refRectF.bottomRight();
+ bottomRight.setX(bottomRight.x() * image.width());
+ bottomRight.setY(bottomRight.y() * image.height());
+
+ dbgUI << "Shape pixel coordinate: " << QRectF(topLeft, bottomRight);
+
+ cacheCanvasImage = refImage->getImage().copy(QRectF(topLeft, bottomRight).toRect());
+ sampledRefImage = true;
+ }
+ }
+ }
+ }
+
+ if (!sampledRefImage)
+ // Copy a piece of canvas image with size = (previewDocRect size) / (zoom preview scale)
+ cacheCanvasImage = m_d->canvas->image()->convertToQImage(canvasSampleRectF.toRect(), nullptr);
cachePainter.setClipPath(tf.map(m_d->cacheInnerPath));
cachePainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
- // QtDoc: Note: The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
+ // QtDoc: The image is scaled to fit the rectangle, if both the image and rectangle size disagree.
// Since the piece of canvas is (zoom preview scale) times smaller than cacheRect
- // Draw image will scale it up that many times, thus achieving the zoom effect
+ // drawImage will scale it up that many times, thus achieving the zoom effect
cachePainter.drawImage(cacheRect, cacheCanvasImage);
cachePainter.setClipPath(QPainterPath(), Qt::NoClip);