[graphics/krita] libs/image: Mask generation refactor
L. E. Segovia
null at kde.org
Sun Mar 27 16:47:19 BST 2022
Git commit 3aeeae38ee1f51cc9a294d5f4dab94529db09d58 by L. E. Segovia.
Committed on 27/03/2022 at 14:46.
Pushed by lsegovia into branch 'master'.
Mask generation refactor
This commit is a preparation for the xsimd port. It refactors the
following:
- FastRowProcessor is now a templated class that takes the individual
generators + a friend class statement. This allows to hide the
implementation inside a Vc-aware processor factory.
- MaskApplicatorFactory is now Vc-aware, needing only the generator
class as a parameter.
- MaskApplicatorFactory is now instantiated separately for the Scalar
mode, implementing properly the #define hack used for the Vc-free mode
by splitting the cpp in two source files.
- Scalar and vector applicators are now compiled separately, allowing to
use the latter only when Vc is available, and thus enabling the above
change.
CCMAIL: kimageshop at kde.org
M +8 -3 libs/image/CMakeLists.txt
M +2 -1 libs/image/kis_base_mask_generator.cpp
M +28 -588 libs/image/kis_brush_mask_applicator_factories.cpp
M +5 -20 libs/image/kis_brush_mask_applicator_factories.h
A +73 -0 libs/image/kis_brush_mask_applicator_factories_Scalar.cpp [License: GPL(v2.0+)]
D +0 -201 libs/image/kis_brush_mask_applicators.h
C +115 -205 libs/image/kis_brush_mask_processor_factories.cpp [from: libs/image/kis_brush_mask_applicator_factories.cpp - 058% similarity]
A +92 -0 libs/image/kis_brush_mask_scalar_applicator.h [License: GPL(v2.0+)]
A +143 -0 libs/image/kis_brush_mask_vector_applicator.h [License: GPL(v2.0+)]
M +3 -22 libs/image/kis_circle_mask_generator.cpp
M +6 -3 libs/image/kis_circle_mask_generator.h
M +3 -26 libs/image/kis_curve_circle_mask_generator.cpp
M +6 -3 libs/image/kis_curve_circle_mask_generator.h
M +4 -24 libs/image/kis_curve_rect_mask_generator.cpp
M +7 -3 libs/image/kis_curve_rect_mask_generator.h
M +3 -23 libs/image/kis_gauss_circle_mask_generator.cpp
M +7 -4 libs/image/kis_gauss_circle_mask_generator.h
M +4 -22 libs/image/kis_gauss_rect_mask_generator.cpp
M +7 -3 libs/image/kis_gauss_rect_mask_generator.h
M +4 -23 libs/image/kis_rect_mask_generator.cpp
M +9 -4 libs/image/kis_rect_mask_generator.h
https://invent.kde.org/graphics/krita/commit/3aeeae38ee1f51cc9a294d5f4dab94529db09d58
diff --git a/libs/image/CMakeLists.txt b/libs/image/CMakeLists.txt
index bbcdf3b895..95b3996a84 100644
--- a/libs/image/CMakeLists.txt
+++ b/libs/image/CMakeLists.txt
@@ -27,9 +27,12 @@ endif()
if(HAVE_VC)
include_directories(SYSTEM ${Vc_INCLUDE_DIR} ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS})
- ko_compile_for_all_implementations(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp)
-else()
- set(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp)
+ ko_compile_for_all_implementations_no_scalar(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp)
+ ko_compile_for_all_implementations_no_scalar(_per_arch_processor_objs kis_brush_mask_processor_factories.cpp)
+
+ message("Following objects are generated from the per-arch lib")
+ message("${__per_arch_circle_mask_generator_objs}")
+ message("${_per_arch_processor_objs}")
endif()
set(kritaimage_LIB_SRCS
@@ -245,6 +248,8 @@ set(kritaimage_LIB_SRCS
kis_gauss_circle_mask_generator.cpp
kis_gauss_rect_mask_generator.cpp
${__per_arch_circle_mask_generator_objs}
+ ${_per_arch_processor_objs}
+ kis_brush_mask_applicator_factories_Scalar.cpp
kis_curve_circle_mask_generator.cpp
kis_curve_rect_mask_generator.cpp
kis_math_toolbox.cpp
diff --git a/libs/image/kis_base_mask_generator.cpp b/libs/image/kis_base_mask_generator.cpp
index 3f04e8c422..94a3f755a2 100644
--- a/libs/image/kis_base_mask_generator.cpp
+++ b/libs/image/kis_base_mask_generator.cpp
@@ -2,6 +2,7 @@
* SPDX-FileCopyrightText: 2004, 2007-2009 Cyrille Berger <cberger at cberger.net>
* SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev at gmail.com>
* SPDX-FileCopyrightText: 2011 Sven Langkamp <sven.langkamp at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -134,7 +135,7 @@ KisBrushMaskApplicatorBase* KisMaskGenerator::applicator()
{
if (!d->defaultMaskProcessor) {
d->defaultMaskProcessor.reset(
- createOptimizedClass<MaskApplicatorFactory<KisMaskGenerator, KisBrushMaskScalarApplicator> >(this));
+ createOptimizedClass<MaskApplicatorFactory<KisMaskGenerator>>(this));
}
return d->defaultMaskProcessor.data();
diff --git a/libs/image/kis_brush_mask_applicator_factories.cpp b/libs/image/kis_brush_mask_applicator_factories.cpp
index 11f5688c5f..105d8577da 100644
--- a/libs/image/kis_brush_mask_applicator_factories.cpp
+++ b/libs/image/kis_brush_mask_applicator_factories.cpp
@@ -1,634 +1,74 @@
/*
* SPDX-FileCopyrightText: 2012 Dmitry Kazakov <dimula73 at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "kis_brush_mask_applicator_factories.h"
-#include "vc_extra_math.h"
#include "kis_circle_mask_generator.h"
-#include "kis_circle_mask_generator_p.h"
-#include "kis_gauss_circle_mask_generator_p.h"
-#include "kis_curve_circle_mask_generator_p.h"
-#include "kis_gauss_rect_mask_generator_p.h"
-#include "kis_curve_rect_mask_generator_p.h"
-#include "kis_rect_mask_generator_p.h"
+#include "kis_gauss_circle_mask_generator.h"
+#include "kis_curve_circle_mask_generator.h"
+#include "kis_gauss_rect_mask_generator.h"
+#include "kis_curve_rect_mask_generator.h"
+#include "kis_rect_mask_generator.h"
-#include "kis_brush_mask_applicators.h"
#include "kis_brush_mask_applicator_base.h"
-
-#define a(_s) #_s
-#define b(_s) a(_s)
+#include "kis_brush_mask_vector_applicator.h"
template<>
template<>
-MaskApplicatorFactory<KisMaskGenerator, KisBrushMaskScalarApplicator>::ReturnType
-MaskApplicatorFactory<KisMaskGenerator, KisBrushMaskScalarApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
+MaskApplicatorFactory<KisMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisMaskGenerator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
{
- return new KisBrushMaskScalarApplicator<KisMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
+ return new KisBrushMaskScalarApplicator<KisMaskGenerator, Vc::CurrentImplementation::current()>(maskGenerator);
}
template<>
template<>
-MaskApplicatorFactory<KisCircleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisCircleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
+MaskApplicatorFactory<KisCircleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisCircleMaskGenerator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
{
- return new KisBrushMaskVectorApplicator<KisCircleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
+ return new KisBrushMaskVectorApplicator<KisCircleMaskGenerator, Vc::CurrentImplementation::current()>(maskGenerator);
}
template<>
template<>
-MaskApplicatorFactory<KisGaussCircleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisGaussCircleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
+MaskApplicatorFactory<KisGaussCircleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisGaussCircleMaskGenerator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
{
- return new KisBrushMaskVectorApplicator<KisGaussCircleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
+ return new KisBrushMaskVectorApplicator<KisGaussCircleMaskGenerator, Vc::CurrentImplementation::current()>(maskGenerator);
}
template<>
template<>
-MaskApplicatorFactory<KisCurveCircleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisCurveCircleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
+MaskApplicatorFactory<KisCurveCircleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisCurveCircleMaskGenerator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
{
- return new KisBrushMaskVectorApplicator<KisCurveCircleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
+ return new KisBrushMaskVectorApplicator<KisCurveCircleMaskGenerator, Vc::CurrentImplementation::current()>(maskGenerator);
}
template<>
template<>
-MaskApplicatorFactory<KisRectangleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisRectangleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
+MaskApplicatorFactory<KisRectangleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisRectangleMaskGenerator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
{
- return new KisBrushMaskVectorApplicator<KisRectangleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
+ return new KisBrushMaskVectorApplicator<KisRectangleMaskGenerator, Vc::CurrentImplementation::current()>(maskGenerator);
}
template<>
template<>
-MaskApplicatorFactory<KisGaussRectangleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisGaussRectangleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
+MaskApplicatorFactory<KisGaussRectangleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisGaussRectangleMaskGenerator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
{
- return new KisBrushMaskVectorApplicator<KisGaussRectangleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
+ return new KisBrushMaskVectorApplicator<KisGaussRectangleMaskGenerator, Vc::CurrentImplementation::current()>(maskGenerator);
}
template<>
template<>
-MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
-{
- return new KisBrushMaskVectorApplicator<KisCurveRectangleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
-}
-
-
-#if defined HAVE_VC
-
-struct KisCircleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisCircleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisCircleMaskGenerator::Private *d;
-};
-
-template<> void KisCircleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
-{
- const bool useSmoothing = d->copyOfAntialiasEdges;
-
- float y_ = y - centerY;
- float sinay_ = sina * y_;
- float cosay_ = cosa * y_;
-
- float* bufferPointer = buffer;
-
- Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
-
- Vc::float_v increment((float)Vc::float_v::size());
- Vc::float_v vCenterX(centerX);
-
- Vc::float_v vCosa(cosa);
- Vc::float_v vSina(sina);
- Vc::float_v vCosaY_(cosay_);
- Vc::float_v vSinaY_(sinay_);
-
- Vc::float_v vXCoeff(static_cast<float>(d->xcoef));
- Vc::float_v vYCoeff(static_cast<float>(d->ycoef));
-
- Vc::float_v vTransformedFadeX(static_cast<float>(d->transformedFadeX));
- Vc::float_v vTransformedFadeY(static_cast<float>(d->transformedFadeY));
-
- Vc::float_v vOne(Vc::One);
-
- for (size_t i=0; i < static_cast<size_t>(width); i+= Vc::float_v::size()){
-
- Vc::float_v x_ = currentIndices - vCenterX;
-
- Vc::float_v xr = x_ * vCosa - vSinaY_;
- Vc::float_v yr = x_ * vSina + vCosaY_;
-
- Vc::float_v n = pow2(xr * vXCoeff) + pow2(yr * vYCoeff);
- Vc::float_m outsideMask = n > vOne;
-
- if (!outsideMask.isFull()) {
- if (useSmoothing) {
- xr = Vc::abs(xr) + vOne;
- yr = Vc::abs(yr) + vOne;
- }
- Vc::float_v vNormFade = pow2(xr * vTransformedFadeX) + pow2(yr * vTransformedFadeY);
- Vc::float_m vNormLowMask = vNormFade < vOne;
- vNormFade.setZero(vNormLowMask);
-
- //255 * n * (normeFade - 1) / (normeFade - n)
- Vc::float_v vFade = n * (vNormFade - vOne) / (vNormFade - n);
-
- // Mask in the inner circle of the mask
- Vc::float_m mask = vNormFade < vOne;
- vFade.setZero(mask);
-
- // Mask out the outer circle of the mask
- vFade(outsideMask) = vOne;
-
- vFade.store(bufferPointer, Vc::Aligned);
-
- } else {
- // Mask out everything outside the circle
- vOne.store(bufferPointer, Vc::Aligned);
- }
-
- currentIndices = currentIndices + increment;
-
- bufferPointer += Vc::float_v::size();
- }
-}
-
-
-struct KisGaussCircleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisGaussCircleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisGaussCircleMaskGenerator::Private *d;
-};
-
-template<> void KisGaussCircleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
-{
- float y_ = y - centerY;
- float sinay_ = sina * y_;
- float cosay_ = cosa * y_;
-
- float* bufferPointer = buffer;
-
- Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
-
- Vc::float_v increment(static_cast<float>(Vc::float_v::size()));
- Vc::float_v vCenterX(centerX);
- Vc::float_v vCenter(static_cast<float>(d->center));
-
- Vc::float_v vCosa(cosa);
- Vc::float_v vSina(sina);
- Vc::float_v vCosaY_(cosay_);
- Vc::float_v vSinaY_(sinay_);
-
- Vc::float_v vYCoeff(static_cast<float>(d->ycoef));
- Vc::float_v vDistfactor(static_cast<float>(d->distfactor));
- Vc::float_v vAlphafactor(static_cast<float>(d->alphafactor));
-
- Vc::float_v vZero(Vc::Zero);
- Vc::float_v vValMax(255.f);
-
- for (size_t i=0; i < static_cast<size_t>(width); i+= Vc::float_v::size()){
-
- Vc::float_v x_ = currentIndices - vCenterX;
-
- Vc::float_v xr = x_ * vCosa - vSinaY_;
- Vc::float_v yr = x_ * vSina + vCosaY_;
-
- Vc::float_v dist = sqrt(pow2(xr) + pow2(yr * vYCoeff));
-
- // Apply FadeMaker mask and operations
- Vc::float_m excludeMask = d->fadeMaker.needFade(dist);
-
- if (!excludeMask.isFull()) {
- Vc::float_v valDist = dist * vDistfactor;
- Vc::float_v fullFade = vAlphafactor * ( VcExtraMath::erf(valDist + vCenter) - VcExtraMath::erf(valDist - vCenter));
-
- Vc::float_m mask;
- // Mask in the inner circle of the mask
- mask = fullFade < vZero;
- fullFade.setZero(mask);
-
- // Mask the outer circle
- mask = fullFade > 254.974f;
- fullFade(mask) = vValMax;
-
- // Mask (value - value), precision errors.
- Vc::float_v vFade = (vValMax - fullFade) / vValMax;
-
- // return original dist values before vFade transform
- vFade(excludeMask) = dist;
- vFade.store(bufferPointer, Vc::Aligned);
-
- } else {
- dist.store(bufferPointer, Vc::Aligned);
- }
- currentIndices = currentIndices + increment;
-
- bufferPointer += Vc::float_v::size();
- }
-}
-
-struct KisCurveCircleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisCurveCircleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisCurveCircleMaskGenerator::Private *d;
-};
-
-
-template<> void KisCurveCircleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
-{
- float y_ = y - centerY;
- float sinay_ = sina * y_;
- float cosay_ = cosa * y_;
-
- float* bufferPointer = buffer;
-
- qreal* curveDataPointer = d->curveData.data();
-
- Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
-
- Vc::float_v increment((float)Vc::float_v::size());
- Vc::float_v vCenterX(centerX);
-
- Vc::float_v vCosa(cosa);
- Vc::float_v vSina(sina);
- Vc::float_v vCosaY_(cosay_);
- Vc::float_v vSinaY_(sinay_);
-
- Vc::float_v vYCoeff(static_cast<float>(d->ycoef));
- Vc::float_v vXCoeff(static_cast<float>(d->xcoef));
- Vc::float_v vCurveResolution(static_cast<float>(d->curveResolution));
-
- Vc::float_v vCurvedData(Vc::Zero);
- Vc::float_v vCurvedData1(Vc::Zero);
-
- Vc::float_v vOne(Vc::One);
- Vc::float_v vZero(Vc::Zero);
-
- for (size_t i=0; i < static_cast<size_t>(width); i+= Vc::float_v::size()){
-
- Vc::float_v x_ = currentIndices - vCenterX;
-
- Vc::float_v xr = x_ * vCosa - vSinaY_;
- Vc::float_v yr = x_ * vSina + vCosaY_;
-
- Vc::float_v dist = pow2(xr * vXCoeff) + pow2(yr * vYCoeff);
-
- // Apply FadeMaker mask and operations
- Vc::float_m excludeMask = d->fadeMaker.needFade(dist);
-
- if (!excludeMask.isFull()) {
- Vc::float_v valDist = dist * vCurveResolution;
- // truncate
- Vc::float_v::IndexType vAlphaValue(valDist);
- Vc::float_v vFloatAlphaValue = vAlphaValue;
-
- Vc::float_v alphaValueF = valDist - vFloatAlphaValue;
-
- Vc::float_m alphaMask = vAlphaValue < vZero;
- vAlphaValue.setZero(alphaMask);
-
- vCurvedData.gather(curveDataPointer,vAlphaValue);
- vCurvedData1.gather(curveDataPointer,vAlphaValue + 1);
-// Vc::float_v vCurvedData1(curveDataPointer,vAlphaValue + 1);
-
- // vAlpha
- Vc::float_v fullFade = (
- (vOne - alphaValueF) * vCurvedData +
- alphaValueF * vCurvedData1);
-
- Vc::float_m mask;
- // Mask in the inner circle of the mask
- mask = fullFade < vZero;
- fullFade.setZero(mask);
-
- // Mask outer circle of mask
- mask = fullFade >= vOne;
- Vc::float_v vFade = (vOne - fullFade);
- vFade.setZero(mask);
-
- // return original dist values before vFade transform
- vFade(excludeMask) = dist;
- vFade.store(bufferPointer, Vc::Aligned);
-
- } else {
- dist.store(bufferPointer, Vc::Aligned);
- }
- currentIndices = currentIndices + increment;
-
- bufferPointer += Vc::float_v::size();
- }
-}
-
-struct KisGaussRectangleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisGaussRectangleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisGaussRectangleMaskGenerator::Private *d;
-};
-
-struct KisRectangleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisRectangleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisRectangleMaskGenerator::Private *d;
-};
-
-template<> void KisRectangleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
-{
- const bool useSmoothing = d->copyOfAntialiasEdges;
-
- float y_ = y - centerY;
- float sinay_ = sina * y_;
- float cosay_ = cosa * y_;
-
- float* bufferPointer = buffer;
-
- Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
-
- Vc::float_v increment((float)Vc::float_v::size());
- Vc::float_v vCenterX(centerX);
-
- Vc::float_v vCosa(cosa);
- Vc::float_v vSina(sina);
- Vc::float_v vCosaY_(cosay_);
- Vc::float_v vSinaY_(sinay_);
-
- Vc::float_v vXCoeff(static_cast<float>(d->xcoeff));
- Vc::float_v vYCoeff(static_cast<float>(d->ycoeff));
-
- Vc::float_v vTransformedFadeX(static_cast<float>(d->transformedFadeX));
- Vc::float_v vTransformedFadeY(static_cast<float>(d->transformedFadeY));
-
- Vc::float_v vOne(Vc::One);
- Vc::float_v vZero(Vc::Zero);
- Vc::float_v vTolerance(10000.f);
-
- for (size_t i=0; i < static_cast<size_t>(width); i+= Vc::float_v::size()){
-
- Vc::float_v x_ = currentIndices - vCenterX;
-
- Vc::float_v xr = Vc::abs(x_ * vCosa - vSinaY_);
- Vc::float_v yr = Vc::abs(x_ * vSina + vCosaY_);
-
- Vc::float_v nxr = xr * vXCoeff;
- Vc::float_v nyr = yr * vYCoeff;
-
- Vc::float_m outsideMask = (nxr > vOne) || (nyr > vOne);
-
- if (!outsideMask.isFull()) {
- if (useSmoothing) {
- xr = Vc::abs(xr) + vOne;
- yr = Vc::abs(yr) + vOne;
- }
-
- Vc::float_v fxr = xr * vTransformedFadeX;
- Vc::float_v fyr = yr * vTransformedFadeY;
-
- Vc::float_v fxrNorm = nxr * (fxr - vOne) / (fxr - nxr);
- Vc::float_v fyrNorm = nyr * (fyr - vOne) / (fyr - nyr);
-
- Vc::float_v vFade(vZero);
-
- Vc::float_m vFadeMask = fxrNorm < fyrNorm;
- Vc::float_v vMaxVal = vFade;
- vMaxVal(fxr > vOne) = fxrNorm;
- vMaxVal(vFadeMask && fyr > vOne) = fyrNorm;
- vFade = vMaxVal;
-
- // Mask out the outer circle of the mask
- vFade(outsideMask) = vOne;
- vFade.store(bufferPointer, Vc::Aligned);
- } else {
- // Mask out everything outside the circle
- vOne.store(bufferPointer, Vc::Aligned);
- }
-
- currentIndices = currentIndices + increment;
-
- bufferPointer += Vc::float_v::size();
- }
-}
-
-
-template<> void KisGaussRectangleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
-{
- float y_ = y - centerY;
- float sinay_ = sina * y_;
- float cosay_ = cosa * y_;
-
- float* bufferPointer = buffer;
-
- Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
-
- Vc::float_v increment((float)Vc::float_v::size());
- Vc::float_v vCenterX(centerX);
-
- Vc::float_v vCosa(cosa);
- Vc::float_v vSina(sina);
- Vc::float_v vCosaY_(cosay_);
- Vc::float_v vSinaY_(sinay_);
-
- Vc::float_v vhalfWidth(static_cast<float>(d->halfWidth));
- Vc::float_v vhalfHeight(static_cast<float>(d->halfHeight));
- Vc::float_v vXFade(static_cast<float>(d->xfade));
- Vc::float_v vYFade(static_cast<float>(d->yfade));
-
- Vc::float_v vAlphafactor(static_cast<float>(d->alphafactor));
-
- Vc::float_v vOne(Vc::One);
- Vc::float_v vZero(Vc::Zero);
- Vc::float_v vValMax(255.f);
-
- for (size_t i = 0; i < static_cast<size_t>(width); i += Vc::float_v::size()) {
- Vc::float_v x_ = currentIndices - vCenterX;
-
- Vc::float_v xr = x_ * vCosa - vSinaY_;
- Vc::float_v yr = Vc::abs(x_ * vSina + vCosaY_);
-
- Vc::float_v vValue;
-
- // check if we need to apply fader on values
- Vc::float_m excludeMask = d->fadeMaker.needFade(xr,yr);
- vValue(excludeMask) = vOne;
-
- if (!excludeMask.isFull()) {
- Vc::float_v fullFade = vValMax - (vAlphafactor * (VcExtraMath::erf((vhalfWidth + xr) * vXFade) + VcExtraMath::erf((vhalfWidth - xr) * vXFade))
- * (VcExtraMath::erf((vhalfHeight + yr) * vYFade) + VcExtraMath::erf((vhalfHeight - yr) * vYFade)));
-
- // apply antialias fader
- d->fadeMaker.apply2DFader(fullFade,excludeMask,xr,yr);
-
- Vc::float_m mask;
-
- // Mask in the inner circle of the mask
- mask = fullFade < vZero;
- fullFade.setZero(mask);
-
- // Mask the outer circle
- mask = fullFade > 254.974f;
- fullFade(mask) = vValMax;
-
- // Mask (value - value), precision errors.
- Vc::float_v vFade = fullFade / vValMax;
-
- // return original vValue values before vFade transform
- vFade(excludeMask) = vValue;
- vFade.store(bufferPointer, Vc::Aligned);
-
- } else {
- vValue.store(bufferPointer, Vc::Aligned);
- }
- currentIndices = currentIndices + increment;
-
- bufferPointer += Vc::float_v::size();
- }
-}
-
-struct KisCurveRectangleMaskGenerator::FastRowProcessor
+MaskApplicatorFactory<KisCurveRectangleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisCurveRectangleMaskGenerator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
{
- FastRowProcessor(KisCurveRectangleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisCurveRectangleMaskGenerator::Private *d;
-};
-
-template<> void KisCurveRectangleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
-{
- float y_ = y - centerY;
- float sinay_ = sina * y_;
- float cosay_ = cosa * y_;
-
- float* bufferPointer = buffer;
-
- qreal* curveDataPointer = d->curveData.data();
-
- Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
-
- Vc::float_v increment((float)Vc::float_v::size());
- Vc::float_v vCenterX(centerX);
-
- Vc::float_v vCosa(cosa);
- Vc::float_v vSina(sina);
- Vc::float_v vCosaY_(cosay_);
- Vc::float_v vSinaY_(sinay_);
-
- Vc::float_v vYCoeff(static_cast<float>(d->ycoeff));
- Vc::float_v vXCoeff(static_cast<float>(d->xcoeff));
- Vc::float_v vCurveResolution(static_cast<float>(d->curveResolution));
-
- Vc::float_v vOne(Vc::One);
- Vc::float_v vZero(Vc::Zero);
- Vc::float_v vValMax(255.f);
-
- for (size_t i = 0; i < static_cast<size_t>(width); i += Vc::float_v::size()) {
- Vc::float_v x_ = currentIndices - vCenterX;
-
- Vc::float_v xr = x_ * vCosa - vSinaY_;
- Vc::float_v yr = Vc::abs(x_ * vSina + vCosaY_);
-
- Vc::float_v vValue;
-
- // check if we need to apply fader on values
- Vc::float_m excludeMask = d->fadeMaker.needFade(xr,yr);
- vValue(excludeMask) = vOne;
-
- if (!excludeMask.isFull()) {
- // We need to mask the extra area given for aliniation
- // the next operation should never give values above 1
- Vc::float_v preSIndex = Vc::abs(xr) * vXCoeff;
- Vc::float_v preTIndex = Vc::abs(yr) * vYCoeff;
-
- preSIndex(preSIndex > vOne) = vOne;
- preTIndex(preTIndex > vOne) = vOne;
-
- Vc::float_v::IndexType sIndex( round(preSIndex * vCurveResolution));
- Vc::float_v::IndexType tIndex( round(preTIndex * vCurveResolution));
-
- Vc::float_v::IndexType sIndexInverted = vCurveResolution - sIndex;
- Vc::float_v::IndexType tIndexInverted = vCurveResolution - tIndex;
-
- Vc::float_v vCurvedDataSIndex(curveDataPointer, sIndex);
- Vc::float_v vCurvedDataTIndex(curveDataPointer, tIndex);
- Vc::float_v vCurvedDataSIndexInv(curveDataPointer, sIndexInverted);
- Vc::float_v vCurvedDataTIndexInv(curveDataPointer, tIndexInverted);
-
- Vc::float_v fullFade = vValMax * (vOne - (vCurvedDataSIndex * (vOne - vCurvedDataSIndexInv) *
- vCurvedDataTIndex * (vOne - vCurvedDataTIndexInv)));
-
- // apply antialias fader
- d->fadeMaker.apply2DFader(fullFade,excludeMask,xr,yr);
-
- Vc::float_m mask;
-
- // Mask in the inner circle of the mask
- mask = fullFade < vZero;
- fullFade.setZero(mask);
-
- // Mask the outer circle
- mask = fullFade > 254.974f;
- fullFade(mask) = vValMax;
-
- // Mask (value - value), precision errors.
- Vc::float_v vFade = fullFade / vValMax;
-
- // return original vValue values before vFade transform
- vFade(excludeMask) = vValue;
- vFade.store(bufferPointer, Vc::Aligned);
-
- } else {
- vValue.store(bufferPointer, Vc::Aligned);
- }
- currentIndices = currentIndices + increment;
-
- bufferPointer += Vc::float_v::size();
- }
+ return new KisBrushMaskVectorApplicator<KisCurveRectangleMaskGenerator, Vc::CurrentImplementation::current()>(maskGenerator);
}
-
-#endif /* defined HAVE_VC */
diff --git a/libs/image/kis_brush_mask_applicator_factories.h b/libs/image/kis_brush_mask_applicator_factories.h
index 0e7e06d599..60592e4516 100644
--- a/libs/image/kis_brush_mask_applicator_factories.h
+++ b/libs/image/kis_brush_mask_applicator_factories.h
@@ -1,5 +1,6 @@
/*
* SPDX-FileCopyrightText: 2012 Dmitry Kazakov <dimula73 at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -11,26 +12,10 @@
class KisBrushMaskApplicatorBase;
-template<class MaskGenerator, Vc::Implementation _impl>
-struct KisBrushMaskScalarApplicator;
-
-#ifdef HAVE_VC
-
-template<class MaskGenerator, Vc::Implementation _impl>
-struct KisBrushMaskVectorApplicator;
-
-#else /* HAVE_VC */
-
-#define KisBrushMaskVectorApplicator KisBrushMaskScalarApplicator
-
-#endif /* HAVE_VC */
-
-template<class MaskGenerator,
- template<class U, Vc::Implementation V> class Applicator>
-struct MaskApplicatorFactory
-{
- typedef MaskGenerator* ParamType;
- typedef KisBrushMaskApplicatorBase* ReturnType;
+template<class MaskGenerator>
+struct MaskApplicatorFactory {
+ using ParamType = MaskGenerator *;
+ using ReturnType = KisBrushMaskApplicatorBase *;
template<Vc::Implementation _impl>
static ReturnType create(ParamType maskGenerator);
diff --git a/libs/image/kis_brush_mask_applicator_factories_Scalar.cpp b/libs/image/kis_brush_mask_applicator_factories_Scalar.cpp
new file mode 100644
index 0000000000..6cf142561f
--- /dev/null
+++ b/libs/image/kis_brush_mask_applicator_factories_Scalar.cpp
@@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: 2012 Dmitry Kazakov <dimula73 at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "kis_brush_mask_applicator_factories.h"
+
+#include "kis_circle_mask_generator.h"
+#include "kis_curve_circle_mask_generator.h"
+#include "kis_curve_rect_mask_generator.h"
+#include "kis_gauss_circle_mask_generator.h"
+#include "kis_gauss_rect_mask_generator.h"
+#include "kis_rect_mask_generator.h"
+
+#include "kis_brush_mask_scalar_applicator.h"
+
+template<>
+template<>
+MaskApplicatorFactory<KisMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisMaskGenerator>::create<Vc::ScalarImpl>(ParamType maskGenerator)
+{
+ return new KisBrushMaskScalarApplicator<KisMaskGenerator, Vc::ScalarImpl>(maskGenerator);
+}
+
+template<>
+template<>
+MaskApplicatorFactory<KisCircleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisCircleMaskGenerator>::create<Vc::ScalarImpl>(ParamType maskGenerator)
+{
+ return new KisBrushMaskScalarApplicator<KisCircleMaskGenerator, Vc::ScalarImpl>(maskGenerator);
+}
+
+template<>
+template<>
+MaskApplicatorFactory<KisGaussCircleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisGaussCircleMaskGenerator>::create<Vc::ScalarImpl>(ParamType maskGenerator)
+{
+ return new KisBrushMaskScalarApplicator<KisGaussCircleMaskGenerator, Vc::ScalarImpl>(maskGenerator);
+}
+
+template<>
+template<>
+MaskApplicatorFactory<KisCurveCircleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisCurveCircleMaskGenerator>::create<Vc::ScalarImpl>(ParamType maskGenerator)
+{
+ return new KisBrushMaskScalarApplicator<KisCurveCircleMaskGenerator, Vc::ScalarImpl>(maskGenerator);
+}
+
+template<>
+template<>
+MaskApplicatorFactory<KisRectangleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisRectangleMaskGenerator>::create<Vc::ScalarImpl>(ParamType maskGenerator)
+{
+ return new KisBrushMaskScalarApplicator<KisRectangleMaskGenerator, Vc::ScalarImpl>(maskGenerator);
+}
+
+template<>
+template<>
+MaskApplicatorFactory<KisGaussRectangleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisGaussRectangleMaskGenerator>::create<Vc::ScalarImpl>(ParamType maskGenerator)
+{
+ return new KisBrushMaskScalarApplicator<KisGaussRectangleMaskGenerator, Vc::ScalarImpl>(maskGenerator);
+}
+
+template<>
+template<>
+MaskApplicatorFactory<KisCurveRectangleMaskGenerator>::ReturnType
+MaskApplicatorFactory<KisCurveRectangleMaskGenerator>::create<Vc::ScalarImpl>(ParamType maskGenerator)
+{
+ return new KisBrushMaskScalarApplicator<KisCurveRectangleMaskGenerator, Vc::ScalarImpl>(maskGenerator);
+}
diff --git a/libs/image/kis_brush_mask_applicators.h b/libs/image/kis_brush_mask_applicators.h
deleted file mode 100644
index 7f51067bbc..0000000000
--- a/libs/image/kis_brush_mask_applicators.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2012 Sven Langkamp <sven.langkamp at gmail.com>
- * SPDX-FileCopyrightText: 2012 Dmitry Kazakov <dimula73 at gmail.com>
- *
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-#ifndef __KIS_BRUSH_MASK_APPLICATORS_H
-#define __KIS_BRUSH_MASK_APPLICATORS_H
-
-#include "kis_brush_mask_applicator_base.h"
-#include "kis_global.h"
-#include "kis_random_source.h"
-
-// 3x3 supersampling
-#define SUPERSAMPLING 3
-
-
-template<class MaskGenerator, Vc::Implementation _impl>
-struct KisBrushMaskScalarApplicator : public KisBrushMaskApplicatorBase
-{
- KisBrushMaskScalarApplicator(MaskGenerator *maskGenerator)
- : m_maskGenerator(maskGenerator)
- {
- }
-
- void process(const QRect &rect) override {
- processScalar(rect);
- }
-
-protected:
- void processScalar(const QRect &rect);
-
-protected:
- MaskGenerator *m_maskGenerator;
- KisRandomSource m_randomSource; // TODO: make it more deterministic for LoD
-};
-
-#if defined HAVE_VC
-
-template<class MaskGenerator, Vc::Implementation _impl>
-struct KisBrushMaskVectorApplicator : public KisBrushMaskScalarApplicator<MaskGenerator, _impl>
-{
- KisBrushMaskVectorApplicator(MaskGenerator *maskGenerator)
- : KisBrushMaskScalarApplicator<MaskGenerator, _impl>(maskGenerator)
- {
- }
-
- void process(const QRect &rect) {
- startProcessing(rect, TypeHelper<MaskGenerator, _impl>());
- }
-
-protected:
- void processVector(const QRect &rect);
-
-private:
- template<class U, Vc::Implementation V> struct TypeHelper {};
-
-private:
- template<class U>
- inline void startProcessing(const QRect &rect, TypeHelper<U, Vc::ScalarImpl>) {
- KisBrushMaskScalarApplicator<MaskGenerator, _impl>::processScalar(rect);
- }
-
- template<class U, Vc::Implementation V>
- inline void startProcessing(const QRect &rect, TypeHelper<U, V>) {
- MaskGenerator *m_maskGenerator = KisBrushMaskScalarApplicator<MaskGenerator, _impl>::m_maskGenerator;
-
- if (m_maskGenerator->shouldVectorize()) {
- processVector(rect);
- } else {
- KisBrushMaskScalarApplicator<MaskGenerator, _impl>::processScalar(rect);
- }
- }
-};
-
-template<class MaskGenerator, Vc::Implementation _impl>
-void KisBrushMaskVectorApplicator<MaskGenerator, _impl>::processVector(const QRect &rect)
-{
- const MaskProcessingData *m_d = KisBrushMaskApplicatorBase::m_d;
- MaskGenerator *m_maskGenerator = KisBrushMaskScalarApplicator<MaskGenerator, _impl>::m_maskGenerator;
-
- qreal random = 1.0;
- quint8* dabPointer = m_d->device->data() + rect.y() * rect.width() * m_d->pixelSize;
- quint8 alphaValue = OPACITY_TRANSPARENT_U8;
- // this offset is needed when brush size is smaller then fixed device size
- int offset = (m_d->device->bounds().width() - rect.width()) * m_d->pixelSize;
-
- int width = rect.width();
-
- // We need to calculate with a multiple of the width of the simd register
- size_t alignOffset = 0;
- if (width % Vc::float_v::size() != 0) {
- alignOffset = Vc::float_v::size() - (width % Vc::float_v::size());
- }
- size_t simdWidth = width + alignOffset;
-
- float *buffer = Vc::malloc<float, Vc::AlignOnCacheline>(simdWidth);
-
- typename MaskGenerator::FastRowProcessor processor(m_maskGenerator);
-
- for (int y = rect.y(); y < rect.y() + rect.height(); y++) {
-
- processor.template process<_impl>(buffer, simdWidth, y, m_d->cosa, m_d->sina, m_d->centerX, m_d->centerY);
-
- if (m_d->randomness != 0.0 || m_d->density != 1.0) {
- for (int x = 0; x < width; x++) {
-
- if (m_d->randomness!= 0.0){
- random = (1.0 - m_d->randomness) + m_d->randomness * KisBrushMaskScalarApplicator<MaskGenerator, _impl>::m_randomSource.generateNormalized();
- }
-
- alphaValue = quint8( (OPACITY_OPAQUE_U8 - buffer[x]*255) * random);
-
- // avoid computation of random numbers if density is full
- if (m_d->density != 1.0){
- // compute density only for visible pixels of the mask
- if (alphaValue != OPACITY_TRANSPARENT_U8){
- if ( !(m_d->density >= KisBrushMaskScalarApplicator<MaskGenerator, _impl>::m_randomSource.generateNormalized()) ){
- alphaValue = OPACITY_TRANSPARENT_U8;
- }
- }
- }
-
- if (m_d->color) {
- memcpy(dabPointer, m_d->color, m_d->pixelSize);
- }
-
- m_d->colorSpace->applyAlphaU8Mask(dabPointer, &alphaValue, 1);
- dabPointer += m_d->pixelSize;
- }
- } else if (m_d->color) {
- m_d->colorSpace->fillInverseAlphaNormedFloatMaskWithColor(dabPointer, buffer, m_d->color, width);
- dabPointer += width * m_d->pixelSize;
- } else {
- m_d->colorSpace->applyInverseNormedFloatMask(dabPointer, buffer, width);
- dabPointer += width * m_d->pixelSize;
- }//endfor x
- dabPointer += offset;
- }//endfor y
- Vc::free(buffer);
-}
-
-#endif /* defined HAVE_VC */
-
-template<class MaskGenerator, Vc::Implementation _impl>
-void KisBrushMaskScalarApplicator<MaskGenerator, _impl>::processScalar(const QRect &rect)
-{
- const MaskProcessingData *m_d = KisBrushMaskApplicatorBase::m_d;
- MaskGenerator *m_maskGenerator = KisBrushMaskScalarApplicator<MaskGenerator, _impl>::m_maskGenerator;
-
- qreal random = 1.0;
- quint8* dabPointer = m_d->device->data() + rect.y() * rect.width() * m_d->pixelSize;
- quint8 alphaValue = OPACITY_TRANSPARENT_U8;
- // this offset is needed when brush size is smaller then fixed device size
- int offset = (m_d->device->bounds().width() - rect.width()) * m_d->pixelSize;
- int supersample = (m_maskGenerator->shouldSupersample() ? SUPERSAMPLING : 1);
- double invss = 1.0 / supersample;
- int samplearea = pow2(supersample);
- for (int y = rect.y(); y < rect.y() + rect.height(); y++) {
- for (int x = rect.x(); x < rect.x() + rect.width(); x++) {
- int value = 0;
- for (int sy = 0; sy < supersample; sy++) {
- for (int sx = 0; sx < supersample; sx++) {
- double x_ = x + sx * invss - m_d->centerX;
- double y_ = y + sy * invss - m_d->centerY;
- double maskX = m_d->cosa * x_ - m_d->sina * y_;
- double maskY = m_d->sina * x_ + m_d->cosa * y_;
- value += m_maskGenerator->valueAt(maskX, maskY);
- }
- }
- if (supersample != 1) value /= samplearea;
-
- if (m_d->randomness!= 0.0){
- random = (1.0 - m_d->randomness) + m_d->randomness * m_randomSource.generateNormalized();
- }
-
- alphaValue = quint8( (OPACITY_OPAQUE_U8 - value) * random);
-
- // avoid computation of random numbers if density is full
- if (m_d->density != 1.0){
- // compute density only for visible pixels of the mask
- if (alphaValue != OPACITY_TRANSPARENT_U8){
- if ( !(m_d->density >= m_randomSource.generateNormalized()) ){
- alphaValue = OPACITY_TRANSPARENT_U8;
- }
- }
- }
-
- if (m_d->color) {
- memcpy(dabPointer, m_d->color, static_cast<size_t>(m_d->pixelSize));
- }
-
- m_d->colorSpace->applyAlphaU8Mask(dabPointer, &alphaValue, 1);
- dabPointer += m_d->pixelSize;
- }//endfor x
- dabPointer += offset;
- }//endfor y
-}
-
-#endif /* __KIS_BRUSH_MASK_APPLICATORS_H */
diff --git a/libs/image/kis_brush_mask_applicator_factories.cpp b/libs/image/kis_brush_mask_processor_factories.cpp
similarity index 58%
copy from libs/image/kis_brush_mask_applicator_factories.cpp
copy to libs/image/kis_brush_mask_processor_factories.cpp
index 11f5688c5f..3989df79ce 100644
--- a/libs/image/kis_brush_mask_applicator_factories.cpp
+++ b/libs/image/kis_brush_mask_processor_factories.cpp
@@ -1,100 +1,44 @@
/*
* SPDX-FileCopyrightText: 2012 Dmitry Kazakov <dimula73 at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#include "kis_brush_mask_applicator_factories.h"
-#include "vc_extra_math.h"
+#include <compositeops/KoVcMultiArchBuildSupport.h>
+
+#if defined HAVE_VC
#include "kis_circle_mask_generator.h"
#include "kis_circle_mask_generator_p.h"
-#include "kis_gauss_circle_mask_generator_p.h"
+#include "kis_curve_circle_mask_generator.h"
#include "kis_curve_circle_mask_generator_p.h"
-#include "kis_gauss_rect_mask_generator_p.h"
+#include "kis_curve_rect_mask_generator.h"
#include "kis_curve_rect_mask_generator_p.h"
+#include "kis_gauss_circle_mask_generator.h"
+#include "kis_gauss_circle_mask_generator_p.h"
+#include "kis_gauss_rect_mask_generator.h"
+#include "kis_gauss_rect_mask_generator_p.h"
+#include "kis_rect_mask_generator.h"
#include "kis_rect_mask_generator_p.h"
-#include "kis_brush_mask_applicators.h"
#include "kis_brush_mask_applicator_base.h"
+#include "kis_brush_mask_vector_applicator.h"
+
+#include "vc_extra_math.h"
#define a(_s) #_s
#define b(_s) a(_s)
template<>
template<>
-MaskApplicatorFactory<KisMaskGenerator, KisBrushMaskScalarApplicator>::ReturnType
-MaskApplicatorFactory<KisMaskGenerator, KisBrushMaskScalarApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
-{
- return new KisBrushMaskScalarApplicator<KisMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
-}
-
-template<>
-template<>
-MaskApplicatorFactory<KisCircleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisCircleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
-{
- return new KisBrushMaskVectorApplicator<KisCircleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
-}
-
-template<>
-template<>
-MaskApplicatorFactory<KisGaussCircleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisGaussCircleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
-{
- return new KisBrushMaskVectorApplicator<KisGaussCircleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
-}
-
-template<>
-template<>
-MaskApplicatorFactory<KisCurveCircleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisCurveCircleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
-{
- return new KisBrushMaskVectorApplicator<KisCurveCircleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
-}
-
-template<>
-template<>
-MaskApplicatorFactory<KisRectangleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisRectangleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
-{
- return new KisBrushMaskVectorApplicator<KisRectangleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
-}
-
-template<>
-template<>
-MaskApplicatorFactory<KisGaussRectangleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisGaussRectangleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
-{
- return new KisBrushMaskVectorApplicator<KisGaussRectangleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
-}
-
-template<>
-template<>
-MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator>::ReturnType
-MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator>::create<Vc::CurrentImplementation::current()>(ParamType maskGenerator)
-{
- return new KisBrushMaskVectorApplicator<KisCurveRectangleMaskGenerator,Vc::CurrentImplementation::current()>(maskGenerator);
-}
-
-
-#if defined HAVE_VC
-
-struct KisCircleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisCircleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisCircleMaskGenerator::Private *d;
-};
-
-template<> void KisCircleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
+void FastRowProcessor<KisCircleMaskGenerator>::process<Vc::CurrentImplementation::current()>(float *buffer,
+ int width,
+ float y,
+ float cosa,
+ float sina,
+ float centerX,
+ float centerY)
{
const bool useSmoothing = d->copyOfAntialiasEdges;
@@ -102,7 +46,7 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
float sinay_ = sina * y_;
float cosay_ = cosa * y_;
- float* bufferPointer = buffer;
+ float *bufferPointer = buffer;
Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
@@ -122,8 +66,7 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_v vOne(Vc::One);
- for (size_t i=0; i < static_cast<size_t>(width); i+= Vc::float_v::size()){
-
+ for (size_t i = 0; i < static_cast<size_t>(width); i += Vc::float_v::size()) {
Vc::float_v x_ = currentIndices - vCenterX;
Vc::float_v xr = x_ * vCosa - vSinaY_;
@@ -141,7 +84,7 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_m vNormLowMask = vNormFade < vOne;
vNormFade.setZero(vNormLowMask);
- //255 * n * (normeFade - 1) / (normeFade - n)
+ // 255 * n * (normeFade - 1) / (normeFade - n)
Vc::float_v vFade = n * (vNormFade - vOne) / (vNormFade - n);
// Mask in the inner circle of the mask
@@ -164,28 +107,21 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
}
}
-
-struct KisGaussCircleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisGaussCircleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisGaussCircleMaskGenerator::Private *d;
-};
-
-template<> void KisGaussCircleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
+template<>
+template<>
+void FastRowProcessor<KisGaussCircleMaskGenerator>::process<Vc::CurrentImplementation::current()>(float *buffer,
+ int width,
+ float y,
+ float cosa,
+ float sina,
+ float centerX,
+ float centerY)
{
float y_ = y - centerY;
float sinay_ = sina * y_;
float cosay_ = cosa * y_;
- float* bufferPointer = buffer;
+ float *bufferPointer = buffer;
Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
@@ -205,8 +141,7 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_v vZero(Vc::Zero);
Vc::float_v vValMax(255.f);
- for (size_t i=0; i < static_cast<size_t>(width); i+= Vc::float_v::size()){
-
+ for (size_t i = 0; i < static_cast<size_t>(width); i += Vc::float_v::size()) {
Vc::float_v x_ = currentIndices - vCenterX;
Vc::float_v xr = x_ * vCosa - vSinaY_;
@@ -219,7 +154,8 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
if (!excludeMask.isFull()) {
Vc::float_v valDist = dist * vDistfactor;
- Vc::float_v fullFade = vAlphafactor * ( VcExtraMath::erf(valDist + vCenter) - VcExtraMath::erf(valDist - vCenter));
+ Vc::float_v fullFade =
+ vAlphafactor * (VcExtraMath::erf(valDist + vCenter) - VcExtraMath::erf(valDist - vCenter));
Vc::float_m mask;
// Mask in the inner circle of the mask
@@ -238,38 +174,31 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
vFade.store(bufferPointer, Vc::Aligned);
} else {
- dist.store(bufferPointer, Vc::Aligned);
- }
- currentIndices = currentIndices + increment;
+ dist.store(bufferPointer, Vc::Aligned);
+ }
+ currentIndices = currentIndices + increment;
- bufferPointer += Vc::float_v::size();
+ bufferPointer += Vc::float_v::size();
}
}
-struct KisCurveCircleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisCurveCircleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisCurveCircleMaskGenerator::Private *d;
-};
-
-
-template<> void KisCurveCircleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
+template<>
+template<>
+void FastRowProcessor<KisCurveCircleMaskGenerator>::process<Vc::CurrentImplementation::current()>(float *buffer,
+ int width,
+ float y,
+ float cosa,
+ float sina,
+ float centerX,
+ float centerY)
{
float y_ = y - centerY;
float sinay_ = sina * y_;
float cosay_ = cosa * y_;
- float* bufferPointer = buffer;
+ float *bufferPointer = buffer;
- qreal* curveDataPointer = d->curveData.data();
+ qreal *curveDataPointer = d->curveData.data();
Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
@@ -291,8 +220,7 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_v vOne(Vc::One);
Vc::float_v vZero(Vc::Zero);
- for (size_t i=0; i < static_cast<size_t>(width); i+= Vc::float_v::size()){
-
+ for (size_t i = 0; i < static_cast<size_t>(width); i += Vc::float_v::size()) {
Vc::float_v x_ = currentIndices - vCenterX;
Vc::float_v xr = x_ * vCosa - vSinaY_;
@@ -314,14 +242,12 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_m alphaMask = vAlphaValue < vZero;
vAlphaValue.setZero(alphaMask);
- vCurvedData.gather(curveDataPointer,vAlphaValue);
- vCurvedData1.gather(curveDataPointer,vAlphaValue + 1);
-// Vc::float_v vCurvedData1(curveDataPointer,vAlphaValue + 1);
+ vCurvedData.gather(curveDataPointer, vAlphaValue);
+ vCurvedData1.gather(curveDataPointer, vAlphaValue + 1);
+ // Vc::float_v vCurvedData1(curveDataPointer,vAlphaValue + 1);
// vAlpha
- Vc::float_v fullFade = (
- (vOne - alphaValueF) * vCurvedData +
- alphaValueF * vCurvedData1);
+ Vc::float_v fullFade = ((vOne - alphaValueF) * vCurvedData + alphaValueF * vCurvedData1);
Vc::float_m mask;
// Mask in the inner circle of the mask
@@ -338,41 +264,23 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
vFade.store(bufferPointer, Vc::Aligned);
} else {
- dist.store(bufferPointer, Vc::Aligned);
- }
- currentIndices = currentIndices + increment;
+ dist.store(bufferPointer, Vc::Aligned);
+ }
+ currentIndices = currentIndices + increment;
- bufferPointer += Vc::float_v::size();
+ bufferPointer += Vc::float_v::size();
}
}
-struct KisGaussRectangleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisGaussRectangleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisGaussRectangleMaskGenerator::Private *d;
-};
-
-struct KisRectangleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisRectangleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisRectangleMaskGenerator::Private *d;
-};
-
-template<> void KisRectangleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
+template<>
+template<>
+void FastRowProcessor<KisRectangleMaskGenerator>::process<Vc::CurrentImplementation::current()>(float *buffer,
+ int width,
+ float y,
+ float cosa,
+ float sina,
+ float centerX,
+ float centerY)
{
const bool useSmoothing = d->copyOfAntialiasEdges;
@@ -380,7 +288,7 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
float sinay_ = sina * y_;
float cosay_ = cosa * y_;
- float* bufferPointer = buffer;
+ float *bufferPointer = buffer;
Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
@@ -402,8 +310,7 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_v vZero(Vc::Zero);
Vc::float_v vTolerance(10000.f);
- for (size_t i=0; i < static_cast<size_t>(width); i+= Vc::float_v::size()){
-
+ for (size_t i = 0; i < static_cast<size_t>(width); i += Vc::float_v::size()) {
Vc::float_v x_ = currentIndices - vCenterX;
Vc::float_v xr = Vc::abs(x_ * vCosa - vSinaY_);
@@ -448,16 +355,21 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
}
}
-
-template<> void KisGaussRectangleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
+template<>
+template<>
+void FastRowProcessor<KisGaussRectangleMaskGenerator>::process<Vc::CurrentImplementation::current()>(float *buffer,
+ int width,
+ float y,
+ float cosa,
+ float sina,
+ float centerX,
+ float centerY)
{
float y_ = y - centerY;
float sinay_ = sina * y_;
float cosay_ = cosa * y_;
- float* bufferPointer = buffer;
+ float *bufferPointer = buffer;
Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
@@ -489,15 +401,17 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_v vValue;
// check if we need to apply fader on values
- Vc::float_m excludeMask = d->fadeMaker.needFade(xr,yr);
+ Vc::float_m excludeMask = d->fadeMaker.needFade(xr, yr);
vValue(excludeMask) = vOne;
if (!excludeMask.isFull()) {
- Vc::float_v fullFade = vValMax - (vAlphafactor * (VcExtraMath::erf((vhalfWidth + xr) * vXFade) + VcExtraMath::erf((vhalfWidth - xr) * vXFade))
- * (VcExtraMath::erf((vhalfHeight + yr) * vYFade) + VcExtraMath::erf((vhalfHeight - yr) * vYFade)));
+ Vc::float_v fullFade = vValMax
+ - (vAlphafactor
+ * (VcExtraMath::erf((vhalfWidth + xr) * vXFade) + VcExtraMath::erf((vhalfWidth - xr) * vXFade))
+ * (VcExtraMath::erf((vhalfHeight + yr) * vYFade) + VcExtraMath::erf((vhalfHeight - yr) * vYFade)));
// apply antialias fader
- d->fadeMaker.apply2DFader(fullFade,excludeMask,xr,yr);
+ d->fadeMaker.apply2DFader(fullFade, excludeMask, xr, yr);
Vc::float_m mask;
@@ -517,37 +431,31 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
vFade.store(bufferPointer, Vc::Aligned);
} else {
- vValue.store(bufferPointer, Vc::Aligned);
- }
- currentIndices = currentIndices + increment;
+ vValue.store(bufferPointer, Vc::Aligned);
+ }
+ currentIndices = currentIndices + increment;
- bufferPointer += Vc::float_v::size();
+ bufferPointer += Vc::float_v::size();
}
}
-struct KisCurveRectangleMaskGenerator::FastRowProcessor
-{
- FastRowProcessor(KisCurveRectangleMaskGenerator *maskGenerator)
- : d(maskGenerator->d.data()) {}
-
- template<Vc::Implementation _impl>
- void process(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY);
-
- KisCurveRectangleMaskGenerator::Private *d;
-};
-
-template<> void KisCurveRectangleMaskGenerator::
-FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, int width, float y, float cosa, float sina,
- float centerX, float centerY)
+template<>
+template<>
+void FastRowProcessor<KisCurveRectangleMaskGenerator>::process<Vc::CurrentImplementation::current()>(float *buffer,
+ int width,
+ float y,
+ float cosa,
+ float sina,
+ float centerX,
+ float centerY)
{
float y_ = y - centerY;
float sinay_ = sina * y_;
float cosay_ = cosa * y_;
- float* bufferPointer = buffer;
+ float *bufferPointer = buffer;
- qreal* curveDataPointer = d->curveData.data();
+ qreal *curveDataPointer = d->curveData.data();
Vc::float_v currentIndices = Vc::float_v::IndexesFromZero();
@@ -576,7 +484,7 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_v vValue;
// check if we need to apply fader on values
- Vc::float_m excludeMask = d->fadeMaker.needFade(xr,yr);
+ Vc::float_m excludeMask = d->fadeMaker.needFade(xr, yr);
vValue(excludeMask) = vOne;
if (!excludeMask.isFull()) {
@@ -588,8 +496,8 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
preSIndex(preSIndex > vOne) = vOne;
preTIndex(preTIndex > vOne) = vOne;
- Vc::float_v::IndexType sIndex( round(preSIndex * vCurveResolution));
- Vc::float_v::IndexType tIndex( round(preTIndex * vCurveResolution));
+ Vc::float_v::IndexType sIndex(round(preSIndex * vCurveResolution));
+ Vc::float_v::IndexType tIndex(round(preTIndex * vCurveResolution));
Vc::float_v::IndexType sIndexInverted = vCurveResolution - sIndex;
Vc::float_v::IndexType tIndexInverted = vCurveResolution - tIndex;
@@ -599,11 +507,13 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
Vc::float_v vCurvedDataSIndexInv(curveDataPointer, sIndexInverted);
Vc::float_v vCurvedDataTIndexInv(curveDataPointer, tIndexInverted);
- Vc::float_v fullFade = vValMax * (vOne - (vCurvedDataSIndex * (vOne - vCurvedDataSIndexInv) *
- vCurvedDataTIndex * (vOne - vCurvedDataTIndexInv)));
+ Vc::float_v fullFade = vValMax
+ * (vOne
+ - (vCurvedDataSIndex * (vOne - vCurvedDataSIndexInv) * vCurvedDataTIndex
+ * (vOne - vCurvedDataTIndexInv)));
// apply antialias fader
- d->fadeMaker.apply2DFader(fullFade,excludeMask,xr,yr);
+ d->fadeMaker.apply2DFader(fullFade, excludeMask, xr, yr);
Vc::float_m mask;
@@ -623,11 +533,11 @@ FastRowProcessor::process<Vc::CurrentImplementation::current()>(float* buffer, i
vFade.store(bufferPointer, Vc::Aligned);
} else {
- vValue.store(bufferPointer, Vc::Aligned);
- }
- currentIndices = currentIndices + increment;
+ vValue.store(bufferPointer, Vc::Aligned);
+ }
+ currentIndices = currentIndices + increment;
- bufferPointer += Vc::float_v::size();
+ bufferPointer += Vc::float_v::size();
}
}
diff --git a/libs/image/kis_brush_mask_scalar_applicator.h b/libs/image/kis_brush_mask_scalar_applicator.h
new file mode 100644
index 0000000000..51ca1a0656
--- /dev/null
+++ b/libs/image/kis_brush_mask_scalar_applicator.h
@@ -0,0 +1,92 @@
+/*
+ * SPDX-FileCopyrightText: 2012 Sven Langkamp <sven.langkamp at gmail.com>
+ * SPDX-FileCopyrightText: 2012 Dmitry Kazakov <dimula73 at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef KIS_BRUSH_SCALAR_APPLICATOR_H
+#define KIS_BRUSH_SCALAR_APPLICATOR_H
+
+#include "kis_brush_mask_applicator_base.h"
+#include "kis_global.h"
+#include "kis_random_source.h"
+
+// 3x3 supersampling
+#define SUPERSAMPLING 3
+
+template<class MaskGenerator, Vc::Implementation impl>
+struct KisBrushMaskScalarApplicator : public KisBrushMaskApplicatorBase {
+ KisBrushMaskScalarApplicator(MaskGenerator *maskGenerator)
+ : m_maskGenerator(maskGenerator)
+ {
+ }
+
+ void process(const QRect &rect) override
+ {
+ processScalar(rect);
+ }
+
+protected:
+ void processScalar(const QRect &rect)
+ {
+ const MaskProcessingData *m_d = KisBrushMaskApplicatorBase::m_d;
+ MaskGenerator *m_maskGenerator = KisBrushMaskScalarApplicator<MaskGenerator, impl>::m_maskGenerator;
+
+ qreal random = 1.0;
+ quint8 *dabPointer = m_d->device->data() + rect.y() * rect.width() * m_d->pixelSize;
+ quint8 alphaValue = OPACITY_TRANSPARENT_U8;
+ // this offset is needed when brush size is smaller then fixed device size
+ int offset = (m_d->device->bounds().width() - rect.width()) * m_d->pixelSize;
+ int supersample = (m_maskGenerator->shouldSupersample() ? SUPERSAMPLING : 1);
+ double invss = 1.0 / supersample;
+ int samplearea = pow2(supersample);
+ for (int y = rect.y(); y < rect.y() + rect.height(); y++) {
+ for (int x = rect.x(); x < rect.x() + rect.width(); x++) {
+ int value = 0;
+ for (int sy = 0; sy < supersample; sy++) {
+ for (int sx = 0; sx < supersample; sx++) {
+ double x_ = x + sx * invss - m_d->centerX;
+ double y_ = y + sy * invss - m_d->centerY;
+ double maskX = m_d->cosa * x_ - m_d->sina * y_;
+ double maskY = m_d->sina * x_ + m_d->cosa * y_;
+ value += m_maskGenerator->valueAt(maskX, maskY);
+ }
+ }
+ if (supersample != 1)
+ value /= samplearea;
+
+ if (m_d->randomness != 0.0) {
+ random = (1.0 - m_d->randomness) + m_d->randomness * m_randomSource.generateNormalized();
+ }
+
+ alphaValue = quint8((OPACITY_OPAQUE_U8 - value) * random);
+
+ // avoid computation of random numbers if density is full
+ if (m_d->density != 1.0) {
+ // compute density only for visible pixels of the mask
+ if (alphaValue != OPACITY_TRANSPARENT_U8) {
+ if (!(m_d->density >= m_randomSource.generateNormalized())) {
+ alphaValue = OPACITY_TRANSPARENT_U8;
+ }
+ }
+ }
+
+ if (m_d->color) {
+ memcpy(dabPointer, m_d->color, static_cast<size_t>(m_d->pixelSize));
+ }
+
+ m_d->colorSpace->applyAlphaU8Mask(dabPointer, &alphaValue, 1);
+ dabPointer += m_d->pixelSize;
+ } // endfor x
+ dabPointer += offset;
+ } // endfor y
+ }
+
+protected:
+ MaskGenerator *m_maskGenerator;
+ KisRandomSource m_randomSource; // TODO: make it more deterministic for LoD
+};
+
+#endif /* KIS_BRUSH_SCALAR_APPLICATOR_H */
diff --git a/libs/image/kis_brush_mask_vector_applicator.h b/libs/image/kis_brush_mask_vector_applicator.h
new file mode 100644
index 0000000000..dc53a369a1
--- /dev/null
+++ b/libs/image/kis_brush_mask_vector_applicator.h
@@ -0,0 +1,143 @@
+/*
+ * SPDX-FileCopyrightText: 2012 Sven Langkamp <sven.langkamp at gmail.com>
+ * SPDX-FileCopyrightText: 2012 Dmitry Kazakov <dimula73 at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef KIS_BRUSH_VECTOR_APPLICATOR_H
+#define KIS_BRUSH_VECTOR_APPLICATOR_H
+
+#include <config-vc.h>
+
+#if defined HAVE_VC
+
+#include <KoVcMultiArchBuildSupport.h>
+
+#include "kis_brush_mask_scalar_applicator.h"
+
+template<class V>
+struct FastRowProcessor {
+ FastRowProcessor(V *maskGenerator)
+ : d(maskGenerator->d.data())
+ {
+ }
+
+ template<Vc::Implementation _impl>
+ void process(float *buffer, int width, float y, float cosa, float sina, float centerX, float centerY);
+
+ typename V::Private *d;
+};
+
+template<class MaskGenerator, Vc::Implementation _impl>
+struct KisBrushMaskVectorApplicator : public KisBrushMaskScalarApplicator<MaskGenerator, _impl> {
+ KisBrushMaskVectorApplicator(MaskGenerator *maskGenerator)
+ : KisBrushMaskScalarApplicator<MaskGenerator, _impl>(maskGenerator)
+ {
+ }
+
+ void process(const QRect &rect) override
+ {
+ startProcessing(rect, TypeHelper<MaskGenerator, _impl>());
+ }
+
+protected:
+ void processVector(const QRect &rect);
+
+private:
+ template<class U, Vc::Implementation V>
+ struct TypeHelper {
+ };
+
+private:
+ template<class U>
+ inline void startProcessing(const QRect &rect, TypeHelper<U, Vc::ScalarImpl>)
+ {
+ KisBrushMaskScalarApplicator<MaskGenerator, _impl>::processScalar(rect);
+ }
+
+ template<class U, Vc::Implementation V>
+ inline void startProcessing(const QRect &rect, TypeHelper<U, V>)
+ {
+ MaskGenerator *m_maskGenerator = KisBrushMaskScalarApplicator<MaskGenerator, _impl>::m_maskGenerator;
+
+ if (m_maskGenerator->shouldVectorize()) {
+ processVector(rect);
+ } else {
+ KisBrushMaskScalarApplicator<MaskGenerator, _impl>::processScalar(rect);
+ }
+ }
+};
+
+template<class MaskGenerator, Vc::Implementation impl>
+void KisBrushMaskVectorApplicator<MaskGenerator, impl>::processVector(const QRect &rect)
+{
+ const MaskProcessingData *m_d = KisBrushMaskApplicatorBase::m_d;
+ MaskGenerator *m_maskGenerator = KisBrushMaskScalarApplicator<MaskGenerator, impl>::m_maskGenerator;
+
+ qreal random = 1.0;
+ quint8 *dabPointer = m_d->device->data() + rect.y() * rect.width() * m_d->pixelSize;
+ quint8 alphaValue = OPACITY_TRANSPARENT_U8;
+ // this offset is needed when brush size is smaller then fixed device size
+ int offset = (m_d->device->bounds().width() - rect.width()) * m_d->pixelSize;
+
+ int width = rect.width();
+
+ // We need to calculate with a multiple of the width of the simd register
+ size_t alignOffset = 0;
+ if (width % Vc::float_v::size() != 0) {
+ alignOffset = Vc::float_v::size() - (width % Vc::float_v::size());
+ }
+ size_t simdWidth = width + alignOffset;
+
+ float *buffer = Vc::malloc<float, Vc::AlignOnCacheline>(simdWidth);
+
+ FastRowProcessor<MaskGenerator> processor(m_maskGenerator);
+
+ for (int y = rect.y(); y < rect.y() + rect.height(); y++) {
+ processor.template process<impl>(buffer, simdWidth, y, m_d->cosa, m_d->sina, m_d->centerX, m_d->centerY);
+
+ if (m_d->randomness != 0.0 || m_d->density != 1.0) {
+ for (int x = 0; x < width; x++) {
+ if (m_d->randomness != 0.0) {
+ random = (1.0 - m_d->randomness)
+ + m_d->randomness
+ * KisBrushMaskScalarApplicator<MaskGenerator, impl>::m_randomSource.generateNormalized();
+ }
+
+ alphaValue = quint8((OPACITY_OPAQUE_U8 - buffer[x] * 255) * random);
+
+ // avoid computation of random numbers if density is full
+ if (m_d->density != 1.0) {
+ // compute density only for visible pixels of the mask
+ if (alphaValue != OPACITY_TRANSPARENT_U8) {
+ if (!(m_d->density >= KisBrushMaskScalarApplicator<MaskGenerator, impl>::m_randomSource
+ .generateNormalized())) {
+ alphaValue = OPACITY_TRANSPARENT_U8;
+ }
+ }
+ }
+
+ if (m_d->color) {
+ memcpy(dabPointer, m_d->color, m_d->pixelSize);
+ }
+
+ m_d->colorSpace->applyAlphaU8Mask(dabPointer, &alphaValue, 1);
+ dabPointer += m_d->pixelSize;
+ }
+ } else if (m_d->color) {
+ m_d->colorSpace->fillInverseAlphaNormedFloatMaskWithColor(dabPointer, buffer, m_d->color, width);
+ dabPointer += width * m_d->pixelSize;
+ } else {
+ m_d->colorSpace->applyInverseNormedFloatMask(dabPointer, buffer, width);
+ dabPointer += width * m_d->pixelSize;
+ } // endfor x
+ dabPointer += offset;
+ } // endfor y
+ Vc::free(buffer);
+}
+
+#endif /* defined HAVE_VC */
+
+#endif /* KIS_BRUSH_VECTOR_APPLICATOR_H */
diff --git a/libs/image/kis_circle_mask_generator.cpp b/libs/image/kis_circle_mask_generator.cpp
index 242ef11120..940c362770 100644
--- a/libs/image/kis_circle_mask_generator.cpp
+++ b/libs/image/kis_circle_mask_generator.cpp
@@ -8,25 +8,6 @@
#include <cmath>
-#include <config-vc.h>
-#ifdef HAVE_VC
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wundef"
-#pragma GCC diagnostic ignored "-Wlocal-type-template-args"
-#endif
-#if defined _MSC_VER
-// Lets shut up the "possible loss of data" and "forcing value to bool 'true' or 'false'
-#pragma warning ( push )
-#pragma warning ( disable : 4244 )
-#pragma warning ( disable : 4800 )
-#endif
-#include <Vc/Vc>
-#include <Vc/IO>
-#if defined _MSC_VER
-#pragma warning ( pop )
-#endif
-#endif
-
#include <QDomDocument>
#include "kis_fast_math.h"
@@ -46,14 +27,14 @@ KisCircleMaskGenerator::KisCircleMaskGenerator(qreal diameter, qreal ratio, qrea
// store the variable locally to allow vector implementation read it easily
d->copyOfAntialiasEdges = antialiasEdges;
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator> >(this));
}
KisCircleMaskGenerator::KisCircleMaskGenerator(const KisCircleMaskGenerator &rhs)
: KisMaskGenerator(rhs),
d(new Private(*rhs.d))
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator> >(this));
}
KisMaskGenerator* KisCircleMaskGenerator::clone() const
@@ -121,5 +102,5 @@ void KisCircleMaskGenerator::setSoftness(qreal softness)
void KisCircleMaskGenerator::resetMaskApplicator(bool forceScalar)
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this,forceScalar));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCircleMaskGenerator> >(this,forceScalar));
}
diff --git a/libs/image/kis_circle_mask_generator.h b/libs/image/kis_circle_mask_generator.h
index 4d93fc5194..fa55bcdecb 100644
--- a/libs/image/kis_circle_mask_generator.h
+++ b/libs/image/kis_circle_mask_generator.h
@@ -1,5 +1,6 @@
/*
* SPDX-FileCopyrightText: 2008-2009 Cyrille Berger <cberger at cberger.net>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -9,17 +10,17 @@
#include "kritaimage_export.h"
-#include "kis_mask_generator.h"
+#include "kis_base_mask_generator.h"
#include <QScopedPointer>
+template <typename V>
+class FastRowProcessor;
/**
* Create, serialize and deserialize an elliptical 8-bit mask.
*/
class KRITAIMAGE_EXPORT KisCircleMaskGenerator : public KisMaskGenerator
{
-public:
- struct FastRowProcessor;
public:
KisCircleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges);
KisCircleMaskGenerator(const KisCircleMaskGenerator &rhs);
@@ -46,6 +47,8 @@ private:
private:
struct Private;
const QScopedPointer<Private> d;
+
+ friend class FastRowProcessor<KisCircleMaskGenerator>;
};
#endif
diff --git a/libs/image/kis_curve_circle_mask_generator.cpp b/libs/image/kis_curve_circle_mask_generator.cpp
index 787ce89129..b41960740d 100644
--- a/libs/image/kis_curve_circle_mask_generator.cpp
+++ b/libs/image/kis_curve_circle_mask_generator.cpp
@@ -4,37 +4,14 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#include <compositeops/KoVcMultiArchBuildSupport.h> //MSVC requires that Vc come first
#include <cmath>
-#include <config-vc.h>
-#ifdef HAVE_VC
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wundef"
-#pragma GCC diagnostic ignored "-Wlocal-type-template-args"
-#endif
-#if defined _MSC_VER
-// Lets shut up the "possible loss of data" and "forcing value to bool 'true' or 'false'
-#pragma warning ( push )
-#pragma warning ( disable : 4244 )
-#pragma warning ( disable : 4800 )
-#endif
-#include <Vc/Vc>
-#include <Vc/IO>
-#if defined _MSC_VER
-#pragma warning ( pop )
-#endif
-#endif
-
#include <QDomDocument>
#include <QVector>
#include <QPointF>
#include <KoColorSpaceConstants.h>
-#include "kis_fast_math.h"
-
-#include "kis_base_mask_generator.h"
#include "kis_antialiasing_fade_maker.h"
#include "kis_brush_mask_applicator_factories.h"
@@ -55,14 +32,14 @@ KisCurveCircleMaskGenerator::KisCurveCircleMaskGenerator(qreal diameter, qreal r
setScale(1.0, 1.0);
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveCircleMaskGenerator> >(this));
}
KisCurveCircleMaskGenerator::KisCurveCircleMaskGenerator(const KisCurveCircleMaskGenerator &rhs)
: KisMaskGenerator(rhs),
d(new Private(*rhs.d))
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveCircleMaskGenerator> >(this));
}
KisCurveCircleMaskGenerator::~KisCurveCircleMaskGenerator()
@@ -171,5 +148,5 @@ void KisCurveCircleMaskGenerator::transformCurveForSoftness(qreal softness,const
void KisCurveCircleMaskGenerator::resetMaskApplicator(bool forceScalar)
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this,forceScalar));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveCircleMaskGenerator> >(this,forceScalar));
}
diff --git a/libs/image/kis_curve_circle_mask_generator.h b/libs/image/kis_curve_circle_mask_generator.h
index 7e58497294..205d76e7ca 100644
--- a/libs/image/kis_curve_circle_mask_generator.h
+++ b/libs/image/kis_curve_circle_mask_generator.h
@@ -1,5 +1,6 @@
/*
* SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -12,7 +13,7 @@
#include <QScopedPointer>
#include "kritaimage_export.h"
-#include "kis_mask_generator.h"
+#include "kis_base_mask_generator.h"
class KisCubicCurve;
class QDomElement;
@@ -20,6 +21,8 @@ class QDomDocument;
class QPointF;
+template<typename V>
+class FastRowProcessor;
/**
* This mask generator use softness/hardness defined by user curve
@@ -27,8 +30,6 @@ class QPointF;
*/
class KRITAIMAGE_EXPORT KisCurveCircleMaskGenerator : public KisMaskGenerator
{
-public:
- struct FastRowProcessor;
public:
KisCurveCircleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes,const KisCubicCurve& curve, bool antialiasEdges);
@@ -59,6 +60,8 @@ private:
private:
struct Private;
const QScopedPointer<Private> d;
+
+ friend class FastRowProcessor<KisCurveCircleMaskGenerator>;
};
#endif
diff --git a/libs/image/kis_curve_rect_mask_generator.cpp b/libs/image/kis_curve_rect_mask_generator.cpp
index c02d12a206..f374326c22 100644
--- a/libs/image/kis_curve_rect_mask_generator.cpp
+++ b/libs/image/kis_curve_rect_mask_generator.cpp
@@ -4,29 +4,8 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#include <compositeops/KoVcMultiArchBuildSupport.h> //MSVC requires that Vc come first
-
#include <cmath>
-#include <config-vc.h>
-#ifdef HAVE_VC
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wundef"
-#pragma GCC diagnostic ignored "-Wlocal-type-template-args"
-#endif
-#if defined _MSC_VER
-// Lets shut up the "possible loss of data" and "forcing value to bool 'true' or 'false'
-#pragma warning ( push )
-#pragma warning ( disable : 4244 )
-#pragma warning ( disable : 4800 )
-#endif
-#include <Vc/Vc>
-#include <Vc/IO>
-#if defined _MSC_VER
-#pragma warning ( pop )
-#endif
-#endif
-
#include <QDomDocument>
#include <QVector>
#include <QPointF>
@@ -38,6 +17,7 @@
#include "kis_curve_rect_mask_generator.h"
#include "kis_curve_rect_mask_generator_p.h"
+#include "kis_curve_circle_mask_generator.h"
#include "kis_cubic_curve.h"
@@ -52,14 +32,14 @@ KisCurveRectangleMaskGenerator::KisCurveRectangleMaskGenerator(qreal diameter, q
setScale(1.0, 1.0);
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator>>(this));
}
KisCurveRectangleMaskGenerator::KisCurveRectangleMaskGenerator(const KisCurveRectangleMaskGenerator &rhs)
: KisMaskGenerator(rhs),
d(new Private(*rhs.d))
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator>>(this));
}
KisMaskGenerator* KisCurveRectangleMaskGenerator::clone() const
@@ -144,6 +124,6 @@ KisBrushMaskApplicatorBase* KisCurveRectangleMaskGenerator::applicator()
void KisCurveRectangleMaskGenerator::resetMaskApplicator(bool forceScalar)
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this,forceScalar));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisCurveRectangleMaskGenerator>>(this,forceScalar));
}
diff --git a/libs/image/kis_curve_rect_mask_generator.h b/libs/image/kis_curve_rect_mask_generator.h
index 3d613032ed..4f05d63b54 100644
--- a/libs/image/kis_curve_rect_mask_generator.h
+++ b/libs/image/kis_curve_rect_mask_generator.h
@@ -1,5 +1,6 @@
/*
* SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -13,15 +14,16 @@ class KisCubicCurve;
class QDomElement;
class QDomDocument;
-#include "kis_mask_generator.h"
+#include "kis_base_mask_generator.h"
+
+template<typename V>
+class FastRowProcessor;
/**
* Curve based softness for this rectangular mask generator
*/
class KRITAIMAGE_EXPORT KisCurveRectangleMaskGenerator : public KisMaskGenerator
{
-public:
- struct FastRowProcessor;
public:
KisCurveRectangleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes, const KisCubicCurve& curve, bool antialiasEdges);
@@ -44,6 +46,8 @@ public:
private:
struct Private;
const QScopedPointer<Private> d;
+
+ friend class FastRowProcessor<KisCurveRectangleMaskGenerator>;
};
#endif
diff --git a/libs/image/kis_gauss_circle_mask_generator.cpp b/libs/image/kis_gauss_circle_mask_generator.cpp
index 476413088f..fbd5bf07ae 100644
--- a/libs/image/kis_gauss_circle_mask_generator.cpp
+++ b/libs/image/kis_gauss_circle_mask_generator.cpp
@@ -5,28 +5,8 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#include <compositeops/KoVcMultiArchBuildSupport.h> //MSVC requires that Vc come first
#include <cmath>
-#include <config-vc.h>
-#ifdef HAVE_VC
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wundef"
-#pragma GCC diagnostic ignored "-Wlocal-type-template-args"
-#endif
-#if defined _MSC_VER
-// Lets shut up the "possible loss of data" and "forcing value to bool 'true' or 'false'
-#pragma warning ( push )
-#pragma warning ( disable : 4244 )
-#pragma warning ( disable : 4800 )
-#endif
-#include <Vc/Vc>
-#include <Vc/IO>
-#if defined _MSC_VER
-#pragma warning ( pop )
-#endif
-#endif
-
#include <QDomDocument>
#include <QVector>
#include <QPointF>
@@ -64,7 +44,7 @@ KisGaussCircleMaskGenerator::KisGaussCircleMaskGenerator(qreal diameter, qreal r
d->center = (2.5 * (6761.0*d->fade-10000.0))/(M_SQRT_2*6761.0*d->fade);
d->alphafactor = 255.0 / (2.0 * erf(d->center));
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussCircleMaskGenerator>>(this));
}
@@ -72,7 +52,7 @@ KisGaussCircleMaskGenerator::KisGaussCircleMaskGenerator(const KisGaussCircleMas
: KisMaskGenerator(rhs),
d(new Private(*rhs.d))
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussCircleMaskGenerator>>(this));
}
KisMaskGenerator* KisGaussCircleMaskGenerator::clone() const
@@ -129,5 +109,5 @@ quint8 KisGaussCircleMaskGenerator::valueAt(qreal x, qreal y) const
void KisGaussCircleMaskGenerator::resetMaskApplicator(bool forceScalar)
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussCircleMaskGenerator, KisBrushMaskVectorApplicator> >(this,forceScalar));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussCircleMaskGenerator>>(this,forceScalar));
}
diff --git a/libs/image/kis_gauss_circle_mask_generator.h b/libs/image/kis_gauss_circle_mask_generator.h
index 604ad64ab3..ab431e81a6 100644
--- a/libs/image/kis_gauss_circle_mask_generator.h
+++ b/libs/image/kis_gauss_circle_mask_generator.h
@@ -1,6 +1,7 @@
/*
* SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev at gmail.com>
* SPDX-FileCopyrightText: 2011 Geoffry Song <goffrie at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -10,18 +11,18 @@
#include "kritaimage_export.h"
-#include "kis_mask_generator.h"
+#include "kis_base_mask_generator.h"
#include <QScopedPointer>
+template<typename V>
+class FastRowProcessor;
+
/**
* This mask generator uses a Gaussian-blurred circle
*/
class KRITAIMAGE_EXPORT KisGaussCircleMaskGenerator : public KisMaskGenerator
{
public:
- struct FastRowProcessor;
-public:
-
KisGaussCircleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges);
KisGaussCircleMaskGenerator(const KisGaussCircleMaskGenerator &rhs);
~KisGaussCircleMaskGenerator() override;
@@ -45,6 +46,8 @@ private:
private:
struct Private;
const QScopedPointer<Private> d;
+
+ friend class FastRowProcessor<KisGaussCircleMaskGenerator>;
};
#endif
diff --git a/libs/image/kis_gauss_rect_mask_generator.cpp b/libs/image/kis_gauss_rect_mask_generator.cpp
index d5c6bb8aa1..80676cd82f 100644
--- a/libs/image/kis_gauss_rect_mask_generator.cpp
+++ b/libs/image/kis_gauss_rect_mask_generator.cpp
@@ -1,32 +1,14 @@
/*
* SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev at gmail.com>
* SPDX-FileCopyrightText: 2011 Geoffry Song <goffrie at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#include <compositeops/KoVcMultiArchBuildSupport.h> //MSVC requires that Vc come first
#include <cmath>
#include <algorithm>
-#include <config-vc.h>
-#ifdef HAVE_VC
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wundef"
-#pragma GCC diagnostic ignored "-Wlocal-type-template-args"
-#endif
-#if defined _MSC_VER
-// Lets shut up the "possible loss of data" and "forcing value to bool 'true' or 'false'
-#pragma warning ( push )
-#pragma warning ( disable : 4244 )
-#pragma warning ( disable : 4800 )
-#endif
-#include <Vc/Vc>
-#include <Vc/IO>
-#if defined _MSC_VER
-#pragma warning ( pop )
-#endif
-#endif
#include <QDomDocument>
#include <QVector>
@@ -58,14 +40,14 @@ KisGaussRectangleMaskGenerator::KisGaussRectangleMaskGenerator(qreal diameter, q
{
setScale(1.0, 1.0);
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussRectangleMaskGenerator>>(this));
}
KisGaussRectangleMaskGenerator::KisGaussRectangleMaskGenerator(const KisGaussRectangleMaskGenerator &rhs)
: KisMaskGenerator(rhs),
d(new Private(*rhs.d))
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussRectangleMaskGenerator>>(this));
}
KisMaskGenerator* KisGaussRectangleMaskGenerator::clone() const
@@ -130,5 +112,5 @@ KisBrushMaskApplicatorBase* KisGaussRectangleMaskGenerator::applicator()
void KisGaussRectangleMaskGenerator::resetMaskApplicator(bool forceScalar)
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this,forceScalar));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisGaussRectangleMaskGenerator>>(this,forceScalar));
}
diff --git a/libs/image/kis_gauss_rect_mask_generator.h b/libs/image/kis_gauss_rect_mask_generator.h
index ce96a5091f..1594e80f48 100644
--- a/libs/image/kis_gauss_rect_mask_generator.h
+++ b/libs/image/kis_gauss_rect_mask_generator.h
@@ -1,6 +1,7 @@
/*
* SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev at gmail.com>
* SPDX-FileCopyrightText: 2011 Geoffry Song <goffrie at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -10,15 +11,16 @@
#include "kritaimage_export.h"
-#include "kis_mask_generator.h"
+#include "kis_base_mask_generator.h"
+
+template<typename V>
+class FastRowProcessor;
/**
* This mask generator uses a Gaussian-blurred rectangle
*/
class KRITAIMAGE_EXPORT KisGaussRectangleMaskGenerator : public KisMaskGenerator
{
-public:
- struct FastRowProcessor;
public:
KisGaussRectangleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges);
@@ -36,6 +38,8 @@ public:
private:
struct Private;
const QScopedPointer<Private> d;
+
+ friend class FastRowProcessor<KisGaussRectangleMaskGenerator>;
};
#endif
diff --git a/libs/image/kis_rect_mask_generator.cpp b/libs/image/kis_rect_mask_generator.cpp
index c26832d318..f9cf0822ec 100644
--- a/libs/image/kis_rect_mask_generator.cpp
+++ b/libs/image/kis_rect_mask_generator.cpp
@@ -1,32 +1,13 @@
/*
* SPDX-FileCopyrightText: 2004, 2007-2010 Cyrille Berger <cberger at cberger.net>
* SPDX-FileCopyrightText: 2018 Ivan Santa Maria <ghevan at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#include <compositeops/KoVcMultiArchBuildSupport.h> //MSVC requires that Vc come first
#include <cmath>
-#include <config-vc.h>
-#ifdef HAVE_VC
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wundef"
-#pragma GCC diagnostic ignored "-Wlocal-type-template-args"
-#endif
-#if defined _MSC_VER
-// Lets shut up the "possible loss of data" and "forcing value to bool 'true' or 'false'
-#pragma warning ( push )
-#pragma warning ( disable : 4244 )
-#pragma warning ( disable : 4800 )
-#endif
-#include <Vc/Vc>
-#include <Vc/IO>
-#if defined _MSC_VER
-#pragma warning ( pop )
-#endif
-#endif
-
#include <QDomDocument>
@@ -47,14 +28,14 @@ KisRectangleMaskGenerator::KisRectangleMaskGenerator(qreal radius, qreal ratio,
// store the variable locally to allow vector implementation read it easily
d->copyOfAntialiasEdges = antialiasEdges;
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator>>(this));
}
KisRectangleMaskGenerator::KisRectangleMaskGenerator(const KisRectangleMaskGenerator &rhs)
: KisMaskGenerator(rhs),
d(new Private(*rhs.d))
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator>>(this));
}
KisMaskGenerator* KisRectangleMaskGenerator::clone() const
@@ -99,7 +80,7 @@ KisBrushMaskApplicatorBase* KisRectangleMaskGenerator::applicator()
void KisRectangleMaskGenerator::resetMaskApplicator(bool forceScalar)
{
- d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator, KisBrushMaskVectorApplicator> >(this,forceScalar));
+ d->applicator.reset(createOptimizedClass<MaskApplicatorFactory<KisRectangleMaskGenerator>>(this,forceScalar));
}
quint8 KisRectangleMaskGenerator::valueAt(qreal x, qreal y) const
diff --git a/libs/image/kis_rect_mask_generator.h b/libs/image/kis_rect_mask_generator.h
index 84fe295acc..01b8210994 100644
--- a/libs/image/kis_rect_mask_generator.h
+++ b/libs/image/kis_rect_mask_generator.h
@@ -1,6 +1,7 @@
/*
* SPDX-FileCopyrightText: 2008-2009 Cyrille Berger <cberger at cberger.net>
* SPDX-FileCopyrightText: 2018 Ivan Santa Maria <ghevan at gmail.com>
+ * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy at amyspark.me>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@@ -8,18 +9,20 @@
#ifndef _KIS_RECT_MASK_GENERATOR_H_
#define _KIS_RECT_MASK_GENERATOR_H_
-#include <QScopedPointer>
#include "kritaimage_export.h"
-#include "kis_mask_generator.h"
+#include <QScopedPointer>
+
+#include "kis_base_mask_generator.h"
+
+template<typename V>
+class FastRowProcessor;
/**
* Represent, serialize and deserialize a rectangular 8-bit mask.
*/
class KRITAIMAGE_EXPORT KisRectangleMaskGenerator : public KisMaskGenerator
{
-public:
- struct FastRowProcessor;
public:
KisRectangleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges);
@@ -39,6 +42,8 @@ public:
private:
struct Private;
const QScopedPointer<Private> d;
+
+ friend class FastRowProcessor<KisRectangleMaskGenerator>;
};
#endif
More information about the kimageshop
mailing list