• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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