Revert[6] "Remove SkDraw from device-draw methods, and enable device-centric clipping.""""""
Previous failure was failure to detect that the clip wasn't wide-open when
optimizing for retain-vs-discard in copy-on-write. gm:copy_on_write_retain
detected this. Now fixed by adding new method to SkBaseDevice.h
This reverts commit 27d07f0acb85eea4062075dfbe9148ce12d92c66.
BUG=skia:6214
Change-Id: I532d16ec075a4525c2a550b1157bcec695dd8efd
Reviewed-on: https://skia-review.googlesource.com/9341
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 5c7039f..daefeeb 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -75,8 +75,17 @@
const SkISize size = this->getBaseLayerSize();
const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
- if (!this->getClipStack()->quickContains(bounds)) {
- return false;
+
+ // if we're clipped at all, we can't overwrite the entire surface
+ {
+ SkBaseDevice* base = this->getDevice();
+ SkBaseDevice* top = this->getTopDevice();
+ if (base != top) {
+ return false; // we're in a saveLayer, so conservatively don't assume we'll overwrite
+ }
+ if (!base->clipIsWideOpen()) {
+ return false;
+ }
}
if (rect) {
@@ -192,10 +201,8 @@
SkMatrix fMatrixStorage;
SkMatrix fStashedMatrix; // original CTM; used by imagefilter in saveLayer
- DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
- bool conservativeRasterClip, const SkMatrix& stashed)
+ DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, const SkMatrix& stashed)
: fNext(nullptr)
- , fClip(conservativeRasterClip)
, fStashedMatrix(stashed)
{
SkSafeRef(device);
@@ -214,48 +221,6 @@
SkASSERT(fDevice);
fClip.setRect(bounds);
}
-
- void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
- SkRasterClip* updateClip) {
- int x = fDevice->getOrigin().x();
- int y = fDevice->getOrigin().y();
- int width = fDevice->width();
- int height = fDevice->height();
-
- if ((x | y) == 0) {
- fMatrix = &totalMatrix;
- fClip = totalClip;
- } else {
- fMatrixStorage = totalMatrix;
- fMatrixStorage.postTranslate(SkIntToScalar(-x),
- SkIntToScalar(-y));
- fMatrix = &fMatrixStorage;
- totalClip.translate(-x, -y, &fClip);
- }
-
- fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
-
-#ifdef SK_USE_DEVICE_CLIPPING
- SkASSERT(*fMatrix == fDevice->ctm());
- // TODO: debug tiles-rt-8888 so we can enable this all the time
-// fDevice->validateDevBounds(fClip.getBounds());
-#endif
-
- // intersect clip, but don't translate it (yet)
-
- if (updateClip) {
- updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
- SkRegion::kDifference_Op);
- }
-
-#ifdef SK_DEBUG
- if (!fClip.isEmpty()) {
- SkIRect deviceR;
- deviceR.set(0, 0, width, height);
- SkASSERT(deviceR.contains(fClip.getBounds()));
- }
-#endif
- }
};
/* This is the record we keep for each save/restore level in the stack.
@@ -275,15 +240,15 @@
reference counted, since the real owner is either our fLayer field,
or a previous one in a lower level.)
*/
- DeviceCM* fTopLayer;
- SkRasterClip fRasterClip;
- SkMatrix fMatrix;
- int fDeferredSaveCount;
+ DeviceCM* fTopLayer;
+ SkConservativeClip fRasterClip;
+ SkMatrix fMatrix;
+ int fDeferredSaveCount;
// This is the current cumulative depth (aggregate of all done translateZ calls)
SkScalar fCurDrawDepth;
- MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
+ MCRec() {
fFilter = nullptr;
fLayer = nullptr;
fTopLayer = nullptr;
@@ -320,70 +285,26 @@
}
};
-static SkIRect compute_device_bounds(SkBaseDevice* device) {
- return SkIRect::MakeXYWH(device->getOrigin().x(), device->getOrigin().y(),
- device->width(), device->height());
-}
-
-class SkDrawIter : public SkDraw {
+class SkDrawIter {
public:
- SkDrawIter(SkCanvas* canvas) : fDevice(nullptr) {
- canvas->updateDeviceCMCache();
-
- fClipStack = canvas->getClipStack();
- fCurrLayer = canvas->fMCRec->fTopLayer;
-
- fMultiDeviceCS = nullptr;
- if (fCurrLayer->fNext) {
- fMultiDeviceCS = canvas->fClipStack.get();
- fMultiDeviceCS->save();
- }
-#ifdef SK_USE_DEVICE_CLIPPING
- fClipStack = nullptr; // for testing
-#endif
- }
-
- ~SkDrawIter() {
- if (fMultiDeviceCS) {
- fMultiDeviceCS->restore();
- }
- }
+ SkDrawIter(SkCanvas* canvas)
+ : fDevice(nullptr), fCurrLayer(canvas->fMCRec->fTopLayer), fPaint(nullptr)
+ {}
bool next() {
- if (fMultiDeviceCS && fDevice) {
- // remove the previous device's bounds
- fMultiDeviceCS->clipDevRect(compute_device_bounds(fDevice), kDifference_SkClipOp);
- }
-
- // skip over recs with empty clips
- while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
- fCurrLayer = fCurrLayer->fNext;
- }
-
const DeviceCM* rec = fCurrLayer;
if (rec && rec->fDevice) {
-
- fMatrix = rec->fMatrix;
- fRC = &rec->fClip;
fDevice = rec->fDevice;
- if (!fDevice->accessPixels(&fDst)) {
- fDst.reset(fDevice->imageInfo(), nullptr, 0);
- }
fPaint = rec->fPaint;
- SkDEBUGCODE(this->validate();)
-
fCurrLayer = rec->fNext;
// fCurrLayer may be nullptr now
-
return true;
}
return false;
}
- const SkRasterClip& getClip() const { return *fRC; }
int getX() const { return fDevice->getOrigin().x(); }
int getY() const { return fDevice->getOrigin().y(); }
- const SkMatrix& getMatrix() const { return *fMatrix; }
const SkPaint* getPaint() const { return fPaint; }
SkBaseDevice* fDevice;
@@ -391,9 +312,6 @@
private:
const DeviceCM* fCurrLayer;
const SkPaint* fPaint; // May be null.
- SkClipStack* fMultiDeviceCS;
-
- typedef SkDraw INHERITED;
};
#define FOR_EACH_TOP_DEVICE( code ) \
@@ -657,7 +575,6 @@
void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
this->restoreToCount(1);
- fClipStack->reset();
fMCRec->reset(bounds);
// We're peering through a lot of structs here. Only at this scope do we
@@ -671,29 +588,22 @@
if (device && device->forceConservativeRasterClip()) {
flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
}
- // Since init() is only called once by our constructors, it is safe to perform this
- // const-cast.
- *const_cast<bool*>(&fConservativeRasterClip) = SkToBool(flags & kConservativeRasterClip_InitFlag);
fAllowSimplifyClip = false;
- fDeviceCMDirty = true;
fSaveCount = 1;
fMetaData = nullptr;
#ifdef SK_EXPERIMENTAL_SHADOWING
fLights = nullptr;
#endif
- fClipStack.reset(new SkClipStack);
-
fMCRec = (MCRec*)fMCStack.push_back();
- new (fMCRec) MCRec(fConservativeRasterClip);
+ new (fMCRec) MCRec;
fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
fIsScaleTranslate = true;
SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
- new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip,
- fMCRec->fMatrix);
+ new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fMCRec->fMatrix);
fMCRec->fTopLayer = fMCRec->fLayer;
@@ -706,9 +616,7 @@
fMCRec->fRasterClip.setRect(device->getGlobalBounds());
fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
-#ifdef SK_USE_DEVICE_CLIPPING
device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
-#endif
}
return device;
@@ -717,7 +625,6 @@
SkCanvas::SkCanvas()
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(SkSurfaceProps::kLegacyFontHost_InitType)
- , fConservativeRasterClip(false)
{
inc_canvas();
@@ -746,7 +653,6 @@
SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(SkSurfacePropsCopyOrDefault(props))
- , fConservativeRasterClip(false)
{
inc_canvas();
@@ -757,7 +663,6 @@
SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(SkSurfaceProps::kLegacyFontHost_InitType)
- , fConservativeRasterClip(false)
{
inc_canvas();
@@ -767,7 +672,6 @@
SkCanvas::SkCanvas(SkBaseDevice* device)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(device->surfaceProps())
- , fConservativeRasterClip(false)
{
inc_canvas();
@@ -777,7 +681,6 @@
SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(device->surfaceProps())
- , fConservativeRasterClip(false)
{
inc_canvas();
@@ -787,7 +690,6 @@
SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(props)
- , fConservativeRasterClip(false)
{
inc_canvas();
@@ -800,7 +702,6 @@
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(SkSurfaceProps::kLegacyFontHost_InitType)
, fAllocator(std::move(alloc))
- , fConservativeRasterClip(false)
{
inc_canvas();
@@ -967,26 +868,6 @@
//////////////////////////////////////////////////////////////////////////////
-void SkCanvas::updateDeviceCMCache() {
- if (fDeviceCMDirty) {
- const SkMatrix& totalMatrix = this->getTotalMatrix();
- const SkRasterClip& totalClip = fMCRec->fRasterClip;
- DeviceCM* layer = fMCRec->fTopLayer;
-
- if (nullptr == layer->fNext) { // only one layer
- layer->updateMC(totalMatrix, totalClip, nullptr);
- } else {
- SkRasterClip clip(totalClip);
- do {
- layer->updateMC(totalMatrix, clip, &clip);
- } while ((layer = layer->fNext) != nullptr);
- }
- fDeviceCMDirty = false;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
void SkCanvas::checkForDeferredSave() {
if (fMCRec->fDeferredSaveCount > 0) {
this->doSave();
@@ -1057,10 +938,7 @@
new (newTop) MCRec(*fMCRec); // balanced in restore()
fMCRec = newTop;
- fClipStack->save();
-#ifdef SK_USE_DEVICE_CLIPPING
FOR_EACH_TOP_DEVICE(device->save());
-#endif
}
bool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
@@ -1091,6 +969,7 @@
// early exit if the layer's bounds are clipped out
if (!ir.intersect(clipBounds)) {
if (BoundsAffectsClip(saveLayerFlags)) {
+ fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty
fMCRec->fRasterClip.setEmpty();
fDeviceClipBounds.setEmpty();
}
@@ -1103,7 +982,6 @@
if (BoundsAffectsClip(saveLayerFlags)) {
// Simplify the current clips since they will be applied properly during restore()
- fClipStack->clipDevRect(ir, kReplace_SkClipOp);
fMCRec->fRasterClip.setRect(ir);
fDeviceClipBounds = qr_clip_bounds(ir);
}
@@ -1136,7 +1014,7 @@
void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
SkBaseDevice* dst, const SkIPoint& dstOrigin,
- const SkMatrix& ctm, const SkClipStack* clipStack) {
+ const SkMatrix& ctm) {
SkDraw draw;
SkRasterClip rc;
rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
@@ -1145,7 +1023,6 @@
}
draw.fMatrix = &SkMatrix::I();
draw.fRC = &rc;
- draw.fClipStack = clipStack;
SkPaint p;
if (filter) {
@@ -1156,7 +1033,7 @@
int y = src->getOrigin().y() - dstOrigin.y();
auto special = src->snapSpecial();
if (special) {
- dst->drawSpecial(draw, special.get(), x, y, p);
+ dst->drawSpecial(special.get(), x, y, p);
}
}
@@ -1220,8 +1097,6 @@
// that would invoke a possibly overridden virtual
this->internalSave();
- fDeviceCMDirty = true;
-
SkIRect ir;
if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
return;
@@ -1265,12 +1140,8 @@
return;
}
}
-#ifndef SK_USE_DEVICE_CLIPPING
- newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
-#endif
-
DeviceCM* layer =
- new DeviceCM(newDevice.get(), paint, this, fConservativeRasterClip, stashedMatrix);
+ new DeviceCM(newDevice.get(), paint, this, stashedMatrix);
// only have a "next" if this new layer doesn't affect the clip (rare)
layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
@@ -1279,10 +1150,9 @@
if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
- fMCRec->fMatrix, this->getClipStack());
+ fMCRec->fMatrix);
}
-#ifdef SK_USE_DEVICE_CLIPPING
newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
@@ -1295,7 +1165,6 @@
layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
} while (layer->fNext);
}
-#endif
}
int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
@@ -1311,10 +1180,6 @@
void SkCanvas::internalRestore() {
SkASSERT(fMCStack.count() != 0);
- fDeviceCMDirty = true;
-
- fClipStack->restore();
-
// reserve our layer (if any)
DeviceCM* layer = fMCRec->fLayer; // may be null
// now detach it from fMCRec so we can pop(). Gets freed after its drawn
@@ -1325,11 +1190,9 @@
fMCStack.pop_back();
fMCRec = (MCRec*)fMCStack.back();
-#ifdef SK_USE_DEVICE_CLIPPING
if (fMCRec) {
FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
}
-#endif
/* Time to draw the layer's offscreen. We can't call the public drawSprite,
since if we're being recorded, we don't want to record this (the
@@ -1342,7 +1205,6 @@
// restore what we smashed in internalSaveLayer
fMCRec->fMatrix = layer->fStashedMatrix;
// reset this, since internalDrawDevice will have set it to true
- fDeviceCMDirty = true;
delete layer;
} else {
// we're at the root
@@ -1448,10 +1310,10 @@
if (filter) {
sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
if (specialImage) {
- dstDev->drawSpecial(iter, specialImage.get(), pos.x(), pos.y(), *paint);
+ dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint);
}
} else {
- dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
+ dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
}
}
@@ -1463,15 +1325,12 @@
void SkCanvas::translate(SkScalar dx, SkScalar dy) {
if (dx || dy) {
this->checkForDeferredSave();
- fDeviceCMDirty = true;
fMCRec->fMatrix.preTranslate(dx,dy);
// Translate shouldn't affect the is-scale-translateness of the matrix.
SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
-#ifdef SK_USE_DEVICE_CLIPPING
FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
-#endif
this->didTranslate(dx,dy);
}
@@ -1507,25 +1366,19 @@
}
this->checkForDeferredSave();
- 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::internalSetMatrix(const SkMatrix& matrix) {
- fDeviceCMDirty = true;
fMCRec->fMatrix = matrix;
fIsScaleTranslate = matrix.isScaleTranslate();
-#ifdef SK_USE_DEVICE_CLIPPING
FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
-#endif
}
void SkCanvas::setMatrix(const SkMatrix& matrix) {
@@ -1569,36 +1422,25 @@
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,
isAA);
- fDeviceCMDirty = true;
fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
}
void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
fClipRestrictionRect = rect;
- fClipStack->setDeviceClipRestriction(fClipRestrictionRect);
if (fClipRestrictionRect.isEmpty()) {
// we notify the device, but we *dont* resolve deferred saves (since we're just
// removing the restriction if the rect is empty. how I hate this api.
-#ifdef SK_USE_DEVICE_CLIPPING
FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
-#endif
} else {
this->checkForDeferredSave();
-#ifdef SK_USE_DEVICE_CLIPPING
FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
-#endif
AutoValidateClip avc(this);
- fClipStack->clipDevRect(fClipRestrictionRect, kIntersect_SkClipOp);
fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op);
- fDeviceCMDirty = true;
fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
}
}
@@ -1616,19 +1458,13 @@
void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
AutoValidateClip avc(this);
- 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);
fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
- return;
}
void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
@@ -1659,24 +1495,12 @@
void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
AutoValidateClip avc(this);
- 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;
const SkMatrix* matrix = &fMCRec->fMatrix;
- SkPath tempPath;
- if (fAllowSimplifyClip) {
- isAA = getClipStack()->asPath(&tempPath);
- rasterClipPath = &tempPath;
- matrix = &SkMatrix::I();
- op = kReplace_SkClipOp;
- }
fMCRec->fRasterClip.op(*rasterClipPath, *matrix, this->getTopLayerBounds(), (SkRegion::Op)op,
isAA);
fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
@@ -1688,18 +1512,10 @@
}
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;
-
- // todo: signal fClipStack that we have a region, and therefore (I guess)
- // we have to ignore it, and use the region directly?
- fClipStack->clipDevRect(rgn.getBounds(), op);
-
fMCRec->fRasterClip.op(rgn, (SkRegion::Op)op);
fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
}
@@ -1712,51 +1528,61 @@
SkASSERT(this->isClipEmpty());
return;
}
-
- SkIRect ir;
- ir.set(0, 0, device->width(), device->height());
- SkRasterClip tmpClip(ir, fConservativeRasterClip);
-
- SkClipStack::B2TIter iter(*fClipStack);
- const SkClipStack::Element* element;
- while ((element = iter.next()) != nullptr) {
- switch (element->getType()) {
- case SkClipStack::Element::kRect_Type:
- element->getRect().round(&ir);
- tmpClip.op(ir, (SkRegion::Op)element->getOp());
- break;
- case SkClipStack::Element::kEmpty_Type:
- tmpClip.setEmpty();
- break;
- default: {
- SkPath path;
- element->asPath(&path);
- tmpClip.op(path, SkMatrix::I(), this->getTopLayerBounds(),
- (SkRegion::Op)element->getOp(), element->isAA());
- break;
- }
- }
- }
}
#endif
void SkCanvas::replayClips(ClipVisitor* visitor) const {
+#if 0
SkClipStack::B2TIter iter(*fClipStack);
const SkClipStack::Element* element;
while ((element = iter.next()) != nullptr) {
element->replay(visitor);
}
+#endif
+}
+
+bool SkCanvas::androidFramework_isClipAA() const {
+ bool containsAA = false;
+
+ FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
+
+ return containsAA;
+}
+
+class RgnAccumulator {
+ SkRegion* fRgn;
+public:
+ RgnAccumulator(SkRegion* total) : fRgn(total) {}
+ void accumulate(SkBaseDevice* device, SkRegion* rgn) {
+ SkIPoint origin = device->getOrigin();
+ if (origin.x() | origin.y()) {
+ rgn->translate(origin.x(), origin.y());
+ }
+ fRgn->op(*rgn, SkRegion::kUnion_Op);
+ }
+};
+
+void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
+ RgnAccumulator accum(rgn);
+ SkRegion tmp;
+
+ rgn->setEmpty();
+ FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
}
///////////////////////////////////////////////////////////////////////////////
bool SkCanvas::isClipEmpty() const {
- return fMCRec->fRasterClip.isEmpty();
+ SkBaseDevice* dev = this->getTopDevice();
+ // if no device we return true
+ return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
}
bool SkCanvas::isClipRect() const {
- return fMCRec->fRasterClip.isRect();
+ SkBaseDevice* dev = this->getTopDevice();
+ // if no device we return false
+ return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
}
static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
@@ -1857,38 +1683,13 @@
}
SkIRect SkCanvas::onGetDeviceClipBounds() const {
- const SkRasterClip& clip = fMCRec->fRasterClip;
- if (clip.isEmpty()) {
- return SkIRect::MakeEmpty();
- }
- return clip.getBounds();
+ return fMCRec->fRasterClip.getBounds();
}
const SkMatrix& SkCanvas::getTotalMatrix() const {
return fMCRec->fMatrix;
}
-void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
- // we know that ganesh doesn't track the rgn, so ask for its clipstack
- if (this->getGrContext()) {
- const SkClipStack* cs = this->getClipStack();
- SkClipStack::BoundsType boundType;
- bool isIntersectionOfRects;
- SkRect bounds;
- cs->getBounds(&bounds, &boundType, &isIntersectionOfRects);
- if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) {
- rgn->setRect(bounds.round());
- return;
- }
- SkPath path;
- cs->asPath(&path);
- SkISize size = this->getBaseLayerSize();
- rgn->setPath(path, SkRegion(SkIRect::MakeWH(size.width(), size.height())));
- } else {
- *rgn = fMCRec->fRasterClip.forceGetBW();
- }
-}
-
GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
SkBaseDevice* dev = this->getTopDevice();
return dev ? dev->accessRenderTargetContext() : nullptr;
@@ -2158,7 +1959,7 @@
LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
while (iter.next()) {
- iter.fDevice->drawPaint(iter, looper.paint());
+ iter.fDevice->drawPaint(looper.paint());
}
LOOPER_END
@@ -2192,7 +1993,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
while (iter.next()) {
- iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
+ iter.fDevice->drawPoints(mode, count, pts, looper.paint());
}
LOOPER_END
@@ -2224,7 +2025,7 @@
LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
while (iter.next()) {
- iter.fDevice->drawRect(iter, r, looper.paint());
+ iter.fDevice->drawRect(r, looper.paint());
}
LOOPER_END
@@ -2232,7 +2033,7 @@
this->predrawNotify(&r, &paint, false);
SkDrawIter iter(this);
while (iter.next()) {
- iter.fDevice->drawRect(iter, r, paint);
+ iter.fDevice->drawRect(r, paint);
}
}
}
@@ -2249,7 +2050,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, ®ionRect)
while (iter.next()) {
- iter.fDevice->drawRegion(iter, region, looper.paint());
+ iter.fDevice->drawRegion(region, looper.paint());
}
LOOPER_END
@@ -2267,7 +2068,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
while (iter.next()) {
- iter.fDevice->drawOval(iter, oval, looper.paint());
+ iter.fDevice->drawOval(oval, looper.paint());
}
LOOPER_END
@@ -2288,7 +2089,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
while (iter.next()) {
- iter.fDevice->drawArc(iter, oval, startAngle, sweepAngle, useCenter, looper.paint());
+ iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
}
LOOPER_END
@@ -2316,7 +2117,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
while (iter.next()) {
- iter.fDevice->drawRRect(iter, rrect, looper.paint());
+ iter.fDevice->drawRRect(rrect, looper.paint());
}
LOOPER_END
@@ -2333,7 +2134,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
while (iter.next()) {
- iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
+ iter.fDevice->drawDRRect(outer, inner, looper.paint());
}
LOOPER_END
@@ -2363,7 +2164,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
while (iter.next()) {
- iter.fDevice->drawPath(iter, path, looper.paint());
+ iter.fDevice->drawPath(path, looper.paint());
}
LOOPER_END
@@ -2425,12 +2226,12 @@
const SkPaint& pnt = looper.paint();
if (special) {
SkPoint pt;
- iter.fMatrix->mapXY(x, y, &pt);
- iter.fDevice->drawSpecial(iter, special.get(),
+ iter.fDevice->ctm().mapXY(x, y, &pt);
+ iter.fDevice->drawSpecial(special.get(),
SkScalarRoundToInt(pt.fX),
SkScalarRoundToInt(pt.fY), pnt);
} else {
- iter.fDevice->drawImage(iter, image, x, y, pnt);
+ iter.fDevice->drawImage(image, x, y, pnt);
}
}
@@ -2458,7 +2259,7 @@
image->isOpaque())
while (iter.next()) {
- iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
+ iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
}
LOOPER_END
@@ -2506,12 +2307,12 @@
const SkPaint& pnt = looper.paint();
if (special) {
SkPoint pt;
- iter.fMatrix->mapXY(x, y, &pt);
- iter.fDevice->drawSpecial(iter, special.get(),
+ iter.fDevice->ctm().mapXY(x, y, &pt);
+ iter.fDevice->drawSpecial(special.get(),
SkScalarRoundToInt(pt.fX),
SkScalarRoundToInt(pt.fY), pnt);
} else {
- iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
+ iter.fDevice->drawBitmap(bitmap, matrix, looper.paint());
}
}
@@ -2542,7 +2343,7 @@
bitmap.isOpaque())
while (iter.next()) {
- iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
+ iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
}
LOOPER_END
@@ -2574,7 +2375,7 @@
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
- iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
+ iter.fDevice->drawImageNine(image, center, dst, looper.paint());
}
LOOPER_END
@@ -2600,7 +2401,7 @@
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
- iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
+ iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
}
LOOPER_END
@@ -2623,7 +2424,7 @@
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
- iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint());
+ iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
}
LOOPER_END
@@ -2646,7 +2447,7 @@
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
- iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint());
+ iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
}
LOOPER_END
@@ -2678,7 +2479,7 @@
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
- iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
+ iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
}
LOOPER_END
@@ -2692,7 +2493,7 @@
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
- iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
+ iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
dfp.paint());
}
@@ -2708,7 +2509,7 @@
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
- iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
+ iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
dfp.paint());
}
@@ -2720,7 +2521,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
+ iter.fDevice->drawTextOnPath(text, byteLength, path,
matrix, looper.paint());
}
@@ -2736,7 +2537,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint());
+ iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
}
LOOPER_END
@@ -2765,7 +2566,7 @@
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
- iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
+ iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
}
LOOPER_END
@@ -2825,7 +2626,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
+ iter.fDevice->drawVertices(vmode, vertexCount, verts, texs,
colors, bmode, indices, indexCount,
looper.paint());
}
@@ -2840,7 +2641,7 @@
while (iter.next()) {
// In the common case of one iteration we could std::move vertices here.
- iter.fDevice->drawVerticesObject(iter, vertices, bmode, looper.paint(), flags);
+ iter.fDevice->drawVerticesObject(vertices, bmode, looper.paint(), flags);
}
LOOPER_END
@@ -2880,7 +2681,7 @@
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawPatch(iter, cubics, colors, texCoords, bmode, paint);
+ iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint);
}
LOOPER_END
@@ -2924,7 +2725,7 @@
LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, bmode, pnt);
+ iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
}
LOOPER_END
}
@@ -2935,7 +2736,7 @@
SkPaint paint;
LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawAnnotation(iter, rect, key, value);
+ iter.fDevice->drawAnnotation(rect, key, value);
}
LOOPER_END
}
@@ -3310,7 +3111,7 @@
}
const SkMatrix& SkCanvas::LayerIter::matrix() const {
- return fImpl->getMatrix();
+ return fImpl->fDevice->ctm();
}
const SkPaint& SkCanvas::LayerIter::paint() const {
@@ -3321,7 +3122,10 @@
return *paint;
}
-const SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
+void SkCanvas::LayerIter::clip(SkRegion* rgn) const {
+ return fImpl->fDevice->onAsRgnClip(rgn);
+}
+
int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
int SkCanvas::LayerIter::y() const { return fImpl->getY(); }