aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/SkRasterClip.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/SkRasterClip.cpp')
-rw-r--r--src/core/SkRasterClip.cpp270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/core/SkRasterClip.cpp b/src/core/SkRasterClip.cpp
new file mode 100644
index 0000000..9bf39fa
--- /dev/null
+++ b/src/core/SkRasterClip.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkRasterClip.h"
+
+
+SkRasterClip::SkRasterClip() {
+ fIsBW = true;
+}
+
+SkRasterClip::SkRasterClip(const SkRasterClip& src) {
+ AUTO_RASTERCLIP_VALIDATE(src);
+
+ fIsBW = src.fIsBW;
+ if (fIsBW) {
+ fBW = src.fBW;
+ } else {
+ fAA = src.fAA;
+ }
+}
+
+SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) {
+ fIsBW = true;
+}
+
+SkRasterClip::~SkRasterClip() {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+}
+
+bool SkRasterClip::isEmpty() const {
+ return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
+}
+
+bool SkRasterClip::isRect() const {
+ return fIsBW ? fBW.isRect() : false;
+}
+
+bool SkRasterClip::isComplex() const {
+ return fIsBW ? fBW.isComplex() : !fAA.isEmpty();
+}
+
+const SkIRect& SkRasterClip::getBounds() const {
+ return fIsBW ? fBW.getBounds() : fAA.getBounds();
+}
+
+bool SkRasterClip::setEmpty() {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ fIsBW = true;
+ fBW.setEmpty();
+ fAA.setEmpty();
+ return false;
+}
+
+bool SkRasterClip::setRect(const SkIRect& rect) {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ fIsBW = true;
+ fAA.setEmpty();
+ return fBW.setRect(rect);
+}
+
+bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ if (this->isBW() && !doAA) {
+ return fBW.setPath(path, clip);
+ } else {
+ if (this->isBW()) {
+ this->convertToAA();
+ }
+ return fAA.setPath(path, &clip, doAA);
+ }
+}
+
+bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
+ SkRegion tmp;
+ tmp.setRect(clip);
+ return this->setPath(path, tmp, doAA);
+}
+
+bool SkRasterClip::setPath(const SkPath& path, const SkRasterClip& clip,
+ bool doAA) {
+ if (clip.isBW()) {
+ return this->setPath(path, clip.bwRgn(), doAA);
+ } else {
+ SkRegion tmp;
+ tmp.setRect(clip.getBounds());
+ if (!this->setPath(path, clip, doAA)) {
+ return false;
+ }
+ return this->op(clip, SkRegion::kIntersect_Op);
+ }
+}
+
+bool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ return fIsBW ? fBW.op(rect, op) : fAA.op(rect, op);
+}
+
+bool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ if (fIsBW) {
+ return fBW.op(rgn, op);
+ } else {
+ SkAAClip tmp;
+ tmp.setRegion(rgn);
+ return fAA.op(tmp, op);
+ }
+}
+
+bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+ clip.validate();
+
+ if (this->isBW() && clip.isBW()) {
+ return fBW.op(clip.fBW, op);
+ } else {
+ SkAAClip tmp;
+ const SkAAClip* other;
+
+ if (this->isBW()) {
+ this->convertToAA();
+ }
+ if (clip.isBW()) {
+ tmp.setRegion(clip.bwRgn());
+ other = &tmp;
+ } else {
+ other = &clip.aaRgn();
+ }
+ return fAA.op(*other, op);
+ }
+}
+
+// return true if x is nearly integral (within 1/16) since that is the highest
+// precision our aa code can have.
+static bool is_integral(SkScalar x) {
+ int ix = SkScalarRoundToInt(x);
+ SkScalar sx = SkIntToScalar(ix);
+ return SkScalarAbs(sx - x) < (SK_Scalar1 / 16);
+}
+
+bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ if (doAA) {
+ // check that the rect really needs aa
+ if (is_integral(r.fLeft) && is_integral(r.fTop) &&
+ is_integral(r.fRight) && is_integral(r.fBottom)) {
+ doAA = false;
+ }
+ }
+
+ if (fIsBW && !doAA) {
+ SkIRect ir;
+ r.round(&ir);
+ return fBW.op(ir, op);
+ } else {
+ if (fIsBW) {
+ this->convertToAA();
+ }
+ return fAA.op(r, op, doAA);
+ }
+}
+
+void SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const {
+ if (NULL == dst) {
+ return;
+ }
+
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ if (this->isEmpty()) {
+ dst->setEmpty();
+ return;
+ }
+ if (0 == (dx | dy)) {
+ *dst = *this;
+ return;
+ }
+
+ dst->fIsBW = fIsBW;
+ if (fIsBW) {
+ fBW.translate(dx, dy, &dst->fBW);
+ dst->fAA.setEmpty();
+ } else {
+ fAA.translate(dx, dy, &dst->fAA);
+ dst->fBW.setEmpty();
+ }
+}
+
+bool SkRasterClip::quickContains(const SkIRect& ir) const {
+ return fIsBW ? fBW.quickContains(ir) : fAA.quickContains(ir);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+const SkRegion& SkRasterClip::forceGetBW() {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ if (!fIsBW) {
+ fBW.setRect(fAA.getBounds());
+ }
+ return fBW;
+}
+
+void SkRasterClip::convertToAA() {
+ AUTO_RASTERCLIP_VALIDATE(*this);
+
+ SkASSERT(fIsBW);
+ fAA.setRegion(fBW);
+ fIsBW = false;
+}
+
+#ifdef SK_DEBUG
+void SkRasterClip::validate() const {
+ // can't ever assert that fBW is empty, since we may have called forceGetBW
+ if (fIsBW) {
+ SkASSERT(fAA.isEmpty());
+ }
+
+ fBW.validate();
+ fAA.validate();
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkAAClipBlitterWrapper::SkAAClipBlitterWrapper() {
+ SkDEBUGCODE(fClipRgn = NULL;)
+ SkDEBUGCODE(fBlitter = NULL;)
+}
+
+SkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkRasterClip& clip,
+ SkBlitter* blitter) {
+ this->init(clip, blitter);
+}
+
+SkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkAAClip* aaclip,
+ SkBlitter* blitter) {
+ SkASSERT(blitter);
+ SkASSERT(aaclip);
+ fBWRgn.setRect(aaclip->getBounds());
+ fAABlitter.init(blitter, aaclip);
+ // now our return values
+ fClipRgn = &fBWRgn;
+ fBlitter = &fAABlitter;
+}
+
+void SkAAClipBlitterWrapper::init(const SkRasterClip& clip, SkBlitter* blitter) {
+ SkASSERT(blitter);
+ if (clip.isBW()) {
+ fClipRgn = &clip.bwRgn();
+ fBlitter = blitter;
+ } else {
+ const SkAAClip& aaclip = clip.aaRgn();
+ fBWRgn.setRect(aaclip.getBounds());
+ fAABlitter.init(blitter, &aaclip);
+ // now our return values
+ fClipRgn = &fBWRgn;
+ fBlitter = &fAABlitter;
+ }
+}
+