add backdrop option to SaveLayerRec
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1523053003 Review URL: https://codereview.chromium.org/1523053003
This commit is contained in:
parent
5820fe846f
commit
247415969a
@ -104,3 +104,77 @@ DEF_SIMPLE_GM(fast_slow_blurimagefilter, canvas, 620, 260) {
|
||||
canvas->translate(r.width() + 20, 0);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "Resources.h"
|
||||
#include "SkBlurImageFilter.h"
|
||||
#include "SkMatrixConvolutionImageFilter.h"
|
||||
#include "SkMorphologyImageFilter.h"
|
||||
#include "SkColorMatrixFilter.h"
|
||||
#include "SkColorFilterImageFilter.h"
|
||||
#include "SkRRect.h"
|
||||
|
||||
static void draw_set(SkCanvas* canvas, SkImageFilter* filters[], int count) {
|
||||
const SkRect r = SkRect::MakeXYWH(30, 30, 200, 200);
|
||||
const SkScalar offset = 250;
|
||||
SkScalar dx = 0, dy = 0;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
canvas->save();
|
||||
SkRRect rr = SkRRect::MakeRectXY(r.makeOffset(dx, dy), 20, 20);
|
||||
canvas->clipRRect(rr, SkRegion::kIntersect_Op, true);
|
||||
canvas->saveLayer({ &rr.getBounds(), nullptr, filters[i], 0 });
|
||||
canvas->drawColor(0x40FFFFFF);
|
||||
canvas->restore();
|
||||
canvas->restore();
|
||||
|
||||
if (0 == dx) {
|
||||
dx = offset;
|
||||
} else {
|
||||
dx = 0;
|
||||
dy = offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(savelayer_with_backdrop, canvas, 830, 550) {
|
||||
SkColorMatrix cm;
|
||||
cm.setSaturation(10);
|
||||
SkAutoTUnref<SkColorFilter> cf(SkColorMatrixFilter::Create(cm));
|
||||
const SkScalar kernel[] = { 4, 0, 4, 0, -15, 0, 4, 0, 4 };
|
||||
SkImageFilter* filters[] = {
|
||||
SkBlurImageFilter::Create(10, 10),
|
||||
SkDilateImageFilter::Create(8, 8),
|
||||
SkMatrixConvolutionImageFilter::Create({ 3, 3 }, kernel, 1, 0, { 0, 0 },
|
||||
SkMatrixConvolutionImageFilter::kClampToBlack_TileMode,
|
||||
true),
|
||||
SkColorFilterImageFilter::Create(cf),
|
||||
};
|
||||
|
||||
const struct {
|
||||
SkScalar fSx, fSy, fTx, fTy;
|
||||
} xforms[] = {
|
||||
{ 1, 1, 0, 0 },
|
||||
{ 0.5f, 0.5f, 530, 0 },
|
||||
{ 0.25f, 0.25f, 530, 275 },
|
||||
{ 0.125f, 0.125f, 530, 420 },
|
||||
};
|
||||
|
||||
SkPaint paint;
|
||||
paint.setFilterQuality(kMedium_SkFilterQuality);
|
||||
SkAutoTUnref<SkImage> image(GetResourceAsImage("mandrill_512.png"));
|
||||
|
||||
canvas->translate(20, 20);
|
||||
for (const auto& xform : xforms) {
|
||||
canvas->save();
|
||||
canvas->translate(xform.fTx, xform.fTy);
|
||||
canvas->scale(xform.fSx, xform.fSy);
|
||||
canvas->drawImage(image, 0, 0, &paint);
|
||||
draw_set(canvas, filters, SK_ARRAY_COUNT(filters));
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
for (auto& filter : filters) {
|
||||
filter->unref();
|
||||
}
|
||||
}
|
||||
|
@ -422,16 +422,27 @@ public:
|
||||
typedef uint32_t SaveLayerFlags;
|
||||
|
||||
struct SaveLayerRec {
|
||||
SaveLayerRec() : fBounds(nullptr), fPaint(nullptr), fSaveLayerFlags(0) {}
|
||||
SaveLayerRec()
|
||||
: fBounds(nullptr), fPaint(nullptr), fBackdrop(nullptr), fSaveLayerFlags(0)
|
||||
{}
|
||||
SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
|
||||
: fBounds(bounds)
|
||||
, fPaint(paint)
|
||||
, fBackdrop(nullptr)
|
||||
, fSaveLayerFlags(saveLayerFlags)
|
||||
{}
|
||||
SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
|
||||
SaveLayerFlags saveLayerFlags)
|
||||
: fBounds(bounds)
|
||||
, fPaint(paint)
|
||||
, fBackdrop(backdrop)
|
||||
, fSaveLayerFlags(saveLayerFlags)
|
||||
{}
|
||||
|
||||
const SkRect* fBounds; // optional
|
||||
const SkPaint* fPaint; // optional
|
||||
SaveLayerFlags fSaveLayerFlags;
|
||||
const SkRect* fBounds; // optional
|
||||
const SkPaint* fPaint; // optional
|
||||
const SkImageFilter* fBackdrop; // optional
|
||||
SaveLayerFlags fSaveLayerFlags;
|
||||
};
|
||||
|
||||
int saveLayer(const SaveLayerRec&);
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkDrawable.h"
|
||||
#include "SkImageFilter.h"
|
||||
#include "SkMatrix.h"
|
||||
#include "SkPath.h"
|
||||
#include "SkPicture.h"
|
||||
@ -197,6 +198,7 @@ RECORD(Save, 0);
|
||||
RECORD(SaveLayer, 0,
|
||||
Optional<SkRect> bounds;
|
||||
Optional<SkPaint> paint;
|
||||
RefBox<const SkImageFilter> backdrop;
|
||||
SkCanvas::SaveLayerFlags saveLayerFlags);
|
||||
|
||||
RECORD(SetMatrix, 0,
|
||||
|
@ -1396,6 +1396,15 @@ void SampleWindow::afterChildren(SkCanvas* orig) {
|
||||
|
||||
if (fUseMPD) {
|
||||
SkAutoTUnref<const SkPicture> picture(fRecorder.endRecording());
|
||||
|
||||
if (false) {
|
||||
SkDynamicMemoryWStream wstream;
|
||||
picture->serialize(&wstream);
|
||||
|
||||
SkAutoTDelete<SkStream> rstream(wstream.detachAsStream());
|
||||
picture.reset(SkPicture::CreateFromStream(rstream));
|
||||
}
|
||||
|
||||
if (true) {
|
||||
if (true) {
|
||||
SkImageInfo info;
|
||||
|
@ -232,8 +232,80 @@ protected:
|
||||
private:
|
||||
typedef SkView INHERITED;
|
||||
};
|
||||
DEF_SAMPLE( return new LayersView; )
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static SkView* MyFactory() { return new LayersView; }
|
||||
static SkViewRegister reg(MyFactory);
|
||||
#include "SkBlurImageFilter.h"
|
||||
#include "SkMatrixConvolutionImageFilter.h"
|
||||
#include "SkMorphologyImageFilter.h"
|
||||
|
||||
#include "Resources.h"
|
||||
#include "SkAnimTimer.h"
|
||||
|
||||
class BackdropView : public SampleView {
|
||||
SkPoint fCenter;
|
||||
SkScalar fAngle;
|
||||
SkAutoTUnref<SkImage> fImage;
|
||||
SkAutoTUnref<SkImageFilter> fFilter;
|
||||
public:
|
||||
BackdropView() {
|
||||
fCenter.set(200, 150);
|
||||
fAngle = 0;
|
||||
fImage.reset(GetResourceAsImage("mandrill_512.png"));
|
||||
fFilter.reset(SkDilateImageFilter::Create(8, 8));
|
||||
}
|
||||
|
||||
protected:
|
||||
// overrides from SkEventSink
|
||||
bool onQuery(SkEvent* evt) override {
|
||||
if (SampleCode::TitleQ(*evt)) {
|
||||
SampleCode::TitleR(evt, "Backdrop");
|
||||
return true;
|
||||
}
|
||||
return this->INHERITED::onQuery(evt);
|
||||
}
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) override {
|
||||
canvas->drawImage(fImage, 0, 0, nullptr);
|
||||
|
||||
const SkScalar w = 250;
|
||||
const SkScalar h = 150;
|
||||
SkPath path;
|
||||
path.addOval(SkRect::MakeXYWH(-w/2, -h/2, w, h));
|
||||
SkMatrix m;
|
||||
m.setRotate(fAngle);
|
||||
m.postTranslate(fCenter.x(), fCenter.y());
|
||||
path.transform(m);
|
||||
|
||||
canvas->clipPath(path, SkRegion::kIntersect_Op, true);
|
||||
const SkRect bounds = path.getBounds();
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAlpha(0xCC);
|
||||
canvas->saveLayer({ &bounds, &paint, fFilter, 0 });
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
bool onAnimate(const SkAnimTimer& timer) override {
|
||||
fAngle = SkDoubleToScalar(fmod(timer.secs() * 360 / 5, 360));
|
||||
return true;
|
||||
}
|
||||
|
||||
SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
|
||||
this->inval(nullptr);
|
||||
return new Click(this);
|
||||
}
|
||||
|
||||
bool onClick(Click* click) override {
|
||||
this->inval(nullptr);
|
||||
fCenter = click->fCurr;
|
||||
return this->INHERITED::onClick(click);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef SampleView INHERITED;
|
||||
};
|
||||
DEF_SAMPLE( return new BackdropView; )
|
||||
|
||||
|
@ -114,7 +114,6 @@ bool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
|
||||
|
||||
// experimental for faster tiled drawing...
|
||||
//#define SK_ENABLE_CLIP_QUICKREJECT
|
||||
|
||||
//#define SK_TRACE_SAVERESTORE
|
||||
|
||||
#ifdef SK_TRACE_SAVERESTORE
|
||||
@ -481,7 +480,7 @@ public:
|
||||
// Make rawBounds include all paint outsets except for those due to image filters.
|
||||
rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage);
|
||||
}
|
||||
(void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp, 0),
|
||||
(void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp),
|
||||
SkCanvas::kFullLayer_SaveLayerStrategy);
|
||||
fTempLayerForImageFilter = true;
|
||||
// we remove the imagefilter/xfermode inside doNext()
|
||||
@ -1173,7 +1172,8 @@ int SkCanvas::saveLayer(const SaveLayerRec& origRec) {
|
||||
return this->getSaveCount() - 1;
|
||||
}
|
||||
|
||||
static void draw_filter_into_device(SkBaseDevice* src, SkImageFilter* filter, SkBaseDevice* dst) {
|
||||
static void draw_filter_into_device(SkBaseDevice* src, const SkImageFilter* filter,
|
||||
SkBaseDevice* dst, const SkMatrix& ctm) {
|
||||
|
||||
SkBitmap srcBM;
|
||||
|
||||
@ -1198,9 +1198,12 @@ static void draw_filter_into_device(SkBaseDevice* src, SkImageFilter* filter, Sk
|
||||
|
||||
SkCanvas c(dst);
|
||||
|
||||
SkAutoTUnref<SkImageFilter> localF(filter->newWithLocalMatrix(ctm));
|
||||
SkPaint p;
|
||||
p.setImageFilter(filter);
|
||||
c.drawBitmap(srcBM, 0, 0, &p);
|
||||
p.setImageFilter(localF);
|
||||
const SkScalar x = SkIntToScalar(src->getOrigin().x());
|
||||
const SkScalar y = SkIntToScalar(src->getOrigin().y());
|
||||
c.drawBitmap(srcBM, x, y, &p);
|
||||
}
|
||||
|
||||
void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
|
||||
@ -1268,11 +1271,10 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
|
||||
}
|
||||
device = newDev;
|
||||
}
|
||||
|
||||
device->setOrigin(ir.fLeft, ir.fTop);
|
||||
|
||||
if (0) {
|
||||
draw_filter_into_device(fMCRec->fTopLayer->fDevice, nullptr, device);
|
||||
if (rec.fBackdrop) {
|
||||
draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, device, fMCRec->fMatrix);
|
||||
}
|
||||
|
||||
DeviceCM* layer =
|
||||
|
@ -75,9 +75,10 @@ enum DrawType {
|
||||
DRAW_IMAGE_NINE,
|
||||
DRAW_IMAGE_RECT,
|
||||
|
||||
SAVE_LAYER_SAVELAYERFLAGS,
|
||||
SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016,
|
||||
SAVE_LAYER_SAVELAYERREC,
|
||||
|
||||
LAST_DRAWTYPE_ENUM = SAVE_LAYER_SAVELAYERFLAGS,
|
||||
LAST_DRAWTYPE_ENUM = SAVE_LAYER_SAVELAYERREC,
|
||||
};
|
||||
|
||||
// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
|
||||
@ -95,6 +96,13 @@ enum DrawAtlasFlags {
|
||||
DRAW_ATLAS_HAS_CULL = 1 << 1,
|
||||
};
|
||||
|
||||
enum SaveLayerRecFlatFlags {
|
||||
SAVELAYERREC_HAS_BOUNDS = 1 << 0,
|
||||
SAVELAYERREC_HAS_PAINT = 1 << 1,
|
||||
SAVELAYERREC_HAS_BACKDROP = 1 << 2,
|
||||
SAVELAYERREC_HAS_FLAGS = 1 << 3,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// clipparams are packed in 5 bits
|
||||
// doAA:1 | regionOp:4
|
||||
|
@ -483,11 +483,29 @@ void SkPicturePlayback::handleOp(SkReader32* reader,
|
||||
auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt());
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
|
||||
} break;
|
||||
case SAVE_LAYER_SAVELAYERFLAGS: {
|
||||
case SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016: {
|
||||
const SkRect* boundsPtr = get_rect_ptr(reader);
|
||||
const SkPaint* paint = fPictureData->getPaint(reader);
|
||||
canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, reader->readInt()));
|
||||
} break;
|
||||
case SAVE_LAYER_SAVELAYERREC: {
|
||||
SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
|
||||
const uint32_t flatFlags = reader->readInt();
|
||||
if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
|
||||
rec.fBounds = &reader->skipT<SkRect>();
|
||||
}
|
||||
if (flatFlags & SAVELAYERREC_HAS_PAINT) {
|
||||
rec.fPaint = fPictureData->getPaint(reader);
|
||||
}
|
||||
if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
|
||||
const SkPaint* paint = fPictureData->getPaint(reader);
|
||||
rec.fBackdrop = paint->getImageFilter();
|
||||
}
|
||||
if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
|
||||
rec.fSaveLayerFlags = reader->readInt();
|
||||
}
|
||||
canvas->saveLayer(rec);
|
||||
} break;
|
||||
case SCALE: {
|
||||
SkScalar sx = reader->readScalar();
|
||||
SkScalar sy = reader->readScalar();
|
||||
|
@ -76,19 +76,44 @@ SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLaye
|
||||
void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
|
||||
fContentInfo.onSaveLayer();
|
||||
|
||||
// op + bool for 'bounds'
|
||||
// op + flatflags
|
||||
size_t size = 2 * kUInt32Size;
|
||||
uint32_t flatFlags = 0;
|
||||
|
||||
if (rec.fBounds) {
|
||||
size += sizeof(*rec.fBounds); // + rect
|
||||
flatFlags |= SAVELAYERREC_HAS_BOUNDS;
|
||||
size += sizeof(*rec.fBounds);
|
||||
}
|
||||
if (rec.fPaint) {
|
||||
flatFlags |= SAVELAYERREC_HAS_PAINT;
|
||||
size += sizeof(uint32_t); // index
|
||||
}
|
||||
if (rec.fBackdrop) {
|
||||
flatFlags |= SAVELAYERREC_HAS_BACKDROP;
|
||||
size += sizeof(uint32_t); // (paint) index
|
||||
}
|
||||
if (rec.fSaveLayerFlags) {
|
||||
flatFlags |= SAVELAYERREC_HAS_FLAGS;
|
||||
size += sizeof(uint32_t);
|
||||
}
|
||||
// + paint index + flags
|
||||
size += 2 * kUInt32Size;
|
||||
|
||||
size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERFLAGS, &size);
|
||||
this->addRectPtr(rec.fBounds);
|
||||
this->addPaintPtr(rec.fPaint);
|
||||
this->addInt(rec.fSaveLayerFlags);
|
||||
|
||||
const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
|
||||
this->addInt(flatFlags);
|
||||
if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
|
||||
this->addRect(*rec.fBounds);
|
||||
}
|
||||
if (flatFlags & SAVELAYERREC_HAS_PAINT) {
|
||||
this->addPaintPtr(rec.fPaint);
|
||||
}
|
||||
if (flatFlags & SAVELAYERREC_HAS_BACKDROP) {
|
||||
// overkill, but we didn't already track single flattenables, so using a paint for that
|
||||
SkPaint paint;
|
||||
paint.setImageFilter(const_cast<SkImageFilter*>(rec.fBackdrop));
|
||||
this->addPaint(paint);
|
||||
}
|
||||
if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
|
||||
this->addInt(rec.fSaveLayerFlags);
|
||||
}
|
||||
this->validate(initialOffset, size);
|
||||
}
|
||||
|
||||
@ -224,7 +249,8 @@ void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t
|
||||
uint32_t opSize;
|
||||
DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize);
|
||||
SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp);
|
||||
SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERFLAGS == drawOp);
|
||||
SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp);
|
||||
SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ template <> void Draw::draw(const NoOp&) {}
|
||||
#define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; }
|
||||
DRAW(Restore, restore());
|
||||
DRAW(Save, save());
|
||||
DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds, r.paint, r.saveLayerFlags)));
|
||||
DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds, r.paint, r.backdrop, r.saveLayerFlags)));
|
||||
DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));
|
||||
DRAW(Concat, concat(r.matrix));
|
||||
|
||||
|
@ -337,7 +337,8 @@ void SkRecorder::willSave() {
|
||||
}
|
||||
|
||||
SkCanvas::SaveLayerStrategy SkRecorder::getSaveLayerStrategy(const SaveLayerRec& rec) {
|
||||
APPEND(SaveLayer, this->copy(rec.fBounds), this->copy(rec.fPaint), rec.fSaveLayerFlags);
|
||||
APPEND(SaveLayer,
|
||||
this->copy(rec.fBounds), this->copy(rec.fPaint), rec.fBackdrop, rec.fSaveLayerFlags);
|
||||
return SkCanvas::kNoLayer_SaveLayerStrategy;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user