Build flag available for backends to begin testing their impl.
Need to formalize save/restore, and how to forward these to device but not on picture canvases.
BUG=skia:6214
Change-Id: Ic5c0afba3e8c84fcf124567e63fe2f5880b623e7
Reviewed-on: https://skia-review.googlesource.com/8183
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Brian Salomon <bsalomon@google.com>
{
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) {
{
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,
return cache;
}
-///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const {
if (kN32_SkColorType != fBitmap.colorType() ||
}
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);
+}
#include "SkDevice.h"
#include "SkImageInfo.h"
#include "SkPixelRef.h"
+#include "SkRasterClip.h"
#include "SkRect.h"
#include "SkScalar.h"
#include "SkSize.h"
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
SkBitmap fBitmap;
void* fRasterHandle = nullptr;
+ SkTArray<SkRasterClip> fRCStack;
void setNewSize(const SkISize&); // Used by SkCanvas for resetForNextPicture().
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) {
SkASSERT(fMCRec->fDeferredSaveCount > 0);
fMCRec->fDeferredSaveCount -= 1;
this->internalSave();
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->save());
+#endif
}
void SkCanvas::restore() {
fSaveCount -= 1;
this->internalRestore();
this->didRestore();
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
+#endif
}
}
}
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);
}
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,
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);
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;
}
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;
#include "SkColor.h"
#include "SkSurfaceProps.h"
+// enable to test new device-base clipping
+//#define SK_USE_DEVICE_CLIPPING
+
class SkBitmap;
class SkDraw;
class SkDrawFilter;
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
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
SkIPoint fOrigin;
const SkImageInfo fInfo;
const SkSurfaceProps fSurfaceProps;
+ SkMatrix fCTM;
typedef SkRefCnt INHERITED;
};