1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkBlitter_RGB16.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1050 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkBlitRow.h" 1.14 +#include "SkCoreBlitters.h" 1.15 +#include "SkColorPriv.h" 1.16 +#include "SkDither.h" 1.17 +#include "SkShader.h" 1.18 +#include "SkUtils.h" 1.19 +#include "SkXfermode.h" 1.20 + 1.21 +#if defined(__ARM_HAVE_NEON) && defined(SK_CPU_LENDIAN) 1.22 + #define SK_USE_NEON 1.23 + #include <arm_neon.h> 1.24 +#else 1.25 + // if we don't have neon, then our black blitter is worth the extra code 1.26 + #define USE_BLACK_BLITTER 1.27 +#endif 1.28 + 1.29 +void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, 1.30 + int count) { 1.31 + if (count > 0) { 1.32 + // see if we need to write one short before we can cast to an 4byte ptr 1.33 + // (we do this subtract rather than (unsigned)dst so we don't get warnings 1.34 + // on 64bit machines) 1.35 + if (((char*)dst - (char*)0) & 2) { 1.36 + *dst++ = value; 1.37 + count -= 1; 1.38 + SkTSwap(value, other); 1.39 + } 1.40 + 1.41 + // fast way to set [value,other] pairs 1.42 +#ifdef SK_CPU_BENDIAN 1.43 + sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1); 1.44 +#else 1.45 + sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1); 1.46 +#endif 1.47 + 1.48 + if (count & 1) { 1.49 + dst[count - 1] = value; 1.50 + } 1.51 + } 1.52 +} 1.53 + 1.54 +/////////////////////////////////////////////////////////////////////////////// 1.55 + 1.56 +class SkRGB16_Blitter : public SkRasterBlitter { 1.57 +public: 1.58 + SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint); 1.59 + virtual void blitH(int x, int y, int width); 1.60 + virtual void blitAntiH(int x, int y, const SkAlpha* antialias, 1.61 + const int16_t* runs); 1.62 + virtual void blitV(int x, int y, int height, SkAlpha alpha); 1.63 + virtual void blitRect(int x, int y, int width, int height); 1.64 + virtual void blitMask(const SkMask&, 1.65 + const SkIRect&); 1.66 + virtual const SkBitmap* justAnOpaqueColor(uint32_t*); 1.67 + 1.68 +protected: 1.69 + SkPMColor fSrcColor32; 1.70 + uint32_t fExpandedRaw16; 1.71 + unsigned fScale; 1.72 + uint16_t fColor16; // already scaled by fScale 1.73 + uint16_t fRawColor16; // unscaled 1.74 + uint16_t fRawDither16; // unscaled 1.75 + SkBool8 fDoDither; 1.76 + 1.77 + // illegal 1.78 + SkRGB16_Blitter& operator=(const SkRGB16_Blitter&); 1.79 + 1.80 + typedef SkRasterBlitter INHERITED; 1.81 +}; 1.82 + 1.83 +class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter { 1.84 +public: 1.85 + SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint); 1.86 + virtual void blitH(int x, int y, int width); 1.87 + virtual void blitAntiH(int x, int y, const SkAlpha* antialias, 1.88 + const int16_t* runs); 1.89 + virtual void blitV(int x, int y, int height, SkAlpha alpha); 1.90 + virtual void blitRect(int x, int y, int width, int height); 1.91 + virtual void blitMask(const SkMask&, 1.92 + const SkIRect&); 1.93 + 1.94 +private: 1.95 + typedef SkRGB16_Blitter INHERITED; 1.96 +}; 1.97 + 1.98 +#ifdef USE_BLACK_BLITTER 1.99 +class SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter { 1.100 +public: 1.101 + SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint); 1.102 + virtual void blitMask(const SkMask&, const SkIRect&); 1.103 + virtual void blitAntiH(int x, int y, const SkAlpha* antialias, 1.104 + const int16_t* runs); 1.105 + 1.106 +private: 1.107 + typedef SkRGB16_Opaque_Blitter INHERITED; 1.108 +}; 1.109 +#endif 1.110 + 1.111 +class SkRGB16_Shader_Blitter : public SkShaderBlitter { 1.112 +public: 1.113 + SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint); 1.114 + virtual ~SkRGB16_Shader_Blitter(); 1.115 + virtual void blitH(int x, int y, int width); 1.116 + virtual void blitAntiH(int x, int y, const SkAlpha* antialias, 1.117 + const int16_t* runs); 1.118 + virtual void blitRect(int x, int y, int width, int height); 1.119 + 1.120 +protected: 1.121 + SkPMColor* fBuffer; 1.122 + SkBlitRow::Proc fOpaqueProc; 1.123 + SkBlitRow::Proc fAlphaProc; 1.124 + 1.125 +private: 1.126 + // illegal 1.127 + SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&); 1.128 + 1.129 + typedef SkShaderBlitter INHERITED; 1.130 +}; 1.131 + 1.132 +// used only if the shader can perform shadSpan16 1.133 +class SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter { 1.134 +public: 1.135 + SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint); 1.136 + virtual void blitH(int x, int y, int width); 1.137 + virtual void blitAntiH(int x, int y, const SkAlpha* antialias, 1.138 + const int16_t* runs); 1.139 + virtual void blitRect(int x, int y, int width, int height); 1.140 + 1.141 +private: 1.142 + typedef SkRGB16_Shader_Blitter INHERITED; 1.143 +}; 1.144 + 1.145 +class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter { 1.146 +public: 1.147 + SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint); 1.148 + virtual ~SkRGB16_Shader_Xfermode_Blitter(); 1.149 + virtual void blitH(int x, int y, int width); 1.150 + virtual void blitAntiH(int x, int y, const SkAlpha* antialias, 1.151 + const int16_t* runs); 1.152 + 1.153 +private: 1.154 + SkXfermode* fXfermode; 1.155 + SkPMColor* fBuffer; 1.156 + uint8_t* fAAExpand; 1.157 + 1.158 + // illegal 1.159 + SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&); 1.160 + 1.161 + typedef SkShaderBlitter INHERITED; 1.162 +}; 1.163 + 1.164 +/////////////////////////////////////////////////////////////////////////////// 1.165 +#ifdef USE_BLACK_BLITTER 1.166 +SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint) 1.167 + : INHERITED(device, paint) { 1.168 + SkASSERT(paint.getShader() == NULL); 1.169 + SkASSERT(paint.getColorFilter() == NULL); 1.170 + SkASSERT(paint.getXfermode() == NULL); 1.171 + SkASSERT(paint.getColor() == SK_ColorBLACK); 1.172 +} 1.173 + 1.174 +#if 1 1.175 +#define black_8_pixels(mask, dst) \ 1.176 + do { \ 1.177 + if (mask & 0x80) dst[0] = 0; \ 1.178 + if (mask & 0x40) dst[1] = 0; \ 1.179 + if (mask & 0x20) dst[2] = 0; \ 1.180 + if (mask & 0x10) dst[3] = 0; \ 1.181 + if (mask & 0x08) dst[4] = 0; \ 1.182 + if (mask & 0x04) dst[5] = 0; \ 1.183 + if (mask & 0x02) dst[6] = 0; \ 1.184 + if (mask & 0x01) dst[7] = 0; \ 1.185 + } while (0) 1.186 +#else 1.187 +static inline black_8_pixels(U8CPU mask, uint16_t dst[]) 1.188 +{ 1.189 + if (mask & 0x80) dst[0] = 0; 1.190 + if (mask & 0x40) dst[1] = 0; 1.191 + if (mask & 0x20) dst[2] = 0; 1.192 + if (mask & 0x10) dst[3] = 0; 1.193 + if (mask & 0x08) dst[4] = 0; 1.194 + if (mask & 0x04) dst[5] = 0; 1.195 + if (mask & 0x02) dst[6] = 0; 1.196 + if (mask & 0x01) dst[7] = 0; 1.197 +} 1.198 +#endif 1.199 + 1.200 +#define SK_BLITBWMASK_NAME SkRGB16_Black_BlitBW 1.201 +#define SK_BLITBWMASK_ARGS 1.202 +#define SK_BLITBWMASK_BLIT8(mask, dst) black_8_pixels(mask, dst) 1.203 +#define SK_BLITBWMASK_GETADDR getAddr16 1.204 +#define SK_BLITBWMASK_DEVTYPE uint16_t 1.205 +#include "SkBlitBWMaskTemplate.h" 1.206 + 1.207 +void SkRGB16_Black_Blitter::blitMask(const SkMask& mask, 1.208 + const SkIRect& clip) { 1.209 + if (mask.fFormat == SkMask::kBW_Format) { 1.210 + SkRGB16_Black_BlitBW(fDevice, mask, clip); 1.211 + } else { 1.212 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 1.213 + const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop); 1.214 + unsigned width = clip.width(); 1.215 + unsigned height = clip.height(); 1.216 + size_t deviceRB = fDevice.rowBytes() - (width << 1); 1.217 + unsigned maskRB = mask.fRowBytes - width; 1.218 + 1.219 + SkASSERT((int)height > 0); 1.220 + SkASSERT((int)width > 0); 1.221 + SkASSERT((int)deviceRB >= 0); 1.222 + SkASSERT((int)maskRB >= 0); 1.223 + 1.224 + do { 1.225 + unsigned w = width; 1.226 + do { 1.227 + unsigned aa = *alpha++; 1.228 + *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa)); 1.229 + device += 1; 1.230 + } while (--w != 0); 1.231 + device = (uint16_t*)((char*)device + deviceRB); 1.232 + alpha += maskRB; 1.233 + } while (--height != 0); 1.234 + } 1.235 +} 1.236 + 1.237 +void SkRGB16_Black_Blitter::blitAntiH(int x, int y, 1.238 + const SkAlpha* SK_RESTRICT antialias, 1.239 + const int16_t* SK_RESTRICT runs) { 1.240 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.241 + 1.242 + for (;;) { 1.243 + int count = runs[0]; 1.244 + SkASSERT(count >= 0); 1.245 + if (count <= 0) { 1.246 + return; 1.247 + } 1.248 + runs += count; 1.249 + 1.250 + unsigned aa = antialias[0]; 1.251 + antialias += count; 1.252 + if (aa) { 1.253 + if (aa == 255) { 1.254 + memset(device, 0, count << 1); 1.255 + } else { 1.256 + aa = SkAlpha255To256(255 - aa); 1.257 + do { 1.258 + *device = SkAlphaMulRGB16(*device, aa); 1.259 + device += 1; 1.260 + } while (--count != 0); 1.261 + continue; 1.262 + } 1.263 + } 1.264 + device += count; 1.265 + } 1.266 +} 1.267 +#endif 1.268 + 1.269 +/////////////////////////////////////////////////////////////////////////////// 1.270 +/////////////////////////////////////////////////////////////////////////////// 1.271 + 1.272 +SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device, 1.273 + const SkPaint& paint) 1.274 +: INHERITED(device, paint) {} 1.275 + 1.276 +void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) { 1.277 + SkASSERT(width > 0); 1.278 + SkASSERT(x + width <= fDevice.width()); 1.279 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.280 + uint16_t srcColor = fColor16; 1.281 + 1.282 + SkASSERT(fRawColor16 == srcColor); 1.283 + if (fDoDither) { 1.284 + uint16_t ditherColor = fRawDither16; 1.285 + if ((x ^ y) & 1) { 1.286 + SkTSwap(ditherColor, srcColor); 1.287 + } 1.288 + sk_dither_memset16(device, srcColor, ditherColor, width); 1.289 + } else { 1.290 + sk_memset16(device, srcColor, width); 1.291 + } 1.292 +} 1.293 + 1.294 +// return 1 or 0 from a bool 1.295 +static inline int Bool2Int(int value) { 1.296 + return !!value; 1.297 +} 1.298 + 1.299 +void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y, 1.300 + const SkAlpha* SK_RESTRICT antialias, 1.301 + const int16_t* SK_RESTRICT runs) { 1.302 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.303 + uint16_t srcColor = fRawColor16; 1.304 + uint32_t srcExpanded = fExpandedRaw16; 1.305 + int ditherInt = Bool2Int(fDoDither); 1.306 + uint16_t ditherColor = fRawDither16; 1.307 + // if we have no dithering, this will always fail 1.308 + if ((x ^ y) & ditherInt) { 1.309 + SkTSwap(ditherColor, srcColor); 1.310 + } 1.311 + for (;;) { 1.312 + int count = runs[0]; 1.313 + SkASSERT(count >= 0); 1.314 + if (count <= 0) { 1.315 + return; 1.316 + } 1.317 + runs += count; 1.318 + 1.319 + unsigned aa = antialias[0]; 1.320 + antialias += count; 1.321 + if (aa) { 1.322 + if (aa == 255) { 1.323 + if (ditherInt) { 1.324 + sk_dither_memset16(device, srcColor, 1.325 + ditherColor, count); 1.326 + } else { 1.327 + sk_memset16(device, srcColor, count); 1.328 + } 1.329 + } else { 1.330 + // TODO: respect fDoDither 1.331 + unsigned scale5 = SkAlpha255To256(aa) >> 3; 1.332 + uint32_t src32 = srcExpanded * scale5; 1.333 + scale5 = 32 - scale5; // now we can use it on the device 1.334 + int n = count; 1.335 + do { 1.336 + uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 1.337 + *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 1.338 + } while (--n != 0); 1.339 + goto DONE; 1.340 + } 1.341 + } 1.342 + device += count; 1.343 + 1.344 + DONE: 1.345 + // if we have no dithering, this will always fail 1.346 + if (count & ditherInt) { 1.347 + SkTSwap(ditherColor, srcColor); 1.348 + } 1.349 + } 1.350 +} 1.351 + 1.352 +#define solid_8_pixels(mask, dst, color) \ 1.353 + do { \ 1.354 + if (mask & 0x80) dst[0] = color; \ 1.355 + if (mask & 0x40) dst[1] = color; \ 1.356 + if (mask & 0x20) dst[2] = color; \ 1.357 + if (mask & 0x10) dst[3] = color; \ 1.358 + if (mask & 0x08) dst[4] = color; \ 1.359 + if (mask & 0x04) dst[5] = color; \ 1.360 + if (mask & 0x02) dst[6] = color; \ 1.361 + if (mask & 0x01) dst[7] = color; \ 1.362 + } while (0) 1.363 + 1.364 +#define SK_BLITBWMASK_NAME SkRGB16_BlitBW 1.365 +#define SK_BLITBWMASK_ARGS , uint16_t color 1.366 +#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) 1.367 +#define SK_BLITBWMASK_GETADDR getAddr16 1.368 +#define SK_BLITBWMASK_DEVTYPE uint16_t 1.369 +#include "SkBlitBWMaskTemplate.h" 1.370 + 1.371 +static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) { 1.372 + return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5)); 1.373 +} 1.374 + 1.375 +void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask, 1.376 + const SkIRect& clip) { 1.377 + if (mask.fFormat == SkMask::kBW_Format) { 1.378 + SkRGB16_BlitBW(fDevice, mask, clip, fColor16); 1.379 + return; 1.380 + } 1.381 + 1.382 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 1.383 + const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop); 1.384 + int width = clip.width(); 1.385 + int height = clip.height(); 1.386 + size_t deviceRB = fDevice.rowBytes() - (width << 1); 1.387 + unsigned maskRB = mask.fRowBytes - width; 1.388 + uint32_t expanded32 = fExpandedRaw16; 1.389 + 1.390 +#ifdef SK_USE_NEON 1.391 +#define UNROLL 8 1.392 + do { 1.393 + int w = width; 1.394 + if (w >= UNROLL) { 1.395 + uint32x4_t color, dev_lo, dev_hi; 1.396 + uint32x4_t wn1, wn2, tmp; 1.397 + uint32x4_t vmask_g16, vmask_ng16; 1.398 + uint16x8_t valpha, vdev; 1.399 + uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi; 1.400 + 1.401 + // prepare constants 1.402 + vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE); 1.403 + vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE); 1.404 + color = vdupq_n_u32(expanded32); 1.405 + 1.406 + do { 1.407 + // alpha is 8x8, widen and split to get a pair of 16x4 1.408 + valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha)); 1.409 + valpha = vshrq_n_u16(valpha, 3); 1.410 + valpha_lo = vget_low_u16(valpha); 1.411 + valpha_hi = vget_high_u16(valpha); 1.412 + 1.413 + // load pixels 1.414 + vdev = vld1q_u16(device); 1.415 + dev_lo = vmovl_u16(vget_low_u16(vdev)); 1.416 + dev_hi = vmovl_u16(vget_high_u16(vdev)); 1.417 + 1.418 + // unpack them in 32 bits 1.419 + dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16); 1.420 + dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16); 1.421 + 1.422 + // blend with color 1.423 + tmp = (color - dev_lo) * vmovl_u16(valpha_lo); 1.424 + tmp = vshrq_n_u32(tmp, 5); 1.425 + dev_lo += tmp; 1.426 + 1.427 + tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi)); 1.428 + tmp = vshrq_n_u32(tmp, 5); 1.429 + dev_hi += tmp; 1.430 + 1.431 + // re-compact 1.432 + wn1 = dev_lo & vmask_ng16; 1.433 + wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16; 1.434 + odev_lo = vmovn_u32(wn1 | wn2); 1.435 + 1.436 + wn1 = dev_hi & vmask_ng16; 1.437 + wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16; 1.438 + odev_hi = vmovn_u32(wn1 | wn2); 1.439 + 1.440 + // store 1.441 + vst1q_u16(device, vcombine_u16(odev_lo, odev_hi)); 1.442 + 1.443 + device += UNROLL; 1.444 + alpha += UNROLL; 1.445 + w -= UNROLL; 1.446 + } while (w >= UNROLL); 1.447 + } 1.448 + 1.449 + // residuals 1.450 + while (w > 0) { 1.451 + *device = blend_compact(expanded32, SkExpand_rgb_16(*device), 1.452 + SkAlpha255To256(*alpha++) >> 3); 1.453 + device += 1; 1.454 + --w; 1.455 + } 1.456 + device = (uint16_t*)((char*)device + deviceRB); 1.457 + alpha += maskRB; 1.458 + } while (--height != 0); 1.459 +#undef UNROLL 1.460 +#else // non-neon code 1.461 + do { 1.462 + int w = width; 1.463 + do { 1.464 + *device = blend_compact(expanded32, SkExpand_rgb_16(*device), 1.465 + SkAlpha255To256(*alpha++) >> 3); 1.466 + device += 1; 1.467 + } while (--w != 0); 1.468 + device = (uint16_t*)((char*)device + deviceRB); 1.469 + alpha += maskRB; 1.470 + } while (--height != 0); 1.471 +#endif 1.472 +} 1.473 + 1.474 +void SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 1.475 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.476 + size_t deviceRB = fDevice.rowBytes(); 1.477 + 1.478 + // TODO: respect fDoDither 1.479 + unsigned scale5 = SkAlpha255To256(alpha) >> 3; 1.480 + uint32_t src32 = fExpandedRaw16 * scale5; 1.481 + scale5 = 32 - scale5; 1.482 + do { 1.483 + uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 1.484 + *device = SkCompact_rgb_16((src32 + dst32) >> 5); 1.485 + device = (uint16_t*)((char*)device + deviceRB); 1.486 + } while (--height != 0); 1.487 +} 1.488 + 1.489 +void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) { 1.490 + SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height()); 1.491 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.492 + size_t deviceRB = fDevice.rowBytes(); 1.493 + uint16_t color16 = fColor16; 1.494 + 1.495 + if (fDoDither) { 1.496 + uint16_t ditherColor = fRawDither16; 1.497 + if ((x ^ y) & 1) { 1.498 + SkTSwap(ditherColor, color16); 1.499 + } 1.500 + while (--height >= 0) { 1.501 + sk_dither_memset16(device, color16, ditherColor, width); 1.502 + SkTSwap(ditherColor, color16); 1.503 + device = (uint16_t*)((char*)device + deviceRB); 1.504 + } 1.505 + } else { // no dither 1.506 + while (--height >= 0) { 1.507 + sk_memset16(device, color16, width); 1.508 + device = (uint16_t*)((char*)device + deviceRB); 1.509 + } 1.510 + } 1.511 +} 1.512 + 1.513 +/////////////////////////////////////////////////////////////////////////////// 1.514 + 1.515 +SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint) 1.516 + : INHERITED(device) { 1.517 + SkColor color = paint.getColor(); 1.518 + 1.519 + fSrcColor32 = SkPreMultiplyColor(color); 1.520 + fScale = SkAlpha255To256(SkColorGetA(color)); 1.521 + 1.522 + int r = SkColorGetR(color); 1.523 + int g = SkColorGetG(color); 1.524 + int b = SkColorGetB(color); 1.525 + 1.526 + fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b); 1.527 + // if we're dithered, use fRawDither16 to hold that. 1.528 + if ((fDoDither = paint.isDither()) != false) { 1.529 + fRawDither16 = SkDitherPack888ToRGB16(r, g, b); 1.530 + } 1.531 + 1.532 + fExpandedRaw16 = SkExpand_rgb_16(fRawColor16); 1.533 + 1.534 + fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS), 1.535 + SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS), 1.536 + SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS)); 1.537 +} 1.538 + 1.539 +const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) { 1.540 + if (!fDoDither && 256 == fScale) { 1.541 + *value = fRawColor16; 1.542 + return &fDevice; 1.543 + } 1.544 + return NULL; 1.545 +} 1.546 + 1.547 +static uint32_t pmcolor_to_expand16(SkPMColor c) { 1.548 + unsigned r = SkGetPackedR32(c); 1.549 + unsigned g = SkGetPackedG32(c); 1.550 + unsigned b = SkGetPackedB32(c); 1.551 + return (g << 24) | (r << 13) | (b << 2); 1.552 +} 1.553 + 1.554 +static inline void blend32_16_row(SkPMColor src, uint16_t dst[], int count) { 1.555 + SkASSERT(count > 0); 1.556 + uint32_t src_expand = pmcolor_to_expand16(src); 1.557 + unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3; 1.558 + do { 1.559 + uint32_t dst_expand = SkExpand_rgb_16(*dst) * scale; 1.560 + *dst = SkCompact_rgb_16((src_expand + dst_expand) >> 5); 1.561 + dst += 1; 1.562 + } while (--count != 0); 1.563 +} 1.564 + 1.565 +void SkRGB16_Blitter::blitH(int x, int y, int width) { 1.566 + SkASSERT(width > 0); 1.567 + SkASSERT(x + width <= fDevice.width()); 1.568 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.569 + 1.570 + // TODO: respect fDoDither 1.571 + blend32_16_row(fSrcColor32, device, width); 1.572 +} 1.573 + 1.574 +void SkRGB16_Blitter::blitAntiH(int x, int y, 1.575 + const SkAlpha* SK_RESTRICT antialias, 1.576 + const int16_t* SK_RESTRICT runs) { 1.577 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.578 + uint32_t srcExpanded = fExpandedRaw16; 1.579 + unsigned scale = fScale; 1.580 + 1.581 + // TODO: respect fDoDither 1.582 + for (;;) { 1.583 + int count = runs[0]; 1.584 + SkASSERT(count >= 0); 1.585 + if (count <= 0) { 1.586 + return; 1.587 + } 1.588 + runs += count; 1.589 + 1.590 + unsigned aa = antialias[0]; 1.591 + antialias += count; 1.592 + if (aa) { 1.593 + unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3); 1.594 + uint32_t src32 = srcExpanded * scale5; 1.595 + scale5 = 32 - scale5; 1.596 + do { 1.597 + uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 1.598 + *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 1.599 + } while (--count != 0); 1.600 + continue; 1.601 + } 1.602 + device += count; 1.603 + } 1.604 +} 1.605 + 1.606 +static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale, 1.607 + U16CPU srcColor) { 1.608 + if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale); 1.609 + if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale); 1.610 + if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale); 1.611 + if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale); 1.612 + if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale); 1.613 + if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale); 1.614 + if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale); 1.615 + if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale); 1.616 +} 1.617 + 1.618 +#define SK_BLITBWMASK_NAME SkRGB16_BlendBW 1.619 +#define SK_BLITBWMASK_ARGS , unsigned dst_scale, U16CPU src_color 1.620 +#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, dst_scale, src_color) 1.621 +#define SK_BLITBWMASK_GETADDR getAddr16 1.622 +#define SK_BLITBWMASK_DEVTYPE uint16_t 1.623 +#include "SkBlitBWMaskTemplate.h" 1.624 + 1.625 +void SkRGB16_Blitter::blitMask(const SkMask& mask, 1.626 + const SkIRect& clip) { 1.627 + if (mask.fFormat == SkMask::kBW_Format) { 1.628 + SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16); 1.629 + return; 1.630 + } 1.631 + 1.632 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 1.633 + const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop); 1.634 + int width = clip.width(); 1.635 + int height = clip.height(); 1.636 + size_t deviceRB = fDevice.rowBytes() - (width << 1); 1.637 + unsigned maskRB = mask.fRowBytes - width; 1.638 + uint32_t color32 = fExpandedRaw16; 1.639 + 1.640 + unsigned scale256 = fScale; 1.641 + do { 1.642 + int w = width; 1.643 + do { 1.644 + unsigned aa = *alpha++; 1.645 + unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3); 1.646 + uint32_t src32 = color32 * scale; 1.647 + uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale); 1.648 + *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 1.649 + } while (--w != 0); 1.650 + device = (uint16_t*)((char*)device + deviceRB); 1.651 + alpha += maskRB; 1.652 + } while (--height != 0); 1.653 +} 1.654 + 1.655 +void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 1.656 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.657 + size_t deviceRB = fDevice.rowBytes(); 1.658 + 1.659 + // TODO: respect fDoDither 1.660 + unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3); 1.661 + uint32_t src32 = fExpandedRaw16 * scale5; 1.662 + scale5 = 32 - scale5; 1.663 + do { 1.664 + uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 1.665 + *device = SkCompact_rgb_16((src32 + dst32) >> 5); 1.666 + device = (uint16_t*)((char*)device + deviceRB); 1.667 + } while (--height != 0); 1.668 +} 1.669 + 1.670 +void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) { 1.671 + SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height()); 1.672 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.673 + size_t deviceRB = fDevice.rowBytes(); 1.674 + SkPMColor src32 = fSrcColor32; 1.675 + 1.676 + while (--height >= 0) { 1.677 + blend32_16_row(src32, device, width); 1.678 + device = (uint16_t*)((char*)device + deviceRB); 1.679 + } 1.680 +} 1.681 + 1.682 +/////////////////////////////////////////////////////////////////////////////// 1.683 + 1.684 +SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device, 1.685 + const SkPaint& paint) 1.686 + : SkRGB16_Shader_Blitter(device, paint) { 1.687 + SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags)); 1.688 +} 1.689 + 1.690 +void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) { 1.691 + SkASSERT(x + width <= fDevice.width()); 1.692 + 1.693 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.694 + SkShader* shader = fShader; 1.695 + 1.696 + int alpha = shader->getSpan16Alpha(); 1.697 + if (0xFF == alpha) { 1.698 + shader->shadeSpan16(x, y, device, width); 1.699 + } else { 1.700 + uint16_t* span16 = (uint16_t*)fBuffer; 1.701 + shader->shadeSpan16(x, y, span16, width); 1.702 + SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width); 1.703 + } 1.704 +} 1.705 + 1.706 +void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) { 1.707 + SkShader* shader = fShader; 1.708 + uint16_t* dst = fDevice.getAddr16(x, y); 1.709 + size_t dstRB = fDevice.rowBytes(); 1.710 + int alpha = shader->getSpan16Alpha(); 1.711 + 1.712 + if (0xFF == alpha) { 1.713 + if (fShaderFlags & SkShader::kConstInY16_Flag) { 1.714 + // have the shader blit directly into the device the first time 1.715 + shader->shadeSpan16(x, y, dst, width); 1.716 + // and now just memcpy that line on the subsequent lines 1.717 + if (--height > 0) { 1.718 + const uint16_t* orig = dst; 1.719 + do { 1.720 + dst = (uint16_t*)((char*)dst + dstRB); 1.721 + memcpy(dst, orig, width << 1); 1.722 + } while (--height); 1.723 + } 1.724 + } else { // need to call shadeSpan16 for every line 1.725 + do { 1.726 + shader->shadeSpan16(x, y, dst, width); 1.727 + y += 1; 1.728 + dst = (uint16_t*)((char*)dst + dstRB); 1.729 + } while (--height); 1.730 + } 1.731 + } else { 1.732 + int scale = SkAlpha255To256(alpha); 1.733 + uint16_t* span16 = (uint16_t*)fBuffer; 1.734 + if (fShaderFlags & SkShader::kConstInY16_Flag) { 1.735 + shader->shadeSpan16(x, y, span16, width); 1.736 + do { 1.737 + SkBlendRGB16(span16, dst, scale, width); 1.738 + dst = (uint16_t*)((char*)dst + dstRB); 1.739 + } while (--height); 1.740 + } else { 1.741 + do { 1.742 + shader->shadeSpan16(x, y, span16, width); 1.743 + SkBlendRGB16(span16, dst, scale, width); 1.744 + y += 1; 1.745 + dst = (uint16_t*)((char*)dst + dstRB); 1.746 + } while (--height); 1.747 + } 1.748 + } 1.749 +} 1.750 + 1.751 +void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y, 1.752 + const SkAlpha* SK_RESTRICT antialias, 1.753 + const int16_t* SK_RESTRICT runs) { 1.754 + SkShader* shader = fShader; 1.755 + SkPMColor* SK_RESTRICT span = fBuffer; 1.756 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.757 + 1.758 + int alpha = shader->getSpan16Alpha(); 1.759 + uint16_t* span16 = (uint16_t*)span; 1.760 + 1.761 + if (0xFF == alpha) { 1.762 + for (;;) { 1.763 + int count = *runs; 1.764 + if (count <= 0) { 1.765 + break; 1.766 + } 1.767 + SkASSERT(count <= fDevice.width()); // don't overrun fBuffer 1.768 + 1.769 + int aa = *antialias; 1.770 + if (aa == 255) { 1.771 + // go direct to the device! 1.772 + shader->shadeSpan16(x, y, device, count); 1.773 + } else if (aa) { 1.774 + shader->shadeSpan16(x, y, span16, count); 1.775 + SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); 1.776 + } 1.777 + device += count; 1.778 + runs += count; 1.779 + antialias += count; 1.780 + x += count; 1.781 + } 1.782 + } else { // span alpha is < 255 1.783 + alpha = SkAlpha255To256(alpha); 1.784 + for (;;) { 1.785 + int count = *runs; 1.786 + if (count <= 0) { 1.787 + break; 1.788 + } 1.789 + SkASSERT(count <= fDevice.width()); // don't overrun fBuffer 1.790 + 1.791 + int aa = SkAlphaMul(*antialias, alpha); 1.792 + if (aa) { 1.793 + shader->shadeSpan16(x, y, span16, count); 1.794 + SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); 1.795 + } 1.796 + 1.797 + device += count; 1.798 + runs += count; 1.799 + antialias += count; 1.800 + x += count; 1.801 + } 1.802 + } 1.803 +} 1.804 + 1.805 +/////////////////////////////////////////////////////////////////////////////// 1.806 + 1.807 +SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device, 1.808 + const SkPaint& paint) 1.809 +: INHERITED(device, paint) { 1.810 + SkASSERT(paint.getXfermode() == NULL); 1.811 + 1.812 + fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor)); 1.813 + 1.814 + // compute SkBlitRow::Procs 1.815 + unsigned flags = 0; 1.816 + 1.817 + uint32_t shaderFlags = fShaderFlags; 1.818 + // shaders take care of global alpha, so we never set it in SkBlitRow 1.819 + if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) { 1.820 + flags |= SkBlitRow::kSrcPixelAlpha_Flag; 1.821 + } 1.822 + // don't dither if the shader is really 16bit 1.823 + if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) { 1.824 + flags |= SkBlitRow::kDither_Flag; 1.825 + } 1.826 + // used when we know our global alpha is 0xFF 1.827 + fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config); 1.828 + // used when we know our global alpha is < 0xFF 1.829 + fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag, 1.830 + SkBitmap::kRGB_565_Config); 1.831 +} 1.832 + 1.833 +SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() { 1.834 + sk_free(fBuffer); 1.835 +} 1.836 + 1.837 +void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) { 1.838 + SkASSERT(x + width <= fDevice.width()); 1.839 + 1.840 + fShader->shadeSpan(x, y, fBuffer, width); 1.841 + // shaders take care of global alpha, so we pass 0xFF (should be ignored) 1.842 + fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y); 1.843 +} 1.844 + 1.845 +void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) { 1.846 + SkShader* shader = fShader; 1.847 + SkBlitRow::Proc proc = fOpaqueProc; 1.848 + SkPMColor* buffer = fBuffer; 1.849 + uint16_t* dst = fDevice.getAddr16(x, y); 1.850 + size_t dstRB = fDevice.rowBytes(); 1.851 + 1.852 + if (fShaderFlags & SkShader::kConstInY32_Flag) { 1.853 + shader->shadeSpan(x, y, buffer, width); 1.854 + do { 1.855 + proc(dst, buffer, width, 0xFF, x, y); 1.856 + y += 1; 1.857 + dst = (uint16_t*)((char*)dst + dstRB); 1.858 + } while (--height); 1.859 + } else { 1.860 + do { 1.861 + shader->shadeSpan(x, y, buffer, width); 1.862 + proc(dst, buffer, width, 0xFF, x, y); 1.863 + y += 1; 1.864 + dst = (uint16_t*)((char*)dst + dstRB); 1.865 + } while (--height); 1.866 + } 1.867 +} 1.868 + 1.869 +static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) { 1.870 + int count = 0; 1.871 + for (;;) { 1.872 + int n = *runs; 1.873 + if (n == 0 || *aa == 0) { 1.874 + break; 1.875 + } 1.876 + runs += n; 1.877 + aa += n; 1.878 + count += n; 1.879 + } 1.880 + return count; 1.881 +} 1.882 + 1.883 +void SkRGB16_Shader_Blitter::blitAntiH(int x, int y, 1.884 + const SkAlpha* SK_RESTRICT antialias, 1.885 + const int16_t* SK_RESTRICT runs) { 1.886 + SkShader* shader = fShader; 1.887 + SkPMColor* SK_RESTRICT span = fBuffer; 1.888 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.889 + 1.890 + for (;;) { 1.891 + int count = *runs; 1.892 + if (count <= 0) { 1.893 + break; 1.894 + } 1.895 + int aa = *antialias; 1.896 + if (0 == aa) { 1.897 + device += count; 1.898 + runs += count; 1.899 + antialias += count; 1.900 + x += count; 1.901 + continue; 1.902 + } 1.903 + 1.904 + int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count); 1.905 + 1.906 + SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer 1.907 + shader->shadeSpan(x, y, span, nonZeroCount); 1.908 + 1.909 + SkPMColor* localSpan = span; 1.910 + for (;;) { 1.911 + SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc; 1.912 + proc(device, localSpan, count, aa, x, y); 1.913 + 1.914 + x += count; 1.915 + device += count; 1.916 + runs += count; 1.917 + antialias += count; 1.918 + nonZeroCount -= count; 1.919 + if (nonZeroCount == 0) { 1.920 + break; 1.921 + } 1.922 + localSpan += count; 1.923 + SkASSERT(nonZeroCount > 0); 1.924 + count = *runs; 1.925 + SkASSERT(count > 0); 1.926 + aa = *antialias; 1.927 + } 1.928 + } 1.929 +} 1.930 + 1.931 +/////////////////////////////////////////////////////////////////////// 1.932 + 1.933 +SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter( 1.934 + const SkBitmap& device, const SkPaint& paint) 1.935 +: INHERITED(device, paint) { 1.936 + fXfermode = paint.getXfermode(); 1.937 + SkASSERT(fXfermode); 1.938 + fXfermode->ref(); 1.939 + 1.940 + int width = device.width(); 1.941 + fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor)); 1.942 + fAAExpand = (uint8_t*)(fBuffer + width); 1.943 +} 1.944 + 1.945 +SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() { 1.946 + fXfermode->unref(); 1.947 + sk_free(fBuffer); 1.948 +} 1.949 + 1.950 +void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) { 1.951 + SkASSERT(x + width <= fDevice.width()); 1.952 + 1.953 + uint16_t* device = fDevice.getAddr16(x, y); 1.954 + SkPMColor* span = fBuffer; 1.955 + 1.956 + fShader->shadeSpan(x, y, span, width); 1.957 + fXfermode->xfer16(device, span, width, NULL); 1.958 +} 1.959 + 1.960 +void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y, 1.961 + const SkAlpha* SK_RESTRICT antialias, 1.962 + const int16_t* SK_RESTRICT runs) { 1.963 + SkShader* shader = fShader; 1.964 + SkXfermode* mode = fXfermode; 1.965 + SkPMColor* SK_RESTRICT span = fBuffer; 1.966 + uint8_t* SK_RESTRICT aaExpand = fAAExpand; 1.967 + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1.968 + 1.969 + for (;;) { 1.970 + int count = *runs; 1.971 + if (count <= 0) { 1.972 + break; 1.973 + } 1.974 + int aa = *antialias; 1.975 + if (0 == aa) { 1.976 + device += count; 1.977 + runs += count; 1.978 + antialias += count; 1.979 + x += count; 1.980 + continue; 1.981 + } 1.982 + 1.983 + int nonZeroCount = count + count_nonzero_span(runs + count, 1.984 + antialias + count); 1.985 + 1.986 + SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer 1.987 + shader->shadeSpan(x, y, span, nonZeroCount); 1.988 + 1.989 + x += nonZeroCount; 1.990 + SkPMColor* localSpan = span; 1.991 + for (;;) { 1.992 + if (aa == 0xFF) { 1.993 + mode->xfer16(device, localSpan, count, NULL); 1.994 + } else { 1.995 + SkASSERT(aa); 1.996 + memset(aaExpand, aa, count); 1.997 + mode->xfer16(device, localSpan, count, aaExpand); 1.998 + } 1.999 + device += count; 1.1000 + runs += count; 1.1001 + antialias += count; 1.1002 + nonZeroCount -= count; 1.1003 + if (nonZeroCount == 0) { 1.1004 + break; 1.1005 + } 1.1006 + localSpan += count; 1.1007 + SkASSERT(nonZeroCount > 0); 1.1008 + count = *runs; 1.1009 + SkASSERT(count > 0); 1.1010 + aa = *antialias; 1.1011 + } 1.1012 + } 1.1013 +} 1.1014 + 1.1015 +/////////////////////////////////////////////////////////////////////////////// 1.1016 + 1.1017 +SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint, 1.1018 + SkTBlitterAllocator* allocator) { 1.1019 + SkASSERT(allocator != NULL); 1.1020 + 1.1021 + SkBlitter* blitter; 1.1022 + SkShader* shader = paint.getShader(); 1.1023 + SkXfermode* mode = paint.getXfermode(); 1.1024 + 1.1025 + // we require a shader if there is an xfermode, handled by our caller 1.1026 + SkASSERT(NULL == mode || NULL != shader); 1.1027 + 1.1028 + if (shader) { 1.1029 + if (mode) { 1.1030 + blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint); 1.1031 + } else if (shader->canCallShadeSpan16()) { 1.1032 + blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint); 1.1033 + } else { 1.1034 + blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint); 1.1035 + } 1.1036 + } else { 1.1037 + // no shader, no xfermode, (and we always ignore colorfilter) 1.1038 + SkColor color = paint.getColor(); 1.1039 + if (0 == SkColorGetA(color)) { 1.1040 + blitter = allocator->createT<SkNullBlitter>(); 1.1041 +#ifdef USE_BLACK_BLITTER 1.1042 + } else if (SK_ColorBLACK == color) { 1.1043 + blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint); 1.1044 +#endif 1.1045 + } else if (0xFF == SkColorGetA(color)) { 1.1046 + blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint); 1.1047 + } else { 1.1048 + blitter = allocator->createT<SkRGB16_Blitter>(device, paint); 1.1049 + } 1.1050 + } 1.1051 + 1.1052 + return blitter; 1.1053 +}