aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-04-28 13:48:37 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-01 14:07:10 +0000
commit53f77bd4fdd76525b66b7f26d1c5c550858120df (patch)
treed7516fa1c29a35a3e6b62aae82f3bb6e72928cf4 /src
parent57061eea444a8d85189827f014a451de63b49d1a (diff)
Initial clip-mask-layer support
SkBitmapDevice-only implementation. Will add A8 fast path specializations in a follow-up. Change-Id: I2ccb1ffba3689e92ac90a23e94737471dfb121a1 BUG=skia:6005 Change-Id: I2ccb1ffba3689e92ac90a23e94737471dfb121a1 Reviewed-on: https://skia-review.googlesource.com/14183 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkBitmapDevice.cpp73
-rw-r--r--src/core/SkBitmapDevice.h3
-rw-r--r--src/core/SkCanvas.cpp39
-rw-r--r--src/core/SkColorSpaceXformCanvas.cpp3
-rw-r--r--src/core/SkDevice.cpp3
-rw-r--r--src/core/SkDevice.h3
-rw-r--r--src/core/SkDraw.h3
-rw-r--r--src/core/SkLiteDL.cpp15
-rw-r--r--src/core/SkLiteDL.h3
-rw-r--r--src/core/SkLiteRecorder.cpp3
-rw-r--r--src/core/SkPictureFlat.h2
-rw-r--r--src/core/SkPicturePlayback.cpp10
-rw-r--r--src/core/SkPictureRecord.cpp14
-rw-r--r--src/core/SkRecordDraw.cpp2
-rw-r--r--src/core/SkRecordOpts.cpp4
-rw-r--r--src/core/SkRecorder.cpp2
-rw-r--r--src/gpu/SkGpuDevice.cpp11
-rw-r--r--src/gpu/SkGpuDevice.h4
-rw-r--r--src/pdf/SkPDFDevice.cpp6
-rw-r--r--src/pdf/SkPDFDevice.h3
-rw-r--r--src/pipe/SkPipeCanvas.cpp13
-rw-r--r--src/pipe/SkPipeFormat.h2
-rw-r--r--src/pipe/SkPipeReader.cpp11
23 files changed, 176 insertions, 56 deletions
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 09f25fb332..f6286210aa 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -20,6 +20,7 @@
#include "SkShader.h"
#include "SkSpecialImage.h"
#include "SkSurface.h"
+#include "SkTLazy.h"
#include "SkVertices.h"
class SkColorTable;
@@ -387,35 +388,71 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain
///////////////////////////////////////////////////////////////////////////////
-void SkBitmapDevice::drawSpecial(SkSpecialImage* srcImg, int x, int y,
- const SkPaint& paint) {
- SkASSERT(!srcImg->isTextureBacked());
+void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPaint& origPaint,
+ SkImage* clipImage, const SkMatrix& clipMatrix) {
+ SkASSERT(!src->isTextureBacked());
- SkBitmap resultBM;
+ sk_sp<SkSpecialImage> filteredImage;
+ SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
- SkImageFilter* filter = paint.getImageFilter();
- if (filter) {
+ if (SkImageFilter* filter = paint->getImageFilter()) {
SkIPoint offset = SkIPoint::Make(0, 0);
- SkMatrix matrix = this->ctm();
- matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
+ const SkMatrix matrix = SkMatrix::Concat(
+ SkMatrix::MakeTrans(SkIntToScalar(-x), SkIntToScalar(-y)), this->ctm());
const SkIRect clipBounds = fRCStack.rc().getBounds().makeOffset(-x, -y);
sk_sp<SkImageFilterCache> cache(this->getImageFilterCache());
SkImageFilter::OutputProperties outputProperties(fBitmap.colorSpace());
SkImageFilter::Context ctx(matrix, clipBounds, cache.get(), outputProperties);
- sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset));
- if (resultImg) {
- SkPaint tmpUnfiltered(paint);
- tmpUnfiltered.setImageFilter(nullptr);
- if (resultImg->getROPixels(&resultBM)) {
- this->drawSprite(resultBM, x + offset.x(), y + offset.y(), tmpUnfiltered);
- }
+ filteredImage = filter->filterImage(src, ctx, &offset);
+ if (!filteredImage) {
+ return;
}
- } else {
- if (srcImg->getROPixels(&resultBM)) {
- this->drawSprite(resultBM, x, y, paint);
+
+ src = filteredImage.get();
+ paint.writable()->setImageFilter(nullptr);
+ x += offset.x();
+ y += offset.y();
+ }
+
+ if (!clipImage) {
+ SkBitmap resultBM;
+ if (src->getROPixels(&resultBM)) {
+ this->drawSprite(resultBM, x, y, *paint);
}
+ return;
+ }
+
+ // Clip image case.
+ sk_sp<SkImage> srcImage(src->asImage());
+ if (!srcImage) {
+ return;
}
+
+ const SkMatrix totalMatrix = SkMatrix::Concat(this->ctm(), clipMatrix);
+
+ SkRect clipBounds;
+ totalMatrix.mapRect(&clipBounds, SkRect::Make(clipImage->bounds()));
+ const SkIRect srcBounds = srcImage->bounds().makeOffset(x, y);
+
+ SkIRect maskBounds = fRCStack.rc().getBounds();
+ if (!maskBounds.intersect(clipBounds.roundOut()) || !maskBounds.intersect(srcBounds)) {
+ return;
+ }
+
+ sk_sp<SkSurface> surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(maskBounds.width(),
+ maskBounds.height()));
+ SkCanvas* canvas = surf->getCanvas();
+ canvas->translate(-maskBounds.x(), -maskBounds.y());
+ canvas->concat(totalMatrix);
+ canvas->drawImage(clipImage, 0, 0);
+ sk_sp<SkImage> mask = surf->makeImageSnapshot();
+
+ const SkMatrix m = SkMatrix::MakeTrans(x - maskBounds.x(), y - maskBounds.y());
+ paint.writable()->setShader(srcImage->makeShader(&m));
+
+ SkAutoDeviceCTMRestore adctmr(this, SkMatrix::I());
+ this->drawImage(mask.get(), maskBounds.x(), maskBounds.y(), *paint);
}
sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkBitmap& bitmap) {
diff --git a/src/core/SkBitmapDevice.h b/src/core/SkBitmapDevice.h
index 8055b9d12d..3e9473d4ee 100644
--- a/src/core/SkBitmapDevice.h
+++ b/src/core/SkBitmapDevice.h
@@ -112,7 +112,8 @@ protected:
///////////////////////////////////////////////////////////////////////////
- void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&) override;
+ void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
+ SkImage*, const SkMatrix&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
sk_sp<SkSpecialImage> snapSpecial() override;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index a54cf44529..c7e1d6e898 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -253,12 +253,17 @@ struct DeviceCM {
SkRasterClip fClip;
std::unique_ptr<const SkPaint> fPaint; // may be null (in the future)
SkMatrix fStashedMatrix; // original CTM; used by imagefilter in saveLayer
+ sk_sp<SkImage> fClipImage;
+ SkMatrix fClipMatrix;
- DeviceCM(sk_sp<SkBaseDevice> device, const SkPaint* paint, const SkMatrix& stashed)
+ DeviceCM(sk_sp<SkBaseDevice> device, const SkPaint* paint, const SkMatrix& stashed,
+ sk_sp<SkImage> clipImage, const SkMatrix* clipMatrix)
: fNext(nullptr)
, fDevice(std::move(device))
, fPaint(paint ? skstd::make_unique<SkPaint>(*paint) : nullptr)
, fStashedMatrix(stashed)
+ , fClipImage(std::move(clipImage))
+ , fClipMatrix(clipMatrix ? *clipMatrix : SkMatrix::I())
{}
void reset(const SkIRect& bounds) {
@@ -649,7 +654,7 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
- new (fDeviceCMStorage) DeviceCM(sk_ref_sp(device), nullptr, fMCRec->fMatrix);
+ new (fDeviceCMStorage) DeviceCM(sk_ref_sp(device), nullptr, fMCRec->fMatrix, nullptr, nullptr);
fMCRec->fTopLayer = fMCRec->fLayer;
@@ -1010,13 +1015,14 @@ int SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPai
}
int SkCanvas::saveLayer(const SaveLayerRec& origRec) {
- SaveLayerRec rec(origRec);
+ SkTCopyOnFirstWrite<SaveLayerRec> rec(origRec);
if (gIgnoreSaveLayerBounds) {
- rec.fBounds = nullptr;
+ rec.writable()->fBounds = nullptr;
}
- SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec);
+
+ SaveLayerStrategy strategy = this->getSaveLayerStrategy(*rec);
fSaveCount += 1;
- this->internalSaveLayer(rec, strategy);
+ this->internalSaveLayer(*rec, strategy);
return this->getSaveCount() - 1;
}
@@ -1041,7 +1047,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(special.get(), x, y, p, nullptr, SkMatrix::I());
}
}
@@ -1148,7 +1154,7 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
return;
}
}
- DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix);
+ DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix, rec.fClipMask, rec.fClipMatrix);
// only have a "next" if this new layer doesn't affect the clip (rare)
layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
@@ -1209,7 +1215,8 @@ void SkCanvas::internalRestore() {
if (fMCRec) {
const SkIPoint& origin = layer->fDevice->getOrigin();
this->internalDrawDevice(layer->fDevice.get(), origin.x(), origin.y(),
- layer->fPaint.get());
+ layer->fPaint.get(),
+ layer->fClipImage.get(), layer->fClipMatrix);
// restore what we smashed in internalSaveLayer
fMCRec->fMatrix = layer->fStashedMatrix;
// reset this, since internalDrawDevice will have set it to true
@@ -1302,7 +1309,8 @@ bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
/////////////////////////////////////////////////////////////////////////////
-void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint) {
+void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint,
+ SkImage* clipImage, const SkMatrix& clipMatrix) {
SkPaint tmp;
if (nullptr == paint) {
paint = &tmp;
@@ -1315,10 +1323,11 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPa
paint = &looper.paint();
SkImageFilter* filter = paint->getImageFilter();
SkIPoint pos = { x - iter.getX(), y - iter.getY() };
- if (filter) {
+ if (filter || clipImage) {
sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
if (specialImage) {
- dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint);
+ dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint,
+ clipImage, clipMatrix);
}
} else {
dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
@@ -2219,7 +2228,8 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S
iter.fDevice->ctm().mapXY(x, y, &pt);
iter.fDevice->drawSpecial(special.get(),
SkScalarRoundToInt(pt.fX),
- SkScalarRoundToInt(pt.fY), pnt);
+ SkScalarRoundToInt(pt.fY), pnt,
+ nullptr, SkMatrix::I());
} else {
iter.fDevice->drawImage(image, x, y, pnt);
}
@@ -2300,7 +2310,8 @@ void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, cons
iter.fDevice->ctm().mapXY(x, y, &pt);
iter.fDevice->drawSpecial(special.get(),
SkScalarRoundToInt(pt.fX),
- SkScalarRoundToInt(pt.fY), pnt);
+ SkScalarRoundToInt(pt.fY), pnt,
+ nullptr, SkMatrix::I());
} else {
iter.fDevice->drawBitmap(bitmap, matrix, looper.paint());
}
diff --git a/src/core/SkColorSpaceXformCanvas.cpp b/src/core/SkColorSpaceXformCanvas.cpp
index f026c6d176..b4dd5bb1c4 100644
--- a/src/core/SkColorSpaceXformCanvas.cpp
+++ b/src/core/SkColorSpaceXformCanvas.cpp
@@ -229,10 +229,13 @@ public:
SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
sk_sp<SkImageFilter> backdrop = rec.fBackdrop ? fXformer->apply(rec.fBackdrop) : nullptr;
+ sk_sp<SkImage> clipMask = rec.fClipMask ? fXformer->apply(rec.fClipMask.get()) : nullptr;
fTarget->saveLayer({
rec.fBounds,
MaybePaint(rec.fPaint, fXformer.get()),
backdrop.get(),
+ std::move(clipMask),
+ rec.fClipMatrix,
rec.fSaveLayerFlags,
});
return kNoLayer_SaveLayerStrategy;
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index f608134503..0b72eeb9e8 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -282,7 +282,8 @@ void SkBaseDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
///////////////////////////////////////////////////////////////////////////////////////////////////
-void SkBaseDevice::drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&) {}
+void SkBaseDevice::drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
+ SkImage*, const SkMatrix&) {}
sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkBitmap&) { return nullptr; }
sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkImage*) { return nullptr; }
sk_sp<SkSpecialImage> SkBaseDevice::snapSpecial() { return nullptr; }
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index f1f5488111..17ccfdd198 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -258,7 +258,8 @@ protected:
virtual void drawTextRSXform(const void* text, size_t len, const SkRSXform[],
const SkPaint&);
- virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&);
+ virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
+ SkImage* clipImage, const SkMatrix& clipMatrix);
virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
virtual sk_sp<SkSpecialImage> snapSpecial();
diff --git a/src/core/SkDraw.h b/src/core/SkDraw.h
index 3168735799..b142e7edf7 100644
--- a/src/core/SkDraw.h
+++ b/src/core/SkDraw.h
@@ -96,6 +96,8 @@ public:
SkMask* mask, SkMask::CreateMode mode,
SkStrokeRec::InitStyle style);
+ void drawDevMask(const SkMask& mask, const SkPaint&) const;
+
enum RectType {
kHair_RectType,
kFill_RectType,
@@ -122,7 +124,6 @@ public:
const SkPaint&, const SkSurfaceProps*) const;
static SkScalar ComputeResScaleForStroking(const SkMatrix& );
private:
- void drawDevMask(const SkMask& mask, const SkPaint&) const;
void drawBitmapAsMask(const SkBitmap&, const SkPaint&) const;
void drawPath(const SkPath&, const SkPaint&, const SkMatrix* preMatrix,
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index 4a8280d5f5..f84060751e 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -91,18 +91,24 @@ namespace {
struct SaveLayer final : Op {
static const auto kType = Type::SaveLayer;
SaveLayer(const SkRect* bounds, const SkPaint* paint,
- const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
+ const SkImageFilter* backdrop, sk_sp<SkImage> clipMask,
+ const SkMatrix* clipMatrix, SkCanvas::SaveLayerFlags flags) {
if (bounds) { this->bounds = *bounds; }
if (paint) { this->paint = *paint; }
this->backdrop = sk_ref_sp(backdrop);
+ this->clipMask = std::move(clipMask);
+ this->clipMatrix = clipMatrix ? *clipMatrix : SkMatrix::I();
this->flags = flags;
}
SkRect bounds = kUnset;
SkPaint paint;
sk_sp<const SkImageFilter> backdrop;
+ sk_sp<SkImage> clipMask;
+ SkMatrix clipMatrix;
SkCanvas::SaveLayerFlags flags;
void draw(SkCanvas* c, const SkMatrix&) const {
- c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), flags });
+ c->saveLayer({ maybe_unset(bounds), &paint, backdrop.get(), clipMask,
+ clipMatrix.isIdentity() ? nullptr : &clipMatrix, flags });
}
};
@@ -544,8 +550,9 @@ void SkLiteDL::setDrawFilter(SkDrawFilter* df) {
void SkLiteDL:: save() { this->push <Save>(0); }
void SkLiteDL::restore() { this->push<Restore>(0); }
void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint,
- const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
- this->push<SaveLayer>(0, bounds, paint, backdrop, flags);
+ const SkImageFilter* backdrop, sk_sp<SkImage> clipMask,
+ const SkMatrix* clipMatrix, SkCanvas::SaveLayerFlags flags) {
+ this->push<SaveLayer>(0, bounds, paint, backdrop, std::move(clipMask), clipMatrix, flags);
}
void SkLiteDL:: concat(const SkMatrix& matrix) { this->push <Concat>(0, matrix); }
diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h
index 1f344cd9e7..5219cd002c 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -29,7 +29,8 @@ public:
#endif
void save();
- void saveLayer(const SkRect*, const SkPaint*, const SkImageFilter*, SkCanvas::SaveLayerFlags);
+ void saveLayer(const SkRect*, const SkPaint*, const SkImageFilter*, sk_sp<SkImage>,
+ const SkMatrix*, SkCanvas::SaveLayerFlags);
void restore();
void concat (const SkMatrix&);
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
index f899f8822f..c58355bea3 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -31,7 +31,8 @@ SkDrawFilter* SkLiteRecorder::setDrawFilter(SkDrawFilter* df) {
void SkLiteRecorder::willSave() { fDL->save(); }
SkCanvas::SaveLayerStrategy SkLiteRecorder::getSaveLayerStrategy(const SaveLayerRec& rec) {
- fDL->saveLayer(rec.fBounds, rec.fPaint, rec.fBackdrop, rec.fSaveLayerFlags);
+ fDL->saveLayer(rec.fBounds, rec.fPaint, rec.fBackdrop, rec.fClipMask, rec.fClipMatrix,
+ rec.fSaveLayerFlags);
return SkCanvas::kNoLayer_SaveLayerStrategy;
}
void SkLiteRecorder::willRestore() { fDL->restore(); }
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index a1647468f5..745a7e3c48 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -122,6 +122,8 @@ enum SaveLayerRecFlatFlags {
SAVELAYERREC_HAS_PAINT = 1 << 1,
SAVELAYERREC_HAS_BACKDROP = 1 << 2,
SAVELAYERREC_HAS_FLAGS = 1 << 3,
+ SAVELAYERREC_HAS_CLIPMASK = 1 << 4,
+ SAVELAYERREC_HAS_CLIPMATRIX = 1 << 5,
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 51a3da9b0d..84228d0359 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -724,7 +724,8 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
} break;
case SAVE_LAYER_SAVELAYERREC: {
- SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
+ SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, nullptr, nullptr, 0);
+ SkMatrix clipMatrix;
const uint32_t flatFlags = reader->readInt();
SkRect bounds;
if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
@@ -742,6 +743,13 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
rec.fSaveLayerFlags = reader->readInt();
}
+ if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
+ rec.fClipMask = sk_ref_sp(const_cast<SkImage*>(fPictureData->getImage(reader)));
+ }
+ if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
+ reader->readMatrix(&clipMatrix);
+ rec.fClipMatrix = &clipMatrix;
+ }
BREAK_ON_READ_ERROR(reader);
canvas->saveLayer(rec);
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 9bdb6c5cc4..ea4273f582 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -98,6 +98,14 @@ void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
flatFlags |= SAVELAYERREC_HAS_FLAGS;
size += sizeof(uint32_t);
}
+ if (rec.fClipMask) {
+ flatFlags |= SAVELAYERREC_HAS_CLIPMASK;
+ size += sizeof(uint32_t); // clip image index
+ }
+ if (rec.fClipMatrix) {
+ flatFlags |= SAVELAYERREC_HAS_CLIPMATRIX;
+ size += rec.fClipMatrix->writeToMemory(nullptr);
+ }
const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
this->addInt(flatFlags);
@@ -116,6 +124,12 @@ void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
this->addInt(rec.fSaveLayerFlags);
}
+ if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
+ this->addImage(rec.fClipMask.get());
+ }
+ if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
+ this->addMatrix(*rec.fClipMatrix);
+ }
this->validate(initialOffset, size);
}
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 21f9de956b..02c8c69c8e 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -77,6 +77,8 @@ DRAW(Save, save());
DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds,
r.paint,
r.backdrop.get(),
+ r.clipMask,
+ r.clipMatrix,
r.saveLayerFlags)));
DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));
DRAW(Concat, concat(r.matrix));
diff --git a/src/core/SkRecordOpts.cpp b/src/core/SkRecordOpts.cpp
index 07ef19d5a5..8a1ac59368 100644
--- a/src/core/SkRecordOpts.cpp
+++ b/src/core/SkRecordOpts.cpp
@@ -188,8 +188,8 @@ struct SaveLayerDrawRestoreNooper {
typedef Pattern<Is<SaveLayer>, IsDraw, Is<Restore>> Match;
bool onMatch(SkRecord* record, Match* match, int begin, int end) {
- if (match->first<SaveLayer>()->backdrop) {
- // can't throw away the layer if we have a backdrop
+ if (match->first<SaveLayer>()->backdrop || match->first<SaveLayer>()->clipMask) {
+ // can't throw away the layer if we have a backdrop or clip mask
return false;
}
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 0f2891a825..c9d88fc503 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -366,6 +366,8 @@ SkCanvas::SaveLayerStrategy SkRecorder::getSaveLayerStrategy(const SaveLayerRec&
APPEND(SaveLayer, this->copy(rec.fBounds)
, this->copy(rec.fPaint)
, sk_ref_sp(rec.fBackdrop)
+ , rec.fClipMask
+ , this->copy(rec.fClipMatrix)
, rec.fSaveLayerFlags);
return SkCanvas::kNoLayer_SaveLayerStrategy;
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 2d3178c4af..19d9185119 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1125,17 +1125,18 @@ void SkGpuDevice::drawSprite(const SkBitmap& bitmap,
return;
}
- this->drawSpecial(srcImg.get(), left, top, paint);
+ this->drawSpecial(srcImg.get(), left, top, paint, nullptr, SkMatrix::I());
}
-void SkGpuDevice::drawSpecial(SkSpecialImage* special1,
- int left, int top,
- const SkPaint& paint) {
+void SkGpuDevice::drawSpecial(SkSpecialImage* special1, int left, int top, const SkPaint& paint,
+ SkImage* clipImage,const SkMatrix& clipMatrix) {
ASSERT_SINGLE_OWNER
CHECK_SHOULD_DRAW();
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSpecial", fContext.get());
+ // TODO: clipImage support.
+
SkIPoint offset = { 0, 0 };
sk_sp<SkSpecialImage> result;
@@ -1354,7 +1355,7 @@ void SkGpuDevice::drawDevice(SkBaseDevice* device,
return;
}
- this->drawSpecial(srcImg.get(), left, top, paint);
+ this->drawSpecial(srcImg.get(), left, top, paint, nullptr, SkMatrix::I());
}
void SkGpuDevice::drawImage(const SkImage* image, SkScalar x, SkScalar y,
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 4558c1b17a..340f39a072 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -110,8 +110,8 @@ public:
void drawBitmapLattice(const SkBitmap&, const SkCanvas::Lattice&,
const SkRect& dst, const SkPaint&) override;
- void drawSpecial(SkSpecialImage*,
- int left, int top, const SkPaint& paint) override;
+ void drawSpecial(SkSpecialImage*, int left, int top, const SkPaint& paint,
+ SkImage*, const SkMatrix&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
sk_sp<SkSpecialImage> snapSpecial() override;
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 768277a7b9..aa8f7ae23f 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -2202,10 +2202,12 @@ void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix,
#include "SkSpecialImage.h"
#include "SkImageFilter.h"
-void SkPDFDevice::drawSpecial(SkSpecialImage* srcImg, int x, int y,
- const SkPaint& paint) {
+void SkPDFDevice::drawSpecial(SkSpecialImage* srcImg, int x, int y, const SkPaint& paint,
+ SkImage* clipImage, const SkMatrix& clipMatrix) {
SkASSERT(!srcImg->isTextureBacked());
+ //TODO: clipImage support
+
SkBitmap resultBM;
SkImageFilter* filter = paint.getImageFilter();
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index 93eb78dc50..f4318e489d 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -170,7 +170,8 @@ protected:
void drawAnnotation(const SkRect&, const char key[], SkData* value) override;
- void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&) override;
+ void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
+ SkImage*, const SkMatrix&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
sk_sp<SkSpecialImage> snapSpecial() override;
diff --git a/src/pipe/SkPipeCanvas.cpp b/src/pipe/SkPipeCanvas.cpp
index 1473b843f6..91e74eeca5 100644
--- a/src/pipe/SkPipeCanvas.cpp
+++ b/src/pipe/SkPipeCanvas.cpp
@@ -240,6 +240,12 @@ SkCanvas::SaveLayerStrategy SkPipeCanvas::getSaveLayerStrategy(const SaveLayerRe
if (rec.fBackdrop) {
extra |= kHasBackdrop_SaveLayerMask;
}
+ if (rec.fClipMask) {
+ extra |= kHasClipMask_SaveLayerMask;
+ }
+ if (rec.fClipMatrix) {
+ extra |= kHasClipMatrix_SaveLayerMask;
+ }
writer.write32(pack_verb(SkPipeVerb::kSaveLayer, extra));
if (rec.fBounds) {
@@ -251,6 +257,13 @@ SkCanvas::SaveLayerStrategy SkPipeCanvas::getSaveLayerStrategy(const SaveLayerRe
if (rec.fBackdrop) {
writer.writeFlattenable(rec.fBackdrop);
}
+ if (rec.fClipMask) {
+ writer.writeImage(rec.fClipMask.get());
+ }
+ if (rec.fClipMatrix) {
+ writer.writeMatrix(*rec.fClipMatrix);
+ }
+
return kNoLayer_SaveLayerStrategy;
}
diff --git a/src/pipe/SkPipeFormat.h b/src/pipe/SkPipeFormat.h
index 9a1d30c7be..a6521279d0 100644
--- a/src/pipe/SkPipeFormat.h
+++ b/src/pipe/SkPipeFormat.h
@@ -107,6 +107,8 @@ enum {
kHasPaint_SaveLayerMask = 1 << 9,
kHasBackdrop_SaveLayerMask = 1 << 10,
kDontClipToLayer_SaveLayerMask = 1 << 11,
+ kHasClipMask_SaveLayerMask = 1 << 12,
+ kHasClipMatrix_SaveLayerMask = 1 << 13,
};
enum {
diff --git a/src/pipe/SkPipeReader.cpp b/src/pipe/SkPipeReader.cpp
index 974e6b005d..73ef970c1b 100644
--- a/src/pipe/SkPipeReader.cpp
+++ b/src/pipe/SkPipeReader.cpp
@@ -244,6 +244,14 @@ static void saveLayer_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanva
if (extra & kHasBackdrop_SaveLayerMask) {
backdrop = reader.readImageFilter();
}
+ sk_sp<SkImage> clipMask;
+ if (extra & kHasClipMask_SaveLayerMask) {
+ clipMask = reader.readImage();
+ }
+ SkMatrix clipMatrix;
+ if (extra & kHasClipMatrix_SaveLayerMask) {
+ reader.readMatrix(&clipMatrix);
+ }
SkCanvas::SaveLayerFlags flags = (SkCanvas::SaveLayerFlags)(extra & kFlags_SaveLayerMask);
// unremap this wacky flag
@@ -251,7 +259,8 @@ static void saveLayer_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanva
flags |= (1 << 31);//SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag;
}
- canvas->saveLayer(SkCanvas::SaveLayerRec(bounds, paint, backdrop.get(), flags));
+ canvas->saveLayer(SkCanvas::SaveLayerRec(bounds, paint, backdrop.get(), std::move(clipMask),
+ (extra & kHasClipMatrix_SaveLayerMask) ? &clipMatrix : nullptr, flags));
}
static void restore_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {