/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkAAClip.h" #include "SampleCode.h" #include "SkView.h" #include "SkCanvas.h" #include "SkGradientShader.h" #include "SkPath.h" #include "SkRegion.h" #include "SkShader.h" #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); } #endif static void drawClip(SkCanvas* canvas, const SkAAClip& clip) { SkMask mask; SkBitmap bm; clip.copyToMask(&mask); SkAutoMaskFreeImage amfi(mask.fImage); bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes); bm.setPixels(mask.fImage); SkPaint paint; canvas->drawBitmap(bm, SK_Scalar1 * mask.fBounds.fLeft, SK_Scalar1 * mask.fBounds.fTop, &paint); } static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip, const SkPaint& paint) { SkMask mask; SkBitmap bm; clip.copyToMask(&mask); SkAutoMaskFreeImage amfi(mask.fImage); bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes); bm.setPixels(mask.fImage); canvas->drawBitmap(bm, SK_Scalar1 * mask.fBounds.fLeft, SK_Scalar1 * mask.fBounds.fTop, &paint); } class AAClipView2 : public SampleView { public: AAClipView2() { fBase.set(100, 100, 150, 150); fRect = fBase; fRect.inset(5, 5); fRect.offset(25, 25); this->setBGColor(0xFFDDDDDD); } static void setAAClip(SkAAClip* clip, const SkIRect& rect) { SkRect r; r.set(rect); SkPath path; path.addRoundRect(r, SkIntToScalar(5), SkIntToScalar(5)); clip->setPath(path, NULL, true); } void build_rgn(SkAAClip* clip, SkRegion::Op op) { setAAClip(clip, fBase); SkAAClip clip2; setAAClip(&clip2, fRect); clip->op(clip2, op); } protected: // overrides from SkEventSink virtual bool onQuery(SkEvent* evt) { if (SampleCode::TitleQ(*evt)) { SampleCode::TitleR(evt, "AAClips"); return true; } return this->INHERITED::onQuery(evt); } void drawOrig(SkCanvas* canvas, bool bg) { SkRect r; SkPaint paint; paint.setStyle(SkPaint::kStroke_Style); if (bg) paint.setColor(0xFFBBBBBB); r.set(fBase); canvas->drawRect(r, paint); r.set(fRect); canvas->drawRect(r, paint); } static void outer_frame(SkCanvas* canvas, const SkIRect& rect) { SkRect r; r.set(rect); r.inset(-SK_ScalarHalf, -SK_ScalarHalf); SkPaint paint; paint.setColor(SK_ColorGRAY); paint.setStyle(SkPaint::kStroke_Style); canvas->drawRect(r, paint); } void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) { SkAAClip clip; this->build_rgn(&clip, op); this->drawOrig(canvas, true); SkPaint paint; paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24)); paint_rgn(canvas, clip, paint); 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 { SkColor fColor; 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_ColorGREEN, "Rev Diff", SkRegion::kReverseDifference_Op }, { SK_ColorYELLOW, "Replace", SkRegion::kReplace_Op } }; SkPaint textPaint; textPaint.setAntiAlias(true); 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); this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor); 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; } virtual bool onClick(Click* click) { fRect.offset(click->fICurr.fX - click->fIPrev.fX, click->fICurr.fY - click->fIPrev.fY); this->inval(NULL); return true; } private: SkIRect fBase, fRect; typedef SampleView INHERITED; }; ////////////////////////////////////////////////////////////////////////////// static SkView* MyFactory() { return new AAClipView2; } static SkViewRegister reg(MyFactory);