Line data Source code
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 "SkXfermodePriv.h"
13 : #include "SkBlitMask.h"
14 :
15 : ///////////////////////////////////////////////////////////////////////////////
16 :
17 0 : static void SkARGB32_Blit32(const SkPixmap& device, const SkMask& mask,
18 : const SkIRect& clip, SkPMColor srcColor) {
19 0 : U8CPU alpha = SkGetPackedA32(srcColor);
20 0 : unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
21 0 : if (alpha != 255) {
22 0 : flags |= SkBlitRow::kGlobalAlpha_Flag32;
23 : }
24 0 : SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
25 :
26 0 : int x = clip.fLeft;
27 0 : int y = clip.fTop;
28 0 : int width = clip.width();
29 0 : int height = clip.height();
30 :
31 0 : SkPMColor* dstRow = device.writable_addr32(x, y);
32 0 : const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
33 :
34 0 : do {
35 0 : proc(dstRow, srcRow, width, alpha);
36 0 : dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
37 0 : srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
38 : } while (--height != 0);
39 0 : }
40 :
41 : //////////////////////////////////////////////////////////////////////////////////////
42 :
43 144 : SkARGB32_Blitter::SkARGB32_Blitter(const SkPixmap& device, const SkPaint& paint)
44 144 : : INHERITED(device) {
45 144 : SkColor color = paint.getColor();
46 144 : fColor = color;
47 :
48 144 : fSrcA = SkColorGetA(color);
49 144 : unsigned scale = SkAlpha255To256(fSrcA);
50 144 : fSrcR = SkAlphaMul(SkColorGetR(color), scale);
51 144 : fSrcG = SkAlphaMul(SkColorGetG(color), scale);
52 144 : fSrcB = SkAlphaMul(SkColorGetB(color), scale);
53 :
54 144 : fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
55 144 : }
56 :
57 0 : const SkPixmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
58 0 : if (255 == fSrcA) {
59 0 : *value = fPMColor;
60 0 : return &fDevice;
61 : }
62 0 : return nullptr;
63 : }
64 :
65 : #if defined _WIN32 // disable warning : local variable used without having been initialized
66 : #pragma warning ( push )
67 : #pragma warning ( disable : 4701 )
68 : #endif
69 :
70 514 : void SkARGB32_Blitter::blitH(int x, int y, int width) {
71 514 : SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
72 :
73 514 : uint32_t* device = fDevice.writable_addr32(x, y);
74 514 : SkBlitRow::Color32(device, device, width, fPMColor);
75 514 : }
76 :
77 2156 : void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
78 : const int16_t runs[]) {
79 2156 : if (fSrcA == 0) {
80 0 : return;
81 : }
82 :
83 2156 : uint32_t color = fPMColor;
84 2156 : uint32_t* device = fDevice.writable_addr32(x, y);
85 2156 : unsigned opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
86 :
87 : for (;;) {
88 19369 : int count = runs[0];
89 19369 : SkASSERT(count >= 0);
90 19369 : if (count <= 0) {
91 2156 : return;
92 : }
93 17213 : unsigned aa = antialias[0];
94 17213 : if (aa) {
95 11261 : if ((opaqueMask & aa) == 255) {
96 6521 : sk_memset32(device, color, count);
97 : } else {
98 9480 : uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
99 4740 : SkBlitRow::Color32(device, device, count, sc);
100 : }
101 : }
102 17213 : runs += count;
103 17213 : antialias += count;
104 17213 : device += count;
105 17213 : }
106 : }
107 :
108 0 : void SkARGB32_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
109 0 : uint32_t* device = fDevice.writable_addr32(x, y);
110 0 : SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);)
111 :
112 0 : device[0] = SkBlendARGB32(fPMColor, device[0], a0);
113 0 : device[1] = SkBlendARGB32(fPMColor, device[1], a1);
114 0 : }
115 :
116 0 : void SkARGB32_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
117 0 : uint32_t* device = fDevice.writable_addr32(x, y);
118 0 : SkDEBUGCODE((void)fDevice.writable_addr32(x, y + 1);)
119 :
120 0 : device[0] = SkBlendARGB32(fPMColor, device[0], a0);
121 0 : device = (uint32_t*)((char*)device + fDevice.rowBytes());
122 0 : device[0] = SkBlendARGB32(fPMColor, device[0], a1);
123 0 : }
124 :
125 : //////////////////////////////////////////////////////////////////////////////////////
126 :
127 : #define solid_8_pixels(mask, dst, color) \
128 : do { \
129 : if (mask & 0x80) dst[0] = color; \
130 : if (mask & 0x40) dst[1] = color; \
131 : if (mask & 0x20) dst[2] = color; \
132 : if (mask & 0x10) dst[3] = color; \
133 : if (mask & 0x08) dst[4] = color; \
134 : if (mask & 0x04) dst[5] = color; \
135 : if (mask & 0x02) dst[6] = color; \
136 : if (mask & 0x01) dst[7] = color; \
137 : } while (0)
138 :
139 : #define SK_BLITBWMASK_NAME SkARGB32_BlitBW
140 : #define SK_BLITBWMASK_ARGS , SkPMColor color
141 : #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
142 : #define SK_BLITBWMASK_GETADDR writable_addr32
143 : #define SK_BLITBWMASK_DEVTYPE uint32_t
144 : #include "SkBlitBWMaskTemplate.h"
145 :
146 : #define blend_8_pixels(mask, dst, sc, dst_scale) \
147 : do { \
148 : if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); } \
149 : if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); } \
150 : if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); } \
151 : if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); } \
152 : if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); } \
153 : if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); } \
154 : if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); } \
155 : if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); } \
156 : } while (0)
157 :
158 : #define SK_BLITBWMASK_NAME SkARGB32_BlendBW
159 : #define SK_BLITBWMASK_ARGS , uint32_t sc, unsigned dst_scale
160 : #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale)
161 : #define SK_BLITBWMASK_GETADDR writable_addr32
162 : #define SK_BLITBWMASK_DEVTYPE uint32_t
163 : #include "SkBlitBWMaskTemplate.h"
164 :
165 114 : void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
166 114 : SkASSERT(mask.fBounds.contains(clip));
167 114 : SkASSERT(fSrcA != 0xFF);
168 :
169 114 : if (fSrcA == 0) {
170 0 : return;
171 : }
172 :
173 114 : if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
174 114 : return;
175 : }
176 :
177 0 : switch (mask.fFormat) {
178 : case SkMask::kBW_Format:
179 0 : SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
180 0 : break;
181 : case SkMask::kARGB32_Format:
182 0 : SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
183 0 : break;
184 : default:
185 0 : SkFAIL("Mask format not handled.");
186 : }
187 : }
188 :
189 339 : void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
190 : const SkIRect& clip) {
191 339 : SkASSERT(mask.fBounds.contains(clip));
192 :
193 339 : if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
194 339 : return;
195 : }
196 :
197 0 : switch (mask.fFormat) {
198 : case SkMask::kBW_Format:
199 0 : SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
200 0 : break;
201 : case SkMask::kARGB32_Format:
202 0 : SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
203 0 : break;
204 : default:
205 0 : SkFAIL("Mask format not handled.");
206 : }
207 : }
208 :
209 0 : void SkARGB32_Opaque_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
210 0 : uint32_t* device = fDevice.writable_addr32(x, y);
211 0 : SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);)
212 :
213 0 : device[0] = SkFastFourByteInterp(fPMColor, device[0], a0);
214 0 : device[1] = SkFastFourByteInterp(fPMColor, device[1], a1);
215 0 : }
216 :
217 0 : void SkARGB32_Opaque_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
218 0 : uint32_t* device = fDevice.writable_addr32(x, y);
219 0 : SkDEBUGCODE((void)fDevice.writable_addr32(x, y + 1);)
220 :
221 0 : device[0] = SkFastFourByteInterp(fPMColor, device[0], a0);
222 0 : device = (uint32_t*)((char*)device + fDevice.rowBytes());
223 0 : device[0] = SkFastFourByteInterp(fPMColor, device[0], a1);
224 0 : }
225 :
226 : ///////////////////////////////////////////////////////////////////////////////
227 :
228 0 : void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
229 0 : if (alpha == 0 || fSrcA == 0) {
230 0 : return;
231 : }
232 :
233 0 : uint32_t* device = fDevice.writable_addr32(x, y);
234 0 : uint32_t color = fPMColor;
235 :
236 0 : if (alpha != 255) {
237 0 : color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
238 : }
239 :
240 0 : unsigned dst_scale = SkAlpha255To256(255 - SkGetPackedA32(color));
241 0 : size_t rowBytes = fDevice.rowBytes();
242 0 : while (--height >= 0) {
243 0 : device[0] = color + SkAlphaMulQ(device[0], dst_scale);
244 0 : device = (uint32_t*)((char*)device + rowBytes);
245 : }
246 : }
247 :
248 32 : void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
249 32 : SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
250 :
251 32 : if (fSrcA == 0) {
252 0 : return;
253 : }
254 :
255 32 : uint32_t* device = fDevice.writable_addr32(x, y);
256 32 : uint32_t color = fPMColor;
257 32 : size_t rowBytes = fDevice.rowBytes();
258 :
259 12940 : while (--height >= 0) {
260 6454 : SkBlitRow::Color32(device, device, width, color);
261 6454 : device = (uint32_t*)((char*)device + rowBytes);
262 : }
263 : }
264 :
265 : #if defined _WIN32
266 : #pragma warning ( pop )
267 : #endif
268 :
269 : ///////////////////////////////////////////////////////////////////////
270 :
271 0 : void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
272 : const int16_t runs[]) {
273 0 : uint32_t* device = fDevice.writable_addr32(x, y);
274 0 : SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
275 :
276 : for (;;) {
277 0 : int count = runs[0];
278 0 : SkASSERT(count >= 0);
279 0 : if (count <= 0) {
280 0 : return;
281 : }
282 0 : unsigned aa = antialias[0];
283 0 : if (aa) {
284 0 : if (aa == 255) {
285 0 : sk_memset32(device, black, count);
286 : } else {
287 0 : SkPMColor src = aa << SK_A32_SHIFT;
288 0 : unsigned dst_scale = 256 - aa;
289 0 : int n = count;
290 0 : do {
291 0 : --n;
292 0 : device[n] = src + SkAlphaMulQ(device[n], dst_scale);
293 0 : } while (n > 0);
294 : }
295 : }
296 0 : runs += count;
297 0 : antialias += count;
298 0 : device += count;
299 0 : }
300 : }
301 :
302 0 : void SkARGB32_Black_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
303 0 : uint32_t* device = fDevice.writable_addr32(x, y);
304 0 : SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);)
305 :
306 0 : device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0);
307 0 : device[1] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[1], 256 - a1);
308 0 : }
309 :
310 0 : void SkARGB32_Black_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
311 0 : uint32_t* device = fDevice.writable_addr32(x, y);
312 0 : SkDEBUGCODE((void)fDevice.writable_addr32(x, y + 1);)
313 :
314 0 : device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0);
315 0 : device = (uint32_t*)((char*)device + fDevice.rowBytes());
316 0 : device[0] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a1);
317 0 : }
318 :
319 : ///////////////////////////////////////////////////////////////////////////////
320 :
321 : // Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
322 : // instead of kSrcOver_Mode
323 0 : static void blend_srcmode(SkPMColor* SK_RESTRICT device,
324 : const SkPMColor* SK_RESTRICT span,
325 : int count, U8CPU aa) {
326 0 : int aa256 = SkAlpha255To256(aa);
327 0 : for (int i = 0; i < count; ++i) {
328 0 : device[i] = SkFourByteInterp256(span[i], device[i], aa256);
329 : }
330 0 : }
331 :
332 164 : SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkPixmap& device,
333 164 : const SkPaint& paint, SkShader::Context* shaderContext)
334 164 : : INHERITED(device, paint, shaderContext)
335 : {
336 164 : fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
337 :
338 164 : fXfermode = SkXfermode::Peek(paint.getBlendMode());
339 :
340 164 : int flags = 0;
341 164 : if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
342 135 : flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
343 : }
344 : // we call this on the output from the shader
345 164 : fProc32 = SkBlitRow::Factory32(flags);
346 : // we call this on the output from the shader + alpha from the aa buffer
347 164 : fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
348 :
349 164 : fShadeDirectlyIntoDevice = false;
350 164 : if (fXfermode == nullptr) {
351 164 : if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
352 29 : fShadeDirectlyIntoDevice = true;
353 : }
354 : } else {
355 : SkXfermode::Mode mode;
356 0 : if (fXfermode->asMode(&mode)) {
357 0 : if (SkXfermode::kSrc_Mode == mode) {
358 0 : fShadeDirectlyIntoDevice = true;
359 0 : fProc32Blend = blend_srcmode;
360 : }
361 : }
362 : }
363 :
364 164 : fConstInY = SkToBool(shaderContext->getFlags() & SkShader::kConstInY32_Flag);
365 164 : }
366 :
367 328 : SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
368 164 : sk_free(fBuffer);
369 164 : }
370 :
371 1228 : void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
372 1228 : SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
373 :
374 1228 : uint32_t* device = fDevice.writable_addr32(x, y);
375 :
376 1228 : if (fShadeDirectlyIntoDevice) {
377 0 : fShaderContext->shadeSpan(x, y, device, width);
378 : } else {
379 1228 : SkPMColor* span = fBuffer;
380 1228 : fShaderContext->shadeSpan(x, y, span, width);
381 1228 : if (fXfermode) {
382 0 : fXfermode->xfer32(device, span, width, nullptr);
383 : } else {
384 1228 : fProc32(device, span, width, 255);
385 : }
386 : }
387 1228 : }
388 :
389 73 : void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
390 73 : SkASSERT(x >= 0 && y >= 0 &&
391 : x + width <= fDevice.width() && y + height <= fDevice.height());
392 :
393 73 : uint32_t* device = fDevice.writable_addr32(x, y);
394 73 : size_t deviceRB = fDevice.rowBytes();
395 73 : SkShader::Context* shaderContext = fShaderContext;
396 73 : SkPMColor* span = fBuffer;
397 :
398 73 : if (fConstInY) {
399 0 : if (fShadeDirectlyIntoDevice) {
400 : // shade the first row directly into the device
401 0 : shaderContext->shadeSpan(x, y, device, width);
402 0 : span = device;
403 0 : while (--height > 0) {
404 0 : device = (uint32_t*)((char*)device + deviceRB);
405 0 : memcpy(device, span, width << 2);
406 : }
407 : } else {
408 0 : shaderContext->shadeSpan(x, y, span, width);
409 0 : SkXfermode* xfer = fXfermode;
410 0 : if (xfer) {
411 0 : do {
412 0 : xfer->xfer32(device, span, width, nullptr);
413 0 : y += 1;
414 0 : device = (uint32_t*)((char*)device + deviceRB);
415 : } while (--height > 0);
416 : } else {
417 0 : SkBlitRow::Proc32 proc = fProc32;
418 0 : do {
419 0 : proc(device, span, width, 255);
420 0 : y += 1;
421 0 : device = (uint32_t*)((char*)device + deviceRB);
422 : } while (--height > 0);
423 : }
424 : }
425 0 : return;
426 : }
427 :
428 73 : if (fShadeDirectlyIntoDevice) {
429 : void* ctx;
430 47 : SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
431 47 : if (shadeProc) {
432 11341 : do {
433 11341 : shadeProc(ctx, x, y, device, width);
434 11341 : y += 1;
435 11341 : device = (uint32_t*)((char*)device + deviceRB);
436 : } while (--height > 0);
437 : } else {
438 0 : do {
439 0 : shaderContext->shadeSpan(x, y, device, width);
440 0 : y += 1;
441 0 : device = (uint32_t*)((char*)device + deviceRB);
442 : } while (--height > 0);
443 : }
444 : } else {
445 26 : SkXfermode* xfer = fXfermode;
446 26 : if (xfer) {
447 0 : do {
448 0 : shaderContext->shadeSpan(x, y, span, width);
449 0 : xfer->xfer32(device, span, width, nullptr);
450 0 : y += 1;
451 0 : device = (uint32_t*)((char*)device + deviceRB);
452 : } while (--height > 0);
453 : } else {
454 26 : SkBlitRow::Proc32 proc = fProc32;
455 1456 : do {
456 1456 : shaderContext->shadeSpan(x, y, span, width);
457 1456 : proc(device, span, width, 255);
458 1456 : y += 1;
459 1456 : device = (uint32_t*)((char*)device + deviceRB);
460 : } while (--height > 0);
461 : }
462 : }
463 : }
464 :
465 2128 : void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
466 : const int16_t runs[]) {
467 2128 : SkPMColor* span = fBuffer;
468 2128 : uint32_t* device = fDevice.writable_addr32(x, y);
469 2128 : SkShader::Context* shaderContext = fShaderContext;
470 :
471 2128 : if (fXfermode && !fShadeDirectlyIntoDevice) {
472 : for (;;) {
473 0 : SkXfermode* xfer = fXfermode;
474 :
475 0 : int count = *runs;
476 0 : if (count <= 0)
477 0 : break;
478 0 : int aa = *antialias;
479 0 : if (aa) {
480 0 : shaderContext->shadeSpan(x, y, span, count);
481 0 : if (aa == 255) {
482 0 : xfer->xfer32(device, span, count, nullptr);
483 : } else {
484 : // count is almost always 1
485 0 : for (int i = count - 1; i >= 0; --i) {
486 0 : xfer->xfer32(&device[i], &span[i], 1, antialias);
487 : }
488 : }
489 : }
490 0 : device += count;
491 0 : runs += count;
492 0 : antialias += count;
493 0 : x += count;
494 0 : }
495 4244 : } else if (fShadeDirectlyIntoDevice ||
496 2116 : (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
497 : for (;;) {
498 24 : int count = *runs;
499 24 : if (count <= 0) {
500 12 : break;
501 : }
502 12 : int aa = *antialias;
503 12 : if (aa) {
504 12 : if (aa == 255) {
505 : // cool, have the shader draw right into the device
506 12 : shaderContext->shadeSpan(x, y, device, count);
507 : } else {
508 0 : shaderContext->shadeSpan(x, y, span, count);
509 0 : fProc32Blend(device, span, count, aa);
510 : }
511 : }
512 12 : device += count;
513 12 : runs += count;
514 12 : antialias += count;
515 12 : x += count;
516 12 : }
517 : } else {
518 : for (;;) {
519 12299 : int count = *runs;
520 12299 : if (count <= 0) {
521 2116 : break;
522 : }
523 10183 : int aa = *antialias;
524 10183 : if (aa) {
525 5339 : shaderContext->shadeSpan(x, y, span, count);
526 5339 : if (aa == 255) {
527 4349 : fProc32(device, span, count, 255);
528 : } else {
529 990 : fProc32Blend(device, span, count, aa);
530 : }
531 : }
532 10183 : device += count;
533 10183 : runs += count;
534 10183 : antialias += count;
535 10183 : x += count;
536 10183 : }
537 : }
538 2128 : }
539 :
540 61 : void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
541 : // we only handle kA8 with an xfermode
542 61 : if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
543 0 : this->INHERITED::blitMask(mask, clip);
544 0 : return;
545 : }
546 :
547 61 : SkASSERT(mask.fBounds.contains(clip));
548 :
549 61 : SkShader::Context* shaderContext = fShaderContext;
550 61 : SkBlitMask::RowProc proc = nullptr;
551 61 : if (!fXfermode) {
552 61 : unsigned flags = 0;
553 61 : if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
554 61 : flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
555 : }
556 61 : proc = SkBlitMask::RowFactory(kN32_SkColorType, mask.fFormat,
557 61 : (SkBlitMask::RowFlags)flags);
558 61 : if (nullptr == proc) {
559 0 : this->INHERITED::blitMask(mask, clip);
560 0 : return;
561 : }
562 : }
563 :
564 61 : const int x = clip.fLeft;
565 61 : const int width = clip.width();
566 61 : int y = clip.fTop;
567 61 : int height = clip.height();
568 :
569 61 : char* dstRow = (char*)fDevice.writable_addr32(x, y);
570 61 : const size_t dstRB = fDevice.rowBytes();
571 61 : const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
572 61 : const size_t maskRB = mask.fRowBytes;
573 :
574 61 : SkPMColor* span = fBuffer;
575 :
576 61 : if (fXfermode) {
577 0 : SkASSERT(SkMask::kA8_Format == mask.fFormat);
578 0 : SkXfermode* xfer = fXfermode;
579 0 : do {
580 0 : shaderContext->shadeSpan(x, y, span, width);
581 0 : xfer->xfer32(reinterpret_cast<SkPMColor*>(dstRow), span, width, maskRow);
582 0 : dstRow += dstRB;
583 0 : maskRow += maskRB;
584 0 : y += 1;
585 : } while (--height > 0);
586 : } else {
587 90 : do {
588 90 : shaderContext->shadeSpan(x, y, span, width);
589 90 : proc(reinterpret_cast<SkPMColor*>(dstRow), maskRow, span, width);
590 90 : dstRow += dstRB;
591 90 : maskRow += maskRB;
592 90 : y += 1;
593 : } while (--height > 0);
594 : }
595 : }
596 :
597 0 : void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
598 0 : SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
599 :
600 0 : uint32_t* device = fDevice.writable_addr32(x, y);
601 0 : size_t deviceRB = fDevice.rowBytes();
602 0 : SkShader::Context* shaderContext = fShaderContext;
603 :
604 0 : if (fConstInY) {
605 : SkPMColor c;
606 0 : shaderContext->shadeSpan(x, y, &c, 1);
607 :
608 0 : if (fShadeDirectlyIntoDevice) {
609 0 : if (255 == alpha) {
610 0 : do {
611 0 : *device = c;
612 0 : device = (uint32_t*)((char*)device + deviceRB);
613 : } while (--height > 0);
614 : } else {
615 0 : do {
616 0 : *device = SkFourByteInterp(c, *device, alpha);
617 0 : device = (uint32_t*)((char*)device + deviceRB);
618 : } while (--height > 0);
619 : }
620 : } else {
621 0 : SkXfermode* xfer = fXfermode;
622 0 : if (xfer) {
623 0 : do {
624 0 : xfer->xfer32(device, &c, 1, &alpha);
625 0 : device = (uint32_t*)((char*)device + deviceRB);
626 : } while (--height > 0);
627 : } else {
628 0 : SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
629 0 : do {
630 0 : proc(device, &c, 1, alpha);
631 0 : device = (uint32_t*)((char*)device + deviceRB);
632 : } while (--height > 0);
633 : }
634 : }
635 0 : return;
636 : }
637 :
638 0 : if (fShadeDirectlyIntoDevice) {
639 : void* ctx;
640 0 : SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
641 0 : if (255 == alpha) {
642 0 : if (shadeProc) {
643 0 : do {
644 0 : shadeProc(ctx, x, y, device, 1);
645 0 : y += 1;
646 0 : device = (uint32_t*)((char*)device + deviceRB);
647 : } while (--height > 0);
648 : } else {
649 0 : do {
650 0 : shaderContext->shadeSpan(x, y, device, 1);
651 0 : y += 1;
652 0 : device = (uint32_t*)((char*)device + deviceRB);
653 : } while (--height > 0);
654 : }
655 : } else { // alpha < 255
656 : SkPMColor c;
657 0 : if (shadeProc) {
658 0 : do {
659 0 : shadeProc(ctx, x, y, &c, 1);
660 0 : *device = SkFourByteInterp(c, *device, alpha);
661 0 : y += 1;
662 0 : device = (uint32_t*)((char*)device + deviceRB);
663 : } while (--height > 0);
664 : } else {
665 0 : do {
666 0 : shaderContext->shadeSpan(x, y, &c, 1);
667 0 : *device = SkFourByteInterp(c, *device, alpha);
668 0 : y += 1;
669 0 : device = (uint32_t*)((char*)device + deviceRB);
670 : } while (--height > 0);
671 : }
672 : }
673 : } else {
674 0 : SkPMColor* span = fBuffer;
675 0 : SkXfermode* xfer = fXfermode;
676 0 : if (xfer) {
677 0 : do {
678 0 : shaderContext->shadeSpan(x, y, span, 1);
679 0 : xfer->xfer32(device, span, 1, &alpha);
680 0 : y += 1;
681 0 : device = (uint32_t*)((char*)device + deviceRB);
682 : } while (--height > 0);
683 : } else {
684 0 : SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
685 0 : do {
686 0 : shaderContext->shadeSpan(x, y, span, 1);
687 0 : proc(device, span, 1, alpha);
688 0 : y += 1;
689 0 : device = (uint32_t*)((char*)device + deviceRB);
690 : } while (--height > 0);
691 : }
692 : }
693 : }
|