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