• 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 "SkCoreBlitters.h"
11 #include "SkColorPriv.h"
12 #include "SkShader.h"
13 #include "SkXfermode.h"
14 
SkA8_Blitter(const SkBitmap & device,const SkPaint & paint)15 SkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint)
16         : INHERITED(device) {
17     fSrcA = paint.getAlpha();
18 }
19 
justAnOpaqueColor(uint32_t * value)20 const SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) {
21     if (255 == fSrcA) {
22         *value = 255;
23         return &fDevice;
24     }
25     return NULL;
26 }
27 
blitH(int x,int y,int width)28 void SkA8_Blitter::blitH(int x, int y, int width) {
29     SkASSERT(x >= 0 && y >= 0 &&
30              (unsigned)(x + width) <= (unsigned)fDevice.width());
31 
32     if (fSrcA == 0) {
33         return;
34     }
35 
36     uint8_t* device = fDevice.getAddr8(x, y);
37 
38     if (fSrcA == 255) {
39         memset(device, 0xFF, width);
40     } else {
41         unsigned scale = 256 - SkAlpha255To256(fSrcA);
42         unsigned srcA = fSrcA;
43 
44         for (int i = 0; i < width; i++) {
45             device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
46         }
47     }
48 }
49 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])50 void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
51                              const int16_t runs[]) {
52     if (fSrcA == 0) {
53         return;
54     }
55 
56     uint8_t*    device = fDevice.getAddr8(x, y);
57     unsigned    srcA = fSrcA;
58 
59     for (;;) {
60         int count = runs[0];
61         SkASSERT(count >= 0);
62         if (count == 0) {
63             return;
64         }
65         unsigned aa = antialias[0];
66 
67         if (aa == 255 && srcA == 255) {
68             memset(device, 0xFF, count);
69         } else {
70             unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa));
71             unsigned scale = 256 - sa;
72 
73             for (int i = 0; i < count; i++) {
74                 device[i] = SkToU8(sa + SkAlphaMul(device[i], scale));
75             }
76         }
77         runs += count;
78         antialias += count;
79         device += count;
80     }
81 }
82 
83 /////////////////////////////////////////////////////////////////////////////////////
84 
85 #define solid_8_pixels(mask, dst)           \
86     do {                                    \
87         if (mask & 0x80) dst[0] = 0xFF;     \
88         if (mask & 0x40) dst[1] = 0xFF;     \
89         if (mask & 0x20) dst[2] = 0xFF;     \
90         if (mask & 0x10) dst[3] = 0xFF;     \
91         if (mask & 0x08) dst[4] = 0xFF;     \
92         if (mask & 0x04) dst[5] = 0xFF;     \
93         if (mask & 0x02) dst[6] = 0xFF;     \
94         if (mask & 0x01) dst[7] = 0xFF;     \
95     } while (0)
96 
97 #define SK_BLITBWMASK_NAME                  SkA8_BlitBW
98 #define SK_BLITBWMASK_ARGS
99 #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst)
100 #define SK_BLITBWMASK_GETADDR               getAddr8
101 #define SK_BLITBWMASK_DEVTYPE               uint8_t
102 #include "SkBlitBWMaskTemplate.h"
103 
blend_8_pixels(U8CPU bw,uint8_t dst[],U8CPU sa,unsigned dst_scale)104 static inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa,
105                                   unsigned dst_scale) {
106     if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale));
107     if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale));
108     if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale));
109     if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale));
110     if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale));
111     if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale));
112     if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale));
113     if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale));
114 }
115 
116 #define SK_BLITBWMASK_NAME                  SkA8_BlendBW
117 #define SK_BLITBWMASK_ARGS                  , U8CPU sa, unsigned dst_scale
118 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sa, dst_scale)
119 #define SK_BLITBWMASK_GETADDR               getAddr8
120 #define SK_BLITBWMASK_DEVTYPE               uint8_t
121 #include "SkBlitBWMaskTemplate.h"
122 
blitMask(const SkMask & mask,const SkIRect & clip)123 void SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
124     if (fSrcA == 0) {
125         return;
126     }
127 
128     if (mask.fFormat == SkMask::kBW_Format) {
129         if (fSrcA == 0xFF) {
130             SkA8_BlitBW(fDevice, mask, clip);
131         } else {
132             SkA8_BlendBW(fDevice, mask, clip, fSrcA,
133                          SkAlpha255To256(255 - fSrcA));
134         }
135         return;
136     }
137 
138     int x = clip.fLeft;
139     int y = clip.fTop;
140     int width = clip.width();
141     int height = clip.height();
142     uint8_t* device = fDevice.getAddr8(x, y);
143     const uint8_t* alpha = mask.getAddr8(x, y);
144     unsigned    srcA = fSrcA;
145 
146     while (--height >= 0) {
147         for (int i = width - 1; i >= 0; --i) {
148             unsigned sa;
149             // scale our src by the alpha value
150             {
151                 int aa = alpha[i];
152                 if (aa == 0) {
153                     continue;
154                 }
155                 if (aa == 255) {
156                     if (srcA == 255) {
157                         device[i] = 0xFF;
158                         continue;
159                     }
160                     sa = srcA;
161                 } else {
162                     sa = SkAlphaMul(srcA, SkAlpha255To256(aa));
163                 }
164             }
165 
166             int scale = 256 - SkAlpha255To256(sa);
167             device[i] = SkToU8(sa + SkAlphaMul(device[i], scale));
168         }
169         device += fDevice.rowBytes();
170         alpha += mask.fRowBytes;
171     }
172 }
173 
174 ///////////////////////////////////////////////////////////////////////////////
175 
blitV(int x,int y,int height,SkAlpha alpha)176 void SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
177     if (fSrcA == 0) {
178         return;
179     }
180 
181     unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha));
182     uint8_t* device = fDevice.getAddr8(x, y);
183     int      rowBytes = fDevice.rowBytes();
184 
185     if (sa == 0xFF) {
186         for (int i = 0; i < height; i++) {
187             *device = SkToU8(sa);
188             device += rowBytes;
189         }
190     } else {
191         unsigned scale = 256 - SkAlpha255To256(sa);
192 
193         for (int i = 0; i < height; i++) {
194             *device = SkToU8(sa + SkAlphaMul(*device, scale));
195             device += rowBytes;
196         }
197     }
198 }
199 
blitRect(int x,int y,int width,int height)200 void SkA8_Blitter::blitRect(int x, int y, int width, int height) {
201     SkASSERT(x >= 0 && y >= 0 &&
202              (unsigned)(x + width) <= (unsigned)fDevice.width() &&
203              (unsigned)(y + height) <= (unsigned)fDevice.height());
204 
205     if (fSrcA == 0) {
206         return;
207     }
208 
209     uint8_t*    device = fDevice.getAddr8(x, y);
210     unsigned    srcA = fSrcA;
211 
212     if (srcA == 255) {
213         while (--height >= 0) {
214             memset(device, 0xFF, width);
215             device += fDevice.rowBytes();
216         }
217     } else {
218         unsigned scale = 256 - SkAlpha255To256(srcA);
219 
220         while (--height >= 0) {
221             for (int i = 0; i < width; i++) {
222                 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
223             }
224             device += fDevice.rowBytes();
225         }
226     }
227 }
228 
229 ///////////////////////////////////////////////////////////////////////
230 
SkA8_Shader_Blitter(const SkBitmap & device,const SkPaint & paint)231 SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint)
232     : INHERITED(device, paint) {
233     if ((fXfermode = paint.getXfermode()) != NULL) {
234         fXfermode->ref();
235         SkASSERT(fShader);
236     }
237 
238     int width = device.width();
239     fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2)));
240     fAAExpand = (uint8_t*)(fBuffer + width);
241 }
242 
~SkA8_Shader_Blitter()243 SkA8_Shader_Blitter::~SkA8_Shader_Blitter() {
244     if (fXfermode) SkSafeUnref(fXfermode);
245     sk_free(fBuffer);
246 }
247 
blitH(int x,int y,int width)248 void SkA8_Shader_Blitter::blitH(int x, int y, int width) {
249     SkASSERT(x >= 0 && y >= 0 &&
250              (unsigned)(x + width) <= (unsigned)fDevice.width());
251 
252     uint8_t* device = fDevice.getAddr8(x, y);
253 
254     if ((fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) {
255         memset(device, 0xFF, width);
256     } else {
257         SkPMColor*  span = fBuffer;
258 
259         fShader->shadeSpan(x, y, span, width);
260         if (fXfermode) {
261             fXfermode->xferA8(device, span, width, NULL);
262         } else {
263             for (int i = width - 1; i >= 0; --i) {
264                 unsigned    srcA = SkGetPackedA32(span[i]);
265                 unsigned    scale = 256 - SkAlpha255To256(srcA);
266 
267                 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
268             }
269         }
270     }
271 }
272 
aa_blend8(SkPMColor src,U8CPU da,int aa)273 static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) {
274     SkASSERT((unsigned)aa <= 255);
275 
276     int src_scale = SkAlpha255To256(aa);
277     int sa = SkGetPackedA32(src);
278     int dst_scale = 256 - SkAlphaMul(sa, src_scale);
279 
280     return SkToU8((sa * src_scale + da * dst_scale) >> 8);
281 }
282 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])283 void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
284                                     const int16_t runs[]) {
285     SkShader*   shader = fShader;
286     SkXfermode* mode = fXfermode;
287     uint8_t*    aaExpand = fAAExpand;
288     SkPMColor*  span = fBuffer;
289     uint8_t*    device = fDevice.getAddr8(x, y);
290     int         opaque = fShader->getFlags() & SkShader::kOpaqueAlpha_Flag;
291 
292     for (;;) {
293         int count = *runs;
294         if (count == 0) {
295             break;
296         }
297         int aa = *antialias;
298         if (aa) {
299             if (opaque && aa == 255 && mode == NULL) {
300                 memset(device, 0xFF, count);
301             } else {
302                 shader->shadeSpan(x, y, span, count);
303                 if (mode) {
304                     memset(aaExpand, aa, count);
305                     mode->xferA8(device, span, count, aaExpand);
306                 } else {
307                     for (int i = count - 1; i >= 0; --i) {
308                         device[i] = aa_blend8(span[i], device[i], aa);
309                     }
310                 }
311             }
312         }
313         device += count;
314         runs += count;
315         antialias += count;
316         x += count;
317     }
318 }
319 
blitMask(const SkMask & mask,const SkIRect & clip)320 void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
321     if (mask.fFormat == SkMask::kBW_Format) {
322         this->INHERITED::blitMask(mask, clip);
323         return;
324     }
325 
326     int x = clip.fLeft;
327     int y = clip.fTop;
328     int width = clip.width();
329     int height = clip.height();
330     uint8_t* device = fDevice.getAddr8(x, y);
331     const uint8_t* alpha = mask.getAddr8(x, y);
332 
333     SkPMColor*  span = fBuffer;
334 
335     while (--height >= 0) {
336         fShader->shadeSpan(x, y, span, width);
337         if (fXfermode) {
338             fXfermode->xferA8(device, span, width, alpha);
339         }
340 
341         y += 1;
342         device += fDevice.rowBytes();
343         alpha += mask.fRowBytes;
344     }
345 }
346 
347