Git commit 904af511be01bce2cc47e423e93fbb7e74f87e46 by Grigory Tantsevov. Committed on 31/08/2017 at 20:40. Pushed by tantsevov into branch 'tantsevov/T6224-watercolor'. Added gravity support. Fixed stroke finishing when close program bug. M +8 -3 libs/ui/tool/kis_tool_freehand.cc M +3 -0 libs/ui/tool/kis_tool_freehand.h M +7 -1 libs/ui/tool/kis_tool_freehand_helper.cpp M +0 -6 libs/ui/tool/kis_tool_paint.cc M +1 -1 libs/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp M +0 -9 plugins/paintops/watercolor/kis_base_splats_plane.cpp M +0 -4 plugins/paintops/watercolor/kis_base_splats_plane.h M +4 -5 plugins/paintops/watercolor/kis_fixed_splats_plane.cpp M +11 -6 plugins/paintops/watercolor/kis_splat.cpp M +7 -2 plugins/paintops/watercolor/kis_splat.h M +25 -18 plugins/paintops/watercolor/kis_splat_generator_strategy.cpp M +12 -6 plugins/paintops/watercolor/kis_splat_generator_strategy.h M +5 -3 plugins/paintops/watercolor/kis_watercolor_paintop.cpp M +16 -0 plugins/paintops/watercolor/kis_watercolor_paintop_settings.= cpp M +2 -0 plugins/paintops/watercolor/kis_watercolor_paintop_settings.h https://commits.kde.org/krita/904af511be01bce2cc47e423e93fbb7e74f87e46 diff --git a/libs/ui/tool/kis_tool_freehand.cc b/libs/ui/tool/kis_tool_free= hand.cc index 5d3b840b766..86b6d109d2a 100644 --- a/libs/ui/tool/kis_tool_freehand.cc +++ b/libs/ui/tool/kis_tool_freehand.cc @@ -183,12 +183,19 @@ void KisToolFreehand::deactivate() KisToolPaint::deactivate(); } = +void KisToolFreehand::requestStrokeEnd() +{ + if (!m_needEndContinuedStroke && m_helper->isRunning()) { + m_needEndContinuedStroke =3D true; + endStroke(); + } +} + void KisToolFreehand::initStroke(KoPointerEvent *event) { if (m_helper->isRunning()) { if (m_needEndContinuedStroke) m_needEndContinuedStroke =3D false; - qDebug() << "Inited part of continued stroke\n"; m_helper->initPaintInContinuedStroke(event, canvas()->resourceManager(), image(), @@ -218,11 +225,9 @@ void KisToolFreehand::doStroke(KoPointerEvent *event) void KisToolFreehand::endStroke() { if (currentPaintOpPreset()->settings()->needsContinuedStroke() && !m_n= eedEndContinuedStroke) { - qDebug() << "Finished part of continued stroke\n" << ppVar(m_n= eedEndContinuedStroke); m_helper->endPaintInContinuedStroke(); m_updateTimer.start(100); } else { - qDebug() << "Stroke finished finaly\n" << ppVar(m_needEndContinued= Stroke); m_helper->endPaint(); if (m_updateTimer.isActive()) m_updateTimer.stop(); diff --git a/libs/ui/tool/kis_tool_freehand.h b/libs/ui/tool/kis_tool_freeh= and.h index f09b1c270a9..d69e925502e 100644 --- a/libs/ui/tool/kis_tool_freehand.h +++ b/libs/ui/tool/kis_tool_freehand.h @@ -55,6 +55,9 @@ public Q_SLOTS: void activate(ToolActivation toolActivation, const QSet &sha= pes) override; void deactivate() override; = +public Q_SLOTS: + void requestStrokeEnd() override; + protected: bool tryPickByPaintOp(KoPointerEvent *event, AlternateAction action); = diff --git a/libs/ui/tool/kis_tool_freehand_helper.cpp b/libs/ui/tool/kis_t= ool_freehand_helper.cpp index a40a75f93a2..9b6da46ed2b 100644 --- a/libs/ui/tool/kis_tool_freehand_helper.cpp +++ b/libs/ui/tool/kis_tool_freehand_helper.cpp @@ -104,6 +104,8 @@ struct KisToolFreehandHelper::Private int canvasRotation; bool canvasMirroredH; = + bool strokeNotFinished; + qreal effectiveSmoothnessDistance() const; }; = @@ -134,6 +136,8 @@ KisToolFreehandHelper::KisToolFreehandHelper(KisPaintin= gInformationBuilder *info [this]() { emit requestExplicitUpdateOutline(); }); + + m_d->strokeNotFinished =3D false; } = KisToolFreehandHelper::~KisToolFreehandHelper() @@ -164,7 +168,7 @@ QPainterPath KisToolFreehandHelper::paintOpOutline(cons= t QPointF &savedCursorPos info.setCanvasHorizontalMirrorState( m_d->canvasMirroredH ); KisDistanceInformation distanceInfo(prevPoint, 0, startAngle); = - if (!m_d->painterInfos.isEmpty()) { + if (!m_d->painterInfos.isEmpty() && !m_d->strokeNotFinished) { settings =3D m_d->resources->currentPaintOpPreset()->settings(); if (m_d->stabilizerDelayedPaintHelper.running() && m_d->stabilizerDelayedPaintHelper.hasLastPaintInformation(= )) { @@ -602,6 +606,7 @@ void KisToolFreehandHelper::paint(KisPaintInformation &= info) = void KisToolFreehandHelper::endPaint() { + m_d->strokeNotFinished =3D false; if (!m_d->hasPaintAtLeastOnce) { paintAt(m_d->previousPaintInformation); } else if (m_d->smoothingOptions->smoothingType() !=3D KisSmoothingOpt= ions::NO_SMOOTHING) { @@ -668,6 +673,7 @@ void KisToolFreehandHelper::initPaintInContinuedStroke(= KoPointerEvent *event, = void KisToolFreehandHelper::endPaintInContinuedStroke() { + m_d->strokeNotFinished =3D true; if (!m_d->hasPaintAtLeastOnce) { paintAt(m_d->previousPaintInformation); } diff --git a/libs/ui/tool/kis_tool_paint.cc b/libs/ui/tool/kis_tool_paint.cc index c14f3515ea1..ba1d3409189 100644 --- a/libs/ui/tool/kis_tool_paint.cc +++ b/libs/ui/tool/kis_tool_paint.cc @@ -686,9 +686,6 @@ QRectF KisToolPaint::colorPreviewDocRect(const QPointF = &outlineDocPoint) = void KisToolPaint::requestUpdateOutline(const QPointF &outlineDocPoint, co= nst KoPointerEvent *event) { - ENTER_FUNCTION() << ppVar(outlineDocPoint) << ppVar(m_supportOutline); - - if (!m_supportOutline) return; = KisConfig cfg; @@ -717,7 +714,6 @@ void KisToolPaint::requestUpdateOutline(const QPointF &= outlineDocPoint, const Ko = m_outlineDocPoint =3D outlineDocPoint; m_currentOutline =3D getOutlinePath(m_outlineDocPoint, event, outlineM= ode); - QRectF outlinePixelRect =3D m_currentOutline.boundingRect(); QRectF outlineDocRect =3D currentImage()->pixelToDocument(outlinePixel= Rect); = @@ -743,8 +739,6 @@ void KisToolPaint::requestUpdateOutline(const QPointF &= outlineDocPoint, const Ko // DIRTY HACK ALERT: we should fetch the assistant's dirty rect when r= equesting // the update, instead of just dumbly update the ent= ire canvas! = - ENTER_FUNCTION() << ppVar(outlineDocRect); - KisCanvas2 * kiscanvas =3D dynamic_cast(canvas()); KisPaintingAssistantsDecorationSP decoration =3D kiscanvas->paintingAs= sistantsDecoration(); if (decoration && decoration->visible()) { diff --git a/libs/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp b/l= ibs/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp index 1263c2a806c..453cb66817f 100644 --- a/libs/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp +++ b/libs/ui/tool/strokes/kis_painter_based_stroke_strategy.cpp @@ -323,8 +323,8 @@ void KisPainterBasedStrokeStrategy::resumeStrokeCallbac= k() = void KisPainterBasedStrokeStrategy::doStrokeCallback(KisStrokeJobData *dat= a) { - qDebug() << "Updating resources"; UpdateResourceData *d =3D dynamic_cast(data); + KIS_SAFE_ASSERT_RECOVER_RETURN(d); m_resources->setBrush(d->preset); m_resources->setFGColorOverride(d->fgColor); m_resources->setBGColorOverride(d->bgColor); diff --git a/plugins/paintops/watercolor/kis_base_splats_plane.cpp b/plugin= s/paintops/watercolor/kis_base_splats_plane.cpp index 77e4c48449e..ff162f5bed9 100644 --- a/plugins/paintops/watercolor/kis_base_splats_plane.cpp +++ b/plugins/paintops/watercolor/kis_base_splats_plane.cpp @@ -22,7 +22,6 @@ = KisBaseSplatsPlane::KisBaseSplatsPlane(bool useCaching, KisBaseSplatsPlane= *lowLvlPlane, const KoColorSpace* colorSpace) : m_lowLvlPlane(lowLvlPlane), - m_isDirty(true), m_useCaching(useCaching) { if (useCaching) @@ -81,11 +80,9 @@ QRect KisBaseSplatsPlane::update(KisWetMap *wetMap) { // move to protected call to parent class it =3D m_splats.erase(it); - setDirty(splat); dirtyRect |=3D splat->boundingRect().toAlignedRect(); } } else { - setDirty(splat); dirtyRect |=3D splat->boundingRect().toAlignedRect(); ++it; } @@ -93,9 +90,3 @@ QRect KisBaseSplatsPlane::update(KisWetMap *wetMap) = return dirtyRect; } - -void KisBaseSplatsPlane::setDirty(KisSplat *splat) -{ - m_dirtySplats << splat; - m_isDirty =3D true; -} diff --git a/plugins/paintops/watercolor/kis_base_splats_plane.h b/plugins/= paintops/watercolor/kis_base_splats_plane.h index 49bccafc3e9..4cc21529a99 100644 --- a/plugins/paintops/watercolor/kis_base_splats_plane.h +++ b/plugins/paintops/watercolor/kis_base_splats_plane.h @@ -77,13 +77,9 @@ protected: KisBaseSplatsPlane *m_lowLvlPlane; = protected: - void setDirty(KisSplat *splat); - QList m_dirtySplats; bool m_useCaching; KisPaintDeviceSP m_cachedPD; = -private: - bool m_isDirty; }; = #endif // KIS_ABSTRACT_SPLATS_PLANE_H diff --git a/plugins/paintops/watercolor/kis_fixed_splats_plane.cpp b/plugi= ns/paintops/watercolor/kis_fixed_splats_plane.cpp index 957cb3a2ba1..aab37362603 100644 --- a/plugins/paintops/watercolor/kis_fixed_splats_plane.cpp +++ b/plugins/paintops/watercolor/kis_fixed_splats_plane.cpp @@ -26,6 +26,7 @@ KisFixedSplatsPlane::KisFixedSplatsPlane(KisBaseSplatsPla= ne *driedPlane, const K = QRect KisFixedSplatsPlane::update(KisWetMap *wetMap) { + QRect dirtyRect; for (auto it =3D m_splats.begin(); it !=3D m_splats.end();) { KisSplat *splat =3D *it; = @@ -34,17 +35,15 @@ QRect KisFixedSplatsPlane::update(KisWetMap *wetMap) { // move to protected call to parent class it =3D m_splats.erase(it); - if (m_useCaching) { - m_cachedPD->clear(splat->boundingRect().toAlignedRect(= )); - } - setDirty(splat); + m_cachedPD->clear(splat->boundingRect().toAlignedRect()); + dirtyRect |=3D splat->boundingRect().toAlignedRect(); } } else { ++it; } } = - return QRect(); + return dirtyRect; } = void KisFixedSplatsPlane::rewet(KisWetMap *wetMap, QPointF pos, qreal rad,= KisBaseSplatsPlane *flowingPlane) diff --git a/plugins/paintops/watercolor/kis_splat.cpp b/plugins/paintops/w= atercolor/kis_splat.cpp index 1464b7cdfdf..1dda8bdc2f8 100644 --- a/plugins/paintops/watercolor/kis_splat.cpp +++ b/plugins/paintops/watercolor/kis_splat.cpp @@ -35,9 +35,11 @@ double get_random(qreal min, qreal max) } = = -KisSplat::KisSplat(QPointF offset, int width, const KoColor &color) +KisSplat::KisSplat(QPointF offset, int width, const KoColor &color, + int gravityX, int gravityY) : m_life(STANDART_LIFETIME), m_roughness(1.f), m_flow(1.f), - m_motionBias(QPointF(0.f, 0.f)), m_state(Flowing) + m_motionBias(QPointF(0.f, 0.f)), m_state(Flowing), + m_gravityX(gravityX), m_gravityY(gravityY) { m_initColor.fromKoColor(color); m_fix =3D STANDART_LIFETIME; @@ -62,9 +64,11 @@ KisSplat::KisSplat(QPointF offset, int width, const KoCo= lor &color) } = KisSplat::KisSplat(QPointF offset, QPointF velocityBias, int width, int li= fe, - qreal roughness, qreal flow, qreal radialSpeed, const K= oColor &color) + qreal roughness, qreal flow, qreal radialSpeed, const K= oColor &color, + int gravityX, int gravityY) : m_life(life), m_roughness(roughness), m_flow(flow), - m_motionBias(velocityBias), m_state(Flowing) + m_motionBias(velocityBias), m_state(Flowing), + m_gravityX(gravityX), m_gravityY(gravityY) { m_initColor.fromKoColor(color); m_fix =3D STANDART_LIFETIME; @@ -190,8 +194,9 @@ int KisSplat::update(KisWetMap *wetMap) QPointF v =3D m_velocities[i]; QPointF d =3D (1.f - alpha) * m_motionBias + alpha / get_random(1.= f, 1.f + m_roughness) * v; = - QPointF x1 =3D x + m_flow * d; + QPointF(get_random(-m_roughness, = m_roughness), - get_random(-m_roughness, m_= roughness)); + QPointF x1 =3D x + m_flow * d + QPointF(m_gravityX / 12, m_gravity= Y / 12)/* + + QPointF(get_random(-m_roughness, m_roughness) / 5, + get_random(-m_roughness, m_roughness) / 5)*/; newVertices.push_back(x1); } QVector wetPoints =3D wetMap->getWater(newVertices); diff --git a/plugins/paintops/watercolor/kis_splat.h b/plugins/paintops/wat= ercolor/kis_splat.h index 8c07853530c..ae7cef7e919 100644 --- a/plugins/paintops/watercolor/kis_splat.h +++ b/plugins/paintops/watercolor/kis_splat.h @@ -45,9 +45,11 @@ public: Dried }; = - KisSplat(QPointF offset, int width, const KoColor &color); + KisSplat(QPointF offset, int width, const KoColor &color, + int gravityX, int gravityY); KisSplat(QPointF offset, QPointF velocityBias, int width, int life, - qreal roughness, qreal flow, qreal radialSpeed, const KoColor &c= olor); + qreal roughness, qreal flow, qreal radialSpeed, const KoColor= &color, + int gravityX, int gravityY); = void doPaint(KisPainter *painter); = @@ -79,6 +81,9 @@ private: int m_state; = QPainterPath m_oldPath; + + int m_gravityX, + m_gravityY; }; = #endif diff --git a/plugins/paintops/watercolor/kis_splat_generator_strategy.cpp b= /plugins/paintops/watercolor/kis_splat_generator_strategy.cpp index 2d60100e764..365ead9628a 100644 --- a/plugins/paintops/watercolor/kis_splat_generator_strategy.cpp +++ b/plugins/paintops/watercolor/kis_splat_generator_strategy.cpp @@ -22,18 +22,19 @@ = #include = -QList KisSimpleBrushGenerator::generate(KisWetMap *wetMap, QPo= intF pos, qreal radius, const KoColor &color) +QList KisSimpleBrushGenerator::generate(KisWetMap *wetMap, QPo= intF pos, qreal radius, const KoColor &color, int gravityX, int gravityY) { QList ret; KisSplat *newSplat =3D new KisSplat(pos, radius, - color); + color, + gravityX, gravityY); wetMap->addWater(pos.toPoint(), radius / 2); ret << newSplat; = return ret; } = -QList KisWetOnDryGenerator::generate(KisWetMap *wetMap, QPoint= F pos, qreal radius, const KoColor &color) +QList KisWetOnDryGenerator::generate(KisWetMap *wetMap, QPoint= F pos, qreal radius, const KoColor &color, int gravityX, int gravityY) { QList ret; wetMap->addWater(pos.toPoint(), radius / 2); @@ -45,7 +46,8 @@ QList KisWetOnDryGenerator::generate(KisWetMa= p *wetMap, QPointF pos, QVector2D offset; = KisSplat *splat =3D new KisSplat(pos, radius, - color); + color, + gravityX, gravityY); ret << splat; = for (int i =3D 0; i < 6; i++) { @@ -60,27 +62,29 @@ QList KisWetOnDryGenerator::generate(KisWet= Map *wetMap, QPointF pos, 0.5f * radialSpeed, 1.f, radialSpeed, - color); + color, + gravityX, gravityY); ret << splat; } return ret; } = -QList KisCrunchyGenerator::generate(KisWetMap *wetMap, QPointF= pos, qreal radius, const KoColor &color) +QList KisCrunchyGenerator::generate(KisWetMap *wetMap, QPointF= pos, qreal radius, const KoColor &color, int gravityX, int gravityY) { QList ret; wetMap->addWater(pos.toPoint(), radius / 2); = KisSplat *splat =3D new KisSplat(pos, - QPointF(0, 0), - radius, - 15, 5, 0.25f, 2.f, - color); + QPointF(0, 0), + radius, + 30, 5, 0.25f, 2.f, + color, + gravityX, gravityY); ret << splat; return ret; } = -QList KisWetOnWetGenerator::generate(KisWetMap *wetMap, QPoint= F pos, qreal radius, const KoColor &color) +QList KisWetOnWetGenerator::generate(KisWetMap *wetMap, QPoint= F pos, qreal radius, const KoColor &color, int gravityX, int gravityY) { QList ret; wetMap->addWater(pos.toPoint(), radius / 2); @@ -91,20 +95,22 @@ QList KisWetOnWetGenerator::generate(KisWet= Map *wetMap, QPointF pos, KisSplat *splat =3D new KisSplat(pos, QPointF(0, 0), bigD, - 15, 5, 1.f, 2.f, - color); + 30, 5, 1.f, 2.f, + color, + gravityX, gravityY); ret << splat; = splat =3D new KisSplat(pos, QPointF(0, 0), smallD, - 15, 5, 1.f, 2.f, - color); + 30, 5, 1.f, 2.f, + color, + gravityX, gravityY); ret << splat; return ret; } = -QList KisBlobbyGenerator::generate(KisWetMap *wetMap, QPointF = pos, qreal radius, const KoColor &color) +QList KisBlobbyGenerator::generate(KisWetMap *wetMap, QPointF = pos, qreal radius, const KoColor &color, int gravityX, int gravityY) { QList ret; wetMap->addWater(pos.toPoint(), radius / 2); @@ -134,8 +140,9 @@ QList KisBlobbyGenerator::generate(KisWetMa= p *wetMap, QPointF pos, q splat =3D new KisSplat(posN, QPointF(0, 0), size, - 15, 5, 1.f, 2.f, - color); + 30, 5, 1.f, 2.f, + color, + gravityX, gravityY); ret << splat; } = diff --git a/plugins/paintops/watercolor/kis_splat_generator_strategy.h b/p= lugins/paintops/watercolor/kis_splat_generator_strategy.h index cb73d28446e..e96368662eb 100644 --- a/plugins/paintops/watercolor/kis_splat_generator_strategy.h +++ b/plugins/paintops/watercolor/kis_splat_generator_strategy.h @@ -30,38 +30,44 @@ class KisSplatGeneratorStrategy { public: virtual ~KisSplatGeneratorStrategy(){} - virtual QList generate(KisWetMap *wetMap, QPointF pos, qre= al radius, const KoColor &color) =3D 0; + virtual QList generate(KisWetMap *wetMap, QPointF pos, qre= al radius, const KoColor &color, + int gravityX, int gravityY) =3D 0; = }; = class KisSimpleBrushGenerator : public KisSplatGeneratorStrategy { public: - QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color) override; + QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color, + int gravityX, int gravityY) override; }; = class KisWetOnDryGenerator : public KisSplatGeneratorStrategy { public: - QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color) override; + QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color, + int gravityX, int gravityY) override; }; = class KisCrunchyGenerator : public KisSplatGeneratorStrategy { public: - QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color) override; + QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color, + int gravityX, int gravityY) override; }; = class KisWetOnWetGenerator : public KisSplatGeneratorStrategy { public: - QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color) override; + QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color, + int gravityX, int gravityY) override; }; = class KisBlobbyGenerator : public KisSplatGeneratorStrategy { public: - QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color) override; + QList generate(KisWetMap *wetMap, QPointF pos, qreal radiu= s, const KoColor &color, + int gravityX, int gravityY) override; }; = #endif // KIS_SPLAT_GENERATOR_STRATEGY_H diff --git a/plugins/paintops/watercolor/kis_watercolor_paintop.cpp b/plugi= ns/paintops/watercolor/kis_watercolor_paintop.cpp index 37bdd83ca7a..c990e1a8582 100644 --- a/plugins/paintops/watercolor/kis_watercolor_paintop.cpp +++ b/plugins/paintops/watercolor/kis_watercolor_paintop.cpp @@ -72,9 +72,11 @@ KisSpacingInformation KisWatercolorPaintOp::paintAt(cons= t KisPaintInformation &i = QList newSplats =3D strategy->generate(m_wetMap, - info.pos(), - m_watercolorOption.radius, - painter()->paintColor()); + info.pos(), + m_watercolorOption.radius, + painter()->paintColor(), + m_watercolorOption.gravityX, + m_watercolorOption.gravityY); = const QString oldCompositeOpId =3D painter()->compositeOp()->id(); painter()->setCompositeOp(COMPOSITE_OVER); diff --git a/plugins/paintops/watercolor/kis_watercolor_paintop_settings.cp= p b/plugins/paintops/watercolor/kis_watercolor_paintop_settings.cpp index fdf297c8163..db6de566f16 100644 --- a/plugins/paintops/watercolor/kis_watercolor_paintop_settings.cpp +++ b/plugins/paintops/watercolor/kis_watercolor_paintop_settings.cpp @@ -204,3 +204,19 @@ bool KisWatercolorPaintOpSettings::needsContinuedStrok= e() { return true; } + +QPainterPath KisWatercolorPaintOpSettings::brushOutline(const KisPaintInfo= rmation &info, KisPaintOpSettings::OutlineMode mode) +{ + QPainterPath path; + if (mode =3D=3D CursorIsOutline || mode =3D=3D CursorIsCircleOutline |= | mode =3D=3D CursorTiltOutline) { + qreal size =3D getInt(WATERCOLOR_RADIUS) + 1; + path =3D ellipseOutline(size, size, 1.0, 0.0); + + if (mode =3D=3D CursorTiltOutline) { + path.addPath(makeTiltIndicator(info, QPointF(0.0, 0.0), size *= 0.5, 3.0)); + } + + path.translate(info.pos()); + } + return path; +} diff --git a/plugins/paintops/watercolor/kis_watercolor_paintop_settings.h = b/plugins/paintops/watercolor/kis_watercolor_paintop_settings.h index 5dd7eefbdf9..7d901a1b9b1 100644 --- a/plugins/paintops/watercolor/kis_watercolor_paintop_settings.h +++ b/plugins/paintops/watercolor/kis_watercolor_paintop_settings.h @@ -39,6 +39,8 @@ public: = bool needsContinuedStroke() override; = + QPainterPath brushOutline(const KisPaintInformation &info, OutlineMode= mode) override; + private: struct Private; const QScopedPointer m_d;