diff --git a/gm/complexclip2.cpp b/gm/complexclip2.cpp index d6b653e384..df8bca151e 100644 --- a/gm/complexclip2.cpp +++ b/gm/complexclip2.cpp @@ -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; + // 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 = 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; + 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(); - for (int k = 0; k < 5; ++k) { - canvas->clipRect(fRects[k], fOps[j*kRows+i][k]); - } - canvas->drawRect(SkRect::MakeWH(fWidth, fHeight), fillPaint); - canvas->restore(); + + // draw the original shapes first so we can see the + // antialiasing on the clipped draw for (int k = 0; k < 5; ++k) { rectPaint.setColor(fRectColors[k]); - canvas->drawRect(fRects[k], rectPaint); + if (fDoPaths) { + canvas->drawPath(fPaths[k], rectPaint); + } else { + canvas->drawRect(fRects[k], rectPaint); + } } + + for (int k = 0; k < 5; ++k) { + 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); + } diff --git a/samplecode/SampleAAClip2.cpp b/samplecode/SampleAAClip2.cpp index d12e13c6b5..6000da059d 100644 --- a/samplecode/SampleAAClip2.cpp +++ b/samplecode/SampleAAClip2.cpp @@ -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; }