1 /* 2 * Copyright 2006 The Android Open Source Project 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 9 #include "SkScanPriv.h" 10 #include "SkPath.h" 11 #include "SkMatrix.h" 12 #include "SkBlitter.h" 13 #include "SkRegion.h" 14 #include "SkAntiRun.h" 15 16 #define SHIFT 2 17 #define SCALE (1 << SHIFT) 18 #define MASK (SCALE - 1) 19 20 /** @file 21 We have two techniques for capturing the output of the supersampler: 22 - SUPERMASK, which records a large mask-bitmap 23 this is often faster for small, complex objects 24 - RLE, which records a rle-encoded scanline 25 this is often faster for large objects with big spans 26 27 These blitters use two coordinate systems: 28 - destination coordinates, scale equal to the output - often 29 abbreviated with 'i' or 'I' in variable names 30 - supersampled coordinates, scale equal to the output * SCALE 31 */ 32 33 //#define FORCE_SUPERMASK 34 //#define FORCE_RLE 35 36 /////////////////////////////////////////////////////////////////////////////// 37 38 /// Base class for a single-pass supersampled blitter. 39 class BaseSuperBlitter : public SkBlitter { 40 public: 41 BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 42 const SkRegion& clip, bool isInverse); 43 44 /// Must be explicitly defined on subclasses. 45 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 46 const int16_t runs[]) override { 47 SkDEBUGFAIL("How did I get here?"); 48 } 49 /// May not be called on BaseSuperBlitter because it blits out of order. 50 void blitV(int x, int y, int height, SkAlpha alpha) override { 51 SkDEBUGFAIL("How did I get here?"); 52 } 53 54 protected: 55 SkBlitter* fRealBlitter; 56 /// Current y coordinate, in destination coordinates. 57 int fCurrIY; 58 /// Widest row of region to be blitted, in destination coordinates. 59 int fWidth; 60 /// Leftmost x coordinate in any row, in destination coordinates. 61 int fLeft; 62 /// Leftmost x coordinate in any row, in supersampled coordinates. 63 int fSuperLeft; 64 65 SkDEBUGCODE(int fCurrX;) 66 /// Current y coordinate in supersampled coordinates. 67 int fCurrY; 68 /// Initial y coordinate (top of bounds). 69 int fTop; 70 71 SkIRect fSectBounds; 72 }; 73 74 BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlit, const SkIRect& ir, const SkRegion& clip, 75 bool isInverse) { 76 fRealBlitter = realBlit; 77 78 SkIRect sectBounds; 79 if (isInverse) { 80 // We use the clip bounds instead of the ir, since we may be asked to 81 //draw outside of the rect when we're a inverse filltype 82 sectBounds = clip.getBounds(); 83 } else { 84 if (!sectBounds.intersect(ir, clip.getBounds())) { 85 sectBounds.setEmpty(); 86 } 87 } 88 89 const int left = sectBounds.left(); 90 const int right = sectBounds.right(); 91 92 fLeft = left; 93 fSuperLeft = SkLeftShift(left, SHIFT); 94 fWidth = right - left; 95 fTop = sectBounds.top(); 96 fCurrIY = fTop - 1; 97 fCurrY = SkLeftShift(fTop, SHIFT) - 1; 98 99 SkDEBUGCODE(fCurrX = -1;) 100 } 101 102 /// Run-length-encoded supersampling antialiased blitter. 103 class SuperBlitter : public BaseSuperBlitter { 104 public: 105 SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip, bool isInverse); 106 107 ~SuperBlitter() override { 108 this->flush(); 109 } 110 111 /// Once fRuns contains a complete supersampled row, flush() blits 112 /// it out through the wrapped blitter. 113 void flush(); 114 115 /// Blits a row of pixels, with location and width specified 116 /// in supersampled coordinates. 117 void blitH(int x, int y, int width) override; 118 /// Blits a rectangle of pixels, with location and size specified 119 /// in supersampled coordinates. 120 void blitRect(int x, int y, int width, int height) override; 121 122 private: 123 // The next three variables are used to track a circular buffer that 124 // contains the values used in SkAlphaRuns. These variables should only 125 // ever be updated in advanceRuns(), and fRuns should always point to 126 // a valid SkAlphaRuns... 127 int fRunsToBuffer; 128 void* fRunsBuffer; 129 int fCurrentRun; 130 SkAlphaRuns fRuns; 131 132 // extra one to store the zero at the end 133 int getRunsSz() const { return (fWidth + 1 + (fWidth + 2)/2) * sizeof(int16_t); } 134 135 // This function updates the fRuns variable to point to the next buffer space 136 // with adequate storage for a SkAlphaRuns. It mostly just advances fCurrentRun 137 // and resets fRuns to point to an empty scanline. 138 void advanceRuns() { 139 const size_t kRunsSz = this->getRunsSz(); 140 fCurrentRun = (fCurrentRun + 1) % fRunsToBuffer; 141 fRuns.fRuns = reinterpret_cast<int16_t*>( 142 reinterpret_cast<uint8_t*>(fRunsBuffer) + fCurrentRun * kRunsSz); 143 fRuns.fAlpha = reinterpret_cast<SkAlpha*>(fRuns.fRuns + fWidth + 1); 144 fRuns.reset(fWidth); 145 } 146 147 int fOffsetX; 148 }; 149 150 SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip, 151 bool isInverse) 152 : BaseSuperBlitter(realBlitter, ir, clip, isInverse) 153 { 154 fRunsToBuffer = realBlitter->requestRowsPreserved(); 155 fRunsBuffer = realBlitter->allocBlitMemory(fRunsToBuffer * this->getRunsSz()); 156 fCurrentRun = -1; 157 158 this->advanceRuns(); 159 160 fOffsetX = 0; 161 } 162 163 void SuperBlitter::flush() { 164 if (fCurrIY >= fTop) { 165 166 SkASSERT(fCurrentRun < fRunsToBuffer); 167 if (!fRuns.empty()) { 168 // SkDEBUGCODE(fRuns.dump();) 169 fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns); 170 this->advanceRuns(); 171 fOffsetX = 0; 172 } 173 174 fCurrIY = fTop - 1; 175 SkDEBUGCODE(fCurrX = -1;) 176 } 177 } 178 179 /** coverage_to_partial_alpha() is being used by SkAlphaRuns, which 180 *accumulates* SCALE pixels worth of "alpha" in [0,(256/SCALE)] 181 to produce a final value in [0, 255] and handles clamping 256->255 182 itself, with the same (alpha - (alpha >> 8)) correction as 183 coverage_to_exact_alpha(). 184 */ 185 static inline int coverage_to_partial_alpha(int aa) { 186 aa <<= 8 - 2*SHIFT; 187 return aa; 188 } 189 190 /** coverage_to_exact_alpha() is being used by our blitter, which wants 191 a final value in [0, 255]. 192 */ 193 static inline int coverage_to_exact_alpha(int aa) { 194 int alpha = (256 >> SHIFT) * aa; 195 // clamp 256->255 196 return alpha - (alpha >> 8); 197 } 198 199 void SuperBlitter::blitH(int x, int y, int width) { 200 SkASSERT(width > 0); 201 202 int iy = y >> SHIFT; 203 SkASSERT(iy >= fCurrIY); 204 205 x -= fSuperLeft; 206 // hack, until I figure out why my cubics (I think) go beyond the bounds 207 if (x < 0) { 208 width += x; 209 x = 0; 210 } 211 212 #ifdef SK_DEBUG 213 SkASSERT(y != fCurrY || x >= fCurrX); 214 #endif 215 SkASSERT(y >= fCurrY); 216 if (fCurrY != y) { 217 fOffsetX = 0; 218 fCurrY = y; 219 } 220 221 if (iy != fCurrIY) { // new scanline 222 this->flush(); 223 fCurrIY = iy; 224 } 225 226 int start = x; 227 int stop = x + width; 228 229 SkASSERT(start >= 0 && stop > start); 230 // integer-pixel-aligned ends of blit, rounded out 231 int fb = start & MASK; 232 int fe = stop & MASK; 233 int n = (stop >> SHIFT) - (start >> SHIFT) - 1; 234 235 if (n < 0) { 236 fb = fe - fb; 237 n = 0; 238 fe = 0; 239 } else { 240 if (fb == 0) { 241 n += 1; 242 } else { 243 fb = SCALE - fb; 244 } 245 } 246 247 fOffsetX = fRuns.add(x >> SHIFT, coverage_to_partial_alpha(fb), 248 n, coverage_to_partial_alpha(fe), 249 (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT), 250 fOffsetX); 251 252 #ifdef SK_DEBUG 253 fRuns.assertValid(y & MASK, (1 << (8 - SHIFT))); 254 fCurrX = x + width; 255 #endif 256 } 257 258 #if 0 // UNUSED 259 static void set_left_rite_runs(SkAlphaRuns& runs, int ileft, U8CPU leftA, 260 int n, U8CPU riteA) { 261 SkASSERT(leftA <= 0xFF); 262 SkASSERT(riteA <= 0xFF); 263 264 int16_t* run = runs.fRuns; 265 uint8_t* aa = runs.fAlpha; 266 267 if (ileft > 0) { 268 run[0] = ileft; 269 aa[0] = 0; 270 run += ileft; 271 aa += ileft; 272 } 273 274 SkASSERT(leftA < 0xFF); 275 if (leftA > 0) { 276 *run++ = 1; 277 *aa++ = leftA; 278 } 279 280 if (n > 0) { 281 run[0] = n; 282 aa[0] = 0xFF; 283 run += n; 284 aa += n; 285 } 286 287 SkASSERT(riteA < 0xFF); 288 if (riteA > 0) { 289 *run++ = 1; 290 *aa++ = riteA; 291 } 292 run[0] = 0; 293 } 294 #endif 295 296 void SuperBlitter::blitRect(int x, int y, int width, int height) { 297 SkASSERT(width > 0); 298 SkASSERT(height > 0); 299 300 // blit leading rows 301 while ((y & MASK)) { 302 this->blitH(x, y++, width); 303 if (--height <= 0) { 304 return; 305 } 306 } 307 SkASSERT(height > 0); 308 309 // Since this is a rect, instead of blitting supersampled rows one at a 310 // time and then resolving to the destination canvas, we can blit 311 // directly to the destintion canvas one row per SCALE supersampled rows. 312 int start_y = y >> SHIFT; 313 int stop_y = (y + height) >> SHIFT; 314 int count = stop_y - start_y; 315 if (count > 0) { 316 y += count << SHIFT; 317 height -= count << SHIFT; 318 319 // save original X for our tail blitH() loop at the bottom 320 int origX = x; 321 322 x -= fSuperLeft; 323 // hack, until I figure out why my cubics (I think) go beyond the bounds 324 if (x < 0) { 325 width += x; 326 x = 0; 327 } 328 329 // There is always a left column, a middle, and a right column. 330 // ileft is the destination x of the first pixel of the entire rect. 331 // xleft is (SCALE - # of covered supersampled pixels) in that 332 // destination pixel. 333 int ileft = x >> SHIFT; 334 int xleft = x & MASK; 335 // irite is the destination x of the last pixel of the OPAQUE section. 336 // xrite is the number of supersampled pixels extending beyond irite; 337 // xrite/SCALE should give us alpha. 338 int irite = (x + width) >> SHIFT; 339 int xrite = (x + width) & MASK; 340 if (!xrite) { 341 xrite = SCALE; 342 irite--; 343 } 344 345 // Need to call flush() to clean up pending draws before we 346 // even consider blitV(), since otherwise it can look nonmonotonic. 347 SkASSERT(start_y > fCurrIY); 348 this->flush(); 349 350 int n = irite - ileft - 1; 351 if (n < 0) { 352 // If n < 0, we'll only have a single partially-transparent column 353 // of pixels to render. 354 xleft = xrite - xleft; 355 SkASSERT(xleft <= SCALE); 356 SkASSERT(xleft > 0); 357 fRealBlitter->blitV(ileft + fLeft, start_y, count, 358 coverage_to_exact_alpha(xleft)); 359 } else { 360 // With n = 0, we have two possibly-transparent columns of pixels 361 // to render; with n > 0, we have opaque columns between them. 362 363 xleft = SCALE - xleft; 364 365 // Using coverage_to_exact_alpha is not consistent with blitH() 366 const int coverageL = coverage_to_exact_alpha(xleft); 367 const int coverageR = coverage_to_exact_alpha(xrite); 368 369 SkASSERT(coverageL > 0 || n > 0 || coverageR > 0); 370 SkASSERT((coverageL != 0) + n + (coverageR != 0) <= fWidth); 371 372 fRealBlitter->blitAntiRect(ileft + fLeft, start_y, n, count, 373 coverageL, coverageR); 374 } 375 376 // preamble for our next call to blitH() 377 fCurrIY = stop_y - 1; 378 fOffsetX = 0; 379 fCurrY = y - 1; 380 fRuns.reset(fWidth); 381 x = origX; 382 } 383 384 // catch any remaining few rows 385 SkASSERT(height <= MASK); 386 while (--height >= 0) { 387 this->blitH(x, y++, width); 388 } 389 } 390 391 /////////////////////////////////////////////////////////////////////////////// 392 393 /// Masked supersampling antialiased blitter. 394 class MaskSuperBlitter : public BaseSuperBlitter { 395 public: 396 MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion&, bool isInverse); 397 ~MaskSuperBlitter() override { 398 fRealBlitter->blitMask(fMask, fClipRect); 399 } 400 401 void blitH(int x, int y, int width) override; 402 403 static bool CanHandleRect(const SkIRect& bounds) { 404 #ifdef FORCE_RLE 405 return false; 406 #endif 407 int width = bounds.width(); 408 int64_t rb = SkAlign4(width); 409 // use 64bits to detect overflow 410 int64_t storage = rb * bounds.height(); 411 412 return (width <= MaskSuperBlitter::kMAX_WIDTH) && 413 (storage <= MaskSuperBlitter::kMAX_STORAGE); 414 } 415 416 private: 417 enum { 418 #ifdef FORCE_SUPERMASK 419 kMAX_WIDTH = 2048, 420 kMAX_STORAGE = 1024 * 1024 * 2 421 #else 422 kMAX_WIDTH = 32, // so we don't try to do very wide things, where the RLE blitter would be faster 423 kMAX_STORAGE = 1024 424 #endif 425 }; 426 427 SkMask fMask; 428 SkIRect fClipRect; 429 // we add 1 because add_aa_span can write (unchanged) 1 extra byte at the end, rather than 430 // perform a test to see if stopAlpha != 0 431 uint32_t fStorage[(kMAX_STORAGE >> 2) + 1]; 432 }; 433 434 MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip, 435 bool isInverse) 436 : BaseSuperBlitter(realBlitter, ir, clip, isInverse) 437 { 438 SkASSERT(CanHandleRect(ir)); 439 SkASSERT(!isInverse); 440 441 fMask.fImage = (uint8_t*)fStorage; 442 fMask.fBounds = ir; 443 fMask.fRowBytes = ir.width(); 444 fMask.fFormat = SkMask::kA8_Format; 445 446 fClipRect = ir; 447 if (!fClipRect.intersect(clip.getBounds())) { 448 SkASSERT(0); 449 fClipRect.setEmpty(); 450 } 451 452 // For valgrind, write 1 extra byte at the end so we don't read 453 // uninitialized memory. See comment in add_aa_span and fStorage[]. 454 memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1); 455 } 456 457 static void add_aa_span(uint8_t* alpha, U8CPU startAlpha) { 458 /* I should be able to just add alpha[x] + startAlpha. 459 However, if the trailing edge of the previous span and the leading 460 edge of the current span round to the same super-sampled x value, 461 I might overflow to 256 with this add, hence the funny subtract. 462 */ 463 unsigned tmp = *alpha + startAlpha; 464 SkASSERT(tmp <= 256); 465 *alpha = SkToU8(tmp - (tmp >> 8)); 466 } 467 468 static inline uint32_t quadplicate_byte(U8CPU value) { 469 uint32_t pair = (value << 8) | value; 470 return (pair << 16) | pair; 471 } 472 473 // Perform this tricky subtract, to avoid overflowing to 256. Our caller should 474 // only ever call us with at most enough to hit 256 (never larger), so it is 475 // enough to just subtract the high-bit. Actually clamping with a branch would 476 // be slower (e.g. if (tmp > 255) tmp = 255;) 477 // 478 static inline void saturated_add(uint8_t* ptr, U8CPU add) { 479 unsigned tmp = *ptr + add; 480 SkASSERT(tmp <= 256); 481 *ptr = SkToU8(tmp - (tmp >> 8)); 482 } 483 484 // minimum count before we want to setup an inner loop, adding 4-at-a-time 485 #define MIN_COUNT_FOR_QUAD_LOOP 16 486 487 static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, 488 U8CPU stopAlpha, U8CPU maxValue) { 489 SkASSERT(middleCount >= 0); 490 491 saturated_add(alpha, startAlpha); 492 alpha += 1; 493 494 if (middleCount >= MIN_COUNT_FOR_QUAD_LOOP) { 495 // loop until we're quad-byte aligned 496 while (SkTCast<intptr_t>(alpha) & 0x3) { 497 alpha[0] = SkToU8(alpha[0] + maxValue); 498 alpha += 1; 499 middleCount -= 1; 500 } 501 502 int bigCount = middleCount >> 2; 503 uint32_t* qptr = reinterpret_cast<uint32_t*>(alpha); 504 uint32_t qval = quadplicate_byte(maxValue); 505 do { 506 *qptr++ += qval; 507 } while (--bigCount > 0); 508 509 middleCount &= 3; 510 alpha = reinterpret_cast<uint8_t*> (qptr); 511 // fall through to the following while-loop 512 } 513 514 while (--middleCount >= 0) { 515 alpha[0] = SkToU8(alpha[0] + maxValue); 516 alpha += 1; 517 } 518 519 // potentially this can be off the end of our "legal" alpha values, but that 520 // only happens if stopAlpha is also 0. Rather than test for stopAlpha != 0 521 // every time (slow), we just do it, and ensure that we've allocated extra space 522 // (see the + 1 comment in fStorage[] 523 saturated_add(alpha, stopAlpha); 524 } 525 526 void MaskSuperBlitter::blitH(int x, int y, int width) { 527 int iy = (y >> SHIFT); 528 529 SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom); 530 iy -= fMask.fBounds.fTop; // make it relative to 0 531 532 // This should never happen, but it does. Until the true cause is 533 // discovered, let's skip this span instead of crashing. 534 // See http://crbug.com/17569. 535 if (iy < 0) { 536 return; 537 } 538 539 #ifdef SK_DEBUG 540 { 541 int ix = x >> SHIFT; 542 SkASSERT(ix >= fMask.fBounds.fLeft && ix < fMask.fBounds.fRight); 543 } 544 #endif 545 546 x -= SkLeftShift(fMask.fBounds.fLeft, SHIFT); 547 548 // hack, until I figure out why my cubics (I think) go beyond the bounds 549 if (x < 0) { 550 width += x; 551 x = 0; 552 } 553 554 uint8_t* row = fMask.fImage + iy * fMask.fRowBytes + (x >> SHIFT); 555 556 int start = x; 557 int stop = x + width; 558 559 SkASSERT(start >= 0 && stop > start); 560 int fb = start & MASK; 561 int fe = stop & MASK; 562 int n = (stop >> SHIFT) - (start >> SHIFT) - 1; 563 564 565 if (n < 0) { 566 SkASSERT(row >= fMask.fImage); 567 SkASSERT(row < fMask.fImage + kMAX_STORAGE + 1); 568 add_aa_span(row, coverage_to_partial_alpha(fe - fb)); 569 } else { 570 fb = SCALE - fb; 571 SkASSERT(row >= fMask.fImage); 572 SkASSERT(row + n + 1 < fMask.fImage + kMAX_STORAGE + 1); 573 add_aa_span(row, coverage_to_partial_alpha(fb), 574 n, coverage_to_partial_alpha(fe), 575 (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT)); 576 } 577 578 #ifdef SK_DEBUG 579 fCurrX = x + width; 580 #endif 581 } 582 583 /////////////////////////////////////////////////////////////////////////////// 584 585 void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip, 586 SkBlitter* blitter, bool forceRLE) { 587 FillPathFunc fillPathFunc = [](const SkPath& path, SkBlitter* blitter, bool isInverse, 588 const SkIRect& ir, const SkRegion* clipRgn, const SkIRect* clipRect, bool forceRLE){ 589 SkIRect superRect, *superClipRect = nullptr; 590 if (clipRect) { 591 superRect.set(SkLeftShift(clipRect->fLeft, SHIFT), 592 SkLeftShift(clipRect->fTop, SHIFT), 593 SkLeftShift(clipRect->fRight, SHIFT), 594 SkLeftShift(clipRect->fBottom, SHIFT)); 595 superClipRect = &superRect; 596 } 597 598 // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it 599 // if we're an inverse filltype 600 if (!isInverse && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) { 601 MaskSuperBlitter superBlit(blitter, ir, *clipRgn, isInverse); 602 SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); 603 sk_fill_path(path, clipRgn->getBounds(), &superBlit, ir.fTop, ir.fBottom, SHIFT, 604 superClipRect == nullptr); 605 } else { 606 SuperBlitter superBlit(blitter, ir, *clipRgn, isInverse); 607 sk_fill_path(path, clipRgn->getBounds(), &superBlit, ir.fTop, ir.fBottom, SHIFT, 608 superClipRect == nullptr); 609 } 610 }; 611 612 do_fill_path(path, origClip, blitter, forceRLE, SHIFT, std::move(fillPathFunc)); 613 } 614 615 /////////////////////////////////////////////////////////////////////////////// 616 617 #include "SkRasterClip.h" 618 619 void SkScan::FillPath(const SkPath& path, const SkRasterClip& clip, 620 SkBlitter* blitter) { 621 if (clip.isEmpty()) { 622 return; 623 } 624 625 if (clip.isBW()) { 626 FillPath(path, clip.bwRgn(), blitter); 627 } else { 628 SkRegion tmp; 629 SkAAClipBlitter aaBlitter; 630 631 tmp.setRect(clip.getBounds()); 632 aaBlitter.init(blitter, &clip.aaRgn()); 633 SkScan::FillPath(path, tmp, &aaBlitter); 634 } 635 } 636 637 static bool suitableForAAA(const SkPath& path) { 638 if (gSkForceAnalyticAA.load()) { 639 return true; 640 } 641 if (path.isRect(nullptr)) { 642 return true; 643 } 644 const SkRect& bounds = path.getBounds(); 645 // When the path have so many points compared to the size of its bounds/resolution, 646 // it indicates that the path is not quite smooth in the current resolution: 647 // the expected number of turning points in every pixel row/column is significantly greater than 648 // zero. Hence Aanlytic AA is not likely to produce visible quality improvements, and Analytic 649 // AA might be slower than supersampling. 650 return path.countPoints() < SkTMax(bounds.width(), bounds.height()) / 2 - 10; 651 } 652 653 void SkScan::AntiFillPath(const SkPath& path, const SkRasterClip& clip, 654 SkBlitter* blitter) { 655 if (clip.isEmpty()) { 656 return; 657 } 658 659 using FillPathProc = void(*)(const SkPath&, const SkRegion&, SkBlitter*, bool); 660 FillPathProc fillPathProc = &SkScan::AntiFillPath; 661 662 // Do not use AAA if path is too complicated: 663 // there won't be any speedup or significant visual improvement. 664 if (gSkUseAnalyticAA.load() && suitableForAAA(path)) { 665 fillPathProc = &SkScan::AAAFillPath; 666 } 667 668 if (clip.isBW()) { 669 fillPathProc(path, clip.bwRgn(), blitter, false); 670 } else { 671 SkRegion tmp; 672 SkAAClipBlitter aaBlitter; 673 674 tmp.setRect(clip.getBounds()); 675 aaBlitter.init(blitter, &clip.aaRgn()); 676 fillPathProc(path, tmp, &aaBlitter, true); 677 } 678 } 679