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