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