2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkCoreBlitters.h"
9 #include "SkColorPriv.h"
12 #include "SkXfermode.h"
13 #include "SkBlitMask.h"
15 ///////////////////////////////////////////////////////////////////////////////
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;
22 flags |= SkBlitRow::kGlobalAlpha_Flag32;
24 SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
28 int width = clip.width();
29 int height = clip.height();
31 SkPMColor* dstRow = device.getAddr32(x, y);
32 const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
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);
41 //////////////////////////////////////////////////////////////////////////////////////
43 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
45 SkColor color = paint.getColor();
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);
54 fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
55 fColor32Proc = SkBlitRow::ColorProcFactory();
56 fColorRect32Proc = SkBlitRow::ColorRectProcFactory();
59 const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
67 #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized
68 #pragma warning ( push )
69 #pragma warning ( disable : 4701 )
72 void SkARGB32_Blitter::blitH(int x, int y, int width) {
73 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
75 uint32_t* device = fDevice.getAddr32(x, y);
76 fColor32Proc(device, device, width, fPMColor);
79 void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
80 const int16_t runs[]) {
85 uint32_t color = fPMColor;
86 uint32_t* device = fDevice.getAddr32(x, y);
87 unsigned opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
95 unsigned aa = antialias[0];
97 if ((opaqueMask & aa) == 255) {
98 sk_memset32(device, color, count);
100 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
101 fColor32Proc(device, device, count, sc);
110 //////////////////////////////////////////////////////////////////////////////////////
112 #define solid_8_pixels(mask, dst, color) \
114 if (mask & 0x80) dst[0] = color; \
115 if (mask & 0x40) dst[1] = color; \
116 if (mask & 0x20) dst[2] = color; \
117 if (mask & 0x10) dst[3] = color; \
118 if (mask & 0x08) dst[4] = color; \
119 if (mask & 0x04) dst[5] = color; \
120 if (mask & 0x02) dst[6] = color; \
121 if (mask & 0x01) dst[7] = color; \
124 #define SK_BLITBWMASK_NAME SkARGB32_BlitBW
125 #define SK_BLITBWMASK_ARGS , SkPMColor color
126 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
127 #define SK_BLITBWMASK_GETADDR getAddr32
128 #define SK_BLITBWMASK_DEVTYPE uint32_t
129 #include "SkBlitBWMaskTemplate.h"
131 #define blend_8_pixels(mask, dst, sc, dst_scale) \
133 if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); } \
134 if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); } \
135 if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); } \
136 if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); } \
137 if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); } \
138 if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); } \
139 if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); } \
140 if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); } \
143 #define SK_BLITBWMASK_NAME SkARGB32_BlendBW
144 #define SK_BLITBWMASK_ARGS , uint32_t sc, unsigned dst_scale
145 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale)
146 #define SK_BLITBWMASK_GETADDR getAddr32
147 #define SK_BLITBWMASK_DEVTYPE uint32_t
148 #include "SkBlitBWMaskTemplate.h"
150 void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
151 SkASSERT(mask.fBounds.contains(clip));
152 SkASSERT(fSrcA != 0xFF);
158 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
162 if (mask.fFormat == SkMask::kBW_Format) {
163 SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
164 } else if (SkMask::kARGB32_Format == mask.fFormat) {
165 SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
169 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
170 const SkIRect& clip) {
171 SkASSERT(mask.fBounds.contains(clip));
173 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
177 if (mask.fFormat == SkMask::kBW_Format) {
178 SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
179 } else if (SkMask::kARGB32_Format == mask.fFormat) {
180 SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
184 ///////////////////////////////////////////////////////////////////////////////
186 void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
187 if (alpha == 0 || fSrcA == 0) {
191 uint32_t* device = fDevice.getAddr32(x, y);
192 uint32_t color = fPMColor;
195 color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
198 unsigned dst_scale = 255 - SkGetPackedA32(color);
199 size_t rowBytes = fDevice.rowBytes();
200 while (--height >= 0) {
201 device[0] = color + SkAlphaMulQ(device[0], dst_scale);
202 device = (uint32_t*)((char*)device + rowBytes);
206 void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
207 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
213 uint32_t* device = fDevice.getAddr32(x, y);
214 uint32_t color = fPMColor;
215 size_t rowBytes = fDevice.rowBytes();
217 if (255 == SkGetPackedA32(color)) {
218 fColorRect32Proc(device, width, height, rowBytes, color);
220 while (--height >= 0) {
221 fColor32Proc(device, device, width, color);
222 device = (uint32_t*)((char*)device + rowBytes);
227 #if defined _WIN32 && _MSC_VER >= 1300
228 #pragma warning ( pop )
231 ///////////////////////////////////////////////////////////////////////
233 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
234 const int16_t runs[]) {
235 uint32_t* device = fDevice.getAddr32(x, y);
236 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
240 SkASSERT(count >= 0);
244 unsigned aa = antialias[0];
247 sk_memset32(device, black, count);
249 SkPMColor src = aa << SK_A32_SHIFT;
250 unsigned dst_scale = 256 - aa;
254 device[n] = src + SkAlphaMulQ(device[n], dst_scale);
264 ///////////////////////////////////////////////////////////////////////////////
266 // Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
267 // instead of kSrcOver_Mode
268 static void blend_srcmode(SkPMColor* SK_RESTRICT device,
269 const SkPMColor* SK_RESTRICT span,
270 int count, U8CPU aa) {
271 int aa256 = SkAlpha255To256(aa);
272 for (int i = 0; i < count; ++i) {
273 device[i] = SkFourByteInterp256(span[i], device[i], aa256);
277 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
278 const SkPaint& paint, SkShader::Context* shaderContext)
279 : INHERITED(device, paint, shaderContext)
281 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
283 fXfermode = paint.getXfermode();
284 SkSafeRef(fXfermode);
287 if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
288 flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
290 // we call this on the output from the shader
291 fProc32 = SkBlitRow::Factory32(flags);
292 // we call this on the output from the shader + alpha from the aa buffer
293 fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
295 fShadeDirectlyIntoDevice = false;
296 if (fXfermode == NULL) {
297 if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
298 fShadeDirectlyIntoDevice = true;
301 SkXfermode::Mode mode;
302 if (fXfermode->asMode(&mode)) {
303 if (SkXfermode::kSrc_Mode == mode) {
304 fShadeDirectlyIntoDevice = true;
305 fProc32Blend = blend_srcmode;
310 fConstInY = SkToBool(shaderContext->getFlags() & SkShader::kConstInY32_Flag);
313 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
314 SkSafeUnref(fXfermode);
318 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
319 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
321 uint32_t* device = fDevice.getAddr32(x, y);
323 if (fShadeDirectlyIntoDevice) {
324 fShaderContext->shadeSpan(x, y, device, width);
326 SkPMColor* span = fBuffer;
327 fShaderContext->shadeSpan(x, y, span, width);
329 fXfermode->xfer32(device, span, width, NULL);
331 fProc32(device, span, width, 255);
336 void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
337 SkASSERT(x >= 0 && y >= 0 &&
338 x + width <= fDevice.width() && y + height <= fDevice.height());
340 uint32_t* device = fDevice.getAddr32(x, y);
341 size_t deviceRB = fDevice.rowBytes();
342 SkShader::Context* shaderContext = fShaderContext;
343 SkPMColor* span = fBuffer;
346 if (fShadeDirectlyIntoDevice) {
347 // shade the first row directly into the device
348 shaderContext->shadeSpan(x, y, device, width);
350 while (--height > 0) {
351 device = (uint32_t*)((char*)device + deviceRB);
352 memcpy(device, span, width << 2);
355 shaderContext->shadeSpan(x, y, span, width);
356 SkXfermode* xfer = fXfermode;
359 xfer->xfer32(device, span, width, NULL);
361 device = (uint32_t*)((char*)device + deviceRB);
362 } while (--height > 0);
364 SkBlitRow::Proc32 proc = fProc32;
366 proc(device, span, width, 255);
368 device = (uint32_t*)((char*)device + deviceRB);
369 } while (--height > 0);
375 if (fShadeDirectlyIntoDevice) {
377 SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
380 shadeProc(ctx, x, y, device, width);
382 device = (uint32_t*)((char*)device + deviceRB);
383 } while (--height > 0);
386 shaderContext->shadeSpan(x, y, device, width);
388 device = (uint32_t*)((char*)device + deviceRB);
389 } while (--height > 0);
392 SkXfermode* xfer = fXfermode;
395 shaderContext->shadeSpan(x, y, span, width);
396 xfer->xfer32(device, span, width, NULL);
398 device = (uint32_t*)((char*)device + deviceRB);
399 } while (--height > 0);
401 SkBlitRow::Proc32 proc = fProc32;
403 shaderContext->shadeSpan(x, y, span, width);
404 proc(device, span, width, 255);
406 device = (uint32_t*)((char*)device + deviceRB);
407 } while (--height > 0);
412 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
413 const int16_t runs[]) {
414 SkPMColor* span = fBuffer;
415 uint32_t* device = fDevice.getAddr32(x, y);
416 SkShader::Context* shaderContext = fShaderContext;
418 if (fXfermode && !fShadeDirectlyIntoDevice) {
420 SkXfermode* xfer = fXfermode;
427 shaderContext->shadeSpan(x, y, span, count);
429 xfer->xfer32(device, span, count, NULL);
431 // count is almost always 1
432 for (int i = count - 1; i >= 0; --i) {
433 xfer->xfer32(&device[i], &span[i], 1, antialias);
442 } else if (fShadeDirectlyIntoDevice ||
443 (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
452 // cool, have the shader draw right into the device
453 shaderContext->shadeSpan(x, y, device, count);
455 shaderContext->shadeSpan(x, y, span, count);
456 fProc32Blend(device, span, count, aa);
472 shaderContext->shadeSpan(x, y, span, count);
474 fProc32(device, span, count, 255);
476 fProc32Blend(device, span, count, aa);
487 void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
488 // we only handle kA8 with an xfermode
489 if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
490 this->INHERITED::blitMask(mask, clip);
494 SkASSERT(mask.fBounds.contains(clip));
496 SkShader::Context* shaderContext = fShaderContext;
497 SkBlitMask::RowProc proc = NULL;
500 if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
501 flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
503 proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat,
504 (SkBlitMask::RowFlags)flags);
506 this->INHERITED::blitMask(mask, clip);
511 const int x = clip.fLeft;
512 const int width = clip.width();
514 int height = clip.height();
516 char* dstRow = (char*)fDevice.getAddr32(x, y);
517 const size_t dstRB = fDevice.rowBytes();
518 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
519 const size_t maskRB = mask.fRowBytes;
521 SkPMColor* span = fBuffer;
524 SkASSERT(SkMask::kA8_Format == mask.fFormat);
525 SkXfermode* xfer = fXfermode;
527 shaderContext->shadeSpan(x, y, span, width);
528 xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
532 } while (--height > 0);
535 shaderContext->shadeSpan(x, y, span, width);
536 proc(dstRow, maskRow, span, width);
540 } while (--height > 0);
544 void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
545 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
547 uint32_t* device = fDevice.getAddr32(x, y);
548 size_t deviceRB = fDevice.rowBytes();
549 SkShader::Context* shaderContext = fShaderContext;
553 shaderContext->shadeSpan(x, y, &c, 1);
555 if (fShadeDirectlyIntoDevice) {
559 device = (uint32_t*)((char*)device + deviceRB);
560 } while (--height > 0);
563 *device = SkFourByteInterp(c, *device, alpha);
564 device = (uint32_t*)((char*)device + deviceRB);
565 } while (--height > 0);
568 SkXfermode* xfer = fXfermode;
571 xfer->xfer32(device, &c, 1, &alpha);
572 device = (uint32_t*)((char*)device + deviceRB);
573 } while (--height > 0);
575 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
577 proc(device, &c, 1, alpha);
578 device = (uint32_t*)((char*)device + deviceRB);
579 } while (--height > 0);
585 if (fShadeDirectlyIntoDevice) {
587 SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
591 shadeProc(ctx, x, y, device, 1);
593 device = (uint32_t*)((char*)device + deviceRB);
594 } while (--height > 0);
597 shaderContext->shadeSpan(x, y, device, 1);
599 device = (uint32_t*)((char*)device + deviceRB);
600 } while (--height > 0);
602 } else { // alpha < 255
606 shadeProc(ctx, x, y, &c, 1);
607 *device = SkFourByteInterp(c, *device, alpha);
609 device = (uint32_t*)((char*)device + deviceRB);
610 } while (--height > 0);
613 shaderContext->shadeSpan(x, y, &c, 1);
614 *device = SkFourByteInterp(c, *device, alpha);
616 device = (uint32_t*)((char*)device + deviceRB);
617 } while (--height > 0);
621 SkPMColor* span = fBuffer;
622 SkXfermode* xfer = fXfermode;
625 shaderContext->shadeSpan(x, y, span, 1);
626 xfer->xfer32(device, span, 1, &alpha);
628 device = (uint32_t*)((char*)device + deviceRB);
629 } while (--height > 0);
631 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
633 shaderContext->shadeSpan(x, y, span, 1);
634 proc(device, span, 1, alpha);
636 device = (uint32_t*)((char*)device + deviceRB);
637 } while (--height > 0);