diff --git a/libs/image/kis_inpaint_mask.cpp b/libs/image/kis_inpaint_mask.cpp index 28f66d533b..d076cecfea 100644 --- a/libs/image/kis_inpaint_mask.cpp +++ b/libs/image/kis_inpaint_mask.cpp @@ -1,105 +1,64 @@ /* * Copyright (c) 2017 Eugene Ingerman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_inpaint_mask.h" #include "kis_debug.h" #include #include #include #include #include #include "kis_paint_device.h" #include "kis_painter.h" #include "kis_node_visitor.h" #include "kis_processing_visitor.h" KisInpaintMask::KisInpaintMask() : KisTransparencyMask() { } KisInpaintMask::KisInpaintMask(const KisInpaintMask& rhs) : KisTransparencyMask(rhs) { } KisInpaintMask::~KisInpaintMask() { } QRect KisInpaintMask::decorateRect(KisPaintDeviceSP &src, KisPaintDeviceSP &dst, const QRect & rc, PositionToFilthy maskPos) const { Q_UNUSED(maskPos); if (src != dst) { KisPainter::copyAreaOptimized(rc.topLeft(), src, dst, rc); src->fill(rc, KoColor(Qt::darkMagenta, src->colorSpace())); } return rc; } -QRect KisInpaintMask::extent() const -{ - return parent() ? parent()->extent() : QRect(); -} - -QRect KisInpaintMask::exactBounds() const -{ - return parent() ? parent()->exactBounds() : QRect(); -} -QRect KisInpaintMask::changeRect(const QRect &rect, PositionToFilthy pos) const -{ - /** - * Selection on transparency masks have no special meaning: - * They do crop both: change and need area - */ - return KisMask::changeRect(rect, pos); -} - -QRect KisInpaintMask::needRect(const QRect &rect, PositionToFilthy pos) const -{ - /** - * Selection on transparency masks have no special meaning: - * They do crop both: change and need area - */ - return KisMask::needRect(rect, pos); -} - -QIcon KisInpaintMask::icon() const -{ - return KisIconUtils::loadIcon("transparencyMask"); -} - -bool KisInpaintMask::accept(KisNodeVisitor &v) -{ - return v.visit(this); -} - -void KisInpaintMask::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter) -{ - return visitor.visit(this, undoAdapter); -} diff --git a/libs/image/kis_inpaint_mask.h b/libs/image/kis_inpaint_mask.h index 00cfe773a3..e686214ad9 100644 --- a/libs/image/kis_inpaint_mask.h +++ b/libs/image/kis_inpaint_mask.h @@ -1,58 +1,49 @@ /* * Copyright (c) 2017 Eugene Ingerman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_INPAINT_MASK_ #define _KIS_INPAINT_MASK_ #include "kis_types.h" #include "kis_transparency_mask.h" class QRect; /** * A inpaint mask is a single channel mask that works with inpaint operation to denote area affected by inpaint operation. * */ class KRITAIMAGE_EXPORT KisInpaintMask : public KisTransparencyMask { Q_OBJECT public: KisInpaintMask(); KisInpaintMask(const KisInpaintMask& rhs); virtual ~KisInpaintMask(); KisNodeSP clone() const { return KisNodeSP(new KisInpaintMask(*this)); } QRect decorateRect(KisPaintDeviceSP &src, KisPaintDeviceSP &dst, const QRect & rc, PositionToFilthy maskPos) const; - QIcon icon() const; - bool accept(KisNodeVisitor &v); - void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter); - - QRect extent() const; - QRect exactBounds() const; - - QRect changeRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; - QRect needRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; }; #endif //_KIS_INPAINT_MASK_ diff --git a/libs/ui/kis_mask_manager.cc b/libs/ui/kis_mask_manager.cc index 8540a72309..255dcef361 100644 --- a/libs/ui/kis_mask_manager.cc +++ b/libs/ui/kis_mask_manager.cc @@ -1,324 +1,324 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_mask_manager.h" #include #include #include #include #include #include #include #include "KisDocument.h" #include "KisViewManager.h" #include #include #include #include #include #include #include #include #include #include #include "dialogs/kis_dlg_adjustment_layer.h" #include "widgets/kis_mask_widgets.h" #include #include #include #include "dialogs/kis_dlg_adj_layer_props.h" #include #include #include #include #include "kis_node_commands_adapter.h" #include "commands/kis_selection_commands.h" #include "kis_iterator_ng.h" KisMaskManager::KisMaskManager(KisViewManager * view) : m_view(view) , m_imageView(0) , m_commandsAdapter(new KisNodeCommandsAdapter(m_view)) { } void KisMaskManager::setView(QPointerimageView) { m_imageView = imageView; } void KisMaskManager::setup(KActionCollection *actionCollection, KisActionManager *actionManager) { Q_UNUSED(actionCollection); Q_UNUSED(actionManager); } void KisMaskManager::updateGUI() { // XXX: enable/disable menu items according to whether there's a mask selected currently // XXX: disable the selection mask item if there's already a selection mask // YYY: doesn't KisAction do that already? } KisMaskSP KisMaskManager::activeMask() { if (m_imageView) { return m_imageView->currentMask(); } return 0; } KisPaintDeviceSP KisMaskManager::activeDevice() { KisMaskSP mask = activeMask(); return mask ? mask->paintDevice() : 0; } void KisMaskManager::activateMask(KisMaskSP mask) { Q_UNUSED(mask); } void KisMaskManager::masksUpdated() { m_view->updateGUI(); } void KisMaskManager::adjustMaskPosition(KisNodeSP node, KisNodeSP activeNode, bool avoidActiveNode, KisNodeSP &parent, KisNodeSP &above) { Q_ASSERT(node); Q_ASSERT(activeNode); if (!avoidActiveNode && activeNode->allowAsChild(node)) { parent = activeNode; above = activeNode->lastChild(); } else if (activeNode->parent() && activeNode->parent()->allowAsChild(node)) { parent = activeNode->parent(); above = activeNode; } else { KisNodeSP t = activeNode; while ((t = t->nextSibling())) { if (t->allowAsChild(node)) { parent = t; above = t->lastChild(); break; } } if (!t) { t = activeNode; while ((t = t->prevSibling())) { if (t->allowAsChild(node)) { parent = t; above = t->lastChild(); break; } } } if (!t && activeNode->parent()) { adjustMaskPosition(node, activeNode->parent(), true, parent, above); } else if (!t) { KisImageWSP image = m_view->image(); KisLayerSP layer = new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, image->colorSpace()); m_commandsAdapter->addNode(layer, activeNode, 0); parent = layer; above = 0; } } } void KisMaskManager::createMaskCommon(KisMaskSP mask, KisNodeSP activeNode, KisPaintDeviceSP copyFrom, const KUndo2MagicString& macroName, const QString &nodeType, const QString &nodeName, bool suppressSelection, bool avoidActiveNode, bool updateImage) { m_commandsAdapter->beginMacro(macroName); KisNodeSP parent; KisNodeSP above; adjustMaskPosition(mask, activeNode, avoidActiveNode, parent, above); KisLayerSP parentLayer = qobject_cast(parent.data()); Q_ASSERT(parentLayer); if (!suppressSelection) { if (copyFrom) { mask->initSelection(copyFrom, parentLayer); } else { mask->initSelection(m_view->selection(), parentLayer); } } //counting number of KisSelectionMask QList masks = parentLayer->childNodes(QStringList(nodeType),KoProperties()); int number = masks.count() + 1; mask->setName(nodeName + QString(" ") + QString::number(number)); m_commandsAdapter->addNode(mask, parentLayer, above, updateImage, updateImage); m_commandsAdapter->endMacro(); masksUpdated(); } void KisMaskManager::createSelectionMask(KisNodeSP activeNode, KisPaintDeviceSP copyFrom, bool avoidActiveNode) { KisSelectionMaskSP mask = new KisSelectionMask(m_view->image()); createMaskCommon(mask, activeNode, copyFrom, kundo2_i18n("Add Selection Mask"), "KisSelectionMask", i18n("Selection"), false, avoidActiveNode, false); mask->setActive(true); } void KisMaskManager::createTransparencyMask(KisNodeSP activeNode, KisPaintDeviceSP copyFrom, bool avoidActiveNode) { KisMaskSP mask = new KisTransparencyMask(); createMaskCommon(mask, activeNode, copyFrom, kundo2_i18n("Add Transparency Mask"), "KisTransparencyMask", i18n("Transparency Mask"), false, avoidActiveNode); } void KisMaskManager::createInpaintMask(KisNodeSP activeNode, KisPaintDeviceSP copyFrom, bool avoidActiveNode) { KisMaskSP mask = new KisInpaintMask(); - createMaskCommon(mask, activeNode, copyFrom, kundo2_i18n("Add Inpaint Mask"), "KisInpaintMask", i18n("Inpaint Mask"), false, avoidActiveNode); + createMaskCommon(mask, activeNode, copyFrom, kundo2_i18n("Add Inpaint Mask"), "KisInpaintMask", i18n("Inpaint Mask"), false, avoidActiveNode, false); } void KisMaskManager::createFilterMask(KisNodeSP activeNode, KisPaintDeviceSP copyFrom, bool quiet, bool avoidActiveNode) { KisFilterMaskSP mask = new KisFilterMask(); createMaskCommon(mask, activeNode, copyFrom, kundo2_i18n("Add Filter Mask"), "KisFilterMask", i18n("Filter Mask"), false, avoidActiveNode); /** * FIXME: We'll use layer's original for creation of a thumbnail. * Actually, we can't use it's projection as newly created mask * may be going to be inserted in the middle of the masks stack */ KisPaintDeviceSP originalDevice = mask->parent()->original(); KisDlgAdjustmentLayer dialog(mask, mask.data(), originalDevice, mask->name(), i18n("New Filter Mask"), m_view); // If we are supposed to not disturb the user, don't start asking them about things. if(quiet) { KisFilterConfigurationSP filter = KisFilterRegistry::instance()->values().first()->defaultConfiguration(); if (filter) { mask->setFilter(filter); mask->setName(mask->name()); } return; } if (dialog.exec() == QDialog::Accepted) { KisFilterConfigurationSP filter = dialog.filterConfiguration(); if (filter) { QString name = dialog.layerName(); mask->setFilter(filter); mask->setName(name); } } else { m_commandsAdapter->undoLastCommand(); } } void KisMaskManager::createEffectsMask(KisNodeSP activeNode) { KisFilterMaskSP mask = new KisFilterMask(); createMaskCommon(mask, activeNode, 0, kundo2_i18n("Add Effect Mask"), "KisEffectMask", i18n("Inpaint Mask"), false, false); mask->setImage(m_view->image()); } void KisMaskManager::createColorizeMask(KisNodeSP activeNode) { KisColorizeMaskSP mask = new KisColorizeMask(); createMaskCommon(mask, activeNode, 0, kundo2_i18n("Add Colorize Mask"), "KisColorizeMask", i18n("Colorize Mask"), true, false); mask->setImage(m_view->image()); mask->initializeCompositeOp(); delete mask->setColorSpace(mask->parent()->colorSpace()); } void KisMaskManager::createTransformMask(KisNodeSP activeNode) { KisTransformMaskSP mask = new KisTransformMask(); createMaskCommon(mask, activeNode, 0, kundo2_i18n("Add Transform Mask"), "KisTransformMask", i18n("Transform Mask"), true, false); } void KisMaskManager::maskProperties() { if (!activeMask()) return; if (activeMask()->inherits("KisFilterMask")) { KisFilterMask *mask = static_cast(activeMask().data()); KisLayerSP layer = qobject_cast(mask->parent().data()); if (! layer) return; KisPaintDeviceSP dev = layer->original(); if (!dev) { return; } KisDlgAdjLayerProps dlg(layer, mask, dev, m_view, mask->filter().data(), mask->name(), i18n("Filter Mask Properties"), m_view->mainWindow(), "dlgeffectmaskprops"); KisFilterConfigurationSP configBefore(mask->filter()); Q_ASSERT(configBefore); QString xmlBefore = configBefore->toXML(); if (dlg.exec() == QDialog::Accepted) { KisFilterConfigurationSP configAfter(dlg.filterConfiguration()); Q_ASSERT(configAfter); QString xmlAfter = configAfter->toXML(); mask->setName(dlg.layerName()); if(xmlBefore != xmlAfter) { KisChangeFilterCmd *cmd = new KisChangeFilterCmd(mask, configBefore->name(), xmlBefore, configAfter->name(), xmlAfter, false); // FIXME: check whether is needed cmd->redo(); m_view->undoAdapter()->addCommand(cmd); m_view->document()->setModified(true); } } else { KisFilterConfigurationSP configAfter(dlg.filterConfiguration()); Q_ASSERT(configAfter); QString xmlAfter = configAfter->toXML(); if(xmlBefore != xmlAfter) { mask->setFilter(KisFilterRegistry::instance()->cloneConfiguration(configBefore.data())); mask->setDirty(); } } } else { // Not much to show for transparency or selection masks? } } diff --git a/plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp b/plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp index b00b327ffa..05ace3c2fa 100644 --- a/plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp +++ b/plugins/tools/tool_smart_patch/kis_tool_smart_patch.cpp @@ -1,173 +1,189 @@ /* * Copyright (c) 2017 Eugene Ingerman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_smart_patch.h" #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "kis_cursor.h" #include "kis_config.h" #include "kundo2magicstring.h" #include "KoProperties.h" #include "kis_node_manager.h" #include "kis_tool_smart_patch_options_widget.h" - +#include "libs/image/kis_paint_device_debug_utils.h" struct KisToolSmartPatch::Private { bool activateMaskMode = false; + KisNodeSP maskNode = nullptr; + KisPaintDeviceSP maskDev = nullptr; }; KisToolSmartPatch::KisToolSmartPatch(KoCanvasBase * canvas) : KisToolFreehand(canvas, KisCursor::load("tool_freehand_cursor.png", 5, 5), kundo2_i18n("Smart Patch Stroke")), m_d(new Private) { setObjectName("tool_SmartPatch"); } KisToolSmartPatch::~KisToolSmartPatch() { } void KisToolSmartPatch::activate(ToolActivation activation, const QSet &shapes) { KisToolFreehand::activate(activation, shapes); } void KisToolSmartPatch::deactivate() { + if( !m_d->maskDev.isNull() ) + KIS_DUMP_DEVICE_2(m_d->maskDev, m_d->maskDev->extent(), "output", "/home/eugening/Projects/Out"); + KisToolFreehand::deactivate(); } void KisToolSmartPatch::resetCursorStyle() { KisToolFreehand::resetCursorStyle(); } bool KisToolSmartPatch::inpaintMaskActive() const { KisNodeSP node = currentNode(); - return node && node->inherits("KisFilterMask"); + return node && node->inherits("KisInpaintMask"); } bool KisToolSmartPatch::canCreateInpaintMask() const { KisNodeSP node = currentNode(); return node && node->inherits("KisLayer"); } void KisToolSmartPatch::activatePrimaryAction() { KisToolFreehand::activatePrimaryAction(); if (!inpaintMaskActive() && canCreateInpaintMask()) { //useCursor(KisCursor::handCursor()); m_d->activateMaskMode = true; setOutlineEnabled(true); } } void KisToolSmartPatch::deactivatePrimaryAction() { if (m_d->activateMaskMode) { m_d->activateMaskMode = false; setOutlineEnabled(true); resetCursorStyle(); } KisToolFreehand::deactivatePrimaryAction(); } void KisToolSmartPatch::beginPrimaryAction(KoPointerEvent *event) { if (m_d->activateMaskMode) { KisNodeSP node = currentNode(); if (!node) return; - KoProperties properties; - properties.setProperty("visible", true); - properties.setProperty("temporary", true); - properties.setProperty("smartpatch", true); - - QList masks = node->childNodes(QStringList("KisInpaintMask"), properties); - - if (!masks.isEmpty()) { + if (!m_d->maskNode.isNull()) { KisCanvas2 * kiscanvas = static_cast(canvas()); - KisViewManager* viewManager = kiscanvas->viewManager(); - viewManager->nodeManager()->slotNonUiActivatedNode(masks.first()); + viewManager->nodeManager()->slotNonUiActivatedNode(m_d->maskNode); } else { KisCanvas2 * kiscanvas = static_cast(canvas()); KisViewManager* viewManager = kiscanvas->viewManager(); viewManager->nodeManager()->createNode("KisInpaintMask", true); - KisNodeSP node = currentNode(); + m_d->maskNode = currentNode(); - if ( node ){ - node->setProperty("visible", true); - node->setProperty("temporary", true); - node->setProperty("smartpatch", true); + if ( m_d->maskNode ){ +// m_d->maskNode->setProperty("visible", false); +// m_d->maskNode->setProperty("temporary", true); + m_d->maskNode->setProperty("smartpatch", true); } - } } else { KisToolFreehand::beginPrimaryAction(event); } } void KisToolSmartPatch::continuePrimaryAction(KoPointerEvent *event) { if (m_d->activateMaskMode) return; KisToolFreehand::continuePrimaryAction(event); } + void KisToolSmartPatch::endPrimaryAction(KoPointerEvent *event) { - if (m_d->activateMaskMode) return; + if (m_d->activateMaskMode || m_d->maskNode.isNull()) return; + KisToolFreehand::endPrimaryAction(event); + + m_d->maskDev = new KisPaintDevice(m_d->maskNode->paintDevice()->colorSpace()); + m_d->maskDev->makeCloneFrom(m_d->maskNode->paintDevice(), m_d->maskNode->paintDevice()->extent()); + + qDebug() << "mask size: " << m_d->maskNode->paintDevice()->extent(); + qDebug() << "mask size0: " << m_d->maskNode->paintDevice()->exactBounds(); + qDebug() << "mask size1: " << m_d->maskDev->extent(); + qDebug() << "mask size2: " << m_d->maskDev->exactBounds(); + + //KIS_DUMP_DEVICE_2(m_d->maskDev, m_d->maskDev->extent(), "output", "/home/eugening/Projects/Out"); + + KisCanvas2 * kiscanvas = static_cast(canvas()); + + qDebug() << "image size: " << kiscanvas->currentImage()->size(); + + KisViewManager* viewManager = kiscanvas->viewManager(); + viewManager->nodeManager()->removeSingleNode(m_d->maskNode); + m_d->maskNode = nullptr; } QWidget * KisToolSmartPatch::createOptionWidget() { KisCanvas2 * kiscanvas = dynamic_cast(canvas()); QWidget *optionsWidget = new KisToolSmartPatchOptionsWidget(kiscanvas->viewManager()->resourceProvider(), 0); optionsWidget->setObjectName(toolId() + "option widget"); // // See https://bugs.kde.org/show_bug.cgi?id=316896 // QWidget *specialSpacer = new QWidget(optionsWidget); // specialSpacer->setObjectName("SpecialSpacer"); // specialSpacer->setFixedSize(0, 0); // optionsWidget->layout()->addWidget(specialSpacer); return optionsWidget; } diff --git a/plugins/tools/tool_smart_patch/kis_tool_smart_patch.h b/plugins/tools/tool_smart_patch/kis_tool_smart_patch.h index ebccd4f480..37f5d67f45 100644 --- a/plugins/tools/tool_smart_patch/kis_tool_smart_patch.h +++ b/plugins/tools/tool_smart_patch/kis_tool_smart_patch.h @@ -1,99 +1,100 @@ /* * Copyright (c) 2017 Eugene Ingerman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TOOL_SMART_PATCH_H_ #define KIS_TOOL_SMART_PATCH_H_ #include #include "kis_tool_freehand.h" #include "KoToolFactoryBase.h" #include #include #include #include #include #include class KActionCollection; class KoCanvasBase; class KisToolSmartPatch : public KisToolFreehand { Q_OBJECT public: KisToolSmartPatch(KoCanvasBase * canvas); virtual ~KisToolSmartPatch(); QWidget * createOptionWidget(); void activatePrimaryAction(); void deactivatePrimaryAction(); void beginPrimaryAction(KoPointerEvent *event); void continuePrimaryAction(KoPointerEvent *event); void endPrimaryAction(KoPointerEvent *event); protected Q_SLOTS: void resetCursorStyle(); public Q_SLOTS: virtual void activate(ToolActivation toolActivation, const QSet &shapes); void deactivate(); Q_SIGNALS: private: bool inpaintMaskActive() const; bool canCreateInpaintMask() const; private: struct Private; const QScopedPointer m_d; + }; class KisToolSmartPatchFactory : public KoToolFactoryBase { public: KisToolSmartPatchFactory() : KoToolFactoryBase("KritaShape/KisToolSmartPatch") { setToolTip(i18n("Smart Patch Tool")); // Temporarily setSection(TOOL_TYPE_FILL); setIconName(koIconNameCStr("krita_tool_smart_patch")); //setShortcut(QKeySequence(Qt::Key_Shift + Qt::Key_B)); setPriority(4); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); } virtual ~KisToolSmartPatchFactory() {} virtual KoToolBase * createTool(KoCanvasBase *canvas) { return new KisToolSmartPatch(canvas); } }; #endif // KIS_TOOL_SMART_PATCH_H_