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 |