• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkArithmeticMode.h"
2 #include "SkColorPriv.h"
3 #include "SkUnPreMultiply.h"
4 
5 class SkArithmeticMode_scalar : public SkXfermode {
6 public:
SkArithmeticMode_scalar(SkScalar k1,SkScalar k2,SkScalar k3,SkScalar k4)7     SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4) {
8         fK[0] = k1;
9         fK[1] = k2;
10         fK[2] = k3;
11         fK[3] = k4;
12     }
13 
14     virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
15                         const SkAlpha aa[]) SK_OVERRIDE;
16     virtual Factory getFactory() SK_OVERRIDE;
17 
Create(SkFlattenableReadBuffer & buffer)18     static SkFlattenable* Create(SkFlattenableReadBuffer& buffer) {
19         return NULL;
20     }
21 
22 private:
23     SkScalar fK[4];
24 };
25 
getFactory()26 SkFlattenable::Factory SkArithmeticMode_scalar::getFactory() {
27     return Create;
28 }
29 
pinToByte(int value)30 static int pinToByte(int value) {
31     if (value < 0) {
32         value = 0;
33     } else if (value > 255) {
34         value = 255;
35     }
36     return value;
37 }
38 
arith(SkScalar k1,SkScalar k2,SkScalar k3,SkScalar k4,int src,int dst)39 static int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
40                  int src, int dst) {
41     SkScalar result = SkScalarMul(k1, src * dst) +
42                       SkScalarMul(k2, src) +
43                       SkScalarMul(k3, dst) +
44                       k4;
45     int res = SkScalarRoundToInt(result);
46     return pinToByte(res);
47 }
48 
blend(int src,int dst,int scale)49 static int blend(int src, int dst, int scale) {
50     return dst + ((src - dst) * scale >> 8);
51 }
52 
needsUnpremul(int alpha)53 static bool needsUnpremul(int alpha) {
54     return 0 != alpha && 0xFF != alpha;
55 }
56 
xfer32(SkPMColor dst[],const SkPMColor src[],int count,const SkAlpha aaCoverage[])57 void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
58                                      int count, const SkAlpha aaCoverage[]) {
59     SkScalar k1 = fK[0] / 255;
60     SkScalar k2 = fK[1];
61     SkScalar k3 = fK[2];
62     SkScalar k4 = fK[3] * 255;
63 
64     for (int i = 0; i < count; ++i) {
65         if ((NULL == aaCoverage) || aaCoverage[i]) {
66             SkPMColor sc = src[i];
67             SkPMColor dc = dst[i];
68             int sa = SkGetPackedA32(sc);
69             int da = SkGetPackedA32(dc);
70 
71             int srcNeedsUnpremul = needsUnpremul(sa);
72             int dstNeedsUnpremul = needsUnpremul(sa);
73 
74             int a, r, g, b;
75 
76             if (!srcNeedsUnpremul && !srcNeedsUnpremul) {
77                 a = arith(k1, k2, k3, k4, sa, sa);
78                 r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
79                 g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
80                 b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
81             } else {
82                 int sr = SkGetPackedR32(sc);
83                 int sg = SkGetPackedG32(sc);
84                 int sb = SkGetPackedB32(sc);
85                 if (srcNeedsUnpremul) {
86                     SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(sa);
87                     sr = SkUnPreMultiply::ApplyScale(scale, sr);
88                     sg = SkUnPreMultiply::ApplyScale(scale, sg);
89                     sb = SkUnPreMultiply::ApplyScale(scale, sb);
90                 }
91 
92                 int dr = SkGetPackedR32(dc);
93                 int dg = SkGetPackedG32(dc);
94                 int db = SkGetPackedB32(dc);
95                 if (dstNeedsUnpremul) {
96                     SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(da);
97                     dr = SkUnPreMultiply::ApplyScale(scale, dr);
98                     dg = SkUnPreMultiply::ApplyScale(scale, dg);
99                     db = SkUnPreMultiply::ApplyScale(scale, db);
100                 }
101 
102                 a = arith(k1, k2, k3, k4, sa, sa);
103                 r = arith(k1, k2, k3, k4, sr, dr);
104                 g = arith(k1, k2, k3, k4, sg, dg);
105                 b = arith(k1, k2, k3, k4, sb, db);
106             }
107 
108             // apply antialias coverage if necessary
109             if (aaCoverage && 0xFF != aaCoverage[i]) {
110                 int scale = aaCoverage[i] + (aaCoverage[i] >> 7);
111                 a = blend(a, SkGetPackedA32(sc), scale);
112                 r = blend(r, SkGetPackedR32(sc), scale);
113                 g = blend(g, SkGetPackedG32(sc), scale);
114                 b = blend(b, SkGetPackedB32(sc), scale);
115             }
116 
117             // turn the result back into premul
118             if (0xFF != a) {
119                 int scale = a + (a >> 7);
120                 r = SkAlphaMul(r, scale);
121                 g = SkAlphaMul(g, scale);
122                 b = SkAlphaMul(b, scale);
123             }
124             dst[i] = SkPackARGB32(a, r, g, b);
125         }
126     }
127 }
128 
129 
130 ///////////////////////////////////////////////////////////////////////////////
131 
fitsInBits(SkScalar x,int bits)132 static bool fitsInBits(SkScalar x, int bits) {
133 #ifdef SK_SCALAR_IS_FIXED
134     x = SkAbs32(x);
135     x += 1 << 7;
136     x >>= 8;
137     return x < (1 << (bits - 1));
138 #else
139     return SkScalarAbs(x) < (1 << (bits - 1));
140 #endif
141 }
142 
toDot8(SkScalar x)143 static int32_t toDot8(SkScalar x) {
144 #ifdef SK_SCALAR_IS_FIXED
145     x += 1 << 7;
146     x >>= 8;
147     return x;
148 #else
149     return (int32_t)(x * 256);
150 #endif
151 }
152 
Create(SkScalar k1,SkScalar k2,SkScalar k3,SkScalar k4)153 SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
154                                      SkScalar k3, SkScalar k4) {
155     if (fitsInBits(k1, 8) && fitsInBits(k2, 16) &&
156         fitsInBits(k2, 16) && fitsInBits(k2, 24)) {
157 
158         int32_t i1 = toDot8(k1);
159         int32_t i2 = toDot8(k2);
160         int32_t i3 = toDot8(k3);
161         int32_t i4 = toDot8(k4);
162 #if 0
163         if (i1) {
164             return SkNEW_ARGS(SkArithmeticMode_quad, (i1, i2, i3, i4));
165         }
166         if (0 == i2) {
167             return SkNEW_ARGS(SkArithmeticMode_dst, (i3, i4));
168         }
169         if (0 == i3) {
170             return SkNEW_ARGS(SkArithmeticMode_src, (i2, i4));
171         }
172         return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4));
173 #endif
174     }
175     return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4));
176 }
177 
178