/* * 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/gm.h" #include "include/core/SkBitmap.h" #include "include/core/SkCanvas.h" #include "include/core/SkClipOp.h" #include "include/core/SkColor.h" #include "include/core/SkFont.h" #include "include/core/SkPaint.h" #include "include/core/SkPath.h" #include "include/core/SkRect.h" #include "include/core/SkRegion.h" #include "include/core/SkScalar.h" #include "include/core/SkSize.h" #include "include/core/SkString.h" #include "include/core/SkTypeface.h" #include "include/core/SkTypes.h" #include "src/core/SkAAClip.h" #include "src/core/SkClipOpPriv.h" #include "src/core/SkMask.h" #include "tools/ToolUtils.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; ToolUtils::copy_to(&bm2, bm.colorType(), bm); canvas->drawImage(bm2.asImage(), SK_Scalar1 * mask.fBounds.fLeft, SK_Scalar1 * mask.fBounds.fTop, SkSamplingOptions(), &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.setLTRB(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(0xFFDDDDDD); } void buildRgn(SkAAClip* clip, SkClipOp op) { clip->setPath(fBasePath, nullptr, true); SkAAClip clip2; clip2.setPath(fRectPath, nullptr, true); clip->op(clip2, (SkRegion::Op)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, SkClipOp 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, SkClipOp 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, true); canvas->clipPath(fRectPath, op, true); } else { // rect-based case canvas->clipRect(fBase, 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(500, 240); } void onDraw(SkCanvas* canvas) override { const struct { SkColor fColor; const char* fName; SkClipOp fOp; } gOps[] = { {SK_ColorBLACK, "Difference", kDifference_SkClipOp}, {SK_ColorRED, "Intersect", kIntersect_SkClipOp}, }; SkPaint textPaint; SkFont font(ToolUtils::create_portable_typeface(), 24); int xOff = 0; for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) { canvas->drawString(gOps[op].fName, 75.0f, 50.0f, font, 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 using INHERITED = GM; }; ////////////////////////////////////////////////////////////////////////////// // 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); ) } // namespace skiagm