• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "SkCoreBlitters.h"
9 #include "SkColorPriv.h"
10 #include "SkShader.h"
11 #include "SkUtils.h"
12 #include "SkXfermode.h"
13 #include "SkBlitMask.h"
14 
15 ///////////////////////////////////////////////////////////////////////////////
16 
SkARGB32_Blit32(const SkBitmap & device,const SkMask & mask,const SkIRect & clip,SkPMColor srcColor)17 static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
18 							const SkIRect& clip, SkPMColor srcColor) {
19 	U8CPU alpha = SkGetPackedA32(srcColor);
20 	unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
21 	if (alpha != 255) {
22 		flags |= SkBlitRow::kGlobalAlpha_Flag32;
23 	}
24 	SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
25 
26     int x = clip.fLeft;
27     int y = clip.fTop;
28     int width = clip.width();
29     int height = clip.height();
30 
31     SkPMColor*		 dstRow = device.getAddr32(x, y);
32     const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
33 
34     do {
35 		proc(dstRow, srcRow, width, alpha);
36         dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
37         srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
38     } while (--height != 0);
39 }
40 
41 //////////////////////////////////////////////////////////////////////////////////////
42 
SkARGB32_Blitter(const SkBitmap & device,const SkPaint & paint)43 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
44         : INHERITED(device) {
45     SkColor color = paint.getColor();
46     fColor = color;
47 
48     fSrcA = SkColorGetA(color);
49     unsigned scale = SkAlpha255To256(fSrcA);
50     fSrcR = SkAlphaMul(SkColorGetR(color), scale);
51     fSrcG = SkAlphaMul(SkColorGetG(color), scale);
52     fSrcB = SkAlphaMul(SkColorGetB(color), scale);
53 
54     fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
55     fColor32Proc = SkBlitRow::ColorProcFactory();
56 }
57 
justAnOpaqueColor(uint32_t * value)58 const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
59     if (255 == fSrcA) {
60         *value = fPMColor;
61         return &fDevice;
62     }
63     return NULL;
64 }
65 
66 #if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
67 #pragma warning ( push )
68 #pragma warning ( disable : 4701 )
69 #endif
70 
blitH(int x,int y,int width)71 void SkARGB32_Blitter::blitH(int x, int y, int width) {
72     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
73 
74     uint32_t*   device = fDevice.getAddr32(x, y);
75     fColor32Proc(device, device, width, fPMColor);
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, SkAlpha255To256(aa));
100                 fColor32Proc(device, device, count, sc);
101             }
102         }
103         runs += count;
104         antialias += count;
105         device += count;
106     }
107 }
108 
109 //////////////////////////////////////////////////////////////////////////////////////
110 
111 #define solid_8_pixels(mask, dst, color)    \
112     do {                                    \
113         if (mask & 0x80) dst[0] = color;    \
114         if (mask & 0x40) dst[1] = color;    \
115         if (mask & 0x20) dst[2] = color;    \
116         if (mask & 0x10) dst[3] = color;    \
117         if (mask & 0x08) dst[4] = color;    \
118         if (mask & 0x04) dst[5] = color;    \
119         if (mask & 0x02) dst[6] = color;    \
120         if (mask & 0x01) dst[7] = color;    \
121     } while (0)
122 
123 #define SK_BLITBWMASK_NAME                  SkARGB32_BlitBW
124 #define SK_BLITBWMASK_ARGS                  , SkPMColor color
125 #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
126 #define SK_BLITBWMASK_GETADDR               getAddr32
127 #define SK_BLITBWMASK_DEVTYPE               uint32_t
128 #include "SkBlitBWMaskTemplate.h"
129 
130 #define blend_8_pixels(mask, dst, sc, dst_scale)                            \
131     do {                                                                    \
132         if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); }  \
133         if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); }  \
134         if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); }  \
135         if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); }  \
136         if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); }  \
137         if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); }  \
138         if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); }  \
139         if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); }  \
140     } while (0)
141 
142 #define SK_BLITBWMASK_NAME                  SkARGB32_BlendBW
143 #define SK_BLITBWMASK_ARGS                  , uint32_t sc, unsigned dst_scale
144 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
145 #define SK_BLITBWMASK_GETADDR               getAddr32
146 #define SK_BLITBWMASK_DEVTYPE               uint32_t
147 #include "SkBlitBWMaskTemplate.h"
148 
blitMask(const SkMask & mask,const SkIRect & clip)149 void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
150     SkASSERT(mask.fBounds.contains(clip));
151     SkASSERT(fSrcA != 0xFF);
152 
153     if (fSrcA == 0) {
154         return;
155     }
156 
157     if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
158         return;
159     }
160 
161     if (mask.fFormat == SkMask::kBW_Format) {
162         SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
163     } else if (SkMask::kARGB32_Format == mask.fFormat) {
164 		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
165     }
166 }
167 
blitMask(const SkMask & mask,const SkIRect & clip)168 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
169                                        const SkIRect& clip) {
170     SkASSERT(mask.fBounds.contains(clip));
171 
172     if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
173         return;
174     }
175 
176     if (mask.fFormat == SkMask::kBW_Format) {
177         SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
178     } else if (SkMask::kARGB32_Format == mask.fFormat) {
179 		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
180 	}
181 }
182 
183 ///////////////////////////////////////////////////////////////////////////////
184 
blitV(int x,int y,int height,SkAlpha alpha)185 void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
186     if (alpha == 0 || fSrcA == 0) {
187         return;
188     }
189 
190     uint32_t* device = fDevice.getAddr32(x, y);
191     uint32_t  color = fPMColor;
192 
193     if (alpha != 255) {
194         color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
195     }
196 
197     unsigned dst_scale = 255 - SkGetPackedA32(color);
198     uint32_t rowBytes = fDevice.rowBytes();
199     while (--height >= 0) {
200         device[0] = color + SkAlphaMulQ(device[0], dst_scale);
201         device = (uint32_t*)((char*)device + rowBytes);
202     }
203 }
204 
blitRect(int x,int y,int width,int height)205 void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
206     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
207 
208     if (fSrcA == 0) {
209         return;
210     }
211 
212     uint32_t*   device = fDevice.getAddr32(x, y);
213     uint32_t    color = fPMColor;
214     size_t      rowBytes = fDevice.rowBytes();
215 
216     while (--height >= 0) {
217         fColor32Proc(device, device, width, color);
218         device = (uint32_t*)((char*)device + rowBytes);
219     }
220 }
221 
222 #if defined _WIN32 && _MSC_VER >= 1300
223 #pragma warning ( pop )
224 #endif
225 
226 ///////////////////////////////////////////////////////////////////////
227 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])228 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
229                                        const int16_t runs[]) {
230     uint32_t*   device = fDevice.getAddr32(x, y);
231     SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
232 
233     for (;;) {
234         int count = runs[0];
235         SkASSERT(count >= 0);
236         if (count <= 0) {
237             return;
238         }
239         unsigned aa = antialias[0];
240         if (aa) {
241             if (aa == 255) {
242                 sk_memset32(device, black, count);
243             } else {
244                 SkPMColor src = aa << SK_A32_SHIFT;
245                 unsigned dst_scale = 256 - aa;
246                 int n = count;
247                 do {
248                     --n;
249                     device[n] = src + SkAlphaMulQ(device[n], dst_scale);
250                 } while (n > 0);
251             }
252         }
253         runs += count;
254         antialias += count;
255         device += count;
256     }
257 }
258 
259 ///////////////////////////////////////////////////////////////////////////////
260 
SkARGB32_Shader_Blitter(const SkBitmap & device,const SkPaint & paint)261 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
262                             const SkPaint& paint) : INHERITED(device, paint) {
263     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
264 
265     fXfermode = paint.getXfermode();
266     SkSafeRef(fXfermode);
267 
268     int flags = 0;
269     if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
270         flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
271     }
272     // we call this on the output from the shader
273     fProc32 = SkBlitRow::Factory32(flags);
274     // we call this on the output from the shader + alpha from the aa buffer
275     fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
276 }
277 
~SkARGB32_Shader_Blitter()278 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
279     SkSafeUnref(fXfermode);
280     sk_free(fBuffer);
281 }
282 
blitH(int x,int y,int width)283 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
284     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
285 
286     uint32_t*   device = fDevice.getAddr32(x, y);
287 
288     if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
289         fShader->shadeSpan(x, y, device, width);
290     } else {
291         SkPMColor*  span = fBuffer;
292         fShader->shadeSpan(x, y, span, width);
293         if (fXfermode) {
294             fXfermode->xfer32(device, span, width, NULL);
295         } else {
296             fProc32(device, span, width, 255);
297         }
298     }
299 }
300 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])301 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
302                                         const int16_t runs[]) {
303     SkPMColor*  span = fBuffer;
304     uint32_t*   device = fDevice.getAddr32(x, y);
305     SkShader*   shader = fShader;
306 
307     if (fXfermode) {
308         for (;;) {
309             SkXfermode* xfer = fXfermode;
310 
311             int count = *runs;
312             if (count <= 0)
313                 break;
314             int aa = *antialias;
315             if (aa) {
316                 shader->shadeSpan(x, y, span, count);
317                 if (aa == 255) {
318                     xfer->xfer32(device, span, count, NULL);
319                 } else {
320                     // count is almost always 1
321                     for (int i = count - 1; i >= 0; --i) {
322                         xfer->xfer32(&device[i], &span[i], 1, antialias);
323                     }
324                 }
325             }
326             device += count;
327             runs += count;
328             antialias += count;
329             x += count;
330         }
331     } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
332         for (;;) {
333             int count = *runs;
334             if (count <= 0) {
335                 break;
336             }
337             int aa = *antialias;
338             if (aa) {
339                 if (aa == 255) {
340                     // cool, have the shader draw right into the device
341                     shader->shadeSpan(x, y, device, count);
342                 } else {
343                     shader->shadeSpan(x, y, span, count);
344                     fProc32Blend(device, span, count, aa);
345                 }
346             }
347             device += count;
348             runs += count;
349             antialias += count;
350             x += count;
351         }
352     } else {    // no xfermode but the shader not opaque
353         for (;;) {
354             int count = *runs;
355             if (count <= 0) {
356                 break;
357             }
358             int aa = *antialias;
359             if (aa) {
360                 fShader->shadeSpan(x, y, span, count);
361                 if (aa == 255) {
362                     fProc32(device, span, count, 255);
363                 } else {
364                     fProc32Blend(device, span, count, aa);
365                 }
366             }
367             device += count;
368             runs += count;
369             antialias += count;
370             x += count;
371         }
372     }
373 }
374 
blitMask(const SkMask & mask,const SkIRect & clip)375 void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
376     // we only handle kA8 with an xfermode
377     if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
378         this->INHERITED::blitMask(mask, clip);
379         return;
380     }
381 
382     SkASSERT(mask.fBounds.contains(clip));
383 
384     SkBlitMask::RowProc proc = NULL;
385     if (!fXfermode) {
386         unsigned flags = 0;
387         if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
388             flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
389         }
390         proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat,
391                                       (SkBlitMask::RowFlags)flags);
392         if (NULL == proc) {
393             this->INHERITED::blitMask(mask, clip);
394             return;
395         }
396     }
397 
398     const int x = clip.fLeft;
399     const int width = clip.width();
400     int y = clip.fTop;
401     int height = clip.height();
402 
403     char* dstRow = (char*)fDevice.getAddr32(x, y);
404     const size_t dstRB = fDevice.rowBytes();
405     const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
406     const size_t maskRB = mask.fRowBytes;
407 
408     SkShader* shader = fShader;
409     SkPMColor* span = fBuffer;
410 
411     if (fXfermode) {
412         SkASSERT(SkMask::kA8_Format == mask.fFormat);
413         SkXfermode* xfer = fXfermode;
414         do {
415             shader->shadeSpan(x, y, span, width);
416             xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
417             dstRow += dstRB;
418             maskRow += maskRB;
419             y += 1;
420         } while (--height > 0);
421     } else {
422         do {
423             shader->shadeSpan(x, y, span, width);
424             proc(dstRow, maskRow, span, width);
425             dstRow += dstRB;
426             maskRow += maskRB;
427             y += 1;
428         } while (--height > 0);
429     }
430 }
431 
432