1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkArithmeticMode.h"
9 #include "SkColorPriv.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12 #include "SkString.h"
13 #include "SkUnPreMultiply.h"
14 #if SK_SUPPORT_GPU
15 #include "SkArithmeticMode_gpu.h"
16 #endif
17
18 class SkArithmeticMode_scalar : public SkXfermode {
19 public:
SkArithmeticMode_scalar(SkScalar k1,SkScalar k2,SkScalar k3,SkScalar k4,bool enforcePMColor)20 SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
21 bool enforcePMColor) {
22 fK[0] = k1;
23 fK[1] = k2;
24 fK[2] = k3;
25 fK[3] = k4;
26 fEnforcePMColor = enforcePMColor;
27 }
28
29 void xfer32(SkPMColor[], const SkPMColor[], int count, const SkAlpha[]) const override;
30
31 SK_TO_STRING_OVERRIDE()
32 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar)
33
34 #if SK_SUPPORT_GPU
35 const GrFragmentProcessor* getFragmentProcessorForImageFilter(
36 const GrFragmentProcessor* dst) const override;
37 GrXPFactory* asXPFactory() const override;
38 #endif
39
40 private:
flatten(SkWriteBuffer & buffer) const41 void flatten(SkWriteBuffer& buffer) const override {
42 buffer.writeScalar(fK[0]);
43 buffer.writeScalar(fK[1]);
44 buffer.writeScalar(fK[2]);
45 buffer.writeScalar(fK[3]);
46 buffer.writeBool(fEnforcePMColor);
47 }
48
49 SkScalar fK[4];
50 bool fEnforcePMColor;
51
52 friend class SkArithmeticMode;
53
54 typedef SkXfermode INHERITED;
55 };
56
CreateProc(SkReadBuffer & buffer)57 SkFlattenable* SkArithmeticMode_scalar::CreateProc(SkReadBuffer& buffer) {
58 const SkScalar k1 = buffer.readScalar();
59 const SkScalar k2 = buffer.readScalar();
60 const SkScalar k3 = buffer.readScalar();
61 const SkScalar k4 = buffer.readScalar();
62 const bool enforcePMColor = buffer.readBool();
63 return SkArithmeticMode::Create(k1, k2, k3, k4, enforcePMColor);
64 }
65
pinToByte(int value)66 static int pinToByte(int value) {
67 if (value < 0) {
68 value = 0;
69 } else if (value > 255) {
70 value = 255;
71 }
72 return value;
73 }
74
arith(SkScalar k1,SkScalar k2,SkScalar k3,SkScalar k4,int src,int dst)75 static int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
76 int src, int dst) {
77 SkScalar result = SkScalarMul(k1, src * dst) +
78 SkScalarMul(k2, src) +
79 SkScalarMul(k3, dst) +
80 k4;
81 int res = SkScalarRoundToInt(result);
82 return pinToByte(res);
83 }
84
blend(int src,int dst,int scale)85 static int blend(int src, int dst, int scale) {
86 return dst + ((src - dst) * scale >> 8);
87 }
88
xfer32(SkPMColor dst[],const SkPMColor src[],int count,const SkAlpha aaCoverage[]) const89 void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
90 int count, const SkAlpha aaCoverage[]) const {
91 SkScalar k1 = fK[0] / 255;
92 SkScalar k2 = fK[1];
93 SkScalar k3 = fK[2];
94 SkScalar k4 = fK[3] * 255;
95
96 for (int i = 0; i < count; ++i) {
97 if ((nullptr == aaCoverage) || aaCoverage[i]) {
98 SkPMColor sc = src[i];
99 SkPMColor dc = dst[i];
100
101 int a, r, g, b;
102
103 a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc));
104 r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
105 g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
106 b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
107 if (fEnforcePMColor) {
108 r = SkMin32(r, a);
109 g = SkMin32(g, a);
110 b = SkMin32(b, a);
111 }
112
113 // apply antialias coverage if necessary
114 if (aaCoverage && 0xFF != aaCoverage[i]) {
115 int scale = aaCoverage[i] + (aaCoverage[i] >> 7);
116 a = blend(a, SkGetPackedA32(sc), scale);
117 r = blend(r, SkGetPackedR32(sc), scale);
118 g = blend(g, SkGetPackedG32(sc), scale);
119 b = blend(b, SkGetPackedB32(sc), scale);
120 }
121
122 dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32NoCheck(a, r, g, b);
123 }
124 }
125 }
126
127 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const128 void SkArithmeticMode_scalar::toString(SkString* str) const {
129 str->append("SkArithmeticMode_scalar: ");
130 for (int i = 0; i < 4; ++i) {
131 str->appendScalar(fK[i]);
132 str->append(" ");
133 }
134 str->appendS32(fEnforcePMColor ? 1 : 0);
135 }
136 #endif
137
138 ///////////////////////////////////////////////////////////////////////////////
139
Create(SkScalar k1,SkScalar k2,SkScalar k3,SkScalar k4,bool enforcePMColor)140 SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
141 SkScalar k3, SkScalar k4,
142 bool enforcePMColor) {
143 if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) &&
144 SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
145 return SkXfermode::Create(SkXfermode::kSrc_Mode);
146 } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
147 SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) {
148 return SkXfermode::Create(SkXfermode::kDst_Mode);
149 }
150
151 return new SkArithmeticMode_scalar(k1, k2, k3, k4, enforcePMColor);
152 }
153
154
155 //////////////////////////////////////////////////////////////////////////////
156
157 #if SK_SUPPORT_GPU
getFragmentProcessorForImageFilter(const GrFragmentProcessor * dst) const158 const GrFragmentProcessor* SkArithmeticMode_scalar::getFragmentProcessorForImageFilter(
159 const GrFragmentProcessor* dst) const {
160 return GrArithmeticFP::Create(SkScalarToFloat(fK[0]),
161 SkScalarToFloat(fK[1]),
162 SkScalarToFloat(fK[2]),
163 SkScalarToFloat(fK[3]),
164 fEnforcePMColor,
165 dst);
166 }
167
asXPFactory() const168 GrXPFactory* SkArithmeticMode_scalar::asXPFactory() const {
169 return GrArithmeticXPFactory::Create(SkScalarToFloat(fK[0]),
170 SkScalarToFloat(fK[1]),
171 SkScalarToFloat(fK[2]),
172 SkScalarToFloat(fK[3]),
173 fEnforcePMColor);
174 }
175
176 #endif
177
178 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkArithmeticMode)
179 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticMode_scalar)
180 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
181