aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-11 17:30:33 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-06-11 17:30:33 +0000
commit5ee6491b7a1e7c177abc0186c2749ebe1f71fcf7 (patch)
treef58ac55a0761c18f843905ecfd9637d1120a66bf
parentdb15a420c3f1c8f16d009ff5638475ec481337f0 (diff)
Better fix for rev. 4214 (inverse-fill and clipping). This fix avoids changing
the actual clipping bounds, which caused tiny differences in the scan converter. Also adding a gm (which I should have the first time.) Review URL: https://codereview.appspot.com/6297073 git-svn-id: http://skia.googlecode.com/svn/trunk@4227 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--gm/pathfill.cpp88
-rw-r--r--src/core/SkScanPriv.h3
-rw-r--r--src/core/SkScan_Path.cpp16
3 files changed, 85 insertions, 22 deletions
diff --git a/gm/pathfill.cpp b/gm/pathfill.cpp
index 6da507da34..f9fa6e9950 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 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 GM INHERITED;
+ 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 96ed5ab8fb..82402a7454 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 8973397760..a04a2f3c93 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) {