1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "DMSrcSink.h"
9#include "SamplePipeControllers.h"
10#include "SkCodec.h"
11#include "SkCommonFlags.h"
12#include "SkData.h"
13#include "SkDeferredCanvas.h"
14#include "SkDocument.h"
15#include "SkError.h"
16#include "SkFunction.h"
17#include "SkImageGenerator.h"
18#include "SkMultiPictureDraw.h"
19#include "SkNullCanvas.h"
20#include "SkOSFile.h"
21#include "SkPictureData.h"
22#include "SkPictureRecorder.h"
23#include "SkRandom.h"
24#include "SkRecordDraw.h"
25#include "SkRecorder.h"
26#include "SkSVGCanvas.h"
27#include "SkScanlineDecoder.h"
28#include "SkStream.h"
29#include "SkXMLWriter.h"
30
31DEFINE_bool(multiPage, false, "For document-type backends, render the source"
32            " into multiple pages");
33
34static bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) {
35    SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size));
36    return encoded && SkInstallDiscardablePixelRef(encoded, dst);
37}
38
39namespace DM {
40
41GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
42
43Error GMSrc::draw(SkCanvas* canvas) const {
44    SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
45    canvas->concat(gm->getInitialTransform());
46    gm->draw(canvas);
47    return "";
48}
49
50SkISize GMSrc::size() const {
51    SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
52    return gm->getISize();
53}
54
55Name GMSrc::name() const {
56    SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
57    return gm->getName();
58}
59
60/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
61
62CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType)
63    : fPath(path)
64    , fMode(mode)
65    , fDstColorType(dstColorType)
66{}
67
68Error CodecSrc::draw(SkCanvas* canvas) const {
69    SkImageInfo canvasInfo;
70    if (NULL == canvas->peekPixels(&canvasInfo, NULL)) {
71        // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferred decode to
72        // let the GPU handle it.
73        return Error::Nonfatal("No need to test decoding to non-raster backend.");
74    }
75
76    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
77    if (!encoded) {
78        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
79    }
80    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
81    if (NULL == codec.get()) {
82        return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
83    }
84
85    // Choose the color type to decode to
86    SkImageInfo decodeInfo = codec->getInfo();
87    SkColorType canvasColorType = canvasInfo.colorType();
88    switch (fDstColorType) {
89        case kIndex8_Always_DstColorType:
90            decodeInfo = codec->getInfo().makeColorType(kIndex_8_SkColorType);
91            if (kRGB_565_SkColorType == canvasColorType) {
92                return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
93            }
94            break;
95        case kGrayscale_Always_DstColorType:
96            decodeInfo = codec->getInfo().makeColorType(kGray_8_SkColorType);
97            if (kRGB_565_SkColorType == canvasColorType) {
98                return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
99            }
100            break;
101        default:
102            decodeInfo = decodeInfo.makeColorType(canvasColorType);
103            break;
104    }
105
106    // Construct a color table for the decode if necessary
107    SkAutoTUnref<SkColorTable> colorTable(NULL);
108    SkPMColor* colorPtr = NULL;
109    int* colorCountPtr = NULL;
110    int maxColors = 256;
111    if (kIndex_8_SkColorType == decodeInfo.colorType()) {
112        SkPMColor colors[256];
113        colorTable.reset(SkNEW_ARGS(SkColorTable, (colors, maxColors)));
114        colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
115        colorCountPtr = &maxColors;
116    }
117
118    // FIXME: Currently we cannot draw unpremultiplied sources.
119    if (decodeInfo.alphaType() == kUnpremul_SkAlphaType) {
120        decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType);
121    }
122
123    SkBitmap bitmap;
124    if (!bitmap.tryAllocPixels(decodeInfo, NULL, colorTable.get())) {
125        return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(),
126                              decodeInfo.width(), decodeInfo.height());
127    }
128
129    switch (fMode) {
130        case kNormal_Mode:
131            switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), NULL,
132                    colorPtr, colorCountPtr)) {
133                case SkImageGenerator::kSuccess:
134                    // We consider incomplete to be valid, since we should still decode what is
135                    // available.
136                case SkImageGenerator::kIncompleteInput:
137                    break;
138                case SkImageGenerator::kInvalidConversion:
139                    return Error::Nonfatal("Incompatible colortype conversion");
140                default:
141                    // Everything else is considered a failure.
142                    return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
143            }
144            break;
145        case kScanline_Mode: {
146            SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecoder(decodeInfo, NULL,
147                    colorPtr, colorCountPtr);
148            if (NULL == scanlineDecoder) {
149                return Error::Nonfatal("Cannot use scanline decoder for all images");
150            }
151            for (int y = 0; y < decodeInfo.height(); ++y) {
152                const SkImageGenerator::Result result = scanlineDecoder->getScanlines(
153                        bitmap.getAddr(0, y), 1, 0);
154                switch (result) {
155                    case SkImageGenerator::kSuccess:
156                    case SkImageGenerator::kIncompleteInput:
157                        break;
158                    default:
159                        return SkStringPrintf("%s failed after %d scanlines with error message %d",
160                                              fPath.c_str(), y-1, (int) result);
161                }
162            }
163            break;
164        }
165    }
166    canvas->drawBitmap(bitmap, 0, 0);
167    return "";
168}
169
170SkISize CodecSrc::size() const {
171    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
172    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
173    if (NULL != codec) {
174        return codec->getInfo().dimensions();
175    } else {
176        return SkISize::Make(0, 0);
177    }
178}
179
180Name CodecSrc::name() const {
181    return SkOSPath::Basename(fPath.c_str());
182}
183
184/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
185
186ImageSrc::ImageSrc(Path path, int divisor) : fPath(path), fDivisor(divisor) {}
187
188Error ImageSrc::draw(SkCanvas* canvas) const {
189    SkImageInfo canvasInfo;
190    if (NULL == canvas->peekPixels(&canvasInfo, NULL)) {
191        // TODO: Instead, use lazy decoding to allow the GPU to handle cases like YUV.
192        return Error::Nonfatal("No need to test decoding to non-raster backend.");
193    }
194
195    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
196    if (!encoded) {
197        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
198    }
199    const SkColorType dstColorType = canvasInfo.colorType();
200    if (fDivisor == 0) {
201        // Decode the full image.
202        SkBitmap bitmap;
203        if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap,
204                                          dstColorType, SkImageDecoder::kDecodePixels_Mode)) {
205            return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
206        }
207        if (kRGB_565_SkColorType == dstColorType && !bitmap.isOpaque()) {
208            // Do not draw a bitmap with alpha to a destination without alpha.
209            return Error::Nonfatal("Uninteresting to decode image with alpha into 565.");
210        }
211        encoded.reset((SkData*)NULL);  // Might as well drop this when we're done with it.
212        canvas->drawBitmap(bitmap, 0,0);
213        return "";
214    }
215    // Decode subsets.  This is a little involved.
216    SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
217    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream.get()));
218    if (!decoder) {
219        return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str());
220    }
221    stream->rewind();
222    int w,h;
223    if (!decoder->buildTileIndex(stream.detach(), &w, &h) || w*h == 1) {
224        return Error::Nonfatal("Subset decoding not supported.");
225    }
226
227    // Divide the image into subsets that cover the entire image.
228    if (fDivisor > w || fDivisor > h) {
229        return SkStringPrintf("divisor %d is too big for %s with dimensions (%d x %d)",
230                              fDivisor, fPath.c_str(), w, h);
231    }
232    const int subsetWidth  = w / fDivisor,
233              subsetHeight = h / fDivisor;
234    for (int y = 0; y < h; y += subsetHeight) {
235        for (int x = 0; x < w; x += subsetWidth) {
236            SkBitmap subset;
237            SkIRect rect = SkIRect::MakeXYWH(x, y, subsetWidth, subsetHeight);
238            if (!decoder->decodeSubset(&subset, rect, dstColorType)) {
239                return SkStringPrintf("Could not decode subset (%d, %d, %d, %d).",
240                                      x, y, x+subsetWidth, y+subsetHeight);
241            }
242            if (kRGB_565_SkColorType == dstColorType && !subset.isOpaque()) {
243                // Do not draw a bitmap with alpha to a destination without alpha.
244                // This is not an error, but there is nothing interesting to show.
245
246                // This should only happen on the first iteration through the loop.
247                SkASSERT(0 == x && 0 == y);
248
249                return Error::Nonfatal("Uninteresting to decode image with alpha into 565.");
250            }
251            canvas->drawBitmap(subset, SkIntToScalar(x), SkIntToScalar(y));
252        }
253    }
254    return "";
255}
256
257SkISize ImageSrc::size() const {
258    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
259    SkBitmap bitmap;
260    if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
261                                                  encoded->size(),
262                                                  &bitmap,
263                                                  kUnknown_SkColorType,
264                                                  SkImageDecoder::kDecodeBounds_Mode)) {
265        return SkISize::Make(0,0);
266    }
267    return bitmap.dimensions();
268}
269
270Name ImageSrc::name() const {
271    return SkOSPath::Basename(fPath.c_str());
272}
273
274/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
275
276static const SkRect kSKPViewport = {0,0, 1000,1000};
277
278SKPSrc::SKPSrc(Path path) : fPath(path) {}
279
280Error SKPSrc::draw(SkCanvas* canvas) const {
281    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
282    if (!stream) {
283        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
284    }
285    SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream, &lazy_decode_bitmap));
286    if (!pic) {
287        return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
288    }
289    stream.reset((SkStream*)NULL);  // Might as well drop this when we're done with it.
290
291    canvas->clipRect(kSKPViewport);
292    canvas->drawPicture(pic);
293    return "";
294}
295
296SkISize SKPSrc::size() const {
297    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
298    if (!stream) {
299        return SkISize::Make(0,0);
300    }
301    SkPictInfo info;
302    if (!SkPicture::InternalOnly_StreamIsSKP(stream, &info)) {
303        return SkISize::Make(0,0);
304    }
305    SkRect viewport = kSKPViewport;
306    if (!viewport.intersect(info.fCullRect)) {
307        return SkISize::Make(0,0);
308    }
309    return viewport.roundOut().size();
310}
311
312Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
313
314/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
315
316Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
317    SkAutoTDelete<SkCanvas> canvas(SkCreateNullCanvas());
318    return src.draw(canvas);
319}
320
321/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
322
323DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
324
325GPUSink::GPUSink(GrContextFactory::GLContextType ct,
326                 GrGLStandard api,
327                 int samples,
328                 bool dfText,
329                 bool threaded)
330    : fContextType(ct)
331    , fGpuAPI(api)
332    , fSampleCount(samples)
333    , fUseDFText(dfText)
334    , fThreaded(threaded) {}
335
336int GPUSink::enclave() const {
337    return fThreaded ? kAnyThread_Enclave : kGPU_Enclave;
338}
339
340void PreAbandonGpuContextErrorHandler(SkError, void*) {}
341
342Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
343    GrContextFactory factory;
344    const SkISize size = src.size();
345    const SkImageInfo info =
346        SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
347    SkAutoTUnref<SkSurface> surface(
348            NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
349    if (!surface) {
350        return "Could not create a surface.";
351    }
352    if (FLAGS_preAbandonGpuContext) {
353        SkSetErrorCallback(&PreAbandonGpuContextErrorHandler, NULL);
354        factory.abandonContexts();
355    }
356    SkCanvas* canvas = surface->getCanvas();
357    Error err = src.draw(canvas);
358    if (!err.isEmpty()) {
359        return err;
360    }
361    canvas->flush();
362    if (FLAGS_gpuStats) {
363        canvas->getGrContext()->dumpCacheStats(log);
364        canvas->getGrContext()->dumpGpuStats(log);
365    }
366    dst->allocPixels(info);
367    canvas->readPixels(dst, 0, 0);
368    if (FLAGS_abandonGpuContext) {
369        factory.abandonContexts();
370    }
371    return "";
372}
373
374/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
375
376static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
377    // Print the given DM:Src to a document, breaking on 8.5x11 pages.
378    SkASSERT(doc);
379    int width  = src.size().width(),
380        height = src.size().height();
381
382    if (FLAGS_multiPage) {
383        const int kLetterWidth = 612,  // 8.5 * 72
384                kLetterHeight = 792;   // 11 * 72
385        const SkRect letter = SkRect::MakeWH(SkIntToScalar(kLetterWidth),
386                                             SkIntToScalar(kLetterHeight));
387
388        int xPages = ((width - 1) / kLetterWidth) + 1;
389        int yPages = ((height - 1) / kLetterHeight) + 1;
390
391        for (int y = 0; y < yPages; ++y) {
392            for (int x = 0; x < xPages; ++x) {
393                int w = SkTMin(kLetterWidth, width - (x * kLetterWidth));
394                int h = SkTMin(kLetterHeight, height - (y * kLetterHeight));
395                SkCanvas* canvas =
396                        doc->beginPage(SkIntToScalar(w), SkIntToScalar(h));
397                if (!canvas) {
398                    return "SkDocument::beginPage(w,h) returned NULL";
399                }
400                canvas->clipRect(letter);
401                canvas->translate(-letter.width() * x, -letter.height() * y);
402                Error err = src.draw(canvas);
403                if (!err.isEmpty()) {
404                    return err;
405                }
406                doc->endPage();
407            }
408        }
409    } else {
410        SkCanvas* canvas =
411                doc->beginPage(SkIntToScalar(width), SkIntToScalar(height));
412        if (!canvas) {
413            return "SkDocument::beginPage(w,h) returned NULL";
414        }
415        Error err = src.draw(canvas);
416        if (!err.isEmpty()) {
417            return err;
418        }
419        doc->endPage();
420    }
421    if (!doc->close()) {
422        return "SkDocument::close() returned false";
423    }
424    dst->flush();
425    return "";
426}
427
428PDFSink::PDFSink() {}
429
430Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
431    SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
432    if (!doc) {
433        return "SkDocument::CreatePDF() returned NULL";
434    }
435    return draw_skdocument(src, doc.get(), dst);
436}
437
438/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
439
440XPSSink::XPSSink() {}
441
442Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
443    SkAutoTUnref<SkDocument> doc(SkDocument::CreateXPS(dst));
444    if (!doc) {
445        return "SkDocument::CreateXPS() returned NULL";
446    }
447    return draw_skdocument(src, doc.get(), dst);
448}
449/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
450
451SKPSink::SKPSink() {}
452
453Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
454    SkSize size;
455    size = src.size();
456    SkPictureRecorder recorder;
457    Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
458    if (!err.isEmpty()) {
459        return err;
460    }
461    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
462    pic->serialize(dst);
463    return "";
464}
465
466/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
467
468SVGSink::SVGSink() {}
469
470Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
471    SkAutoTDelete<SkXMLWriter> xmlWriter(SkNEW_ARGS(SkXMLStreamWriter, (dst)));
472    SkAutoTUnref<SkCanvas> canvas(SkSVGCanvas::Create(
473        SkRect::MakeWH(SkIntToScalar(src.size().width()), SkIntToScalar(src.size().height())),
474        xmlWriter));
475    return src.draw(canvas);
476}
477
478/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
479
480RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
481
482Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
483    const SkISize size = src.size();
484    // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
485    SkAlphaType alphaType = kPremul_SkAlphaType;
486    (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
487
488    dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
489    dst->eraseColor(SK_ColorTRANSPARENT);
490    SkCanvas canvas(*dst);
491    return src.draw(&canvas);
492}
493
494/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
495
496// Handy for front-patching a Src.  Do whatever up-front work you need, then call draw_to_canvas(),
497// passing the Sink draw() arguments, a size, and a function draws into an SkCanvas.
498// Several examples below.
499
500static Error draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, SkString* log,
501                            SkISize size, SkFunction<Error(SkCanvas*)> draw) {
502    class ProxySrc : public Src {
503    public:
504        ProxySrc(SkISize size, SkFunction<Error(SkCanvas*)> draw) : fSize(size), fDraw(draw) {}
505        Error   draw(SkCanvas* canvas) const override { return fDraw(canvas); }
506        Name                    name() const override { sk_throw(); return ""; } // Won't be called.
507        SkISize                 size() const override { return fSize; }
508    private:
509        SkISize                      fSize;
510        SkFunction<Error(SkCanvas*)> fDraw;
511    };
512    return sink->draw(ProxySrc(size, draw), bitmap, stream, log);
513}
514
515/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
516
517static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
518    SkRect bounds = SkRect::MakeIWH(srcW, srcH);
519    matrix->mapRect(&bounds);
520    matrix->postTranslate(-bounds.x(), -bounds.y());
521    return SkISize::Make(SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height()));
522}
523
524ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
525
526Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
527    SkMatrix matrix = fMatrix;
528    SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
529    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
530        canvas->concat(matrix);
531        return src.draw(canvas);
532    });
533}
534
535// Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
536// This should be pixel-preserving.
537ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
538
539Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
540    Error err = fSink->draw(src, bitmap, stream, log);
541    if (!err.isEmpty()) {
542        return err;
543    }
544
545    SkMatrix inverse;
546    if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) {
547        return "Cannot upright --matrix.";
548    }
549    SkMatrix upright = SkMatrix::I();
550    upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX()));
551    upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY()));
552    upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX()));
553    upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY()));
554
555    SkBitmap uprighted;
556    SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height());
557    uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height()));
558
559    SkCanvas canvas(uprighted);
560    canvas.concat(upright);
561    SkPaint paint;
562    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
563    canvas.drawBitmap(*bitmap, 0, 0, &paint);
564
565    *bitmap = uprighted;
566    bitmap->lockPixels();
567    return "";
568}
569
570/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
571
572Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
573    auto size = src.size();
574    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
575        PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
576        SkGPipeWriter pipe;
577        const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
578        return src.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
579    });
580}
581
582/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
583
584Error ViaDeferred::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
585    // We draw via a deferred canvas into a surface that's compatible with the original canvas,
586    // then snap that surface as an image and draw it into the original canvas.
587    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error {
588        SkAutoTUnref<SkSurface> surface(canvas->newSurface(canvas->imageInfo()));
589        if (!surface.get()) {
590            return "can't make surface for deferred canvas";
591        }
592        SkAutoTDelete<SkDeferredCanvas> defcan(SkDeferredCanvas::Create(surface));
593        Error err = src.draw(defcan);
594        if (!err.isEmpty()) {
595            return err;
596        }
597        SkAutoTUnref<SkImage> image(defcan->newImageSnapshot());
598        if (!image) {
599            return "failed to create deferred image snapshot";
600        }
601        canvas->drawImage(image, 0, 0, NULL);
602        return "";
603    });
604}
605
606/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
607
608Error ViaSerialization::draw(
609        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
610    // Record our Src into a picture.
611    auto size = src.size();
612    SkPictureRecorder recorder;
613    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
614                                                 SkIntToScalar(size.height())));
615    if (!err.isEmpty()) {
616        return err;
617    }
618    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
619
620    // Serialize it and then deserialize it.
621    SkDynamicMemoryWStream wStream;
622    pic->serialize(&wStream);
623    SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
624    SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream, &lazy_decode_bitmap));
625
626    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
627        canvas->drawPicture(deserialized);
628        return "";
629    });
630}
631
632/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
633
634ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
635    : Via(sink)
636    , fW(w)
637    , fH(h)
638    , fFactory(factory) {}
639
640Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
641    auto size = src.size();
642    SkPictureRecorder recorder;
643    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
644                                                 SkIntToScalar(size.height()),
645                                                 fFactory.get()));
646    if (!err.isEmpty()) {
647        return err;
648    }
649    SkAutoTUnref<SkPicture> pic(recorder.endRecordingAsPicture());
650
651    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) {
652        const int xTiles = (size.width()  + fW - 1) / fW,
653                  yTiles = (size.height() + fH - 1) / fH;
654        SkMultiPictureDraw mpd(xTiles*yTiles);
655        SkTDArray<SkSurface*> surfaces;
656        surfaces.setReserve(xTiles*yTiles);
657
658        SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
659        for (int j = 0; j < yTiles; j++) {
660            for (int i = 0; i < xTiles; i++) {
661                // This lets our ultimate Sink determine the best kind of surface.
662                // E.g., if it's a GpuSink, the surfaces and images are textures.
663                SkSurface* s = canvas->newSurface(info);
664                if (!s) {
665                    s = SkSurface::NewRaster(info);  // Some canvases can't create surfaces.
666                }
667                surfaces.push(s);
668                SkCanvas* c = s->getCanvas();
669                c->translate(SkIntToScalar(-i * fW),
670                             SkIntToScalar(-j * fH));  // Line up the canvas with this tile.
671                mpd.add(c, pic);
672            }
673        }
674        mpd.draw();
675        for (int j = 0; j < yTiles; j++) {
676            for (int i = 0; i < xTiles; i++) {
677                SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
678                canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
679            }
680        }
681        surfaces.unrefAll();
682        return "";
683    });
684}
685
686/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
687
688// Draw the Src into two pictures, then draw the second picture into the wrapped Sink.
689// This tests that any shortcuts we may take while recording that second picture are legal.
690Error ViaSecondPicture::draw(
691        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
692    auto size = src.size();
693    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
694        SkPictureRecorder recorder;
695        SkAutoTUnref<SkPicture> pic;
696        for (int i = 0; i < 2; i++) {
697            Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
698                                                         SkIntToScalar(size.height())));
699            if (!err.isEmpty()) {
700                return err;
701            }
702            pic.reset(recorder.endRecordingAsPicture());
703        }
704        canvas->drawPicture(pic);
705        return "";
706    });
707}
708
709/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
710
711// Draw the Src twice.  This can help exercise caching.
712Error ViaTwice::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
713    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error {
714        for (int i = 0; i < 2; i++) {
715            SkAutoCanvasRestore acr(canvas, true/*save now*/);
716            canvas->clear(SK_ColorTRANSPARENT);
717            Error err = src.draw(canvas);
718            if (err.isEmpty()) {
719                return err;
720            }
721        }
722        return "";
723    });
724}
725
726/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
727
728// This is like SkRecords::Draw, in that it plays back SkRecords ops into a Canvas.
729// Unlike SkRecords::Draw, it builds a single-op sub-picture out of each Draw-type op.
730// This is an only-slightly-exaggerated simluation of Blink's Slimming Paint pictures.
731struct DrawsAsSingletonPictures {
732    SkCanvas* fCanvas;
733
734    SK_CREATE_MEMBER_DETECTOR(paint);
735
736    template <typename T>
737    void draw(const T& op, SkCanvas* canvas) {
738        // We must pass SkMatrix::I() as our initial matrix.
739        // By default SkRecords::Draw() uses the canvas' matrix as its initial matrix,
740        // which would have the funky effect of applying transforms over and over.
741        SkRecords::Draw(canvas, nullptr, nullptr, 0, &SkMatrix::I())(op);
742    }
743
744    // Most things that have paints are Draw-type ops.  Create sub-pictures for each.
745    template <typename T>
746    SK_WHEN(HasMember_paint<T>, void) operator()(const T& op) {
747        SkPictureRecorder rec;
748        this->draw(op, rec.beginRecording(SkRect::MakeLargest()));
749        SkAutoTUnref<SkPicture> pic(rec.endRecordingAsPicture());
750        fCanvas->drawPicture(pic);
751    }
752
753    // If you don't have a paint or are a SaveLayer, you're not a Draw-type op.
754    // We cannot make subpictures out of these because they affect state.  Draw them directly.
755    template <typename T>
756    SK_WHEN(!HasMember_paint<T>, void) operator()(const T& op) { this->draw(op, fCanvas); }
757    void operator()(const SkRecords::SaveLayer& op)            { this->draw(op, fCanvas); }
758};
759
760// Record Src into a picture, then record it into a macro picture with a sub-picture for each draw.
761// Then play back that macro picture into our wrapped sink.
762Error ViaSingletonPictures::draw(
763        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
764    auto size = src.size();
765    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
766        // Use low-level (Skia-private) recording APIs so we can read the SkRecord.
767        SkRecord skr;
768        SkRecorder recorder(&skr, size.width(), size.height());
769        Error err = src.draw(&recorder);
770        if (!err.isEmpty()) {
771            return err;
772        }
773
774        // Record our macro-picture, with each draw op as its own sub-picture.
775        SkPictureRecorder macroRec;
776        SkCanvas* macroCanvas = macroRec.beginRecording(SkIntToScalar(size.width()),
777                                                        SkIntToScalar(size.height()));
778        DrawsAsSingletonPictures drawsAsSingletonPictures = { macroCanvas };
779        for (unsigned i = 0; i < skr.count(); i++) {
780            skr.visit<void>(i, drawsAsSingletonPictures);
781        }
782        SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture());
783
784        canvas->drawPicture(macroPic);
785        return "";
786    });
787}
788
789}  // namespace DM
790