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