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