| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 The Android Open Source Project | 3 * Copyright 2011 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkScan.h" | 10 #include "SkScan.h" |
| 11 #include "SkBlitter.h" | 11 #include "SkBlitter.h" |
| 12 #include "SkColorPriv.h" | 12 #include "SkColorPriv.h" |
| 13 #include "SkLineClipper.h" | 13 #include "SkLineClipper.h" |
| 14 #include "SkRasterClip.h" | 14 #include "SkRasterClip.h" |
| 15 #include "SkFDot6.h" | 15 #include "SkFDot6.h" |
| 16 | 16 |
| 17 /* Our attempt to compute the worst case "bounds" for the horizontal and | 17 /* Our attempt to compute the worst case "bounds" for the horizontal and |
| 18 vertical cases has some numerical bug in it, and we sometimes undervalue | 18 vertical cases has some numerical bug in it, and we sometimes undervalue |
| 19 our extends. The bug is that when this happens, we will set the clip to | 19 our extends. The bug is that when this happens, we will set the clip to |
| 20 NULL (for speed), and thus draw outside of the clip by a pixel, which might | 20 nullptr (for speed), and thus draw outside of the clip by a pixel, which mig
ht |
| 21 only look bad, but it might also access memory outside of the valid range | 21 only look bad, but it might also access memory outside of the valid range |
| 22 allcoated for the device bitmap. | 22 allcoated for the device bitmap. |
| 23 | 23 |
| 24 This define enables our fix to outset our "bounds" by 1, thus avoiding the | 24 This define enables our fix to outset our "bounds" by 1, thus avoiding the |
| 25 chance of the bug, but at the cost of sometimes taking the rectblitter | 25 chance of the bug, but at the cost of sometimes taking the rectblitter |
| 26 case (i.e. not setting the clip to NULL) when we might not actually need | 26 case (i.e. not setting the clip to nullptr) when we might not actually need |
| 27 to. If we can improve/fix the actual calculations, then we can remove this | 27 to. If we can improve/fix the actual calculations, then we can remove this |
| 28 step. | 28 step. |
| 29 */ | 29 */ |
| 30 #define OUTSET_BEFORE_CLIP_TEST true | 30 #define OUTSET_BEFORE_CLIP_TEST true |
| 31 | 31 |
| 32 #define HLINE_STACK_BUFFER 100 | 32 #define HLINE_STACK_BUFFER 100 |
| 33 | 33 |
| 34 static inline int SmallDot6Scale(int value, int dot6) { | 34 static inline int SmallDot6Scale(int value, int dot6) { |
| 35 SkASSERT((int16_t)value == value); | 35 SkASSERT((int16_t)value == value); |
| 36 SkASSERT((unsigned)dot6 <= 64); | 36 SkASSERT((unsigned)dot6 <= 64); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 runs[0] = SkToS16(n); | 81 runs[0] = SkToS16(n); |
| 82 runs[n] = 0; | 82 runs[n] = 0; |
| 83 blitter->blitAntiH(x, y, aa, runs); | 83 blitter->blitAntiH(x, y, aa, runs); |
| 84 x += n; | 84 x += n; |
| 85 count -= n; | 85 count -= n; |
| 86 } while (count > 0); | 86 } while (count > 0); |
| 87 } | 87 } |
| 88 | 88 |
| 89 class SkAntiHairBlitter { | 89 class SkAntiHairBlitter { |
| 90 public: | 90 public: |
| 91 SkAntiHairBlitter() : fBlitter(NULL) {} | 91 SkAntiHairBlitter() : fBlitter(nullptr) {} |
| 92 virtual ~SkAntiHairBlitter() {} | 92 virtual ~SkAntiHairBlitter() {} |
| 93 | 93 |
| 94 SkBlitter* getBlitter() const { return fBlitter; } | 94 SkBlitter* getBlitter() const { return fBlitter; } |
| 95 | 95 |
| 96 void setup(SkBlitter* blitter) { | 96 void setup(SkBlitter* blitter) { |
| 97 fBlitter = blitter; | 97 fBlitter = blitter; |
| 98 } | 98 } |
| 99 | 99 |
| 100 virtual SkFixed drawCap(int x, SkFixed fy, SkFixed slope, int mod64) = 0; | 100 virtual SkFixed drawCap(int x, SkFixed fy, SkFixed slope, int mod64) = 0; |
| 101 virtual SkFixed drawLine(int x, int stopx, SkFixed fy, SkFixed slope) = 0; | 101 virtual SkFixed drawLine(int x, int stopx, SkFixed fy, SkFixed slope) = 0; |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 } | 333 } |
| 334 | 334 |
| 335 int scaleStart, scaleStop; | 335 int scaleStart, scaleStop; |
| 336 int istart, istop; | 336 int istart, istop; |
| 337 SkFixed fstart, slope; | 337 SkFixed fstart, slope; |
| 338 | 338 |
| 339 HLine_SkAntiHairBlitter hline_blitter; | 339 HLine_SkAntiHairBlitter hline_blitter; |
| 340 Horish_SkAntiHairBlitter horish_blitter; | 340 Horish_SkAntiHairBlitter horish_blitter; |
| 341 VLine_SkAntiHairBlitter vline_blitter; | 341 VLine_SkAntiHairBlitter vline_blitter; |
| 342 Vertish_SkAntiHairBlitter vertish_blitter; | 342 Vertish_SkAntiHairBlitter vertish_blitter; |
| 343 SkAntiHairBlitter* hairBlitter = NULL; | 343 SkAntiHairBlitter* hairBlitter = nullptr; |
| 344 | 344 |
| 345 if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) { // mostly horizontal | 345 if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) { // mostly horizontal |
| 346 if (x0 > x1) { // we want to go left-to-right | 346 if (x0 > x1) { // we want to go left-to-right |
| 347 SkTSwap<SkFDot6>(x0, x1); | 347 SkTSwap<SkFDot6>(x0, x1); |
| 348 SkTSwap<SkFDot6>(y0, y1); | 348 SkTSwap<SkFDot6>(y0, y1); |
| 349 } | 349 } |
| 350 | 350 |
| 351 istart = SkFDot6Floor(x0); | 351 istart = SkFDot6Floor(x0); |
| 352 istop = SkFDot6Ceil(x1); | 352 istop = SkFDot6Ceil(x1); |
| 353 fstart = SkFDot6ToFixed(y0); | 353 fstart = SkFDot6ToFixed(y0); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 top = SkFixedFloorToInt(fstart + (istop - istart - 1) * slope -
SK_FixedHalf); | 405 top = SkFixedFloorToInt(fstart + (istop - istart - 1) * slope -
SK_FixedHalf); |
| 406 } | 406 } |
| 407 #ifdef OUTSET_BEFORE_CLIP_TEST | 407 #ifdef OUTSET_BEFORE_CLIP_TEST |
| 408 top -= 1; | 408 top -= 1; |
| 409 bottom += 1; | 409 bottom += 1; |
| 410 #endif | 410 #endif |
| 411 if (top >= clip->fBottom || bottom <= clip->fTop) { | 411 if (top >= clip->fBottom || bottom <= clip->fTop) { |
| 412 return; | 412 return; |
| 413 } | 413 } |
| 414 if (clip->fTop <= top && clip->fBottom >= bottom) { | 414 if (clip->fTop <= top && clip->fBottom >= bottom) { |
| 415 clip = NULL; | 415 clip = nullptr; |
| 416 } | 416 } |
| 417 } | 417 } |
| 418 } else { // mostly vertical | 418 } else { // mostly vertical |
| 419 if (y0 > y1) { // we want to go top-to-bottom | 419 if (y0 > y1) { // we want to go top-to-bottom |
| 420 SkTSwap<SkFDot6>(x0, x1); | 420 SkTSwap<SkFDot6>(x0, x1); |
| 421 SkTSwap<SkFDot6>(y0, y1); | 421 SkTSwap<SkFDot6>(y0, y1); |
| 422 } | 422 } |
| 423 | 423 |
| 424 istart = SkFDot6Floor(y0); | 424 istart = SkFDot6Floor(y0); |
| 425 istop = SkFDot6Ceil(y1); | 425 istop = SkFDot6Ceil(y1); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 left = SkFixedFloorToInt(fstart + (istop - istart - 1) * slope -
SK_FixedHalf); | 481 left = SkFixedFloorToInt(fstart + (istop - istart - 1) * slope -
SK_FixedHalf); |
| 482 } | 482 } |
| 483 #ifdef OUTSET_BEFORE_CLIP_TEST | 483 #ifdef OUTSET_BEFORE_CLIP_TEST |
| 484 left -= 1; | 484 left -= 1; |
| 485 right += 1; | 485 right += 1; |
| 486 #endif | 486 #endif |
| 487 if (left >= clip->fRight || right <= clip->fLeft) { | 487 if (left >= clip->fRight || right <= clip->fLeft) { |
| 488 return; | 488 return; |
| 489 } | 489 } |
| 490 if (clip->fLeft <= left && clip->fRight >= right) { | 490 if (clip->fLeft <= left && clip->fRight >= right) { |
| 491 clip = NULL; | 491 clip = nullptr; |
| 492 } | 492 } |
| 493 } | 493 } |
| 494 } | 494 } |
| 495 | 495 |
| 496 SkRectClipBlitter rectClipper; | 496 SkRectClipBlitter rectClipper; |
| 497 if (clip) { | 497 if (clip) { |
| 498 rectClipper.init(blitter, *clip); | 498 rectClipper.init(blitter, *clip); |
| 499 blitter = &rectClipper; | 499 blitter = &rectClipper; |
| 500 } | 500 } |
| 501 | 501 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 519 hairBlitter->drawCap(istop - 1, fstart, slope, scaleStop); | 519 hairBlitter->drawCap(istop - 1, fstart, slope, scaleStop); |
| 520 } | 520 } |
| 521 } | 521 } |
| 522 | 522 |
| 523 void SkScan::AntiHairLineRgn(const SkPoint array[], int arrayCount, const SkRegi
on* clip, | 523 void SkScan::AntiHairLineRgn(const SkPoint array[], int arrayCount, const SkRegi
on* clip, |
| 524 SkBlitter* blitter) { | 524 SkBlitter* blitter) { |
| 525 if (clip && clip->isEmpty()) { | 525 if (clip && clip->isEmpty()) { |
| 526 return; | 526 return; |
| 527 } | 527 } |
| 528 | 528 |
| 529 SkASSERT(clip == NULL || !clip->getBounds().isEmpty()); | 529 SkASSERT(clip == nullptr || !clip->getBounds().isEmpty()); |
| 530 | 530 |
| 531 #ifdef TEST_GAMMA | 531 #ifdef TEST_GAMMA |
| 532 build_gamma_table(); | 532 build_gamma_table(); |
| 533 #endif | 533 #endif |
| 534 | 534 |
| 535 const SkScalar max = SkIntToScalar(32767); | 535 const SkScalar max = SkIntToScalar(32767); |
| 536 const SkRect fixedBounds = SkRect::MakeLTRB(-max, -max, max, max); | 536 const SkRect fixedBounds = SkRect::MakeLTRB(-max, -max, max, max); |
| 537 | 537 |
| 538 SkRect clipBounds; | 538 SkRect clipBounds; |
| 539 if (clip) { | 539 if (clip) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 const SkIRect* r = &iter.rect(); | 588 const SkIRect* r = &iter.rect(); |
| 589 | 589 |
| 590 while (!iter.done()) { | 590 while (!iter.done()) { |
| 591 do_anti_hairline(x0, y0, x1, y1, r, blitter); | 591 do_anti_hairline(x0, y0, x1, y1, r, blitter); |
| 592 iter.next(); | 592 iter.next(); |
| 593 } | 593 } |
| 594 continue; | 594 continue; |
| 595 } | 595 } |
| 596 // fall through to no-clip case | 596 // fall through to no-clip case |
| 597 } | 597 } |
| 598 do_anti_hairline(x0, y0, x1, y1, NULL, blitter); | 598 do_anti_hairline(x0, y0, x1, y1, nullptr, blitter); |
| 599 } | 599 } |
| 600 } | 600 } |
| 601 | 601 |
| 602 void SkScan::AntiHairRect(const SkRect& rect, const SkRasterClip& clip, | 602 void SkScan::AntiHairRect(const SkRect& rect, const SkRasterClip& clip, |
| 603 SkBlitter* blitter) { | 603 SkBlitter* blitter) { |
| 604 SkPoint pts[5]; | 604 SkPoint pts[5]; |
| 605 | 605 |
| 606 pts[0].set(rect.fLeft, rect.fTop); | 606 pts[0].set(rect.fLeft, rect.fTop); |
| 607 pts[1].set(rect.fRight, rect.fTop); | 607 pts[1].set(rect.fRight, rect.fTop); |
| 608 pts[2].set(rect.fRight, rect.fBottom); | 608 pts[2].set(rect.fRight, rect.fBottom); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 static void antifillrect(const SkXRect& xr, SkBlitter* blitter) { | 692 static void antifillrect(const SkXRect& xr, SkBlitter* blitter) { |
| 693 antifilldot8(SkFixedToFDot8(xr.fLeft), SkFixedToFDot8(xr.fTop), | 693 antifilldot8(SkFixedToFDot8(xr.fLeft), SkFixedToFDot8(xr.fTop), |
| 694 SkFixedToFDot8(xr.fRight), SkFixedToFDot8(xr.fBottom), | 694 SkFixedToFDot8(xr.fRight), SkFixedToFDot8(xr.fBottom), |
| 695 blitter, true); | 695 blitter, true); |
| 696 } | 696 } |
| 697 | 697 |
| 698 /////////////////////////////////////////////////////////////////////////////// | 698 /////////////////////////////////////////////////////////////////////////////// |
| 699 | 699 |
| 700 void SkScan::AntiFillXRect(const SkXRect& xr, const SkRegion* clip, | 700 void SkScan::AntiFillXRect(const SkXRect& xr, const SkRegion* clip, |
| 701 SkBlitter* blitter) { | 701 SkBlitter* blitter) { |
| 702 if (NULL == clip) { | 702 if (nullptr == clip) { |
| 703 antifillrect(xr, blitter); | 703 antifillrect(xr, blitter); |
| 704 } else { | 704 } else { |
| 705 SkIRect outerBounds; | 705 SkIRect outerBounds; |
| 706 XRect_roundOut(xr, &outerBounds); | 706 XRect_roundOut(xr, &outerBounds); |
| 707 | 707 |
| 708 if (clip->isRect()) { | 708 if (clip->isRect()) { |
| 709 const SkIRect& clipBounds = clip->getBounds(); | 709 const SkIRect& clipBounds = clip->getBounds(); |
| 710 | 710 |
| 711 if (clipBounds.contains(outerBounds)) { | 711 if (clipBounds.contains(outerBounds)) { |
| 712 antifillrect(xr, blitter); | 712 antifillrect(xr, blitter); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 738 | 738 |
| 739 void SkScan::AntiFillXRect(const SkXRect& xr, const SkRasterClip& clip, | 739 void SkScan::AntiFillXRect(const SkXRect& xr, const SkRasterClip& clip, |
| 740 SkBlitter* blitter) { | 740 SkBlitter* blitter) { |
| 741 if (clip.isBW()) { | 741 if (clip.isBW()) { |
| 742 AntiFillXRect(xr, &clip.bwRgn(), blitter); | 742 AntiFillXRect(xr, &clip.bwRgn(), blitter); |
| 743 } else { | 743 } else { |
| 744 SkIRect outerBounds; | 744 SkIRect outerBounds; |
| 745 XRect_roundOut(xr, &outerBounds); | 745 XRect_roundOut(xr, &outerBounds); |
| 746 | 746 |
| 747 if (clip.quickContains(outerBounds)) { | 747 if (clip.quickContains(outerBounds)) { |
| 748 AntiFillXRect(xr, NULL, blitter); | 748 AntiFillXRect(xr, nullptr, blitter); |
| 749 } else { | 749 } else { |
| 750 SkAAClipBlitterWrapper wrapper(clip, blitter); | 750 SkAAClipBlitterWrapper wrapper(clip, blitter); |
| 751 blitter = wrapper.getBlitter(); | 751 blitter = wrapper.getBlitter(); |
| 752 | 752 |
| 753 AntiFillXRect(xr, &wrapper.getRgn(), wrapper.getBlitter()); | 753 AntiFillXRect(xr, &wrapper.getRgn(), wrapper.getBlitter()); |
| 754 } | 754 } |
| 755 } | 755 } |
| 756 } | 756 } |
| 757 | 757 |
| 758 /* This guy takes a float-rect, but with the key improvement that it has | 758 /* This guy takes a float-rect, but with the key improvement that it has |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 | 994 |
| 995 void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, | 995 void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, |
| 996 const SkRasterClip& clip, SkBlitter* blitter) { | 996 const SkRasterClip& clip, SkBlitter* blitter) { |
| 997 if (clip.isBW()) { | 997 if (clip.isBW()) { |
| 998 AntiFrameRect(r, strokeSize, &clip.bwRgn(), blitter); | 998 AntiFrameRect(r, strokeSize, &clip.bwRgn(), blitter); |
| 999 } else { | 999 } else { |
| 1000 SkAAClipBlitterWrapper wrap(clip, blitter); | 1000 SkAAClipBlitterWrapper wrap(clip, blitter); |
| 1001 AntiFrameRect(r, strokeSize, &wrap.getRgn(), wrap.getBlitter()); | 1001 AntiFrameRect(r, strokeSize, &wrap.getRgn(), wrap.getBlitter()); |
| 1002 } | 1002 } |
| 1003 } | 1003 } |
| OLD | NEW |