diff --git a/gm/pathfill.cpp b/gm/pathfill.cpp index 6da507da3..f9fa6e995 100644 --- a/gm/pathfill.cpp +++ b/gm/pathfill.cpp @@ -117,9 +117,7 @@ static const MakePathProc gProcs[] = { #define N SK_ARRAY_COUNT(gProcs) -namespace skiagm { - -class PathFillGM : public GM { +class PathFillGM : public skiagm::GM { SkPath fPath[N]; SkScalar fDY[N]; public: @@ -128,16 +126,16 @@ public: fDY[i] = gProcs[i](&fPath[i]); } } - + protected: virtual SkString onShortName() { return SkString("pathfill"); } - + virtual SkISize onISize() { - return make_isize(640, 480); + return SkISize::Make(640, 480); } - + virtual void onDraw(SkCanvas* canvas) { SkPaint paint; paint.setAntiAlias(true); @@ -147,14 +145,82 @@ protected: canvas->translate(SkIntToScalar(0), fDY[i]); } } - + private: - typedef GM INHERITED; + typedef skiagm::GM INHERITED; +}; + +// test inverse-fill w/ a clip that completely excludes the geometry +class PathInverseFillGM : public skiagm::GM { + SkPath fPath[N]; + SkScalar fDY[N]; +public: + PathInverseFillGM() { + for (size_t i = 0; i < N; i++) { + fDY[i] = gProcs[i](&fPath[i]); + } + } + +protected: + virtual SkString onShortName() { + return SkString("pathinvfill"); + } + + virtual SkISize onISize() { + return SkISize::Make(450, 220); + } + + static void show(SkCanvas* canvas, const SkPath& path, const SkPaint& paint, + const SkRect* clip, SkScalar top, const SkScalar bottom) { + canvas->save(); + if (clip) { + SkRect r = *clip; + r.fTop = top; + r.fBottom = bottom; + canvas->clipRect(r); + } + canvas->drawPath(path, paint); + canvas->restore(); + } + + virtual void onDraw(SkCanvas* canvas) { + SkPath path; + + path.addCircle(SkIntToScalar(50), SkIntToScalar(50), SkIntToScalar(40)); + path.toggleInverseFillType(); + + SkRect clipR = { 0, 0, SkIntToScalar(100), SkIntToScalar(200) }; + + canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); + + for (int doclip = 0; doclip <= 1; ++doclip) { + for (int aa = 0; aa <= 1; ++aa) { + SkPaint paint; + paint.setAntiAlias(SkToBool(aa)); + + canvas->save(); + canvas->clipRect(clipR); + + const SkRect* clipPtr = doclip ? &clipR : NULL; + + show(canvas, path, paint, clipPtr, clipR.fTop, clipR.centerY()); + show(canvas, path, paint, clipPtr, clipR.centerY(), clipR.fBottom); + + canvas->restore(); + canvas->translate(SkIntToScalar(110), 0); + } + } + } + +private: + typedef skiagm::GM INHERITED; }; /////////////////////////////////////////////////////////////////////////////// -static GM* MyFactory(void*) { return new PathFillGM; } -static GMRegistry reg(MyFactory); +static skiagm::GM* MyFactory(void*) { return new PathFillGM; } +static skiagm::GMRegistry reg(MyFactory); + +static skiagm::GM* F1(void*) { return new PathInverseFillGM; } +static skiagm::GMRegistry gR1(F1); -} diff --git a/src/core/SkScanPriv.h b/src/core/SkScanPriv.h index 96ed5ab8f..82402a745 100644 --- a/src/core/SkScanPriv.h +++ b/src/core/SkScanPriv.h @@ -15,7 +15,8 @@ class SkScanClipper { public: - SkScanClipper(SkBlitter* blitter, const SkRegion* clip, const SkIRect& bounds); + SkScanClipper(SkBlitter* blitter, const SkRegion* clip, const SkIRect& bounds, + bool skipRejectTest = false); SkBlitter* getBlitter() const { return fBlitter; } const SkIRect* getClipRect() const { return fClipRect; } diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp index 897339776..a04a2f3c9 100644 --- a/src/core/SkScan_Path.cpp +++ b/src/core/SkScan_Path.cpp @@ -540,22 +540,19 @@ void sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) /////////////////////////////////////////////////////////////////////////////// -static const SkIRect gHugeIRect = { - SK_MinS32, SK_MinS32, SK_MaxS32, SK_MaxS32 -}; - /** - * If the caller is drawing an inverse-fill path, then it shouldn't pass a - * huge rect for ir, since the path draws "everywhere". + * If the caller is drawing an inverse-fill path, then it pass true for + * skipRejectTest, so we don't abort drawing just because the src bounds (ir) + * is outside of the clip. */ SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, - const SkIRect& ir) { + const SkIRect& ir, bool skipRejectTest) { fBlitter = NULL; // null means blit nothing fClipRect = NULL; if (clip) { fClipRect = &clip->getBounds(); - if (!SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out + if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out return; } @@ -618,8 +615,7 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& origClip, return; } - SkScanClipper clipper(blitter, clipPtr, - path.isInverseFillType() ? gHugeIRect : ir); + SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType()); blitter = clipper.getBlitter(); if (blitter) {