gfx/skia/trunk/src/core/SkBlitter.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1
michael@0 2 /*
michael@0 3 * Copyright 2006 The Android Open Source Project
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10 #include "SkBlitter.h"
michael@0 11 #include "SkAntiRun.h"
michael@0 12 #include "SkColor.h"
michael@0 13 #include "SkColorFilter.h"
michael@0 14 #include "SkCoreBlitters.h"
michael@0 15 #include "SkFilterShader.h"
michael@0 16 #include "SkReadBuffer.h"
michael@0 17 #include "SkWriteBuffer.h"
michael@0 18 #include "SkMask.h"
michael@0 19 #include "SkMaskFilter.h"
michael@0 20 #include "SkString.h"
michael@0 21 #include "SkTLazy.h"
michael@0 22 #include "SkUtils.h"
michael@0 23 #include "SkXfermode.h"
michael@0 24
michael@0 25 SkBlitter::~SkBlitter() {}
michael@0 26
michael@0 27 bool SkBlitter::isNullBlitter() const { return false; }
michael@0 28
michael@0 29 const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
michael@0 30 return NULL;
michael@0 31 }
michael@0 32
michael@0 33 void SkBlitter::blitH(int x, int y, int width) {
michael@0 34 SkDEBUGFAIL("unimplemented");
michael@0 35 }
michael@0 36
michael@0 37 void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
michael@0 38 const int16_t runs[]) {
michael@0 39 SkDEBUGFAIL("unimplemented");
michael@0 40 }
michael@0 41
michael@0 42 void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
michael@0 43 if (alpha == 255) {
michael@0 44 this->blitRect(x, y, 1, height);
michael@0 45 } else {
michael@0 46 int16_t runs[2];
michael@0 47 runs[0] = 1;
michael@0 48 runs[1] = 0;
michael@0 49
michael@0 50 while (--height >= 0) {
michael@0 51 this->blitAntiH(x, y++, &alpha, runs);
michael@0 52 }
michael@0 53 }
michael@0 54 }
michael@0 55
michael@0 56 void SkBlitter::blitRect(int x, int y, int width, int height) {
michael@0 57 SkASSERT(width > 0);
michael@0 58 while (--height >= 0) {
michael@0 59 this->blitH(x, y++, width);
michael@0 60 }
michael@0 61 }
michael@0 62
michael@0 63 /// Default implementation doesn't check for any easy optimizations
michael@0 64 /// such as alpha == 0 or 255; also uses blitV(), which some subclasses
michael@0 65 /// may not support.
michael@0 66 void SkBlitter::blitAntiRect(int x, int y, int width, int height,
michael@0 67 SkAlpha leftAlpha, SkAlpha rightAlpha) {
michael@0 68 this->blitV(x++, y, height, leftAlpha);
michael@0 69 if (width > 0) {
michael@0 70 this->blitRect(x, y, width, height);
michael@0 71 x += width;
michael@0 72 }
michael@0 73 this->blitV(x, y, height, rightAlpha);
michael@0 74 }
michael@0 75
michael@0 76 //////////////////////////////////////////////////////////////////////////////
michael@0 77
michael@0 78 static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
michael@0 79 const uint8_t bits[],
michael@0 80 U8CPU left_mask, int rowBytes,
michael@0 81 U8CPU right_mask) {
michael@0 82 int inFill = 0;
michael@0 83 int pos = 0;
michael@0 84
michael@0 85 while (--rowBytes >= 0) {
michael@0 86 unsigned b = *bits++ & left_mask;
michael@0 87 if (rowBytes == 0) {
michael@0 88 b &= right_mask;
michael@0 89 }
michael@0 90
michael@0 91 for (unsigned test = 0x80; test != 0; test >>= 1) {
michael@0 92 if (b & test) {
michael@0 93 if (!inFill) {
michael@0 94 pos = x;
michael@0 95 inFill = true;
michael@0 96 }
michael@0 97 } else {
michael@0 98 if (inFill) {
michael@0 99 blitter->blitH(pos, y, x - pos);
michael@0 100 inFill = false;
michael@0 101 }
michael@0 102 }
michael@0 103 x += 1;
michael@0 104 }
michael@0 105 left_mask = 0xFF;
michael@0 106 }
michael@0 107
michael@0 108 // final cleanup
michael@0 109 if (inFill) {
michael@0 110 blitter->blitH(pos, y, x - pos);
michael@0 111 }
michael@0 112 }
michael@0 113
michael@0 114 void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
michael@0 115 SkASSERT(mask.fBounds.contains(clip));
michael@0 116
michael@0 117 if (mask.fFormat == SkMask::kBW_Format) {
michael@0 118 int cx = clip.fLeft;
michael@0 119 int cy = clip.fTop;
michael@0 120 int maskLeft = mask.fBounds.fLeft;
michael@0 121 int mask_rowBytes = mask.fRowBytes;
michael@0 122 int height = clip.height();
michael@0 123
michael@0 124 const uint8_t* bits = mask.getAddr1(cx, cy);
michael@0 125
michael@0 126 if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
michael@0 127 while (--height >= 0) {
michael@0 128 bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
michael@0 129 bits += mask_rowBytes;
michael@0 130 cy += 1;
michael@0 131 }
michael@0 132 } else {
michael@0 133 int left_edge = cx - maskLeft;
michael@0 134 SkASSERT(left_edge >= 0);
michael@0 135 int rite_edge = clip.fRight - maskLeft;
michael@0 136 SkASSERT(rite_edge > left_edge);
michael@0 137
michael@0 138 int left_mask = 0xFF >> (left_edge & 7);
michael@0 139 int rite_mask = 0xFF << (8 - (rite_edge & 7));
michael@0 140 int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
michael@0 141
michael@0 142 // check for empty right mask, so we don't read off the end (or go slower than we need to)
michael@0 143 if (rite_mask == 0) {
michael@0 144 SkASSERT(full_runs >= 0);
michael@0 145 full_runs -= 1;
michael@0 146 rite_mask = 0xFF;
michael@0 147 }
michael@0 148 if (left_mask == 0xFF) {
michael@0 149 full_runs -= 1;
michael@0 150 }
michael@0 151
michael@0 152 // back up manually so we can keep in sync with our byte-aligned src
michael@0 153 // have cx reflect our actual starting x-coord
michael@0 154 cx -= left_edge & 7;
michael@0 155
michael@0 156 if (full_runs < 0) {
michael@0 157 SkASSERT((left_mask & rite_mask) != 0);
michael@0 158 while (--height >= 0) {
michael@0 159 bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
michael@0 160 bits += mask_rowBytes;
michael@0 161 cy += 1;
michael@0 162 }
michael@0 163 } else {
michael@0 164 while (--height >= 0) {
michael@0 165 bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
michael@0 166 bits += mask_rowBytes;
michael@0 167 cy += 1;
michael@0 168 }
michael@0 169 }
michael@0 170 }
michael@0 171 } else {
michael@0 172 int width = clip.width();
michael@0 173 SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
michael@0 174 int16_t* runs = runStorage.get();
michael@0 175 const uint8_t* aa = mask.getAddr8(clip.fLeft, clip.fTop);
michael@0 176
michael@0 177 sk_memset16((uint16_t*)runs, 1, width);
michael@0 178 runs[width] = 0;
michael@0 179
michael@0 180 int height = clip.height();
michael@0 181 int y = clip.fTop;
michael@0 182 while (--height >= 0) {
michael@0 183 this->blitAntiH(clip.fLeft, y, aa, runs);
michael@0 184 aa += mask.fRowBytes;
michael@0 185 y += 1;
michael@0 186 }
michael@0 187 }
michael@0 188 }
michael@0 189
michael@0 190 /////////////////////// these guys are not virtual, just a helpers
michael@0 191
michael@0 192 void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
michael@0 193 if (clip.quickReject(mask.fBounds)) {
michael@0 194 return;
michael@0 195 }
michael@0 196
michael@0 197 SkRegion::Cliperator clipper(clip, mask.fBounds);
michael@0 198
michael@0 199 while (!clipper.done()) {
michael@0 200 const SkIRect& cr = clipper.rect();
michael@0 201 this->blitMask(mask, cr);
michael@0 202 clipper.next();
michael@0 203 }
michael@0 204 }
michael@0 205
michael@0 206 void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
michael@0 207 SkRegion::Cliperator clipper(clip, rect);
michael@0 208
michael@0 209 while (!clipper.done()) {
michael@0 210 const SkIRect& cr = clipper.rect();
michael@0 211 this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
michael@0 212 clipper.next();
michael@0 213 }
michael@0 214 }
michael@0 215
michael@0 216 void SkBlitter::blitRegion(const SkRegion& clip) {
michael@0 217 SkRegion::Iterator iter(clip);
michael@0 218
michael@0 219 while (!iter.done()) {
michael@0 220 const SkIRect& cr = iter.rect();
michael@0 221 this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
michael@0 222 iter.next();
michael@0 223 }
michael@0 224 }
michael@0 225
michael@0 226 ///////////////////////////////////////////////////////////////////////////////
michael@0 227
michael@0 228 void SkNullBlitter::blitH(int x, int y, int width) {}
michael@0 229
michael@0 230 void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
michael@0 231 const int16_t runs[]) {}
michael@0 232
michael@0 233 void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
michael@0 234
michael@0 235 void SkNullBlitter::blitRect(int x, int y, int width, int height) {}
michael@0 236
michael@0 237 void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
michael@0 238
michael@0 239 const SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
michael@0 240 return NULL;
michael@0 241 }
michael@0 242
michael@0 243 bool SkNullBlitter::isNullBlitter() const { return true; }
michael@0 244
michael@0 245 ///////////////////////////////////////////////////////////////////////////////
michael@0 246
michael@0 247 static int compute_anti_width(const int16_t runs[]) {
michael@0 248 int width = 0;
michael@0 249
michael@0 250 for (;;) {
michael@0 251 int count = runs[0];
michael@0 252
michael@0 253 SkASSERT(count >= 0);
michael@0 254 if (count == 0) {
michael@0 255 break;
michael@0 256 }
michael@0 257 width += count;
michael@0 258 runs += count;
michael@0 259 }
michael@0 260 return width;
michael@0 261 }
michael@0 262
michael@0 263 static inline bool y_in_rect(int y, const SkIRect& rect) {
michael@0 264 return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
michael@0 265 }
michael@0 266
michael@0 267 static inline bool x_in_rect(int x, const SkIRect& rect) {
michael@0 268 return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
michael@0 269 }
michael@0 270
michael@0 271 void SkRectClipBlitter::blitH(int left, int y, int width) {
michael@0 272 SkASSERT(width > 0);
michael@0 273
michael@0 274 if (!y_in_rect(y, fClipRect)) {
michael@0 275 return;
michael@0 276 }
michael@0 277
michael@0 278 int right = left + width;
michael@0 279
michael@0 280 if (left < fClipRect.fLeft) {
michael@0 281 left = fClipRect.fLeft;
michael@0 282 }
michael@0 283 if (right > fClipRect.fRight) {
michael@0 284 right = fClipRect.fRight;
michael@0 285 }
michael@0 286
michael@0 287 width = right - left;
michael@0 288 if (width > 0) {
michael@0 289 fBlitter->blitH(left, y, width);
michael@0 290 }
michael@0 291 }
michael@0 292
michael@0 293 void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
michael@0 294 const int16_t runs[]) {
michael@0 295 if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
michael@0 296 return;
michael@0 297 }
michael@0 298
michael@0 299 int x0 = left;
michael@0 300 int x1 = left + compute_anti_width(runs);
michael@0 301
michael@0 302 if (x1 <= fClipRect.fLeft) {
michael@0 303 return;
michael@0 304 }
michael@0 305
michael@0 306 SkASSERT(x0 < x1);
michael@0 307 if (x0 < fClipRect.fLeft) {
michael@0 308 int dx = fClipRect.fLeft - x0;
michael@0 309 SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
michael@0 310 runs += dx;
michael@0 311 aa += dx;
michael@0 312 x0 = fClipRect.fLeft;
michael@0 313 }
michael@0 314
michael@0 315 SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
michael@0 316 if (x1 > fClipRect.fRight) {
michael@0 317 x1 = fClipRect.fRight;
michael@0 318 SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
michael@0 319 ((int16_t*)runs)[x1 - x0] = 0;
michael@0 320 }
michael@0 321
michael@0 322 SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
michael@0 323 SkASSERT(compute_anti_width(runs) == x1 - x0);
michael@0 324
michael@0 325 fBlitter->blitAntiH(x0, y, aa, runs);
michael@0 326 }
michael@0 327
michael@0 328 void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
michael@0 329 SkASSERT(height > 0);
michael@0 330
michael@0 331 if (!x_in_rect(x, fClipRect)) {
michael@0 332 return;
michael@0 333 }
michael@0 334
michael@0 335 int y0 = y;
michael@0 336 int y1 = y + height;
michael@0 337
michael@0 338 if (y0 < fClipRect.fTop) {
michael@0 339 y0 = fClipRect.fTop;
michael@0 340 }
michael@0 341 if (y1 > fClipRect.fBottom) {
michael@0 342 y1 = fClipRect.fBottom;
michael@0 343 }
michael@0 344
michael@0 345 if (y0 < y1) {
michael@0 346 fBlitter->blitV(x, y0, y1 - y0, alpha);
michael@0 347 }
michael@0 348 }
michael@0 349
michael@0 350 void SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
michael@0 351 SkIRect r;
michael@0 352
michael@0 353 r.set(left, y, left + width, y + height);
michael@0 354 if (r.intersect(fClipRect)) {
michael@0 355 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
michael@0 356 }
michael@0 357 }
michael@0 358
michael@0 359 void SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
michael@0 360 SkAlpha leftAlpha, SkAlpha rightAlpha) {
michael@0 361 SkIRect r;
michael@0 362
michael@0 363 // The *true* width of the rectangle blitted is width+2:
michael@0 364 r.set(left, y, left + width + 2, y + height);
michael@0 365 if (r.intersect(fClipRect)) {
michael@0 366 if (r.fLeft != left) {
michael@0 367 SkASSERT(r.fLeft > left);
michael@0 368 leftAlpha = 255;
michael@0 369 }
michael@0 370 if (r.fRight != left + width + 2) {
michael@0 371 SkASSERT(r.fRight < left + width + 2);
michael@0 372 rightAlpha = 255;
michael@0 373 }
michael@0 374 if (255 == leftAlpha && 255 == rightAlpha) {
michael@0 375 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
michael@0 376 } else if (1 == r.width()) {
michael@0 377 if (r.fLeft == left) {
michael@0 378 fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
michael@0 379 } else {
michael@0 380 SkASSERT(r.fLeft == left + width + 1);
michael@0 381 fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
michael@0 382 }
michael@0 383 } else {
michael@0 384 fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
michael@0 385 leftAlpha, rightAlpha);
michael@0 386 }
michael@0 387 }
michael@0 388 }
michael@0 389
michael@0 390 void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
michael@0 391 SkASSERT(mask.fBounds.contains(clip));
michael@0 392
michael@0 393 SkIRect r = clip;
michael@0 394
michael@0 395 if (r.intersect(fClipRect)) {
michael@0 396 fBlitter->blitMask(mask, r);
michael@0 397 }
michael@0 398 }
michael@0 399
michael@0 400 const SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
michael@0 401 return fBlitter->justAnOpaqueColor(value);
michael@0 402 }
michael@0 403
michael@0 404 ///////////////////////////////////////////////////////////////////////////////
michael@0 405
michael@0 406 void SkRgnClipBlitter::blitH(int x, int y, int width) {
michael@0 407 SkRegion::Spanerator span(*fRgn, y, x, x + width);
michael@0 408 int left, right;
michael@0 409
michael@0 410 while (span.next(&left, &right)) {
michael@0 411 SkASSERT(left < right);
michael@0 412 fBlitter->blitH(left, y, right - left);
michael@0 413 }
michael@0 414 }
michael@0 415
michael@0 416 void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
michael@0 417 const int16_t runs[]) {
michael@0 418 int width = compute_anti_width(runs);
michael@0 419 SkRegion::Spanerator span(*fRgn, y, x, x + width);
michael@0 420 int left, right;
michael@0 421 SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
michael@0 422
michael@0 423 int prevRite = x;
michael@0 424 while (span.next(&left, &right)) {
michael@0 425 SkASSERT(x <= left);
michael@0 426 SkASSERT(left < right);
michael@0 427 SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
michael@0 428
michael@0 429 SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
michael@0 430
michael@0 431 // now zero before left
michael@0 432 if (left > prevRite) {
michael@0 433 int index = prevRite - x;
michael@0 434 ((uint8_t*)aa)[index] = 0; // skip runs after right
michael@0 435 ((int16_t*)runs)[index] = SkToS16(left - prevRite);
michael@0 436 }
michael@0 437
michael@0 438 prevRite = right;
michael@0 439 }
michael@0 440
michael@0 441 if (prevRite > x) {
michael@0 442 ((int16_t*)runs)[prevRite - x] = 0;
michael@0 443
michael@0 444 if (x < 0) {
michael@0 445 int skip = runs[0];
michael@0 446 SkASSERT(skip >= -x);
michael@0 447 aa += skip;
michael@0 448 runs += skip;
michael@0 449 x += skip;
michael@0 450 }
michael@0 451 fBlitter->blitAntiH(x, y, aa, runs);
michael@0 452 }
michael@0 453 }
michael@0 454
michael@0 455 void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
michael@0 456 SkIRect bounds;
michael@0 457 bounds.set(x, y, x + 1, y + height);
michael@0 458
michael@0 459 SkRegion::Cliperator iter(*fRgn, bounds);
michael@0 460
michael@0 461 while (!iter.done()) {
michael@0 462 const SkIRect& r = iter.rect();
michael@0 463 SkASSERT(bounds.contains(r));
michael@0 464
michael@0 465 fBlitter->blitV(x, r.fTop, r.height(), alpha);
michael@0 466 iter.next();
michael@0 467 }
michael@0 468 }
michael@0 469
michael@0 470 void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
michael@0 471 SkIRect bounds;
michael@0 472 bounds.set(x, y, x + width, y + height);
michael@0 473
michael@0 474 SkRegion::Cliperator iter(*fRgn, bounds);
michael@0 475
michael@0 476 while (!iter.done()) {
michael@0 477 const SkIRect& r = iter.rect();
michael@0 478 SkASSERT(bounds.contains(r));
michael@0 479
michael@0 480 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
michael@0 481 iter.next();
michael@0 482 }
michael@0 483 }
michael@0 484
michael@0 485 void SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
michael@0 486 SkAlpha leftAlpha, SkAlpha rightAlpha) {
michael@0 487 // The *true* width of the rectangle to blit is width + 2
michael@0 488 SkIRect bounds;
michael@0 489 bounds.set(x, y, x + width + 2, y + height);
michael@0 490
michael@0 491 SkRegion::Cliperator iter(*fRgn, bounds);
michael@0 492
michael@0 493 while (!iter.done()) {
michael@0 494 const SkIRect& r = iter.rect();
michael@0 495 SkASSERT(bounds.contains(r));
michael@0 496 SkASSERT(r.fLeft >= x);
michael@0 497 SkASSERT(r.fRight <= x + width + 2);
michael@0 498
michael@0 499 SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
michael@0 500 SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
michael@0 501 rightAlpha : 255;
michael@0 502
michael@0 503 if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
michael@0 504 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
michael@0 505 } else if (1 == r.width()) {
michael@0 506 if (r.fLeft == x) {
michael@0 507 fBlitter->blitV(r.fLeft, r.fTop, r.height(),
michael@0 508 effectiveLeftAlpha);
michael@0 509 } else {
michael@0 510 SkASSERT(r.fLeft == x + width + 1);
michael@0 511 fBlitter->blitV(r.fLeft, r.fTop, r.height(),
michael@0 512 effectiveRightAlpha);
michael@0 513 }
michael@0 514 } else {
michael@0 515 fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
michael@0 516 effectiveLeftAlpha, effectiveRightAlpha);
michael@0 517 }
michael@0 518 iter.next();
michael@0 519 }
michael@0 520 }
michael@0 521
michael@0 522
michael@0 523 void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
michael@0 524 SkASSERT(mask.fBounds.contains(clip));
michael@0 525
michael@0 526 SkRegion::Cliperator iter(*fRgn, clip);
michael@0 527 const SkIRect& r = iter.rect();
michael@0 528 SkBlitter* blitter = fBlitter;
michael@0 529
michael@0 530 while (!iter.done()) {
michael@0 531 blitter->blitMask(mask, r);
michael@0 532 iter.next();
michael@0 533 }
michael@0 534 }
michael@0 535
michael@0 536 const SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
michael@0 537 return fBlitter->justAnOpaqueColor(value);
michael@0 538 }
michael@0 539
michael@0 540 ///////////////////////////////////////////////////////////////////////////////
michael@0 541
michael@0 542 SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
michael@0 543 const SkIRect* ir) {
michael@0 544 if (clip) {
michael@0 545 const SkIRect& clipR = clip->getBounds();
michael@0 546
michael@0 547 if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
michael@0 548 blitter = &fNullBlitter;
michael@0 549 } else if (clip->isRect()) {
michael@0 550 if (ir == NULL || !clipR.contains(*ir)) {
michael@0 551 fRectBlitter.init(blitter, clipR);
michael@0 552 blitter = &fRectBlitter;
michael@0 553 }
michael@0 554 } else {
michael@0 555 fRgnBlitter.init(blitter, clip);
michael@0 556 blitter = &fRgnBlitter;
michael@0 557 }
michael@0 558 }
michael@0 559 return blitter;
michael@0 560 }
michael@0 561
michael@0 562 ///////////////////////////////////////////////////////////////////////////////
michael@0 563
michael@0 564 #include "SkColorShader.h"
michael@0 565 #include "SkColorPriv.h"
michael@0 566
michael@0 567 class Sk3DShader : public SkShader {
michael@0 568 public:
michael@0 569 Sk3DShader(SkShader* proxy) : fProxy(proxy) {
michael@0 570 SkSafeRef(proxy);
michael@0 571 fMask = NULL;
michael@0 572 }
michael@0 573
michael@0 574 virtual ~Sk3DShader() {
michael@0 575 SkSafeUnref(fProxy);
michael@0 576 }
michael@0 577
michael@0 578 void setMask(const SkMask* mask) { fMask = mask; }
michael@0 579
michael@0 580 virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
michael@0 581 const SkMatrix& matrix) SK_OVERRIDE {
michael@0 582 if (!this->INHERITED::setContext(device, paint, matrix)) {
michael@0 583 return false;
michael@0 584 }
michael@0 585 if (fProxy) {
michael@0 586 if (!fProxy->setContext(device, paint, matrix)) {
michael@0 587 // must keep our set/end context calls balanced
michael@0 588 this->INHERITED::endContext();
michael@0 589 return false;
michael@0 590 }
michael@0 591 } else {
michael@0 592 fPMColor = SkPreMultiplyColor(paint.getColor());
michael@0 593 }
michael@0 594 return true;
michael@0 595 }
michael@0 596
michael@0 597 virtual void endContext() SK_OVERRIDE {
michael@0 598 if (fProxy) {
michael@0 599 fProxy->endContext();
michael@0 600 }
michael@0 601 this->INHERITED::endContext();
michael@0 602 }
michael@0 603
michael@0 604 virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE {
michael@0 605 if (fProxy) {
michael@0 606 fProxy->shadeSpan(x, y, span, count);
michael@0 607 }
michael@0 608
michael@0 609 if (fMask == NULL) {
michael@0 610 if (fProxy == NULL) {
michael@0 611 sk_memset32(span, fPMColor, count);
michael@0 612 }
michael@0 613 return;
michael@0 614 }
michael@0 615
michael@0 616 SkASSERT(fMask->fBounds.contains(x, y));
michael@0 617 SkASSERT(fMask->fBounds.contains(x + count - 1, y));
michael@0 618
michael@0 619 size_t size = fMask->computeImageSize();
michael@0 620 const uint8_t* alpha = fMask->getAddr8(x, y);
michael@0 621 const uint8_t* mulp = alpha + size;
michael@0 622 const uint8_t* addp = mulp + size;
michael@0 623
michael@0 624 if (fProxy) {
michael@0 625 for (int i = 0; i < count; i++) {
michael@0 626 if (alpha[i]) {
michael@0 627 SkPMColor c = span[i];
michael@0 628 if (c) {
michael@0 629 unsigned a = SkGetPackedA32(c);
michael@0 630 unsigned r = SkGetPackedR32(c);
michael@0 631 unsigned g = SkGetPackedG32(c);
michael@0 632 unsigned b = SkGetPackedB32(c);
michael@0 633
michael@0 634 unsigned mul = SkAlpha255To256(mulp[i]);
michael@0 635 unsigned add = addp[i];
michael@0 636
michael@0 637 r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
michael@0 638 g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
michael@0 639 b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
michael@0 640
michael@0 641 span[i] = SkPackARGB32(a, r, g, b);
michael@0 642 }
michael@0 643 } else {
michael@0 644 span[i] = 0;
michael@0 645 }
michael@0 646 }
michael@0 647 } else { // color
michael@0 648 unsigned a = SkGetPackedA32(fPMColor);
michael@0 649 unsigned r = SkGetPackedR32(fPMColor);
michael@0 650 unsigned g = SkGetPackedG32(fPMColor);
michael@0 651 unsigned b = SkGetPackedB32(fPMColor);
michael@0 652 for (int i = 0; i < count; i++) {
michael@0 653 if (alpha[i]) {
michael@0 654 unsigned mul = SkAlpha255To256(mulp[i]);
michael@0 655 unsigned add = addp[i];
michael@0 656
michael@0 657 span[i] = SkPackARGB32( a,
michael@0 658 SkFastMin32(SkAlphaMul(r, mul) + add, a),
michael@0 659 SkFastMin32(SkAlphaMul(g, mul) + add, a),
michael@0 660 SkFastMin32(SkAlphaMul(b, mul) + add, a));
michael@0 661 } else {
michael@0 662 span[i] = 0;
michael@0 663 }
michael@0 664 }
michael@0 665 }
michael@0 666 }
michael@0 667
michael@0 668 #ifndef SK_IGNORE_TO_STRING
michael@0 669 virtual void toString(SkString* str) const SK_OVERRIDE {
michael@0 670 str->append("Sk3DShader: (");
michael@0 671
michael@0 672 if (NULL != fProxy) {
michael@0 673 str->append("Proxy: ");
michael@0 674 fProxy->toString(str);
michael@0 675 }
michael@0 676
michael@0 677 this->INHERITED::toString(str);
michael@0 678
michael@0 679 str->append(")");
michael@0 680 }
michael@0 681 #endif
michael@0 682
michael@0 683 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
michael@0 684
michael@0 685 protected:
michael@0 686 Sk3DShader(SkReadBuffer& buffer) : INHERITED(buffer) {
michael@0 687 fProxy = buffer.readShader();
michael@0 688 fPMColor = buffer.readColor();
michael@0 689 fMask = NULL;
michael@0 690 }
michael@0 691
michael@0 692 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
michael@0 693 this->INHERITED::flatten(buffer);
michael@0 694 buffer.writeFlattenable(fProxy);
michael@0 695 buffer.writeColor(fPMColor);
michael@0 696 }
michael@0 697
michael@0 698 private:
michael@0 699 SkShader* fProxy;
michael@0 700 SkPMColor fPMColor;
michael@0 701 const SkMask* fMask;
michael@0 702
michael@0 703 typedef SkShader INHERITED;
michael@0 704 };
michael@0 705
michael@0 706 class Sk3DBlitter : public SkBlitter {
michael@0 707 public:
michael@0 708 Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader)
michael@0 709 : fProxy(proxy)
michael@0 710 , f3DShader(SkRef(shader))
michael@0 711 {}
michael@0 712
michael@0 713 virtual void blitH(int x, int y, int width) {
michael@0 714 fProxy->blitH(x, y, width);
michael@0 715 }
michael@0 716
michael@0 717 virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
michael@0 718 const int16_t runs[]) {
michael@0 719 fProxy->blitAntiH(x, y, antialias, runs);
michael@0 720 }
michael@0 721
michael@0 722 virtual void blitV(int x, int y, int height, SkAlpha alpha) {
michael@0 723 fProxy->blitV(x, y, height, alpha);
michael@0 724 }
michael@0 725
michael@0 726 virtual void blitRect(int x, int y, int width, int height) {
michael@0 727 fProxy->blitRect(x, y, width, height);
michael@0 728 }
michael@0 729
michael@0 730 virtual void blitMask(const SkMask& mask, const SkIRect& clip) {
michael@0 731 if (mask.fFormat == SkMask::k3D_Format) {
michael@0 732 f3DShader->setMask(&mask);
michael@0 733
michael@0 734 ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
michael@0 735 fProxy->blitMask(mask, clip);
michael@0 736 ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
michael@0 737
michael@0 738 f3DShader->setMask(NULL);
michael@0 739 } else {
michael@0 740 fProxy->blitMask(mask, clip);
michael@0 741 }
michael@0 742 }
michael@0 743
michael@0 744 private:
michael@0 745 // fProxy is unowned. It will be deleted by SkSmallAllocator.
michael@0 746 SkBlitter* fProxy;
michael@0 747 SkAutoTUnref<Sk3DShader> f3DShader;
michael@0 748 };
michael@0 749
michael@0 750 ///////////////////////////////////////////////////////////////////////////////
michael@0 751
michael@0 752 #include "SkCoreBlitters.h"
michael@0 753
michael@0 754 static bool just_solid_color(const SkPaint& paint) {
michael@0 755 if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
michael@0 756 SkShader* shader = paint.getShader();
michael@0 757 if (NULL == shader ||
michael@0 758 (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
michael@0 759 return true;
michael@0 760 }
michael@0 761 }
michael@0 762 return false;
michael@0 763 }
michael@0 764
michael@0 765 /** By analyzing the paint (with an xfermode), we may decide we can take
michael@0 766 special action. This enum lists our possible actions
michael@0 767 */
michael@0 768 enum XferInterp {
michael@0 769 kNormal_XferInterp, // no special interpretation, draw normally
michael@0 770 kSrcOver_XferInterp, // draw as if in srcover mode
michael@0 771 kSkipDrawing_XferInterp // draw nothing
michael@0 772 };
michael@0 773
michael@0 774 static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
michael@0 775 SkColorType deviceCT) {
michael@0 776 SkXfermode::Mode mode;
michael@0 777
michael@0 778 if (SkXfermode::AsMode(xfer, &mode)) {
michael@0 779 switch (mode) {
michael@0 780 case SkXfermode::kSrc_Mode:
michael@0 781 if (just_solid_color(paint)) {
michael@0 782 return kSrcOver_XferInterp;
michael@0 783 }
michael@0 784 break;
michael@0 785 case SkXfermode::kDst_Mode:
michael@0 786 return kSkipDrawing_XferInterp;
michael@0 787 case SkXfermode::kSrcOver_Mode:
michael@0 788 return kSrcOver_XferInterp;
michael@0 789 case SkXfermode::kDstOver_Mode:
michael@0 790 if (kRGB_565_SkColorType == deviceCT) {
michael@0 791 return kSkipDrawing_XferInterp;
michael@0 792 }
michael@0 793 break;
michael@0 794 case SkXfermode::kSrcIn_Mode:
michael@0 795 if (kRGB_565_SkColorType == deviceCT &&
michael@0 796 just_solid_color(paint)) {
michael@0 797 return kSrcOver_XferInterp;
michael@0 798 }
michael@0 799 break;
michael@0 800 case SkXfermode::kDstIn_Mode:
michael@0 801 if (just_solid_color(paint)) {
michael@0 802 return kSkipDrawing_XferInterp;
michael@0 803 }
michael@0 804 break;
michael@0 805 default:
michael@0 806 break;
michael@0 807 }
michael@0 808 }
michael@0 809 return kNormal_XferInterp;
michael@0 810 }
michael@0 811
michael@0 812 SkBlitter* SkBlitter::Choose(const SkBitmap& device,
michael@0 813 const SkMatrix& matrix,
michael@0 814 const SkPaint& origPaint,
michael@0 815 SkTBlitterAllocator* allocator,
michael@0 816 bool drawCoverage) {
michael@0 817 SkASSERT(allocator != NULL);
michael@0 818
michael@0 819 SkBlitter* blitter = NULL;
michael@0 820
michael@0 821 // which check, in case we're being called by a client with a dummy device
michael@0 822 // (e.g. they have a bounder that always aborts the draw)
michael@0 823 if (kUnknown_SkColorType == device.colorType() ||
michael@0 824 (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) {
michael@0 825 blitter = allocator->createT<SkNullBlitter>();
michael@0 826 return blitter;
michael@0 827 }
michael@0 828
michael@0 829 SkShader* shader = origPaint.getShader();
michael@0 830 SkColorFilter* cf = origPaint.getColorFilter();
michael@0 831 SkXfermode* mode = origPaint.getXfermode();
michael@0 832 Sk3DShader* shader3D = NULL;
michael@0 833
michael@0 834 SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
michael@0 835
michael@0 836 if (origPaint.getMaskFilter() != NULL &&
michael@0 837 origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
michael@0 838 shader3D = SkNEW_ARGS(Sk3DShader, (shader));
michael@0 839 // we know we haven't initialized lazyPaint yet, so just do it
michael@0 840 paint.writable()->setShader(shader3D)->unref();
michael@0 841 shader = shader3D;
michael@0 842 }
michael@0 843
michael@0 844 if (NULL != mode) {
michael@0 845 switch (interpret_xfermode(*paint, mode, device.colorType())) {
michael@0 846 case kSrcOver_XferInterp:
michael@0 847 mode = NULL;
michael@0 848 paint.writable()->setXfermode(NULL);
michael@0 849 break;
michael@0 850 case kSkipDrawing_XferInterp:{
michael@0 851 blitter = allocator->createT<SkNullBlitter>();
michael@0 852 return blitter;
michael@0 853 }
michael@0 854 default:
michael@0 855 break;
michael@0 856 }
michael@0 857 }
michael@0 858
michael@0 859 /*
michael@0 860 * If the xfermode is CLEAR, then we can completely ignore the installed
michael@0 861 * color/shader/colorfilter, and just pretend we're SRC + color==0. This
michael@0 862 * will fall into our optimizations for SRC mode.
michael@0 863 */
michael@0 864 if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) {
michael@0 865 SkPaint* p = paint.writable();
michael@0 866 shader = p->setShader(NULL);
michael@0 867 cf = p->setColorFilter(NULL);
michael@0 868 mode = p->setXfermodeMode(SkXfermode::kSrc_Mode);
michael@0 869 p->setColor(0);
michael@0 870 }
michael@0 871
michael@0 872 if (NULL == shader) {
michael@0 873 if (mode) {
michael@0 874 // xfermodes (and filters) require shaders for our current blitters
michael@0 875 shader = SkNEW(SkColorShader);
michael@0 876 paint.writable()->setShader(shader)->unref();
michael@0 877 } else if (cf) {
michael@0 878 // if no shader && no xfermode, we just apply the colorfilter to
michael@0 879 // our color and move on.
michael@0 880 SkPaint* writablePaint = paint.writable();
michael@0 881 writablePaint->setColor(cf->filterColor(paint->getColor()));
michael@0 882 writablePaint->setColorFilter(NULL);
michael@0 883 cf = NULL;
michael@0 884 }
michael@0 885 }
michael@0 886
michael@0 887 if (cf) {
michael@0 888 SkASSERT(shader);
michael@0 889 shader = SkNEW_ARGS(SkFilterShader, (shader, cf));
michael@0 890 paint.writable()->setShader(shader)->unref();
michael@0 891 // blitters should ignore the presence/absence of a filter, since
michael@0 892 // if there is one, the shader will take care of it.
michael@0 893 }
michael@0 894
michael@0 895 /*
michael@0 896 * We need to have balanced calls to the shader:
michael@0 897 * setContext
michael@0 898 * endContext
michael@0 899 * We make the first call here, in case it fails we can abort the draw.
michael@0 900 * The endContext() call is made by the blitter (assuming setContext did
michael@0 901 * not fail) in its destructor.
michael@0 902 */
michael@0 903 if (shader && !shader->setContext(device, *paint, matrix)) {
michael@0 904 blitter = allocator->createT<SkNullBlitter>();
michael@0 905 return blitter;
michael@0 906 }
michael@0 907
michael@0 908
michael@0 909 switch (device.colorType()) {
michael@0 910 case kAlpha_8_SkColorType:
michael@0 911 if (drawCoverage) {
michael@0 912 SkASSERT(NULL == shader);
michael@0 913 SkASSERT(NULL == paint->getXfermode());
michael@0 914 blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint);
michael@0 915 } else if (shader) {
michael@0 916 blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint);
michael@0 917 } else {
michael@0 918 blitter = allocator->createT<SkA8_Blitter>(device, *paint);
michael@0 919 }
michael@0 920 break;
michael@0 921
michael@0 922 case kRGB_565_SkColorType:
michael@0 923 blitter = SkBlitter_ChooseD565(device, *paint, allocator);
michael@0 924 break;
michael@0 925
michael@0 926 case kPMColor_SkColorType:
michael@0 927 if (shader) {
michael@0 928 blitter = allocator->createT<SkARGB32_Shader_Blitter>(device, *paint);
michael@0 929 } else if (paint->getColor() == SK_ColorBLACK) {
michael@0 930 blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint);
michael@0 931 } else if (paint->getAlpha() == 0xFF) {
michael@0 932 blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint);
michael@0 933 } else {
michael@0 934 blitter = allocator->createT<SkARGB32_Blitter>(device, *paint);
michael@0 935 }
michael@0 936 break;
michael@0 937
michael@0 938 default:
michael@0 939 SkDEBUGFAIL("unsupported device config");
michael@0 940 blitter = allocator->createT<SkNullBlitter>();
michael@0 941 break;
michael@0 942 }
michael@0 943
michael@0 944 if (shader3D) {
michael@0 945 SkBlitter* innerBlitter = blitter;
michael@0 946 // innerBlitter was allocated by allocator, which will delete it.
michael@0 947 blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shader3D);
michael@0 948 }
michael@0 949 return blitter;
michael@0 950 }
michael@0 951
michael@0 952 ///////////////////////////////////////////////////////////////////////////////
michael@0 953
michael@0 954 const uint16_t gMask_0F0F = 0xF0F;
michael@0 955 const uint32_t gMask_00FF00FF = 0xFF00FF;
michael@0 956
michael@0 957 ///////////////////////////////////////////////////////////////////////////////
michael@0 958
michael@0 959 SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
michael@0 960 : INHERITED(device) {
michael@0 961 fShader = paint.getShader();
michael@0 962 SkASSERT(fShader);
michael@0 963 SkASSERT(fShader->setContextHasBeenCalled());
michael@0 964
michael@0 965 fShader->ref();
michael@0 966 fShaderFlags = fShader->getFlags();
michael@0 967 }
michael@0 968
michael@0 969 SkShaderBlitter::~SkShaderBlitter() {
michael@0 970 SkASSERT(fShader->setContextHasBeenCalled());
michael@0 971 fShader->endContext();
michael@0 972 fShader->unref();
michael@0 973 }

mercurial