1 /* libs/graphics/sgl/SkBlitter_ARGB32.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #include "SkCoreBlitters.h" 19 #include "SkColorPriv.h" 20 #include "SkShader.h" 21 #include "SkUtils.h" 22 #include "SkXfermode.h" 23 24 #if defined(SK_SUPPORT_LCDTEXT) 25 namespace skia_blitter_support { 26 // subpixel helper functions from SkBlitter_ARGB32_Subpixel.cpp 27 uint32_t* adjustForSubpixelClip(const SkMask& mask, 28 const SkIRect& clip, const SkBitmap& device, 29 int* widthAdjustment, int* heightAdjustment, 30 const uint32_t** alpha32); 31 extern uint32_t BlendLCDPixelWithColor(const uint32_t alphaPixel, const uint32_t originalPixel, 32 const uint32_t sourcePixel); 33 extern uint32_t BlendLCDPixelWithOpaqueColor(const uint32_t alphaPixel, const uint32_t originalPixel, 34 const uint32_t sourcePixel); 35 extern uint32_t BlendLCDPixelWithBlack(const uint32_t alphaPixel, const uint32_t originalPixel); 36 } 37 38 using namespace skia_blitter_support; 39 #endif 40 41 ////////////////////////////////////////////////////////////////////////////////////// 42 43 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint) 44 : INHERITED(device) { 45 uint32_t color = paint.getColor(); 46 47 fSrcA = SkColorGetA(color); 48 unsigned scale = SkAlpha255To256(fSrcA); 49 fSrcR = SkAlphaMul(SkColorGetR(color), scale); 50 fSrcG = SkAlphaMul(SkColorGetG(color), scale); 51 fSrcB = SkAlphaMul(SkColorGetB(color), scale); 52 53 fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB); 54 } 55 56 const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) { 57 if (255 == fSrcA) { 58 *value = fPMColor; 59 return &fDevice; 60 } 61 return NULL; 62 } 63 64 #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 65 #pragma warning ( push ) 66 #pragma warning ( disable : 4701 ) 67 #endif 68 69 void SkARGB32_Blitter::blitH(int x, int y, int width) { 70 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 71 72 SkBlitRow::Color32(fDevice.getAddr32(x, y), width, fPMColor); 73 } 74 75 void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 76 const int16_t runs[]) { 77 if (fSrcA == 0) { 78 return; 79 } 80 81 uint32_t color = fPMColor; 82 uint32_t* device = fDevice.getAddr32(x, y); 83 unsigned opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case 84 85 for (;;) { 86 int count = runs[0]; 87 SkASSERT(count >= 0); 88 if (count <= 0) { 89 return; 90 } 91 unsigned aa = antialias[0]; 92 if (aa) { 93 if ((opaqueMask & aa) == 255) { 94 sk_memset32(device, color, count); 95 } else { 96 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa)); 97 SkBlitRow::Color32(device, count, sc); 98 } 99 } 100 runs += count; 101 antialias += count; 102 device += count; 103 } 104 } 105 106 ////////////////////////////////////////////////////////////////////////////////////// 107 108 #define solid_8_pixels(mask, dst, color) \ 109 do { \ 110 if (mask & 0x80) dst[0] = color; \ 111 if (mask & 0x40) dst[1] = color; \ 112 if (mask & 0x20) dst[2] = color; \ 113 if (mask & 0x10) dst[3] = color; \ 114 if (mask & 0x08) dst[4] = color; \ 115 if (mask & 0x04) dst[5] = color; \ 116 if (mask & 0x02) dst[6] = color; \ 117 if (mask & 0x01) dst[7] = color; \ 118 } while (0) 119 120 #define SK_BLITBWMASK_NAME SkARGB32_BlitBW 121 #define SK_BLITBWMASK_ARGS , SkPMColor color 122 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) 123 #define SK_BLITBWMASK_GETADDR getAddr32 124 #define SK_BLITBWMASK_DEVTYPE uint32_t 125 #include "SkBlitBWMaskTemplate.h" 126 127 #define blend_8_pixels(mask, dst, sc, dst_scale) \ 128 do { \ 129 if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); } \ 130 if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); } \ 131 if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); } \ 132 if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); } \ 133 if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); } \ 134 if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); } \ 135 if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); } \ 136 if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); } \ 137 } while (0) 138 139 #define SK_BLITBWMASK_NAME SkARGB32_BlendBW 140 #define SK_BLITBWMASK_ARGS , uint32_t sc, unsigned dst_scale 141 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale) 142 #define SK_BLITBWMASK_GETADDR getAddr32 143 #define SK_BLITBWMASK_DEVTYPE uint32_t 144 #include "SkBlitBWMaskTemplate.h" 145 146 void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 147 SkASSERT(mask.fBounds.contains(clip)); 148 SkASSERT(fSrcA != 0xFF); 149 150 if (fSrcA == 0) { 151 return; 152 } 153 154 if (mask.fFormat == SkMask::kBW_Format) { 155 SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA)); 156 return; 157 } 158 159 int x = clip.fLeft; 160 int y = clip.fTop; 161 int width = clip.width(); 162 int height = clip.height(); 163 164 uint32_t* device = fDevice.getAddr32(x, y); 165 const uint8_t* alpha = mask.getAddr(x, y); 166 uint32_t srcColor = fPMColor; 167 unsigned devRB = fDevice.rowBytes() - (width << 2); 168 unsigned maskRB = mask.fRowBytes - width; 169 170 do { 171 int w = width; 172 do { 173 unsigned aa = *alpha++; 174 *device = SkBlendARGB32(srcColor, *device, aa); 175 device += 1; 176 } while (--w != 0); 177 device = (uint32_t*)((char*)device + devRB); 178 alpha += maskRB; 179 } while (--height != 0); 180 } 181 182 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask, 183 const SkIRect& clip) { 184 SkASSERT(mask.fBounds.contains(clip)); 185 186 if (mask.fFormat == SkMask::kBW_Format) { 187 SkARGB32_BlitBW(fDevice, mask, clip, fPMColor); 188 return; 189 } 190 191 int x = clip.fLeft; 192 int y = clip.fTop; 193 int width = clip.width(); 194 int height = clip.height(); 195 196 #if defined(SK_SUPPORT_LCDTEXT) 197 const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format; 198 const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format; 199 #endif 200 201 // In LCD mode the masks have either an extra couple of rows or columns on the edges. 202 uint32_t srcColor = fPMColor; 203 204 #if defined(SK_SUPPORT_LCDTEXT) 205 if (lcdMode || verticalLCDMode) { 206 int widthAdjustment, heightAdjustment; 207 const uint32_t* alpha32; 208 uint32_t* device = adjustForSubpixelClip(mask, clip, fDevice, &widthAdjustment, &heightAdjustment, &alpha32); 209 210 width += widthAdjustment; 211 height += heightAdjustment; 212 213 unsigned devRB = fDevice.rowBytes() - (width << 2); 214 unsigned alphaExtraRowWords = mask.rowWordsLCD() - width; 215 216 do { 217 unsigned w = width; 218 do { 219 const uint32_t alphaPixel = *alpha32++; 220 const uint32_t originalPixel = *device; 221 *device++ = BlendLCDPixelWithOpaqueColor(alphaPixel, originalPixel, srcColor); 222 } while (--w != 0); 223 device = (uint32_t*)((char*)device + devRB); 224 alpha32 += alphaExtraRowWords; 225 } while (--height != 0); 226 227 return; 228 } 229 #endif 230 231 uint32_t* device = fDevice.getAddr32(x, y); 232 const uint8_t* alpha = mask.getAddr(x, y); 233 unsigned maskRB = mask.fRowBytes - width; 234 unsigned devRB = fDevice.rowBytes() - (width << 2); 235 do { 236 int w = width; 237 do { 238 unsigned aa = *alpha++; 239 *device = SkAlphaMulQ(srcColor, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa)); 240 device += 1; 241 } while (--w != 0); 242 device = (uint32_t*)((char*)device + devRB); 243 alpha += maskRB; 244 } while (--height != 0); 245 } 246 247 ////////////////////////////////////////////////////////////////////////////////////// 248 249 void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 250 if (alpha == 0 || fSrcA == 0) { 251 return; 252 } 253 254 uint32_t* device = fDevice.getAddr32(x, y); 255 uint32_t color = fPMColor; 256 257 if (alpha != 255) { 258 color = SkAlphaMulQ(color, SkAlpha255To256(alpha)); 259 } 260 261 unsigned dst_scale = 255 - SkGetPackedA32(color); 262 uint32_t prevDst = ~device[0]; 263 uint32_t result SK_INIT_TO_AVOID_WARNING; 264 uint32_t rowBytes = fDevice.rowBytes(); 265 266 while (--height >= 0) { 267 uint32_t dst = device[0]; 268 if (dst != prevDst) { 269 result = color + SkAlphaMulQ(dst, dst_scale); 270 prevDst = dst; 271 } 272 device[0] = result; 273 device = (uint32_t*)((char*)device + rowBytes); 274 } 275 } 276 277 void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) { 278 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height()); 279 280 if (fSrcA == 0) { 281 return; 282 } 283 284 uint32_t* device = fDevice.getAddr32(x, y); 285 uint32_t color = fPMColor; 286 size_t rowBytes = fDevice.rowBytes(); 287 288 while (--height >= 0) { 289 SkBlitRow::Color32(device, width, color); 290 device = (uint32_t*)((char*)device + rowBytes); 291 } 292 } 293 294 #if defined _WIN32 && _MSC_VER >= 1300 295 #pragma warning ( pop ) 296 #endif 297 298 /////////////////////////////////////////////////////////////////////// 299 300 void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 301 SkASSERT(mask.fBounds.contains(clip)); 302 303 if (mask.fFormat == SkMask::kBW_Format) { 304 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); 305 306 SkARGB32_BlitBW(fDevice, mask, clip, black); 307 } else { 308 #if defined(SK_SUPPORT_LCDTEXT) 309 const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format; 310 const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format; 311 #endif 312 313 // In LCD mode the masks have either an extra couple of rows or columns on the edges. 314 unsigned width = clip.width(); 315 unsigned height = clip.height(); 316 317 SkASSERT((int)height > 0); 318 SkASSERT((int)width > 0); 319 320 #if defined(SK_SUPPORT_LCDTEXT) 321 if (lcdMode || verticalLCDMode) { 322 int widthAdjustment, heightAdjustment; 323 const uint32_t* alpha32; 324 uint32_t* device = adjustForSubpixelClip(mask, clip, fDevice, &widthAdjustment, &heightAdjustment, &alpha32); 325 326 width += widthAdjustment; 327 height += heightAdjustment; 328 329 unsigned deviceRB = fDevice.rowBytes() - (width << 2); 330 unsigned alphaExtraRowWords = mask.rowWordsLCD() - width; 331 332 do { 333 unsigned w = width; 334 do { 335 const uint32_t alphaPixel = *alpha32++; 336 const uint32_t originalPixel = *device; 337 *device++ = BlendLCDPixelWithBlack(alphaPixel, originalPixel); 338 } while (--w != 0); 339 device = (uint32_t*)((char*)device + deviceRB); 340 alpha32 += alphaExtraRowWords; 341 } while (--height != 0); 342 343 return; 344 } 345 #endif 346 347 uint32_t* device = fDevice.getAddr32(clip.fLeft, clip.fTop); 348 unsigned maskRB = mask.fRowBytes - width; 349 unsigned deviceRB = fDevice.rowBytes() - (width << 2); 350 const uint8_t* alpha = mask.getAddr(clip.fLeft, clip.fTop); 351 do { 352 unsigned w = width; 353 do { 354 unsigned aa = *alpha++; 355 *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa)); 356 device += 1; 357 } while (--w != 0); 358 device = (uint32_t*)((char*)device + deviceRB); 359 alpha += maskRB; 360 } while (--height != 0); 361 } 362 } 363 364 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 365 const int16_t runs[]) { 366 uint32_t* device = fDevice.getAddr32(x, y); 367 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); 368 369 for (;;) { 370 int count = runs[0]; 371 SkASSERT(count >= 0); 372 if (count <= 0) { 373 return; 374 } 375 unsigned aa = antialias[0]; 376 if (aa) { 377 if (aa == 255) { 378 sk_memset32(device, black, count); 379 } else { 380 SkPMColor src = aa << SK_A32_SHIFT; 381 unsigned dst_scale = 256 - aa; 382 int n = count; 383 do { 384 --n; 385 device[n] = src + SkAlphaMulQ(device[n], dst_scale); 386 } while (n > 0); 387 } 388 } 389 runs += count; 390 antialias += count; 391 device += count; 392 } 393 } 394 395 ////////////////////////////////////////////////////////////////////////////////////////// 396 397 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, 398 const SkPaint& paint) : INHERITED(device, paint) { 399 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); 400 401 fXfermode = paint.getXfermode(); 402 SkSafeRef(fXfermode); 403 404 int flags = 0; 405 if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { 406 flags |= SkBlitRow::kSrcPixelAlpha_Flag32; 407 } 408 // we call this on the output from the shader 409 fProc32 = SkBlitRow::Factory32(flags); 410 // we call this on the output from the shader + alpha from the aa buffer 411 fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32); 412 } 413 414 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() { 415 fXfermode->safeUnref(); 416 sk_free(fBuffer); 417 } 418 419 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) { 420 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 421 422 uint32_t* device = fDevice.getAddr32(x, y); 423 424 if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { 425 fShader->shadeSpan(x, y, device, width); 426 } else { 427 SkPMColor* span = fBuffer; 428 fShader->shadeSpan(x, y, span, width); 429 if (fXfermode) { 430 fXfermode->xfer32(device, span, width, NULL); 431 } else { 432 fProc32(device, span, width, 255); 433 } 434 } 435 } 436 437 /////////////////////////////////////////////////////////////////////////////////////////////// 438 439 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 440 const int16_t runs[]) { 441 SkPMColor* span = fBuffer; 442 uint32_t* device = fDevice.getAddr32(x, y); 443 SkShader* shader = fShader; 444 445 if (fXfermode) { 446 for (;;) { 447 SkXfermode* xfer = fXfermode; 448 449 int count = *runs; 450 if (count <= 0) 451 break; 452 int aa = *antialias; 453 if (aa) { 454 shader->shadeSpan(x, y, span, count); 455 if (aa == 255) { 456 xfer->xfer32(device, span, count, NULL); 457 } else { 458 // count is almost always 1 459 for (int i = count - 1; i >= 0; --i) { 460 xfer->xfer32(&device[i], &span[i], 1, antialias); 461 } 462 } 463 } 464 device += count; 465 runs += count; 466 antialias += count; 467 x += count; 468 } 469 } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { 470 for (;;) { 471 int count = *runs; 472 if (count <= 0) { 473 break; 474 } 475 int aa = *antialias; 476 if (aa) { 477 if (aa == 255) { 478 // cool, have the shader draw right into the device 479 shader->shadeSpan(x, y, device, count); 480 } else { 481 shader->shadeSpan(x, y, span, count); 482 fProc32Blend(device, span, count, aa); 483 } 484 } 485 device += count; 486 runs += count; 487 antialias += count; 488 x += count; 489 } 490 } else { // no xfermode but the shader not opaque 491 for (;;) { 492 int count = *runs; 493 if (count <= 0) { 494 break; 495 } 496 int aa = *antialias; 497 if (aa) { 498 fShader->shadeSpan(x, y, span, count); 499 if (aa == 255) { 500 fProc32(device, span, count, 255); 501 } else { 502 fProc32Blend(device, span, count, aa); 503 } 504 } 505 device += count; 506 runs += count; 507 antialias += count; 508 x += count; 509 } 510 } 511 } 512