blob: f86bc47074b50f884c37ef98583041af8525529f [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkCoreBlitters.h"
9#include "SkColorPriv.h"
10#include "SkShader.h"
11#include "SkUtils.h"
12#include "SkXfermode.h"
reed@google.com58af9a62011-10-12 13:43:52 +000013#include "SkBlitMask.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014
reed@google.comf88d6762011-03-10 15:06:27 +000015///////////////////////////////////////////////////////////////////////////////
16
reed@android.comf2b98d62010-12-20 18:26:13 +000017static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
rmistry@google.comfbfcd562012-08-23 18:09:54 +000018 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);
reed@android.comf2b98d62010-12-20 18:26:13 +000025
26 int x = clip.fLeft;
27 int y = clip.fTop;
28 int width = clip.width();
29 int height = clip.height();
reed@google.com82065d62011-02-07 15:30:46 +000030
rmistry@google.comfbfcd562012-08-23 18:09:54 +000031 SkPMColor* dstRow = device.getAddr32(x, y);
reed@google.com79891862011-10-18 15:44:57 +000032 const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
reed@android.comf2b98d62010-12-20 18:26:13 +000033
34 do {
rmistry@google.comfbfcd562012-08-23 18:09:54 +000035 proc(dstRow, srcRow, width, alpha);
reed@android.comf2b98d62010-12-20 18:26:13 +000036 dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
37 srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
38 } while (--height != 0);
39}
40
41//////////////////////////////////////////////////////////////////////////////////////
42
reed@android.com8a1c16f2008-12-17 15:59:43 +000043SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
44 : INHERITED(device) {
reed@google.comee467ee2011-03-09 13:23:57 +000045 SkColor color = paint.getColor();
46 fColor = color;
reed@android.com8a1c16f2008-12-17 15:59:43 +000047
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);
senorblanco@chromium.org29e50542010-12-16 19:07:45 +000055 fColor32Proc = SkBlitRow::ColorProcFactory();
tomhudson@google.com8dd90a92012-03-19 13:49:50 +000056 fColorRect32Proc = SkBlitRow::ColorRectProcFactory();
reed@android.com8a1c16f2008-12-17 15:59:43 +000057}
58
59const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
60 if (255 == fSrcA) {
61 *value = fPMColor;
62 return &fDevice;
63 }
64 return NULL;
65}
66
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 )
70#endif
71
72void SkARGB32_Blitter::blitH(int x, int y, int width) {
73 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
74
senorblanco@chromium.org29e50542010-12-16 19:07:45 +000075 uint32_t* device = fDevice.getAddr32(x, y);
76 fColor32Proc(device, device, width, fPMColor);
reed@android.com8a1c16f2008-12-17 15:59:43 +000077}
78
79void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
80 const int16_t runs[]) {
81 if (fSrcA == 0) {
82 return;
83 }
84
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
88
89 for (;;) {
90 int count = runs[0];
91 SkASSERT(count >= 0);
92 if (count <= 0) {
93 return;
94 }
95 unsigned aa = antialias[0];
96 if (aa) {
97 if ((opaqueMask & aa) == 255) {
98 sk_memset32(device, color, count);
99 } else {
reed@android.comc4cae852009-09-23 15:06:10 +0000100 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000101 fColor32Proc(device, device, count, sc);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102 }
103 }
104 runs += count;
105 antialias += count;
106 device += count;
107 }
108}
109
110//////////////////////////////////////////////////////////////////////////////////////
111
112#define solid_8_pixels(mask, dst, color) \
113 do { \
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; \
122 } while (0)
123
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"
130
131#define blend_8_pixels(mask, dst, sc, dst_scale) \
132 do { \
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); } \
141 } while (0)
142
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"
149
150void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
151 SkASSERT(mask.fBounds.contains(clip));
152 SkASSERT(fSrcA != 0xFF);
153
154 if (fSrcA == 0) {
155 return;
156 }
157
reed@google.comedb606c2011-10-18 13:56:50 +0000158 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
caryclark@google.com1eeaf0b2011-06-22 13:19:43 +0000159 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 }
161
reed@google.comedb606c2011-10-18 13:56:50 +0000162 if (mask.fFormat == SkMask::kBW_Format) {
163 SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
164 } else if (SkMask::kARGB32_Format == mask.fFormat) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000165 SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
reed@google.comedb606c2011-10-18 13:56:50 +0000166 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000167}
168
169void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
170 const SkIRect& clip) {
171 SkASSERT(mask.fBounds.contains(clip));
172
reed@google.comedb606c2011-10-18 13:56:50 +0000173 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
174 return;
175 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000176
reed@android.com8a1c16f2008-12-17 15:59:43 +0000177 if (mask.fFormat == SkMask::kBW_Format) {
178 SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
reed@android.comf2b98d62010-12-20 18:26:13 +0000179 } else if (SkMask::kARGB32_Format == mask.fFormat) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000180 SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
181 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000182}
183
reed@google.com67cdbf52011-10-25 20:47:10 +0000184///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185
186void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
187 if (alpha == 0 || fSrcA == 0) {
188 return;
189 }
190
191 uint32_t* device = fDevice.getAddr32(x, y);
192 uint32_t color = fPMColor;
193
194 if (alpha != 255) {
195 color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
196 }
197
198 unsigned dst_scale = 255 - SkGetPackedA32(color);
scroggo@google.come5f48242013-02-25 21:47:41 +0000199 size_t rowBytes = fDevice.rowBytes();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200 while (--height >= 0) {
reed@google.com67cdbf52011-10-25 20:47:10 +0000201 device[0] = color + SkAlphaMulQ(device[0], dst_scale);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000202 device = (uint32_t*)((char*)device + rowBytes);
203 }
204}
205
206void 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());
208
209 if (fSrcA == 0) {
210 return;
211 }
212
213 uint32_t* device = fDevice.getAddr32(x, y);
214 uint32_t color = fPMColor;
reed@android.comc4cae852009-09-23 15:06:10 +0000215 size_t rowBytes = fDevice.rowBytes();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216
tomhudson@google.com57e080c2012-03-19 15:27:13 +0000217 if (255 == SkGetPackedA32(color)) {
tomhudson@google.com8dd90a92012-03-19 13:49:50 +0000218 fColorRect32Proc(device, width, height, rowBytes, color);
tomhudson@google.com57e080c2012-03-19 15:27:13 +0000219 } else {
220 while (--height >= 0) {
221 fColor32Proc(device, device, width, color);
222 device = (uint32_t*)((char*)device + rowBytes);
223 }
224 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000225}
226
227#if defined _WIN32 && _MSC_VER >= 1300
228#pragma warning ( pop )
229#endif
230
231///////////////////////////////////////////////////////////////////////
232
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233void 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);
237
238 for (;;) {
239 int count = runs[0];
240 SkASSERT(count >= 0);
241 if (count <= 0) {
242 return;
243 }
244 unsigned aa = antialias[0];
245 if (aa) {
246 if (aa == 255) {
247 sk_memset32(device, black, count);
248 } else {
249 SkPMColor src = aa << SK_A32_SHIFT;
250 unsigned dst_scale = 256 - aa;
251 int n = count;
252 do {
253 --n;
254 device[n] = src + SkAlphaMulQ(device[n], dst_scale);
255 } while (n > 0);
256 }
257 }
258 runs += count;
259 antialias += count;
260 device += count;
261 }
262}
263
reed@google.com1750bf12011-11-15 19:51:02 +0000264///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000265
reed@google.com13201e72012-11-16 13:20:41 +0000266// Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
267// instead of kSrcOver_Mode
268static 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);
274 }
275}
reed@google.com13201e72012-11-16 13:20:41 +0000276
reed@android.com8a1c16f2008-12-17 15:59:43 +0000277SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000278 const SkPaint& paint, SkShader::Context* shaderContext)
279 : INHERITED(device, paint, shaderContext)
280{
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
282
reed@android.comc4cae852009-09-23 15:06:10 +0000283 fXfermode = paint.getXfermode();
284 SkSafeRef(fXfermode);
285
286 int flags = 0;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000287 if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
reed@android.comc4cae852009-09-23 15:06:10 +0000288 flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
289 }
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);
reed@google.com13201e72012-11-16 13:20:41 +0000294
295 fShadeDirectlyIntoDevice = false;
296 if (fXfermode == NULL) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000297 if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
reed@google.com13201e72012-11-16 13:20:41 +0000298 fShadeDirectlyIntoDevice = true;
299 }
300 } else {
reed@google.com13201e72012-11-16 13:20:41 +0000301 SkXfermode::Mode mode;
302 if (fXfermode->asMode(&mode)) {
303 if (SkXfermode::kSrc_Mode == mode) {
304 fShadeDirectlyIntoDevice = true;
305 fProc32Blend = blend_srcmode;
306 }
307 }
reed@google.com13201e72012-11-16 13:20:41 +0000308 }
309
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000310 fConstInY = SkToBool(shaderContext->getFlags() & SkShader::kConstInY32_Flag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000311}
312
313SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
reed@google.com82065d62011-02-07 15:30:46 +0000314 SkSafeUnref(fXfermode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000315 sk_free(fBuffer);
316}
317
318void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
319 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
320
321 uint32_t* device = fDevice.getAddr32(x, y);
322
reed@google.com13201e72012-11-16 13:20:41 +0000323 if (fShadeDirectlyIntoDevice) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000324 fShaderContext->shadeSpan(x, y, device, width);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000325 } else {
326 SkPMColor* span = fBuffer;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000327 fShaderContext->shadeSpan(x, y, span, width);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328 if (fXfermode) {
329 fXfermode->xfer32(device, span, width, NULL);
330 } else {
reed@android.comc4cae852009-09-23 15:06:10 +0000331 fProc32(device, span, width, 255);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000332 }
333 }
334}
335
reed@google.com3bafe742012-10-12 18:56:18 +0000336void 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());
skia.committer@gmail.comf57c01b2012-10-13 02:01:56 +0000339
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000340 uint32_t* device = fDevice.getAddr32(x, y);
341 size_t deviceRB = fDevice.rowBytes();
342 SkShader::Context* shaderContext = fShaderContext;
343 SkPMColor* span = fBuffer;
reed@google.com3bafe742012-10-12 18:56:18 +0000344
reed@google.com13201e72012-11-16 13:20:41 +0000345 if (fConstInY) {
346 if (fShadeDirectlyIntoDevice) {
347 // shade the first row directly into the device
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000348 shaderContext->shadeSpan(x, y, device, width);
reed@google.com13201e72012-11-16 13:20:41 +0000349 span = device;
350 while (--height > 0) {
351 device = (uint32_t*)((char*)device + deviceRB);
352 memcpy(device, span, width << 2);
353 }
354 } else {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000355 shaderContext->shadeSpan(x, y, span, width);
reed@google.com13201e72012-11-16 13:20:41 +0000356 SkXfermode* xfer = fXfermode;
357 if (xfer) {
358 do {
359 xfer->xfer32(device, span, width, NULL);
360 y += 1;
361 device = (uint32_t*)((char*)device + deviceRB);
362 } while (--height > 0);
363 } else {
364 SkBlitRow::Proc32 proc = fProc32;
365 do {
366 proc(device, span, width, 255);
367 y += 1;
368 device = (uint32_t*)((char*)device + deviceRB);
369 } while (--height > 0);
370 }
371 }
372 return;
373 }
374
375 if (fShadeDirectlyIntoDevice) {
reed@google.com3bafe742012-10-12 18:56:18 +0000376 void* ctx;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000377 SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
reed@google.com3bafe742012-10-12 18:56:18 +0000378 if (shadeProc) {
379 do {
380 shadeProc(ctx, x, y, device, width);
381 y += 1;
382 device = (uint32_t*)((char*)device + deviceRB);
383 } while (--height > 0);
384 } else {
385 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000386 shaderContext->shadeSpan(x, y, device, width);
reed@google.com3bafe742012-10-12 18:56:18 +0000387 y += 1;
388 device = (uint32_t*)((char*)device + deviceRB);
389 } while (--height > 0);
390 }
391 } else {
reed@google.com3bafe742012-10-12 18:56:18 +0000392 SkXfermode* xfer = fXfermode;
393 if (xfer) {
394 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000395 shaderContext->shadeSpan(x, y, span, width);
reed@google.com3bafe742012-10-12 18:56:18 +0000396 xfer->xfer32(device, span, width, NULL);
397 y += 1;
398 device = (uint32_t*)((char*)device + deviceRB);
399 } while (--height > 0);
400 } else {
401 SkBlitRow::Proc32 proc = fProc32;
402 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000403 shaderContext->shadeSpan(x, y, span, width);
reed@google.com3bafe742012-10-12 18:56:18 +0000404 proc(device, span, width, 255);
405 y += 1;
406 device = (uint32_t*)((char*)device + deviceRB);
407 } while (--height > 0);
408 }
409 }
410}
411
reed@android.com8a1c16f2008-12-17 15:59:43 +0000412void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
413 const int16_t runs[]) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000414 SkPMColor* span = fBuffer;
415 uint32_t* device = fDevice.getAddr32(x, y);
416 SkShader::Context* shaderContext = fShaderContext;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000417
reed@google.com13201e72012-11-16 13:20:41 +0000418 if (fXfermode && !fShadeDirectlyIntoDevice) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419 for (;;) {
420 SkXfermode* xfer = fXfermode;
421
422 int count = *runs;
423 if (count <= 0)
424 break;
425 int aa = *antialias;
426 if (aa) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000427 shaderContext->shadeSpan(x, y, span, count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428 if (aa == 255) {
429 xfer->xfer32(device, span, count, NULL);
430 } else {
431 // count is almost always 1
432 for (int i = count - 1; i >= 0; --i) {
433 xfer->xfer32(&device[i], &span[i], 1, antialias);
434 }
435 }
436 }
437 device += count;
438 runs += count;
439 antialias += count;
440 x += count;
reed@google.com82065d62011-02-07 15:30:46 +0000441 }
reed@google.com13201e72012-11-16 13:20:41 +0000442 } else if (fShadeDirectlyIntoDevice ||
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000443 (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000444 for (;;) {
445 int count = *runs;
446 if (count <= 0) {
447 break;
448 }
449 int aa = *antialias;
450 if (aa) {
reed@android.comc4cae852009-09-23 15:06:10 +0000451 if (aa == 255) {
452 // cool, have the shader draw right into the device
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000453 shaderContext->shadeSpan(x, y, device, count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000454 } else {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000455 shaderContext->shadeSpan(x, y, span, count);
reed@android.comc4cae852009-09-23 15:06:10 +0000456 fProc32Blend(device, span, count, aa);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000457 }
458 }
459 device += count;
460 runs += count;
461 antialias += count;
462 x += count;
reed@google.com82065d62011-02-07 15:30:46 +0000463 }
reed@google.com13201e72012-11-16 13:20:41 +0000464 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465 for (;;) {
466 int count = *runs;
467 if (count <= 0) {
468 break;
469 }
470 int aa = *antialias;
471 if (aa) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000472 shaderContext->shadeSpan(x, y, span, count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000473 if (aa == 255) {
reed@android.comc4cae852009-09-23 15:06:10 +0000474 fProc32(device, span, count, 255);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475 } else {
reed@android.comc4cae852009-09-23 15:06:10 +0000476 fProc32Blend(device, span, count, aa);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000477 }
478 }
479 device += count;
480 runs += count;
481 antialias += count;
482 x += count;
reed@google.com82065d62011-02-07 15:30:46 +0000483 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000484 }
485}
reed@google.com1750bf12011-11-15 19:51:02 +0000486
487void 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);
491 return;
492 }
493
494 SkASSERT(mask.fBounds.contains(clip));
495
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000496 SkShader::Context* shaderContext = fShaderContext;
reed@google.com1750bf12011-11-15 19:51:02 +0000497 SkBlitMask::RowProc proc = NULL;
498 if (!fXfermode) {
499 unsigned flags = 0;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000500 if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
reed@google.com1750bf12011-11-15 19:51:02 +0000501 flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
502 }
commit-bot@chromium.orgcba73782014-05-29 15:57:47 +0000503 proc = SkBlitMask::RowFactory(kN32_SkColorType, mask.fFormat,
reed@google.com1750bf12011-11-15 19:51:02 +0000504 (SkBlitMask::RowFlags)flags);
505 if (NULL == proc) {
506 this->INHERITED::blitMask(mask, clip);
507 return;
508 }
509 }
510
511 const int x = clip.fLeft;
512 const int width = clip.width();
513 int y = clip.fTop;
514 int height = clip.height();
515
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;
520
reed@google.com1750bf12011-11-15 19:51:02 +0000521 SkPMColor* span = fBuffer;
522
523 if (fXfermode) {
524 SkASSERT(SkMask::kA8_Format == mask.fFormat);
525 SkXfermode* xfer = fXfermode;
526 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000527 shaderContext->shadeSpan(x, y, span, width);
reed@google.com1750bf12011-11-15 19:51:02 +0000528 xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
529 dstRow += dstRB;
530 maskRow += maskRB;
531 y += 1;
532 } while (--height > 0);
533 } else {
534 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000535 shaderContext->shadeSpan(x, y, span, width);
reed@google.com1750bf12011-11-15 19:51:02 +0000536 proc(dstRow, maskRow, span, width);
537 dstRow += dstRB;
538 maskRow += maskRB;
539 y += 1;
540 } while (--height > 0);
541 }
542}
543
reed@google.com13201e72012-11-16 13:20:41 +0000544void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
545 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
skia.committer@gmail.com886b25f2012-11-16 18:15:12 +0000546
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000547 uint32_t* device = fDevice.getAddr32(x, y);
548 size_t deviceRB = fDevice.rowBytes();
549 SkShader::Context* shaderContext = fShaderContext;
skia.committer@gmail.com886b25f2012-11-16 18:15:12 +0000550
reed@google.com13201e72012-11-16 13:20:41 +0000551 if (fConstInY) {
552 SkPMColor c;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000553 shaderContext->shadeSpan(x, y, &c, 1);
reed@google.com13201e72012-11-16 13:20:41 +0000554
555 if (fShadeDirectlyIntoDevice) {
556 if (255 == alpha) {
557 do {
558 *device = c;
559 device = (uint32_t*)((char*)device + deviceRB);
560 } while (--height > 0);
561 } else {
562 do {
563 *device = SkFourByteInterp(c, *device, alpha);
564 device = (uint32_t*)((char*)device + deviceRB);
565 } while (--height > 0);
566 }
567 } else {
568 SkXfermode* xfer = fXfermode;
569 if (xfer) {
570 do {
571 xfer->xfer32(device, &c, 1, &alpha);
572 device = (uint32_t*)((char*)device + deviceRB);
573 } while (--height > 0);
574 } else {
reed@google.com53007a22012-11-26 14:39:50 +0000575 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
reed@google.com13201e72012-11-16 13:20:41 +0000576 do {
577 proc(device, &c, 1, alpha);
578 device = (uint32_t*)((char*)device + deviceRB);
579 } while (--height > 0);
580 }
581 }
582 return;
583 }
584
585 if (fShadeDirectlyIntoDevice) {
586 void* ctx;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000587 SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
reed@google.com13201e72012-11-16 13:20:41 +0000588 if (255 == alpha) {
589 if (shadeProc) {
590 do {
591 shadeProc(ctx, x, y, device, 1);
592 y += 1;
593 device = (uint32_t*)((char*)device + deviceRB);
594 } while (--height > 0);
595 } else {
596 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000597 shaderContext->shadeSpan(x, y, device, 1);
reed@google.com13201e72012-11-16 13:20:41 +0000598 y += 1;
599 device = (uint32_t*)((char*)device + deviceRB);
600 } while (--height > 0);
601 }
602 } else { // alpha < 255
603 SkPMColor c;
604 if (shadeProc) {
605 do {
606 shadeProc(ctx, x, y, &c, 1);
607 *device = SkFourByteInterp(c, *device, alpha);
608 y += 1;
609 device = (uint32_t*)((char*)device + deviceRB);
610 } while (--height > 0);
611 } else {
612 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000613 shaderContext->shadeSpan(x, y, &c, 1);
reed@google.com13201e72012-11-16 13:20:41 +0000614 *device = SkFourByteInterp(c, *device, alpha);
615 y += 1;
616 device = (uint32_t*)((char*)device + deviceRB);
617 } while (--height > 0);
618 }
619 }
620 } else {
621 SkPMColor* span = fBuffer;
622 SkXfermode* xfer = fXfermode;
623 if (xfer) {
624 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000625 shaderContext->shadeSpan(x, y, span, 1);
reed@google.com13201e72012-11-16 13:20:41 +0000626 xfer->xfer32(device, span, 1, &alpha);
627 y += 1;
628 device = (uint32_t*)((char*)device + deviceRB);
629 } while (--height > 0);
630 } else {
reed@google.com59d968f2012-11-16 14:46:00 +0000631 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
reed@google.com13201e72012-11-16 13:20:41 +0000632 do {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000633 shaderContext->shadeSpan(x, y, span, 1);
reed@google.com59d968f2012-11-16 14:46:00 +0000634 proc(device, span, 1, alpha);
reed@google.com13201e72012-11-16 13:20:41 +0000635 y += 1;
636 device = (uint32_t*)((char*)device + deviceRB);
637 } while (--height > 0);
638 }
639 }
640}