| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 #include "SkArithmeticMode.h" | 8 #include "SkArithmeticMode.h" |
| 9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
| 10 #include "SkReadBuffer.h" | 10 #include "SkReadBuffer.h" |
| 11 #include "SkWriteBuffer.h" | 11 #include "SkWriteBuffer.h" |
| 12 #include "SkString.h" | 12 #include "SkString.h" |
| 13 #include "SkUnPreMultiply.h" | 13 #include "SkUnPreMultiply.h" |
| 14 #if SK_SUPPORT_GPU | 14 #if SK_SUPPORT_GPU |
| 15 #include "SkArithmeticMode_gpu.h" | 15 #include "SkArithmeticMode_gpu.h" |
| 16 #endif | 16 #endif |
| 17 | 17 |
| 18 static const bool gUseUnpremul = false; | |
| 19 | |
| 20 class SkArithmeticMode_scalar : public SkXfermode { | 18 class SkArithmeticMode_scalar : public SkXfermode { |
| 21 public: | 19 public: |
| 22 static SkXfermode* Create(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4
, | 20 SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, |
| 23 bool enforcePMColor) { | 21 bool enforcePMColor) { |
| 24 if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) && | 22 fK[0] = k1; |
| 25 SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { | 23 fK[1] = k2; |
| 26 return SkXfermode::Create(SkXfermode::kSrc_Mode); | 24 fK[2] = k3; |
| 27 } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && | 25 fK[3] = k4; |
| 28 SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)
) { | 26 fEnforcePMColor = enforcePMColor; |
| 29 return SkXfermode::Create(SkXfermode::kDst_Mode); | |
| 30 } | |
| 31 | |
| 32 return new SkArithmeticMode_scalar(k1, k2, k3, k4, enforcePMColor); | |
| 33 } | 27 } |
| 34 | 28 |
| 35 void xfer32(SkPMColor dst[], const SkPMColor src[], int count, | 29 void xfer32(SkPMColor[], const SkPMColor[], int count, const SkAlpha[]) cons
t override; |
| 36 const SkAlpha aa[]) const override; | |
| 37 | 30 |
| 38 SK_TO_STRING_OVERRIDE() | 31 SK_TO_STRING_OVERRIDE() |
| 39 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar) | 32 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar) |
| 40 | 33 |
| 41 #if SK_SUPPORT_GPU | 34 #if SK_SUPPORT_GPU |
| 42 const GrFragmentProcessor* getFragmentProcessorForImageFilter( | 35 const GrFragmentProcessor* getFragmentProcessorForImageFilter( |
| 43 const GrFragmentProcessor* dst)
const override; | 36 const GrFragmentProcessor* dst)
const override; |
| 44 GrXPFactory* asXPFactory() const override; | 37 GrXPFactory* asXPFactory() const override; |
| 45 #endif | 38 #endif |
| 46 | 39 |
| 47 private: | 40 private: |
| 48 SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
bool enforcePMColor) { | |
| 49 fK[0] = k1; | |
| 50 fK[1] = k2; | |
| 51 fK[2] = k3; | |
| 52 fK[3] = k4; | |
| 53 fEnforcePMColor = enforcePMColor; | |
| 54 } | |
| 55 | |
| 56 void flatten(SkWriteBuffer& buffer) const override { | 41 void flatten(SkWriteBuffer& buffer) const override { |
| 57 buffer.writeScalar(fK[0]); | 42 buffer.writeScalar(fK[0]); |
| 58 buffer.writeScalar(fK[1]); | 43 buffer.writeScalar(fK[1]); |
| 59 buffer.writeScalar(fK[2]); | 44 buffer.writeScalar(fK[2]); |
| 60 buffer.writeScalar(fK[3]); | 45 buffer.writeScalar(fK[3]); |
| 61 buffer.writeBool(fEnforcePMColor); | 46 buffer.writeBool(fEnforcePMColor); |
| 62 } | 47 } |
| 63 | 48 |
| 64 SkScalar fK[4]; | 49 SkScalar fK[4]; |
| 65 bool fEnforcePMColor; | 50 bool fEnforcePMColor; |
| 66 | 51 |
| 67 friend class SkArithmeticMode; | 52 friend class SkArithmeticMode; |
| 68 | 53 |
| 69 typedef SkXfermode INHERITED; | 54 typedef SkXfermode INHERITED; |
| 70 }; | 55 }; |
| 71 | 56 |
| 72 SkFlattenable* SkArithmeticMode_scalar::CreateProc(SkReadBuffer& buffer) { | 57 SkFlattenable* SkArithmeticMode_scalar::CreateProc(SkReadBuffer& buffer) { |
| 73 const SkScalar k1 = buffer.readScalar(); | 58 const SkScalar k1 = buffer.readScalar(); |
| 74 const SkScalar k2 = buffer.readScalar(); | 59 const SkScalar k2 = buffer.readScalar(); |
| 75 const SkScalar k3 = buffer.readScalar(); | 60 const SkScalar k3 = buffer.readScalar(); |
| 76 const SkScalar k4 = buffer.readScalar(); | 61 const SkScalar k4 = buffer.readScalar(); |
| 77 const bool enforcePMColor = buffer.readBool(); | 62 const bool enforcePMColor = buffer.readBool(); |
| 78 return Create(k1, k2, k3, k4, enforcePMColor); | 63 return SkArithmeticMode::Create(k1, k2, k3, k4, enforcePMColor); |
| 79 } | 64 } |
| 80 | 65 |
| 81 static int pinToByte(int value) { | 66 static int pinToByte(int value) { |
| 82 if (value < 0) { | 67 if (value < 0) { |
| 83 value = 0; | 68 value = 0; |
| 84 } else if (value > 255) { | 69 } else if (value > 255) { |
| 85 value = 255; | 70 value = 255; |
| 86 } | 71 } |
| 87 return value; | 72 return value; |
| 88 } | 73 } |
| 89 | 74 |
| 90 static int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, | 75 static int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, |
| 91 int src, int dst) { | 76 int src, int dst) { |
| 92 SkScalar result = SkScalarMul(k1, src * dst) + | 77 SkScalar result = SkScalarMul(k1, src * dst) + |
| 93 SkScalarMul(k2, src) + | 78 SkScalarMul(k2, src) + |
| 94 SkScalarMul(k3, dst) + | 79 SkScalarMul(k3, dst) + |
| 95 k4; | 80 k4; |
| 96 int res = SkScalarRoundToInt(result); | 81 int res = SkScalarRoundToInt(result); |
| 97 return pinToByte(res); | 82 return pinToByte(res); |
| 98 } | 83 } |
| 99 | 84 |
| 100 static int blend(int src, int dst, int scale) { | 85 static int blend(int src, int dst, int scale) { |
| 101 return dst + ((src - dst) * scale >> 8); | 86 return dst + ((src - dst) * scale >> 8); |
| 102 } | 87 } |
| 103 | 88 |
| 104 static bool needsUnpremul(int alpha) { | |
| 105 return 0 != alpha && 0xFF != alpha; | |
| 106 } | |
| 107 | |
| 108 void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[], | 89 void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[], |
| 109 int count, const SkAlpha aaCoverage[]) const { | 90 int count, const SkAlpha aaCoverage[]) const { |
| 110 SkScalar k1 = fK[0] / 255; | 91 SkScalar k1 = fK[0] / 255; |
| 111 SkScalar k2 = fK[1]; | 92 SkScalar k2 = fK[1]; |
| 112 SkScalar k3 = fK[2]; | 93 SkScalar k3 = fK[2]; |
| 113 SkScalar k4 = fK[3] * 255; | 94 SkScalar k4 = fK[3] * 255; |
| 114 | 95 |
| 115 for (int i = 0; i < count; ++i) { | 96 for (int i = 0; i < count; ++i) { |
| 116 if ((nullptr == aaCoverage) || aaCoverage[i]) { | 97 if ((nullptr == aaCoverage) || aaCoverage[i]) { |
| 117 SkPMColor sc = src[i]; | 98 SkPMColor sc = src[i]; |
| 118 SkPMColor dc = dst[i]; | 99 SkPMColor dc = dst[i]; |
| 119 | 100 |
| 120 int a, r, g, b; | 101 int a, r, g, b; |
| 121 | 102 |
| 122 if (gUseUnpremul) { | 103 a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc)); |
| 123 int sa = SkGetPackedA32(sc); | 104 r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc)); |
| 124 int da = SkGetPackedA32(dc); | 105 g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc)); |
| 125 | 106 b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc)); |
| 126 int srcNeedsUnpremul = needsUnpremul(sa); | 107 if (fEnforcePMColor) { |
| 127 int dstNeedsUnpremul = needsUnpremul(da); | 108 r = SkMin32(r, a); |
| 128 | 109 g = SkMin32(g, a); |
| 129 if (!srcNeedsUnpremul && !dstNeedsUnpremul) { | 110 b = SkMin32(b, a); |
| 130 a = arith(k1, k2, k3, k4, sa, da); | |
| 131 r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32
(dc)); | |
| 132 g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32
(dc)); | |
| 133 b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32
(dc)); | |
| 134 } else { | |
| 135 int sr = SkGetPackedR32(sc); | |
| 136 int sg = SkGetPackedG32(sc); | |
| 137 int sb = SkGetPackedB32(sc); | |
| 138 if (srcNeedsUnpremul) { | |
| 139 SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale
(sa); | |
| 140 sr = SkUnPreMultiply::ApplyScale(scale, sr); | |
| 141 sg = SkUnPreMultiply::ApplyScale(scale, sg); | |
| 142 sb = SkUnPreMultiply::ApplyScale(scale, sb); | |
| 143 } | |
| 144 | |
| 145 int dr = SkGetPackedR32(dc); | |
| 146 int dg = SkGetPackedG32(dc); | |
| 147 int db = SkGetPackedB32(dc); | |
| 148 if (dstNeedsUnpremul) { | |
| 149 SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale
(da); | |
| 150 dr = SkUnPreMultiply::ApplyScale(scale, dr); | |
| 151 dg = SkUnPreMultiply::ApplyScale(scale, dg); | |
| 152 db = SkUnPreMultiply::ApplyScale(scale, db); | |
| 153 } | |
| 154 | |
| 155 a = arith(k1, k2, k3, k4, sa, da); | |
| 156 r = arith(k1, k2, k3, k4, sr, dr); | |
| 157 g = arith(k1, k2, k3, k4, sg, dg); | |
| 158 b = arith(k1, k2, k3, k4, sb, db); | |
| 159 } | |
| 160 } else { | |
| 161 a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc)
); | |
| 162 r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc)
); | |
| 163 g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc)
); | |
| 164 b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc)
); | |
| 165 if (fEnforcePMColor) { | |
| 166 r = SkMin32(r, a); | |
| 167 g = SkMin32(g, a); | |
| 168 b = SkMin32(b, a); | |
| 169 } | |
| 170 } | 111 } |
| 171 | 112 |
| 172 // apply antialias coverage if necessary | 113 // apply antialias coverage if necessary |
| 173 if (aaCoverage && 0xFF != aaCoverage[i]) { | 114 if (aaCoverage && 0xFF != aaCoverage[i]) { |
| 174 int scale = aaCoverage[i] + (aaCoverage[i] >> 7); | 115 int scale = aaCoverage[i] + (aaCoverage[i] >> 7); |
| 175 a = blend(a, SkGetPackedA32(sc), scale); | 116 a = blend(a, SkGetPackedA32(sc), scale); |
| 176 r = blend(r, SkGetPackedR32(sc), scale); | 117 r = blend(r, SkGetPackedR32(sc), scale); |
| 177 g = blend(g, SkGetPackedG32(sc), scale); | 118 g = blend(g, SkGetPackedG32(sc), scale); |
| 178 b = blend(b, SkGetPackedB32(sc), scale); | 119 b = blend(b, SkGetPackedB32(sc), scale); |
| 179 } | 120 } |
| 180 | 121 |
| 181 // turn the result back into premul | |
| 182 if (gUseUnpremul && (0xFF != a)) { | |
| 183 int scale = a + (a >> 7); | |
| 184 r = SkAlphaMul(r, scale); | |
| 185 g = SkAlphaMul(g, scale); | |
| 186 b = SkAlphaMul(b, scale); | |
| 187 } | |
| 188 dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32No
Check(a, r, g, b); | 122 dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32No
Check(a, r, g, b); |
| 189 } | 123 } |
| 190 } | 124 } |
| 191 } | 125 } |
| 192 | 126 |
| 193 #ifndef SK_IGNORE_TO_STRING | 127 #ifndef SK_IGNORE_TO_STRING |
| 194 void SkArithmeticMode_scalar::toString(SkString* str) const { | 128 void SkArithmeticMode_scalar::toString(SkString* str) const { |
| 195 str->append("SkArithmeticMode_scalar: "); | 129 str->append("SkArithmeticMode_scalar: "); |
| 196 for (int i = 0; i < 4; ++i) { | 130 for (int i = 0; i < 4; ++i) { |
| 197 str->appendScalar(fK[i]); | 131 str->appendScalar(fK[i]); |
| 198 str->append(" "); | 132 str->append(" "); |
| 199 } | 133 } |
| 200 str->appendS32(fEnforcePMColor ? 1 : 0); | 134 str->appendS32(fEnforcePMColor ? 1 : 0); |
| 201 } | 135 } |
| 202 #endif | 136 #endif |
| 203 | 137 |
| 204 /////////////////////////////////////////////////////////////////////////////// | 138 /////////////////////////////////////////////////////////////////////////////// |
| 205 | 139 |
| 206 static bool fitsInBits(SkScalar x, int bits) { | |
| 207 return SkScalarAbs(x) < (1 << (bits - 1)); | |
| 208 } | |
| 209 | |
| 210 #if 0 // UNUSED | |
| 211 static int32_t toDot8(SkScalar x) { | |
| 212 return (int32_t)(x * 256); | |
| 213 } | |
| 214 #endif | |
| 215 | |
| 216 SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2, | 140 SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2, |
| 217 SkScalar k3, SkScalar k4, | 141 SkScalar k3, SkScalar k4, |
| 218 bool enforcePMColor) { | 142 bool enforcePMColor) { |
| 219 if (fitsInBits(k1, 8) && fitsInBits(k2, 16) && | 143 if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) && |
| 220 fitsInBits(k2, 16) && fitsInBits(k2, 24)) { | 144 SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { |
| 221 | 145 return SkXfermode::Create(SkXfermode::kSrc_Mode); |
| 222 #if 0 // UNUSED | 146 } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && |
| 223 int32_t i1 = toDot8(k1); | 147 SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) { |
| 224 int32_t i2 = toDot8(k2); | 148 return SkXfermode::Create(SkXfermode::kDst_Mode); |
| 225 int32_t i3 = toDot8(k3); | |
| 226 int32_t i4 = toDot8(k4); | |
| 227 if (i1) { | |
| 228 return new SkArithmeticMode_quad (i1, i2, i3, i4); | |
| 229 } | |
| 230 if (0 == i2) { | |
| 231 return new SkArithmeticMode_dst (i3, i4); | |
| 232 } | |
| 233 if (0 == i3) { | |
| 234 return new SkArithmeticMode_src (i2, i4); | |
| 235 } | |
| 236 return new SkArithmeticMode_linear (i2, i3, i4); | |
| 237 #endif | |
| 238 } | 149 } |
| 239 return SkArithmeticMode_scalar::Create(k1, k2, k3, k4, enforcePMColor); | 150 |
| 151 return new SkArithmeticMode_scalar(k1, k2, k3, k4, enforcePMColor); |
| 240 } | 152 } |
| 241 | 153 |
| 242 | 154 |
| 243 ////////////////////////////////////////////////////////////////////////////// | 155 ////////////////////////////////////////////////////////////////////////////// |
| 244 | 156 |
| 245 #if SK_SUPPORT_GPU | 157 #if SK_SUPPORT_GPU |
| 246 const GrFragmentProcessor* SkArithmeticMode_scalar::getFragmentProcessorForImage
Filter( | 158 const GrFragmentProcessor* SkArithmeticMode_scalar::getFragmentProcessorForImage
Filter( |
| 247 const GrFragmentProc
essor* dst) const { | 159 const GrFragmentProc
essor* dst) const { |
| 248 return GrArithmeticFP::Create(SkScalarToFloat(fK[0]), | 160 return GrArithmeticFP::Create(SkScalarToFloat(fK[0]), |
| 249 SkScalarToFloat(fK[1]), | 161 SkScalarToFloat(fK[1]), |
| 250 SkScalarToFloat(fK[2]), | 162 SkScalarToFloat(fK[2]), |
| 251 SkScalarToFloat(fK[3]), | 163 SkScalarToFloat(fK[3]), |
| 252 fEnforcePMColor, | 164 fEnforcePMColor, |
| 253 dst); | 165 dst); |
| 254 } | 166 } |
| 255 | 167 |
| 256 GrXPFactory* SkArithmeticMode_scalar::asXPFactory() const { | 168 GrXPFactory* SkArithmeticMode_scalar::asXPFactory() const { |
| 257 return GrArithmeticXPFactory::Create(SkScalarToFloat(fK[0]), | 169 return GrArithmeticXPFactory::Create(SkScalarToFloat(fK[0]), |
| 258 SkScalarToFloat(fK[1]), | 170 SkScalarToFloat(fK[1]), |
| 259 SkScalarToFloat(fK[2]), | 171 SkScalarToFloat(fK[2]), |
| 260 SkScalarToFloat(fK[3]), | 172 SkScalarToFloat(fK[3]), |
| 261 fEnforcePMColor); | 173 fEnforcePMColor); |
| 262 } | 174 } |
| 263 | 175 |
| 264 #endif | 176 #endif |
| 265 | 177 |
| 266 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode) | 178 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode) |
| 267 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar) | 179 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar) |
| 268 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 180 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| OLD | NEW |