| Index: dm/DMSrcSink.cpp
|
| diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
|
| index c5e039532bee06ea94b117a11f27096262fb80e0..4a3808ace56b7fda7733cf8cf8886a2f91ec7d90 100644
|
| --- a/dm/DMSrcSink.cpp
|
| +++ b/dm/DMSrcSink.cpp
|
| @@ -20,6 +20,8 @@
|
| #include "SkPictureData.h"
|
| #include "SkPictureRecorder.h"
|
| #include "SkRandom.h"
|
| +#include "SkRecordDraw.h"
|
| +#include "SkRecorder.h"
|
| #include "SkSVGCanvas.h"
|
| #include "SkScanlineDecoder.h"
|
| #include "SkStream.h"
|
| @@ -724,4 +726,69 @@ Error ViaSecondPicture::draw(
|
| });
|
| }
|
|
|
| +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
| +
|
| +// This is like SkRecords::Draw, in that it plays back SkRecords ops into a Canvas.
|
| +// Unlike SkRecords::Draw, it builds a single-op sub-picture out of each Draw-type op.
|
| +// This is an only-slightly-exaggerated simluation of Blink's Slimming Paint pictures.
|
| +struct DrawsAsSingletonPictures {
|
| + SkCanvas* fCanvas;
|
| +
|
| + SK_CREATE_MEMBER_DETECTOR(paint);
|
| +
|
| + template <typename T>
|
| + void draw(const T& op, SkCanvas* canvas) {
|
| + // We must pass SkMatrix::I() as our initial matrix.
|
| + // By default SkRecords::Draw() uses the canvas' matrix as its initial matrix,
|
| + // which would have the funky effect of applying transforms over and over.
|
| + SkRecords::Draw(canvas, nullptr, nullptr, 0, &SkMatrix::I())(op);
|
| + }
|
| +
|
| + // Most things that have paints are Draw-type ops. Create sub-pictures for each.
|
| + template <typename T>
|
| + SK_WHEN(HasMember_paint<T>, void) operator()(const T& op) {
|
| + SkPictureRecorder rec;
|
| + this->draw(op, rec.beginRecording(SkRect::MakeLargest()));
|
| + SkAutoTUnref<SkPicture> pic(rec.endRecordingAsPicture());
|
| + fCanvas->drawPicture(pic);
|
| + }
|
| +
|
| + // If you don't have a paint or are a SaveLayer, you're not a Draw-type op.
|
| + // We cannot make subpictures out of these because they affect state. Draw them directly.
|
| + template <typename T>
|
| + SK_WHEN(!HasMember_paint<T>, void) operator()(const T& op) { this->draw(op, fCanvas); }
|
| + void operator()(const SkRecords::SaveLayer& op) { this->draw(op, fCanvas); }
|
| +};
|
| +
|
| +ViaSingletonPictures::ViaSingletonPictures(Sink* sink) : fSink(sink) {}
|
| +
|
| +// Record Src into a picture, then record it into a macro picture with a sub-picture for each draw.
|
| +// Then play back that macro picture into our wrapped sink.
|
| +Error ViaSingletonPictures::draw(
|
| + const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
|
| + auto size = src.size();
|
| + return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
|
| + // Use low-level (Skia-private) recording APIs so we can read the SkRecord.
|
| + SkRecord skr;
|
| + SkRecorder recorder(&skr, size.width(), size.height());
|
| + Error err = src.draw(&recorder);
|
| + if (!err.isEmpty()) {
|
| + return err;
|
| + }
|
| +
|
| + // Record our macro-picture, with each draw op as its own sub-picture.
|
| + SkPictureRecorder macroRec;
|
| + SkCanvas* macroCanvas = macroRec.beginRecording(SkIntToScalar(size.width()),
|
| + SkIntToScalar(size.height()));
|
| + DrawsAsSingletonPictures drawsAsSingletonPictures = { macroCanvas };
|
| + for (unsigned i = 0; i < skr.count(); i++) {
|
| + skr.visit<void>(i, drawsAsSingletonPictures);
|
| + }
|
| + SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture());
|
| +
|
| + canvas->drawPicture(macroPic);
|
| + return "";
|
| + });
|
| +}
|
| +
|
| } // namespace DM
|
|
|