| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef Sk4pxXfermode_DEFINED | 8 #ifndef Sk4pxXfermode_DEFINED |
| 9 #define Sk4pxXfermode_DEFINED | 9 #define Sk4pxXfermode_DEFINED |
| 10 | 10 |
| 11 #include "Sk4px.h" | 11 #include "Sk4px.h" |
| 12 #include "SkNx.h" | 12 #include "SkNx.h" |
| 13 #include "SkXfermode_proccoeff.h" | 13 #include "SkXfermode_proccoeff.h" |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 // Most xfermodes can be done most efficiently 4 pixels at a time in 8 or 16-bit
fixed point. | 17 // Most xfermodes can be done most efficiently 4 pixels at a time in 8 or 16-bit
fixed point. |
| 18 #define XFERMODE(Name) static Sk4px SK_VECTORCALL Name(Sk4px s, Sk4px d) | 18 #define XFERMODE(Xfermode) \ |
| 19 struct Xfermode { Sk4px operator()(const Sk4px&, const Sk4px&) const; }; \ |
| 20 inline Sk4px Xfermode::operator()(const Sk4px& s, const Sk4px& d) const |
| 19 | 21 |
| 20 XFERMODE(Clear) { return Sk4px::DupPMColor(0); } | 22 XFERMODE(Clear) { return Sk4px::DupPMColor(0); } |
| 21 XFERMODE(Src) { return s; } | 23 XFERMODE(Src) { return s; } |
| 22 XFERMODE(Dst) { return d; } | 24 XFERMODE(Dst) { return d; } |
| 23 XFERMODE(SrcIn) { return s.approxMulDiv255(d.alphas() ); } | 25 XFERMODE(SrcIn) { return s.approxMulDiv255(d.alphas() ); } |
| 24 XFERMODE(SrcOut) { return s.approxMulDiv255(d.alphas().inv()); } | 26 XFERMODE(SrcOut) { return s.approxMulDiv255(d.alphas().inv()); } |
| 25 XFERMODE(SrcOver) { return s + d.approxMulDiv255(s.alphas().inv()); } | 27 XFERMODE(SrcOver) { return s + d.approxMulDiv255(s.alphas().inv()); } |
| 26 XFERMODE(DstIn) { return SrcIn (d,s); } | 28 XFERMODE(DstIn) { return SrcIn ()(d,s); } |
| 27 XFERMODE(DstOut) { return SrcOut (d,s); } | 29 XFERMODE(DstOut) { return SrcOut ()(d,s); } |
| 28 XFERMODE(DstOver) { return SrcOver(d,s); } | 30 XFERMODE(DstOver) { return SrcOver()(d,s); } |
| 29 | 31 |
| 30 // [ S * Da + (1 - Sa) * D] | 32 // [ S * Da + (1 - Sa) * D] |
| 31 XFERMODE(SrcATop) { return (s * d.alphas() + d * s.alphas().inv()).div255(); } | 33 XFERMODE(SrcATop) { return (s * d.alphas() + d * s.alphas().inv()).div255(); } |
| 32 XFERMODE(DstATop) { return SrcATop(d,s); } | 34 XFERMODE(DstATop) { return SrcATop()(d,s); } |
| 33 //[ S * (1 - Da) + (1 - Sa) * D ] | 35 //[ S * (1 - Da) + (1 - Sa) * D ] |
| 34 XFERMODE(Xor) { return (s * d.alphas().inv() + d * s.alphas().inv()).div255(); } | 36 XFERMODE(Xor) { return (s * d.alphas().inv() + d * s.alphas().inv()).div255(); } |
| 35 // [S + D ] | 37 // [S + D ] |
| 36 XFERMODE(Plus) { return s.saturatedAdd(d); } | 38 XFERMODE(Plus) { return s.saturatedAdd(d); } |
| 37 // [S * D ] | 39 // [S * D ] |
| 38 XFERMODE(Modulate) { return s.approxMulDiv255(d); } | 40 XFERMODE(Modulate) { return s.approxMulDiv255(d); } |
| 39 // [S + D - S * D] | 41 // [S + D - S * D] |
| 40 XFERMODE(Screen) { | 42 XFERMODE(Screen) { |
| 41 // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subtract
can be done | 43 // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subtract
can be done |
| 42 // in 8-bit space without overflow. S + (1-S)*D is a touch faster because i
nv() is cheap. | 44 // in 8-bit space without overflow. S + (1-S)*D is a touch faster because i
nv() is cheap. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 72 auto isLite = ((sa-s) < s).widenLoHi(); | 74 auto isLite = ((sa-s) < s).widenLoHi(); |
| 73 | 75 |
| 74 auto lite = sa*da - ((da-d)*(sa-s) << 1), | 76 auto lite = sa*da - ((da-d)*(sa-s) << 1), |
| 75 dark = s*d << 1, | 77 dark = s*d << 1, |
| 76 both = s*da.inv() + d*sa.inv(); | 78 both = s*da.inv() + d*sa.inv(); |
| 77 | 79 |
| 78 auto alphas = srcover; | 80 auto alphas = srcover; |
| 79 auto colors = (both + isLite.thenElse(lite, dark)).div255(); | 81 auto colors = (both + isLite.thenElse(lite, dark)).div255(); |
| 80 return alphas.zeroColors() + colors.zeroAlphas(); | 82 return alphas.zeroColors() + colors.zeroAlphas(); |
| 81 } | 83 } |
| 82 XFERMODE(Overlay) { return HardLight(d,s); } | 84 XFERMODE(Overlay) { return HardLight()(d,s); } |
| 83 | 85 |
| 84 XFERMODE(Darken) { | 86 XFERMODE(Darken) { |
| 85 auto sa = s.alphas(), | 87 auto sa = s.alphas(), |
| 86 da = d.alphas(); | 88 da = d.alphas(); |
| 87 | 89 |
| 88 auto sda = (s*da).div255(), | 90 auto sda = (s*da).div255(), |
| 89 dsa = (d*sa).div255(); | 91 dsa = (d*sa).div255(); |
| 90 | 92 |
| 91 auto srcover = s + (d * sa.inv()).div255(), | 93 auto srcover = s + (d * sa.inv()).div255(), |
| 92 dstover = d + (s * da.inv()).div255(); | 94 dstover = d + (s * da.inv()).div255(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 103 | 105 |
| 104 auto srcover = s + (d * sa.inv()).div255(), | 106 auto srcover = s + (d * sa.inv()).div255(), |
| 105 dstover = d + (s * da.inv()).div255(); | 107 dstover = d + (s * da.inv()).div255(); |
| 106 auto alphas = srcover, | 108 auto alphas = srcover, |
| 107 colors = (dsa < sda).thenElse(srcover, dstover); | 109 colors = (dsa < sda).thenElse(srcover, dstover); |
| 108 return alphas.zeroColors() + colors.zeroAlphas(); | 110 return alphas.zeroColors() + colors.zeroAlphas(); |
| 109 } | 111 } |
| 110 #undef XFERMODE | 112 #undef XFERMODE |
| 111 | 113 |
| 112 // Some xfermodes use math like divide or sqrt that's best done in floats 1 pixe
l at a time. | 114 // Some xfermodes use math like divide or sqrt that's best done in floats 1 pixe
l at a time. |
| 113 #define XFERMODE(Name) static Sk4f SK_VECTORCALL Name(Sk4f d, Sk4f s) | 115 #define XFERMODE(Xfermode) \ |
| 116 struct Xfermode { Sk4f operator()(const Sk4f&, const Sk4f&) const; }; \ |
| 117 inline Sk4f Xfermode::operator()(const Sk4f& d, const Sk4f& s) const |
| 114 | 118 |
| 115 static inline Sk4f a_rgb(const Sk4f& a, const Sk4f& rgb) { | 119 static inline Sk4f a_rgb(const Sk4f& a, const Sk4f& rgb) { |
| 116 static_assert(SK_A32_SHIFT == 24, ""); | 120 static_assert(SK_A32_SHIFT == 24, ""); |
| 117 return a * Sk4f(0,0,0,1) + rgb * Sk4f(1,1,1,0); | 121 return a * Sk4f(0,0,0,1) + rgb * Sk4f(1,1,1,0); |
| 118 } | 122 } |
| 119 static inline Sk4f alphas(const Sk4f& f) { | 123 static inline Sk4f alphas(const Sk4f& f) { |
| 120 return SkNx_dup<SK_A32_SHIFT/8>(f); | 124 return SkNx_dup<SK_A32_SHIFT/8>(f); |
| 121 } | 125 } |
| 122 | 126 |
| 123 XFERMODE(ColorDodge) { | 127 XFERMODE(ColorDodge) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 | 178 |
| 175 auto alpha = s + d*isa; | 179 auto alpha = s + d*isa; |
| 176 auto colors = s*ida + d*isa + (s2 <= sa).thenElse(darkSrc, liteSrc);
// Case 1 or 2/3? | 180 auto colors = s*ida + d*isa + (s2 <= sa).thenElse(darkSrc, liteSrc);
// Case 1 or 2/3? |
| 177 | 181 |
| 178 return a_rgb(alpha, colors); | 182 return a_rgb(alpha, colors); |
| 179 } | 183 } |
| 180 #undef XFERMODE | 184 #undef XFERMODE |
| 181 | 185 |
| 182 // A reasonable fallback mode for doing AA is to simply apply the transfermode f
irst, | 186 // A reasonable fallback mode for doing AA is to simply apply the transfermode f
irst, |
| 183 // then linearly interpolate the AA. | 187 // then linearly interpolate the AA. |
| 184 template <Sk4px (SK_VECTORCALL *Mode)(Sk4px, Sk4px)> | 188 template <typename Xfermode> |
| 185 static Sk4px SK_VECTORCALL xfer_aa(Sk4px s, Sk4px d, Sk4px aa) { | 189 static Sk4px xfer_aa(const Sk4px& s, const Sk4px& d, const Sk4px& aa) { |
| 186 Sk4px bw = Mode(s, d); | 190 Sk4px bw = Xfermode()(s, d); |
| 187 return (bw * aa + d * aa.inv()).div255(); | 191 return (bw * aa + d * aa.inv()).div255(); |
| 188 } | 192 } |
| 189 | 193 |
| 190 // For some transfermodes we specialize AA, either for correctness or performanc
e. | 194 // For some transfermodes we specialize AA, either for correctness or performanc
e. |
| 191 #define XFERMODE_AA(Name) \ | 195 #define XFERMODE_AA(Xfermode) \ |
| 192 template <> Sk4px SK_VECTORCALL xfer_aa<Name>(Sk4px s, Sk4px d, Sk4px aa) | 196 template <> Sk4px xfer_aa<Xfermode>(const Sk4px& s, const Sk4px& d, const Sk
4px& aa) |
| 193 | 197 |
| 194 // Plus' clamp needs to happen after AA. skia:3852 | 198 // Plus' clamp needs to happen after AA. skia:3852 |
| 195 XFERMODE_AA(Plus) { // [ clamp( (1-AA)D + (AA)(S+D) ) == clamp(D + AA*S) ] | 199 XFERMODE_AA(Plus) { // [ clamp( (1-AA)D + (AA)(S+D) ) == clamp(D + AA*S) ] |
| 196 return d.saturatedAdd(s.approxMulDiv255(aa)); | 200 return d.saturatedAdd(s.approxMulDiv255(aa)); |
| 197 } | 201 } |
| 198 | 202 |
| 199 #undef XFERMODE_AA | 203 #undef XFERMODE_AA |
| 200 | 204 |
| 205 template <typename Xfermode> |
| 201 class Sk4pxXfermode : public SkProcCoeffXfermode { | 206 class Sk4pxXfermode : public SkProcCoeffXfermode { |
| 202 public: | 207 public: |
| 203 typedef Sk4px (SK_VECTORCALL *Proc4)(Sk4px, Sk4px); | 208 Sk4pxXfermode(const ProcCoeff& rec, SkXfermode::Mode mode) |
| 204 typedef Sk4px (SK_VECTORCALL *AAProc4)(Sk4px, Sk4px, Sk4px); | 209 : INHERITED(rec, mode) {} |
| 205 | |
| 206 Sk4pxXfermode(const ProcCoeff& rec, SkXfermode::Mode mode, Proc4 proc4, AAPr
oc4 aaproc4) | |
| 207 : INHERITED(rec, mode) | |
| 208 , fProc4(proc4) | |
| 209 , fAAProc4(aaproc4) {} | |
| 210 | 210 |
| 211 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[
]) const override { | 211 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[
]) const override { |
| 212 if (nullptr == aa) { | 212 if (nullptr == aa) { |
| 213 Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& sr
c4) { | 213 Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& sr
c4) { |
| 214 return fProc4(src4, dst4); | 214 return Xfermode()(src4, dst4); |
| 215 }); | 215 }); |
| 216 } else { | 216 } else { |
| 217 Sk4px::MapDstSrcAlpha(n, dst, src, aa, | 217 Sk4px::MapDstSrcAlpha(n, dst, src, aa, |
| 218 [&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha
) { | 218 [&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha
) { |
| 219 return fAAProc4(src4, dst4, alpha); | 219 return xfer_aa<Xfermode>(src4, dst4, alpha); |
| 220 }); | 220 }); |
| 221 } | 221 } |
| 222 } | 222 } |
| 223 | 223 |
| 224 void xfer16(uint16_t dst[], const SkPMColor src[], int n, const SkAlpha aa[]
) const override { | 224 void xfer16(uint16_t dst[], const SkPMColor src[], int n, const SkAlpha aa[]
) const override { |
| 225 if (nullptr == aa) { | 225 SkPMColor dst32[4]; |
| 226 Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& sr
c4) { | 226 while (n >= 4) { |
| 227 return fProc4(src4, dst4); | 227 dst32[0] = SkPixel16ToPixel32(dst[0]); |
| 228 }); | 228 dst32[1] = SkPixel16ToPixel32(dst[1]); |
| 229 } else { | 229 dst32[2] = SkPixel16ToPixel32(dst[2]); |
| 230 Sk4px::MapDstSrcAlpha(n, dst, src, aa, | 230 dst32[3] = SkPixel16ToPixel32(dst[3]); |
| 231 [&](const Sk4px& dst4, const Sk4px& src4, const Sk4px& alpha
) { | 231 |
| 232 return fAAProc4(src4, dst4, alpha); | 232 this->xfer32(dst32, src, 4, aa); |
| 233 }); | 233 |
| 234 dst[0] = SkPixel32ToPixel16(dst32[0]); |
| 235 dst[1] = SkPixel32ToPixel16(dst32[1]); |
| 236 dst[2] = SkPixel32ToPixel16(dst32[2]); |
| 237 dst[3] = SkPixel32ToPixel16(dst32[3]); |
| 238 |
| 239 dst += 4; |
| 240 src += 4; |
| 241 aa += aa ? 4 : 0; |
| 242 n -= 4; |
| 243 } |
| 244 while (n) { |
| 245 SkPMColor dst32 = SkPixel16ToPixel32(*dst); |
| 246 this->xfer32(&dst32, src, 1, aa); |
| 247 *dst = SkPixel32ToPixel16(dst32); |
| 248 |
| 249 dst += 1; |
| 250 src += 1; |
| 251 aa += aa ? 1 : 0; |
| 252 n -= 1; |
| 234 } | 253 } |
| 235 } | 254 } |
| 236 | 255 |
| 237 private: | 256 private: |
| 238 Proc4 fProc4; | |
| 239 AAProc4 fAAProc4; | |
| 240 typedef SkProcCoeffXfermode INHERITED; | 257 typedef SkProcCoeffXfermode INHERITED; |
| 241 }; | 258 }; |
| 242 | 259 |
| 260 template <typename Xfermode> |
| 243 class Sk4fXfermode : public SkProcCoeffXfermode { | 261 class Sk4fXfermode : public SkProcCoeffXfermode { |
| 244 public: | 262 public: |
| 245 typedef Sk4f (SK_VECTORCALL *ProcF)(Sk4f, Sk4f); | 263 Sk4fXfermode(const ProcCoeff& rec, SkXfermode::Mode mode) |
| 246 Sk4fXfermode(const ProcCoeff& rec, SkXfermode::Mode mode, ProcF procf) | 264 : INHERITED(rec, mode) {} |
| 247 : INHERITED(rec, mode) | |
| 248 , fProcF(procf) {} | |
| 249 | 265 |
| 250 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[
]) const override { | 266 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[
]) const override { |
| 251 for (int i = 0; i < n; i++) { | 267 for (int i = 0; i < n; i++) { |
| 252 dst[i] = aa ? this->xfer32(dst[i], src[i], aa[i]) | 268 dst[i] = Xfer32_1(dst[i], src[i], aa ? aa+i : nullptr); |
| 253 : this->xfer32(dst[i], src[i]); | |
| 254 } | 269 } |
| 255 } | 270 } |
| 256 | 271 |
| 257 void xfer16(uint16_t dst[], const SkPMColor src[], int n, const SkAlpha aa[]
) const override { | 272 void xfer16(uint16_t dst[], const SkPMColor src[], int n, const SkAlpha aa[]
) const override { |
| 258 for (int i = 0; i < n; i++) { | 273 for (int i = 0; i < n; i++) { |
| 259 SkPMColor dst32 = SkPixel16ToPixel32(dst[i]); | 274 SkPMColor dst32 = SkPixel16ToPixel32(dst[i]); |
| 260 dst32 = aa ? this->xfer32(dst32, src[i], aa[i]) | 275 dst32 = Xfer32_1(dst32, src[i], aa ? aa+i : nullptr); |
| 261 : this->xfer32(dst32, src[i]); | |
| 262 dst[i] = SkPixel32ToPixel16(dst32); | 276 dst[i] = SkPixel32ToPixel16(dst32); |
| 263 } | 277 } |
| 264 } | 278 } |
| 265 | 279 |
| 266 private: | 280 private: |
| 281 static SkPMColor Xfer32_1(SkPMColor dst, const SkPMColor src, const SkAlpha*
aa) { |
| 282 Sk4f d = Load(dst), |
| 283 s = Load(src), |
| 284 b = Xfermode()(d, s); |
| 285 if (aa) { |
| 286 Sk4f a = Sk4f(*aa) * Sk4f(1.0f/255); |
| 287 b = b*a + d*(Sk4f(1)-a); |
| 288 } |
| 289 return Round(b); |
| 290 } |
| 291 |
| 267 static Sk4f Load(SkPMColor c) { | 292 static Sk4f Load(SkPMColor c) { |
| 268 return SkNx_cast<float>(Sk4b::Load((uint8_t*)&c)) * Sk4f(1.0f/255); | 293 return SkNx_cast<float>(Sk4b::Load((uint8_t*)&c)) * Sk4f(1.0f/255); |
| 269 } | 294 } |
| 295 |
| 270 static SkPMColor Round(const Sk4f& f) { | 296 static SkPMColor Round(const Sk4f& f) { |
| 271 SkPMColor c; | 297 SkPMColor c; |
| 272 SkNx_cast<uint8_t>(f * Sk4f(255) + Sk4f(0.5f)).store((uint8_t*)&c); | 298 SkNx_cast<uint8_t>(f * Sk4f(255) + Sk4f(0.5f)).store((uint8_t*)&c); |
| 273 return c; | 299 return c; |
| 274 } | 300 } |
| 275 inline SkPMColor xfer32(SkPMColor dst, SkPMColor src) const { | |
| 276 return Round(fProcF(Load(dst), Load(src))); | |
| 277 } | |
| 278 | 301 |
| 279 inline SkPMColor xfer32(SkPMColor dst, SkPMColor src, SkAlpha aa) const { | |
| 280 Sk4f s(Load(src)), | |
| 281 d(Load(dst)), | |
| 282 b(fProcF(d,s)); | |
| 283 // We do aa in full float precision before going back down to bytes, bec
ause we can! | |
| 284 Sk4f a = Sk4f(aa) * Sk4f(1.0f/255); | |
| 285 b = b*a + d*(Sk4f(1)-a); | |
| 286 return Round(b); | |
| 287 } | |
| 288 | |
| 289 ProcF fProcF; | |
| 290 typedef SkProcCoeffXfermode INHERITED; | 302 typedef SkProcCoeffXfermode INHERITED; |
| 291 }; | 303 }; |
| 292 | 304 |
| 293 } // namespace | 305 } // namespace |
| 294 | 306 |
| 295 namespace SK_OPTS_NS { | 307 namespace SK_OPTS_NS { |
| 296 | 308 |
| 297 static SkXfermode* create_xfermode(const ProcCoeff& rec, SkXfermode::Mode mode)
{ | 309 static SkXfermode* create_xfermode(const ProcCoeff& rec, SkXfermode::Mode mode)
{ |
| 298 switch (mode) { | 310 switch (mode) { |
| 299 #define CASE(Mode) \ | 311 #define CASE(Xfermode) \ |
| 300 case SkXfermode::k##Mode##_Mode: return new Sk4pxXfermode(rec, mode, &Mode,
&xfer_aa<Mode>) | 312 case SkXfermode::k##Xfermode##_Mode: return new Sk4pxXfermode<Xfermode>(rec,
mode) |
| 301 CASE(Clear); | 313 CASE(Clear); |
| 302 CASE(Src); | 314 CASE(Src); |
| 303 CASE(Dst); | 315 CASE(Dst); |
| 304 CASE(SrcOver); | 316 CASE(SrcOver); |
| 305 CASE(DstOver); | 317 CASE(DstOver); |
| 306 CASE(SrcIn); | 318 CASE(SrcIn); |
| 307 CASE(DstIn); | 319 CASE(DstIn); |
| 308 CASE(SrcOut); | 320 CASE(SrcOut); |
| 309 CASE(DstOut); | 321 CASE(DstOut); |
| 310 CASE(SrcATop); | 322 CASE(SrcATop); |
| 311 CASE(DstATop); | 323 CASE(DstATop); |
| 312 CASE(Xor); | 324 CASE(Xor); |
| 313 CASE(Plus); | 325 CASE(Plus); |
| 314 CASE(Modulate); | 326 CASE(Modulate); |
| 315 CASE(Screen); | 327 CASE(Screen); |
| 316 CASE(Multiply); | 328 CASE(Multiply); |
| 317 CASE(Difference); | 329 CASE(Difference); |
| 318 CASE(Exclusion); | 330 CASE(Exclusion); |
| 319 CASE(HardLight); | 331 CASE(HardLight); |
| 320 CASE(Overlay); | 332 CASE(Overlay); |
| 321 CASE(Darken); | 333 CASE(Darken); |
| 322 CASE(Lighten); | 334 CASE(Lighten); |
| 323 #undef CASE | 335 #undef CASE |
| 324 | 336 |
| 325 #define CASE(Mode) \ | 337 #define CASE(Xfermode) \ |
| 326 case SkXfermode::k##Mode##_Mode: return new Sk4fXfermode(rec, mode, &Mode) | 338 case SkXfermode::k##Xfermode##_Mode: return new Sk4fXfermode<Xfermode>(rec,
mode) |
| 327 CASE(ColorDodge); | 339 CASE(ColorDodge); |
| 328 CASE(ColorBurn); | 340 CASE(ColorBurn); |
| 329 CASE(SoftLight); | 341 CASE(SoftLight); |
| 330 #undef CASE | 342 #undef CASE |
| 331 | 343 |
| 332 default: break; | 344 default: break; |
| 333 } | 345 } |
| 334 return nullptr; | 346 return nullptr; |
| 335 } | 347 } |
| 336 | 348 |
| 337 } // namespace SK_OPTS_NS | 349 } // namespace SK_OPTS_NS |
| 338 | 350 |
| 339 #endif//Sk4pxXfermode_DEFINED | 351 #endif//Sk4pxXfermode_DEFINED |
| OLD | NEW |