Home | History | Annotate | Download | only in dm
      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 
     39 DEFINE_bool(multiPage, false, "For document-type backends, render the source"
     40             " into multiple pages");
     41 DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?");
     42 
     43 namespace DM {
     44 
     45 GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
     46 
     47 Error 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 
     54 SkISize GMSrc::size() const {
     55     SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
     56     return gm->getISize();
     57 }
     58 
     59 Name GMSrc::name() const {
     60     SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
     61     return gm->getName();
     62 }
     63 
     64 void GMSrc::modifyGrContextOptions(GrContextOptions* options) const {
     65     SkAutoTDelete<skiagm::GM> gm(fFactory(nullptr));
     66     gm->modifyGrContextOptions(options);
     67 }
     68 
     69 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
     70 
     71 BRDSrc::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 
     80 bool 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 
     86 static 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 
     95 Error 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 
    213 SkISize 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 
    222 static SkString get_scaled_name(const Path& path, float scale) {
    223     return SkStringPrintf("%s_%.3f", SkOSPath::Basename(path.c_str()).c_str(), scale);
    224 }
    225 
    226 Name 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 
    237 static 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 
    256 CodecSrc::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 
    266 bool 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.
    281 void 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 
    309 bool 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 
    337 Error 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 
    361 Error 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 
    625 SkISize 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 
    634 Name 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 
    643 AndroidCodecSrc::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 
    653 bool 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 
    659 Error 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 
    786 SkISize 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 
    795 Name 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 
    806 static const SkRect kSKPViewport = {0,0, 1000,1000};
    807 
    808 SKPSrc::SKPSrc(Path path) : fPath(path) {}
    809 
    810 Error 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 
    826 SkISize 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 
    842 Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
    843 
    844 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    845 
    846 Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
    847     SkAutoTDelete<SkCanvas> canvas(SkCreateNullCanvas());
    848     return src.draw(canvas);
    849 }
    850 
    851 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    852 
    853 DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
    854 
    855 GPUSink::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 
    866 void PreAbandonGpuContextErrorHandler(SkError, void*) {}
    867 
    868 DEFINE_bool(imm, false, "Run gpu configs in immediate mode.");
    869 DEFINE_bool(batchClip, false, "Clip each GrBatch to its device bounds for testing.");
    870 DEFINE_bool(batchBounds, false, "Draw a wireframe bounds of each GrBatch.");
    871 DEFINE_int32(batchLookback, -1, "Maximum GrBatch lookback for combining, negative means default.");
    872 
    873 Error 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 
    923 static 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 
    975 PDFSink::PDFSink(const char* rasterizer) : fRasterizer(rasterizer) {}
    976 
    977 Error 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 
    996 XPSSink::XPSSink() {}
    997 
    998 Error 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 
   1007 SKPSink::SKPSink() {}
   1008 
   1009 Error 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 
   1024 SVGSink::SVGSink() {}
   1025 
   1026 Error 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 
   1036 RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
   1037 
   1038 Error 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 
   1058 template <typename Fn>
   1059 static 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 
   1076 DEFINE_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?
   1079 static 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 
   1106 static 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 
   1113 ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
   1114 
   1115 Error 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.
   1126 ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
   1127 
   1128 Error 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 
   1161 Error 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 
   1173 Error 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 
   1199 ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
   1200     : Via(sink)
   1201     , fW(w)
   1202     , fH(h)
   1203     , fFactory(factory) {}
   1204 
   1205 Error 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 
   1253 Error 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.
   1273 Error 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.
   1295 Error 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.
   1363 struct 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.
   1394 Error 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