diff --git a/samplecode/SampleAAClip2.cpp b/samplecode/SampleAAClip2.cpp new file mode 100644 index 0000000000..bdb3741704 --- /dev/null +++ b/samplecode/SampleAAClip2.cpp @@ -0,0 +1,175 @@ + +/* + * 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" + +#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); + bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), + mask.fBounds.height(), mask.fRowBytes); + bm.setPixels(mask.fImage); + + SkPaint paint; + canvas->drawBitmap(bm, mask.fBounds.fLeft, mask.fBounds.fTop, &paint); +} + +static void paint_rgn(SkCanvas* canvas, const SkAAClip& clip, + const SkPaint& paint) { + SkMask mask; + SkBitmap bm; + + clip.copyToMask(&mask); + bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), + mask.fBounds.height(), mask.fRowBytes); + bm.setPixels(mask.fImage); + + canvas->drawBitmap(bm, mask.fBounds.fLeft, 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); + } + + void build_rgn(SkAAClip* clip, SkRegion::Op op) { + clip->setRect(fBase); +#if 0 + SkIRect r = fBase; + r.offset(75, 20); + rgn->op(r, SkRegion::kUnion_Op); +#endif + + SkRect r; + r.set(fRect); + SkPath path; + path.addOval(r); + SkAAClip clip2; + clip2.setPath(path); + // hack + op = SkRegion::kIntersect_Op; + 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); + } + + 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); + } + + 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 } + }; + + SkPaint textPaint; + textPaint.setAntiAlias(true); + textPaint.setTextSize(SK_Scalar1*24); + + this->drawOrig(canvas, false); + canvas->save(); + canvas->translate(SkIntToScalar(200), 0); + this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK); + canvas->restore(); + + 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); + + 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); + diff --git a/src/core/SkAAClip.cpp b/src/core/SkAAClip.cpp index a79cca1a3a..ff5715e949 100644 --- a/src/core/SkAAClip.cpp +++ b/src/core/SkAAClip.cpp @@ -112,7 +112,7 @@ void SkAAClip::Iter::next() { /////////////////////////////////////////////////////////////////////////////// void SkAAClip::freeRuns() { - if (this->isComplex()) { + if (fRunHead) { SkASSERT(fRunHead->fRefCnt >= 1); if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) { sk_free(fRunHead); @@ -122,11 +122,11 @@ void SkAAClip::freeRuns() { SkAAClip::SkAAClip() { fBounds.setEmpty(); - fRunHead = SkAAClip_gEmptyPtr; + fRunHead = NULL; } SkAAClip::SkAAClip(const SkAAClip& src) { - fRunHead = SkAAClip_gEmptyPtr; + fRunHead = NULL; *this = src; } @@ -139,7 +139,7 @@ SkAAClip& SkAAClip::operator=(const SkAAClip& src) { this->freeRuns(); fBounds = src.fBounds; fRunHead = src.fRunHead; - if (this->isComplex()) { + if (fRunHead) { sk_atomic_inc(&fRunHead->fRefCnt); } } @@ -163,7 +163,7 @@ bool operator==(const SkAAClip& a, const SkAAClip& b) { } // now we insist that both are complex (but different ptrs) - if (!a.isComplex() || !b.isComplex()) { + if (!a.fRunHead || !b.fRunHead) { return false; } @@ -185,7 +185,7 @@ bool SkAAClip::set(const SkAAClip& src) { bool SkAAClip::setEmpty() { this->freeRuns(); fBounds.setEmpty(); - fRunHead = SkAAClip_gEmptyPtr; + fRunHead = NULL; return false; } @@ -193,10 +193,14 @@ bool SkAAClip::setRect(const SkIRect& bounds) { if (bounds.isEmpty()) { return this->setEmpty(); } - this->freeRuns(); - fBounds = bounds; - fRunHead = SkAAClip_gRectPtr; - return true; + + // TODO: special case this + + SkRect r; + r.set(bounds); + SkPath path; + path.addRect(r); + return this->setPath(path); } bool SkAAClip::setRect(const SkRect& r) { @@ -212,7 +216,7 @@ bool SkAAClip::setRect(const SkRect& r) { /////////////////////////////////////////////////////////////////////////////// const uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const { - SkASSERT(this->isComplex()); + SkASSERT(fRunHead); if (!y_in_rect(y, fBounds)) { return NULL; @@ -894,6 +898,22 @@ bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, return !this->isEmpty(); } +bool SkAAClip::op(const SkIRect& r, SkRegion::Op op) { + SkAAClip clip; + clip.setRect(r); + return this->op(*this, clip, op); +} + +bool SkAAClip::op(const SkRect& r, SkRegion::Op op) { + SkAAClip clip; + clip.setRect(r); + return this->op(*this, clip, op); +} + +bool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { + return this->op(*this, clip, op); +} + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkAAClip.h b/src/core/SkAAClip.h index 98df3a6c01..cebe97ce9f 100644 --- a/src/core/SkAAClip.h +++ b/src/core/SkAAClip.h @@ -12,9 +12,6 @@ #include "SkBlitter.h" #include "SkRegion.h" -#define SkAAClip_gEmptyPtr ((SkAAClip::RunHead*)-1) -#define SkAAClip_gRectPtr NULL - class SkAAClip { public: SkAAClip(); @@ -29,9 +26,7 @@ public: void swap(SkAAClip&); - bool isEmpty() const { return SkAAClip_gEmptyPtr == fRunHead; } -// bool isRect() const { return SkAAClip_gRectPtr == fRunHead; } - bool isComplex() const { return !this->isEmpty() /*&& !this->isRect()*/; } + bool isEmpty() const { return NULL == fRunHead; } const SkIRect& getBounds() const { return fBounds; } bool setEmpty(); @@ -42,6 +37,11 @@ public: bool op(const SkAAClip&, const SkAAClip&, SkRegion::Op); + // Helpers for op() + bool op(const SkIRect&, SkRegion::Op); + bool op(const SkRect&, SkRegion::Op); + bool op(const SkAAClip&, SkRegion::Op); + /** * Allocates a mask the size of the aaclip, and expands its data into * the mask, using kA8_Format