• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/sgl/SkBlitter_ARGB32.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 "SkUtils.h"
22 #include "SkXfermode.h"
23 
SkARGB32_Blitter(const SkBitmap & device,const SkPaint & paint)24 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
25         : INHERITED(device) {
26     uint32_t color = paint.getColor();
27 
28     fSrcA = SkColorGetA(color);
29     unsigned scale = SkAlpha255To256(fSrcA);
30     fSrcR = SkAlphaMul(SkColorGetR(color), scale);
31     fSrcG = SkAlphaMul(SkColorGetG(color), scale);
32     fSrcB = SkAlphaMul(SkColorGetB(color), scale);
33 
34     fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
35 }
36 
justAnOpaqueColor(uint32_t * value)37 const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
38     if (255 == fSrcA) {
39         *value = fPMColor;
40         return &fDevice;
41     }
42     return NULL;
43 }
44 
45 #if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
46 #pragma warning ( push )
47 #pragma warning ( disable : 4701 )
48 #endif
49 
blitH(int x,int y,int width)50 void SkARGB32_Blitter::blitH(int x, int y, int width) {
51     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
52 
53     if (fSrcA == 0) {
54         return;
55     }
56 
57     uint32_t* device = fDevice.getAddr32(x, y);
58 
59     if (fSrcA == 255) {
60         sk_memset32(device, fPMColor, width);
61     } else {
62         uint32_t color = fPMColor;
63         unsigned dst_scale = SkAlpha255To256(255 - fSrcA);
64         uint32_t prevDst = ~device[0];  // so we always fail the test the first time
65         uint32_t result SK_INIT_TO_AVOID_WARNING;
66 
67         for (int i = 0; i < width; i++) {
68             uint32_t currDst = device[i];
69             if (currDst != prevDst) {
70                 result = color + SkAlphaMulQ(currDst, dst_scale);
71                 prevDst = currDst;
72             }
73             device[i] = result;
74         }
75     }
76 }
77 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])78 void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
79                                  const int16_t runs[]) {
80     if (fSrcA == 0) {
81         return;
82     }
83 
84     uint32_t    color = fPMColor;
85     uint32_t*   device = fDevice.getAddr32(x, y);
86     unsigned    opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
87 
88     for (;;) {
89         int count = runs[0];
90         SkASSERT(count >= 0);
91         if (count <= 0) {
92             return;
93         }
94         unsigned aa = antialias[0];
95         if (aa) {
96             if ((opaqueMask & aa) == 255) {
97                 sk_memset32(device, color, count);
98             } else {
99                 uint32_t sc = SkAlphaMulQ(color, aa);
100                 unsigned dst_scale = 255 - SkGetPackedA32(sc);
101                 int n = count;
102                 do {
103                     --n;
104                     device[n] = sc + SkAlphaMulQ(device[n], dst_scale);
105                 } while (n > 0);
106             }
107         }
108         runs += count;
109         antialias += count;
110         device += count;
111     }
112 }
113 
114 //////////////////////////////////////////////////////////////////////////////////////
115 
116 #define solid_8_pixels(mask, dst, color)    \
117     do {                                    \
118         if (mask & 0x80) dst[0] = color;    \
119         if (mask & 0x40) dst[1] = color;    \
120         if (mask & 0x20) dst[2] = color;    \
121         if (mask & 0x10) dst[3] = color;    \
122         if (mask & 0x08) dst[4] = color;    \
123         if (mask & 0x04) dst[5] = color;    \
124         if (mask & 0x02) dst[6] = color;    \
125         if (mask & 0x01) dst[7] = color;    \
126     } while (0)
127 
128 #define SK_BLITBWMASK_NAME                  SkARGB32_BlitBW
129 #define SK_BLITBWMASK_ARGS                  , SkPMColor color
130 #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
131 #define SK_BLITBWMASK_GETADDR               getAddr32
132 #define SK_BLITBWMASK_DEVTYPE               uint32_t
133 #include "SkBlitBWMaskTemplate.h"
134 
135 #define blend_8_pixels(mask, dst, sc, dst_scale)                            \
136     do {                                                                    \
137         if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); }  \
138         if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); }  \
139         if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); }  \
140         if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); }  \
141         if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); }  \
142         if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); }  \
143         if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); }  \
144         if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); }  \
145     } while (0)
146 
147 #define SK_BLITBWMASK_NAME                  SkARGB32_BlendBW
148 #define SK_BLITBWMASK_ARGS                  , uint32_t sc, unsigned dst_scale
149 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
150 #define SK_BLITBWMASK_GETADDR               getAddr32
151 #define SK_BLITBWMASK_DEVTYPE               uint32_t
152 #include "SkBlitBWMaskTemplate.h"
153 
blitMask(const SkMask & mask,const SkIRect & clip)154 void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
155     SkASSERT(mask.fBounds.contains(clip));
156     SkASSERT(fSrcA != 0xFF);
157 
158     if (fSrcA == 0) {
159         return;
160     }
161 
162     if (mask.fFormat == SkMask::kBW_Format) {
163         SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
164         return;
165     }
166 
167     int x = clip.fLeft;
168     int y = clip.fTop;
169     int width = clip.width();
170     int height = clip.height();
171 
172     uint32_t*       device = fDevice.getAddr32(x, y);
173     const uint8_t*  alpha = mask.getAddr(x, y);
174     uint32_t        srcColor = fPMColor;
175     unsigned        devRB = fDevice.rowBytes() - (width << 2);
176     unsigned        maskRB = mask.fRowBytes - width;
177 
178     do {
179         int w = width;
180         do {
181             unsigned aa = *alpha++;
182             *device = SkBlendARGB32(srcColor, *device, aa);
183             device += 1;
184         } while (--w != 0);
185         device = (uint32_t*)((char*)device + devRB);
186         alpha += maskRB;
187     } while (--height != 0);
188 }
189 
blitMask(const SkMask & mask,const SkIRect & clip)190 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
191                                        const SkIRect& clip) {
192     SkASSERT(mask.fBounds.contains(clip));
193 
194     if (mask.fFormat == SkMask::kBW_Format) {
195         SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
196         return;
197     }
198 
199     int x = clip.fLeft;
200     int y = clip.fTop;
201     int width = clip.width();
202     int height = clip.height();
203 
204     uint32_t*       device = fDevice.getAddr32(x, y);
205     const uint8_t*  alpha = mask.getAddr(x, y);
206     uint32_t        srcColor = fPMColor;
207     unsigned        devRB = fDevice.rowBytes() - (width << 2);
208     unsigned        maskRB = mask.fRowBytes - width;
209 
210     do {
211         int w = width;
212         do {
213             unsigned aa = *alpha++;
214             *device = SkAlphaMulQ(srcColor, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
215             device += 1;
216         } while (--w != 0);
217         device = (uint32_t*)((char*)device + devRB);
218         alpha += maskRB;
219     } while (--height != 0);
220 }
221 
222 //////////////////////////////////////////////////////////////////////////////////////
223 
blitV(int x,int y,int height,SkAlpha alpha)224 void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
225     if (alpha == 0 || fSrcA == 0) {
226         return;
227     }
228 
229     uint32_t* device = fDevice.getAddr32(x, y);
230     uint32_t  color = fPMColor;
231 
232     if (alpha != 255) {
233         color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
234     }
235 
236     unsigned dst_scale = 255 - SkGetPackedA32(color);
237     uint32_t prevDst = ~device[0];
238     uint32_t result  SK_INIT_TO_AVOID_WARNING;
239     uint32_t rowBytes = fDevice.rowBytes();
240 
241     while (--height >= 0) {
242         uint32_t dst = device[0];
243         if (dst != prevDst) {
244             result = color + SkAlphaMulQ(dst, dst_scale);
245             prevDst = dst;
246         }
247         device[0] = result;
248         device = (uint32_t*)((char*)device + rowBytes);
249     }
250 }
251 
blitRect(int x,int y,int width,int height)252 void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
253     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
254 
255     if (fSrcA == 0) {
256         return;
257     }
258 
259     uint32_t*   device = fDevice.getAddr32(x, y);
260     uint32_t    color = fPMColor;
261 
262     if (fSrcA == 255) {
263         while (--height >= 0) {
264             sk_memset32(device, color, width);
265             device = (uint32_t*)((char*)device + fDevice.rowBytes());
266         }
267     } else {
268         unsigned dst_scale = SkAlpha255To256(255 - fSrcA);
269 
270         while (--height >= 0) {
271             uint32_t prevDst = ~device[0];
272             uint32_t result SK_INIT_TO_AVOID_WARNING;
273 
274             for (int i = 0; i < width; i++) {
275                 uint32_t dst = device[i];
276                 if (dst != prevDst) {
277                     result = color + SkAlphaMulQ(dst, dst_scale);
278                     prevDst = dst;
279                 }
280                 device[i] = result;
281             }
282             device = (uint32_t*)((char*)device + fDevice.rowBytes());
283         }
284     }
285 }
286 
287 #if defined _WIN32 && _MSC_VER >= 1300
288 #pragma warning ( pop )
289 #endif
290 
291 ///////////////////////////////////////////////////////////////////////
292 
blitMask(const SkMask & mask,const SkIRect & clip)293 void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
294     SkASSERT(mask.fBounds.contains(clip));
295 
296     if (mask.fFormat == SkMask::kBW_Format) {
297         SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
298 
299         SkARGB32_BlitBW(fDevice, mask, clip, black);
300     } else {
301         uint32_t*       device = fDevice.getAddr32(clip.fLeft, clip.fTop);
302         const uint8_t*  alpha = mask.getAddr(clip.fLeft, clip.fTop);
303         unsigned        width = clip.width();
304         unsigned        height = clip.height();
305         unsigned        deviceRB = fDevice.rowBytes() - (width << 2);
306         unsigned        maskRB = mask.fRowBytes - width;
307 
308         SkASSERT((int)height > 0);
309         SkASSERT((int)width > 0);
310         SkASSERT((int)deviceRB >= 0);
311         SkASSERT((int)maskRB >= 0);
312 
313         do {
314             unsigned w = width;
315             do {
316                 unsigned aa = *alpha++;
317                 *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
318                 device += 1;
319             } while (--w != 0);
320             device = (uint32_t*)((char*)device + deviceRB);
321             alpha += maskRB;
322         } while (--height != 0);
323     }
324 }
325 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])326 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
327                                        const int16_t runs[]) {
328     uint32_t*   device = fDevice.getAddr32(x, y);
329     SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
330 
331     for (;;) {
332         int count = runs[0];
333         SkASSERT(count >= 0);
334         if (count <= 0) {
335             return;
336         }
337         unsigned aa = antialias[0];
338         if (aa) {
339             if (aa == 255) {
340                 sk_memset32(device, black, count);
341             } else {
342                 SkPMColor src = aa << SK_A32_SHIFT;
343                 unsigned dst_scale = 256 - aa;
344                 int n = count;
345                 do {
346                     --n;
347                     device[n] = src + SkAlphaMulQ(device[n], dst_scale);
348                 } while (n > 0);
349             }
350         }
351         runs += count;
352         antialias += count;
353         device += count;
354     }
355 }
356 
357 //////////////////////////////////////////////////////////////////////////////////////////
358 
SkARGB32_Shader_Blitter(const SkBitmap & device,const SkPaint & paint)359 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
360                                                  const SkPaint& paint)
361         : INHERITED(device, paint) {
362     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
363 
364     (fXfermode = paint.getXfermode())->safeRef();
365 }
366 
~SkARGB32_Shader_Blitter()367 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
368     fXfermode->safeUnref();
369     sk_free(fBuffer);
370 }
371 
blitH(int x,int y,int width)372 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
373     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
374 
375     uint32_t*   device = fDevice.getAddr32(x, y);
376 
377     if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
378         fShader->shadeSpan(x, y, device, width);
379     } else {
380         SkPMColor*  span = fBuffer;
381         fShader->shadeSpan(x, y, span, width);
382         if (fXfermode) {
383             fXfermode->xfer32(device, span, width, NULL);
384         } else {
385             for (int i = 0; i < width; i++) {
386                 uint32_t src = span[i];
387                 if (src) {
388                     unsigned srcA = SkGetPackedA32(src);
389                     if (srcA != 0xFF) {
390                         src += SkAlphaMulQ(device[i], SkAlpha255To256(255 - srcA));
391                     }
392                     device[i] = src;
393                 }
394             }
395         }
396     }
397 }
398 
399 ///////////////////////////////////////////////////////////////////////////////////////////////
400 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])401 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
402                                         const int16_t runs[]) {
403     SkPMColor*  span = fBuffer;
404     uint32_t*   device = fDevice.getAddr32(x, y);
405     SkShader*   shader = fShader;
406 
407     if (fXfermode) {
408         for (;;) {
409             SkXfermode* xfer = fXfermode;
410 
411             int count = *runs;
412             if (count <= 0)
413                 break;
414             int aa = *antialias;
415             if (aa) {
416                 shader->shadeSpan(x, y, span, count);
417                 if (aa == 255) {
418                     xfer->xfer32(device, span, count, NULL);
419                 } else {
420                     // count is almost always 1
421                     for (int i = count - 1; i >= 0; --i) {
422                         xfer->xfer32(&device[i], &span[i], 1, antialias);
423                     }
424                 }
425             }
426             device += count;
427             runs += count;
428             antialias += count;
429             x += count;
430         }
431     } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
432         for (;;) {
433             int count = *runs;
434             if (count <= 0) {
435                 break;
436             }
437             int aa = *antialias;
438             if (aa) {
439                 if (aa == 255) {  // cool, have the shader draw right into the device
440                     shader->shadeSpan(x, y, device, count);
441                 } else {
442                     shader->shadeSpan(x, y, span, count);
443                     for (int i = count - 1; i >= 0; --i) {
444                         if (span[i]) {
445                             device[i] = SkBlendARGB32(span[i], device[i], aa);
446                         }
447                     }
448                 }
449             }
450             device += count;
451             runs += count;
452             antialias += count;
453             x += count;
454         }
455     } else {    // no xfermode but we are not opaque
456         for (;;) {
457             int count = *runs;
458             if (count <= 0) {
459                 break;
460             }
461             int aa = *antialias;
462             if (aa) {
463                 fShader->shadeSpan(x, y, span, count);
464                 if (aa == 255) {
465                     for (int i = count - 1; i >= 0; --i) {
466                         if (span[i]) {
467                             device[i] = SkPMSrcOver(span[i], device[i]);
468                         }
469                     }
470                 } else {
471                     for (int i = count - 1; i >= 0; --i) {
472                         if (span[i]) {
473                             device[i] = SkBlendARGB32(span[i], device[i], aa);
474                         }
475                     }
476                 }
477             }
478             device += count;
479             runs += count;
480             antialias += count;
481             x += count;
482         }
483     }
484 }
485 
486