|  | /* | 
|  | * Copyright 2012 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "gm.h" | 
|  | #include "SkAAClip.h" | 
|  | #include "SkCanvas.h" | 
|  | #include "SkPath.h" | 
|  |  | 
|  | namespace skiagm { | 
|  |  | 
|  | static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip, | 
|  | const SkPaint& paint) { | 
|  | SkMask mask; | 
|  | SkBitmap bm; | 
|  |  | 
|  | clip.copyToMask(&mask); | 
|  |  | 
|  | SkAutoMaskFreeImage amfi(mask.fImage); | 
|  |  | 
|  | bm.installMaskPixels(mask); | 
|  |  | 
|  | // need to copy for deferred drawing test to work | 
|  | SkBitmap bm2; | 
|  |  | 
|  | bm.deepCopyTo(&bm2); | 
|  |  | 
|  | canvas->drawBitmap(bm2, | 
|  | SK_Scalar1 * mask.fBounds.fLeft, | 
|  | SK_Scalar1 * mask.fBounds.fTop, | 
|  | &paint); | 
|  | } | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////////////////// | 
|  | /* | 
|  | * This GM tests anti aliased single operation booleans with SkAAClips, | 
|  | * SkRect and SkPaths. | 
|  | */ | 
|  | class SimpleClipGM : public GM { | 
|  | public: | 
|  | enum SkGeomTypes { | 
|  | kRect_GeomType, | 
|  | kPath_GeomType, | 
|  | kAAClip_GeomType | 
|  | }; | 
|  |  | 
|  | SimpleClipGM(SkGeomTypes geomType) | 
|  | : fGeomType(geomType) { | 
|  | } | 
|  |  | 
|  | protected: | 
|  | void onOnceBeforeDraw() override { | 
|  | // offset the rects a bit so we get anti-aliasing in the rect case | 
|  | fBase.set(100.65f, | 
|  | 100.65f, | 
|  | 150.65f, | 
|  | 150.65f); | 
|  | fRect = fBase; | 
|  | fRect.inset(5, 5); | 
|  | fRect.offset(25, 25); | 
|  |  | 
|  | fBasePath.addRoundRect(fBase, SkIntToScalar(5), SkIntToScalar(5)); | 
|  | fRectPath.addRoundRect(fRect, SkIntToScalar(5), SkIntToScalar(5)); | 
|  | INHERITED::setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD)); | 
|  | } | 
|  |  | 
|  | void buildRgn(SkAAClip* clip, SkRegion::Op op) { | 
|  | clip->setPath(fBasePath, nullptr, true); | 
|  |  | 
|  | SkAAClip clip2; | 
|  | clip2.setPath(fRectPath, nullptr, true); | 
|  | clip->op(clip2, op); | 
|  | } | 
|  |  | 
|  | void drawOrig(SkCanvas* canvas) { | 
|  | SkPaint     paint; | 
|  |  | 
|  | paint.setStyle(SkPaint::kStroke_Style); | 
|  | paint.setColor(SK_ColorBLACK); | 
|  |  | 
|  | canvas->drawRect(fBase, paint); | 
|  | canvas->drawRect(fRect, paint); | 
|  | } | 
|  |  | 
|  | void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) { | 
|  |  | 
|  | SkAAClip clip; | 
|  |  | 
|  | this->buildRgn(&clip, op); | 
|  | this->drawOrig(canvas); | 
|  |  | 
|  | SkPaint paint; | 
|  | paint.setColor(color); | 
|  | paint_rgn(canvas, clip, paint); | 
|  | } | 
|  |  | 
|  | void drawPathsOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) { | 
|  |  | 
|  | this->drawOrig(canvas); | 
|  |  | 
|  | canvas->save(); | 
|  |  | 
|  | // create the clip mask with the supplied boolean op | 
|  | if (kPath_GeomType == fGeomType) { | 
|  | // path-based case | 
|  | canvas->clipPath(fBasePath, SkRegion::kReplace_Op, true); | 
|  | canvas->clipPath(fRectPath, op, true); | 
|  | } else { | 
|  | // rect-based case | 
|  | canvas->clipRect(fBase, SkRegion::kReplace_Op, true); | 
|  | canvas->clipRect(fRect, op, true); | 
|  | } | 
|  |  | 
|  | // 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(); | 
|  | } | 
|  |  | 
|  | SkString onShortName() override { | 
|  | SkString str; | 
|  | str.printf("simpleaaclip_%s", | 
|  | kRect_GeomType == fGeomType ? "rect" : | 
|  | (kPath_GeomType == fGeomType ? "path" : | 
|  | "aaclip")); | 
|  | return str; | 
|  | } | 
|  |  | 
|  | SkISize onISize() override { | 
|  | return SkISize::Make(640, 480); | 
|  | } | 
|  |  | 
|  | void onDraw(SkCanvas* canvas) override { | 
|  |  | 
|  | static const struct { | 
|  | SkColor         fColor; | 
|  | const char*     fName; | 
|  | SkRegion::Op    fOp; | 
|  | } gOps[] = { | 
|  | { SK_ColorBLACK,    "Difference", SkRegion::kDifference_Op    }, | 
|  | { SK_ColorRED,      "Intersect",  SkRegion::kIntersect_Op     }, | 
|  | { sk_tool_utils::color_to_565(0xFF008800), "Union", SkRegion::kUnion_Op }, | 
|  | { SK_ColorGREEN,    "Rev Diff",   SkRegion::kReverseDifference_Op }, | 
|  | { SK_ColorYELLOW,   "Replace",    SkRegion::kReplace_Op       }, | 
|  | { SK_ColorBLUE,     "XOR",        SkRegion::kXOR_Op           }, | 
|  | }; | 
|  |  | 
|  | SkPaint textPaint; | 
|  | textPaint.setAntiAlias(true); | 
|  | sk_tool_utils::set_portable_typeface(&textPaint); | 
|  | textPaint.setTextSize(SK_Scalar1*24); | 
|  | int xOff = 0; | 
|  |  | 
|  | 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); | 
|  |  | 
|  | if (kAAClip_GeomType == fGeomType) { | 
|  | this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor); | 
|  | } else { | 
|  | this->drawPathsOped(canvas, gOps[op].fOp, gOps[op].fColor); | 
|  | } | 
|  |  | 
|  | if (xOff >= 400) { | 
|  | canvas->translate(SkIntToScalar(-400), SkIntToScalar(250)); | 
|  | xOff = 0; | 
|  | } else { | 
|  | canvas->translate(SkIntToScalar(200), 0); | 
|  | xOff += 200; | 
|  | } | 
|  | } | 
|  | } | 
|  | private: | 
|  |  | 
|  | SkGeomTypes fGeomType; | 
|  |  | 
|  | SkRect fBase; | 
|  | SkRect fRect; | 
|  |  | 
|  | SkPath fBasePath;       // fBase as a round rect | 
|  | SkPath fRectPath;       // fRect as a round rect | 
|  |  | 
|  | typedef GM INHERITED; | 
|  | }; | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | // rects | 
|  | DEF_GM( return new SimpleClipGM(SimpleClipGM::kRect_GeomType); ) | 
|  | DEF_GM( return new SimpleClipGM(SimpleClipGM::kPath_GeomType); ) | 
|  | DEF_GM( return new SimpleClipGM(SimpleClipGM::kAAClip_GeomType); ) | 
|  |  | 
|  | } |