Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_tool_smart_patch.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2017 Eugene Ingerman
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include "QApplication"
10#include "QPainterPath"
11
12#include <klocalizedstring.h>
13#include <KoColor.h>
14#include <KisViewManager.h>
15#include "kis_canvas2.h"
16#include "kis_cursor.h"
17#include "kis_painter.h"
18#include "kis_paintop_preset.h"
19
20#include "kundo2magicstring.h"
21#include "kundo2stack.h"
23#include "kis_transaction.h"
24
26#include "kis_datamanager.h"
27
31
34
35#include "kis_paint_layer.h"
36#include "kis_algebra_2d.h"
38
39QRect patchImage(KisPaintDeviceSP imageDev, KisPaintDeviceSP maskDev, int radius, int accuracy, KisSelectionSP selection);
40
57
61 float brushRadius = 50.; //initial default. actually read from ui.
64 QPainterPath brushOutline;
65};
66
67
69 : KisToolPaint(canvas, KisCursor::blankCursor()),
70 m_d(new Private)
71{
73 setObjectName("tool_SmartPatch");
74 m_d->maskDev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8());
75 m_d->maskDevPainter.begin( m_d->maskDev );
76
77 m_d->maskDevPainter.setPaintColor(KoColor(Qt::magenta, m_d->maskDev->colorSpace()));
78 m_d->maskDevPainter.setBackgroundColor(KoColor(Qt::white, m_d->maskDev->colorSpace()));
79 m_d->maskDevPainter.setFillStyle( KisPainter::FillStyleForegroundColor );
80}
81
83{
84 m_d->optionsWidget = nullptr;
85 m_d->maskDevPainter.end();
86}
87
88void KisToolSmartPatch::activate(const QSet<KoShape*> &shapes)
89{
91}
92
97
102
108
114
116{
117 KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2 *>(canvas());
118 KIS_ASSERT(canvas2);
119 const KisCoordinatesConverter *converter = canvas2->coordinatesConverter();
120
121 QPointF imagePos = currentImage()->documentToPixel(event->point);
122 QPainterPath currentBrushOutline = brushOutline().translated(KisAlgebra2D::alignForZoom(imagePos, converter->effectivePhysicalZoom()));
123 m_d->maskDevPainter.fillPainterPath(currentBrushOutline);
124
125 canvas()->updateCanvas(currentImage()->pixelToDocument(m_d->maskDev->exactBounds()));
126}
127
129{
130 //we can only apply inpaint operation to paint layer
131 if ( currentNode().isNull() || !currentNode()->inherits("KisPaintLayer") || nodePaintAbility()!=NodePaintAbility::PAINT ) {
132 KisCanvas2 * kiscanvas = static_cast<KisCanvas2*>(canvas());
133 kiscanvas->viewManager()->
134 showFloatingMessage(
135 i18n("Select a paint layer to use this tool"),
136 QIcon(), 2000, KisFloatingMessage::Medium, Qt::AlignCenter);
137 event->ignore();
138 return;
139 }
140
141 addMaskPath(event);
144}
145
152
154{
156 addMaskPath(event);
159
160 KisCursorOverrideLock cursorLock(KisCursor::waitCursor());
161
162 int accuracy = 50; //default accuracy - middle value
163 int patchRadius = 4; //default radius, which works well for most cases tested
164
165 if (m_d->optionsWidget) {
166 accuracy = m_d->optionsWidget->getAccuracy();
167 patchRadius = m_d->optionsWidget->getPatchRadius();
168 }
169
170 KisResourcesSnapshotSP resources =
171 new KisResourcesSnapshot(image(), currentNode(), this->canvas()->resourceManager());
172
174 kundo2_i18n("Smart Patch"));
175
176 //actual inpaint operation. filling in areas masked by user
178 currentNode()->paintDevice(),
179 accuracy, patchRadius,
180 resources->activeSelection()),
182
183 applicator.end();
184 image()->waitForDone();
185
186 m_d->maskDev->clear();
187}
188
190{
191 const qreal diameter = m_d->brushRadius;
192 QPainterPath outline;
193 outline.addEllipse(QPointF(0,0), -0.5 * diameter, -0.5 * diameter );
194 return outline;
195}
196
197QPainterPath KisToolSmartPatch::getBrushOutlinePath(const QPointF &documentPos,
198 const KoPointerEvent *event)
199{
200 Q_UNUSED(event);
201
202 QPointF imagePos = currentImage()->documentToPixel(documentPos);
203 QPainterPath path = brushOutline();
204
205 KisCanvas2 *canvas2 = dynamic_cast<KisCanvas2 *>(canvas());
206 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(canvas2, QPainterPath());
207 const KisCoordinatesConverter *converter = canvas2->coordinatesConverter();
208
209 return path.translated(KisAlgebra2D::alignForZoom(imagePos, converter->effectivePhysicalZoom()));
210}
211
212void KisToolSmartPatch::requestUpdateOutline(const QPointF &outlineDocPoint, const KoPointerEvent *event)
213{
214 static QPointF lastDocPoint = QPointF(0,0);
215 if( event )
216 lastDocPoint=outlineDocPoint;
217
218 m_d->brushRadius = currentPaintOpPreset()->settings()->paintOpSize();
219 m_d->brushOutline = getBrushOutlinePath(lastDocPoint, event);
220
221 QRectF outlinePixelRect = m_d->brushOutline.boundingRect();
222 QRectF outlineDocRect = currentImage()->pixelToDocument(outlinePixelRect);
223
224 // This adjusted call is needed as we paint with a 3 pixel wide brush and the pen is outside the bounds of the path
225 // Pen uses view coordinates so we have to zoom the document value to match 2 pixel in view coordinates
226 // See BUG 275829
227 qreal zoomX;
228 qreal zoomY;
229 canvas()->viewConverter()->zoom(&zoomX, &zoomY);
230 qreal xoffset = 2.0/zoomX;
231 qreal yoffset = 2.0/zoomY;
232
233 if (!outlineDocRect.isEmpty()) {
234 outlineDocRect.adjust(-xoffset,-yoffset,xoffset,yoffset);
235 }
236
237 if (!m_d->oldOutlineRect.isEmpty()) {
238 canvas()->updateCanvas(m_d->oldOutlineRect);
239 }
240
241 if (!outlineDocRect.isEmpty()) {
242 canvas()->updateCanvas(outlineDocRect);
243 }
244
245 m_d->oldOutlineRect = outlineDocRect;
246}
247
248void KisToolSmartPatch::paint(QPainter &painter, const KoViewConverter &converter)
249{
250 Q_UNUSED(converter);
251
252 painter.save();
253 QPainterPath path = pixelToView(m_d->brushOutline);
254 paintToolOutline(&painter, path);
255 painter.restore();
256
257 painter.save();
258 painter.setBrush(Qt::magenta);
259 KisCanvas2 * kiscanvas = dynamic_cast<KisCanvas2*>(canvas());
260 QImage img = kiscanvas->displayColorConverter()->convertImageToDisplayColorSpace(m_d->maskDev);
261 if( !img.size().isEmpty() ){
262
263 painter.drawImage(pixelToView(m_d->maskDev->exactBounds()), img);
264 }
265 painter.restore();
266}
267
269{
270 KisCanvas2 * kiscanvas = dynamic_cast<KisCanvas2*>(canvas());
271 KIS_ASSERT(kiscanvas);
272
273 m_d->optionsWidget = new KisToolSmartPatchOptionsWidget(kiscanvas->viewManager()->canvasResourceProvider(), 0);
274 m_d->optionsWidget->setObjectName(toolId() + "option widget");
275
276 return m_d->optionsWidget;
277}
278
QVector< KisImageSignalType > KisImageSignalVector
KisDisplayColorConverter displayColorConverter
KisCoordinatesConverter * coordinatesConverter
void updateCanvas(const QRectF &rc) override
KisViewManager * viewManager() const
const KoViewConverter * viewConverter() const override
static QCursor waitCursor()
Definition kis_cursor.cc:54
QImage convertImageToDisplayColorSpace(KisPaintDeviceSP srcDevice, QRect source=QRect(), bool applyOcio=false) const
convertImageToDisplayColorSpace Same as convertColorToDisplayColorSpace, but then for a KisPaintDevic...
void waitForDone()
QPointF documentToPixel(const QPointF &documentCoord) const
QPointF pixelToDocument(const QPointF &pixelCoord) const
@ FillStyleForegroundColor
static KisPaintDeviceSP convertToAlphaAsAlpha(KisPaintDeviceSP src)
void applyCommand(KUndo2Command *command, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
The KisResourcesSnapshot class takes a snapshot of the various resources like colors and settings use...
KisSelectionSP activeSelection() const
void setSupportOutline(bool supportOutline)
void deactivate() override
void activate(const QSet< KoShape * > &shapes) override
void setOutlineVisible(bool visible)
void deactivatePrimaryAction() override
void setMode(ToolMode mode) override
void activatePrimaryAction() override
InpaintCommand(KisPaintDeviceSP maskDev, KisPaintDeviceSP imageDev, int accuracy, int patchRadius, KisSelectionSP selection)
void deactivatePrimaryAction() override
QPainterPath getBrushOutlinePath(const QPointF &documentPos, const KoPointerEvent *event)
void beginPrimaryAction(KoPointerEvent *event) override
void paint(QPainter &painter, const KoViewConverter &converter) override
QWidget * createOptionWidget() override
const QScopedPointer< Private > m_d
void activate(const QSet< KoShape * > &shapes) override
void endPrimaryAction(KoPointerEvent *event) override
void continuePrimaryAction(KoPointerEvent *event) override
void addMaskPath(KoPointerEvent *event)
KisToolSmartPatch(KoCanvasBase *canvas)
void resetCursorStyle() override
void requestUpdateOutline(const QPointF &outlineDocPoint, const KoPointerEvent *event) override
void activatePrimaryAction() override
KUndo2Command * endAndTake()
KisCanvasResourceProvider * canvasResourceProvider()
QPointF point
The point in document coordinates.
Q_INVOKABLE QString toolId() const
virtual KoToolSelection * selection()
virtual void zoom(qreal *zoomX, qreal *zoomY) const
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
QRect patchImage(const KisPaintDeviceSP imageDev, const KisPaintDeviceSP maskDev, int patchRadius, int accuracy, KisSelectionSP selection)
#define CHECK_MODE_SANITY_OR_RETURN(_mode)
Definition kis_tool.h:27
QRect patchImage(KisPaintDeviceSP imageDev, KisPaintDeviceSP maskDev, int radius, int accuracy, KisSelectionSP selection)
KUndo2MagicString kundo2_i18n(const char *text)
QPointF alignForZoom(const QPointF &pt, qreal zoom)
KisToolSmartPatchOptionsWidget * optionsWidget
KisImageWSP currentImage()
Definition kis_tool.cc:393
KisTool::NodePaintAbility nodePaintAbility()
Definition kis_tool.cc:539
virtual void resetCursorStyle()
Definition kis_tool.cc:613
virtual void beginPrimaryAction(KoPointerEvent *event)
Definition kis_tool.cc:431
KisPaintOpPresetSP currentPaintOpPreset()
Definition kis_tool.cc:359
QPointF pixelToView(const QPoint &pixelCoord) const
Definition kis_tool.cc:269
KisNodeSP currentNode() const
Definition kis_tool.cc:370
virtual void endPrimaryAction(KoPointerEvent *event)
Definition kis_tool.cc:446
virtual void continuePrimaryAction(KoPointerEvent *event)
Definition kis_tool.cc:441
void paintToolOutline(QPainter *painter, const KisOptimizedBrushOutline &path)
Definition kis_tool.cc:589
KisImageWSP image() const
Definition kis_tool.cc:332
@ PAINT_MODE
Definition kis_tool.h:300
@ HOVER_MODE
Definition kis_tool.h:299
static KoColorSpaceRegistry * instance()
KisCanvas2 * canvas