• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/effects/SkAvoidXfermode.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkAvoidXfermode.h"
19 #include "SkColorPriv.h"
20 
SkAvoidXfermode(SkColor opColor,U8CPU tolerance,Mode mode)21 SkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode)
22 {
23     if (tolerance > 255) {
24         tolerance = 255;
25     }
26 
27     fOpColor = opColor;
28     fDistMul = (256 << 14) / (tolerance + 1);
29     fMode = mode;
30 }
31 
SkAvoidXfermode(SkFlattenableReadBuffer & buffer)32 SkAvoidXfermode::SkAvoidXfermode(SkFlattenableReadBuffer& buffer)
33     : INHERITED(buffer)
34 {
35     fOpColor = buffer.readU32();
36     fDistMul = buffer.readU32();
37     fMode = (Mode)buffer.readU8();
38 }
39 
flatten(SkFlattenableWriteBuffer & buffer)40 void SkAvoidXfermode::flatten(SkFlattenableWriteBuffer& buffer)
41 {
42     this->INHERITED::flatten(buffer);
43 
44     buffer.write32(fOpColor);
45     buffer.write32(fDistMul);
46     buffer.write8(fMode);
47 }
48 
Create(SkFlattenableReadBuffer & rb)49 SkFlattenable* SkAvoidXfermode::Create(SkFlattenableReadBuffer& rb)
50 {
51     return SkNEW_ARGS(SkAvoidXfermode, (rb));
52 }
53 
getFactory()54 SkFlattenable::Factory SkAvoidXfermode::getFactory()
55 {
56     return Create;
57 }
58 
59 // returns 0..31
color_dist16(uint16_t c,unsigned r,unsigned g,unsigned b)60 static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b)
61 {
62     SkASSERT(r <= SK_R16_MASK);
63     SkASSERT(g <= SK_G16_MASK);
64     SkASSERT(b <= SK_B16_MASK);
65 
66     unsigned dr = SkAbs32(SkGetPackedR16(c) - r);
67     unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS);
68     unsigned db = SkAbs32(SkGetPackedB16(c) - b);
69 
70     return SkMax32(dr, SkMax32(dg, db));
71 }
72 
73 // returns 0..15
color_dist4444(uint16_t c,unsigned r,unsigned g,unsigned b)74 static unsigned color_dist4444(uint16_t c, unsigned r, unsigned g, unsigned b)
75 {
76     SkASSERT(r <= 0xF);
77     SkASSERT(g <= 0xF);
78     SkASSERT(b <= 0xF);
79 
80     unsigned dr = SkAbs32(SkGetPackedR4444(c) - r);
81     unsigned dg = SkAbs32(SkGetPackedG4444(c) - g);
82     unsigned db = SkAbs32(SkGetPackedB4444(c) - b);
83 
84     return SkMax32(dr, SkMax32(dg, db));
85 }
86 
87 // returns 0..255
color_dist32(SkPMColor c,U8CPU r,U8CPU g,U8CPU b)88 static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b)
89 {
90     SkASSERT(r <= 0xFF);
91     SkASSERT(g <= 0xFF);
92     SkASSERT(b <= 0xFF);
93 
94     unsigned dr = SkAbs32(SkGetPackedR32(c) - r);
95     unsigned dg = SkAbs32(SkGetPackedG32(c) - g);
96     unsigned db = SkAbs32(SkGetPackedB32(c) - b);
97 
98     return SkMax32(dr, SkMax32(dg, db));
99 }
100 
scale_dist_14(int dist,uint32_t mul,uint32_t sub)101 static int scale_dist_14(int dist, uint32_t mul, uint32_t sub)
102 {
103     int tmp = dist * mul - sub;
104     int result = (tmp + (1 << 13)) >> 14;
105 
106     return result;
107 }
108 
SkFourByteInterp(SkPMColor src,SkPMColor dst,unsigned scale)109 static SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, unsigned scale)
110 {
111     unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
112     unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
113     unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
114     unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
115 
116     return SkPackARGB32(a, r, g, b);
117 }
118 
xfer32(SkPMColor dst[],const SkPMColor src[],int count,const SkAlpha aa[])119 void SkAvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
120                              const SkAlpha aa[])
121 {
122     unsigned    opR = SkColorGetR(fOpColor);
123     unsigned    opG = SkColorGetG(fOpColor);
124     unsigned    opB = SkColorGetB(fOpColor);
125     uint32_t    mul = fDistMul;
126     uint32_t    sub = (fDistMul - (1 << 14)) << 8;
127 
128     int MAX, mask;
129 
130     if (kTargetColor_Mode == fMode) {
131         mask = -1;
132         MAX = 255;
133     } else {
134         mask = 0;
135         MAX = 0;
136     }
137 
138     for (int i = 0; i < count; i++) {
139         int d = color_dist32(dst[i], opR, opG, opB);
140         // now reverse d if we need to
141         d = MAX + (d ^ mask) - mask;
142         SkASSERT((unsigned)d <= 255);
143         d = SkAlpha255To256(d);
144 
145         d = scale_dist_14(d, mul, sub);
146         SkASSERT(d <= 256);
147 
148         if (d > 0) {
149             if (NULL != aa) {
150                 d = SkAlphaMul(d, SkAlpha255To256(*aa++));
151                 if (0 == d) {
152                     continue;
153                 }
154             }
155             dst[i] = SkFourByteInterp(src[i], dst[i], d);
156         }
157     }
158 }
159 
SkBlend3216(SkPMColor src,U16CPU dst,unsigned scale)160 static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale)
161 {
162     SkASSERT(scale <= 32);
163     scale <<= 3;
164 
165     return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale),
166                         SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale),
167                         SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale));
168 }
169 
xfer16(uint16_t dst[],const SkPMColor src[],int count,const SkAlpha aa[])170 void SkAvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
171                              const SkAlpha aa[])
172 {
173     unsigned    opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS);
174     unsigned    opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS);
175     unsigned    opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS);
176     uint32_t    mul = fDistMul;
177     uint32_t    sub = (fDistMul - (1 << 14)) << 8;
178 
179     int MAX, mask;
180 
181     if (kTargetColor_Mode == fMode) {
182         mask = -1;
183         MAX = 31;
184     } else {
185         mask = 0;
186         MAX = 0;
187     }
188 
189     for (int i = 0; i < count; i++) {
190         int d = color_dist16(dst[i], opR, opG, opB);
191         // now reverse d if we need to
192         d = MAX + (d ^ mask) - mask;
193         SkASSERT((unsigned)d <= 31);
194         // convert from 0..31 to 0..32
195         d += d >> 4;
196 
197         d = scale_dist_14(d, mul, sub);
198         SkASSERT(d <= 32);
199 
200         if (d > 0) {
201             if (NULL != aa) {
202                 d = SkAlphaMul(d, SkAlpha255To256(*aa++));
203                 if (0 == d) {
204                     continue;
205                 }
206             }
207             dst[i] = SkBlend3216(src[i], dst[i], d);
208         }
209     }
210 }
211 
xfer4444(uint16_t dst[],const SkPMColor src[],int count,const SkAlpha aa[])212 void SkAvoidXfermode::xfer4444(uint16_t dst[], const SkPMColor src[], int count,
213                                const SkAlpha aa[])
214 {
215     unsigned    opR = SkColorGetR(fOpColor) >> 4;
216     unsigned    opG = SkColorGetG(fOpColor) >> 4;
217     unsigned    opB = SkColorGetB(fOpColor) >> 4;
218     uint32_t    mul = fDistMul;
219     uint32_t    sub = (fDistMul - (1 << 14)) << 8;
220 
221     int MAX, mask;
222 
223     if (kTargetColor_Mode == fMode) {
224         mask = -1;
225         MAX = 15;
226     } else {
227         mask = 0;
228         MAX = 0;
229     }
230 
231     for (int i = 0; i < count; i++) {
232         int d = color_dist4444(dst[i], opR, opG, opB);
233         // now reverse d if we need to
234         d = MAX + (d ^ mask) - mask;
235         SkASSERT((unsigned)d <= 15);
236         d = SkAlpha255To256(d);
237 
238         d = scale_dist_14(d, mul, sub);
239         SkASSERT(d <= 16);
240 
241         if (d > 0) {
242             if (NULL != aa) {
243                 d = SkAlphaMul(d, SkAlpha255To256(*aa++));
244                 if (0 == d) {
245                     continue;
246                 }
247             }
248             dst[i] = SkBlend4444(SkPixel32ToPixel4444(src[i]), dst[i], d);
249         }
250     }
251 }
252 
xferA8(SkAlpha dst[],const SkPMColor src[],int count,const SkAlpha aa[])253 void SkAvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count, const SkAlpha aa[])
254 {
255     // override in subclass
256 }
257 
258