Updated AAClips Sample slide and complexclip2 GM to exercise AA clipping
authorrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 15 May 2012 17:03:16 +0000 (17:03 +0000)
committerrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 15 May 2012 17:03:16 +0000 (17:03 +0000)
http://codereview.appspot.com/6212047/

will require image rebaselining

git-svn-id: http://skia.googlecode.com/svn/trunk@3943 2bbb7eff-a529-9590-31e7-b0007b416f81

gm/complexclip2.cpp
samplecode/SampleAAClip2.cpp

index d6b653e..df8bca1 100644 (file)
@@ -15,39 +15,47 @@ namespace skiagm {
 
 class ComplexClip2GM : public GM {
 public:
-    ComplexClip2GM() {
+    ComplexClip2GM(bool doPaths, bool antiAlias)
+    : fDoPaths(doPaths)
+    , fAntiAlias(antiAlias) {
         this->setBGColor(SkColorSetRGB(0xDD,0xA0,0xDD));
         
-        SkScalar xA =  0 * SK_Scalar1;
-        SkScalar xB = 10 * SK_Scalar1;
-        SkScalar xC = 20 * SK_Scalar1;
-        SkScalar xD = 30 * SK_Scalar1;
-        SkScalar xE = 40 * SK_Scalar1;
-        SkScalar xF = 50 * SK_Scalar1;
-
-        SkScalar yA =  0 * SK_Scalar1;
-        SkScalar yB = 10 * SK_Scalar1;
-        SkScalar yC = 20 * SK_Scalar1;
-        SkScalar yD = 30 * SK_Scalar1;
-        SkScalar yE = 40 * SK_Scalar1;
-        SkScalar yF = 50 * SK_Scalar1;
+        // offset the rects a bit so we get antialiasing even in the rect case
+        SkScalar xA = SkFloatToScalar(0.5f);
+        SkScalar xB = SkFloatToScalar(10.5f);
+        SkScalar xC = SkFloatToScalar(20.5f);
+        SkScalar xD = SkFloatToScalar(30.5f);
+        SkScalar xE = SkFloatToScalar(40.5f);
+        SkScalar xF = SkFloatToScalar(50.5f);
+
+        SkScalar yA = SkFloatToScalar(0.5f);
+        SkScalar yB = SkFloatToScalar(10.5f);
+        SkScalar yC = SkFloatToScalar(20.5f);
+        SkScalar yD = SkFloatToScalar(30.5f);
+        SkScalar yE = SkFloatToScalar(40.5f);
+        SkScalar yF = SkFloatToScalar(50.5f);
 
         fWidth = xF - xA;
         fHeight = yF - yA;
 
         fRects[0].set(xB, yB, xE, yE);
+        fPaths[0].addRoundRect(fRects[0], SkIntToScalar(5), SkIntToScalar(5));
         fRectColors[0] = SK_ColorRED;
 
         fRects[1].set(xA, yA, xD, yD);
+        fPaths[1].addRoundRect(fRects[1], SkIntToScalar(5), SkIntToScalar(5));
         fRectColors[1] = SK_ColorGREEN;
 
         fRects[2].set(xC, yA, xF, yD);
+        fPaths[2].addRoundRect(fRects[2], SkIntToScalar(5), SkIntToScalar(5));
         fRectColors[2] = SK_ColorBLUE;
 
         fRects[3].set(xA, yC, xD, yF);
+        fPaths[3].addRoundRect(fRects[3], SkIntToScalar(5), SkIntToScalar(5));
         fRectColors[3] = SK_ColorYELLOW;
 
         fRects[4].set(xC, yC, xF, yF);
+        fPaths[4].addRoundRect(fRects[4], SkIntToScalar(5), SkIntToScalar(5));
         fRectColors[4] = SK_ColorCYAN;
 
         fTotalWidth = kCols * fWidth + SK_Scalar1 * (kCols + 1) * kPadX;
@@ -80,7 +88,15 @@ protected:
     static const int kPadY = 20;
 
     virtual SkString onShortName() {
-        return SkString("complexclip2");
+        if (!fDoPaths && !fAntiAlias) {
+            return SkString("complexclip2");
+        }
+
+        SkString str;
+        str.printf("complexclip2_%s_%s", 
+                    fDoPaths ? "path" : "rect",
+                    fAntiAlias ? "aa" : "bw");
+        return str;
     }
 
     virtual SkISize onISize() {
@@ -99,24 +115,42 @@ protected:
         for (int i = 0; i < kRows; ++i) {
             for (int j = 0; j < kCols; ++j) {
                 canvas->save();
+
                 canvas->translate(kPadX * SK_Scalar1 + (fWidth + kPadX * SK_Scalar1)*j,
                                   kPadY * SK_Scalar1 + (fHeight + kPadY * SK_Scalar1)*i);
-                canvas->save();
+
+                // draw the original shapes first so we can see the 
+                // antialiasing on the clipped draw
                 for (int k = 0; k < 5; ++k) {
-                    canvas->clipRect(fRects[k], fOps[j*kRows+i][k]);
+                    rectPaint.setColor(fRectColors[k]);
+                    if (fDoPaths) {
+                        canvas->drawPath(fPaths[k], rectPaint);
+                    } else {
+                        canvas->drawRect(fRects[k], rectPaint);
+                    }
                 }
-                canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint);
-                canvas->restore();
+
                 for (int k = 0; k < 5; ++k) {
-                    rectPaint.setColor(fRectColors[k]);
-                    canvas->drawRect(fRects[k], rectPaint);
+                    if (fDoPaths) {
+                        canvas->clipPath(fPaths[k], 
+                                         fOps[j*kRows+i][k], 
+                                         fAntiAlias);
+                    } else {
+                        canvas->clipRect(fRects[k], 
+                                         fOps[j*kRows+i][k], 
+                                         fAntiAlias);
+                    }
                 }
+                canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint);
                 canvas->restore();
             }
         }
     }
 private:
+    bool fDoPaths;
+    bool fAntiAlias;
     SkRect fRects[5];
+    SkPath fPaths[5];
     SkColor fRectColors[5];
     SkRegion::Op fOps[kRows * kCols][5];
     SkScalar fWidth;
@@ -129,7 +163,20 @@ private:
 
 //////////////////////////////////////////////////////////////////////////////
 
-static GM* MyFactory(void*) { return new ComplexClip2GM; }
+// bw rects
+static GM* MyFactory(void*) { return new ComplexClip2GM(false, false); }
 static GMRegistry reg(MyFactory);
 
+// bw paths
+static GM* MyFactory2(void*) { return new ComplexClip2GM(true, false); }
+static GMRegistry reg2(MyFactory2);
+
+// aa rects
+static GM* MyFactory3(void*) { return new ComplexClip2GM(false, true); }
+static GMRegistry reg3(MyFactory3);
+
+// aa paths
+static GM* MyFactory4(void*) { return new ComplexClip2GM(true, true); }
+static GMRegistry reg4(MyFactory4);
+
 }
index d12e13c..6000da0 100644 (file)
@@ -16,6 +16,8 @@
 #include "SkUtils.h"
 #include "SkImageDecoder.h"
 
+#define USE_PATHS 1
+
 #ifdef SK_BUILD_FOR_WIN
 // windows doesn't have roundf
 inline float roundf(float x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); }
@@ -59,7 +61,7 @@ static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip,
 
 class AAClipView2 : public SampleView {
 public:
-       AAClipView2() {
+        AAClipView2() {
         fBase.set(100, 100, 150, 150);
         fRect = fBase;
         fRect.inset(5, 5);
@@ -72,7 +74,7 @@ public:
         r.set(rect);
         SkPath path;
         path.addRoundRect(r, SkIntToScalar(5), SkIntToScalar(5));
-        clip->setPath(path);
+        clip->setPath(path, NULL, true);
     }
 
     void build_rgn(SkAAClip* clip, SkRegion::Op op) {
@@ -83,7 +85,6 @@ public:
         clip->op(clip2, op);
     }
 
-
 protected:
     // overrides from SkEventSink
     virtual bool onQuery(SkEvent* evt) {
@@ -120,10 +121,10 @@ protected:
     }
 
     void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
+
         SkAAClip clip;
 
         this->build_rgn(&clip, op);
-        
         this->drawOrig(canvas, true);
 
         SkPaint paint;
@@ -133,13 +134,69 @@ protected:
         paint.setStyle(SkPaint::kStroke_Style);
         paint.setColor(color);
         paint_rgn(canvas, clip, paint);
-        
         SkAAClip clip2(clip);
         clip2.translate(0, 80);
         outer_frame(canvas, clip2.getBounds());
         paint_rgn(canvas, clip2, paint);
     }
     
+    static void createPath(SkPath *path, const SkIRect& rect) {
+        SkRect r;
+        r.set(rect);
+        path->addRoundRect(r, SkIntToScalar(5), SkIntToScalar(5));
+    }
+
+    void drawPathsOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
+
+        this->drawOrig(canvas, true);
+
+        canvas->save();
+
+        // create the clip mask with the supplied boolean op
+
+#if USE_PATHS
+        // path-based case
+        SkPath base;
+        createPath(&base, fBase);
+
+        canvas->clipPath(base, SkRegion::kReplace_Op, true);
+#else
+        // rect-based case
+        SkRect base;
+        base.set(fBase);
+        // offset the rects so we get a bit of anti-aliasing
+        base.offset(SkFloatToScalar(0.5f), SkFloatToScalar(0.5f));
+        canvas->clipRect(base, SkRegion::kReplace_Op, true);
+
+#endif
+
+#if USE_PATHS
+        // path-based case
+        SkPath rect;
+        createPath(&rect, fRect);
+
+        canvas->clipPath(rect, op, true);
+#else
+        // rect-based case
+        SkRect rect;
+        rect.set(fRect);
+        // offset the rects so we get a bit of anti-aliasing
+        rect.offset(SkFloatToScalar(0.5f), SkFloatToScalar(0.5f));
+        canvas->clipRect(rect, op, true);
+#endif
+
+        // draw a rect that will entirely cover the clip mask area
+        SkPaint paint;
+        paint.setColor(color);
+
+        SkRect r = SkRect::MakeLTRB(SkIntToScalar(90),  SkIntToScalar(90),
+                                    SkIntToScalar(180), SkIntToScalar(180));
+
+        canvas->drawRect(r, paint);
+
+        canvas->restore();
+    }
+
     virtual void onDrawContent(SkCanvas* canvas) {
 
         static const struct {
@@ -147,10 +204,12 @@ protected:
             const char*     fName;
             SkRegion::Op    fOp;
         } gOps[] = {
-            { SK_ColorBLACK,    "Difference",   SkRegion::kDifference_Op    },
-            { SK_ColorRED,      "Intersect",    SkRegion::kIntersect_Op     },
-            { 0xFF008800,       "Union",        SkRegion::kUnion_Op         },
-            { SK_ColorBLUE,     "XOR",          SkRegion::kXOR_Op           }
+            { SK_ColorBLACK,    "Difference", SkRegion::kDifference_Op    },
+            { SK_ColorRED,      "Intersect",  SkRegion::kIntersect_Op     },
+            { 0xFF008800,       "Union",      SkRegion::kUnion_Op         },
+            { SK_ColorBLUE,     "XOR",        SkRegion::kXOR_Op           },
+            { SK_ColorGREEN,    "Rev Diff",   SkRegion::kReverseDifference_Op },
+            { SK_ColorYELLOW,   "Replace",    SkRegion::kReplace_Op       }
         };
 
         SkPaint textPaint;
@@ -158,18 +217,40 @@ protected:
         textPaint.setTextSize(SK_Scalar1*24);
 
         this->drawOrig(canvas, false);
-        
+
         canvas->translate(0, SkIntToScalar(200));
 
         for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
-            canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), SkIntToScalar(75), SkIntToScalar(50), textPaint);
+            canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
+                             SkIntToScalar(75), SkIntToScalar(50), textPaint);
 
             this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
-            
-            canvas->translate(SkIntToScalar(200), 0);
+
+            if (op && !(op % 3)) {
+                canvas->translate(SkIntToScalar(-600), SkIntToScalar(250));
+            } else {
+                canvas->translate(SkIntToScalar(200), 0);
+            }
+        }
+
+        canvas->translate(SkIntToScalar(int(SK_ARRAY_COUNT(gOps) / 3) * -200), 
+                          SkIntToScalar(250));
+
+        for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
+            canvas->drawText(gOps[op].fName, strlen(gOps[op].fName),
+                             SkIntToScalar(75), SkIntToScalar(50), textPaint);
+
+            this->drawPathsOped(canvas, gOps[op].fOp, gOps[op].fColor);
+
+            if (op && !(op % 3)) {
+                canvas->translate(SkIntToScalar(-600), SkIntToScalar(250));
+            } else {
+                canvas->translate(SkIntToScalar(200), 0);
+            }
         }
+
     }
-    
+
     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
         return fRect.contains(SkScalarRound(x), SkScalarRound(y)) ? new Click(this) : NULL;
     }