1 /* 2 * Copyright (c) 2014 Dmitry Kazakov <dimula73@gmail.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19 #ifndef __KIS_ANTIALIASING_FADE_MAKER_H 20 #define __KIS_ANTIALIASING_FADE_MAKER_H 21 22 #include "kis_global.h" 23 24 template <class BaseFade> 25 class KisAntialiasingFadeMaker1D 26 { 27 public: KisAntialiasingFadeMaker1D(const BaseFade & baseFade,bool enableAntialiasing)28 KisAntialiasingFadeMaker1D(const BaseFade &baseFade, bool enableAntialiasing) 29 : m_radius(0.0), 30 m_fadeStartValue(0), 31 m_antialiasingFadeStart(0), 32 m_antialiasingFadeCoeff(0), 33 m_enableAntialiasing(enableAntialiasing), 34 m_baseFade(baseFade) 35 { 36 } 37 KisAntialiasingFadeMaker1D(const KisAntialiasingFadeMaker1D & rhs,const BaseFade & baseFade)38 KisAntialiasingFadeMaker1D(const KisAntialiasingFadeMaker1D &rhs, const BaseFade &baseFade) 39 : m_radius(rhs.m_radius), 40 m_fadeStartValue(rhs.m_fadeStartValue), 41 m_antialiasingFadeStart(rhs.m_antialiasingFadeStart), 42 m_antialiasingFadeCoeff(rhs.m_antialiasingFadeCoeff), 43 m_enableAntialiasing(rhs.m_enableAntialiasing), 44 m_baseFade(baseFade) 45 { 46 } 47 setSquareNormCoeffs(qreal xcoeff,qreal ycoeff)48 void setSquareNormCoeffs(qreal xcoeff, qreal ycoeff) { 49 m_radius = 1.0; 50 51 qreal xf = qMax(0.0, ((1.0 / xcoeff) - 1.0) * xcoeff); 52 qreal yf = qMax(0.0, ((1.0 / ycoeff) - 1.0) * ycoeff); 53 54 m_antialiasingFadeStart = pow2(0.5 * (xf + yf)); 55 56 m_fadeStartValue = m_baseFade.value(m_antialiasingFadeStart); 57 m_antialiasingFadeCoeff = qMax(0.0, 255.0 - m_fadeStartValue) / (m_radius - m_antialiasingFadeStart); 58 } 59 setRadius(qreal radius)60 void setRadius(qreal radius) { 61 m_radius = radius; 62 m_antialiasingFadeStart = qMax(0.0, m_radius - 1.0); 63 64 m_fadeStartValue = m_baseFade.value(m_antialiasingFadeStart); 65 m_antialiasingFadeCoeff = qMax(0.0, 255.0 - m_fadeStartValue) / (m_radius - m_antialiasingFadeStart); 66 } 67 needFade(qreal dist,quint8 * value)68 inline bool needFade(qreal dist, quint8 *value) { 69 if (dist > m_radius) { 70 *value = 255; 71 return true; 72 } 73 74 if (!m_enableAntialiasing) { 75 return false; 76 } 77 78 if (dist > m_antialiasingFadeStart) { 79 *value = m_fadeStartValue + (dist - m_antialiasingFadeStart) * m_antialiasingFadeCoeff; 80 return true; 81 } 82 83 return false; 84 } 85 86 #if defined HAVE_VC needFade(Vc::float_v & dist)87 Vc::float_m needFade(Vc::float_v &dist) { 88 const Vc::float_v vOne(Vc::One); 89 const Vc::float_v vValMax(255.f); 90 91 Vc::float_v vRadius(m_radius); 92 Vc::float_v vFadeStartValue(m_fadeStartValue); 93 Vc::float_v vAntialiasingFadeStart(m_antialiasingFadeStart); 94 Vc::float_v vAntialiasingFadeCoeff(m_antialiasingFadeCoeff); 95 96 Vc::float_m outsideMask = dist > vRadius; 97 dist(outsideMask) = vOne; 98 99 Vc::float_m fadeStartMask(false); 100 101 if(m_enableAntialiasing){ 102 fadeStartMask = dist > vAntialiasingFadeStart; 103 dist((outsideMask ^ fadeStartMask) & fadeStartMask) = (vFadeStartValue + 104 (dist - vAntialiasingFadeStart) * vAntialiasingFadeCoeff) / vValMax; 105 } 106 return (outsideMask | fadeStartMask); 107 } 108 109 #endif /* defined HAVE_VC */ 110 111 private: 112 qreal m_radius; 113 quint8 m_fadeStartValue; 114 qreal m_antialiasingFadeStart; 115 qreal m_antialiasingFadeCoeff; 116 bool m_enableAntialiasing; 117 const BaseFade &m_baseFade; 118 }; 119 120 template <class BaseFade> 121 class KisAntialiasingFadeMaker2D 122 { 123 public: KisAntialiasingFadeMaker2D(const BaseFade & baseFade,bool enableAntialiasing)124 KisAntialiasingFadeMaker2D(const BaseFade &baseFade, bool enableAntialiasing) 125 : m_xLimit(0), 126 m_yLimit(0), 127 m_xFadeLimitStart(0), 128 m_yFadeLimitStart(0), 129 m_xFadeCoeff(0), 130 m_yFadeCoeff(0), 131 m_enableAntialiasing(enableAntialiasing), 132 m_baseFade(baseFade) 133 { 134 } 135 KisAntialiasingFadeMaker2D(const KisAntialiasingFadeMaker2D & rhs,const BaseFade & baseFade)136 KisAntialiasingFadeMaker2D(const KisAntialiasingFadeMaker2D &rhs, const BaseFade &baseFade) 137 : m_xLimit(rhs.m_xLimit), 138 m_yLimit(rhs.m_yLimit), 139 m_xFadeLimitStart(rhs.m_xFadeLimitStart), 140 m_yFadeLimitStart(rhs.m_yFadeLimitStart), 141 m_xFadeCoeff(rhs.m_xFadeCoeff), 142 m_yFadeCoeff(rhs.m_yFadeCoeff), 143 m_enableAntialiasing(rhs.m_enableAntialiasing), 144 m_baseFade(baseFade) 145 { 146 } 147 setLimits(qreal halfWidth,qreal halfHeight)148 void setLimits(qreal halfWidth, qreal halfHeight) { 149 m_xLimit = halfWidth; 150 m_yLimit = halfHeight; 151 152 m_xFadeLimitStart = m_xLimit - 1.0; 153 m_yFadeLimitStart = m_yLimit - 1.0; 154 155 m_xFadeCoeff = 1.0 / (m_xLimit - m_xFadeLimitStart); 156 m_yFadeCoeff = 1.0 / (m_yLimit - m_yFadeLimitStart); 157 } 158 needFade(qreal x,qreal y,quint8 * value)159 inline bool needFade(qreal x, qreal y, quint8 *value) { 160 x = qAbs(x); 161 y = qAbs(y); 162 163 if (x > m_xLimit) { 164 *value = 255; 165 return true; 166 } 167 168 if (y > m_yLimit) { 169 *value = 255; 170 return true; 171 } 172 173 if (!m_enableAntialiasing) { 174 return false; 175 } 176 177 if (x > m_xFadeLimitStart) { 178 quint8 baseValue = m_baseFade.value(x, y); 179 *value = baseValue + (255.0 - baseValue) * (x - m_xFadeLimitStart) * m_xFadeCoeff; 180 181 if (y > m_yFadeLimitStart && *value < 255) { 182 *value += (255.0 - *value) * (y - m_yFadeLimitStart) * m_yFadeCoeff; 183 } 184 185 return true; 186 } 187 188 if (y > m_yFadeLimitStart) { 189 quint8 baseValue = m_baseFade.value(x, y); 190 *value = baseValue + (255.0 - baseValue) * (y - m_yFadeLimitStart) * m_yFadeCoeff; 191 192 if (x > m_xFadeLimitStart && *value < 255) { 193 *value += (255.0 - *value) * (x - m_xFadeLimitStart) * m_xFadeCoeff; 194 } 195 196 return true; 197 } 198 199 return false; 200 } 201 202 #if defined HAVE_VC needFade(Vc::float_v & xr,Vc::float_v & yr)203 Vc::float_m needFade(Vc::float_v &xr, Vc::float_v &yr) const { 204 205 Vc::float_v vXLimit(m_xLimit); 206 Vc::float_v vYLimit(m_yLimit); 207 208 Vc::float_m outXMask = Vc::abs(xr) > vXLimit; 209 Vc::float_m outYMask = Vc::abs(yr) > vYLimit; 210 211 return (outXMask | outYMask); 212 } 213 214 // Apply fader separately to avoid calculating vValue twice. apply2DFader(Vc::float_v & vValue,Vc::float_m & excludeMask,Vc::float_v & xr,Vc::float_v & yr)215 void apply2DFader(Vc::float_v &vValue, Vc::float_m &excludeMask, Vc::float_v &xr, Vc::float_v &yr) const { 216 const Vc::float_v vValMax(255.f); 217 218 if(m_enableAntialiasing){ 219 Vc::float_v vXFadeLimitStart(m_xFadeLimitStart); 220 Vc::float_v vYFadeLimitStart(m_yFadeLimitStart); 221 Vc::float_v vXFadeCoeff(m_xFadeCoeff); 222 Vc::float_v vYFadeCoeff(m_yFadeCoeff); 223 224 Vc::float_v xra = abs(xr); 225 Vc::float_m fadeXStartMask(false); 226 Vc::float_m fadeYStartMask(false); 227 228 Vc::float_v fadeValue; 229 Vc::SimdArray<quint16,Vc::float_v::size()> vBaseValue(vValue); 230 231 fadeXStartMask = xra > vXFadeLimitStart; 232 fadeXStartMask = (fadeXStartMask ^ excludeMask) & fadeXStartMask; 233 if (!fadeXStartMask.isFull()) { 234 fadeValue = vBaseValue + (vValMax - vBaseValue) * (xra - vXFadeLimitStart) * vXFadeCoeff; 235 fadeValue(fadeXStartMask & ((yr > vYFadeLimitStart) & (fadeValue < vValMax)) ) = 236 fadeValue + (vValMax - fadeValue) * (yr - vYFadeLimitStart) * vYFadeCoeff; 237 vValue(fadeXStartMask) = fadeValue; 238 } 239 240 fadeYStartMask = yr > vYFadeLimitStart; 241 fadeYStartMask = (fadeYStartMask ^ fadeXStartMask) & fadeYStartMask; 242 if (!fadeYStartMask.isFull()) { 243 fadeValue = vBaseValue + (vValMax - vBaseValue) * (yr - vYFadeLimitStart) * vYFadeCoeff; 244 fadeValue(fadeYStartMask & ((xra > vXFadeLimitStart) & (fadeValue < vValMax)) ) = 245 fadeValue + (vValMax - fadeValue) * (xra - vXFadeLimitStart) * vXFadeCoeff; 246 vValue(fadeYStartMask) = fadeValue; 247 } 248 } 249 return; 250 } 251 252 #endif /* defined HAVE_VC */ 253 254 private: 255 qreal m_xLimit; 256 qreal m_yLimit; 257 258 qreal m_xFadeLimitStart; 259 qreal m_yFadeLimitStart; 260 261 qreal m_xFadeCoeff; 262 qreal m_yFadeCoeff; 263 264 bool m_enableAntialiasing; 265 266 const BaseFade &m_baseFade; 267 }; 268 269 #endif /* __KIS_ANTIALIASING_FADE_MAKER_H */ 270