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