aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkCanvas.cpp
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-03-04 21:47:47 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-03-04 21:48:01 +0000
commit27d07f0acb85eea4062075dfbe9148ce12d92c66 (patch)
tree7328000f52b82a4c1478ddc79b8d383f2b832bed /src/core/SkCanvas.cpp
parent5b4599f137ce0966a88d2ba2bdbb6aa72b1ae082 (diff)
Revert "Revert "Revert "Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping."""""
This reverts commit 025e2444c1f5a0c3cdc0bf60d1fa59941a0b5db4. Reason for revert: layouttest failures -- need to rebase these (tiny diffs in gradients) https://storage.googleapis.com/chromium-layout-test-archives/linux_trusty_blink_rel/6018/layout-test-results/results.html Original change's description: > Revert "Revert "Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping."""" > > This reverts commit baf06bc89a0ee2ac4033281e7310f6c727faab79. > > Reason for revert: reland to diagnose possible g3 failure > > Original change's description: > > Revert "Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping.""" > > > > This reverts commit cfaa63237b152ae216f1351207bce3ea9808814c. > > > > Reason for revert: speculative revert to fix Google3 > > > > Original change's description: > > > Revert[2] "Remove SkDraw from device-draw methods, and enable device-centric clipping."" > > > > > > passes new (augmented) CanvasClipType unittest > > > fixed rasterclipstack::setnewsize > > > > > > This reverts commit ea5e676a7b75600edcde3912886486004ccd7626. > > > > > > BUG=skia: > > > > > > Change-Id: I004653e0f4d01454662f8516fccab0046486f273 > > > Reviewed-on: https://skia-review.googlesource.com/9185 > > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > > Commit-Queue: Mike Reed <reed@google.com> > > > > > > > TBR=bsalomon@google.com,reed@google.com,reviews@skia.org > > NOPRESUBMIT=true > > NOTREECHECKS=true > > NOTRY=true > > BUG=skia: > > > > Change-Id: Ibd7ee6383999f008eb6ee59c1c3f1c06a86044ea > > Reviewed-on: https://skia-review.googlesource.com/9230 > > Reviewed-by: Cary Clark <caryclark@google.com> > > Commit-Queue: Cary Clark <caryclark@google.com> > > > > TBR=bsalomon@google.com,reviews@skia.org,caryclark@google.com,reed@google.com,mtklein@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=skia: > > Change-Id: I093fa8788056be39af01191bbf3a9e5de9f73954 > Reviewed-on: https://skia-review.googlesource.com/9244 > Reviewed-by: Mike Reed <reed@google.com> > Commit-Queue: Mike Reed <reed@google.com> > TBR=mtklein@chromium.org,bsalomon@google.com,reviews@skia.org,caryclark@google.com,reed@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=skia: Change-Id: I58f810a8ff241dbaf3133e2fe844548fcd0fa67a Reviewed-on: https://skia-review.googlesource.com/9245 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/core/SkCanvas.cpp')
-rw-r--r--src/core/SkCanvas.cpp403
1 files changed, 302 insertions, 101 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 0e8e7e5644..5c7039fc50 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -75,13 +75,9 @@ bool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* pa
const SkISize size = this->getBaseLayerSize();
const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
-
-#if 0
- // Replace with device method?
if (!this->getClipStack()->quickContains(bounds)) {
return false;
}
-#endif
if (rect) {
if (!this->getTotalMatrix().isScaleTranslate()) {
@@ -196,8 +192,10 @@ struct DeviceCM {
SkMatrix fMatrixStorage;
SkMatrix fStashedMatrix; // original CTM; used by imagefilter in saveLayer
- DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, const SkMatrix& stashed)
+ DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
+ bool conservativeRasterClip, const SkMatrix& stashed)
: fNext(nullptr)
+ , fClip(conservativeRasterClip)
, fStashedMatrix(stashed)
{
SkSafeRef(device);
@@ -216,6 +214,48 @@ struct DeviceCM {
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.
@@ -235,15 +275,15 @@ public:
reference counted, since the real owner is either our fLayer field,
or a previous one in a lower level.)
*/
- DeviceCM* fTopLayer;
- SkConservativeClip fRasterClip;
- SkMatrix fMatrix;
- int fDeferredSaveCount;
+ DeviceCM* fTopLayer;
+ SkRasterClip fRasterClip;
+ SkMatrix fMatrix;
+ int fDeferredSaveCount;
// This is the current cumulative depth (aggregate of all done translateZ calls)
SkScalar fCurDrawDepth;
- MCRec() {
+ MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
fFilter = nullptr;
fLayer = nullptr;
fTopLayer = nullptr;
@@ -280,26 +320,70 @@ public:
}
};
-class SkDrawIter {
+static SkIRect compute_device_bounds(SkBaseDevice* device) {
+ return SkIRect::MakeXYWH(device->getOrigin().x(), device->getOrigin().y(),
+ device->width(), device->height());
+}
+
+class SkDrawIter : public SkDraw {
public:
- SkDrawIter(SkCanvas* canvas)
- : fDevice(nullptr), fCurrLayer(canvas->fMCRec->fTopLayer), fPaint(nullptr)
- {}
+ 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();
+ }
+ }
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;
@@ -307,6 +391,9 @@ public:
private:
const DeviceCM* fCurrLayer;
const SkPaint* fPaint; // May be null.
+ SkClipStack* fMultiDeviceCS;
+
+ typedef SkDraw INHERITED;
};
#define FOR_EACH_TOP_DEVICE( code ) \
@@ -570,6 +657,7 @@ static inline SkRect qr_clip_bounds(const SkIRect& bounds) {
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
@@ -583,22 +671,29 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
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;
+ new (fMCRec) MCRec(fConservativeRasterClip);
fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
fIsScaleTranslate = true;
SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
- new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fMCRec->fMatrix);
+ new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRasterClip,
+ fMCRec->fMatrix);
fMCRec->fTopLayer = fMCRec->fLayer;
@@ -611,7 +706,9 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
fMCRec->fRasterClip.setRect(device->getGlobalBounds());
fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
+#ifdef SK_USE_DEVICE_CLIPPING
device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
+#endif
}
return device;
@@ -620,6 +717,7 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
SkCanvas::SkCanvas()
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(SkSurfaceProps::kLegacyFontHost_InitType)
+ , fConservativeRasterClip(false)
{
inc_canvas();
@@ -648,6 +746,7 @@ private:
SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(SkSurfacePropsCopyOrDefault(props))
+ , fConservativeRasterClip(false)
{
inc_canvas();
@@ -658,6 +757,7 @@ SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(SkSurfaceProps::kLegacyFontHost_InitType)
+ , fConservativeRasterClip(false)
{
inc_canvas();
@@ -667,6 +767,7 @@ SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
SkCanvas::SkCanvas(SkBaseDevice* device)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(device->surfaceProps())
+ , fConservativeRasterClip(false)
{
inc_canvas();
@@ -676,6 +777,7 @@ SkCanvas::SkCanvas(SkBaseDevice* device)
SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(device->surfaceProps())
+ , fConservativeRasterClip(false)
{
inc_canvas();
@@ -685,6 +787,7 @@ SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(props)
+ , fConservativeRasterClip(false)
{
inc_canvas();
@@ -697,6 +800,7 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptr<SkRasterHandleAllocat
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
, fProps(SkSurfaceProps::kLegacyFontHost_InitType)
, fAllocator(std::move(alloc))
+ , fConservativeRasterClip(false)
{
inc_canvas();
@@ -863,6 +967,26 @@ bool SkCanvas::writePixels(const SkImageInfo& srcInfo, const void* pixels, size_
//////////////////////////////////////////////////////////////////////////////
+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();
@@ -933,7 +1057,10 @@ void SkCanvas::internalSave() {
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) {
@@ -964,7 +1091,6 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag
// 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();
}
@@ -977,6 +1103,7 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag
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);
}
@@ -1009,7 +1136,7 @@ int SkCanvas::saveLayer(const SaveLayerRec& origRec) {
void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
SkBaseDevice* dst, const SkIPoint& dstOrigin,
- const SkMatrix& ctm) {
+ const SkMatrix& ctm, const SkClipStack* clipStack) {
SkDraw draw;
SkRasterClip rc;
rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
@@ -1018,6 +1145,7 @@ void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filt
}
draw.fMatrix = &SkMatrix::I();
draw.fRC = &rc;
+ draw.fClipStack = clipStack;
SkPaint p;
if (filter) {
@@ -1028,7 +1156,7 @@ void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filt
int y = src->getOrigin().y() - dstOrigin.y();
auto special = src->snapSpecial();
if (special) {
- dst->drawSpecial(special.get(), x, y, p);
+ dst->drawSpecial(draw, special.get(), x, y, p);
}
}
@@ -1092,6 +1220,8 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
// that would invoke a possibly overridden virtual
this->internalSave();
+ fDeviceCMDirty = true;
+
SkIRect ir;
if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
return;
@@ -1135,8 +1265,12 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
return;
}
}
+#ifndef SK_USE_DEVICE_CLIPPING
+ newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
+#endif
+
DeviceCM* layer =
- new DeviceCM(newDevice.get(), paint, this, stashedMatrix);
+ new DeviceCM(newDevice.get(), paint, this, fConservativeRasterClip, stashedMatrix);
// only have a "next" if this new layer doesn't affect the clip (rare)
layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
@@ -1145,9 +1279,10 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
- fMCRec->fMatrix);
+ fMCRec->fMatrix, this->getClipStack());
}
+#ifdef SK_USE_DEVICE_CLIPPING
newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
@@ -1160,6 +1295,7 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
} while (layer->fNext);
}
+#endif
}
int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
@@ -1175,6 +1311,10 @@ int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
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
@@ -1185,9 +1325,11 @@ void SkCanvas::internalRestore() {
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
@@ -1200,6 +1342,7 @@ void SkCanvas::internalRestore() {
// 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
@@ -1305,10 +1448,10 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPa
if (filter) {
sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
if (specialImage) {
- dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint);
+ dstDev->drawSpecial(iter, specialImage.get(), pos.x(), pos.y(), *paint);
}
} else {
- dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
+ dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
}
}
@@ -1320,12 +1463,15 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPa
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);
}
@@ -1361,19 +1507,25 @@ void SkCanvas::concat(const SkMatrix& matrix) {
}
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) {
@@ -1417,25 +1569,36 @@ 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,
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());
}
}
@@ -1453,13 +1616,19 @@ void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
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) {
@@ -1490,12 +1659,24 @@ void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
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());
@@ -1507,10 +1688,18 @@ 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;
+
+ // 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());
}
@@ -1523,61 +1712,51 @@ void SkCanvas::validateClip() const {
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 {
- SkBaseDevice* dev = this->getTopDevice();
- // if no device we return true
- return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
+ return fMCRec->fRasterClip.isEmpty();
}
bool SkCanvas::isClipRect() const {
- SkBaseDevice* dev = this->getTopDevice();
- // if no device we return false
- return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
+ return fMCRec->fRasterClip.isRect();
}
static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
@@ -1678,13 +1857,38 @@ SkRect SkCanvas::onGetLocalClipBounds() const {
}
SkIRect SkCanvas::onGetDeviceClipBounds() const {
- return fMCRec->fRasterClip.getBounds();
+ const SkRasterClip& clip = fMCRec->fRasterClip;
+ if (clip.isEmpty()) {
+ return SkIRect::MakeEmpty();
+ }
+ return clip.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;
@@ -1954,7 +2158,7 @@ void SkCanvas::internalDrawPaint(const SkPaint& paint) {
LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
while (iter.next()) {
- iter.fDevice->drawPaint(looper.paint());
+ iter.fDevice->drawPaint(iter, looper.paint());
}
LOOPER_END
@@ -1988,7 +2192,7 @@ void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
while (iter.next()) {
- iter.fDevice->drawPoints(mode, count, pts, looper.paint());
+ iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
}
LOOPER_END
@@ -2020,7 +2224,7 @@ void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
while (iter.next()) {
- iter.fDevice->drawRect(r, looper.paint());
+ iter.fDevice->drawRect(iter, r, looper.paint());
}
LOOPER_END
@@ -2028,7 +2232,7 @@ void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
this->predrawNotify(&r, &paint, false);
SkDrawIter iter(this);
while (iter.next()) {
- iter.fDevice->drawRect(r, paint);
+ iter.fDevice->drawRect(iter, r, paint);
}
}
}
@@ -2045,7 +2249,7 @@ void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
while (iter.next()) {
- iter.fDevice->drawRegion(region, looper.paint());
+ iter.fDevice->drawRegion(iter, region, looper.paint());
}
LOOPER_END
@@ -2063,7 +2267,7 @@ void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
while (iter.next()) {
- iter.fDevice->drawOval(oval, looper.paint());
+ iter.fDevice->drawOval(iter, oval, looper.paint());
}
LOOPER_END
@@ -2084,7 +2288,7 @@ void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
while (iter.next()) {
- iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
+ iter.fDevice->drawArc(iter, oval, startAngle, sweepAngle, useCenter, looper.paint());
}
LOOPER_END
@@ -2112,7 +2316,7 @@ void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
while (iter.next()) {
- iter.fDevice->drawRRect(rrect, looper.paint());
+ iter.fDevice->drawRRect(iter, rrect, looper.paint());
}
LOOPER_END
@@ -2129,7 +2333,7 @@ void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const Sk
LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
while (iter.next()) {
- iter.fDevice->drawDRRect(outer, inner, looper.paint());
+ iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
}
LOOPER_END
@@ -2159,7 +2363,7 @@ void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
while (iter.next()) {
- iter.fDevice->drawPath(path, looper.paint());
+ iter.fDevice->drawPath(iter, path, looper.paint());
}
LOOPER_END
@@ -2221,12 +2425,12 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S
const SkPaint& pnt = looper.paint();
if (special) {
SkPoint pt;
- iter.fDevice->ctm().mapXY(x, y, &pt);
- iter.fDevice->drawSpecial(special.get(),
+ iter.fMatrix->mapXY(x, y, &pt);
+ iter.fDevice->drawSpecial(iter, special.get(),
SkScalarRoundToInt(pt.fX),
SkScalarRoundToInt(pt.fY), pnt);
} else {
- iter.fDevice->drawImage(image, x, y, pnt);
+ iter.fDevice->drawImage(iter, image, x, y, pnt);
}
}
@@ -2254,7 +2458,7 @@ void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const Sk
image->isOpaque())
while (iter.next()) {
- iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
+ iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
}
LOOPER_END
@@ -2302,12 +2506,12 @@ void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, cons
const SkPaint& pnt = looper.paint();
if (special) {
SkPoint pt;
- iter.fDevice->ctm().mapXY(x, y, &pt);
- iter.fDevice->drawSpecial(special.get(),
+ iter.fMatrix->mapXY(x, y, &pt);
+ iter.fDevice->drawSpecial(iter, special.get(),
SkScalarRoundToInt(pt.fX),
SkScalarRoundToInt(pt.fY), pnt);
} else {
- iter.fDevice->drawBitmap(bitmap, matrix, looper.paint());
+ iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
}
}
@@ -2338,7 +2542,7 @@ void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
bitmap.isOpaque())
while (iter.next()) {
- iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
+ iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
}
LOOPER_END
@@ -2370,7 +2574,7 @@ void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, cons
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
- iter.fDevice->drawImageNine(image, center, dst, looper.paint());
+ iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
}
LOOPER_END
@@ -2396,7 +2600,7 @@ void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, c
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
- iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
+ iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
}
LOOPER_END
@@ -2419,7 +2623,7 @@ void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
- iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
+ iter.fDevice->drawImageLattice(iter, image, lattice, dst, looper.paint());
}
LOOPER_END
@@ -2442,7 +2646,7 @@ void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattic
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
while (iter.next()) {
- iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
+ iter.fDevice->drawBitmapLattice(iter, bitmap, lattice, dst, looper.paint());
}
LOOPER_END
@@ -2474,7 +2678,7 @@ void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkSca
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
- iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
+ iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
}
LOOPER_END
@@ -2488,7 +2692,7 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
- iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
+ iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
dfp.paint());
}
@@ -2504,7 +2708,7 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
- iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
+ iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
dfp.paint());
}
@@ -2516,7 +2720,7 @@ void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPat
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawTextOnPath(text, byteLength, path,
+ iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
matrix, looper.paint());
}
@@ -2532,7 +2736,7 @@ void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRS
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
+ iter.fDevice->drawTextRSXform(iter, text, byteLength, xform, looper.paint());
}
LOOPER_END
@@ -2561,7 +2765,7 @@ void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
- iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
+ iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
}
LOOPER_END
@@ -2621,7 +2825,7 @@ void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawVertices(vmode, vertexCount, verts, texs,
+ iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
colors, bmode, indices, indexCount,
looper.paint());
}
@@ -2636,7 +2840,7 @@ void SkCanvas::onDrawVerticesObject(sk_sp<SkVertices> vertices, SkBlendMode bmod
while (iter.next()) {
// In the common case of one iteration we could std::move vertices here.
- iter.fDevice->drawVerticesObject(vertices, bmode, looper.paint(), flags);
+ iter.fDevice->drawVerticesObject(iter, vertices, bmode, looper.paint(), flags);
}
LOOPER_END
@@ -2676,7 +2880,7 @@ void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint);
+ iter.fDevice->drawPatch(iter, cubics, colors, texCoords, bmode, paint);
}
LOOPER_END
@@ -2720,7 +2924,7 @@ void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const
LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
+ iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, bmode, pnt);
}
LOOPER_END
}
@@ -2731,7 +2935,7 @@ void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* va
SkPaint paint;
LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
while (iter.next()) {
- iter.fDevice->drawAnnotation(rect, key, value);
+ iter.fDevice->drawAnnotation(iter, rect, key, value);
}
LOOPER_END
}
@@ -3106,7 +3310,7 @@ SkBaseDevice* SkCanvas::LayerIter::device() const {
}
const SkMatrix& SkCanvas::LayerIter::matrix() const {
- return fImpl->fDevice->ctm();
+ return fImpl->getMatrix();
}
const SkPaint& SkCanvas::LayerIter::paint() const {
@@ -3117,10 +3321,7 @@ const SkPaint& SkCanvas::LayerIter::paint() const {
return *paint;
}
-void SkCanvas::LayerIter::clip(SkRegion* rgn) const {
- return fImpl->fDevice->onAsRgnClip(rgn);
-}
-
+const SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
int SkCanvas::LayerIter::y() const { return fImpl->getY(); }