|
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 |
|
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 |
|
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 fColorRect32Proc = SkBlitRow::ColorRectProcFactory(); |
|
57 } |
|
58 |
|
59 const 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 |
|
72 void SkARGB32_Blitter::blitH(int x, int y, int width) { |
|
73 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); |
|
74 |
|
75 uint32_t* device = fDevice.getAddr32(x, y); |
|
76 fColor32Proc(device, device, width, fPMColor); |
|
77 } |
|
78 |
|
79 void 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 { |
|
100 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa)); |
|
101 fColor32Proc(device, device, count, sc); |
|
102 } |
|
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 |
|
150 void 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 |
|
158 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) { |
|
159 return; |
|
160 } |
|
161 |
|
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); |
|
166 } |
|
167 } |
|
168 |
|
169 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask, |
|
170 const SkIRect& clip) { |
|
171 SkASSERT(mask.fBounds.contains(clip)); |
|
172 |
|
173 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) { |
|
174 return; |
|
175 } |
|
176 |
|
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); |
|
181 } |
|
182 } |
|
183 |
|
184 /////////////////////////////////////////////////////////////////////////////// |
|
185 |
|
186 void 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); |
|
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); |
|
203 } |
|
204 } |
|
205 |
|
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()); |
|
208 |
|
209 if (fSrcA == 0) { |
|
210 return; |
|
211 } |
|
212 |
|
213 uint32_t* device = fDevice.getAddr32(x, y); |
|
214 uint32_t color = fPMColor; |
|
215 size_t rowBytes = fDevice.rowBytes(); |
|
216 |
|
217 if (255 == SkGetPackedA32(color)) { |
|
218 fColorRect32Proc(device, width, height, rowBytes, color); |
|
219 } else { |
|
220 while (--height >= 0) { |
|
221 fColor32Proc(device, device, width, color); |
|
222 device = (uint32_t*)((char*)device + rowBytes); |
|
223 } |
|
224 } |
|
225 } |
|
226 |
|
227 #if defined _WIN32 && _MSC_VER >= 1300 |
|
228 #pragma warning ( pop ) |
|
229 #endif |
|
230 |
|
231 /////////////////////////////////////////////////////////////////////// |
|
232 |
|
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); |
|
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 |
|
264 /////////////////////////////////////////////////////////////////////////////// |
|
265 |
|
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); |
|
274 } |
|
275 } |
|
276 |
|
277 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, |
|
278 const SkPaint& paint) : INHERITED(device, paint) { |
|
279 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); |
|
280 |
|
281 fXfermode = paint.getXfermode(); |
|
282 SkSafeRef(fXfermode); |
|
283 |
|
284 int flags = 0; |
|
285 if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { |
|
286 flags |= SkBlitRow::kSrcPixelAlpha_Flag32; |
|
287 } |
|
288 // we call this on the output from the shader |
|
289 fProc32 = SkBlitRow::Factory32(flags); |
|
290 // we call this on the output from the shader + alpha from the aa buffer |
|
291 fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32); |
|
292 |
|
293 fShadeDirectlyIntoDevice = false; |
|
294 if (fXfermode == NULL) { |
|
295 if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { |
|
296 fShadeDirectlyIntoDevice = true; |
|
297 } |
|
298 } else { |
|
299 SkXfermode::Mode mode; |
|
300 if (fXfermode->asMode(&mode)) { |
|
301 if (SkXfermode::kSrc_Mode == mode) { |
|
302 fShadeDirectlyIntoDevice = true; |
|
303 fProc32Blend = blend_srcmode; |
|
304 } |
|
305 } |
|
306 } |
|
307 |
|
308 fConstInY = SkToBool(fShader->getFlags() & SkShader::kConstInY32_Flag); |
|
309 } |
|
310 |
|
311 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() { |
|
312 SkSafeUnref(fXfermode); |
|
313 sk_free(fBuffer); |
|
314 } |
|
315 |
|
316 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) { |
|
317 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); |
|
318 |
|
319 uint32_t* device = fDevice.getAddr32(x, y); |
|
320 |
|
321 if (fShadeDirectlyIntoDevice) { |
|
322 fShader->shadeSpan(x, y, device, width); |
|
323 } else { |
|
324 SkPMColor* span = fBuffer; |
|
325 fShader->shadeSpan(x, y, span, width); |
|
326 if (fXfermode) { |
|
327 fXfermode->xfer32(device, span, width, NULL); |
|
328 } else { |
|
329 fProc32(device, span, width, 255); |
|
330 } |
|
331 } |
|
332 } |
|
333 |
|
334 void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) { |
|
335 SkASSERT(x >= 0 && y >= 0 && |
|
336 x + width <= fDevice.width() && y + height <= fDevice.height()); |
|
337 |
|
338 uint32_t* device = fDevice.getAddr32(x, y); |
|
339 size_t deviceRB = fDevice.rowBytes(); |
|
340 SkShader* shader = fShader; |
|
341 SkPMColor* span = fBuffer; |
|
342 |
|
343 if (fConstInY) { |
|
344 if (fShadeDirectlyIntoDevice) { |
|
345 // shade the first row directly into the device |
|
346 fShader->shadeSpan(x, y, device, width); |
|
347 span = device; |
|
348 while (--height > 0) { |
|
349 device = (uint32_t*)((char*)device + deviceRB); |
|
350 memcpy(device, span, width << 2); |
|
351 } |
|
352 } else { |
|
353 fShader->shadeSpan(x, y, span, width); |
|
354 SkXfermode* xfer = fXfermode; |
|
355 if (xfer) { |
|
356 do { |
|
357 xfer->xfer32(device, span, width, NULL); |
|
358 y += 1; |
|
359 device = (uint32_t*)((char*)device + deviceRB); |
|
360 } while (--height > 0); |
|
361 } else { |
|
362 SkBlitRow::Proc32 proc = fProc32; |
|
363 do { |
|
364 proc(device, span, width, 255); |
|
365 y += 1; |
|
366 device = (uint32_t*)((char*)device + deviceRB); |
|
367 } while (--height > 0); |
|
368 } |
|
369 } |
|
370 return; |
|
371 } |
|
372 |
|
373 if (fShadeDirectlyIntoDevice) { |
|
374 void* ctx; |
|
375 SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx); |
|
376 if (shadeProc) { |
|
377 do { |
|
378 shadeProc(ctx, x, y, device, width); |
|
379 y += 1; |
|
380 device = (uint32_t*)((char*)device + deviceRB); |
|
381 } while (--height > 0); |
|
382 } else { |
|
383 do { |
|
384 shader->shadeSpan(x, y, device, width); |
|
385 y += 1; |
|
386 device = (uint32_t*)((char*)device + deviceRB); |
|
387 } while (--height > 0); |
|
388 } |
|
389 } else { |
|
390 SkXfermode* xfer = fXfermode; |
|
391 if (xfer) { |
|
392 do { |
|
393 shader->shadeSpan(x, y, span, width); |
|
394 xfer->xfer32(device, span, width, NULL); |
|
395 y += 1; |
|
396 device = (uint32_t*)((char*)device + deviceRB); |
|
397 } while (--height > 0); |
|
398 } else { |
|
399 SkBlitRow::Proc32 proc = fProc32; |
|
400 do { |
|
401 shader->shadeSpan(x, y, span, width); |
|
402 proc(device, span, width, 255); |
|
403 y += 1; |
|
404 device = (uint32_t*)((char*)device + deviceRB); |
|
405 } while (--height > 0); |
|
406 } |
|
407 } |
|
408 } |
|
409 |
|
410 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], |
|
411 const int16_t runs[]) { |
|
412 SkPMColor* span = fBuffer; |
|
413 uint32_t* device = fDevice.getAddr32(x, y); |
|
414 SkShader* shader = fShader; |
|
415 |
|
416 if (fXfermode && !fShadeDirectlyIntoDevice) { |
|
417 for (;;) { |
|
418 SkXfermode* xfer = fXfermode; |
|
419 |
|
420 int count = *runs; |
|
421 if (count <= 0) |
|
422 break; |
|
423 int aa = *antialias; |
|
424 if (aa) { |
|
425 shader->shadeSpan(x, y, span, count); |
|
426 if (aa == 255) { |
|
427 xfer->xfer32(device, span, count, NULL); |
|
428 } else { |
|
429 // count is almost always 1 |
|
430 for (int i = count - 1; i >= 0; --i) { |
|
431 xfer->xfer32(&device[i], &span[i], 1, antialias); |
|
432 } |
|
433 } |
|
434 } |
|
435 device += count; |
|
436 runs += count; |
|
437 antialias += count; |
|
438 x += count; |
|
439 } |
|
440 } else if (fShadeDirectlyIntoDevice || |
|
441 (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { |
|
442 for (;;) { |
|
443 int count = *runs; |
|
444 if (count <= 0) { |
|
445 break; |
|
446 } |
|
447 int aa = *antialias; |
|
448 if (aa) { |
|
449 if (aa == 255) { |
|
450 // cool, have the shader draw right into the device |
|
451 shader->shadeSpan(x, y, device, count); |
|
452 } else { |
|
453 shader->shadeSpan(x, y, span, count); |
|
454 fProc32Blend(device, span, count, aa); |
|
455 } |
|
456 } |
|
457 device += count; |
|
458 runs += count; |
|
459 antialias += count; |
|
460 x += count; |
|
461 } |
|
462 } else { |
|
463 for (;;) { |
|
464 int count = *runs; |
|
465 if (count <= 0) { |
|
466 break; |
|
467 } |
|
468 int aa = *antialias; |
|
469 if (aa) { |
|
470 fShader->shadeSpan(x, y, span, count); |
|
471 if (aa == 255) { |
|
472 fProc32(device, span, count, 255); |
|
473 } else { |
|
474 fProc32Blend(device, span, count, aa); |
|
475 } |
|
476 } |
|
477 device += count; |
|
478 runs += count; |
|
479 antialias += count; |
|
480 x += count; |
|
481 } |
|
482 } |
|
483 } |
|
484 |
|
485 void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { |
|
486 // we only handle kA8 with an xfermode |
|
487 if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) { |
|
488 this->INHERITED::blitMask(mask, clip); |
|
489 return; |
|
490 } |
|
491 |
|
492 SkASSERT(mask.fBounds.contains(clip)); |
|
493 |
|
494 SkBlitMask::RowProc proc = NULL; |
|
495 if (!fXfermode) { |
|
496 unsigned flags = 0; |
|
497 if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { |
|
498 flags |= SkBlitMask::kSrcIsOpaque_RowFlag; |
|
499 } |
|
500 proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat, |
|
501 (SkBlitMask::RowFlags)flags); |
|
502 if (NULL == proc) { |
|
503 this->INHERITED::blitMask(mask, clip); |
|
504 return; |
|
505 } |
|
506 } |
|
507 |
|
508 const int x = clip.fLeft; |
|
509 const int width = clip.width(); |
|
510 int y = clip.fTop; |
|
511 int height = clip.height(); |
|
512 |
|
513 char* dstRow = (char*)fDevice.getAddr32(x, y); |
|
514 const size_t dstRB = fDevice.rowBytes(); |
|
515 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); |
|
516 const size_t maskRB = mask.fRowBytes; |
|
517 |
|
518 SkShader* shader = fShader; |
|
519 SkPMColor* span = fBuffer; |
|
520 |
|
521 if (fXfermode) { |
|
522 SkASSERT(SkMask::kA8_Format == mask.fFormat); |
|
523 SkXfermode* xfer = fXfermode; |
|
524 do { |
|
525 shader->shadeSpan(x, y, span, width); |
|
526 xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow); |
|
527 dstRow += dstRB; |
|
528 maskRow += maskRB; |
|
529 y += 1; |
|
530 } while (--height > 0); |
|
531 } else { |
|
532 do { |
|
533 shader->shadeSpan(x, y, span, width); |
|
534 proc(dstRow, maskRow, span, width); |
|
535 dstRow += dstRB; |
|
536 maskRow += maskRB; |
|
537 y += 1; |
|
538 } while (--height > 0); |
|
539 } |
|
540 } |
|
541 |
|
542 void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { |
|
543 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); |
|
544 |
|
545 uint32_t* device = fDevice.getAddr32(x, y); |
|
546 size_t deviceRB = fDevice.rowBytes(); |
|
547 SkShader* shader = fShader; |
|
548 |
|
549 if (fConstInY) { |
|
550 SkPMColor c; |
|
551 fShader->shadeSpan(x, y, &c, 1); |
|
552 |
|
553 if (fShadeDirectlyIntoDevice) { |
|
554 if (255 == alpha) { |
|
555 do { |
|
556 *device = c; |
|
557 device = (uint32_t*)((char*)device + deviceRB); |
|
558 } while (--height > 0); |
|
559 } else { |
|
560 do { |
|
561 *device = SkFourByteInterp(c, *device, alpha); |
|
562 device = (uint32_t*)((char*)device + deviceRB); |
|
563 } while (--height > 0); |
|
564 } |
|
565 } else { |
|
566 SkXfermode* xfer = fXfermode; |
|
567 if (xfer) { |
|
568 do { |
|
569 xfer->xfer32(device, &c, 1, &alpha); |
|
570 device = (uint32_t*)((char*)device + deviceRB); |
|
571 } while (--height > 0); |
|
572 } else { |
|
573 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend; |
|
574 do { |
|
575 proc(device, &c, 1, alpha); |
|
576 device = (uint32_t*)((char*)device + deviceRB); |
|
577 } while (--height > 0); |
|
578 } |
|
579 } |
|
580 return; |
|
581 } |
|
582 |
|
583 if (fShadeDirectlyIntoDevice) { |
|
584 void* ctx; |
|
585 SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx); |
|
586 if (255 == alpha) { |
|
587 if (shadeProc) { |
|
588 do { |
|
589 shadeProc(ctx, x, y, device, 1); |
|
590 y += 1; |
|
591 device = (uint32_t*)((char*)device + deviceRB); |
|
592 } while (--height > 0); |
|
593 } else { |
|
594 do { |
|
595 shader->shadeSpan(x, y, device, 1); |
|
596 y += 1; |
|
597 device = (uint32_t*)((char*)device + deviceRB); |
|
598 } while (--height > 0); |
|
599 } |
|
600 } else { // alpha < 255 |
|
601 SkPMColor c; |
|
602 if (shadeProc) { |
|
603 do { |
|
604 shadeProc(ctx, x, y, &c, 1); |
|
605 *device = SkFourByteInterp(c, *device, alpha); |
|
606 y += 1; |
|
607 device = (uint32_t*)((char*)device + deviceRB); |
|
608 } while (--height > 0); |
|
609 } else { |
|
610 do { |
|
611 shader->shadeSpan(x, y, &c, 1); |
|
612 *device = SkFourByteInterp(c, *device, alpha); |
|
613 y += 1; |
|
614 device = (uint32_t*)((char*)device + deviceRB); |
|
615 } while (--height > 0); |
|
616 } |
|
617 } |
|
618 } else { |
|
619 SkPMColor* span = fBuffer; |
|
620 SkXfermode* xfer = fXfermode; |
|
621 if (xfer) { |
|
622 do { |
|
623 shader->shadeSpan(x, y, span, 1); |
|
624 xfer->xfer32(device, span, 1, &alpha); |
|
625 y += 1; |
|
626 device = (uint32_t*)((char*)device + deviceRB); |
|
627 } while (--height > 0); |
|
628 } else { |
|
629 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend; |
|
630 do { |
|
631 shader->shadeSpan(x, y, span, 1); |
|
632 proc(device, span, 1, alpha); |
|
633 y += 1; |
|
634 device = (uint32_t*)((char*)device + deviceRB); |
|
635 } while (--height > 0); |
|
636 } |
|
637 } |
|
638 } |