Git commit ace6d8252a5a7b783ace53added6584f315ebe1f by Dmitry Kazakov. Committed on 09/06/2018 at 09:00. Pushed by dkazakov into branch 'krita/4.0'. Connect Erode/Dilate algorithms to "Stroke" layer style Now it is **much** faster, more roundish and doesn't eat your memory :) BUG:361130 BUG:390985 CC:kimageshop@kde.org M +0 -18 libs/image/layerstyles/kis_layer_style_filter_environment.cpp M +0 -2 libs/image/layerstyles/kis_layer_style_filter_environment.h M +43 -46 libs/image/layerstyles/kis_ls_stroke_filter.cpp https://commits.kde.org/krita/ace6d8252a5a7b783ace53added6584f315ebe1f diff --git a/libs/image/layerstyles/kis_layer_style_filter_environment.cpp = b/libs/image/layerstyles/kis_layer_style_filter_environment.cpp index 4ba2d485974..f1e7438a568 100644 --- a/libs/image/layerstyles/kis_layer_style_filter_environment.cpp +++ b/libs/image/layerstyles/kis_layer_style_filter_environment.cpp @@ -105,24 +105,6 @@ int KisLayerStyleFilterEnvironment::currentLevelOfDeta= il() const m_d->sourceLayer->original()->defaultBounds()->currentLevelOfDetai= l() : 0; } = -QPainterPath KisLayerStyleFilterEnvironment::layerOutlineCache() const -{ - // TODO: make it really cachable! - Q_ASSERT(m_d->sourceLayer); - KisPaintDeviceSP srcDevice =3D m_d->sourceLayer->projection(); - QRect srcRect =3D srcDevice->exactBounds(); - if (srcRect.isEmpty()) return QPainterPath(); - - KisSelectionSP baseSelection =3D - KisLsUtils::selectionFromAlphaChannel(srcDevice, srcRect); - KisPixelSelectionSP selection =3D baseSelection->pixelSelection(); - - // needs no 'invalidate' call - selection->recalculateOutlineCache(); - - return selection->outlineCache(); -} - void KisLayerStyleFilterEnvironment::setupFinalPainter(KisPainter *gc, quint8 opacity, const QBitArray &ch= annelFlags) const diff --git a/libs/image/layerstyles/kis_layer_style_filter_environment.h b/= libs/image/layerstyles/kis_layer_style_filter_environment.h index 940f1ecdb8f..a54c9475c64 100644 --- a/libs/image/layerstyles/kis_layer_style_filter_environment.h +++ b/libs/image/layerstyles/kis_layer_style_filter_environment.h @@ -41,8 +41,6 @@ public: QRect defaultBounds() const; int currentLevelOfDetail() const; = - QPainterPath layerOutlineCache() const; - void setupFinalPainter(KisPainter *gc, quint8 opacity, const QBitArray &channelFlags) const; diff --git a/libs/image/layerstyles/kis_ls_stroke_filter.cpp b/libs/image/l= ayerstyles/kis_ls_stroke_filter.cpp index 2843abfc64e..d152f1edc57 100644 --- a/libs/image/layerstyles/kis_ls_stroke_filter.cpp +++ b/libs/image/layerstyles/kis_ls_stroke_filter.cpp @@ -44,22 +44,33 @@ #include "kis_ls_utils.h" #include "kis_multiple_projection.h" = +namespace { = -KisLsStrokeFilter::KisLsStrokeFilter() - : KisLayerStyleFilter(KoID("lsstroke", i18n("Stroke (style)"))) +int borderSize(psd_stroke_position position, int size) { + int border =3D 0; + + switch (position) { + case psd_stroke_outside: + border =3D 2 * size + 1; + break; + case psd_stroke_center: + border =3D size + 1; + break; + case psd_stroke_inside: + border =3D 1; + break; + } + + return border; +} + } = -void paintPathOnSelection(KisPixelSelectionSP selection, - const QPainterPath &path, - const QRect &applyRect, - int size) + +KisLsStrokeFilter::KisLsStrokeFilter() + : KisLayerStyleFilter(KoID("lsstroke", i18n("Stroke (style)"))) { - QPen pen(Qt::white, size); - KisPainter gc(selection); - gc.setPaintColor(KoColor(Qt::white, selection->colorSpace())); - gc.drawPainterPath(path, pen, applyRect); - gc.end(); } = void KisLsStrokeFilter::applyStroke(KisPaintDeviceSP srcDevice, @@ -70,41 +81,30 @@ void KisLsStrokeFilter::applyStroke(KisPaintDeviceSP sr= cDevice, { if (applyRect.isEmpty()) return; = - KisSelectionSP baseSelection =3D new KisSelection(new KisSelectionEmpt= yBounds(0)); - KisPixelSelectionSP selection =3D baseSelection->pixelSelection(); - - //selection->convertToQImage(0, QRect(0,0,300,300)).save("0_selection_= initial.png"); - - QPainterPath strokePath =3D env->layerOutlineCache(); - if (strokePath.isEmpty()) return; + const QRect needRect =3D kisGrowRect(applyRect, borderSize(config->pos= ition(), config->size())); = - if (config->position() =3D=3D psd_stroke_center) { - paintPathOnSelection(selection, strokePath, - applyRect, config->size()); - } else if (config->position() =3D=3D psd_stroke_outside || - config->position() =3D=3D psd_stroke_inside) { - - paintPathOnSelection(selection, strokePath, - applyRect, 2 * config->size()); - - KisSelectionSP knockOutSelection =3D - KisLsUtils::selectionFromAlphaChannel(srcDevice, applyRect); - - // disabled intentionally, because it creates artifacts on smooth = lines - // KisLsUtils::findEdge(knockOutSelection->pixelSelection(), apply= Rect, true); + KisSelectionSP baseSelection =3D KisLsUtils::selectionFromAlphaChannel= (srcDevice, needRect); + KisPixelSelectionSP selection =3D baseSelection->pixelSelection(); = - if (config->position() =3D=3D psd_stroke_inside) { - knockOutSelection->pixelSelection()->invert(); + { + KisPixelSelectionSP knockOutSelection =3D new KisPixelSelection(ne= w KisSelectionEmptyBounds(0)); + knockOutSelection->makeCloneFromRough(selection, needRect); + + if (config->position() =3D=3D psd_stroke_outside) { + KisGaussianKernel::applyDilate(selection, needRect, 2 * config= ->size(), QBitArray(), 0); + } else if (config->position() =3D=3D psd_stroke_inside) { + KisGaussianKernel::applyErodeU8(knockOutSelection, needRect, 2= * config->size(), QBitArray(), 0); + } else if (config->position() =3D=3D psd_stroke_center) { + KisGaussianKernel::applyDilate(selection, needRect, config->si= ze(), QBitArray(), 0); + KisGaussianKernel::applyErodeU8(knockOutSelection, needRect, c= onfig->size(), QBitArray(), 0); } = KisPainter gc(selection); gc.setCompositeOp(COMPOSITE_ERASE); - gc.bitBlt(applyRect.topLeft(), knockOutSelection->pixelSelection()= , applyRect); + gc.bitBlt(needRect.topLeft(), knockOutSelection, needRect); gc.end(); } = - //selection->convertToQImage(0, QRect(0,0,300,300)).save("1_selection_= stroke.png"); - KisPaintDeviceSP fillDevice =3D new KisPaintDevice(srcDevice->colorSpa= ce()); KisLsUtils::fillOverlayDevice(fillDevice, applyRect, config, env); = @@ -138,19 +138,16 @@ void KisLsStrokeFilter::processDirectly(KisPaintDevic= eSP src, applyStroke(src, dst, applyRect, w.config, env); } = -QRect KisLsStrokeFilter::neededRect(const QRect &rect, KisPSDLayerStyleSP = style, KisLayerStyleFilterEnvironment */*env*/) const -{ - Q_UNUSED(style); - return rect; -} - -QRect KisLsStrokeFilter::changedRect(const QRect &rect, KisPSDLayerStyleSP= style, KisLayerStyleFilterEnvironment *env) const +QRect KisLsStrokeFilter::neededRect(const QRect &rect, KisPSDLayerStyleSP = style, KisLayerStyleFilterEnvironment *env) const { const psd_layer_effects_stroke *config =3D style->stroke(); if (!config->effectEnabled()) return rect; = KisLsUtils::LodWrapper w(env->currentLevelOf= Detail(), config); + return kisGrowRect(rect, borderSize(w.config->position(), w.config->si= ze())); +} = - const int borderSize =3D w.config->size() + 1; - return kisGrowRect(rect, borderSize); +QRect KisLsStrokeFilter::changedRect(const QRect &rect, KisPSDLayerStyleSP= style, KisLayerStyleFilterEnvironment *env) const +{ + return neededRect(rect, style, env); }