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