1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkAAClip.h" 9 #include "SkAtomics.h" 10 #include "SkBlitter.h" 11 #include "SkColorData.h" 12 #include "SkRectPriv.h" 13 #include "SkPath.h" 14 #include "SkScan.h" 15 #include "SkUtils.h" 16 17 class AutoAAClipValidate { 18 public: 19 AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) { 20 fClip.validate(); 21 } 22 ~AutoAAClipValidate() { 23 fClip.validate(); 24 } 25 private: 26 const SkAAClip& fClip; 27 }; 28 29 #ifdef SK_DEBUG 30 #define AUTO_AACLIP_VALIDATE(clip) AutoAAClipValidate acv(clip) 31 #else 32 #define AUTO_AACLIP_VALIDATE(clip) 33 #endif 34 35 /////////////////////////////////////////////////////////////////////////////// 36 37 #define kMaxInt32 0x7FFFFFFF 38 39 #ifdef SK_DEBUG 40 static inline bool x_in_rect(int x, const SkIRect& rect) { 41 return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 42 } 43 #endif 44 45 static inline bool y_in_rect(int y, const SkIRect& rect) { 46 return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 47 } 48 49 /* 50 * Data runs are packed [count, alpha] 51 */ 52 53 struct SkAAClip::YOffset { 54 int32_t fY; 55 uint32_t fOffset; 56 }; 57 58 struct SkAAClip::RunHead { 59 int32_t fRefCnt; 60 int32_t fRowCount; 61 size_t fDataSize; 62 63 YOffset* yoffsets() { 64 return (YOffset*)((char*)this + sizeof(RunHead)); 65 } 66 const YOffset* yoffsets() const { 67 return (const YOffset*)((const char*)this + sizeof(RunHead)); 68 } 69 uint8_t* data() { 70 return (uint8_t*)(this->yoffsets() + fRowCount); 71 } 72 const uint8_t* data() const { 73 return (const uint8_t*)(this->yoffsets() + fRowCount); 74 } 75 76 static RunHead* Alloc(int rowCount, size_t dataSize) { 77 size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize; 78 RunHead* head = (RunHead*)sk_malloc_throw(size); 79 head->fRefCnt = 1; 80 head->fRowCount = rowCount; 81 head->fDataSize = dataSize; 82 return head; 83 } 84 85 static int ComputeRowSizeForWidth(int width) { 86 // 2 bytes per segment, where each segment can store up to 255 for count 87 int segments = 0; 88 while (width > 0) { 89 segments += 1; 90 int n = SkMin32(width, 255); 91 width -= n; 92 } 93 return segments * 2; // each segment is row[0] + row[1] (n + alpha) 94 } 95 96 static RunHead* AllocRect(const SkIRect& bounds) { 97 SkASSERT(!bounds.isEmpty()); 98 int width = bounds.width(); 99 size_t rowSize = ComputeRowSizeForWidth(width); 100 RunHead* head = RunHead::Alloc(1, rowSize); 101 YOffset* yoff = head->yoffsets(); 102 yoff->fY = bounds.height() - 1; 103 yoff->fOffset = 0; 104 uint8_t* row = head->data(); 105 while (width > 0) { 106 int n = SkMin32(width, 255); 107 row[0] = n; 108 row[1] = 0xFF; 109 width -= n; 110 row += 2; 111 } 112 return head; 113 } 114 }; 115 116 class SkAAClip::Iter { 117 public: 118 Iter(const SkAAClip&); 119 120 bool done() const { return fDone; } 121 int top() const { return fTop; } 122 int bottom() const { return fBottom; } 123 const uint8_t* data() const { return fData; } 124 void next(); 125 126 private: 127 const YOffset* fCurrYOff; 128 const YOffset* fStopYOff; 129 const uint8_t* fData; 130 131 int fTop, fBottom; 132 bool fDone; 133 }; 134 135 SkAAClip::Iter::Iter(const SkAAClip& clip) { 136 if (clip.isEmpty()) { 137 fDone = true; 138 fTop = fBottom = clip.fBounds.fBottom; 139 fData = nullptr; 140 fCurrYOff = nullptr; 141 fStopYOff = nullptr; 142 return; 143 } 144 145 const RunHead* head = clip.fRunHead; 146 fCurrYOff = head->yoffsets(); 147 fStopYOff = fCurrYOff + head->fRowCount; 148 fData = head->data() + fCurrYOff->fOffset; 149 150 // setup first value 151 fTop = clip.fBounds.fTop; 152 fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1; 153 fDone = false; 154 } 155 156 void SkAAClip::Iter::next() { 157 if (!fDone) { 158 const YOffset* prev = fCurrYOff; 159 const YOffset* curr = prev + 1; 160 SkASSERT(curr <= fStopYOff); 161 162 fTop = fBottom; 163 if (curr >= fStopYOff) { 164 fDone = true; 165 fBottom = kMaxInt32; 166 fData = nullptr; 167 } else { 168 fBottom += curr->fY - prev->fY; 169 fData += curr->fOffset - prev->fOffset; 170 fCurrYOff = curr; 171 } 172 } 173 } 174 175 #ifdef SK_DEBUG 176 // assert we're exactly width-wide, and then return the number of bytes used 177 static size_t compute_row_length(const uint8_t row[], int width) { 178 const uint8_t* origRow = row; 179 while (width > 0) { 180 int n = row[0]; 181 SkASSERT(n > 0); 182 SkASSERT(n <= width); 183 row += 2; 184 width -= n; 185 } 186 SkASSERT(0 == width); 187 return row - origRow; 188 } 189 190 void SkAAClip::validate() const { 191 if (nullptr == fRunHead) { 192 SkASSERT(fBounds.isEmpty()); 193 return; 194 } 195 SkASSERT(!fBounds.isEmpty()); 196 197 const RunHead* head = fRunHead; 198 SkASSERT(head->fRefCnt > 0); 199 SkASSERT(head->fRowCount > 0); 200 201 const YOffset* yoff = head->yoffsets(); 202 const YOffset* ystop = yoff + head->fRowCount; 203 const int lastY = fBounds.height() - 1; 204 205 // Y and offset must be monotonic 206 int prevY = -1; 207 int32_t prevOffset = -1; 208 while (yoff < ystop) { 209 SkASSERT(prevY < yoff->fY); 210 SkASSERT(yoff->fY <= lastY); 211 prevY = yoff->fY; 212 SkASSERT(prevOffset < (int32_t)yoff->fOffset); 213 prevOffset = yoff->fOffset; 214 const uint8_t* row = head->data() + yoff->fOffset; 215 size_t rowLength = compute_row_length(row, fBounds.width()); 216 SkASSERT(yoff->fOffset + rowLength <= head->fDataSize); 217 yoff += 1; 218 } 219 // check the last entry; 220 --yoff; 221 SkASSERT(yoff->fY == lastY); 222 } 223 224 static void dump_one_row(const uint8_t* SK_RESTRICT row, 225 int width, int leading_num) { 226 if (leading_num) { 227 SkDebugf( "%03d ", leading_num ); 228 } 229 while (width > 0) { 230 int n = row[0]; 231 int val = row[1]; 232 char out = '.'; 233 if (val == 0xff) { 234 out = '*'; 235 } else if (val > 0) { 236 out = '+'; 237 } 238 for (int i = 0 ; i < n ; i++) { 239 SkDebugf( "%c", out ); 240 } 241 row += 2; 242 width -= n; 243 } 244 SkDebugf( "\n" ); 245 } 246 247 void SkAAClip::debug(bool compress_y) const { 248 Iter iter(*this); 249 const int width = fBounds.width(); 250 251 int y = fBounds.fTop; 252 while (!iter.done()) { 253 if (compress_y) { 254 dump_one_row(iter.data(), width, iter.bottom() - iter.top() + 1); 255 } else { 256 do { 257 dump_one_row(iter.data(), width, 0); 258 } while (++y < iter.bottom()); 259 } 260 iter.next(); 261 } 262 } 263 #endif 264 265 /////////////////////////////////////////////////////////////////////////////// 266 267 // Count the number of zeros on the left and right edges of the passed in 268 // RLE row. If 'row' is all zeros return 'width' in both variables. 269 static void count_left_right_zeros(const uint8_t* row, int width, 270 int* leftZ, int* riteZ) { 271 int zeros = 0; 272 do { 273 if (row[1]) { 274 break; 275 } 276 int n = row[0]; 277 SkASSERT(n > 0); 278 SkASSERT(n <= width); 279 zeros += n; 280 row += 2; 281 width -= n; 282 } while (width > 0); 283 *leftZ = zeros; 284 285 if (0 == width) { 286 // this line is completely empty return 'width' in both variables 287 *riteZ = *leftZ; 288 return; 289 } 290 291 zeros = 0; 292 while (width > 0) { 293 int n = row[0]; 294 SkASSERT(n > 0); 295 if (0 == row[1]) { 296 zeros += n; 297 } else { 298 zeros = 0; 299 } 300 row += 2; 301 width -= n; 302 } 303 *riteZ = zeros; 304 } 305 306 #ifdef SK_DEBUG 307 static void test_count_left_right_zeros() { 308 static bool gOnce; 309 if (gOnce) { 310 return; 311 } 312 gOnce = true; 313 314 const uint8_t data0[] = { 0, 0, 10, 0xFF }; 315 const uint8_t data1[] = { 0, 0, 5, 0xFF, 2, 0, 3, 0xFF }; 316 const uint8_t data2[] = { 7, 0, 5, 0, 2, 0, 3, 0xFF }; 317 const uint8_t data3[] = { 0, 5, 5, 0xFF, 2, 0, 3, 0 }; 318 const uint8_t data4[] = { 2, 3, 2, 0, 5, 0xFF, 3, 0 }; 319 const uint8_t data5[] = { 10, 10, 10, 0 }; 320 const uint8_t data6[] = { 2, 2, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 321 322 const uint8_t* array[] = { 323 data0, data1, data2, data3, data4, data5, data6 324 }; 325 326 for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 327 const uint8_t* data = array[i]; 328 const int expectedL = *data++; 329 const int expectedR = *data++; 330 int L = 12345, R = 12345; 331 count_left_right_zeros(data, 10, &L, &R); 332 SkASSERT(expectedL == L); 333 SkASSERT(expectedR == R); 334 } 335 } 336 #endif 337 338 // modify row in place, trimming off (zeros) from the left and right sides. 339 // return the number of bytes that were completely eliminated from the left 340 static int trim_row_left_right(uint8_t* row, int width, int leftZ, int riteZ) { 341 int trim = 0; 342 while (leftZ > 0) { 343 SkASSERT(0 == row[1]); 344 int n = row[0]; 345 SkASSERT(n > 0); 346 SkASSERT(n <= width); 347 width -= n; 348 row += 2; 349 if (n > leftZ) { 350 row[-2] = n - leftZ; 351 break; 352 } 353 trim += 2; 354 leftZ -= n; 355 SkASSERT(leftZ >= 0); 356 } 357 358 if (riteZ) { 359 // walk row to the end, and then we'll back up to trim riteZ 360 while (width > 0) { 361 int n = row[0]; 362 SkASSERT(n <= width); 363 width -= n; 364 row += 2; 365 } 366 // now skip whole runs of zeros 367 do { 368 row -= 2; 369 SkASSERT(0 == row[1]); 370 int n = row[0]; 371 SkASSERT(n > 0); 372 if (n > riteZ) { 373 row[0] = n - riteZ; 374 break; 375 } 376 riteZ -= n; 377 SkASSERT(riteZ >= 0); 378 } while (riteZ > 0); 379 } 380 381 return trim; 382 } 383 384 #ifdef SK_DEBUG 385 // assert that this row is exactly this width 386 static void assert_row_width(const uint8_t* row, int width) { 387 while (width > 0) { 388 int n = row[0]; 389 SkASSERT(n > 0); 390 SkASSERT(n <= width); 391 width -= n; 392 row += 2; 393 } 394 SkASSERT(0 == width); 395 } 396 397 static void test_trim_row_left_right() { 398 static bool gOnce; 399 if (gOnce) { 400 return; 401 } 402 gOnce = true; 403 404 uint8_t data0[] = { 0, 0, 0, 10, 10, 0xFF }; 405 uint8_t data1[] = { 2, 0, 0, 10, 5, 0, 2, 0, 3, 0xFF }; 406 uint8_t data2[] = { 5, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 407 uint8_t data3[] = { 6, 0, 2, 10, 5, 0, 2, 0, 3, 0xFF }; 408 uint8_t data4[] = { 0, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 409 uint8_t data5[] = { 1, 0, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 410 uint8_t data6[] = { 0, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 411 uint8_t data7[] = { 1, 1, 0, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 412 uint8_t data8[] = { 2, 2, 2, 10, 2, 0, 2, 0xFF, 2, 0, 2, 0xFF, 2, 0 }; 413 uint8_t data9[] = { 5, 2, 4, 10, 2, 0, 2, 0, 2, 0, 2, 0xFF, 2, 0 }; 414 uint8_t data10[] ={ 74, 0, 4, 150, 9, 0, 65, 0, 76, 0xFF }; 415 416 uint8_t* array[] = { 417 data0, data1, data2, data3, data4, 418 data5, data6, data7, data8, data9, 419 data10 420 }; 421 422 for (size_t i = 0; i < SK_ARRAY_COUNT(array); ++i) { 423 uint8_t* data = array[i]; 424 const int trimL = *data++; 425 const int trimR = *data++; 426 const int expectedSkip = *data++; 427 const int origWidth = *data++; 428 assert_row_width(data, origWidth); 429 int skip = trim_row_left_right(data, origWidth, trimL, trimR); 430 SkASSERT(expectedSkip == skip); 431 int expectedWidth = origWidth - trimL - trimR; 432 assert_row_width(data + skip, expectedWidth); 433 } 434 } 435 #endif 436 437 bool SkAAClip::trimLeftRight() { 438 SkDEBUGCODE(test_trim_row_left_right();) 439 440 if (this->isEmpty()) { 441 return false; 442 } 443 444 AUTO_AACLIP_VALIDATE(*this); 445 446 const int width = fBounds.width(); 447 RunHead* head = fRunHead; 448 YOffset* yoff = head->yoffsets(); 449 YOffset* stop = yoff + head->fRowCount; 450 uint8_t* base = head->data(); 451 452 // After this loop, 'leftZeros' & 'rightZeros' will contain the minimum 453 // number of zeros on the left and right of the clip. This information 454 // can be used to shrink the bounding box. 455 int leftZeros = width; 456 int riteZeros = width; 457 while (yoff < stop) { 458 int L, R; 459 count_left_right_zeros(base + yoff->fOffset, width, &L, &R); 460 SkASSERT(L + R < width || (L == width && R == width)); 461 if (L < leftZeros) { 462 leftZeros = L; 463 } 464 if (R < riteZeros) { 465 riteZeros = R; 466 } 467 if (0 == (leftZeros | riteZeros)) { 468 // no trimming to do 469 return true; 470 } 471 yoff += 1; 472 } 473 474 SkASSERT(leftZeros || riteZeros); 475 if (width == leftZeros) { 476 SkASSERT(width == riteZeros); 477 return this->setEmpty(); 478 } 479 480 this->validate(); 481 482 fBounds.fLeft += leftZeros; 483 fBounds.fRight -= riteZeros; 484 SkASSERT(!fBounds.isEmpty()); 485 486 // For now we don't realloc the storage (for time), we just shrink in place 487 // This means we don't have to do any memmoves either, since we can just 488 // play tricks with the yoff->fOffset for each row 489 yoff = head->yoffsets(); 490 while (yoff < stop) { 491 uint8_t* row = base + yoff->fOffset; 492 SkDEBUGCODE((void)compute_row_length(row, width);) 493 yoff->fOffset += trim_row_left_right(row, width, leftZeros, riteZeros); 494 SkDEBUGCODE((void)compute_row_length(base + yoff->fOffset, width - leftZeros - riteZeros);) 495 yoff += 1; 496 } 497 return true; 498 } 499 500 static bool row_is_all_zeros(const uint8_t* row, int width) { 501 SkASSERT(width > 0); 502 do { 503 if (row[1]) { 504 return false; 505 } 506 int n = row[0]; 507 SkASSERT(n <= width); 508 width -= n; 509 row += 2; 510 } while (width > 0); 511 SkASSERT(0 == width); 512 return true; 513 } 514 515 bool SkAAClip::trimTopBottom() { 516 if (this->isEmpty()) { 517 return false; 518 } 519 520 this->validate(); 521 522 const int width = fBounds.width(); 523 RunHead* head = fRunHead; 524 YOffset* yoff = head->yoffsets(); 525 YOffset* stop = yoff + head->fRowCount; 526 const uint8_t* base = head->data(); 527 528 // Look to trim away empty rows from the top. 529 // 530 int skip = 0; 531 while (yoff < stop) { 532 const uint8_t* data = base + yoff->fOffset; 533 if (!row_is_all_zeros(data, width)) { 534 break; 535 } 536 skip += 1; 537 yoff += 1; 538 } 539 SkASSERT(skip <= head->fRowCount); 540 if (skip == head->fRowCount) { 541 return this->setEmpty(); 542 } 543 if (skip > 0) { 544 // adjust fRowCount and fBounds.fTop, and slide all the data up 545 // as we remove [skip] number of YOffset entries 546 yoff = head->yoffsets(); 547 int dy = yoff[skip - 1].fY + 1; 548 for (int i = skip; i < head->fRowCount; ++i) { 549 SkASSERT(yoff[i].fY >= dy); 550 yoff[i].fY -= dy; 551 } 552 YOffset* dst = head->yoffsets(); 553 size_t size = head->fRowCount * sizeof(YOffset) + head->fDataSize; 554 memmove(dst, dst + skip, size - skip * sizeof(YOffset)); 555 556 fBounds.fTop += dy; 557 SkASSERT(!fBounds.isEmpty()); 558 head->fRowCount -= skip; 559 SkASSERT(head->fRowCount > 0); 560 561 this->validate(); 562 // need to reset this after the memmove 563 base = head->data(); 564 } 565 566 // Look to trim away empty rows from the bottom. 567 // We know that we have at least one non-zero row, so we can just walk 568 // backwards without checking for running past the start. 569 // 570 stop = yoff = head->yoffsets() + head->fRowCount; 571 do { 572 yoff -= 1; 573 } while (row_is_all_zeros(base + yoff->fOffset, width)); 574 skip = SkToInt(stop - yoff - 1); 575 SkASSERT(skip >= 0 && skip < head->fRowCount); 576 if (skip > 0) { 577 // removing from the bottom is easier than from the top, as we don't 578 // have to adjust any of the Y values, we just have to trim the array 579 memmove(stop - skip, stop, head->fDataSize); 580 581 fBounds.fBottom = fBounds.fTop + yoff->fY + 1; 582 SkASSERT(!fBounds.isEmpty()); 583 head->fRowCount -= skip; 584 SkASSERT(head->fRowCount > 0); 585 } 586 this->validate(); 587 588 return true; 589 } 590 591 // can't validate before we're done, since trimming is part of the process of 592 // making us valid after the Builder. Since we build from top to bottom, its 593 // possible our fBounds.fBottom is bigger than our last scanline of data, so 594 // we trim fBounds.fBottom back up. 595 // 596 // TODO: check for duplicates in X and Y to further compress our data 597 // 598 bool SkAAClip::trimBounds() { 599 if (this->isEmpty()) { 600 return false; 601 } 602 603 const RunHead* head = fRunHead; 604 const YOffset* yoff = head->yoffsets(); 605 606 SkASSERT(head->fRowCount > 0); 607 const YOffset& lastY = yoff[head->fRowCount - 1]; 608 SkASSERT(lastY.fY + 1 <= fBounds.height()); 609 fBounds.fBottom = fBounds.fTop + lastY.fY + 1; 610 SkASSERT(lastY.fY + 1 == fBounds.height()); 611 SkASSERT(!fBounds.isEmpty()); 612 613 return this->trimTopBottom() && this->trimLeftRight(); 614 } 615 616 /////////////////////////////////////////////////////////////////////////////// 617 618 void SkAAClip::freeRuns() { 619 if (fRunHead) { 620 SkASSERT(fRunHead->fRefCnt >= 1); 621 if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) { 622 sk_free(fRunHead); 623 } 624 } 625 } 626 627 SkAAClip::SkAAClip() { 628 fBounds.setEmpty(); 629 fRunHead = nullptr; 630 } 631 632 SkAAClip::SkAAClip(const SkAAClip& src) { 633 SkDEBUGCODE(fBounds.setEmpty();) // need this for validate 634 fRunHead = nullptr; 635 *this = src; 636 } 637 638 SkAAClip::~SkAAClip() { 639 this->freeRuns(); 640 } 641 642 SkAAClip& SkAAClip::operator=(const SkAAClip& src) { 643 AUTO_AACLIP_VALIDATE(*this); 644 src.validate(); 645 646 if (this != &src) { 647 this->freeRuns(); 648 fBounds = src.fBounds; 649 fRunHead = src.fRunHead; 650 if (fRunHead) { 651 sk_atomic_inc(&fRunHead->fRefCnt); 652 } 653 } 654 return *this; 655 } 656 657 bool operator==(const SkAAClip& a, const SkAAClip& b) { 658 a.validate(); 659 b.validate(); 660 661 if (&a == &b) { 662 return true; 663 } 664 if (a.fBounds != b.fBounds) { 665 return false; 666 } 667 668 const SkAAClip::RunHead* ah = a.fRunHead; 669 const SkAAClip::RunHead* bh = b.fRunHead; 670 671 // this catches empties and rects being equal 672 if (ah == bh) { 673 return true; 674 } 675 676 // now we insist that both are complex (but different ptrs) 677 if (!a.fRunHead || !b.fRunHead) { 678 return false; 679 } 680 681 return ah->fRowCount == bh->fRowCount && 682 ah->fDataSize == bh->fDataSize && 683 !memcmp(ah->data(), bh->data(), ah->fDataSize); 684 } 685 686 void SkAAClip::swap(SkAAClip& other) { 687 AUTO_AACLIP_VALIDATE(*this); 688 other.validate(); 689 690 SkTSwap(fBounds, other.fBounds); 691 SkTSwap(fRunHead, other.fRunHead); 692 } 693 694 bool SkAAClip::set(const SkAAClip& src) { 695 *this = src; 696 return !this->isEmpty(); 697 } 698 699 bool SkAAClip::setEmpty() { 700 this->freeRuns(); 701 fBounds.setEmpty(); 702 fRunHead = nullptr; 703 return false; 704 } 705 706 bool SkAAClip::setRect(const SkIRect& bounds) { 707 if (bounds.isEmpty()) { 708 return this->setEmpty(); 709 } 710 711 AUTO_AACLIP_VALIDATE(*this); 712 713 #if 0 714 SkRect r; 715 r.set(bounds); 716 SkPath path; 717 path.addRect(r); 718 return this->setPath(path); 719 #else 720 this->freeRuns(); 721 fBounds = bounds; 722 fRunHead = RunHead::AllocRect(bounds); 723 SkASSERT(!this->isEmpty()); 724 return true; 725 #endif 726 } 727 728 bool SkAAClip::isRect() const { 729 if (this->isEmpty()) { 730 return false; 731 } 732 733 const RunHead* head = fRunHead; 734 if (head->fRowCount != 1) { 735 return false; 736 } 737 const YOffset* yoff = head->yoffsets(); 738 if (yoff->fY != fBounds.fBottom - 1) { 739 return false; 740 } 741 742 const uint8_t* row = head->data() + yoff->fOffset; 743 int width = fBounds.width(); 744 do { 745 if (row[1] != 0xFF) { 746 return false; 747 } 748 int n = row[0]; 749 SkASSERT(n <= width); 750 width -= n; 751 row += 2; 752 } while (width > 0); 753 return true; 754 } 755 756 bool SkAAClip::setRect(const SkRect& r, bool doAA) { 757 if (r.isEmpty()) { 758 return this->setEmpty(); 759 } 760 761 AUTO_AACLIP_VALIDATE(*this); 762 763 // TODO: special case this 764 765 SkPath path; 766 path.addRect(r); 767 return this->setPath(path, nullptr, doAA); 768 } 769 770 static void append_run(SkTDArray<uint8_t>& array, uint8_t value, int count) { 771 SkASSERT(count >= 0); 772 while (count > 0) { 773 int n = count; 774 if (n > 255) { 775 n = 255; 776 } 777 uint8_t* data = array.append(2); 778 data[0] = n; 779 data[1] = value; 780 count -= n; 781 } 782 } 783 784 bool SkAAClip::setRegion(const SkRegion& rgn) { 785 if (rgn.isEmpty()) { 786 return this->setEmpty(); 787 } 788 if (rgn.isRect()) { 789 return this->setRect(rgn.getBounds()); 790 } 791 792 #if 0 793 SkAAClip clip; 794 SkRegion::Iterator iter(rgn); 795 for (; !iter.done(); iter.next()) { 796 clip.op(iter.rect(), SkRegion::kUnion_Op); 797 } 798 this->swap(clip); 799 return !this->isEmpty(); 800 #else 801 const SkIRect& bounds = rgn.getBounds(); 802 const int offsetX = bounds.fLeft; 803 const int offsetY = bounds.fTop; 804 805 SkTDArray<YOffset> yArray; 806 SkTDArray<uint8_t> xArray; 807 808 yArray.setReserve(SkMin32(bounds.height(), 1024)); 809 xArray.setReserve(SkMin32(bounds.width(), 512) * 128); 810 811 SkRegion::Iterator iter(rgn); 812 int prevRight = 0; 813 int prevBot = 0; 814 YOffset* currY = nullptr; 815 816 for (; !iter.done(); iter.next()) { 817 const SkIRect& r = iter.rect(); 818 SkASSERT(bounds.contains(r)); 819 820 int bot = r.fBottom - offsetY; 821 SkASSERT(bot >= prevBot); 822 if (bot > prevBot) { 823 if (currY) { 824 // flush current row 825 append_run(xArray, 0, bounds.width() - prevRight); 826 } 827 // did we introduce an empty-gap from the prev row? 828 int top = r.fTop - offsetY; 829 if (top > prevBot) { 830 currY = yArray.append(); 831 currY->fY = top - 1; 832 currY->fOffset = xArray.count(); 833 append_run(xArray, 0, bounds.width()); 834 } 835 // create a new record for this Y value 836 currY = yArray.append(); 837 currY->fY = bot - 1; 838 currY->fOffset = xArray.count(); 839 prevRight = 0; 840 prevBot = bot; 841 } 842 843 int x = r.fLeft - offsetX; 844 append_run(xArray, 0, x - prevRight); 845 846 int w = r.fRight - r.fLeft; 847 append_run(xArray, 0xFF, w); 848 prevRight = x + w; 849 SkASSERT(prevRight <= bounds.width()); 850 } 851 // flush last row 852 append_run(xArray, 0, bounds.width() - prevRight); 853 854 // now pack everything into a RunHead 855 RunHead* head = RunHead::Alloc(yArray.count(), xArray.bytes()); 856 memcpy(head->yoffsets(), yArray.begin(), yArray.bytes()); 857 memcpy(head->data(), xArray.begin(), xArray.bytes()); 858 859 this->setEmpty(); 860 fBounds = bounds; 861 fRunHead = head; 862 this->validate(); 863 return true; 864 #endif 865 } 866 867 /////////////////////////////////////////////////////////////////////////////// 868 869 const uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const { 870 SkASSERT(fRunHead); 871 872 if (!y_in_rect(y, fBounds)) { 873 return nullptr; 874 } 875 y -= fBounds.y(); // our yoffs values are relative to the top 876 877 const YOffset* yoff = fRunHead->yoffsets(); 878 while (yoff->fY < y) { 879 yoff += 1; 880 SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount); 881 } 882 883 if (lastYForRow) { 884 *lastYForRow = fBounds.y() + yoff->fY; 885 } 886 return fRunHead->data() + yoff->fOffset; 887 } 888 889 const uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const { 890 SkASSERT(x_in_rect(x, fBounds)); 891 x -= fBounds.x(); 892 893 // first skip up to X 894 for (;;) { 895 int n = data[0]; 896 if (x < n) { 897 if (initialCount) { 898 *initialCount = n - x; 899 } 900 break; 901 } 902 data += 2; 903 x -= n; 904 } 905 return data; 906 } 907 908 bool SkAAClip::quickContains(int left, int top, int right, int bottom) const { 909 if (this->isEmpty()) { 910 return false; 911 } 912 if (!fBounds.contains(left, top, right, bottom)) { 913 return false; 914 } 915 #if 0 916 if (this->isRect()) { 917 return true; 918 } 919 #endif 920 921 int lastY SK_INIT_TO_AVOID_WARNING; 922 const uint8_t* row = this->findRow(top, &lastY); 923 if (lastY < bottom) { 924 return false; 925 } 926 // now just need to check in X 927 int count; 928 row = this->findX(row, left, &count); 929 #if 0 930 return count >= (right - left) && 0xFF == row[1]; 931 #else 932 int rectWidth = right - left; 933 while (0xFF == row[1]) { 934 if (count >= rectWidth) { 935 return true; 936 } 937 rectWidth -= count; 938 row += 2; 939 count = row[0]; 940 } 941 return false; 942 #endif 943 } 944 945 /////////////////////////////////////////////////////////////////////////////// 946 947 class SkAAClip::Builder { 948 SkIRect fBounds; 949 struct Row { 950 int fY; 951 int fWidth; 952 SkTDArray<uint8_t>* fData; 953 }; 954 SkTDArray<Row> fRows; 955 Row* fCurrRow; 956 int fPrevY; 957 int fWidth; 958 int fMinY; 959 960 public: 961 Builder(const SkIRect& bounds) : fBounds(bounds) { 962 fPrevY = -1; 963 fWidth = bounds.width(); 964 fCurrRow = nullptr; 965 fMinY = bounds.fTop; 966 } 967 968 ~Builder() { 969 Row* row = fRows.begin(); 970 Row* stop = fRows.end(); 971 while (row < stop) { 972 delete row->fData; 973 row += 1; 974 } 975 } 976 977 const SkIRect& getBounds() const { return fBounds; } 978 979 void addRun(int x, int y, U8CPU alpha, int count) { 980 SkASSERT(count > 0); 981 SkASSERT(fBounds.contains(x, y)); 982 SkASSERT(fBounds.contains(x + count - 1, y)); 983 984 x -= fBounds.left(); 985 y -= fBounds.top(); 986 987 Row* row = fCurrRow; 988 if (y != fPrevY) { 989 SkASSERT(y > fPrevY); 990 fPrevY = y; 991 row = this->flushRow(true); 992 row->fY = y; 993 row->fWidth = 0; 994 SkASSERT(row->fData); 995 SkASSERT(0 == row->fData->count()); 996 fCurrRow = row; 997 } 998 999 SkASSERT(row->fWidth <= x); 1000 SkASSERT(row->fWidth < fBounds.width()); 1001 1002 SkTDArray<uint8_t>& data = *row->fData; 1003 1004 int gap = x - row->fWidth; 1005 if (gap) { 1006 AppendRun(data, 0, gap); 1007 row->fWidth += gap; 1008 SkASSERT(row->fWidth < fBounds.width()); 1009 } 1010 1011 AppendRun(data, alpha, count); 1012 row->fWidth += count; 1013 SkASSERT(row->fWidth <= fBounds.width()); 1014 } 1015 1016 void addColumn(int x, int y, U8CPU alpha, int height) { 1017 SkASSERT(fBounds.contains(x, y + height - 1)); 1018 1019 this->addRun(x, y, alpha, 1); 1020 this->flushRowH(fCurrRow); 1021 y -= fBounds.fTop; 1022 SkASSERT(y == fCurrRow->fY); 1023 fCurrRow->fY = y + height - 1; 1024 } 1025 1026 void addRectRun(int x, int y, int width, int height) { 1027 SkASSERT(fBounds.contains(x + width - 1, y + height - 1)); 1028 this->addRun(x, y, 0xFF, width); 1029 1030 // we assum the rect must be all we'll see for these scanlines 1031 // so we ensure our row goes all the way to our right 1032 this->flushRowH(fCurrRow); 1033 1034 y -= fBounds.fTop; 1035 SkASSERT(y == fCurrRow->fY); 1036 fCurrRow->fY = y + height - 1; 1037 } 1038 1039 void addAntiRectRun(int x, int y, int width, int height, 1040 SkAlpha leftAlpha, SkAlpha rightAlpha) { 1041 // According to SkBlitter.cpp, no matter whether leftAlpha is 0 or positive, 1042 // we should always consider [x, x+1] as the left-most column and [x+1, x+1+width] 1043 // as the rect with full alpha. 1044 SkASSERT(fBounds.contains(x + width + (rightAlpha > 0 ? 1 : 0), 1045 y + height - 1)); 1046 SkASSERT(width >= 0); 1047 1048 // Conceptually we're always adding 3 runs, but we should 1049 // merge or omit them if possible. 1050 if (leftAlpha == 0xFF) { 1051 width++; 1052 } else if (leftAlpha > 0) { 1053 this->addRun(x++, y, leftAlpha, 1); 1054 } else { 1055 // leftAlpha is 0, ignore the left column 1056 x++; 1057 } 1058 if (rightAlpha == 0xFF) { 1059 width++; 1060 } 1061 if (width > 0) { 1062 this->addRun(x, y, 0xFF, width); 1063 } 1064 if (rightAlpha > 0 && rightAlpha < 255) { 1065 this->addRun(x + width, y, rightAlpha, 1); 1066 } 1067 1068 // we assume the rect must be all we'll see for these scanlines 1069 // so we ensure our row goes all the way to our right 1070 this->flushRowH(fCurrRow); 1071 1072 y -= fBounds.fTop; 1073 SkASSERT(y == fCurrRow->fY); 1074 fCurrRow->fY = y + height - 1; 1075 } 1076 1077 bool finish(SkAAClip* target) { 1078 this->flushRow(false); 1079 1080 const Row* row = fRows.begin(); 1081 const Row* stop = fRows.end(); 1082 1083 size_t dataSize = 0; 1084 while (row < stop) { 1085 dataSize += row->fData->count(); 1086 row += 1; 1087 } 1088 1089 if (0 == dataSize) { 1090 return target->setEmpty(); 1091 } 1092 1093 SkASSERT(fMinY >= fBounds.fTop); 1094 SkASSERT(fMinY < fBounds.fBottom); 1095 int adjustY = fMinY - fBounds.fTop; 1096 fBounds.fTop = fMinY; 1097 1098 RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 1099 YOffset* yoffset = head->yoffsets(); 1100 uint8_t* data = head->data(); 1101 uint8_t* baseData = data; 1102 1103 row = fRows.begin(); 1104 SkDEBUGCODE(int prevY = row->fY - 1;) 1105 while (row < stop) { 1106 SkASSERT(prevY < row->fY); // must be monotonic 1107 SkDEBUGCODE(prevY = row->fY); 1108 1109 yoffset->fY = row->fY - adjustY; 1110 yoffset->fOffset = SkToU32(data - baseData); 1111 yoffset += 1; 1112 1113 size_t n = row->fData->count(); 1114 memcpy(data, row->fData->begin(), n); 1115 #ifdef SK_DEBUG 1116 size_t bytesNeeded = compute_row_length(data, fBounds.width()); 1117 SkASSERT(bytesNeeded == n); 1118 #endif 1119 data += n; 1120 1121 row += 1; 1122 } 1123 1124 target->freeRuns(); 1125 target->fBounds = fBounds; 1126 target->fRunHead = head; 1127 return target->trimBounds(); 1128 } 1129 1130 void dump() { 1131 this->validate(); 1132 int y; 1133 for (y = 0; y < fRows.count(); ++y) { 1134 const Row& row = fRows[y]; 1135 SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 1136 const SkTDArray<uint8_t>& data = *row.fData; 1137 int count = data.count(); 1138 SkASSERT(!(count & 1)); 1139 const uint8_t* ptr = data.begin(); 1140 for (int x = 0; x < count; x += 2) { 1141 SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 1142 ptr += 2; 1143 } 1144 SkDebugf("\n"); 1145 } 1146 } 1147 1148 void validate() { 1149 #ifdef SK_DEBUG 1150 if (false) { // avoid bit rot, suppress warning 1151 test_count_left_right_zeros(); 1152 } 1153 int prevY = -1; 1154 for (int i = 0; i < fRows.count(); ++i) { 1155 const Row& row = fRows[i]; 1156 SkASSERT(prevY < row.fY); 1157 SkASSERT(fWidth == row.fWidth); 1158 int count = row.fData->count(); 1159 const uint8_t* ptr = row.fData->begin(); 1160 SkASSERT(!(count & 1)); 1161 int w = 0; 1162 for (int x = 0; x < count; x += 2) { 1163 int n = ptr[0]; 1164 SkASSERT(n > 0); 1165 w += n; 1166 SkASSERT(w <= fWidth); 1167 ptr += 2; 1168 } 1169 SkASSERT(w == fWidth); 1170 prevY = row.fY; 1171 } 1172 #endif 1173 } 1174 1175 // only called by BuilderBlitter 1176 void setMinY(int y) { 1177 fMinY = y; 1178 } 1179 1180 private: 1181 void flushRowH(Row* row) { 1182 // flush current row if needed 1183 if (row->fWidth < fWidth) { 1184 AppendRun(*row->fData, 0, fWidth - row->fWidth); 1185 row->fWidth = fWidth; 1186 } 1187 } 1188 1189 Row* flushRow(bool readyForAnother) { 1190 Row* next = nullptr; 1191 int count = fRows.count(); 1192 if (count > 0) { 1193 this->flushRowH(&fRows[count - 1]); 1194 } 1195 if (count > 1) { 1196 // are our last two runs the same? 1197 Row* prev = &fRows[count - 2]; 1198 Row* curr = &fRows[count - 1]; 1199 SkASSERT(prev->fWidth == fWidth); 1200 SkASSERT(curr->fWidth == fWidth); 1201 if (*prev->fData == *curr->fData) { 1202 prev->fY = curr->fY; 1203 if (readyForAnother) { 1204 curr->fData->rewind(); 1205 next = curr; 1206 } else { 1207 delete curr->fData; 1208 fRows.removeShuffle(count - 1); 1209 } 1210 } else { 1211 if (readyForAnother) { 1212 next = fRows.append(); 1213 next->fData = new SkTDArray<uint8_t>; 1214 } 1215 } 1216 } else { 1217 if (readyForAnother) { 1218 next = fRows.append(); 1219 next->fData = new SkTDArray<uint8_t>; 1220 } 1221 } 1222 return next; 1223 } 1224 1225 static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 1226 do { 1227 int n = count; 1228 if (n > 255) { 1229 n = 255; 1230 } 1231 uint8_t* ptr = data.append(2); 1232 ptr[0] = n; 1233 ptr[1] = alpha; 1234 count -= n; 1235 } while (count > 0); 1236 } 1237 }; 1238 1239 class SkAAClip::BuilderBlitter : public SkBlitter { 1240 int fLastY; 1241 1242 /* 1243 If we see a gap of 1 or more empty scanlines while building in Y-order, 1244 we inject an explicit empty scanline (alpha==0) 1245 1246 See AAClipTest.cpp : test_path_with_hole() 1247 */ 1248 void checkForYGap(int y) { 1249 SkASSERT(y >= fLastY); 1250 if (fLastY > -SK_MaxS32) { 1251 int gap = y - fLastY; 1252 if (gap > 1) { 1253 fBuilder->addRun(fLeft, y - 1, 0, fRight - fLeft); 1254 } 1255 } 1256 fLastY = y; 1257 } 1258 1259 public: 1260 1261 BuilderBlitter(Builder* builder) { 1262 fBuilder = builder; 1263 fLeft = builder->getBounds().fLeft; 1264 fRight = builder->getBounds().fRight; 1265 fMinY = SK_MaxS32; 1266 fLastY = -SK_MaxS32; // sentinel 1267 } 1268 1269 void finish() { 1270 if (fMinY < SK_MaxS32) { 1271 fBuilder->setMinY(fMinY); 1272 } 1273 } 1274 1275 /** 1276 Must evaluate clips in scan-line order, so don't want to allow blitV(), 1277 but an AAClip can be clipped down to a single pixel wide, so we 1278 must support it (given AntiRect semantics: minimum width is 2). 1279 Instead we'll rely on the runtime asserts to guarantee Y monotonicity; 1280 any failure cases that misses may have minor artifacts. 1281 */ 1282 void blitV(int x, int y, int height, SkAlpha alpha) override { 1283 if (height == 1) { 1284 // We're still in scan-line order if height is 1 1285 // This is useful for Analytic AA 1286 const SkAlpha alphas[2] = {alpha, 0}; 1287 const int16_t runs[2] = {1, 0}; 1288 this->blitAntiH(x, y, alphas, runs); 1289 } else { 1290 this->recordMinY(y); 1291 fBuilder->addColumn(x, y, alpha, height); 1292 fLastY = y + height - 1; 1293 } 1294 } 1295 1296 void blitRect(int x, int y, int width, int height) override { 1297 this->recordMinY(y); 1298 this->checkForYGap(y); 1299 fBuilder->addRectRun(x, y, width, height); 1300 fLastY = y + height - 1; 1301 } 1302 1303 virtual void blitAntiRect(int x, int y, int width, int height, 1304 SkAlpha leftAlpha, SkAlpha rightAlpha) override { 1305 this->recordMinY(y); 1306 this->checkForYGap(y); 1307 fBuilder->addAntiRectRun(x, y, width, height, leftAlpha, rightAlpha); 1308 fLastY = y + height - 1; 1309 } 1310 1311 void blitMask(const SkMask&, const SkIRect& clip) override 1312 { unexpected(); } 1313 1314 const SkPixmap* justAnOpaqueColor(uint32_t*) override { 1315 return nullptr; 1316 } 1317 1318 void blitH(int x, int y, int width) override { 1319 this->recordMinY(y); 1320 this->checkForYGap(y); 1321 fBuilder->addRun(x, y, 0xFF, width); 1322 } 1323 1324 virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 1325 const int16_t runs[]) override { 1326 this->recordMinY(y); 1327 this->checkForYGap(y); 1328 for (;;) { 1329 int count = *runs; 1330 if (count <= 0) { 1331 return; 1332 } 1333 1334 // The supersampler's buffer can be the width of the device, so 1335 // we may have to trim the run to our bounds. Previously, we assert that 1336 // the extra spans are always alpha==0. 1337 // However, the analytic AA is too sensitive to precision errors 1338 // so it may have extra spans with very tiny alpha because after several 1339 // arithmatic operations, the edge may bleed the path boundary a little bit. 1340 // Therefore, instead of always asserting alpha==0, we assert alpha < 0x10. 1341 int localX = x; 1342 int localCount = count; 1343 if (x < fLeft) { 1344 SkASSERT(0x10 > *alpha); 1345 int gap = fLeft - x; 1346 SkASSERT(gap <= count); 1347 localX += gap; 1348 localCount -= gap; 1349 } 1350 int right = x + count; 1351 if (right > fRight) { 1352 SkASSERT(0x10 > *alpha); 1353 localCount -= right - fRight; 1354 SkASSERT(localCount >= 0); 1355 } 1356 1357 if (localCount) { 1358 fBuilder->addRun(localX, y, *alpha, localCount); 1359 } 1360 // Next run 1361 runs += count; 1362 alpha += count; 1363 x += count; 1364 } 1365 } 1366 1367 private: 1368 Builder* fBuilder; 1369 int fLeft; // cache of builder's bounds' left edge 1370 int fRight; 1371 int fMinY; 1372 1373 /* 1374 * We track this, in case the scan converter skipped some number of 1375 * scanlines at the (relative to the bounds it was given). This allows 1376 * the builder, during its finish, to trip its bounds down to the "real" 1377 * top. 1378 */ 1379 void recordMinY(int y) { 1380 if (y < fMinY) { 1381 fMinY = y; 1382 } 1383 } 1384 1385 void unexpected() { 1386 SK_ABORT("---- did not expect to get called here"); 1387 } 1388 }; 1389 1390 bool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 1391 AUTO_AACLIP_VALIDATE(*this); 1392 1393 if (clip && clip->isEmpty()) { 1394 return this->setEmpty(); 1395 } 1396 1397 SkIRect ibounds; 1398 path.getBounds().roundOut(&ibounds); 1399 1400 SkRegion tmpClip; 1401 if (nullptr == clip) { 1402 tmpClip.setRect(ibounds); 1403 clip = &tmpClip; 1404 } 1405 1406 // Since we assert that the BuilderBlitter will never blit outside the intersection 1407 // of clip and ibounds, we create this snugClip to be that intersection and send it 1408 // to the scan-converter. 1409 SkRegion snugClip(*clip); 1410 1411 if (path.isInverseFillType()) { 1412 ibounds = clip->getBounds(); 1413 } else { 1414 if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 1415 return this->setEmpty(); 1416 } 1417 snugClip.op(ibounds, SkRegion::kIntersect_Op); 1418 } 1419 1420 Builder builder(ibounds); 1421 BuilderBlitter blitter(&builder); 1422 1423 if (doAA) { 1424 SkScan::AntiFillPath(path, snugClip, &blitter, true); 1425 } else { 1426 SkScan::FillPath(path, snugClip, &blitter); 1427 } 1428 1429 blitter.finish(); 1430 return builder.finish(this); 1431 } 1432 1433 /////////////////////////////////////////////////////////////////////////////// 1434 1435 typedef void (*RowProc)(SkAAClip::Builder&, int bottom, 1436 const uint8_t* rowA, const SkIRect& rectA, 1437 const uint8_t* rowB, const SkIRect& rectB); 1438 1439 typedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 1440 1441 static U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1442 // Multiply 1443 return SkMulDiv255Round(alphaA, alphaB); 1444 } 1445 1446 static U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1447 // SrcOver 1448 return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 1449 } 1450 1451 static U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1452 // SrcOut 1453 return SkMulDiv255Round(alphaA, 0xFF - alphaB); 1454 } 1455 1456 static U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 1457 // XOR 1458 return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 1459 } 1460 1461 static AlphaProc find_alpha_proc(SkRegion::Op op) { 1462 switch (op) { 1463 case SkRegion::kIntersect_Op: 1464 return sectAlphaProc; 1465 case SkRegion::kDifference_Op: 1466 return diffAlphaProc; 1467 case SkRegion::kUnion_Op: 1468 return unionAlphaProc; 1469 case SkRegion::kXOR_Op: 1470 return xorAlphaProc; 1471 default: 1472 SkDEBUGFAIL("unexpected region op"); 1473 return sectAlphaProc; 1474 } 1475 } 1476 1477 class RowIter { 1478 public: 1479 RowIter(const uint8_t* row, const SkIRect& bounds) { 1480 fRow = row; 1481 fLeft = bounds.fLeft; 1482 fBoundsRight = bounds.fRight; 1483 if (row) { 1484 fRight = bounds.fLeft + row[0]; 1485 SkASSERT(fRight <= fBoundsRight); 1486 fAlpha = row[1]; 1487 fDone = false; 1488 } else { 1489 fDone = true; 1490 fRight = kMaxInt32; 1491 fAlpha = 0; 1492 } 1493 } 1494 1495 bool done() const { return fDone; } 1496 int left() const { return fLeft; } 1497 int right() const { return fRight; } 1498 U8CPU alpha() const { return fAlpha; } 1499 void next() { 1500 if (!fDone) { 1501 fLeft = fRight; 1502 if (fRight == fBoundsRight) { 1503 fDone = true; 1504 fRight = kMaxInt32; 1505 fAlpha = 0; 1506 } else { 1507 fRow += 2; 1508 fRight += fRow[0]; 1509 fAlpha = fRow[1]; 1510 SkASSERT(fRight <= fBoundsRight); 1511 } 1512 } 1513 } 1514 1515 private: 1516 const uint8_t* fRow; 1517 int fLeft; 1518 int fRight; 1519 int fBoundsRight; 1520 bool fDone; 1521 uint8_t fAlpha; 1522 }; 1523 1524 static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 1525 if (rite == riteA) { 1526 iter.next(); 1527 leftA = iter.left(); 1528 riteA = iter.right(); 1529 } 1530 } 1531 1532 #if 0 // UNUSED 1533 static bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 1534 SkASSERT(min < max); 1535 SkASSERT(boundsMin < boundsMax); 1536 if (min >= boundsMax || max <= boundsMin) { 1537 return false; 1538 } 1539 if (min < boundsMin) { 1540 min = boundsMin; 1541 } 1542 if (max > boundsMax) { 1543 max = boundsMax; 1544 } 1545 return true; 1546 } 1547 #endif 1548 1549 static void operatorX(SkAAClip::Builder& builder, int lastY, 1550 RowIter& iterA, RowIter& iterB, 1551 AlphaProc proc, const SkIRect& bounds) { 1552 int leftA = iterA.left(); 1553 int riteA = iterA.right(); 1554 int leftB = iterB.left(); 1555 int riteB = iterB.right(); 1556 1557 int prevRite = bounds.fLeft; 1558 1559 do { 1560 U8CPU alphaA = 0; 1561 U8CPU alphaB = 0; 1562 int left, rite; 1563 1564 if (leftA < leftB) { 1565 left = leftA; 1566 alphaA = iterA.alpha(); 1567 if (riteA <= leftB) { 1568 rite = riteA; 1569 } else { 1570 rite = leftA = leftB; 1571 } 1572 } else if (leftB < leftA) { 1573 left = leftB; 1574 alphaB = iterB.alpha(); 1575 if (riteB <= leftA) { 1576 rite = riteB; 1577 } else { 1578 rite = leftB = leftA; 1579 } 1580 } else { 1581 left = leftA; // or leftB, since leftA == leftB 1582 rite = leftA = leftB = SkMin32(riteA, riteB); 1583 alphaA = iterA.alpha(); 1584 alphaB = iterB.alpha(); 1585 } 1586 1587 if (left >= bounds.fRight) { 1588 break; 1589 } 1590 if (rite > bounds.fRight) { 1591 rite = bounds.fRight; 1592 } 1593 1594 if (left >= bounds.fLeft) { 1595 SkASSERT(rite > left); 1596 builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 1597 prevRite = rite; 1598 } 1599 1600 adjust_row(iterA, leftA, riteA, rite); 1601 adjust_row(iterB, leftB, riteB, rite); 1602 } while (!iterA.done() || !iterB.done()); 1603 1604 if (prevRite < bounds.fRight) { 1605 builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 1606 } 1607 } 1608 1609 static void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 1610 if (bot == botA) { 1611 iter.next(); 1612 topA = botA; 1613 SkASSERT(botA == iter.top()); 1614 botA = iter.bottom(); 1615 } 1616 } 1617 1618 static void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 1619 const SkAAClip& B, SkRegion::Op op) { 1620 AlphaProc proc = find_alpha_proc(op); 1621 const SkIRect& bounds = builder.getBounds(); 1622 1623 SkAAClip::Iter iterA(A); 1624 SkAAClip::Iter iterB(B); 1625 1626 SkASSERT(!iterA.done()); 1627 int topA = iterA.top(); 1628 int botA = iterA.bottom(); 1629 SkASSERT(!iterB.done()); 1630 int topB = iterB.top(); 1631 int botB = iterB.bottom(); 1632 1633 do { 1634 const uint8_t* rowA = nullptr; 1635 const uint8_t* rowB = nullptr; 1636 int top, bot; 1637 1638 if (topA < topB) { 1639 top = topA; 1640 rowA = iterA.data(); 1641 if (botA <= topB) { 1642 bot = botA; 1643 } else { 1644 bot = topA = topB; 1645 } 1646 1647 } else if (topB < topA) { 1648 top = topB; 1649 rowB = iterB.data(); 1650 if (botB <= topA) { 1651 bot = botB; 1652 } else { 1653 bot = topB = topA; 1654 } 1655 } else { 1656 top = topA; // or topB, since topA == topB 1657 bot = topA = topB = SkMin32(botA, botB); 1658 rowA = iterA.data(); 1659 rowB = iterB.data(); 1660 } 1661 1662 if (top >= bounds.fBottom) { 1663 break; 1664 } 1665 1666 if (bot > bounds.fBottom) { 1667 bot = bounds.fBottom; 1668 } 1669 SkASSERT(top < bot); 1670 1671 if (!rowA && !rowB) { 1672 builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 1673 } else if (top >= bounds.fTop) { 1674 SkASSERT(bot <= bounds.fBottom); 1675 RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 1676 RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1677 operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1678 } 1679 1680 adjust_iter(iterA, topA, botA, bot); 1681 adjust_iter(iterB, topB, botB, bot); 1682 } while (!iterA.done() || !iterB.done()); 1683 } 1684 1685 bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1686 SkRegion::Op op) { 1687 AUTO_AACLIP_VALIDATE(*this); 1688 1689 if (SkRegion::kReplace_Op == op) { 1690 return this->set(clipBOrig); 1691 } 1692 1693 const SkAAClip* clipA = &clipAOrig; 1694 const SkAAClip* clipB = &clipBOrig; 1695 1696 if (SkRegion::kReverseDifference_Op == op) { 1697 SkTSwap(clipA, clipB); 1698 op = SkRegion::kDifference_Op; 1699 } 1700 1701 bool a_empty = clipA->isEmpty(); 1702 bool b_empty = clipB->isEmpty(); 1703 1704 SkIRect bounds; 1705 switch (op) { 1706 case SkRegion::kDifference_Op: 1707 if (a_empty) { 1708 return this->setEmpty(); 1709 } 1710 if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1711 return this->set(*clipA); 1712 } 1713 bounds = clipA->fBounds; 1714 break; 1715 1716 case SkRegion::kIntersect_Op: 1717 if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1718 clipB->fBounds)) { 1719 return this->setEmpty(); 1720 } 1721 break; 1722 1723 case SkRegion::kUnion_Op: 1724 case SkRegion::kXOR_Op: 1725 if (a_empty) { 1726 return this->set(*clipB); 1727 } 1728 if (b_empty) { 1729 return this->set(*clipA); 1730 } 1731 bounds = clipA->fBounds; 1732 bounds.join(clipB->fBounds); 1733 break; 1734 1735 default: 1736 SkDEBUGFAIL("unknown region op"); 1737 return !this->isEmpty(); 1738 } 1739 1740 SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1741 SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1742 1743 Builder builder(bounds); 1744 operateY(builder, *clipA, *clipB, op); 1745 1746 return builder.finish(this); 1747 } 1748 1749 /* 1750 * It can be expensive to build a local aaclip before applying the op, so 1751 * we first see if we can restrict the bounds of new rect to our current 1752 * bounds, or note that the new rect subsumes our current clip. 1753 */ 1754 1755 bool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1756 SkIRect rStorage; 1757 const SkIRect* r = &rOrig; 1758 1759 switch (op) { 1760 case SkRegion::kIntersect_Op: 1761 if (!rStorage.intersect(rOrig, fBounds)) { 1762 // no overlap, so we're empty 1763 return this->setEmpty(); 1764 } 1765 if (rStorage == fBounds) { 1766 // we were wholly inside the rect, no change 1767 return !this->isEmpty(); 1768 } 1769 if (this->quickContains(rStorage)) { 1770 // the intersection is wholly inside us, we're a rect 1771 return this->setRect(rStorage); 1772 } 1773 r = &rStorage; // use the intersected bounds 1774 break; 1775 case SkRegion::kDifference_Op: 1776 break; 1777 case SkRegion::kUnion_Op: 1778 if (rOrig.contains(fBounds)) { 1779 return this->setRect(rOrig); 1780 } 1781 break; 1782 default: 1783 break; 1784 } 1785 1786 SkAAClip clip; 1787 clip.setRect(*r); 1788 return this->op(*this, clip, op); 1789 } 1790 1791 bool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1792 SkRect rStorage, boundsStorage; 1793 const SkRect* r = &rOrig; 1794 1795 boundsStorage.set(fBounds); 1796 switch (op) { 1797 case SkRegion::kIntersect_Op: 1798 case SkRegion::kDifference_Op: 1799 if (!rStorage.intersect(rOrig, boundsStorage)) { 1800 if (SkRegion::kIntersect_Op == op) { 1801 return this->setEmpty(); 1802 } else { // kDifference 1803 return !this->isEmpty(); 1804 } 1805 } 1806 r = &rStorage; // use the intersected bounds 1807 break; 1808 case SkRegion::kUnion_Op: 1809 if (rOrig.contains(boundsStorage)) { 1810 return this->setRect(rOrig); 1811 } 1812 break; 1813 default: 1814 break; 1815 } 1816 1817 SkAAClip clip; 1818 clip.setRect(*r, doAA); 1819 return this->op(*this, clip, op); 1820 } 1821 1822 bool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 1823 return this->op(*this, clip, op); 1824 } 1825 1826 /////////////////////////////////////////////////////////////////////////////// 1827 1828 bool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 1829 if (nullptr == dst) { 1830 return !this->isEmpty(); 1831 } 1832 1833 if (this->isEmpty()) { 1834 return dst->setEmpty(); 1835 } 1836 1837 if (this != dst) { 1838 sk_atomic_inc(&fRunHead->fRefCnt); 1839 dst->freeRuns(); 1840 dst->fRunHead = fRunHead; 1841 dst->fBounds = fBounds; 1842 } 1843 dst->fBounds.offset(dx, dy); 1844 return true; 1845 } 1846 1847 static void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1848 const uint8_t* SK_RESTRICT row, 1849 int width) { 1850 while (width > 0) { 1851 int n = row[0]; 1852 SkASSERT(width >= n); 1853 memset(mask, row[1], n); 1854 mask += n; 1855 row += 2; 1856 width -= n; 1857 } 1858 SkASSERT(0 == width); 1859 } 1860 1861 void SkAAClip::copyToMask(SkMask* mask) const { 1862 mask->fFormat = SkMask::kA8_Format; 1863 if (this->isEmpty()) { 1864 mask->fBounds.setEmpty(); 1865 mask->fImage = nullptr; 1866 mask->fRowBytes = 0; 1867 return; 1868 } 1869 1870 mask->fBounds = fBounds; 1871 mask->fRowBytes = fBounds.width(); 1872 size_t size = mask->computeImageSize(); 1873 mask->fImage = SkMask::AllocImage(size); 1874 1875 Iter iter(*this); 1876 uint8_t* dst = mask->fImage; 1877 const int width = fBounds.width(); 1878 1879 int y = fBounds.fTop; 1880 while (!iter.done()) { 1881 do { 1882 expand_row_to_mask(dst, iter.data(), width); 1883 dst += mask->fRowBytes; 1884 } while (++y < iter.bottom()); 1885 iter.next(); 1886 } 1887 } 1888 1889 /////////////////////////////////////////////////////////////////////////////// 1890 /////////////////////////////////////////////////////////////////////////////// 1891 1892 static void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1893 int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1894 // we don't read our initial n from data, since the caller may have had to 1895 // clip it, hence the initialCount parameter. 1896 int n = initialCount; 1897 for (;;) { 1898 if (n > width) { 1899 n = width; 1900 } 1901 SkASSERT(n > 0); 1902 runs[0] = n; 1903 runs += n; 1904 1905 aa[0] = data[1]; 1906 aa += n; 1907 1908 data += 2; 1909 width -= n; 1910 if (0 == width) { 1911 break; 1912 } 1913 // load the next count 1914 n = data[0]; 1915 } 1916 runs[0] = 0; // sentinel 1917 } 1918 1919 SkAAClipBlitter::~SkAAClipBlitter() { 1920 sk_free(fScanlineScratch); 1921 } 1922 1923 void SkAAClipBlitter::ensureRunsAndAA() { 1924 if (nullptr == fScanlineScratch) { 1925 // add 1 so we can store the terminating run count of 0 1926 int count = fAAClipBounds.width() + 1; 1927 // we use this either for fRuns + fAA, or a scaline of a mask 1928 // which may be as deep as 32bits 1929 fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1930 fRuns = (int16_t*)fScanlineScratch; 1931 fAA = (SkAlpha*)(fRuns + count); 1932 } 1933 } 1934 1935 void SkAAClipBlitter::blitH(int x, int y, int width) { 1936 SkASSERT(width > 0); 1937 SkASSERT(fAAClipBounds.contains(x, y)); 1938 SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1939 1940 const uint8_t* row = fAAClip->findRow(y); 1941 int initialCount; 1942 row = fAAClip->findX(row, x, &initialCount); 1943 1944 if (initialCount >= width) { 1945 SkAlpha alpha = row[1]; 1946 if (0 == alpha) { 1947 return; 1948 } 1949 if (0xFF == alpha) { 1950 fBlitter->blitH(x, y, width); 1951 return; 1952 } 1953 } 1954 1955 this->ensureRunsAndAA(); 1956 expandToRuns(row, initialCount, width, fRuns, fAA); 1957 1958 fBlitter->blitAntiH(x, y, fAA, fRuns); 1959 } 1960 1961 static void merge(const uint8_t* SK_RESTRICT row, int rowN, 1962 const SkAlpha* SK_RESTRICT srcAA, 1963 const int16_t* SK_RESTRICT srcRuns, 1964 SkAlpha* SK_RESTRICT dstAA, 1965 int16_t* SK_RESTRICT dstRuns, 1966 int width) { 1967 SkDEBUGCODE(int accumulated = 0;) 1968 int srcN = srcRuns[0]; 1969 // do we need this check? 1970 if (0 == srcN) { 1971 return; 1972 } 1973 1974 for (;;) { 1975 SkASSERT(rowN > 0); 1976 SkASSERT(srcN > 0); 1977 1978 unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1979 int minN = SkMin32(srcN, rowN); 1980 dstRuns[0] = minN; 1981 dstRuns += minN; 1982 dstAA[0] = newAlpha; 1983 dstAA += minN; 1984 1985 if (0 == (srcN -= minN)) { 1986 srcN = srcRuns[0]; // refresh 1987 srcRuns += srcN; 1988 srcAA += srcN; 1989 srcN = srcRuns[0]; // reload 1990 if (0 == srcN) { 1991 break; 1992 } 1993 } 1994 if (0 == (rowN -= minN)) { 1995 row += 2; 1996 rowN = row[0]; // reload 1997 } 1998 1999 SkDEBUGCODE(accumulated += minN;) 2000 SkASSERT(accumulated <= width); 2001 } 2002 dstRuns[0] = 0; 2003 } 2004 2005 void SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 2006 const int16_t runs[]) { 2007 2008 const uint8_t* row = fAAClip->findRow(y); 2009 int initialCount; 2010 row = fAAClip->findX(row, x, &initialCount); 2011 2012 this->ensureRunsAndAA(); 2013 2014 merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 2015 fBlitter->blitAntiH(x, y, fAA, fRuns); 2016 } 2017 2018 void SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 2019 if (fAAClip->quickContains(x, y, x + 1, y + height)) { 2020 fBlitter->blitV(x, y, height, alpha); 2021 return; 2022 } 2023 2024 for (;;) { 2025 int lastY SK_INIT_TO_AVOID_WARNING; 2026 const uint8_t* row = fAAClip->findRow(y, &lastY); 2027 int dy = lastY - y + 1; 2028 if (dy > height) { 2029 dy = height; 2030 } 2031 height -= dy; 2032 2033 row = fAAClip->findX(row, x); 2034 SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 2035 if (newAlpha) { 2036 fBlitter->blitV(x, y, dy, newAlpha); 2037 } 2038 SkASSERT(height >= 0); 2039 if (height <= 0) { 2040 break; 2041 } 2042 y = lastY + 1; 2043 } 2044 } 2045 2046 void SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 2047 if (fAAClip->quickContains(x, y, x + width, y + height)) { 2048 fBlitter->blitRect(x, y, width, height); 2049 return; 2050 } 2051 2052 while (--height >= 0) { 2053 this->blitH(x, y, width); 2054 y += 1; 2055 } 2056 } 2057 2058 typedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 2059 int initialRowCount, void* dst); 2060 2061 static void small_memcpy(void* dst, const void* src, size_t n) { 2062 memcpy(dst, src, n); 2063 } 2064 2065 static void small_bzero(void* dst, size_t n) { 2066 sk_bzero(dst, n); 2067 } 2068 2069 static inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 2070 return SkMulDiv255Round(value, alpha); 2071 } 2072 2073 static inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 2074 unsigned r = SkGetPackedR16(value); 2075 unsigned g = SkGetPackedG16(value); 2076 unsigned b = SkGetPackedB16(value); 2077 return SkPackRGB16(SkMulDiv255Round(r, alpha), 2078 SkMulDiv255Round(g, alpha), 2079 SkMulDiv255Round(b, alpha)); 2080 } 2081 2082 template <typename T> 2083 void mergeT(const void* inSrc, int srcN, const uint8_t* SK_RESTRICT row, int rowN, void* inDst) { 2084 const T* SK_RESTRICT src = static_cast<const T*>(inSrc); 2085 T* SK_RESTRICT dst = static_cast<T*>(inDst); 2086 for (;;) { 2087 SkASSERT(rowN > 0); 2088 SkASSERT(srcN > 0); 2089 2090 int n = SkMin32(rowN, srcN); 2091 unsigned rowA = row[1]; 2092 if (0xFF == rowA) { 2093 small_memcpy(dst, src, n * sizeof(T)); 2094 } else if (0 == rowA) { 2095 small_bzero(dst, n * sizeof(T)); 2096 } else { 2097 for (int i = 0; i < n; ++i) { 2098 dst[i] = mergeOne(src[i], rowA); 2099 } 2100 } 2101 2102 if (0 == (srcN -= n)) { 2103 break; 2104 } 2105 2106 src += n; 2107 dst += n; 2108 2109 SkASSERT(rowN == n); 2110 row += 2; 2111 rowN = row[0]; 2112 } 2113 } 2114 2115 static MergeAAProc find_merge_aa_proc(SkMask::Format format) { 2116 switch (format) { 2117 case SkMask::kBW_Format: 2118 SkDEBUGFAIL("unsupported"); 2119 return nullptr; 2120 case SkMask::kA8_Format: 2121 case SkMask::k3D_Format: 2122 return mergeT<uint8_t> ; 2123 case SkMask::kLCD16_Format: 2124 return mergeT<uint16_t>; 2125 default: 2126 SkDEBUGFAIL("unsupported"); 2127 return nullptr; 2128 } 2129 } 2130 2131 static U8CPU bit2byte(int bitInAByte) { 2132 SkASSERT(bitInAByte <= 0xFF); 2133 // negation turns any non-zero into 0xFFFFFF??, so we just shift down 2134 // some value >= 8 to get a full FF value 2135 return -bitInAByte >> 8; 2136 } 2137 2138 static void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 2139 SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 2140 SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 2141 2142 const int width = srcMask.fBounds.width(); 2143 const int height = srcMask.fBounds.height(); 2144 2145 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 2146 const size_t srcRB = srcMask.fRowBytes; 2147 uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 2148 const size_t dstRB = dstMask->fRowBytes; 2149 2150 const int wholeBytes = width >> 3; 2151 const int leftOverBits = width & 7; 2152 2153 for (int y = 0; y < height; ++y) { 2154 uint8_t* SK_RESTRICT d = dst; 2155 for (int i = 0; i < wholeBytes; ++i) { 2156 int srcByte = src[i]; 2157 d[0] = bit2byte(srcByte & (1 << 7)); 2158 d[1] = bit2byte(srcByte & (1 << 6)); 2159 d[2] = bit2byte(srcByte & (1 << 5)); 2160 d[3] = bit2byte(srcByte & (1 << 4)); 2161 d[4] = bit2byte(srcByte & (1 << 3)); 2162 d[5] = bit2byte(srcByte & (1 << 2)); 2163 d[6] = bit2byte(srcByte & (1 << 1)); 2164 d[7] = bit2byte(srcByte & (1 << 0)); 2165 d += 8; 2166 } 2167 if (leftOverBits) { 2168 int srcByte = src[wholeBytes]; 2169 for (int x = 0; x < leftOverBits; ++x) { 2170 *d++ = bit2byte(srcByte & 0x80); 2171 srcByte <<= 1; 2172 } 2173 } 2174 src += srcRB; 2175 dst += dstRB; 2176 } 2177 } 2178 2179 void SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 2180 SkASSERT(fAAClip->getBounds().contains(clip)); 2181 2182 if (fAAClip->quickContains(clip)) { 2183 fBlitter->blitMask(origMask, clip); 2184 return; 2185 } 2186 2187 const SkMask* mask = &origMask; 2188 2189 // if we're BW, we need to upscale to A8 (ugh) 2190 SkMask grayMask; 2191 if (SkMask::kBW_Format == origMask.fFormat) { 2192 grayMask.fFormat = SkMask::kA8_Format; 2193 grayMask.fBounds = origMask.fBounds; 2194 grayMask.fRowBytes = origMask.fBounds.width(); 2195 size_t size = grayMask.computeImageSize(); 2196 grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 2197 SkAutoMalloc::kReuse_OnShrink); 2198 2199 upscaleBW2A8(&grayMask, origMask); 2200 mask = &grayMask; 2201 } 2202 2203 this->ensureRunsAndAA(); 2204 2205 // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 2206 // data into a temp block to support it better (ugh) 2207 2208 const void* src = mask->getAddr(clip.fLeft, clip.fTop); 2209 const size_t srcRB = mask->fRowBytes; 2210 const int width = clip.width(); 2211 MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 2212 2213 SkMask rowMask; 2214 rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 2215 rowMask.fBounds.fLeft = clip.fLeft; 2216 rowMask.fBounds.fRight = clip.fRight; 2217 rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 2218 rowMask.fImage = (uint8_t*)fScanlineScratch; 2219 2220 int y = clip.fTop; 2221 const int stopY = y + clip.height(); 2222 2223 do { 2224 int localStopY SK_INIT_TO_AVOID_WARNING; 2225 const uint8_t* row = fAAClip->findRow(y, &localStopY); 2226 // findRow returns last Y, not stop, so we add 1 2227 localStopY = SkMin32(localStopY + 1, stopY); 2228 2229 int initialCount; 2230 row = fAAClip->findX(row, clip.fLeft, &initialCount); 2231 do { 2232 mergeProc(src, width, row, initialCount, rowMask.fImage); 2233 rowMask.fBounds.fTop = y; 2234 rowMask.fBounds.fBottom = y + 1; 2235 fBlitter->blitMask(rowMask, rowMask.fBounds); 2236 src = (const void*)((const char*)src + srcRB); 2237 } while (++y < localStopY); 2238 } while (y < stopY); 2239 } 2240 2241 const SkPixmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 2242 return nullptr; 2243 } 2244