aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkCanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/SkCanvas.cpp')
-rw-r--r--src/core/SkCanvas.cpp75
1 files changed, 59 insertions, 16 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 562e0ae606..0c6f241e97 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -230,12 +230,17 @@ struct DeviceCM {
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) {
@@ -392,7 +397,9 @@ private:
DeviceCM* layer = fMCRec->fTopLayer; \
while (layer) { \
SkBaseDevice* device = layer->fDevice; \
- code; \
+ if (device) { \
+ code; \
+ } \
layer = layer->fNext; \
} \
} while (0)
@@ -694,6 +701,10 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
fMCRec->fLayer->fDevice = SkRef(device);
fMCRec->fRasterClip.setRect(device->getGlobalBounds());
fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
+
+#ifdef SK_USE_DEVICE_CLIPPING
+ device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
+#endif
}
return device;
@@ -720,7 +731,7 @@ public:
SkNoPixelsBitmapDevice(const SkIRect& bounds, const SkSurfaceProps& surfaceProps)
: INHERITED(make_nopixels(bounds.width(), bounds.height()), surfaceProps)
{
- this->setOrigin(bounds.x(), bounds.y());
+ this->setOrigin(SkMatrix::I(), bounds.x(), bounds.y());
}
private:
@@ -1006,9 +1017,6 @@ 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() {
@@ -1024,9 +1032,6 @@ void SkCanvas::restore() {
fSaveCount -= 1;
this->internalRestore();
this->didRestore();
-#ifdef SK_USE_DEVICE_CLIPPING
- FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
-#endif
}
}
}
@@ -1049,6 +1054,9 @@ void SkCanvas::internalSave() {
fMCRec = newTop;
fClipStack->save();
+#ifdef SK_USE_DEVICE_CLIPPING
+ FOR_EACH_TOP_DEVICE(device->save());
+#endif
}
bool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
@@ -1123,8 +1131,8 @@ int SkCanvas::saveLayer(const SaveLayerRec& origRec) {
}
void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
- SkBaseDevice* dst, const SkMatrix& ctm,
- const SkClipStack* clipStack) {
+ SkBaseDevice* dst, const SkIPoint& dstOrigin,
+ const SkMatrix& ctm, const SkClipStack* clipStack) {
SkDraw draw;
SkRasterClip rc;
rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
@@ -1139,8 +1147,8 @@ void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filt
SkPaint p;
p.setImageFilter(filter->makeWithLocalMatrix(ctm));
- int x = src->getOrigin().x() - dst->getOrigin().x();
- int y = src->getOrigin().y() - dst->getOrigin().y();
+ int x = src->getOrigin().x() - dstOrigin.x();
+ int y = src->getOrigin().y() - dstOrigin.y();
auto special = src->snapSpecial();
if (special) {
dst->drawSpecial(draw, special.get(), x, y, p);
@@ -1231,7 +1239,7 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
}
SkBaseDevice* priorDevice = this->getTopDevice();
- if (nullptr == priorDevice) {
+ if (nullptr == priorDevice) { // Do we still need this check???
SkDebugf("Unable to find device for layer.");
return;
}
@@ -1252,7 +1260,9 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
return;
}
}
- newDevice->setOrigin(ir.fLeft, ir.fTop);
+#ifndef SK_USE_DEVICE_CLIPPING
+ newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
+#endif
DeviceCM* layer =
new DeviceCM(newDevice.get(), paint, this, fConservativeRasterClip, stashedMatrix);
@@ -1263,9 +1273,24 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
if (rec.fBackdrop) {
- DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(),
+ DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
fMCRec->fMatrix, this->getClipStack());
}
+
+#ifdef SK_USE_DEVICE_CLIPPING
+ newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
+
+ newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
+ if (layer->fNext) {
+ // need to punch a hole in the previous device, so we don't draw there, given that
+ // the new top-layer will allow drawing to happen "below" it.
+ SkRegion hole(ir);
+ do {
+ layer = layer->fNext;
+ layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
+ } while (layer->fNext);
+ }
+#endif
}
int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
@@ -1295,6 +1320,12 @@ 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
recorder will have already recorded the restore).
@@ -1433,6 +1464,10 @@ void SkCanvas::translate(SkScalar dx, SkScalar 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);
}
}
@@ -1482,6 +1517,10 @@ 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) {
@@ -1542,6 +1581,10 @@ void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
fClipStack->setDeviceClipRestriction(fClipRestrictionRect);
if (!fClipRestrictionRect.isEmpty()) {
this->checkForDeferredSave();
+#ifdef SK_USE_DEVICE_CLIPPING
+ SkRegion restrictRgn(fClipRestrictionRect);
+ FOR_EACH_TOP_DEVICE(device->clipRegion(restrictRgn, SkClipOp::kIntersect));
+#endif
AutoValidateClip avc(this);
fClipStack->clipDevRect(fClipRestrictionRect, kIntersect_SkClipOp);
fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op);