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