| Index: dm/DMSrcSink.cpp
|
| diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
|
| index b33ba14b66dc2b97fb2abbbdecb478c401e551e8..c5e039532bee06ea94b117a11f27096262fb80e0 100644
|
| --- a/dm/DMSrcSink.cpp
|
| +++ b/dm/DMSrcSink.cpp
|
| @@ -7,8 +7,8 @@
|
|
|
| #include "DMSrcSink.h"
|
| #include "SamplePipeControllers.h"
|
| -#include "SkCommonFlags.h"
|
| #include "SkCodec.h"
|
| +#include "SkCommonFlags.h"
|
| #include "SkData.h"
|
| #include "SkDeferredCanvas.h"
|
| #include "SkDocument.h"
|
| @@ -20,8 +20,8 @@
|
| #include "SkPictureData.h"
|
| #include "SkPictureRecorder.h"
|
| #include "SkRandom.h"
|
| -#include "SkScanlineDecoder.h"
|
| #include "SkSVGCanvas.h"
|
| +#include "SkScanlineDecoder.h"
|
| #include "SkStream.h"
|
| #include "SkXMLWriter.h"
|
|
|
| @@ -502,6 +502,28 @@ Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) con
|
|
|
| /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
| +// Handy for front-patching a Src. Do whatever up-front work you need, then call draw_to_canvas(),
|
| +// passing the Sink draw() arguments, a size, and a lambda that takes SkCanvas* and returns Error.
|
| +// Several examples below.
|
| +
|
| +template <typename DrawFn>
|
| +static Error draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, SkString* log,
|
| + SkISize size, DrawFn draw) {
|
| + class ProxySrc : public Src {
|
| + public:
|
| + ProxySrc(SkISize size, DrawFn draw) : fSize(size), fDraw(draw) {}
|
| + Error draw(SkCanvas* canvas) const override { return fDraw(canvas); }
|
| + Name name() const override { sk_throw(); return ""; } // Won't be called.
|
| + SkISize size() const override { return fSize; }
|
| + private:
|
| + SkISize fSize;
|
| + DrawFn fDraw;
|
| + };
|
| + return sink->draw(ProxySrc(size, draw), bitmap, stream, log);
|
| +}
|
| +
|
| +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
| +
|
| static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
|
| SkRect bounds = SkRect::MakeIWH(srcW, srcH);
|
| matrix->mapRect(&bounds);
|
| @@ -512,24 +534,12 @@ static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
|
| ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
|
|
|
| Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
|
| - // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
|
| - struct ProxySrc : public Src {
|
| - const Src& fSrc;
|
| - SkMatrix fMatrix;
|
| - SkISize fSize;
|
| -
|
| - ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {
|
| - fSize = auto_compute_translate(&fMatrix, src.size().width(), src.size().height());
|
| - }
|
| -
|
| - Error draw(SkCanvas* canvas) const override {
|
| - canvas->concat(fMatrix);
|
| - return fSrc.draw(canvas);
|
| - }
|
| - SkISize size() const override { return fSize; }
|
| - Name name() const override { sk_throw(); return ""; } // No one should be calling this.
|
| - } proxy(src, fMatrix);
|
| - return fSink->draw(proxy, bitmap, stream, log);
|
| + SkMatrix matrix = fMatrix;
|
| + SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
|
| + return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
|
| + canvas->concat(matrix);
|
| + return src.draw(canvas);
|
| + });
|
| }
|
|
|
| // Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
|
| @@ -572,70 +582,52 @@ Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkSt
|
| ViaPipe::ViaPipe(Sink* sink) : fSink(sink) {}
|
|
|
| Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
|
| - // We turn ourselves into another Src that draws our argument into bitmap/stream via pipe.
|
| - struct ProxySrc : public Src {
|
| - const Src& fSrc;
|
| - ProxySrc(const Src& src) : fSrc(src) {}
|
| -
|
| - Error draw(SkCanvas* canvas) const override {
|
| - SkISize size = this->size();
|
| - PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
|
| - SkGPipeWriter pipe;
|
| - const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
|
| - return fSrc.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
|
| - }
|
| - SkISize size() const override { return fSrc.size(); }
|
| - Name name() const override { sk_throw(); return ""; } // No one should be calling this.
|
| - } proxy(src);
|
| - return fSink->draw(proxy, bitmap, stream, log);
|
| + auto size = src.size();
|
| + return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
|
| + PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
|
| + SkGPipeWriter pipe;
|
| + const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
|
| + return src.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
|
| + });
|
| }
|
|
|
| /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
| -
|
| +
|
| ViaDeferred::ViaDeferred(Sink* sink) : fSink(sink) {}
|
|
|
| Error ViaDeferred::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
|
| - // We turn ourselves into another Src that draws our argument into a deferred canvas,
|
| - // via a surface created by the original canvas. We then draw a snapped image from that
|
| - // surface back into the original canvas.
|
| - struct ProxySrc : public Src {
|
| - const Src& fSrc;
|
| - ProxySrc(const Src& src) : fSrc(src) {}
|
| -
|
| - Error draw(SkCanvas* canvas) const override {
|
| - SkAutoTUnref<SkSurface> surface(canvas->newSurface(canvas->imageInfo()));
|
| - if (!surface.get()) {
|
| - return "can't make surface for deferred canvas";
|
| - }
|
| - SkAutoTDelete<SkDeferredCanvas> defcan(SkDeferredCanvas::Create(surface));
|
| - Error err = fSrc.draw(defcan);
|
| - if (!err.isEmpty()) {
|
| - return err;
|
| - }
|
| - SkAutoTUnref<SkImage> image(defcan->newImageSnapshot());
|
| - if (!image) {
|
| - return "failed to create deferred image snapshot";
|
| - }
|
| - canvas->drawImage(image, 0, 0, NULL);
|
| - return "";
|
| + // We draw via a deferred canvas into a surface that's compatible with the original canvas,
|
| + // then snap that surface as an image and draw it into the original canvas.
|
| + return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error {
|
| + SkAutoTUnref<SkSurface> surface(canvas->newSurface(canvas->imageInfo()));
|
| + if (!surface.get()) {
|
| + return "can't make surface for deferred canvas";
|
| + }
|
| + SkAutoTDelete<SkDeferredCanvas> defcan(SkDeferredCanvas::Create(surface));
|
| + Error err = src.draw(defcan);
|
| + if (!err.isEmpty()) {
|
| + return err;
|
| + }
|
| + SkAutoTUnref<SkImage> image(defcan->newImageSnapshot());
|
| + if (!image) {
|
| + return "failed to create deferred image snapshot";
|
| }
|
| - SkISize size() const override { return fSrc.size(); }
|
| - Name name() const override { sk_throw(); return ""; } // No one should be calling this.
|
| - } proxy(src);
|
| - return fSink->draw(proxy, bitmap, stream, log);
|
| + canvas->drawImage(image, 0, 0, NULL);
|
| + return "";
|
| + });
|
| }
|
| -
|
| +
|
| /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
| ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
|
|
|
| -Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log)
|
| - const {
|
| +Error ViaSerialization::draw(
|
| + const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
|
| // Record our Src into a picture.
|
| - SkSize size;
|
| - size = src.size();
|
| + auto size = src.size();
|
| SkPictureRecorder recorder;
|
| - Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
|
| + Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
|
| + SkIntToScalar(size.height())));
|
| if (!err.isEmpty()) {
|
| return err;
|
| }
|
| @@ -647,20 +639,10 @@ Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream
|
| SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
|
| SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream, &lazy_decode_bitmap));
|
|
|
| - // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
|
| - struct ProxySrc : public Src {
|
| - const SkPicture* fPic;
|
| - const SkISize fSize;
|
| - ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
|
| -
|
| - Error draw(SkCanvas* canvas) const override {
|
| - canvas->drawPicture(fPic);
|
| - return "";
|
| - }
|
| - SkISize size() const override { return fSize; }
|
| - Name name() const override { sk_throw(); return ""; } // No one should be calling this.
|
| - } proxy(deserialized, src.size());
|
| - return fSink->draw(proxy, bitmap, stream, log);
|
| + return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
|
| + canvas->drawPicture(deserialized);
|
| + return "";
|
| + });
|
| }
|
|
|
| /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
| @@ -672,61 +654,49 @@ ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
|
| , fSink(sink) {}
|
|
|
| Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
|
| - // Record our Src into a picture.
|
| - SkSize size;
|
| - size = src.size();
|
| + auto size = src.size();
|
| SkPictureRecorder recorder;
|
| - Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
|
| + Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
|
| + SkIntToScalar(size.height()),
|
| + fFactory.get()));
|
| if (!err.isEmpty()) {
|
| return err;
|
| }
|
| SkAutoTUnref<SkPicture> pic(recorder.endRecordingAsPicture());
|
|
|
| - // Turn that picture into a Src that draws into our Sink via tiles + MPD.
|
| - struct ProxySrc : public Src {
|
| - const int fW, fH;
|
| - const SkPicture* fPic;
|
| - const SkISize fSize;
|
| - ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
|
| - : fW(w), fH(h), fPic(pic), fSize(size) {}
|
| -
|
| - Error draw(SkCanvas* canvas) const override {
|
| - const int xTiles = (fSize.width() + fW - 1) / fW,
|
| - yTiles = (fSize.height() + fH - 1) / fH;
|
| - SkMultiPictureDraw mpd(xTiles*yTiles);
|
| - SkTDArray<SkSurface*> surfaces;
|
| - surfaces.setReserve(xTiles*yTiles);
|
| -
|
| - SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
|
| - for (int j = 0; j < yTiles; j++) {
|
| - for (int i = 0; i < xTiles; i++) {
|
| - // This lets our ultimate Sink determine the best kind of surface.
|
| - // E.g., if it's a GpuSink, the surfaces and images are textures.
|
| - SkSurface* s = canvas->newSurface(info);
|
| - if (!s) {
|
| - s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
|
| - }
|
| - surfaces.push(s);
|
| - SkCanvas* c = s->getCanvas();
|
| - c->translate(SkIntToScalar(-i * fW),
|
| - SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
|
| - mpd.add(c, fPic);
|
| + return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) {
|
| + const int xTiles = (size.width() + fW - 1) / fW,
|
| + yTiles = (size.height() + fH - 1) / fH;
|
| + SkMultiPictureDraw mpd(xTiles*yTiles);
|
| + SkTDArray<SkSurface*> surfaces;
|
| + surfaces.setReserve(xTiles*yTiles);
|
| +
|
| + SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
|
| + for (int j = 0; j < yTiles; j++) {
|
| + for (int i = 0; i < xTiles; i++) {
|
| + // This lets our ultimate Sink determine the best kind of surface.
|
| + // E.g., if it's a GpuSink, the surfaces and images are textures.
|
| + SkSurface* s = canvas->newSurface(info);
|
| + if (!s) {
|
| + s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
|
| }
|
| + surfaces.push(s);
|
| + SkCanvas* c = s->getCanvas();
|
| + c->translate(SkIntToScalar(-i * fW),
|
| + SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
|
| + mpd.add(c, pic);
|
| }
|
| - mpd.draw();
|
| - for (int j = 0; j < yTiles; j++) {
|
| - for (int i = 0; i < xTiles; i++) {
|
| - SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
|
| - canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
|
| - }
|
| + }
|
| + mpd.draw();
|
| + for (int j = 0; j < yTiles; j++) {
|
| + for (int i = 0; i < xTiles; i++) {
|
| + SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
|
| + canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
|
| }
|
| - surfaces.unrefAll();
|
| - return "";
|
| }
|
| - SkISize size() const override { return fSize; }
|
| - Name name() const override { sk_throw(); return ""; } // No one should be calling this.
|
| - } proxy(fW, fH, pic, src.size());
|
| - return fSink->draw(proxy, bitmap, stream, log);
|
| + surfaces.unrefAll();
|
| + return "";
|
| + });
|
| }
|
|
|
| /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
| @@ -737,29 +707,21 @@ ViaSecondPicture::ViaSecondPicture(Sink* sink) : fSink(sink) {}
|
| // This tests that any shortcuts we may take while recording that second picture are legal.
|
| Error ViaSecondPicture::draw(
|
| const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
|
| - struct ProxySrc : public Src {
|
| - const Src& fSrc;
|
| - ProxySrc(const Src& src) : fSrc(src) {}
|
| -
|
| - Error draw(SkCanvas* canvas) const override {
|
| - SkSize size;
|
| - size = fSrc.size();
|
| - SkPictureRecorder recorder;
|
| - SkAutoTUnref<SkPicture> pic;
|
| - for (int i = 0; i < 2; i++) {
|
| - Error err = fSrc.draw(recorder.beginRecording(size.width(), size.height()));
|
| - if (!err.isEmpty()) {
|
| - return err;
|
| - }
|
| - pic.reset(recorder.endRecordingAsPicture());
|
| + auto size = src.size();
|
| + return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
|
| + SkPictureRecorder recorder;
|
| + SkAutoTUnref<SkPicture> pic;
|
| + for (int i = 0; i < 2; i++) {
|
| + Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
|
| + SkIntToScalar(size.height())));
|
| + if (!err.isEmpty()) {
|
| + return err;
|
| }
|
| - canvas->drawPicture(pic);
|
| - return "";
|
| + pic.reset(recorder.endRecordingAsPicture());
|
| }
|
| - SkISize size() const override { return fSrc.size(); }
|
| - Name name() const override { sk_throw(); return ""; } // No one should be calling this.
|
| - } proxy(src);
|
| - return fSink->draw(proxy, bitmap, stream, log);
|
| + canvas->drawPicture(pic);
|
| + return "";
|
| + });
|
| }
|
|
|
| } // namespace DM
|
|
|