1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkCoreBlitters.h" 11 #include "SkColorPriv.h" 12 #include "SkShader.h" 13 #include "SkXfermode.h" 14 15 SkA8_Blitter::SkA8_Blitter(const SkPixmap& device, const SkPaint& paint) : INHERITED(device) { 16 fSrcA = paint.getAlpha(); 17 } 18 19 const SkPixmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) { 20 if (255 == fSrcA) { 21 *value = 255; 22 return &fDevice; 23 } 24 return nullptr; 25 } 26 27 void SkA8_Blitter::blitH(int x, int y, int width) { 28 SkASSERT(x >= 0 && y >= 0 && 29 (unsigned)(x + width) <= (unsigned)fDevice.width()); 30 31 if (fSrcA == 0) { 32 return; 33 } 34 35 uint8_t* device = fDevice.writable_addr8(x, y); 36 37 if (fSrcA == 255) { 38 memset(device, 0xFF, width); 39 } else { 40 unsigned scale = 256 - SkAlpha255To256(fSrcA); 41 unsigned srcA = fSrcA; 42 43 for (int i = 0; i < width; i++) { 44 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 45 } 46 } 47 } 48 49 void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 50 const int16_t runs[]) { 51 if (fSrcA == 0) { 52 return; 53 } 54 55 uint8_t* device = fDevice.writable_addr8(x, y); 56 unsigned srcA = fSrcA; 57 58 for (;;) { 59 int count = runs[0]; 60 SkASSERT(count >= 0); 61 if (count == 0) { 62 return; 63 } 64 unsigned aa = antialias[0]; 65 66 if (aa == 255 && srcA == 255) { 67 memset(device, 0xFF, count); 68 } else { 69 unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); 70 unsigned scale = 256 - sa; 71 72 for (int i = 0; i < count; i++) { 73 device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); 74 } 75 } 76 runs += count; 77 antialias += count; 78 device += count; 79 } 80 } 81 82 ///////////////////////////////////////////////////////////////////////////////////// 83 84 #define solid_8_pixels(mask, dst) \ 85 do { \ 86 if (mask & 0x80) dst[0] = 0xFF; \ 87 if (mask & 0x40) dst[1] = 0xFF; \ 88 if (mask & 0x20) dst[2] = 0xFF; \ 89 if (mask & 0x10) dst[3] = 0xFF; \ 90 if (mask & 0x08) dst[4] = 0xFF; \ 91 if (mask & 0x04) dst[5] = 0xFF; \ 92 if (mask & 0x02) dst[6] = 0xFF; \ 93 if (mask & 0x01) dst[7] = 0xFF; \ 94 } while (0) 95 96 #define SK_BLITBWMASK_NAME SkA8_BlitBW 97 #define SK_BLITBWMASK_ARGS 98 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst) 99 #define SK_BLITBWMASK_GETADDR writable_addr8 100 #define SK_BLITBWMASK_DEVTYPE uint8_t 101 #include "SkBlitBWMaskTemplate.h" 102 103 static inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa, 104 unsigned dst_scale) { 105 if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale)); 106 if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale)); 107 if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale)); 108 if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale)); 109 if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale)); 110 if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale)); 111 if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale)); 112 if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale)); 113 } 114 115 #define SK_BLITBWMASK_NAME SkA8_BlendBW 116 #define SK_BLITBWMASK_ARGS , U8CPU sa, unsigned dst_scale 117 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sa, dst_scale) 118 #define SK_BLITBWMASK_GETADDR writable_addr8 119 #define SK_BLITBWMASK_DEVTYPE uint8_t 120 #include "SkBlitBWMaskTemplate.h" 121 122 void SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 123 if (fSrcA == 0) { 124 return; 125 } 126 127 if (mask.fFormat == SkMask::kBW_Format) { 128 if (fSrcA == 0xFF) { 129 SkA8_BlitBW(fDevice, mask, clip); 130 } else { 131 SkA8_BlendBW(fDevice, mask, clip, fSrcA, 132 SkAlpha255To256(255 - fSrcA)); 133 } 134 return; 135 } 136 137 int x = clip.fLeft; 138 int y = clip.fTop; 139 int width = clip.width(); 140 int height = clip.height(); 141 uint8_t* device = fDevice.writable_addr8(x, y); 142 const uint8_t* alpha = mask.getAddr8(x, y); 143 unsigned srcA = fSrcA; 144 145 while (--height >= 0) { 146 for (int i = width - 1; i >= 0; --i) { 147 unsigned sa; 148 // scale our src by the alpha value 149 { 150 int aa = alpha[i]; 151 if (aa == 0) { 152 continue; 153 } 154 if (aa == 255) { 155 if (srcA == 255) { 156 device[i] = 0xFF; 157 continue; 158 } 159 sa = srcA; 160 } else { 161 sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); 162 } 163 } 164 165 int scale = 256 - SkAlpha255To256(sa); 166 device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); 167 } 168 device += fDevice.rowBytes(); 169 alpha += mask.fRowBytes; 170 } 171 } 172 173 /////////////////////////////////////////////////////////////////////////////// 174 175 void SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 176 if (fSrcA == 0) { 177 return; 178 } 179 180 unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha)); 181 uint8_t* device = fDevice.writable_addr8(x, y); 182 size_t rowBytes = fDevice.rowBytes(); 183 184 if (sa == 0xFF) { 185 for (int i = 0; i < height; i++) { 186 *device = SkToU8(sa); 187 device += rowBytes; 188 } 189 } else { 190 unsigned scale = 256 - SkAlpha255To256(sa); 191 192 for (int i = 0; i < height; i++) { 193 *device = SkToU8(sa + SkAlphaMul(*device, scale)); 194 device += rowBytes; 195 } 196 } 197 } 198 199 void SkA8_Blitter::blitRect(int x, int y, int width, int height) { 200 SkASSERT(x >= 0 && y >= 0 && 201 (unsigned)(x + width) <= (unsigned)fDevice.width() && 202 (unsigned)(y + height) <= (unsigned)fDevice.height()); 203 204 if (fSrcA == 0) { 205 return; 206 } 207 208 uint8_t* device = fDevice.writable_addr8(x, y); 209 unsigned srcA = fSrcA; 210 211 if (srcA == 255) { 212 while (--height >= 0) { 213 memset(device, 0xFF, width); 214 device += fDevice.rowBytes(); 215 } 216 } else { 217 unsigned scale = 256 - SkAlpha255To256(srcA); 218 219 while (--height >= 0) { 220 for (int i = 0; i < width; i++) { 221 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 222 } 223 device += fDevice.rowBytes(); 224 } 225 } 226 } 227 228 /////////////////////////////////////////////////////////////////////// 229 230 SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkPixmap& device, const SkPaint& paint, 231 SkShader::Context* shaderContext) 232 : INHERITED(device, paint, shaderContext) 233 { 234 if ((fXfermode = paint.getXfermode()) != nullptr) { 235 fXfermode->ref(); 236 SkASSERT(fShaderContext); 237 } 238 239 int width = device.width(); 240 fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2))); 241 fAAExpand = (uint8_t*)(fBuffer + width); 242 } 243 244 SkA8_Shader_Blitter::~SkA8_Shader_Blitter() { 245 if (fXfermode) SkSafeUnref(fXfermode); 246 sk_free(fBuffer); 247 } 248 249 void SkA8_Shader_Blitter::blitH(int x, int y, int width) { 250 SkASSERT(x >= 0 && y >= 0 && 251 (unsigned)(x + width) <= (unsigned)fDevice.width()); 252 253 uint8_t* device = fDevice.writable_addr8(x, y); 254 SkShader::Context* shaderContext = fShaderContext; 255 256 if ((shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) { 257 memset(device, 0xFF, width); 258 } else { 259 SkPMColor* span = fBuffer; 260 261 shaderContext->shadeSpan(x, y, span, width); 262 if (fXfermode) { 263 fXfermode->xferA8(device, span, width, nullptr); 264 } else { 265 for (int i = width - 1; i >= 0; --i) { 266 unsigned srcA = SkGetPackedA32(span[i]); 267 unsigned scale = 256 - SkAlpha255To256(srcA); 268 269 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 270 } 271 } 272 } 273 } 274 275 static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) { 276 SkASSERT((unsigned)aa <= 255); 277 278 int src_scale = SkAlpha255To256(aa); 279 int sa = SkGetPackedA32(src); 280 int dst_scale = 256 - SkAlphaMul(sa, src_scale); 281 282 return SkToU8((sa * src_scale + da * dst_scale) >> 8); 283 } 284 285 void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 286 const int16_t runs[]) { 287 SkShader::Context* shaderContext = fShaderContext; 288 SkXfermode* mode = fXfermode; 289 uint8_t* aaExpand = fAAExpand; 290 SkPMColor* span = fBuffer; 291 uint8_t* device = fDevice.writable_addr8(x, y); 292 int opaque = shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag; 293 294 for (;;) { 295 int count = *runs; 296 if (count == 0) { 297 break; 298 } 299 int aa = *antialias; 300 if (aa) { 301 if (opaque && aa == 255 && mode == nullptr) { 302 memset(device, 0xFF, count); 303 } else { 304 shaderContext->shadeSpan(x, y, span, count); 305 if (mode) { 306 memset(aaExpand, aa, count); 307 mode->xferA8(device, span, count, aaExpand); 308 } else { 309 for (int i = count - 1; i >= 0; --i) { 310 device[i] = aa_blend8(span[i], device[i], aa); 311 } 312 } 313 } 314 } 315 device += count; 316 runs += count; 317 antialias += count; 318 x += count; 319 } 320 } 321 322 void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 323 if (mask.fFormat == SkMask::kBW_Format) { 324 this->INHERITED::blitMask(mask, clip); 325 return; 326 } 327 328 int x = clip.fLeft; 329 int y = clip.fTop; 330 int width = clip.width(); 331 int height = clip.height(); 332 uint8_t* device = fDevice.writable_addr8(x, y); 333 const uint8_t* alpha = mask.getAddr8(x, y); 334 SkShader::Context* shaderContext = fShaderContext; 335 336 SkPMColor* span = fBuffer; 337 338 while (--height >= 0) { 339 shaderContext->shadeSpan(x, y, span, width); 340 if (fXfermode) { 341 fXfermode->xferA8(device, span, width, alpha); 342 } else { 343 for (int i = width - 1; i >= 0; --i) { 344 device[i] = aa_blend8(span[i], device[i], alpha[i]); 345 } 346 } 347 348 y += 1; 349 device += fDevice.rowBytes(); 350 alpha += mask.fRowBytes; 351 } 352 } 353 354 /////////////////////////////////////////////////////////////////////////////// 355 356 SkA8_Coverage_Blitter::SkA8_Coverage_Blitter(const SkPixmap& device, 357 const SkPaint& paint) : SkRasterBlitter(device) { 358 SkASSERT(nullptr == paint.getShader()); 359 SkASSERT(nullptr == paint.getXfermode()); 360 SkASSERT(nullptr == paint.getColorFilter()); 361 } 362 363 void SkA8_Coverage_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 364 const int16_t runs[]) { 365 uint8_t* device = fDevice.writable_addr8(x, y); 366 SkDEBUGCODE(int totalCount = 0;) 367 368 for (;;) { 369 int count = runs[0]; 370 SkASSERT(count >= 0); 371 if (count == 0) { 372 return; 373 } 374 if (antialias[0]) { 375 memset(device, antialias[0], count); 376 } 377 runs += count; 378 antialias += count; 379 device += count; 380 381 SkDEBUGCODE(totalCount += count;) 382 } 383 SkASSERT(fDevice.width() == totalCount); 384 } 385 386 void SkA8_Coverage_Blitter::blitH(int x, int y, int width) { 387 memset(fDevice.writable_addr8(x, y), 0xFF, width); 388 } 389 390 void SkA8_Coverage_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 391 if (0 == alpha) { 392 return; 393 } 394 395 uint8_t* dst = fDevice.writable_addr8(x, y); 396 const size_t dstRB = fDevice.rowBytes(); 397 while (--height >= 0) { 398 *dst = alpha; 399 dst += dstRB; 400 } 401 } 402 403 void SkA8_Coverage_Blitter::blitRect(int x, int y, int width, int height) { 404 uint8_t* dst = fDevice.writable_addr8(x, y); 405 const size_t dstRB = fDevice.rowBytes(); 406 while (--height >= 0) { 407 memset(dst, 0xFF, width); 408 dst += dstRB; 409 } 410 } 411 412 void SkA8_Coverage_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 413 SkASSERT(SkMask::kA8_Format == mask.fFormat); 414 415 int x = clip.fLeft; 416 int y = clip.fTop; 417 int width = clip.width(); 418 int height = clip.height(); 419 420 uint8_t* dst = fDevice.writable_addr8(x, y); 421 const uint8_t* src = mask.getAddr8(x, y); 422 const size_t srcRB = mask.fRowBytes; 423 const size_t dstRB = fDevice.rowBytes(); 424 425 while (--height >= 0) { 426 memcpy(dst, src, width); 427 dst += dstRB; 428 src += srcRB; 429 } 430 } 431 432 const SkPixmap* SkA8_Coverage_Blitter::justAnOpaqueColor(uint32_t*) { 433 return nullptr; 434 } 435