aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkBitmapDevice.cpp35
-rw-r--r--src/core/SkBitmapDevice.h9
-rw-r--r--src/core/SkCanvas.cpp41
-rw-r--r--src/core/SkDevice.h40
4 files changed, 123 insertions, 2 deletions
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index fe43ba24b6..2b5c37fa2e 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -74,6 +74,8 @@ SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
{
SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
fBitmap.lockPixels();
+
+ fRCStack.push_back().setRect(SkIRect::MakeWH(bitmap.width(), bitmap.height()));
}
SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& info) {
@@ -88,6 +90,8 @@ SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkSurfaceProps& sur
{
SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
fBitmap.lockPixels();
+
+ fRCStack.push_back().setRect(SkIRect::MakeWH(bitmap.width(), bitmap.height()));
}
SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
@@ -439,7 +443,7 @@ SkImageFilterCache* SkBitmapDevice::getImageFilterCache() {
return cache;
}
-///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const {
if (kN32_SkColorType != fBitmap.colorType() ||
@@ -453,3 +457,32 @@ bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const {
}
return false;
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void SkBitmapDevice::onSave() {
+ fRCStack.push_back(fRCStack.back());
+}
+
+void SkBitmapDevice::onRestore() {
+ fRCStack.pop_back();
+}
+
+void SkBitmapDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) {
+ fRCStack.back().op(rect, this->ctm(), SkIRect::MakeWH(this->width(), this->height()),
+ (SkRegion::Op)op, aa);
+}
+
+void SkBitmapDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
+ fRCStack.back().op(rrect, this->ctm(), SkIRect::MakeWH(this->width(), this->height()),
+ (SkRegion::Op)op, aa);
+}
+
+void SkBitmapDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) {
+ fRCStack.back().op(path, this->ctm(), SkIRect::MakeWH(this->width(), this->height()),
+ (SkRegion::Op)op, aa);
+}
+
+void SkBitmapDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) {
+ fRCStack.back().op(rgn, (SkRegion::Op)op);
+}
diff --git a/src/core/SkBitmapDevice.h b/src/core/SkBitmapDevice.h
index 1f72d8df3c..0a6471080b 100644
--- a/src/core/SkBitmapDevice.h
+++ b/src/core/SkBitmapDevice.h
@@ -14,6 +14,7 @@
#include "SkDevice.h"
#include "SkImageInfo.h"
#include "SkPixelRef.h"
+#include "SkRasterClip.h"
#include "SkRect.h"
#include "SkScalar.h"
#include "SkSize.h"
@@ -125,6 +126,13 @@ protected:
bool onPeekPixels(SkPixmap*) override;
bool onAccessPixels(SkPixmap*) override;
+ void onSave() override;
+ void onRestore() override;
+ void onClipRect(const SkRect& rect, SkClipOp, bool aa) override;
+ void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override;
+ void onClipPath(const SkPath& path, SkClipOp, bool aa) override;
+ void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override;
+
private:
friend class SkCanvas;
friend struct DeviceCM; //for setMatrixClip
@@ -147,6 +155,7 @@ private:
SkBitmap fBitmap;
void* fRasterHandle = nullptr;
+ SkTArray<SkRasterClip> fRCStack;
void setNewSize(const SkISize&); // Used by SkCanvas for resetForNextPicture().
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index eb81bd7951..64ef348e13 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -387,6 +387,16 @@ private:
typedef SkDraw INHERITED;
};
+#define FOR_EACH_TOP_DEVICE( code ) \
+ do { \
+ DeviceCM* layer = fMCRec->fTopLayer; \
+ while (layer) { \
+ SkBaseDevice* device = layer->fDevice; \
+ code; \
+ layer = layer->fNext; \
+ } \
+ } while (0)
+
/////////////////////////////////////////////////////////////////////////////
static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
@@ -999,6 +1009,9 @@ void SkCanvas::doSave() {
SkASSERT(fMCRec->fDeferredSaveCount > 0);
fMCRec->fDeferredSaveCount -= 1;
this->internalSave();
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->save());
+#endif
}
void SkCanvas::restore() {
@@ -1014,6 +1027,9 @@ void SkCanvas::restore() {
fSaveCount -= 1;
this->internalRestore();
this->didRestore();
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
+#endif
}
}
}
@@ -1456,6 +1472,11 @@ void SkCanvas::concat(const SkMatrix& matrix) {
fDeviceCMDirty = true;
fMCRec->fMatrix.preConcat(matrix);
fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
+
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
+#endif
+
this->didConcat(matrix);
}
@@ -1505,6 +1526,11 @@ void SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
void SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
+
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
+#endif
+
AutoValidateClip avc(this);
fClipStack->clipRect(rect, fMCRec->fMatrix, op, isAA);
fMCRec->fRasterClip.op(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
@@ -1542,6 +1568,11 @@ void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edge
fDeviceCMDirty = true;
bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
+
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
+#endif
+
fClipStack->clipRRect(rrect, fMCRec->fMatrix, op, isAA);
fMCRec->fRasterClip.op(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
isAA);
@@ -1579,7 +1610,11 @@ void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeSty
fDeviceCMDirty = true;
bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
-
+
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
+#endif
+
fClipStack->clipPath(path, fMCRec->fMatrix, op, isAA);
const SkPath* rasterClipPath = &path;
@@ -1602,6 +1637,10 @@ void SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
}
void SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
+#endif
+
AutoValidateClip avc(this);
fDeviceCMDirty = true;
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index 92396725a4..3c0b7785d3 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -13,6 +13,9 @@
#include "SkColor.h"
#include "SkSurfaceProps.h"
+// enable to test new device-base clipping
+//#define SK_USE_DEVICE_CLIPPING
+
class SkBitmap;
class SkDraw;
class SkDrawFilter;
@@ -101,6 +104,35 @@ public:
virtual void* getRasterHandle() const { return nullptr; }
+ void save() { this->onSave(); }
+ void restore(const SkMatrix& ctm) {
+ this->onRestore();
+ this->setGlobalCTM(ctm);
+ }
+ void clipRect(const SkRect& rect, SkClipOp op, bool aa) {
+ this->onClipRect(rect, op, aa);
+ }
+ void clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
+ this->onClipRRect(rrect, op, aa);
+ }
+ void clipPath(const SkPath& path, SkClipOp op, bool aa) {
+ this->onClipPath(path, op, aa);
+ }
+ void clipRegion(const SkRegion& region, SkClipOp op) {
+ this->onClipRegion(region, op);
+ }
+
+ const SkMatrix& ctm() const { return fCTM; }
+ void setCTM(const SkMatrix& ctm) {
+ fCTM = ctm;
+ }
+ void setGlobalCTM(const SkMatrix& ctm) {
+ fCTM = ctm;
+ if (fOrigin.fX | fOrigin.fY) {
+ fCTM.postTranslate(-SkIntToScalar(fOrigin.fX), -SkIntToScalar(fOrigin.fY));
+ }
+ }
+
protected:
enum TileUsage {
kPossible_TileUsage, //!< the created device may be drawn tiled
@@ -119,6 +151,13 @@ protected:
virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
+ virtual void onSave() {}
+ virtual void onRestore() {}
+ virtual void onClipRect(const SkRect& rect, SkClipOp, bool aa) {}
+ virtual void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) {}
+ virtual void onClipPath(const SkPath& path, SkClipOp, bool aa) {}
+ virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp) {}
+
/** These are called inside the per-device-layer loop for each draw call.
When these are called, we have already applied any saveLayer operations,
and are handling any looping from the paint, and any effects from the
@@ -348,6 +387,7 @@ private:
SkIPoint fOrigin;
const SkImageInfo fInfo;
const SkSurfaceProps fSurfaceProps;
+ SkMatrix fCTM;
typedef SkRefCnt INHERITED;
};