DMSrcSink.cpp revision 6dea83f244cfdea52901eef6b31cee60b07a8ea0
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 "SkAndroidCodec.h"
11#include "SkCodec.h"
12#include "SkCommonFlags.h"
13#include "SkData.h"
14#include "SkDocument.h"
15#include "SkError.h"
16#include "SkImageGenerator.h"
17#include "SkMultiPictureDraw.h"
18#include "SkNullCanvas.h"
19#include "SkOSFile.h"
20#include "SkPictureData.h"
21#include "SkPictureRecorder.h"
22#include "SkRandom.h"
23#include "SkRecordDraw.h"
24#include "SkRecorder.h"
25#include "SkRemote.h"
26#include "SkSVGCanvas.h"
27#include "SkStream.h"
28#include "SkTLogic.h"
29#include "SkXMLWriter.h"
30#include "SkSwizzler.h"
31#include <functional>
32
33DEFINE_bool(multiPage, false, "For document-type backends, render the source"
34            " into multiple pages");
35
36static bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) {
37    SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size));
38    return encoded && SkDEPRECATED_InstallDiscardablePixelRef(encoded, dst);
39}
40
41namespace DM {
42
43GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
44
45Error GMSrc::draw(SkCanvas* canvas) const {
46    SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
47    canvas->concat(gm->getInitialTransform());
48    gm->draw(canvas);
49    return "";
50}
51
52SkISize GMSrc::size() const {
53    SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
54    return gm->getISize();
55}
56
57Name GMSrc::name() const {
58    SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
59    return gm->getName();
60}
61
62void GMSrc::modifyGrContextOptions(GrContextOptions* options) const {
63    SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
64    gm->modifyGrContextOptions(options);
65}
66
67/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
68
69BRDSrc::BRDSrc(Path path, SkBitmapRegionDecoder::Strategy strategy, Mode mode,
70        CodecSrc::DstColorType dstColorType, uint32_t sampleSize)
71    : fPath(path)
72    , fStrategy(strategy)
73    , fMode(mode)
74    , fDstColorType(dstColorType)
75    , fSampleSize(sampleSize)
76{}
77
78bool BRDSrc::veto(SinkFlags flags) const {
79    // No need to test to non-raster or indirect backends.
80    return flags.type != SinkFlags::kRaster
81        || flags.approach != SinkFlags::kDirect;
82}
83
84static SkBitmapRegionDecoder* create_brd(Path path,
85        SkBitmapRegionDecoder::Strategy strategy) {
86    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
87    if (!encoded) {
88        return NULL;
89    }
90    return SkBitmapRegionDecoder::Create(encoded, strategy);
91}
92
93Error BRDSrc::draw(SkCanvas* canvas) const {
94    SkColorType colorType = canvas->imageInfo().colorType();
95    if (kRGB_565_SkColorType == colorType &&
96            CodecSrc::kGetFromCanvas_DstColorType != fDstColorType) {
97        return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
98    }
99    switch (fDstColorType) {
100        case CodecSrc::kGetFromCanvas_DstColorType:
101            break;
102        case CodecSrc::kIndex8_Always_DstColorType:
103            colorType = kIndex_8_SkColorType;
104            break;
105        case CodecSrc::kGrayscale_Always_DstColorType:
106            colorType = kGray_8_SkColorType;
107            break;
108    }
109
110    SkAutoTDelete<SkBitmapRegionDecoder> brd(create_brd(fPath, fStrategy));
111    if (nullptr == brd.get()) {
112        return Error::Nonfatal(SkStringPrintf("Could not create brd for %s.", fPath.c_str()));
113    }
114
115    if (!brd->conversionSupported(colorType)) {
116        return Error::Nonfatal("Cannot convert to color type.\n");
117    }
118
119    const uint32_t width = brd->width();
120    const uint32_t height = brd->height();
121    // Visually inspecting very small output images is not necessary.
122    if ((width / fSampleSize <= 10 || height / fSampleSize <= 10) && 1 != fSampleSize) {
123        return Error::Nonfatal("Scaling very small images is uninteresting.");
124    }
125    switch (fMode) {
126        case kFullImage_Mode: {
127            SkBitmap bitmap;
128            if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, width, height),
129                    fSampleSize, colorType, false)) {
130                return "Cannot decode (full) region.\n";
131            }
132            if (colorType != bitmap.colorType()) {
133                return Error::Nonfatal("Cannot convert to color type.\n");
134            }
135            canvas->drawBitmap(bitmap, 0, 0);
136            return "";
137        }
138        case kDivisor_Mode: {
139            const uint32_t divisor = 2;
140            if (width < divisor || height < divisor) {
141                return Error::Nonfatal("Divisor is larger than image dimension.\n");
142            }
143
144            // Use a border to test subsets that extend outside the image.
145            // We will not allow the border to be larger than the image dimensions.  Allowing
146            // these large borders causes off by one errors that indicate a problem with the
147            // test suite, not a problem with the implementation.
148            const uint32_t maxBorder = SkTMin(width, height) / (fSampleSize * divisor);
149            const uint32_t scaledBorder = SkTMin(5u, maxBorder);
150            const uint32_t unscaledBorder = scaledBorder * fSampleSize;
151
152            // We may need to clear the canvas to avoid uninitialized memory.
153            // Assume we are scaling a 780x780 image with sampleSize = 8.
154            // The output image should be 97x97.
155            // Each subset will be 390x390.
156            // Each scaled subset be 48x48.
157            // Four scaled subsets will only fill a 96x96 image.
158            // The bottom row and last column will not be touched.
159            // This is an unfortunate result of our rounding rules when scaling.
160            // Maybe we need to consider testing scaled subsets without trying to
161            // combine them to match the full scaled image?  Or maybe this is the
162            // best we can do?
163            canvas->clear(0);
164
165            for (uint32_t x = 0; x < divisor; x++) {
166                for (uint32_t y = 0; y < divisor; y++) {
167                    // Calculate the subset dimensions
168                    uint32_t subsetWidth = width / divisor;
169                    uint32_t subsetHeight = height / divisor;
170                    const int left = x * subsetWidth;
171                    const int top = y * subsetHeight;
172
173                    // Increase the size of the last subset in each row or column, when the
174                    // divisor does not divide evenly into the image dimensions
175                    subsetWidth += (x + 1 == divisor) ? (width % divisor) : 0;
176                    subsetHeight += (y + 1 == divisor) ? (height % divisor) : 0;
177
178                    // Increase the size of the subset in order to have a border on each side
179                    const int decodeLeft = left - unscaledBorder;
180                    const int decodeTop = top - unscaledBorder;
181                    const uint32_t decodeWidth = subsetWidth + unscaledBorder * 2;
182                    const uint32_t decodeHeight = subsetHeight + unscaledBorder * 2;
183                    SkBitmap bitmap;
184                    if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(decodeLeft,
185                            decodeTop, decodeWidth, decodeHeight), fSampleSize, colorType, false)) {
186                        return "Cannot decode region.\n";
187                    }
188                    if (colorType != bitmap.colorType()) {
189                        return Error::Nonfatal("Cannot convert to color type.\n");
190                    }
191
192                    canvas->drawBitmapRect(bitmap,
193                            SkRect::MakeXYWH((SkScalar) scaledBorder, (SkScalar) scaledBorder,
194                                    (SkScalar) (subsetWidth / fSampleSize),
195                                    (SkScalar) (subsetHeight / fSampleSize)),
196                            SkRect::MakeXYWH((SkScalar) (left / fSampleSize),
197                                    (SkScalar) (top / fSampleSize),
198                                    (SkScalar) (subsetWidth / fSampleSize),
199                                    (SkScalar) (subsetHeight / fSampleSize)),
200                            nullptr);
201                }
202            }
203            return "";
204        }
205        default:
206            SkASSERT(false);
207            return "Error: Should not be reached.\n";
208    }
209}
210
211SkISize BRDSrc::size() const {
212    SkAutoTDelete<SkBitmapRegionDecoder> brd(create_brd(fPath, fStrategy));
213    if (brd) {
214        return SkISize::Make(SkTMax(1, brd->width() / (int) fSampleSize),
215                SkTMax(1, brd->height() / (int) fSampleSize));
216    }
217    return SkISize::Make(0, 0);
218}
219
220static SkString get_scaled_name(const Path& path, float scale) {
221    return SkStringPrintf("%s_%.3f", SkOSPath::Basename(path.c_str()).c_str(), scale);
222}
223
224Name BRDSrc::name() const {
225    // We will replicate the names used by CodecSrc so that images can
226    // be compared in Gold.
227    if (1 == fSampleSize) {
228        return SkOSPath::Basename(fPath.c_str());
229    }
230    return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
231}
232
233/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
234
235CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType, float scale)
236    : fPath(path)
237    , fMode(mode)
238    , fDstColorType(dstColorType)
239    , fScale(scale)
240{}
241
242bool CodecSrc::veto(SinkFlags flags) const {
243    // No need to test decoding to non-raster or indirect backend.
244    // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferred decode to
245    // let the GPU handle it.
246    return flags.type != SinkFlags::kRaster
247        || flags.approach != SinkFlags::kDirect;
248}
249
250bool get_decode_info(SkImageInfo* decodeInfo, const SkImageInfo& defaultInfo,
251        SkColorType canvasColorType, CodecSrc::DstColorType dstColorType) {
252    switch (dstColorType) {
253        case CodecSrc::kIndex8_Always_DstColorType:
254            if (kRGB_565_SkColorType == canvasColorType) {
255                return false;
256            }
257            *decodeInfo = defaultInfo.makeColorType(kIndex_8_SkColorType);
258            break;
259        case CodecSrc::kGrayscale_Always_DstColorType:
260            if (kRGB_565_SkColorType == canvasColorType) {
261                return false;
262            }
263            *decodeInfo = defaultInfo.makeColorType(kGray_8_SkColorType);
264            break;
265        default:
266            *decodeInfo = defaultInfo.makeColorType(canvasColorType);
267            break;
268    }
269
270    // FIXME: Currently we cannot draw unpremultiplied sources.
271    if (decodeInfo->alphaType() == kUnpremul_SkAlphaType) {
272        *decodeInfo = decodeInfo->makeAlphaType(kPremul_SkAlphaType);
273    }
274    return true;
275}
276
277Error CodecSrc::draw(SkCanvas* canvas) const {
278    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
279    if (!encoded) {
280        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
281    }
282    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
283    if (nullptr == codec.get()) {
284        return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
285    }
286
287    SkImageInfo decodeInfo;
288    if (!get_decode_info(&decodeInfo, codec->getInfo(), canvas->imageInfo().colorType(),
289            fDstColorType)) {
290        return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
291    }
292
293    // Try to scale the image if it is desired
294    SkISize size = codec->getScaledDimensions(fScale);
295    if (size == decodeInfo.dimensions() && 1.0f != fScale) {
296        return Error::Nonfatal("Test without scaling is uninteresting.");
297    }
298
299    // Visually inspecting very small output images is not necessary.  We will
300    // cover these cases in unit testing.
301    if ((size.width() <= 10 || size.height() <= 10) && 1.0f != fScale) {
302        return Error::Nonfatal("Scaling very small images is uninteresting.");
303    }
304    decodeInfo = decodeInfo.makeWH(size.width(), size.height());
305
306    // Construct a color table for the decode if necessary
307    SkAutoTUnref<SkColorTable> colorTable(nullptr);
308    SkPMColor* colorPtr = nullptr;
309    int* colorCountPtr = nullptr;
310    int maxColors = 256;
311    if (kIndex_8_SkColorType == decodeInfo.colorType()) {
312        SkPMColor colors[256];
313        colorTable.reset(new SkColorTable(colors, maxColors));
314        colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
315        colorCountPtr = &maxColors;
316    }
317
318    SkBitmap bitmap;
319    if (!bitmap.tryAllocPixels(decodeInfo, nullptr, colorTable.get())) {
320        return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(),
321                              decodeInfo.width(), decodeInfo.height());
322    }
323
324    switch (fMode) {
325        case kCodec_Mode: {
326            switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), nullptr,
327                    colorPtr, colorCountPtr)) {
328                case SkCodec::kSuccess:
329                    // We consider incomplete to be valid, since we should still decode what is
330                    // available.
331                case SkCodec::kIncompleteInput:
332                    break;
333                case SkCodec::kInvalidConversion:
334                    return Error::Nonfatal("Incompatible colortype conversion");
335                default:
336                    // Everything else is considered a failure.
337                    return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
338            }
339            canvas->drawBitmap(bitmap, 0, 0);
340            break;
341        }
342        case kScanline_Mode: {
343            if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL, colorPtr,
344                                                                colorCountPtr)) {
345                return Error::Nonfatal("Could not start scanline decoder");
346            }
347
348            void* dst = bitmap.getAddr(0, 0);
349            size_t rowBytes = bitmap.rowBytes();
350            uint32_t height = decodeInfo.height();
351            switch (codec->getScanlineOrder()) {
352                case SkCodec::kTopDown_SkScanlineOrder:
353                case SkCodec::kBottomUp_SkScanlineOrder:
354                case SkCodec::kNone_SkScanlineOrder:
355                    // We do not need to check the return value.  On an incomplete
356                    // image, memory will be filled with a default value.
357                    codec->getScanlines(dst, height, rowBytes);
358                    break;
359                case SkCodec::kOutOfOrder_SkScanlineOrder: {
360                    for (int y = 0; y < decodeInfo.height(); y++) {
361                        int dstY = codec->outputScanline(y);
362                        void* dstPtr = bitmap.getAddr(0, dstY);
363                        // We complete the loop, even if this call begins to fail
364                        // due to an incomplete image.  This ensures any uninitialized
365                        // memory will be filled with the proper value.
366                        codec->getScanlines(dstPtr, 1, bitmap.rowBytes());
367                    }
368                    break;
369                }
370            }
371
372            canvas->drawBitmap(bitmap, 0, 0);
373            break;
374        }
375        case kStripe_Mode: {
376            const int height = decodeInfo.height();
377            // This value is chosen arbitrarily.  We exercise more cases by choosing a value that
378            // does not align with image blocks.
379            const int stripeHeight = 37;
380            const int numStripes = (height + stripeHeight - 1) / stripeHeight;
381
382            // Decode odd stripes
383            if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL, colorPtr,
384                                                                colorCountPtr)
385                    || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOrder()) {
386                // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
387                // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
388                // to run this test for image types that do not have this scanline ordering.
389                return Error::Nonfatal("Could not start top-down scanline decoder");
390            }
391
392            for (int i = 0; i < numStripes; i += 2) {
393                // Skip a stripe
394                const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight);
395                codec->skipScanlines(linesToSkip);
396
397                // Read a stripe
398                const int startY = (i + 1) * stripeHeight;
399                const int linesToRead = SkTMin(stripeHeight, height - startY);
400                if (linesToRead > 0) {
401                    codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
402                }
403            }
404
405            // Decode even stripes
406            const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo, nullptr,
407                    colorPtr, colorCountPtr);
408            if (SkCodec::kSuccess != startResult) {
409                return "Failed to restart scanline decoder with same parameters.";
410            }
411            for (int i = 0; i < numStripes; i += 2) {
412                // Read a stripe
413                const int startY = i * stripeHeight;
414                const int linesToRead = SkTMin(stripeHeight, height - startY);
415                codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
416
417                // Skip a stripe
418                const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
419                if (linesToSkip > 0) {
420                    codec->skipScanlines(linesToSkip);
421                }
422            }
423            canvas->drawBitmap(bitmap, 0, 0);
424            break;
425        }
426        case kSubset_Mode: {
427            // Arbitrarily choose a divisor.
428            int divisor = 2;
429            // Total width/height of the image.
430            const int W = codec->getInfo().width();
431            const int H = codec->getInfo().height();
432            if (divisor > W || divisor > H) {
433                return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divisor %d is too big "
434                                                      "for %s with dimensions (%d x %d)", divisor,
435                                                      fPath.c_str(), W, H));
436            }
437            // subset dimensions
438            // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
439            const int w = SkAlign2(W / divisor);
440            const int h = SkAlign2(H / divisor);
441            SkIRect subset;
442            SkCodec::Options opts;
443            opts.fSubset = &subset;
444            SkBitmap subsetBm;
445            // We will reuse pixel memory from bitmap.
446            void* pixels = bitmap.getPixels();
447            // Keep track of left and top (for drawing subsetBm into canvas). We could use
448            // fScale * x and fScale * y, but we want integers such that the next subset will start
449            // where the last one ended. So we'll add decodeInfo.width() and height().
450            int left = 0;
451            for (int x = 0; x < W; x += w) {
452                int top = 0;
453                for (int y = 0; y < H; y+= h) {
454                    // Do not make the subset go off the edge of the image.
455                    const int preScaleW = SkTMin(w, W - x);
456                    const int preScaleH = SkTMin(h, H - y);
457                    subset.setXYWH(x, y, preScaleW, preScaleH);
458                    // And scale
459                    // FIXME: Should we have a version of getScaledDimensions that takes a subset
460                    // into account?
461                    decodeInfo = decodeInfo.makeWH(
462                            SkTMax(1, SkScalarRoundToInt(preScaleW * fScale)),
463                            SkTMax(1, SkScalarRoundToInt(preScaleH * fScale)));
464                    size_t rowBytes = decodeInfo.minRowBytes();
465                    if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, colorTable.get(),
466                                                nullptr, nullptr)) {
467                        return SkStringPrintf("could not install pixels for %s.", fPath.c_str());
468                    }
469                    const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes,
470                            &opts, colorPtr, colorCountPtr);
471                    switch (result) {
472                        case SkCodec::kSuccess:
473                        case SkCodec::kIncompleteInput:
474                            break;
475                        case SkCodec::kInvalidConversion:
476                            if (0 == (x|y)) {
477                                // First subset is okay to return unimplemented.
478                                return Error::Nonfatal("Incompatible colortype conversion");
479                            }
480                            // If the first subset succeeded, a later one should not fail.
481                            // fall through to failure
482                        case SkCodec::kUnimplemented:
483                            if (0 == (x|y)) {
484                                // First subset is okay to return unimplemented.
485                                return Error::Nonfatal("subset codec not supported");
486                            }
487                            // If the first subset succeeded, why would a later one fail?
488                            // fall through to failure
489                        default:
490                            return SkStringPrintf("subset codec failed to decode (%d, %d, %d, %d) "
491                                                  "from %s with dimensions (%d x %d)\t error %d",
492                                                  x, y, decodeInfo.width(), decodeInfo.height(),
493                                                  fPath.c_str(), W, H, result);
494                    }
495                    canvas->drawBitmap(subsetBm, SkIntToScalar(left), SkIntToScalar(top));
496                    // translate by the scaled height.
497                    top += decodeInfo.height();
498                }
499                // translate by the scaled width.
500                left += decodeInfo.width();
501            }
502            return "";
503        }
504    }
505    return "";
506}
507
508SkISize CodecSrc::size() const {
509    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
510    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
511    if (nullptr == codec) {
512        return SkISize::Make(0, 0);
513    }
514    return codec->getScaledDimensions(fScale);
515}
516
517Name CodecSrc::name() const {
518    if (1.0f == fScale) {
519        return SkOSPath::Basename(fPath.c_str());
520    }
521    return get_scaled_name(fPath, fScale);
522}
523
524/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
525
526AndroidCodecSrc::AndroidCodecSrc(Path path, Mode mode, CodecSrc::DstColorType dstColorType,
527        int sampleSize)
528    : fPath(path)
529    , fMode(mode)
530    , fDstColorType(dstColorType)
531    , fSampleSize(sampleSize)
532{}
533
534bool AndroidCodecSrc::veto(SinkFlags flags) const {
535    // No need to test decoding to non-raster or indirect backend.
536    // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferred decode to
537    // let the GPU handle it.
538    return flags.type != SinkFlags::kRaster
539        || flags.approach != SinkFlags::kDirect;
540}
541
542Error AndroidCodecSrc::draw(SkCanvas* canvas) const {
543    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
544    if (!encoded) {
545        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
546    }
547    SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromData(encoded));
548    if (nullptr == codec.get()) {
549        return SkStringPrintf("Couldn't create android codec for %s.", fPath.c_str());
550    }
551
552    SkImageInfo decodeInfo;
553    if (!get_decode_info(&decodeInfo, codec->getInfo(), canvas->imageInfo().colorType(),
554            fDstColorType)) {
555        return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
556    }
557
558    // Scale the image if it is desired.
559    SkISize size = codec->getSampledDimensions(fSampleSize);
560
561    // Visually inspecting very small output images is not necessary.  We will
562    // cover these cases in unit testing.
563    if ((size.width() <= 10 || size.height() <= 10) && 1 != fSampleSize) {
564        return Error::Nonfatal("Scaling very small images is uninteresting.");
565    }
566    decodeInfo = decodeInfo.makeWH(size.width(), size.height());
567
568    // Construct a color table for the decode if necessary
569    SkAutoTUnref<SkColorTable> colorTable(nullptr);
570    SkPMColor* colorPtr = nullptr;
571    int* colorCountPtr = nullptr;
572    int maxColors = 256;
573    if (kIndex_8_SkColorType == decodeInfo.colorType()) {
574        SkPMColor colors[256];
575        colorTable.reset(new SkColorTable(colors, maxColors));
576        colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
577        colorCountPtr = &maxColors;
578    }
579
580    SkBitmap bitmap;
581    if (!bitmap.tryAllocPixels(decodeInfo, nullptr, colorTable.get())) {
582        return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(),
583                              decodeInfo.width(), decodeInfo.height());
584    }
585
586    // Create options for the codec.
587    SkAndroidCodec::AndroidOptions options;
588    options.fColorPtr = colorPtr;
589    options.fColorCount = colorCountPtr;
590    options.fSampleSize = fSampleSize;
591
592    switch (fMode) {
593        case kFullImage_Mode: {
594            switch (codec->getAndroidPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(),
595                    &options)) {
596                case SkCodec::kSuccess:
597                case SkCodec::kIncompleteInput:
598                    break;
599                case SkCodec::kInvalidConversion:
600                    return Error::Nonfatal("Cannot convert to requested color type.\n");
601                default:
602                    return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
603            }
604            canvas->drawBitmap(bitmap, 0, 0);
605            return "";
606        }
607        case kDivisor_Mode: {
608            const int width = codec->getInfo().width();
609            const int height = codec->getInfo().height();
610            const int divisor = 2;
611            if (width < divisor || height < divisor) {
612                return Error::Nonfatal("Divisor is larger than image dimension.\n");
613            }
614
615            // Keep track of the final decoded dimensions.
616            int finalScaledWidth = 0;
617            int finalScaledHeight = 0;
618            for (int x = 0; x < divisor; x++) {
619                for (int y = 0; y < divisor; y++) {
620                    // Calculate the subset dimensions
621                    int subsetWidth = width / divisor;
622                    int subsetHeight = height / divisor;
623                    const int left = x * subsetWidth;
624                    const int top = y * subsetHeight;
625
626                    // Increase the size of the last subset in each row or column, when the
627                    // divisor does not divide evenly into the image dimensions
628                    subsetWidth += (x + 1 == divisor) ? (width % divisor) : 0;
629                    subsetHeight += (y + 1 == divisor) ? (height % divisor) : 0;
630                    SkIRect subset = SkIRect::MakeXYWH(left, top, subsetWidth, subsetHeight);
631                    if (!codec->getSupportedSubset(&subset)) {
632                        return "Could not get supported subset to decode.\n";
633                    }
634                    options.fSubset = &subset;
635                    const int scaledWidthOffset = subset.left() / fSampleSize;
636                    const int scaledHeightOffset = subset.top() / fSampleSize;
637                    void* pixels = bitmap.getAddr(scaledWidthOffset, scaledHeightOffset);
638                    SkISize scaledSubsetSize = codec->getSampledSubsetDimensions(fSampleSize,
639                            subset);
640                    SkImageInfo subsetDecodeInfo = decodeInfo.makeWH(scaledSubsetSize.width(),
641                            scaledSubsetSize.height());
642
643                    if (x + 1 == divisor && y + 1 == divisor) {
644                        finalScaledWidth = scaledWidthOffset + scaledSubsetSize.width();
645                        finalScaledHeight = scaledHeightOffset + scaledSubsetSize.height();
646                    }
647
648                    switch (codec->getAndroidPixels(subsetDecodeInfo, pixels, bitmap.rowBytes(),
649                            &options)) {
650                        case SkCodec::kSuccess:
651                        case SkCodec::kIncompleteInput:
652                            break;
653                        case SkCodec::kInvalidConversion:
654                            return Error::Nonfatal("Cannot convert to requested color type.\n");
655                        default:
656                            return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
657                    }
658                }
659            }
660
661            SkRect rect = SkRect::MakeXYWH(0, 0, (SkScalar) finalScaledWidth,
662                    (SkScalar) finalScaledHeight);
663            canvas->drawBitmapRect(bitmap, rect, rect, nullptr);
664            return "";
665        }
666        default:
667            SkASSERT(false);
668            return "Error: Should not be reached.\n";
669    }
670}
671
672SkISize AndroidCodecSrc::size() const {
673    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
674    SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromData(encoded));
675    if (nullptr == codec) {
676        return SkISize::Make(0, 0);
677    }
678    return codec->getSampledDimensions(fSampleSize);
679}
680
681Name AndroidCodecSrc::name() const {
682    // We will replicate the names used by CodecSrc so that images can
683    // be compared in Gold.
684    if (1 == fSampleSize) {
685        return SkOSPath::Basename(fPath.c_str());
686    }
687    return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
688}
689
690/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
691
692ImageSrc::ImageSrc(Path path) : fPath(path) {}
693
694bool ImageSrc::veto(SinkFlags flags) const {
695    // No need to test decoding to non-raster or indirect backend.
696    // TODO: Instead, use lazy decoding to allow the GPU to handle cases like YUV.
697    return flags.type != SinkFlags::kRaster
698        || flags.approach != SinkFlags::kDirect;
699}
700
701Error ImageSrc::draw(SkCanvas* canvas) const {
702    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
703    if (!encoded) {
704        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
705    }
706    const SkColorType dstColorType = canvas->imageInfo().colorType();
707
708    // Decode the full image.
709    SkBitmap bitmap;
710    if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap,
711                                      dstColorType, SkImageDecoder::kDecodePixels_Mode)) {
712        return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
713    }
714    if (kRGB_565_SkColorType == dstColorType && !bitmap.isOpaque()) {
715        // Do not draw a bitmap with alpha to a destination without alpha.
716        return Error::Nonfatal("Uninteresting to decode image with alpha into 565.");
717    }
718    encoded.reset((SkData*)nullptr);  // Might as well drop this when we're done with it.
719    canvas->drawBitmap(bitmap, 0,0);
720    return "";
721}
722
723SkISize ImageSrc::size() const {
724    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
725    SkBitmap bitmap;
726    if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
727                                                  encoded->size(),
728                                                  &bitmap,
729                                                  kUnknown_SkColorType,
730                                                  SkImageDecoder::kDecodeBounds_Mode)) {
731        return SkISize::Make(0,0);
732    }
733    return bitmap.dimensions();
734}
735
736Name ImageSrc::name() const {
737    return SkOSPath::Basename(fPath.c_str());
738}
739
740/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
741
742static const SkRect kSKPViewport = {0,0, 1000,1000};
743
744SKPSrc::SKPSrc(Path path) : fPath(path) {}
745
746Error SKPSrc::draw(SkCanvas* canvas) const {
747    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
748    if (!stream) {
749        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
750    }
751    SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream, &lazy_decode_bitmap));
752    if (!pic) {
753        return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
754    }
755    stream.reset((SkStream*)nullptr);  // Might as well drop this when we're done with it.
756
757    canvas->clipRect(kSKPViewport);
758    canvas->drawPicture(pic);
759    return "";
760}
761
762SkISize SKPSrc::size() const {
763    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
764    if (!stream) {
765        return SkISize::Make(0,0);
766    }
767    SkPictInfo info;
768    if (!SkPicture::InternalOnly_StreamIsSKP(stream, &info)) {
769        return SkISize::Make(0,0);
770    }
771    SkRect viewport = kSKPViewport;
772    if (!viewport.intersect(info.fCullRect)) {
773        return SkISize::Make(0,0);
774    }
775    return viewport.roundOut().size();
776}
777
778Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
779
780/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
781
782Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
783    SkAutoTDelete<SkCanvas> canvas(SkCreateNullCanvas());
784    return src.draw(canvas);
785}
786
787/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
788
789DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
790
791GPUSink::GPUSink(GrContextFactory::GLContextType ct,
792                 GrGLStandard api,
793                 int samples,
794                 bool diText,
795                 bool threaded)
796    : fContextType(ct)
797    , fGpuAPI(api)
798    , fSampleCount(samples)
799    , fUseDIText(diText)
800    , fThreaded(threaded) {}
801
802int GPUSink::enclave() const {
803    return fThreaded ? kAnyThread_Enclave : kGPU_Enclave;
804}
805
806void PreAbandonGpuContextErrorHandler(SkError, void*) {}
807
808DEFINE_bool(imm, false, "Run gpu configs in immediate mode.");
809DEFINE_bool(batchClip, false, "Clip each GrBatch to its device bounds for testing.");
810DEFINE_bool(batchBounds, false, "Draw a wireframe bounds of each GrBatch.");
811
812Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
813    GrContextOptions options;
814    if (FLAGS_imm) {
815        options.fImmediateMode = true;
816    }
817    if (FLAGS_batchClip) {
818        options.fClipBatchToBounds = true;
819    }
820    if (FLAGS_batchBounds) {
821        options.fDrawBatchBounds = true;
822    }
823    src.modifyGrContextOptions(&options);
824
825    GrContextFactory factory(options);
826    const SkISize size = src.size();
827    const SkImageInfo info =
828        SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
829    SkAutoTUnref<SkSurface> surface(
830            NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDIText));
831    if (!surface) {
832        return "Could not create a surface.";
833    }
834    if (FLAGS_preAbandonGpuContext) {
835        SkSetErrorCallback(&PreAbandonGpuContextErrorHandler, nullptr);
836        factory.abandonContexts();
837    }
838    SkCanvas* canvas = surface->getCanvas();
839    Error err = src.draw(canvas);
840    if (!err.isEmpty()) {
841        return err;
842    }
843    canvas->flush();
844    if (FLAGS_gpuStats) {
845        canvas->getGrContext()->dumpCacheStats(log);
846        canvas->getGrContext()->dumpGpuStats(log);
847    }
848    dst->allocPixels(info);
849    canvas->readPixels(dst, 0, 0);
850    if (FLAGS_abandonGpuContext) {
851        factory.abandonContexts();
852    }
853    return "";
854}
855
856/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
857
858static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
859    // Print the given DM:Src to a document, breaking on 8.5x11 pages.
860    SkASSERT(doc);
861    int width  = src.size().width(),
862        height = src.size().height();
863
864    if (FLAGS_multiPage) {
865        const int kLetterWidth = 612,  // 8.5 * 72
866                kLetterHeight = 792;   // 11 * 72
867        const SkRect letter = SkRect::MakeWH(SkIntToScalar(kLetterWidth),
868                                             SkIntToScalar(kLetterHeight));
869
870        int xPages = ((width - 1) / kLetterWidth) + 1;
871        int yPages = ((height - 1) / kLetterHeight) + 1;
872
873        for (int y = 0; y < yPages; ++y) {
874            for (int x = 0; x < xPages; ++x) {
875                int w = SkTMin(kLetterWidth, width - (x * kLetterWidth));
876                int h = SkTMin(kLetterHeight, height - (y * kLetterHeight));
877                SkCanvas* canvas =
878                        doc->beginPage(SkIntToScalar(w), SkIntToScalar(h));
879                if (!canvas) {
880                    return "SkDocument::beginPage(w,h) returned nullptr";
881                }
882                canvas->clipRect(letter);
883                canvas->translate(-letter.width() * x, -letter.height() * y);
884                Error err = src.draw(canvas);
885                if (!err.isEmpty()) {
886                    return err;
887                }
888                doc->endPage();
889            }
890        }
891    } else {
892        SkCanvas* canvas =
893                doc->beginPage(SkIntToScalar(width), SkIntToScalar(height));
894        if (!canvas) {
895            return "SkDocument::beginPage(w,h) returned nullptr";
896        }
897        Error err = src.draw(canvas);
898        if (!err.isEmpty()) {
899            return err;
900        }
901        doc->endPage();
902    }
903    if (!doc->close()) {
904        return "SkDocument::close() returned false";
905    }
906    dst->flush();
907    return "";
908}
909
910PDFSink::PDFSink(const char* rasterizer) : fRasterizer(rasterizer) {}
911
912Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
913    SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
914    if (!doc) {
915        return "SkDocument::CreatePDF() returned nullptr";
916    }
917    SkTArray<SkDocument::Attribute> info;
918    info.emplace_back(SkString("Title"), src.name());
919    info.emplace_back(SkString("Subject"),
920                      SkString("rendering correctness test"));
921    info.emplace_back(SkString("Creator"), SkString("Skia/DM"));
922
923    info.emplace_back(SkString("Keywords"),
924                      SkStringPrintf("Rasterizer:%s;", fRasterizer));
925    doc->setMetadata(info, nullptr, nullptr);
926    return draw_skdocument(src, doc.get(), dst);
927}
928
929/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
930
931XPSSink::XPSSink() {}
932
933Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
934    SkAutoTUnref<SkDocument> doc(SkDocument::CreateXPS(dst));
935    if (!doc) {
936        return "SkDocument::CreateXPS() returned nullptr";
937    }
938    return draw_skdocument(src, doc.get(), dst);
939}
940/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
941
942SKPSink::SKPSink() {}
943
944Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
945    SkSize size;
946    size = src.size();
947    SkPictureRecorder recorder;
948    Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
949    if (!err.isEmpty()) {
950        return err;
951    }
952    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
953    pic->serialize(dst);
954    return "";
955}
956
957/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
958
959SVGSink::SVGSink() {}
960
961Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
962    SkAutoTDelete<SkXMLWriter> xmlWriter(new SkXMLStreamWriter(dst));
963    SkAutoTUnref<SkCanvas> canvas(SkSVGCanvas::Create(
964        SkRect::MakeWH(SkIntToScalar(src.size().width()), SkIntToScalar(src.size().height())),
965        xmlWriter));
966    return src.draw(canvas);
967}
968
969/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
970
971RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
972
973Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
974    const SkISize size = src.size();
975    // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
976    SkAlphaType alphaType = kPremul_SkAlphaType;
977    (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
978
979    dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
980    dst->eraseColor(SK_ColorTRANSPARENT);
981    SkCanvas canvas(*dst);
982    return src.draw(&canvas);
983}
984
985/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
986
987// Handy for front-patching a Src.  Do whatever up-front work you need, then call draw_to_canvas(),
988// passing the Sink draw() arguments, a size, and a function draws into an SkCanvas.
989// Several examples below.
990
991static Error draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, SkString* log,
992                            SkISize size, std::function<Error(SkCanvas*)> draw) {
993    class ProxySrc : public Src {
994    public:
995        ProxySrc(SkISize size, std::function<Error(SkCanvas*)> draw) : fSize(size), fDraw(draw) {}
996        Error   draw(SkCanvas* canvas) const override { return fDraw(canvas); }
997        Name                    name() const override { sk_throw(); return ""; } // Won't be called.
998        SkISize                 size() const override { return fSize; }
999    private:
1000        SkISize                         fSize;
1001        std::function<Error(SkCanvas*)> fDraw;
1002    };
1003    return sink->draw(ProxySrc(size, draw), bitmap, stream, log);
1004}
1005
1006/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1007
1008static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
1009    SkRect bounds = SkRect::MakeIWH(srcW, srcH);
1010    matrix->mapRect(&bounds);
1011    matrix->postTranslate(-bounds.x(), -bounds.y());
1012    return SkISize::Make(SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height()));
1013}
1014
1015ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
1016
1017Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1018    SkMatrix matrix = fMatrix;
1019    SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
1020    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
1021        canvas->concat(matrix);
1022        return src.draw(canvas);
1023    });
1024}
1025
1026// Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
1027// This should be pixel-preserving.
1028ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
1029
1030Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1031    Error err = fSink->draw(src, bitmap, stream, log);
1032    if (!err.isEmpty()) {
1033        return err;
1034    }
1035
1036    SkMatrix inverse;
1037    if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) {
1038        return "Cannot upright --matrix.";
1039    }
1040    SkMatrix upright = SkMatrix::I();
1041    upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX()));
1042    upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY()));
1043    upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX()));
1044    upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY()));
1045
1046    SkBitmap uprighted;
1047    SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height());
1048    uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height()));
1049
1050    SkCanvas canvas(uprighted);
1051    canvas.concat(upright);
1052    SkPaint paint;
1053    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
1054    canvas.drawBitmap(*bitmap, 0, 0, &paint);
1055
1056    *bitmap = uprighted;
1057    bitmap->lockPixels();
1058    return "";
1059}
1060
1061/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1062
1063Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1064    auto size = src.size();
1065    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
1066        PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
1067        SkGPipeWriter pipe;
1068        const uint32_t kFlags = 0;
1069        return src.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
1070    });
1071}
1072
1073Error ViaRemote::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1074    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* target) {
1075        SkAutoTDelete<SkRemote::Encoder> decoder(SkRemote::NewDecoder(target));
1076        SkAutoTDelete<SkRemote::Encoder>   cache(fCache ? SkRemote::NewCachingEncoder(decoder)
1077                                                        : nullptr);
1078        SkAutoTDelete<SkCanvas> canvas(SkRemote::NewCanvas(cache ? cache : decoder));
1079        return src.draw(canvas);
1080    });
1081}
1082
1083/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1084
1085Error ViaSerialization::draw(
1086        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1087    // Record our Src into a picture.
1088    auto size = src.size();
1089    SkPictureRecorder recorder;
1090    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
1091                                                 SkIntToScalar(size.height())));
1092    if (!err.isEmpty()) {
1093        return err;
1094    }
1095    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
1096
1097    // Serialize it and then deserialize it.
1098    SkDynamicMemoryWStream wStream;
1099    pic->serialize(&wStream);
1100    SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
1101    SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream, &lazy_decode_bitmap));
1102
1103    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
1104        canvas->drawPicture(deserialized);
1105        return "";
1106    });
1107}
1108
1109/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1110
1111ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
1112    : Via(sink)
1113    , fW(w)
1114    , fH(h)
1115    , fFactory(factory) {}
1116
1117Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1118    auto size = src.size();
1119    SkPictureRecorder recorder;
1120    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
1121                                                 SkIntToScalar(size.height()),
1122                                                 fFactory.get()));
1123    if (!err.isEmpty()) {
1124        return err;
1125    }
1126    SkAutoTUnref<SkPicture> pic(recorder.endRecordingAsPicture());
1127
1128    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) {
1129        const int xTiles = (size.width()  + fW - 1) / fW,
1130                  yTiles = (size.height() + fH - 1) / fH;
1131        SkMultiPictureDraw mpd(xTiles*yTiles);
1132        SkTDArray<SkSurface*> surfaces;
1133        surfaces.setReserve(xTiles*yTiles);
1134
1135        SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
1136        for (int j = 0; j < yTiles; j++) {
1137            for (int i = 0; i < xTiles; i++) {
1138                // This lets our ultimate Sink determine the best kind of surface.
1139                // E.g., if it's a GpuSink, the surfaces and images are textures.
1140                SkSurface* s = canvas->newSurface(info);
1141                if (!s) {
1142                    s = SkSurface::NewRaster(info);  // Some canvases can't create surfaces.
1143                }
1144                surfaces.push(s);
1145                SkCanvas* c = s->getCanvas();
1146                c->translate(SkIntToScalar(-i * fW),
1147                             SkIntToScalar(-j * fH));  // Line up the canvas with this tile.
1148                mpd.add(c, pic);
1149            }
1150        }
1151        mpd.draw();
1152        for (int j = 0; j < yTiles; j++) {
1153            for (int i = 0; i < xTiles; i++) {
1154                SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
1155                canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
1156            }
1157        }
1158        surfaces.unrefAll();
1159        return "";
1160    });
1161}
1162
1163/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1164
1165// Draw the Src into two pictures, then draw the second picture into the wrapped Sink.
1166// This tests that any shortcuts we may take while recording that second picture are legal.
1167Error ViaSecondPicture::draw(
1168        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1169    auto size = src.size();
1170    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
1171        SkPictureRecorder recorder;
1172        SkAutoTUnref<SkPicture> pic;
1173        for (int i = 0; i < 2; i++) {
1174            Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
1175                                                         SkIntToScalar(size.height())));
1176            if (!err.isEmpty()) {
1177                return err;
1178            }
1179            pic.reset(recorder.endRecordingAsPicture());
1180        }
1181        canvas->drawPicture(pic);
1182        return "";
1183    });
1184}
1185
1186/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1187
1188// Draw the Src twice.  This can help exercise caching.
1189Error ViaTwice::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1190    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error {
1191        for (int i = 0; i < 2; i++) {
1192            SkAutoCanvasRestore acr(canvas, true/*save now*/);
1193            canvas->clear(SK_ColorTRANSPARENT);
1194            Error err = src.draw(canvas);
1195            if (err.isEmpty()) {
1196                return err;
1197            }
1198        }
1199        return "";
1200    });
1201}
1202
1203/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1204
1205// This is like SkRecords::Draw, in that it plays back SkRecords ops into a Canvas.
1206// Unlike SkRecords::Draw, it builds a single-op sub-picture out of each Draw-type op.
1207// This is an only-slightly-exaggerated simluation of Blink's Slimming Paint pictures.
1208struct DrawsAsSingletonPictures {
1209    SkCanvas* fCanvas;
1210    const SkDrawableList& fDrawables;
1211
1212    template <typename T>
1213    void draw(const T& op, SkCanvas* canvas) {
1214        // We must pass SkMatrix::I() as our initial matrix.
1215        // By default SkRecords::Draw() uses the canvas' matrix as its initial matrix,
1216        // which would have the funky effect of applying transforms over and over.
1217        SkRecords::Draw d(canvas, nullptr, fDrawables.begin(), fDrawables.count(), &SkMatrix::I());
1218        d(op);
1219    }
1220
1221    // Draws get their own picture.
1222    template <typename T>
1223    SK_WHEN(T::kTags & SkRecords::kDraw_Tag, void) operator()(const T& op) {
1224        SkPictureRecorder rec;
1225        this->draw(op, rec.beginRecording(SkRect::MakeLargest()));
1226        SkAutoTUnref<SkPicture> pic(rec.endRecordingAsPicture());
1227        fCanvas->drawPicture(pic);
1228    }
1229
1230    // We'll just issue non-draws directly.
1231    template <typename T>
1232    skstd::enable_if_t<!(T::kTags & SkRecords::kDraw_Tag), void> operator()(const T& op) {
1233        this->draw(op, fCanvas);
1234    }
1235};
1236
1237// Record Src into a picture, then record it into a macro picture with a sub-picture for each draw.
1238// Then play back that macro picture into our wrapped sink.
1239Error ViaSingletonPictures::draw(
1240        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
1241    auto size = src.size();
1242    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
1243        // Use low-level (Skia-private) recording APIs so we can read the SkRecord.
1244        SkRecord skr;
1245        SkRecorder recorder(&skr, size.width(), size.height());
1246        Error err = src.draw(&recorder);
1247        if (!err.isEmpty()) {
1248            return err;
1249        }
1250
1251        // Record our macro-picture, with each draw op as its own sub-picture.
1252        SkPictureRecorder macroRec;
1253        SkCanvas* macroCanvas = macroRec.beginRecording(SkIntToScalar(size.width()),
1254                                                        SkIntToScalar(size.height()));
1255
1256        SkAutoTDelete<SkDrawableList> drawables(recorder.detachDrawableList());
1257        const SkDrawableList empty;
1258
1259        DrawsAsSingletonPictures drawsAsSingletonPictures = {
1260            macroCanvas,
1261            drawables ? *drawables : empty,
1262        };
1263        for (int i = 0; i < skr.count(); i++) {
1264            skr.visit<void>(i, drawsAsSingletonPictures);
1265        }
1266        SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture());
1267
1268        canvas->drawPicture(macroPic);
1269        return "";
1270    });
1271}
1272
1273}  // namespace DM
1274