diff --git a/libs/image/kis_antialiasing_fade_maker.h b/libs/image/kis_antialiasing_fade_maker.h index 005337c5b5..ed2cd5e9ab 100644 --- a/libs/image/kis_antialiasing_fade_maker.h +++ b/libs/image/kis_antialiasing_fade_maker.h @@ -1,222 +1,227 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ANTIALIASING_FADE_MAKER_H #define __KIS_ANTIALIASING_FADE_MAKER_H #include "kis_global.h" template class KisAntialiasingFadeMaker1D { public: KisAntialiasingFadeMaker1D(const BaseFade &baseFade, bool enableAntialiasing) : m_radius(0.0), m_fadeStartValue(0), m_antialiasingFadeStart(0), m_antialiasingFadeCoeff(0), m_enableAntialiasing(enableAntialiasing), m_baseFade(baseFade) { } KisAntialiasingFadeMaker1D(const KisAntialiasingFadeMaker1D &rhs, const BaseFade &baseFade) : m_radius(rhs.m_radius), m_fadeStartValue(rhs.m_fadeStartValue), m_antialiasingFadeStart(rhs.m_antialiasingFadeStart), m_antialiasingFadeCoeff(rhs.m_antialiasingFadeCoeff), m_enableAntialiasing(rhs.m_enableAntialiasing), m_baseFade(baseFade) { } void setSquareNormCoeffs(qreal xcoeff, qreal ycoeff) { m_radius = 1.0; qreal xf = qMax(0.0, ((1.0 / xcoeff) - 1.0) * xcoeff); qreal yf = qMax(0.0, ((1.0 / ycoeff) - 1.0) * ycoeff); m_antialiasingFadeStart = pow2(0.5 * (xf + yf)); m_fadeStartValue = m_baseFade.value(m_antialiasingFadeStart); m_antialiasingFadeCoeff = qMax(0.0, 255.0 - m_fadeStartValue) / (m_radius - m_antialiasingFadeStart); } void setRadius(qreal radius) { m_radius = radius; m_antialiasingFadeStart = qMax(0.0, m_radius - 1.0); m_fadeStartValue = m_baseFade.value(m_antialiasingFadeStart); m_antialiasingFadeCoeff = qMax(0.0, 255.0 - m_fadeStartValue) / (m_radius - m_antialiasingFadeStart); } inline bool needFade(qreal dist, quint8 *value) { if (dist > m_radius) { *value = 255; return true; } if (!m_enableAntialiasing) { return false; } if (dist > m_antialiasingFadeStart) { *value = m_fadeStartValue + (dist - m_antialiasingFadeStart) * m_antialiasingFadeCoeff; return true; } return false; } - qreal getRadius(){ - return m_radius; - } +#if defined HAVE_VC + Vc::float_m needFade(Vc::float_v &dist) { + const Vc::float_v vOne(Vc::One); + const Vc::float_v vValMax(255.f); - qreal getAntialiasingFadeStart(){ - return m_antialiasingFadeStart; - } + Vc::float_v vRadius(m_radius); + Vc::float_v vFadeStartValue(m_fadeStartValue); + Vc::float_v vAntialiasingFadeStart(m_antialiasingFadeStart); + Vc::float_v vAntialiasingFadeCoeff(m_antialiasingFadeCoeff); - qreal getFadeStartValue() { - return m_fadeStartValue; - } + Vc::float_m outsideMask = dist > vRadius; + dist(outsideMask) = vOne; - qreal getAntialiasingFadeCoeff(){ - return m_antialiasingFadeCoeff; - } + Vc::float_m fadeStartMask(false); - bool getAliasingEnabled(){ - return m_enableAntialiasing; + if(m_enableAntialiasing){ + fadeStartMask = dist > vAntialiasingFadeStart; + dist((outsideMask ^ fadeStartMask) & fadeStartMask) = (vFadeStartValue + + (dist - vAntialiasingFadeStart) * vAntialiasingFadeCoeff) / vValMax; + } + return (outsideMask | fadeStartMask); } +#endif /* defined HAVE_VC */ + private: qreal m_radius; quint8 m_fadeStartValue; qreal m_antialiasingFadeStart; qreal m_antialiasingFadeCoeff; bool m_enableAntialiasing; const BaseFade &m_baseFade; }; template class KisAntialiasingFadeMaker2D { public: KisAntialiasingFadeMaker2D(const BaseFade &baseFade, bool enableAntialiasing) : m_xLimit(0), m_yLimit(0), m_xFadeLimitStart(0), m_yFadeLimitStart(0), m_xFadeCoeff(0), m_yFadeCoeff(0), m_enableAntialiasing(enableAntialiasing), m_baseFade(baseFade) { } KisAntialiasingFadeMaker2D(const KisAntialiasingFadeMaker2D &rhs, const BaseFade &baseFade) : m_xLimit(rhs.m_xLimit), m_yLimit(rhs.m_yLimit), m_xFadeLimitStart(rhs.m_xFadeLimitStart), m_yFadeLimitStart(rhs.m_yFadeLimitStart), m_xFadeCoeff(rhs.m_xFadeCoeff), m_yFadeCoeff(rhs.m_yFadeCoeff), m_enableAntialiasing(rhs.m_enableAntialiasing), m_baseFade(baseFade) { } void setLimits(qreal halfWidth, qreal halfHeight) { m_xLimit = halfWidth; m_yLimit = halfHeight; m_xFadeLimitStart = m_xLimit - 1.0; m_yFadeLimitStart = m_yLimit - 1.0; m_xFadeCoeff = 1.0 / (m_xLimit - m_xFadeLimitStart); m_yFadeCoeff = 1.0 / (m_yLimit - m_yFadeLimitStart); } inline bool needFade(qreal x, qreal y, quint8 *value) { x = qAbs(x); y = qAbs(y); if (x > m_xLimit) { *value = 255; return true; } if (y > m_yLimit) { *value = 255; return true; } if (!m_enableAntialiasing) { return false; } if (x > m_xFadeLimitStart) { quint8 baseValue = m_baseFade.value(x, y); *value = baseValue + (255.0 - baseValue) * (x - m_xFadeLimitStart) * m_xFadeCoeff; if (y > m_yFadeLimitStart && *value < 255) { *value += (255.0 - *value) * (y - m_yFadeLimitStart) * m_yFadeCoeff; } return true; } if (y > m_yFadeLimitStart) { quint8 baseValue = m_baseFade.value(x, y); *value = baseValue + (255.0 - baseValue) * (y - m_yFadeLimitStart) * m_yFadeCoeff; if (x > m_xFadeLimitStart && *value < 255) { *value += (255.0 - *value) * (x - m_xFadeLimitStart) * m_xFadeCoeff; } return true; } return false; } qreal getXLimit() { return m_xLimit; } qreal getYLimit() { return m_yLimit; } qreal getXFadeLimitStart() { return m_xFadeLimitStart; } qreal getYFadeLimitStart() { return m_yFadeLimitStart; } qreal getXFadeCoeff(){ return m_xFadeCoeff; } qreal getYFadeCoeff(){ return m_yFadeCoeff; } bool getAliasingEnabled() { return m_enableAntialiasing; } private: qreal m_xLimit; qreal m_yLimit; qreal m_xFadeLimitStart; qreal m_yFadeLimitStart; qreal m_xFadeCoeff; qreal m_yFadeCoeff; bool m_enableAntialiasing; const BaseFade &m_baseFade; }; #endif /* __KIS_ANTIALIASING_FADE_MAKER_H */ diff --git a/libs/image/kis_brush_mask_applicator_factories.cpp b/libs/image/kis_brush_mask_applicator_factories.cpp index 27066311bd..148e5c51c9 100644 --- a/libs/image/kis_brush_mask_applicator_factories.cpp +++ b/libs/image/kis_brush_mask_applicator_factories.cpp @@ -1,516 +1,479 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #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_brush_mask_applicators.h" #include "kis_brush_mask_applicator_base.h" #define a(_s) #_s #define b(_s) a(_s) template<> template<> MaskApplicatorFactory::ReturnType MaskApplicatorFactory::create(ParamType maskGenerator) { return new KisBrushMaskScalarApplicator(maskGenerator); } template<> template<> MaskApplicatorFactory::ReturnType MaskApplicatorFactory::create(ParamType maskGenerator) { return new KisBrushMaskVectorApplicator(maskGenerator); } template<> template<> MaskApplicatorFactory::ReturnType MaskApplicatorFactory::create(ParamType maskGenerator) { return new KisBrushMaskVectorApplicator(maskGenerator); } template<> template<> MaskApplicatorFactory::ReturnType MaskApplicatorFactory::create(ParamType maskGenerator) { return new KisBrushMaskVectorApplicator(maskGenerator); } template<> template<> MaskApplicatorFactory::ReturnType MaskApplicatorFactory::create(ParamType maskGenerator) { return new KisBrushMaskVectorApplicator(maskGenerator); } #if defined HAVE_VC struct KisCircleMaskGenerator::FastRowProcessor { FastRowProcessor(KisCircleMaskGenerator *maskGenerator) : d(maskGenerator->d.data()) {} template void process(float* buffer, int width, float y, float cosa, float sina, float centerX, float centerY); KisCircleMaskGenerator::Private *d; }; template<> void KisCircleMaskGenerator:: FastRowProcessor::process(float* buffer, int width, float y, float cosa, float sina, float centerX, float centerY) { const bool useSmoothing = d->copyOfAntialiasEdges; const bool noFading = d->noFading; 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(d->xcoef); Vc::float_v vYCoeff(d->ycoef); Vc::float_v vTransformedFadeX(d->transformedFadeX); Vc::float_v vTransformedFadeY(d->transformedFadeY); Vc::float_v vOne(Vc::One); for (int i=0; i < 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 (noFading) { Vc::float_v vFade(Vc::Zero); vFade(outsideMask) = vOne; vFade.store(bufferPointer, Vc::Aligned); } else { if (useSmoothing) { xr = Vc::abs(xr) + vOne; yr = Vc::abs(yr) + vOne; } Vc::float_v vNormFade = pow2(xr * vTransformedFadeX) + pow2(yr * vTransformedFadeY); //255 * n * (normeFade - 1) / (normeFade - n) Vc::float_v vFade = n * (vNormFade - vOne) / (vNormFade - n); // Mask in the inner circe of the mask Vc::float_m mask = vNormFade < vOne; vFade.setZero(mask); // Mask out the outer circe 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 void process(float* buffer, int width, float y, float cosa, float sina, float centerX, float centerY); KisGaussCircleMaskGenerator::Private *d; }; template<> void KisGaussCircleMaskGenerator:: FastRowProcessor::process(float* buffer, int width, float y, float cosa, float sina, float centerX, float centerY) { - const bool antialiasOn = d->fadeMaker.getAliasingEnabled(); - 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 vCenter(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(d->ycoef); Vc::float_v vDistfactor(d->distfactor); Vc::float_v vAlphafactor(d->alphafactor); - Vc::float_v vFadeRadius(d->fadeMaker.getRadius()); - Vc::float_v vFadeStartValue(d->fadeMaker.getFadeStartValue()); - Vc::float_v vFadeAFadeStart(d->fadeMaker.getAntialiasingFadeStart()); - Vc::float_v vFadeAFadeCoeff(d->fadeMaker.getAntialiasingFadeCoeff()); - - Vc::float_v vOne(Vc::One); Vc::float_v vZero(Vc::Zero); Vc::float_v vValMax(255.f); for (int i=0; i < 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)); - // BEGIN FadeMaker needFade vectorized - // follow fademaker rules for outsideMask - Vc::float_m outsideMask = dist > vFadeRadius; - dist(outsideMask) = vOne; - - Vc::float_m fadeStartMask(false); - // if antialias is off, do not process - if(antialiasOn){ - fadeStartMask = dist > vFadeAFadeStart; - dist((outsideMask ^ fadeStartMask) & fadeStartMask) = (vFadeStartValue + (dist - vFadeAFadeStart) * vFadeAFadeCoeff) / vValMax; - } - Vc::float_m excludeMask(outsideMask | fadeStartMask); + // 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 undefined values, out of range are out of mask mask = Vc::isfinite(fullFade); fullFade.setZero(!mask); // Mask in the inner circe of the mask mask = fullFade < vZero; fullFade.setZero(mask); // Mask the outter circle mask = fullFade > 254.974f; fullFade(mask) = vValMax; // Mask (value - value), presicion 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 void process(float* buffer, int width, float y, float cosa, float sina, float centerX, float centerY); KisCurveCircleMaskGenerator::Private *d; }; template<> void KisCurveCircleMaskGenerator:: FastRowProcessor::process(float* buffer, int width, float y, float cosa, float sina, float centerX, float centerY) { - const bool antialiasOn = d->fadeMaker.getAliasingEnabled(); - 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(d->ycoef); Vc::float_v vXCoeff(d->xcoef); Vc::float_v vCurveResolution(d->curveResolution); Vc::float_v vCurvedData(Vc::Zero); Vc::float_v vCurvedData1(Vc::Zero); - Vc::float_v vFadeRadius(d->fadeMaker.getRadius()); - Vc::float_v vFadeStartValue(d->fadeMaker.getFadeStartValue()); - Vc::float_v vFadeAFadeStart(d->fadeMaker.getAntialiasingFadeStart()); - Vc::float_v vFadeAFadeCoeff(d->fadeMaker.getAntialiasingFadeCoeff()); - Vc::float_v vOne(Vc::One); Vc::float_v vZero(Vc::Zero); - Vc::float_v vValMax(255.f); for (int i=0; i < 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); - // BEGIN FadeMaker needFade vectorized - // follow fademaker rules for outsideMask - Vc::float_m outsideMask = dist > vFadeRadius; - dist(outsideMask) = vOne; - - Vc::float_m fadeStartMask(false); - // if antialias is off, do not process - if(antialiasOn){ - fadeStartMask = dist > vFadeAFadeStart; - dist((outsideMask ^ fadeStartMask) & fadeStartMask) = (vFadeStartValue + (dist - vFadeAFadeStart) * vFadeAFadeCoeff) / vValMax; - } - - Vc::float_m excludeMask = outsideMask | fadeStartMask; + // Apply FadeMaker mask and operations + Vc::float_m excludeMask = d->fadeMaker.needFade(dist); if (!excludeMask.isFull()) { Vc::float_v valDist = dist * vCurveResolution; // truncate Vc::SimdArray vAlphaValue(valDist); Vc::float_v vFloatAlphaValue = vAlphaValue; Vc::float_v alphaValueF = valDist - vFloatAlphaValue; 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 circe 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 void process(float* buffer, int width, float y, float cosa, float sina, float centerX, float centerY); KisGaussRectangleMaskGenerator::Private *d; }; template<> void KisGaussRectangleMaskGenerator:: FastRowProcessor::process(float* buffer, int width, float y, float cosa, float sina, float centerX, float centerY) { const bool antialiasOn = d->fadeMaker.getAliasingEnabled(); 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(d->halfWidth); Vc::float_v vhalfHeight(d->halfHeight); Vc::float_v vXFade(d->xfade); Vc::float_v vYFade(d->yfade); Vc::float_v vAlphafactor(d->alphafactor); Vc::float_v vXLimit(d->fadeMaker.getXLimit()); Vc::float_v vYLimit(d->fadeMaker.getYLimit()); Vc::float_v vXFadeLimitStart(d->fadeMaker.getXFadeLimitStart()); Vc::float_v vYFadeLimitStart(d->fadeMaker.getYFadeLimitStart()); Vc::float_v vXFadeCoeff(d->fadeMaker.getXFadeCoeff()); Vc::float_v vYFadeCoeff(d->fadeMaker.getYFadeCoeff()); Vc::float_v vOne(Vc::One); Vc::float_v vZero(Vc::Zero); Vc::float_v vValMax(255.f); for (int i=0; i < width; i+= Vc::float_v::size()){ Vc::float_v x_ = currentIndices - vCenterX; Vc::float_v xr = x_ * vCosa - vSinaY_; Vc::float_v yr = abs(x_ * vSina + vCosaY_); Vc::float_v vValue; // BEGIN FadeMaker needFade vectorized 2D Vc::float_v xra = abs(xr); Vc::float_m outXMask = xr > vXLimit; Vc::float_m outYMask = yr > vYLimit; Vc::float_m excludeMask(outXMask | outYMask); 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))); // if antialias is off, do not process Vc::float_m fadeXStartMask(false); Vc::float_m fadeYStartMask(false); if(antialiasOn){ Vc::float_v fadeValue; Vc::SimdArray vBaseValue(fullFade); fadeXStartMask = xra > vXFadeLimitStart; fadeXStartMask = (fadeXStartMask ^ excludeMask) & fadeXStartMask; if (!fadeXStartMask.isFull()) { fadeValue = vBaseValue + (vValMax - vBaseValue) * (xra - vXFadeLimitStart) * vXFadeCoeff; fadeValue(fadeXStartMask & ((yr > vYFadeLimitStart) & (fadeValue < vValMax)) ) = fadeValue + (vValMax - fadeValue) * (yr - vYFadeLimitStart) * vYFadeCoeff; fullFade(fadeXStartMask) = fadeValue; } fadeYStartMask = yr > vYFadeLimitStart; fadeYStartMask = (fadeYStartMask ^ fadeXStartMask) & fadeYStartMask; if (!fadeYStartMask.isFull()) { fadeValue = vBaseValue + (vValMax - vBaseValue) * (yr - vYFadeLimitStart) * vYFadeCoeff; fadeValue(fadeYStartMask & ((xra > vXFadeLimitStart) & (fadeValue < vValMax)) ) = fadeValue + (vValMax - fadeValue) * (xra - vXFadeLimitStart) * vXFadeCoeff; fullFade(fadeYStartMask) = fadeValue; } } Vc::float_m mask; // Mask undefined values, out of range are out of mask mask = Vc::isfinite(fullFade); fullFade.setZero(!mask); // Mask in the inner circe of the mask mask = fullFade < vZero; fullFade.setZero(mask); // Mask the outter circle mask = fullFade > 254.974f; fullFade(mask) = vValMax; // Mask (value - value), presicion 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(); } } #endif /* defined HAVE_VC */