diff options
author | Florin Malita <fmalita@chromium.org> | 2017-04-28 13:48:37 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-05-01 14:07:10 +0000 |
commit | 53f77bd4fdd76525b66b7f26d1c5c550858120df (patch) | |
tree | d7516fa1c29a35a3e6b62aae82f3bb6e72928cf4 /src | |
parent | 57061eea444a8d85189827f014a451de63b49d1a (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.cpp | 73 | ||||
-rw-r--r-- | src/core/SkBitmapDevice.h | 3 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 39 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformCanvas.cpp | 3 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 3 | ||||
-rw-r--r-- | src/core/SkDevice.h | 3 | ||||
-rw-r--r-- | src/core/SkDraw.h | 3 | ||||
-rw-r--r-- | src/core/SkLiteDL.cpp | 15 | ||||
-rw-r--r-- | src/core/SkLiteDL.h | 3 | ||||
-rw-r--r-- | src/core/SkLiteRecorder.cpp | 3 | ||||
-rw-r--r-- | src/core/SkPictureFlat.h | 2 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 10 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 14 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 2 | ||||
-rw-r--r-- | src/core/SkRecordOpts.cpp | 4 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 2 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 11 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.h | 4 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 6 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.h | 3 | ||||
-rw-r--r-- | src/pipe/SkPipeCanvas.cpp | 13 | ||||
-rw-r--r-- | src/pipe/SkPipeFormat.h | 2 | ||||
-rw-r--r-- | src/pipe/SkPipeReader.cpp | 11 |
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) { |