diff --git a/libs/image/KisSelectionTags.h b/libs/image/KisSelectionTags.h
--- a/libs/image/KisSelectionTags.h
+++ b/libs/image/KisSelectionTags.h
@@ -30,6 +30,7 @@
SELECTION_ADD,
SELECTION_SUBTRACT,
SELECTION_INTERSECT,
+ SELECTION_EXCLUDE,
SELECTION_DEFAULT
};
diff --git a/libs/image/kis_pixel_selection.h b/libs/image/kis_pixel_selection.h
--- a/libs/image/kis_pixel_selection.h
+++ b/libs/image/kis_pixel_selection.h
@@ -153,6 +153,11 @@
*/
void intersectSelection(KisPixelSelectionSP selection);
+ /**
+ * Exclude a selection
+ */
+ void excludeSelection(KisPixelSelectionSP selection);
+
private:
// We don't want these methods to be used on selections:
using KisPaintDevice::extent;
diff --git a/libs/image/kis_pixel_selection.cpp b/libs/image/kis_pixel_selection.cpp
--- a/libs/image/kis_pixel_selection.cpp
+++ b/libs/image/kis_pixel_selection.cpp
@@ -150,6 +150,9 @@
case SELECTION_INTERSECT:
intersectSelection(selection);
break;
+ case SELECTION_EXCLUDE:
+ excludeSelection(selection);
+ break;
default:
break;
}
@@ -255,6 +258,35 @@
m_d->invalidateThumbnailImage();
}
+void KisPixelSelection::excludeSelection(KisPixelSelectionSP selection)
+{
+ QRect r = selection->selectedRect();
+ if (r.isEmpty()) return;
+
+
+ KisHLineIteratorSP dst = createHLineIteratorNG(r.x(), r.y(), r.width());
+ KisHLineConstIteratorSP src = selection->createHLineConstIteratorNG(r.x(), r.y(), r.width());
+ for (int i = 0; i < r.height(); ++i) {
+ do {
+ if (*dst->rawData() - *src->oldRawData() > MIN_SELECTED)
+ *dst->rawData() = *dst->rawData() - *src->oldRawData();
+ else
+ *dst->rawData() = abs(*dst->rawData() - *src->oldRawData());
+
+ } while (src->nextPixel() && dst->nextPixel());
+ dst->nextRow();
+ src->nextRow();
+ }
+
+ m_d->outlineCacheValid &= selection->outlineCacheValid();
+
+ if (m_d->outlineCacheValid) {
+ m_d->outlineCache += selection->outlineCache() - (m_d->outlineCache &= selection->outlineCache());
+ }
+
+ m_d->invalidateThumbnailImage();
+}
+
void KisPixelSelection::clear(const QRect & r)
{
if (*defaultPixel().data() != MIN_SELECTED) {
diff --git a/libs/libkis/Selection.h b/libs/libkis/Selection.h
--- a/libs/libkis/Selection.h
+++ b/libs/libkis/Selection.h
@@ -196,6 +196,11 @@
*/
void intersect(Selection *selection);
+ /**
+ * Exclude the given selection with this selection.
+ */
+ void exclude(Selection *selection);
+
/**
* @brief pixelData reads the given rectangle from the Selection's mask and returns it as a
* byte array. The pixel data starts top-left, and is ordered row-first.
diff --git a/libs/libkis/Selection.cpp b/libs/libkis/Selection.cpp
--- a/libs/libkis/Selection.cpp
+++ b/libs/libkis/Selection.cpp
@@ -293,6 +293,12 @@
d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_INTERSECT);
}
+void Selection::exclude(Selection *selection)
+{
+ if (!d->selection) return;
+ d->selection->pixelSelection()->applySelection(selection->selection()->pixelSelection(), SELECTION_EXCLUDE);
+}
+
QByteArray Selection::pixelData(int x, int y, int w, int h) const
{
diff --git a/libs/libqml/qml/panels/SelectPanel.qml b/libs/libqml/qml/panels/SelectPanel.qml
--- a/libs/libqml/qml/panels/SelectPanel.qml
+++ b/libs/libqml/qml/panels/SelectPanel.qml
@@ -124,8 +124,8 @@
image: Settings.theme.icon("select-intersect");
width: Constants.ToolbarButtonSize * 0.8;
height: width;
- checked: (toolManager.currentTool && toolManager.currentTool.selectionAction === 3) ? true : false;
- onClicked: if (toolManager.currentTool && toolManager.currentTool.selectionAction !== undefined) toolManager.currentTool.selectionAction = 3;
+ checked: (toolManager.currentTool && toolManager.currentTool.selectionAction === 4) ? true : false;
+ onClicked: if (toolManager.currentTool && toolManager.currentTool.selectionAction !== undefined) toolManager.currentTool.selectionAction = 4;
}
Button {
id: selectAdd;
@@ -145,6 +145,15 @@
checked: (toolManager.currentTool && toolManager.currentTool.selectionAction === 2) ? true : false;
onClicked: if (toolManager.currentTool && toolManager.currentTool.selectionAction !== undefined) toolManager.currentTool.selectionAction = 2;
}
+ Button {
+ id: selectExclude;
+ anchors.left: selectExclude.right;
+ image: Settings.theme.icon("select-exclude");
+ width: Constants.ToolbarButtonSize * 0.8;
+ height: width;
+ checked: (toolManager.currentTool && toolManager.currentTool.selectionAction === 3) ? true : false;
+ onClicked: if (toolManager.currentTool && toolManager.currentTool.selectionAction !== undefined) toolManager.currentTool.selectionAction = 3;
+ }
}
Item {
width: childrenRect.width;
diff --git a/libs/ui/forms/wdgselectionoptions.ui b/libs/ui/forms/wdgselectionoptions.ui
--- a/libs/ui/forms/wdgselectionoptions.ui
+++ b/libs/ui/forms/wdgselectionoptions.ui
@@ -6,35 +6,33 @@
0
0
- 271
- 106
+ 652
+ 257
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
+
-
0
-
-
-
+
-
+
+
+ CrossCursor
+
+
+ Mode:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
- Intersect
+ Subtract (Shortcut S)
...
@@ -63,10 +61,10 @@
- -
-
+
-
+
- Replace (Shortcut R)
+ Add (Shortcut A)
...
@@ -74,18 +72,15 @@
true
-
- true
-
false
- -
-
+
-
+
- Add (Shortcut A)
+ Pixel Selection
...
@@ -93,38 +88,34 @@
true
+
+ true
+
false
- -
-
-
- CrossCursor
+
-
+
+
+ Intersect
- Mode:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+ ...
-
-
- -
-
-
- Action:
+
+ true
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+ false
- -
-
+
-
+
- Pixel Selection
+ Replace (Shortcut R)
...
@@ -140,10 +131,20 @@
- -
-
+
-
+
+
+ Action:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
- Subtract (Shortcut S)
+ Exclude
...
@@ -158,7 +159,7 @@
- -
+
-
Qt::Horizontal
diff --git a/libs/ui/kis_selection_manager.cc b/libs/ui/kis_selection_manager.cc
--- a/libs/ui/kis_selection_manager.cc
+++ b/libs/ui/kis_selection_manager.cc
@@ -650,6 +650,9 @@
case SELECTION_INTERSECT:
actionName = kundo2_i18n("Select Opaque (Intersect)");
break;
+ case SELECTION_EXCLUDE:
+ actionName = kundo2_i18n("Select Opaque (Exclude)");
+ break;
default:
actionName = kundo2_i18n("Select Opaque");
break;
diff --git a/libs/ui/tool/kis_selection_tool_config_widget_helper.cpp b/libs/ui/tool/kis_selection_tool_config_widget_helper.cpp
--- a/libs/ui/tool/kis_selection_tool_config_widget_helper.cpp
+++ b/libs/ui/tool/kis_selection_tool_config_widget_helper.cpp
@@ -59,6 +59,8 @@
this, &KisSelectionToolConfigWidgetHelper::slotGlobalActionChanged);
connect(m_resourceProvider, &KisCanvasResourceProvider::sigSelectionModeChanged,
this, &KisSelectionToolConfigWidgetHelper::slotGlobalModeChanged);
+ connect(m_resourceProvider, &KisCanvasResourceProvider::sigSelectionModeChanged,
+ this, &KisSelectionToolConfigWidgetHelper::slotGlobalModeChanged);
m_optionsWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
m_optionsWidget->adjustSize();
@@ -81,7 +83,7 @@
void KisSelectionToolConfigWidgetHelper::slotWidgetActionChanged(int action)
{
- if (action >= SELECTION_REPLACE && action <= SELECTION_INTERSECT) {
+ if (action >= SELECTION_REPLACE && action <= SELECTION_EXCLUDE) {
m_optionsWidget->setAction(action);
m_resourceProvider->setSelectionAction(action);
emit selectionActionChanged(action);
@@ -124,6 +126,9 @@
case Qt::Key_T:
slotWidgetActionChanged(SELECTION_INTERSECT);
break;
+ case Qt::Key_E:
+ slotWidgetActionChanged(SELECTION_EXCLUDE);
+ break;
default:
event->ignore();
}
diff --git a/libs/ui/tool/kis_selection_tool_helper.cpp b/libs/ui/tool/kis_selection_tool_helper.cpp
--- a/libs/ui/tool/kis_selection_tool_helper.cpp
+++ b/libs/ui/tool/kis_selection_tool_helper.cpp
@@ -105,7 +105,7 @@
KisSelectionTransaction transaction(pixelSelection);
- if (!hasSelection && m_action == SELECTION_SUBTRACT) {
+ if (!hasSelection && m_action == SELECTION_EXCLUDE) {
pixelSelection->invert();
}
diff --git a/libs/ui/widgets/kis_selection_options.cc b/libs/ui/widgets/kis_selection_options.cc
--- a/libs/ui/widgets/kis_selection_options.cc
+++ b/libs/ui/widgets/kis_selection_options.cc
@@ -53,6 +53,7 @@
m_action->addButton(m_page->subtract, SELECTION_SUBTRACT);
m_action->addButton(m_page->replace, SELECTION_REPLACE);
m_action->addButton(m_page->intersect, SELECTION_INTERSECT);
+ m_action->addButton(m_page->exclude, SELECTION_EXCLUDE);
m_page->pixel->setGroupPosition(KoGroupButton::GroupLeft);
m_page->shape->setGroupPosition(KoGroupButton::GroupRight);
@@ -63,10 +64,12 @@
m_page->subtract->setGroupPosition(KoGroupButton::GroupRight);
m_page->replace->setGroupPosition(KoGroupButton::GroupLeft);
m_page->intersect->setGroupPosition(KoGroupButton::GroupCenter);
+ m_page->exclude->setGroupPosition(KoGroupButton::GroupRight);
m_page->add->setIcon(KisIconUtils::loadIcon("selection_add"));
m_page->subtract->setIcon(KisIconUtils::loadIcon("selection_subtract"));
m_page->replace->setIcon(KisIconUtils::loadIcon("selection_replace"));
m_page->intersect->setIcon(KisIconUtils::loadIcon("selection_intersect"));
+ m_page->exclude->setIcon(KisIconUtils::loadIcon("selection_exclude"));
connect(m_mode, SIGNAL(buttonClicked(int)), this, SIGNAL(modeChanged(int)));
connect(m_action, SIGNAL(buttonClicked(int)), this, SIGNAL(actionChanged(int)));
@@ -105,6 +108,7 @@
m_page->subtract->setVisible(isPixelSelection);
m_page->replace->setVisible(isPixelSelection);
m_page->intersect->setVisible(isPixelSelection);
+ m_page->exclude->setVisible(isPixelSelection);
m_page->chkAntiAliasing->setVisible(isPixelSelection);
}
diff --git a/plugins/extensions/pykrita/sip/krita/Selection.sip b/plugins/extensions/pykrita/sip/krita/Selection.sip
--- a/plugins/extensions/pykrita/sip/krita/Selection.sip
+++ b/plugins/extensions/pykrita/sip/krita/Selection.sip
@@ -35,6 +35,7 @@
void add(Selection *selection);
void subtract(Selection *selection);
void intersect(Selection *selection);
+ void exclude(Selection *selection);
QByteArray pixelData(int x, int y, int w, int h) const;
void setPixelData(QByteArray value, int x, int y, int w, int h);
private:
diff --git a/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc b/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc
--- a/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc
+++ b/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc
@@ -59,6 +59,7 @@
Qt::KeyboardModifiers intersectModifiers;
Qt::KeyboardModifiers addModifiers;
Qt::KeyboardModifiers subtractModifiers;
+ Qt::KeyboardModifiers excludeModifiers;
};
@@ -91,13 +92,15 @@
{
KisConfig cfg(true);
if (!cfg.switchSelectionCtrlAlt()) {
- replaceModifiers = Qt::ControlModifier;
- intersectModifiers = (Qt::KeyboardModifiers)(Qt::AltModifier | Qt::ShiftModifier);
- subtractModifiers = Qt::AltModifier;
+ replaceModifiers = Qt::AltModifier;
+ intersectModifiers = (Qt::KeyboardModifiers)(Qt::AltModifier | Qt::ControlModifier);
+ subtractModifiers = Qt::ControlModifier;
+ excludeModifiers = (Qt::KeyboardModifiers)(Qt::AltModifier | Qt::ShiftModifier);
} else {
replaceModifiers = Qt::AltModifier;
intersectModifiers = (Qt::KeyboardModifiers)(Qt::ControlModifier | Qt::ShiftModifier);
- subtractModifiers = Qt::ControlModifier;
+ subtractModifiers = Qt::AltModifier;
+ excludeModifiers = (Qt::KeyboardModifiers)((Qt::ControlModifier | Qt::ShiftModifier)|Qt::AltModifier);
}
addModifiers = Qt::ShiftModifier;
@@ -119,6 +122,9 @@
newAction = SELECTION_ADD;
} else if (m == subtractModifiers) {
newAction = SELECTION_SUBTRACT;
+ } else if (m == excludeModifiers) {
+ newAction = SELECTION_EXCLUDE;
}
+
return newAction;
}