[krita/akamakin/T8628-multithreading-optimization] libs/image/layerstyles: Connect Erode/Dilate algorithms to "Stroke" layer style
Andrey Kamakin
null at kde.org
Tue Jun 26 15:02:16 UTC 2018
Git commit af21ce68e13621dd6a84fd64a767b68e69ec5d2f by Andrey Kamakin, on behalf of Dmitry Kazakov.
Committed on 26/06/2018 at 14:18.
Pushed by akamakin into branch 'akamakin/T8628-multithreading-optimization'.
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 at 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/af21ce68e13621dd6a84fd64a767b68e69ec5d2f
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::currentLevelOfDetail() const
m_d->sourceLayer->original()->defaultBounds()->currentLevelOfDetail() : 0;
}
-QPainterPath KisLayerStyleFilterEnvironment::layerOutlineCache() const
-{
- // TODO: make it really cachable!
- Q_ASSERT(m_d->sourceLayer);
- KisPaintDeviceSP srcDevice = m_d->sourceLayer->projection();
- QRect srcRect = srcDevice->exactBounds();
- if (srcRect.isEmpty()) return QPainterPath();
-
- KisSelectionSP baseSelection =
- KisLsUtils::selectionFromAlphaChannel(srcDevice, srcRect);
- KisPixelSelectionSP selection = baseSelection->pixelSelection();
-
- // needs no 'invalidate' call
- selection->recalculateOutlineCache();
-
- return selection->outlineCache();
-}
-
void KisLayerStyleFilterEnvironment::setupFinalPainter(KisPainter *gc,
quint8 opacity,
const QBitArray &channelFlags) 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/layerstyles/kis_ls_stroke_filter.cpp
index a0c7760a42f..e6236c5a62a 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 = 0;
+
+ switch (position) {
+ case psd_stroke_outside:
+ border = 2 * size + 1;
+ break;
+ case psd_stroke_center:
+ border = size + 1;
+ break;
+ case psd_stroke_inside:
+ border = 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 srcDevice,
{
if (applyRect.isEmpty()) return;
- KisSelectionSP baseSelection = new KisSelection(new KisSelectionEmptyBounds(0));
- KisPixelSelectionSP selection = baseSelection->pixelSelection();
-
- //selection->convertToQImage(0, QRect(0,0,300,300)).save("0_selection_initial.png");
-
- QPainterPath strokePath = env->layerOutlineCache();
- if (strokePath.isEmpty()) return;
+ const QRect needRect = kisGrowRect(applyRect, borderSize(config->position(), config->size()));
- if (config->position() == psd_stroke_center) {
- paintPathOnSelection(selection, strokePath,
- applyRect, config->size());
- } else if (config->position() == psd_stroke_outside ||
- config->position() == psd_stroke_inside) {
-
- paintPathOnSelection(selection, strokePath,
- applyRect, 2 * config->size());
-
- KisSelectionSP knockOutSelection =
- KisLsUtils::selectionFromAlphaChannel(srcDevice, applyRect);
-
- // disabled intentionally, because it creates artifacts on smooth lines
- // KisLsUtils::findEdge(knockOutSelection->pixelSelection(), applyRect, true);
+ KisSelectionSP baseSelection = KisLsUtils::selectionFromAlphaChannel(srcDevice, needRect);
+ KisPixelSelectionSP selection = baseSelection->pixelSelection();
- if (config->position() == psd_stroke_inside) {
- knockOutSelection->pixelSelection()->invert();
+ {
+ KisPixelSelectionSP knockOutSelection = new KisPixelSelection(new KisSelectionEmptyBounds(0));
+ knockOutSelection->makeCloneFromRough(selection, needRect);
+
+ if (config->position() == psd_stroke_outside) {
+ KisGaussianKernel::applyDilate(selection, needRect, 2 * config->size(), QBitArray(), 0);
+ } else if (config->position() == psd_stroke_inside) {
+ KisGaussianKernel::applyErodeU8(knockOutSelection, needRect, 2 * config->size(), QBitArray(), 0);
+ } else if (config->position() == psd_stroke_center) {
+ KisGaussianKernel::applyDilate(selection, needRect, config->size(), QBitArray(), 0);
+ KisGaussianKernel::applyErodeU8(knockOutSelection, needRect, config->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 = new KisPaintDevice(srcDevice->colorSpace());
KisLsUtils::fillOverlayDevice(fillDevice, applyRect, config, env);
@@ -136,19 +136,16 @@ void KisLsStrokeFilter::processDirectly(KisPaintDeviceSP 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 = style->stroke();
if (!config->effectEnabled()) return rect;
KisLsUtils::LodWrapper<psd_layer_effects_stroke> w(env->currentLevelOfDetail(), config);
+ return kisGrowRect(rect, borderSize(w.config->position(), w.config->size()));
+}
- const int borderSize = w.config->size() + 1;
- return kisGrowRect(rect, borderSize);
+QRect KisLsStrokeFilter::changedRect(const QRect &rect, KisPSDLayerStyleSP style, KisLayerStyleFilterEnvironment *env) const
+{
+ return neededRect(rect, style, env);
}
More information about the kimageshop
mailing list