1478652e918d73a4c0330e27e03eaa9564138c0f7scroggo/*
2478652e918d73a4c0330e27e03eaa9564138c0f7scroggo * Copyright 2015 Google Inc.
3478652e918d73a4c0330e27e03eaa9564138c0f7scroggo *
4478652e918d73a4c0330e27e03eaa9564138c0f7scroggo * Use of this source code is governed by a BSD-style license that can be
5478652e918d73a4c0330e27e03eaa9564138c0f7scroggo * found in the LICENSE file.
6478652e918d73a4c0330e27e03eaa9564138c0f7scroggo */
7478652e918d73a4c0330e27e03eaa9564138c0f7scroggo
8748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "DMSrcSink.h"
9748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "SamplePipeControllers.h"
10f24f2247c25b842327e12c70e44efe4cc1b28dfascroggo#include "SkCodec.h"
11a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein#include "SkCommonFlags.h"
12b3e5e4d314301617d2d48b7589dfd426bd68a671mtklein#include "SkData.h"
1306a22f618cd2adbbd33634a701b5cf8353886d63reed#include "SkDeferredCanvas.h"
14748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "SkDocument.h"
155f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt#include "SkError.h"
16e44b5084d86772727826e65b8e95e17dc53ee977mtklein#include "SkFunction.h"
17b3e5e4d314301617d2d48b7589dfd426bd68a671mtklein#include "SkImageGenerator.h"
18748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "SkMultiPictureDraw.h"
19ad66f9b15fd44468b5f013534ee333dc68d6bed6mtklein#include "SkNullCanvas.h"
20748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "SkOSFile.h"
21ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein#include "SkPictureData.h"
22748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "SkPictureRecorder.h"
23748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "SkRandom.h"
24d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein#include "SkRecordDraw.h"
25d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein#include "SkRecorder.h"
262aafe6f427f6d98aa4d173efc6195fe245add91dfmalita#include "SkSVGCanvas.h"
27a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein#include "SkScanlineDecoder.h"
28a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo#include "SkStream.h"
292aafe6f427f6d98aa4d173efc6195fe245add91dfmalita#include "SkXMLWriter.h"
30748ca3bf2d170708f263693e8579e6722389d0efmtklein
317e79818137f2173302d6476a6127525b11684ec2halcanaryDEFINE_bool(multiPage, false, "For document-type backends, render the source"
327e79818137f2173302d6476a6127525b11684ec2halcanary            " into multiple pages");
337e79818137f2173302d6476a6127525b11684ec2halcanary
34b3e5e4d314301617d2d48b7589dfd426bd68a671mtkleinstatic bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) {
35b3e5e4d314301617d2d48b7589dfd426bd68a671mtklein    SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size));
36b3e5e4d314301617d2d48b7589dfd426bd68a671mtklein    return encoded && SkInstallDiscardablePixelRef(encoded, dst);
37b3e5e4d314301617d2d48b7589dfd426bd68a671mtklein}
38b3e5e4d314301617d2d48b7589dfd426bd68a671mtklein
39748ca3bf2d170708f263693e8579e6722389d0efmtkleinnamespace DM {
40748ca3bf2d170708f263693e8579e6722389d0efmtklein
41748ca3bf2d170708f263693e8579e6722389d0efmtkleinGMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
42748ca3bf2d170708f263693e8579e6722389d0efmtklein
43748ca3bf2d170708f263693e8579e6722389d0efmtkleinError GMSrc::draw(SkCanvas* canvas) const {
44748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
45748ca3bf2d170708f263693e8579e6722389d0efmtklein    canvas->concat(gm->getInitialTransform());
46748ca3bf2d170708f263693e8579e6722389d0efmtklein    gm->draw(canvas);
47748ca3bf2d170708f263693e8579e6722389d0efmtklein    return "";
48748ca3bf2d170708f263693e8579e6722389d0efmtklein}
49748ca3bf2d170708f263693e8579e6722389d0efmtklein
50748ca3bf2d170708f263693e8579e6722389d0efmtkleinSkISize GMSrc::size() const {
51748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
52748ca3bf2d170708f263693e8579e6722389d0efmtklein    return gm->getISize();
53748ca3bf2d170708f263693e8579e6722389d0efmtklein}
54748ca3bf2d170708f263693e8579e6722389d0efmtklein
55748ca3bf2d170708f263693e8579e6722389d0efmtkleinName GMSrc::name() const {
56748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
57748ca3bf2d170708f263693e8579e6722389d0efmtklein    return gm->getName();
58748ca3bf2d170708f263693e8579e6722389d0efmtklein}
59748ca3bf2d170708f263693e8579e6722389d0efmtklein
60748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
61748ca3bf2d170708f263693e8579e6722389d0efmtklein
62438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarettCodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType)
63438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    : fPath(path)
64438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    , fMode(mode)
65438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    , fDstColorType(dstColorType)
66438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett{}
679b77ddde08efe702256355a333cf31ade8f15bb0scroggo
689b77ddde08efe702256355a333cf31ade8f15bb0scroggoError CodecSrc::draw(SkCanvas* canvas) const {
699b77ddde08efe702256355a333cf31ade8f15bb0scroggo    SkImageInfo canvasInfo;
709b77ddde08efe702256355a333cf31ade8f15bb0scroggo    if (NULL == canvas->peekPixels(&canvasInfo, NULL)) {
719b77ddde08efe702256355a333cf31ade8f15bb0scroggo        // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferred decode to
729b77ddde08efe702256355a333cf31ade8f15bb0scroggo        // let the GPU handle it.
739b77ddde08efe702256355a333cf31ade8f15bb0scroggo        return Error::Nonfatal("No need to test decoding to non-raster backend.");
749b77ddde08efe702256355a333cf31ade8f15bb0scroggo    }
759b77ddde08efe702256355a333cf31ade8f15bb0scroggo
769b77ddde08efe702256355a333cf31ade8f15bb0scroggo    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
779b77ddde08efe702256355a333cf31ade8f15bb0scroggo    if (!encoded) {
789b77ddde08efe702256355a333cf31ade8f15bb0scroggo        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
799b77ddde08efe702256355a333cf31ade8f15bb0scroggo    }
809b77ddde08efe702256355a333cf31ade8f15bb0scroggo    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
81438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if (NULL == codec.get()) {
82438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str());
83438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    }
84438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
85438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Choose the color type to decode to
86438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    SkImageInfo decodeInfo = codec->getInfo();
87438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    SkColorType canvasColorType = canvasInfo.colorType();
88438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    switch (fDstColorType) {
89438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        case kIndex8_Always_DstColorType:
90e16b04aa6041efb6507546547737e9603fa1606emsarett            decodeInfo = codec->getInfo().makeColorType(kIndex_8_SkColorType);
91e16b04aa6041efb6507546547737e9603fa1606emsarett            if (kRGB_565_SkColorType == canvasColorType) {
92e16b04aa6041efb6507546547737e9603fa1606emsarett                return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
93e16b04aa6041efb6507546547737e9603fa1606emsarett            }
94e16b04aa6041efb6507546547737e9603fa1606emsarett            break;
95438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        case kGrayscale_Always_DstColorType:
96e16b04aa6041efb6507546547737e9603fa1606emsarett            decodeInfo = codec->getInfo().makeColorType(kGray_8_SkColorType);
97438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            if (kRGB_565_SkColorType == canvasColorType) {
98438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                return Error::Nonfatal("Testing non-565 to 565 is uninteresting.");
99438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            }
100438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            break;
101438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        default:
102438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            decodeInfo = decodeInfo.makeColorType(canvasColorType);
103438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            break;
104438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    }
105438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
106438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Construct a color table for the decode if necessary
107438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    SkAutoTUnref<SkColorTable> colorTable(NULL);
108438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    SkPMColor* colorPtr = NULL;
109438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    int* colorCountPtr = NULL;
110438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    int maxColors = 256;
111438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if (kIndex_8_SkColorType == decodeInfo.colorType()) {
112438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        SkPMColor colors[256];
113438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        colorTable.reset(SkNEW_ARGS(SkColorTable, (colors, maxColors)));
114438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
115438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        colorCountPtr = &maxColors;
1169b77ddde08efe702256355a333cf31ade8f15bb0scroggo    }
1179b77ddde08efe702256355a333cf31ade8f15bb0scroggo
118438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // FIXME: Currently we cannot draw unpremultiplied sources.
1199b77ddde08efe702256355a333cf31ade8f15bb0scroggo    if (decodeInfo.alphaType() == kUnpremul_SkAlphaType) {
1209b77ddde08efe702256355a333cf31ade8f15bb0scroggo        decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType);
1219b77ddde08efe702256355a333cf31ade8f15bb0scroggo    }
1229b77ddde08efe702256355a333cf31ade8f15bb0scroggo
1239b77ddde08efe702256355a333cf31ade8f15bb0scroggo    SkBitmap bitmap;
124438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if (!bitmap.tryAllocPixels(decodeInfo, NULL, colorTable.get())) {
1259b77ddde08efe702256355a333cf31ade8f15bb0scroggo        return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(),
1269b77ddde08efe702256355a333cf31ade8f15bb0scroggo                              decodeInfo.width(), decodeInfo.height());
1279b77ddde08efe702256355a333cf31ade8f15bb0scroggo    }
1289b77ddde08efe702256355a333cf31ade8f15bb0scroggo
1299c59ebc0db7cade1537591813430f7be47123e76scroggo    switch (fMode) {
1309c59ebc0db7cade1537591813430f7be47123e76scroggo        case kNormal_Mode:
131438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), NULL,
132438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                    colorPtr, colorCountPtr)) {
1339c59ebc0db7cade1537591813430f7be47123e76scroggo                case SkImageGenerator::kSuccess:
1349c59ebc0db7cade1537591813430f7be47123e76scroggo                    // We consider incomplete to be valid, since we should still decode what is
1359c59ebc0db7cade1537591813430f7be47123e76scroggo                    // available.
1369c59ebc0db7cade1537591813430f7be47123e76scroggo                case SkImageGenerator::kIncompleteInput:
1379c59ebc0db7cade1537591813430f7be47123e76scroggo                    break;
1389c59ebc0db7cade1537591813430f7be47123e76scroggo                case SkImageGenerator::kInvalidConversion:
1399c59ebc0db7cade1537591813430f7be47123e76scroggo                    return Error::Nonfatal("Incompatible colortype conversion");
1409c59ebc0db7cade1537591813430f7be47123e76scroggo                default:
1419c59ebc0db7cade1537591813430f7be47123e76scroggo                    // Everything else is considered a failure.
1429c59ebc0db7cade1537591813430f7be47123e76scroggo                    return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
1439c59ebc0db7cade1537591813430f7be47123e76scroggo            }
1449c59ebc0db7cade1537591813430f7be47123e76scroggo            break;
1459c59ebc0db7cade1537591813430f7be47123e76scroggo        case kScanline_Mode: {
1469e43cabaa1ff26167e990f0bcb9a5c20d662d52cmsarett            SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecoder(decodeInfo, NULL,
1479e43cabaa1ff26167e990f0bcb9a5c20d662d52cmsarett                    colorPtr, colorCountPtr);
1489c59ebc0db7cade1537591813430f7be47123e76scroggo            if (NULL == scanlineDecoder) {
1499c59ebc0db7cade1537591813430f7be47123e76scroggo                return Error::Nonfatal("Cannot use scanline decoder for all images");
1509c59ebc0db7cade1537591813430f7be47123e76scroggo            }
1519c59ebc0db7cade1537591813430f7be47123e76scroggo            for (int y = 0; y < decodeInfo.height(); ++y) {
1529c59ebc0db7cade1537591813430f7be47123e76scroggo                const SkImageGenerator::Result result = scanlineDecoder->getScanlines(
1539c59ebc0db7cade1537591813430f7be47123e76scroggo                        bitmap.getAddr(0, y), 1, 0);
1549c59ebc0db7cade1537591813430f7be47123e76scroggo                switch (result) {
1559c59ebc0db7cade1537591813430f7be47123e76scroggo                    case SkImageGenerator::kSuccess:
1569c59ebc0db7cade1537591813430f7be47123e76scroggo                    case SkImageGenerator::kIncompleteInput:
1579c59ebc0db7cade1537591813430f7be47123e76scroggo                        break;
1589c59ebc0db7cade1537591813430f7be47123e76scroggo                    default:
1599c59ebc0db7cade1537591813430f7be47123e76scroggo                        return SkStringPrintf("%s failed after %d scanlines with error message %d",
1609c59ebc0db7cade1537591813430f7be47123e76scroggo                                              fPath.c_str(), y-1, (int) result);
1619c59ebc0db7cade1537591813430f7be47123e76scroggo                }
1629c59ebc0db7cade1537591813430f7be47123e76scroggo            }
1639c59ebc0db7cade1537591813430f7be47123e76scroggo            break;
1649c59ebc0db7cade1537591813430f7be47123e76scroggo        }
1659b77ddde08efe702256355a333cf31ade8f15bb0scroggo    }
1669c59ebc0db7cade1537591813430f7be47123e76scroggo    canvas->drawBitmap(bitmap, 0, 0);
1679c59ebc0db7cade1537591813430f7be47123e76scroggo    return "";
1689b77ddde08efe702256355a333cf31ade8f15bb0scroggo}
1699b77ddde08efe702256355a333cf31ade8f15bb0scroggo
1709b77ddde08efe702256355a333cf31ade8f15bb0scroggoSkISize CodecSrc::size() const {
1719b77ddde08efe702256355a333cf31ade8f15bb0scroggo    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
1729b77ddde08efe702256355a333cf31ade8f15bb0scroggo    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
1739bde918754bc292469d801f156f3b626eb3db780msarett    if (NULL != codec) {
1749bde918754bc292469d801f156f3b626eb3db780msarett        return codec->getInfo().dimensions();
1759bde918754bc292469d801f156f3b626eb3db780msarett    } else {
1769bde918754bc292469d801f156f3b626eb3db780msarett        return SkISize::Make(0, 0);
1779bde918754bc292469d801f156f3b626eb3db780msarett    }
1789b77ddde08efe702256355a333cf31ade8f15bb0scroggo}
1799b77ddde08efe702256355a333cf31ade8f15bb0scroggo
1809b77ddde08efe702256355a333cf31ade8f15bb0scroggoName CodecSrc::name() const {
1819b77ddde08efe702256355a333cf31ade8f15bb0scroggo    return SkOSPath::Basename(fPath.c_str());
1829b77ddde08efe702256355a333cf31ade8f15bb0scroggo}
1839b77ddde08efe702256355a333cf31ade8f15bb0scroggo
1849b77ddde08efe702256355a333cf31ade8f15bb0scroggo/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1859b77ddde08efe702256355a333cf31ade8f15bb0scroggo
186edc93bc74003e2c19219ba0b30383868b5371a96mtkleinImageSrc::ImageSrc(Path path, int divisor) : fPath(path), fDivisor(divisor) {}
187748ca3bf2d170708f263693e8579e6722389d0efmtklein
188748ca3bf2d170708f263693e8579e6722389d0efmtkleinError ImageSrc::draw(SkCanvas* canvas) const {
1899b77ddde08efe702256355a333cf31ade8f15bb0scroggo    SkImageInfo canvasInfo;
1909b77ddde08efe702256355a333cf31ade8f15bb0scroggo    if (NULL == canvas->peekPixels(&canvasInfo, NULL)) {
1919b77ddde08efe702256355a333cf31ade8f15bb0scroggo        // TODO: Instead, use lazy decoding to allow the GPU to handle cases like YUV.
1929b77ddde08efe702256355a333cf31ade8f15bb0scroggo        return Error::Nonfatal("No need to test decoding to non-raster backend.");
1939b77ddde08efe702256355a333cf31ade8f15bb0scroggo    }
1949b77ddde08efe702256355a333cf31ade8f15bb0scroggo
19575d98fd6f23fc73aad3ce87d6c4b6c41c2d1536emtklein    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
196748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (!encoded) {
197748ca3bf2d170708f263693e8579e6722389d0efmtklein        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
198748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
1999b77ddde08efe702256355a333cf31ade8f15bb0scroggo    const SkColorType dstColorType = canvasInfo.colorType();
200edc93bc74003e2c19219ba0b30383868b5371a96mtklein    if (fDivisor == 0) {
201748ca3bf2d170708f263693e8579e6722389d0efmtklein        // Decode the full image.
202748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkBitmap bitmap;
2039b77ddde08efe702256355a333cf31ade8f15bb0scroggo        if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap,
2049b77ddde08efe702256355a333cf31ade8f15bb0scroggo                                          dstColorType, SkImageDecoder::kDecodePixels_Mode)) {
2059b77ddde08efe702256355a333cf31ade8f15bb0scroggo            return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
2069b77ddde08efe702256355a333cf31ade8f15bb0scroggo        }
2079b77ddde08efe702256355a333cf31ade8f15bb0scroggo        if (kRGB_565_SkColorType == dstColorType && !bitmap.isOpaque()) {
2089b77ddde08efe702256355a333cf31ade8f15bb0scroggo            // Do not draw a bitmap with alpha to a destination without alpha.
2099b77ddde08efe702256355a333cf31ade8f15bb0scroggo            return Error::Nonfatal("Uninteresting to decode image with alpha into 565.");
210748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
21175d98fd6f23fc73aad3ce87d6c4b6c41c2d1536emtklein        encoded.reset((SkData*)NULL);  // Might as well drop this when we're done with it.
212748ca3bf2d170708f263693e8579e6722389d0efmtklein        canvas->drawBitmap(bitmap, 0,0);
213748ca3bf2d170708f263693e8579e6722389d0efmtklein        return "";
214748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
215edc93bc74003e2c19219ba0b30383868b5371a96mtklein    // Decode subsets.  This is a little involved.
216a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo    SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
217a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream.get()));
218748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (!decoder) {
219748ca3bf2d170708f263693e8579e6722389d0efmtklein        return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str());
220748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
221a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo    stream->rewind();
222748ca3bf2d170708f263693e8579e6722389d0efmtklein    int w,h;
223a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo    if (!decoder->buildTileIndex(stream.detach(), &w, &h) || w*h == 1) {
2244089ef7c982592fadeec441438c551ffb4c746bemtklein        return Error::Nonfatal("Subset decoding not supported.");
225748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
226edc93bc74003e2c19219ba0b30383868b5371a96mtklein
227edc93bc74003e2c19219ba0b30383868b5371a96mtklein    // Divide the image into subsets that cover the entire image.
228edc93bc74003e2c19219ba0b30383868b5371a96mtklein    if (fDivisor > w || fDivisor > h) {
229edc93bc74003e2c19219ba0b30383868b5371a96mtklein        return SkStringPrintf("divisor %d is too big for %s with dimensions (%d x %d)",
230edc93bc74003e2c19219ba0b30383868b5371a96mtklein                              fDivisor, fPath.c_str(), w, h);
231edc93bc74003e2c19219ba0b30383868b5371a96mtklein    }
232edc93bc74003e2c19219ba0b30383868b5371a96mtklein    const int subsetWidth  = w / fDivisor,
233edc93bc74003e2c19219ba0b30383868b5371a96mtklein              subsetHeight = h / fDivisor;
234edc93bc74003e2c19219ba0b30383868b5371a96mtklein    for (int y = 0; y < h; y += subsetHeight) {
235edc93bc74003e2c19219ba0b30383868b5371a96mtklein        for (int x = 0; x < w; x += subsetWidth) {
236edc93bc74003e2c19219ba0b30383868b5371a96mtklein            SkBitmap subset;
237edc93bc74003e2c19219ba0b30383868b5371a96mtklein            SkIRect rect = SkIRect::MakeXYWH(x, y, subsetWidth, subsetHeight);
238edc93bc74003e2c19219ba0b30383868b5371a96mtklein            if (!decoder->decodeSubset(&subset, rect, dstColorType)) {
239edc93bc74003e2c19219ba0b30383868b5371a96mtklein                return SkStringPrintf("Could not decode subset (%d, %d, %d, %d).",
240edc93bc74003e2c19219ba0b30383868b5371a96mtklein                                      x, y, x+subsetWidth, y+subsetHeight);
241edc93bc74003e2c19219ba0b30383868b5371a96mtklein            }
24256e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo            if (kRGB_565_SkColorType == dstColorType && !subset.isOpaque()) {
24356e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo                // Do not draw a bitmap with alpha to a destination without alpha.
24456e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo                // This is not an error, but there is nothing interesting to show.
24556e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo
24656e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo                // This should only happen on the first iteration through the loop.
24756e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo                SkASSERT(0 == x && 0 == y);
24856e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo
24956e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo                return Error::Nonfatal("Uninteresting to decode image with alpha into 565.");
25056e25ddf6e2c1f85c5addbe498a082268ebee6eascroggo            }
251edc93bc74003e2c19219ba0b30383868b5371a96mtklein            canvas->drawBitmap(subset, SkIntToScalar(x), SkIntToScalar(y));
252748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
253748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
254748ca3bf2d170708f263693e8579e6722389d0efmtklein    return "";
255748ca3bf2d170708f263693e8579e6722389d0efmtklein}
256748ca3bf2d170708f263693e8579e6722389d0efmtklein
257748ca3bf2d170708f263693e8579e6722389d0efmtkleinSkISize ImageSrc::size() const {
25875d98fd6f23fc73aad3ce87d6c4b6c41c2d1536emtklein    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
2599b77ddde08efe702256355a333cf31ade8f15bb0scroggo    SkBitmap bitmap;
2609b77ddde08efe702256355a333cf31ade8f15bb0scroggo    if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
2619b77ddde08efe702256355a333cf31ade8f15bb0scroggo                                                  encoded->size(),
2629b77ddde08efe702256355a333cf31ade8f15bb0scroggo                                                  &bitmap,
2639b77ddde08efe702256355a333cf31ade8f15bb0scroggo                                                  kUnknown_SkColorType,
2649b77ddde08efe702256355a333cf31ade8f15bb0scroggo                                                  SkImageDecoder::kDecodeBounds_Mode)) {
2659b77ddde08efe702256355a333cf31ade8f15bb0scroggo        return SkISize::Make(0,0);
266748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
2679b77ddde08efe702256355a333cf31ade8f15bb0scroggo    return bitmap.dimensions();
268748ca3bf2d170708f263693e8579e6722389d0efmtklein}
269748ca3bf2d170708f263693e8579e6722389d0efmtklein
2709264a95608c08623f2955823703e5c77558cafa8mtkleinName ImageSrc::name() const {
271edc93bc74003e2c19219ba0b30383868b5371a96mtklein    return SkOSPath::Basename(fPath.c_str());
2729264a95608c08623f2955823703e5c77558cafa8mtklein}
273748ca3bf2d170708f263693e8579e6722389d0efmtklein
274748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
275748ca3bf2d170708f263693e8579e6722389d0efmtklein
276f4ba3219c2d46f41f26876a14c484c4fc581286amtkleinstatic const SkRect kSKPViewport = {0,0, 1000,1000};
277f4ba3219c2d46f41f26876a14c484c4fc581286amtklein
2788d17a13a71edb0d8412e4354c428582b74587b79mtkleinSKPSrc::SKPSrc(Path path) : fPath(path) {}
279748ca3bf2d170708f263693e8579e6722389d0efmtklein
280748ca3bf2d170708f263693e8579e6722389d0efmtkleinError SKPSrc::draw(SkCanvas* canvas) const {
281a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
28275d98fd6f23fc73aad3ce87d6c4b6c41c2d1536emtklein    if (!stream) {
283748ca3bf2d170708f263693e8579e6722389d0efmtklein        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
284748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
285b3e5e4d314301617d2d48b7589dfd426bd68a671mtklein    SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream, &lazy_decode_bitmap));
28675d98fd6f23fc73aad3ce87d6c4b6c41c2d1536emtklein    if (!pic) {
28775d98fd6f23fc73aad3ce87d6c4b6c41c2d1536emtklein        return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
28875d98fd6f23fc73aad3ce87d6c4b6c41c2d1536emtklein    }
28975d98fd6f23fc73aad3ce87d6c4b6c41c2d1536emtklein    stream.reset((SkStream*)NULL);  // Might as well drop this when we're done with it.
2907c3a2f834e0ba3f11a3129d5348b393efcc9b0e1joshualitt
291f4ba3219c2d46f41f26876a14c484c4fc581286amtklein    canvas->clipRect(kSKPViewport);
292748ca3bf2d170708f263693e8579e6722389d0efmtklein    canvas->drawPicture(pic);
293748ca3bf2d170708f263693e8579e6722389d0efmtklein    return "";
294748ca3bf2d170708f263693e8579e6722389d0efmtklein}
295748ca3bf2d170708f263693e8579e6722389d0efmtklein
296748ca3bf2d170708f263693e8579e6722389d0efmtkleinSkISize SKPSrc::size() const {
297ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
298ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    if (!stream) {
299ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein        return SkISize::Make(0,0);
300ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    }
301ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    SkPictInfo info;
302ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    if (!SkPicture::InternalOnly_StreamIsSKP(stream, &info)) {
303ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein        return SkISize::Make(0,0);
304ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    }
305ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    SkRect viewport = kSKPViewport;
306ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    if (!viewport.intersect(info.fCullRect)) {
307ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein        return SkISize::Make(0,0);
308ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    }
309ffa901aa7e360ed5115a0955221f4c2d2632d418mtklein    return viewport.roundOut().size();
310748ca3bf2d170708f263693e8579e6722389d0efmtklein}
311748ca3bf2d170708f263693e8579e6722389d0efmtklein
312748ca3bf2d170708f263693e8579e6722389d0efmtkleinName SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
313748ca3bf2d170708f263693e8579e6722389d0efmtklein
314748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
315748ca3bf2d170708f263693e8579e6722389d0efmtklein
316ad66f9b15fd44468b5f013534ee333dc68d6bed6mtkleinError NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
317ad66f9b15fd44468b5f013534ee333dc68d6bed6mtklein    SkAutoTDelete<SkCanvas> canvas(SkCreateNullCanvas());
318ad66f9b15fd44468b5f013534ee333dc68d6bed6mtklein    return src.draw(canvas);
319ad66f9b15fd44468b5f013534ee333dc68d6bed6mtklein}
320ad66f9b15fd44468b5f013534ee333dc68d6bed6mtklein
321ad66f9b15fd44468b5f013534ee333dc68d6bed6mtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
322ad66f9b15fd44468b5f013534ee333dc68d6bed6mtklein
323b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinDEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
324b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein
32582d2843cc59dc048b7d8d1d928dab743d8e85a3bmtkleinGPUSink::GPUSink(GrContextFactory::GLContextType ct,
32682d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein                 GrGLStandard api,
32782d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein                 int samples,
32882d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein                 bool dfText,
32982d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein                 bool threaded)
330748ca3bf2d170708f263693e8579e6722389d0efmtklein    : fContextType(ct)
331748ca3bf2d170708f263693e8579e6722389d0efmtklein    , fGpuAPI(api)
332748ca3bf2d170708f263693e8579e6722389d0efmtklein    , fSampleCount(samples)
33382d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein    , fUseDFText(dfText)
33482d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein    , fThreaded(threaded) {}
335748ca3bf2d170708f263693e8579e6722389d0efmtklein
336748ca3bf2d170708f263693e8579e6722389d0efmtkleinint GPUSink::enclave() const {
33755e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    return fThreaded ? kAnyThread_Enclave : kGPU_Enclave;
338748ca3bf2d170708f263693e8579e6722389d0efmtklein}
339748ca3bf2d170708f263693e8579e6722389d0efmtklein
3405f5a8d7599b8e248633ac122294b7a01401fedcbjoshualittvoid PreAbandonGpuContextErrorHandler(SkError, void*) {}
3415f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt
342b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinError GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
34355e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    GrContextFactory factory;
344f4ba3219c2d46f41f26876a14c484c4fc581286amtklein    const SkISize size = src.size();
345748ca3bf2d170708f263693e8579e6722389d0efmtklein    const SkImageInfo info =
346748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
347748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAutoTUnref<SkSurface> surface(
34855e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein            NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
349748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (!surface) {
350748ca3bf2d170708f263693e8579e6722389d0efmtklein        return "Could not create a surface.";
351748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
3525f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt    if (FLAGS_preAbandonGpuContext) {
3535f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt        SkSetErrorCallback(&PreAbandonGpuContextErrorHandler, NULL);
3545f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt        factory.abandonContexts();
3555f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt    }
356748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkCanvas* canvas = surface->getCanvas();
357748ca3bf2d170708f263693e8579e6722389d0efmtklein    Error err = src.draw(canvas);
358748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (!err.isEmpty()) {
359748ca3bf2d170708f263693e8579e6722389d0efmtklein        return err;
360748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
361748ca3bf2d170708f263693e8579e6722389d0efmtklein    canvas->flush();
362b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein    if (FLAGS_gpuStats) {
363b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein        canvas->getGrContext()->dumpCacheStats(log);
364b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein        canvas->getGrContext()->dumpGpuStats(log);
365b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein    }
366748ca3bf2d170708f263693e8579e6722389d0efmtklein    dst->allocPixels(info);
3675f5a8d7599b8e248633ac122294b7a01401fedcbjoshualitt    canvas->readPixels(dst, 0, 0);
36855e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    if (FLAGS_abandonGpuContext) {
36955e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein        factory.abandonContexts();
37055e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    }
371748ca3bf2d170708f263693e8579e6722389d0efmtklein    return "";
372748ca3bf2d170708f263693e8579e6722389d0efmtklein}
373748ca3bf2d170708f263693e8579e6722389d0efmtklein
374748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
375748ca3bf2d170708f263693e8579e6722389d0efmtklein
37647ef4d5d934bba86848aa238efab21f54a160c1ahalcanarystatic Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
37747ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    // Print the given DM:Src to a document, breaking on 8.5x11 pages.
37847ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    SkASSERT(doc);
379fd4a993f8b162f6ca541514234a81759b67dc64dhalcanary    int width  = src.size().width(),
380fd4a993f8b162f6ca541514234a81759b67dc64dhalcanary        height = src.size().height();
381fd4a993f8b162f6ca541514234a81759b67dc64dhalcanary
3827e79818137f2173302d6476a6127525b11684ec2halcanary    if (FLAGS_multiPage) {
3837e79818137f2173302d6476a6127525b11684ec2halcanary        const int kLetterWidth = 612,  // 8.5 * 72
3847e79818137f2173302d6476a6127525b11684ec2halcanary                kLetterHeight = 792;   // 11 * 72
3857e79818137f2173302d6476a6127525b11684ec2halcanary        const SkRect letter = SkRect::MakeWH(SkIntToScalar(kLetterWidth),
3867e79818137f2173302d6476a6127525b11684ec2halcanary                                             SkIntToScalar(kLetterHeight));
3877e79818137f2173302d6476a6127525b11684ec2halcanary
3887e79818137f2173302d6476a6127525b11684ec2halcanary        int xPages = ((width - 1) / kLetterWidth) + 1;
3897e79818137f2173302d6476a6127525b11684ec2halcanary        int yPages = ((height - 1) / kLetterHeight) + 1;
3907e79818137f2173302d6476a6127525b11684ec2halcanary
3917e79818137f2173302d6476a6127525b11684ec2halcanary        for (int y = 0; y < yPages; ++y) {
3927e79818137f2173302d6476a6127525b11684ec2halcanary            for (int x = 0; x < xPages; ++x) {
3937e79818137f2173302d6476a6127525b11684ec2halcanary                int w = SkTMin(kLetterWidth, width - (x * kLetterWidth));
3947e79818137f2173302d6476a6127525b11684ec2halcanary                int h = SkTMin(kLetterHeight, height - (y * kLetterHeight));
3957e79818137f2173302d6476a6127525b11684ec2halcanary                SkCanvas* canvas =
3967e79818137f2173302d6476a6127525b11684ec2halcanary                        doc->beginPage(SkIntToScalar(w), SkIntToScalar(h));
3977e79818137f2173302d6476a6127525b11684ec2halcanary                if (!canvas) {
3987e79818137f2173302d6476a6127525b11684ec2halcanary                    return "SkDocument::beginPage(w,h) returned NULL";
3997e79818137f2173302d6476a6127525b11684ec2halcanary                }
4007e79818137f2173302d6476a6127525b11684ec2halcanary                canvas->clipRect(letter);
4017e79818137f2173302d6476a6127525b11684ec2halcanary                canvas->translate(-letter.width() * x, -letter.height() * y);
4027e79818137f2173302d6476a6127525b11684ec2halcanary                Error err = src.draw(canvas);
4037e79818137f2173302d6476a6127525b11684ec2halcanary                if (!err.isEmpty()) {
4047e79818137f2173302d6476a6127525b11684ec2halcanary                    return err;
4057e79818137f2173302d6476a6127525b11684ec2halcanary                }
4067e79818137f2173302d6476a6127525b11684ec2halcanary                doc->endPage();
407fd4a993f8b162f6ca541514234a81759b67dc64dhalcanary            }
408fd4a993f8b162f6ca541514234a81759b67dc64dhalcanary        }
4097e79818137f2173302d6476a6127525b11684ec2halcanary    } else {
4107e79818137f2173302d6476a6127525b11684ec2halcanary        SkCanvas* canvas =
4117e79818137f2173302d6476a6127525b11684ec2halcanary                doc->beginPage(SkIntToScalar(width), SkIntToScalar(height));
4127e79818137f2173302d6476a6127525b11684ec2halcanary        if (!canvas) {
4137e79818137f2173302d6476a6127525b11684ec2halcanary            return "SkDocument::beginPage(w,h) returned NULL";
4147e79818137f2173302d6476a6127525b11684ec2halcanary        }
4157e79818137f2173302d6476a6127525b11684ec2halcanary        Error err = src.draw(canvas);
4167e79818137f2173302d6476a6127525b11684ec2halcanary        if (!err.isEmpty()) {
4177e79818137f2173302d6476a6127525b11684ec2halcanary            return err;
4187e79818137f2173302d6476a6127525b11684ec2halcanary        }
4197e79818137f2173302d6476a6127525b11684ec2halcanary        doc->endPage();
4207e79818137f2173302d6476a6127525b11684ec2halcanary    }
4217e79818137f2173302d6476a6127525b11684ec2halcanary    if (!doc->close()) {
4227e79818137f2173302d6476a6127525b11684ec2halcanary        return "SkDocument::close() returned false";
423748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
424fd4a993f8b162f6ca541514234a81759b67dc64dhalcanary    dst->flush();
425748ca3bf2d170708f263693e8579e6722389d0efmtklein    return "";
426748ca3bf2d170708f263693e8579e6722389d0efmtklein}
427748ca3bf2d170708f263693e8579e6722389d0efmtklein
42847ef4d5d934bba86848aa238efab21f54a160c1ahalcanaryPDFSink::PDFSink() {}
42947ef4d5d934bba86848aa238efab21f54a160c1ahalcanary
43047ef4d5d934bba86848aa238efab21f54a160c1ahalcanaryError PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
43147ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
43247ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    if (!doc) {
43347ef4d5d934bba86848aa238efab21f54a160c1ahalcanary        return "SkDocument::CreatePDF() returned NULL";
43447ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    }
43547ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    return draw_skdocument(src, doc.get(), dst);
43647ef4d5d934bba86848aa238efab21f54a160c1ahalcanary}
43747ef4d5d934bba86848aa238efab21f54a160c1ahalcanary
43847ef4d5d934bba86848aa238efab21f54a160c1ahalcanary/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
43947ef4d5d934bba86848aa238efab21f54a160c1ahalcanary
44047ef4d5d934bba86848aa238efab21f54a160c1ahalcanaryXPSSink::XPSSink() {}
44147ef4d5d934bba86848aa238efab21f54a160c1ahalcanary
44247ef4d5d934bba86848aa238efab21f54a160c1ahalcanaryError XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
44347ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    SkAutoTUnref<SkDocument> doc(SkDocument::CreateXPS(dst));
44447ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    if (!doc) {
44547ef4d5d934bba86848aa238efab21f54a160c1ahalcanary        return "SkDocument::CreateXPS() returned NULL";
44647ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    }
44747ef4d5d934bba86848aa238efab21f54a160c1ahalcanary    return draw_skdocument(src, doc.get(), dst);
44847ef4d5d934bba86848aa238efab21f54a160c1ahalcanary}
449748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
450748ca3bf2d170708f263693e8579e6722389d0efmtklein
4519c3f17d6e859a11535f40497cb9f6e777d15f62emtkleinSKPSink::SKPSink() {}
4529c3f17d6e859a11535f40497cb9f6e777d15f62emtklein
453b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinError SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
4549c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    SkSize size;
4559c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    size = src.size();
4569c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    SkPictureRecorder recorder;
4579c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
4589c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    if (!err.isEmpty()) {
4599c3f17d6e859a11535f40497cb9f6e777d15f62emtklein        return err;
4609c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    }
4619c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
4629c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    pic->serialize(dst);
4639c3f17d6e859a11535f40497cb9f6e777d15f62emtklein    return "";
4649c3f17d6e859a11535f40497cb9f6e777d15f62emtklein}
4659c3f17d6e859a11535f40497cb9f6e777d15f62emtklein
4669c3f17d6e859a11535f40497cb9f6e777d15f62emtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4679c3f17d6e859a11535f40497cb9f6e777d15f62emtklein
4688a4527e98a57b1d2dd248a635f0c4fa227be2089mtkleinSVGSink::SVGSink() {}
4698a4527e98a57b1d2dd248a635f0c4fa227be2089mtklein
470b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinError SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
4712aafe6f427f6d98aa4d173efc6195fe245add91dfmalita    SkAutoTDelete<SkXMLWriter> xmlWriter(SkNEW_ARGS(SkXMLStreamWriter, (dst)));
4722aafe6f427f6d98aa4d173efc6195fe245add91dfmalita    SkAutoTUnref<SkCanvas> canvas(SkSVGCanvas::Create(
4732aafe6f427f6d98aa4d173efc6195fe245add91dfmalita        SkRect::MakeWH(SkIntToScalar(src.size().width()), SkIntToScalar(src.size().height())),
4742aafe6f427f6d98aa4d173efc6195fe245add91dfmalita        xmlWriter));
4752aafe6f427f6d98aa4d173efc6195fe245add91dfmalita    return src.draw(canvas);
4768a4527e98a57b1d2dd248a635f0c4fa227be2089mtklein}
4778a4527e98a57b1d2dd248a635f0c4fa227be2089mtklein
4788a4527e98a57b1d2dd248a635f0c4fa227be2089mtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4798a4527e98a57b1d2dd248a635f0c4fa227be2089mtklein
480748ca3bf2d170708f263693e8579e6722389d0efmtkleinRasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
481748ca3bf2d170708f263693e8579e6722389d0efmtklein
482b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinError RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
483f4ba3219c2d46f41f26876a14c484c4fc581286amtklein    const SkISize size = src.size();
484748ca3bf2d170708f263693e8579e6722389d0efmtklein    // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
485748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAlphaType alphaType = kPremul_SkAlphaType;
486748ca3bf2d170708f263693e8579e6722389d0efmtklein    (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
487748ca3bf2d170708f263693e8579e6722389d0efmtklein
488748ca3bf2d170708f263693e8579e6722389d0efmtklein    dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
489748ca3bf2d170708f263693e8579e6722389d0efmtklein    dst->eraseColor(SK_ColorTRANSPARENT);
490748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkCanvas canvas(*dst);
491748ca3bf2d170708f263693e8579e6722389d0efmtklein    return src.draw(&canvas);
492748ca3bf2d170708f263693e8579e6722389d0efmtklein}
493748ca3bf2d170708f263693e8579e6722389d0efmtklein
494748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
495748ca3bf2d170708f263693e8579e6722389d0efmtklein
496a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein// Handy for front-patching a Src.  Do whatever up-front work you need, then call draw_to_canvas(),
497e44b5084d86772727826e65b8e95e17dc53ee977mtklein// passing the Sink draw() arguments, a size, and a function draws into an SkCanvas.
498a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein// Several examples below.
499a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein
500a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtkleinstatic Error draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, SkString* log,
501e44b5084d86772727826e65b8e95e17dc53ee977mtklein                            SkISize size, SkFunction<Error(SkCanvas*)> draw) {
502a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    class ProxySrc : public Src {
503a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    public:
504e44b5084d86772727826e65b8e95e17dc53ee977mtklein        ProxySrc(SkISize size, SkFunction<Error(SkCanvas*)> draw) : fSize(size), fDraw(draw) {}
505a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        Error   draw(SkCanvas* canvas) const override { return fDraw(canvas); }
506a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        Name                    name() const override { sk_throw(); return ""; } // Won't be called.
507a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkISize                 size() const override { return fSize; }
508a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    private:
509e44b5084d86772727826e65b8e95e17dc53ee977mtklein        SkISize                      fSize;
510e44b5084d86772727826e65b8e95e17dc53ee977mtklein        SkFunction<Error(SkCanvas*)> fDraw;
511a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    };
512a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    return sink->draw(ProxySrc(size, draw), bitmap, stream, log);
513a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein}
514a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein
515a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
516a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein
517d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtkleinstatic SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
518d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    SkRect bounds = SkRect::MakeIWH(srcW, srcH);
519d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    matrix->mapRect(&bounds);
520d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    matrix->postTranslate(-bounds.x(), -bounds.y());
521d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    return SkISize::Make(SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height()));
522d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein}
523d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein
5247882924c10fadaed427b6aa65dc7aa6577b94f32mtkleinViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
525748ca3bf2d170708f263693e8579e6722389d0efmtklein
526b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinError ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
527a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    SkMatrix matrix = fMatrix;
528a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
529a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
530a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        canvas->concat(matrix);
531a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        return src.draw(canvas);
532a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    });
533748ca3bf2d170708f263693e8579e6722389d0efmtklein}
534748ca3bf2d170708f263693e8579e6722389d0efmtklein
535d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein// Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
536d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein// This should be pixel-preserving.
5377882924c10fadaed427b6aa65dc7aa6577b94f32mtkleinViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {}
538d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein
539d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtkleinError ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
540d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    Error err = fSink->draw(src, bitmap, stream, log);
541d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    if (!err.isEmpty()) {
542d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        return err;
543d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    }
544d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein
545d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    SkMatrix inverse;
546d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) {
547d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        return "Cannot upright --matrix.";
548d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    }
549d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    SkMatrix upright = SkMatrix::I();
550d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX()));
551d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY()));
552d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX()));
553d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY()));
554d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein
555d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    SkBitmap uprighted;
556d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height());
557d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height()));
558d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein
559d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    SkCanvas canvas(uprighted);
560d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    canvas.concat(upright);
561d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    SkPaint paint;
562d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
563d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    canvas.drawBitmap(*bitmap, 0, 0, &paint);
564d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein
565d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    *bitmap = uprighted;
566d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    bitmap->lockPixels();
567d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    return "";
568d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein}
569d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein
570748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
571748ca3bf2d170708f263693e8579e6722389d0efmtklein
572b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinError ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
573a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    auto size = src.size();
574a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
575a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
576a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkGPipeWriter pipe;
577a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
578a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        return src.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
579a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    });
580748ca3bf2d170708f263693e8579e6722389d0efmtklein}
581748ca3bf2d170708f263693e8579e6722389d0efmtklein
582748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
583a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein
58406a22f618cd2adbbd33634a701b5cf8353886d63reedError ViaDeferred::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
585a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    // We draw via a deferred canvas into a surface that's compatible with the original canvas,
586a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    // then snap that surface as an image and draw it into the original canvas.
587a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error {
588a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkAutoTUnref<SkSurface> surface(canvas->newSurface(canvas->imageInfo()));
589a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        if (!surface.get()) {
590a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein            return "can't make surface for deferred canvas";
591a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        }
592a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkAutoTDelete<SkDeferredCanvas> defcan(SkDeferredCanvas::Create(surface));
593a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        Error err = src.draw(defcan);
594a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        if (!err.isEmpty()) {
595a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein            return err;
596a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        }
597a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkAutoTUnref<SkImage> image(defcan->newImageSnapshot());
598a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        if (!image) {
599a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein            return "failed to create deferred image snapshot";
60006a22f618cd2adbbd33634a701b5cf8353886d63reed        }
601a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        canvas->drawImage(image, 0, 0, NULL);
602a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        return "";
603a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    });
60406a22f618cd2adbbd33634a701b5cf8353886d63reed}
605a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein
60606a22f618cd2adbbd33634a701b5cf8353886d63reed/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
607748ca3bf2d170708f263693e8579e6722389d0efmtklein
608a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtkleinError ViaSerialization::draw(
609a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
610748ca3bf2d170708f263693e8579e6722389d0efmtklein    // Record our Src into a picture.
611a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    auto size = src.size();
612748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkPictureRecorder recorder;
613a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
614a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                                                 SkIntToScalar(size.height())));
615748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (!err.isEmpty()) {
616748ca3bf2d170708f263693e8579e6722389d0efmtklein        return err;
617748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
618748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
619748ca3bf2d170708f263693e8579e6722389d0efmtklein
620748ca3bf2d170708f263693e8579e6722389d0efmtklein    // Serialize it and then deserialize it.
621748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkDynamicMemoryWStream wStream;
622748ca3bf2d170708f263693e8579e6722389d0efmtklein    pic->serialize(&wStream);
623a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo    SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
624b3e5e4d314301617d2d48b7589dfd426bd68a671mtklein    SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream, &lazy_decode_bitmap));
625748ca3bf2d170708f263693e8579e6722389d0efmtklein
626a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) {
627a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        canvas->drawPicture(deserialized);
628a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        return "";
629a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    });
630748ca3bf2d170708f263693e8579e6722389d0efmtklein}
631748ca3bf2d170708f263693e8579e6722389d0efmtklein
632748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
633748ca3bf2d170708f263693e8579e6722389d0efmtklein
634748ca3bf2d170708f263693e8579e6722389d0efmtkleinViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
6357882924c10fadaed427b6aa65dc7aa6577b94f32mtklein    : Via(sink)
6367882924c10fadaed427b6aa65dc7aa6577b94f32mtklein    , fW(w)
637748ca3bf2d170708f263693e8579e6722389d0efmtklein    , fH(h)
6387882924c10fadaed427b6aa65dc7aa6577b94f32mtklein    , fFactory(factory) {}
639748ca3bf2d170708f263693e8579e6722389d0efmtklein
640b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinError ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
641a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    auto size = src.size();
642748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkPictureRecorder recorder;
643a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
644a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                                                 SkIntToScalar(size.height()),
645a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                                                 fFactory.get()));
646748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (!err.isEmpty()) {
647748ca3bf2d170708f263693e8579e6722389d0efmtklein        return err;
648748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
649b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein    SkAutoTUnref<SkPicture> pic(recorder.endRecordingAsPicture());
650748ca3bf2d170708f263693e8579e6722389d0efmtklein
651a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) {
652a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        const int xTiles = (size.width()  + fW - 1) / fW,
653a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                  yTiles = (size.height() + fH - 1) / fH;
654a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkMultiPictureDraw mpd(xTiles*yTiles);
655a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkTDArray<SkSurface*> surfaces;
656a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        surfaces.setReserve(xTiles*yTiles);
657a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein
658a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
659a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        for (int j = 0; j < yTiles; j++) {
660a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein            for (int i = 0; i < xTiles; i++) {
661a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                // This lets our ultimate Sink determine the best kind of surface.
662a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                // E.g., if it's a GpuSink, the surfaces and images are textures.
663a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                SkSurface* s = canvas->newSurface(info);
664a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                if (!s) {
665a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                    s = SkSurface::NewRaster(info);  // Some canvases can't create surfaces.
666748ca3bf2d170708f263693e8579e6722389d0efmtklein                }
667a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                surfaces.push(s);
668a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                SkCanvas* c = s->getCanvas();
669a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                c->translate(SkIntToScalar(-i * fW),
670a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                             SkIntToScalar(-j * fH));  // Line up the canvas with this tile.
671a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                mpd.add(c, pic);
672748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
673a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        }
674a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        mpd.draw();
675a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        for (int j = 0; j < yTiles; j++) {
676a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein            for (int i = 0; i < xTiles; i++) {
677a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
678a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
679748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
680748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
681a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        surfaces.unrefAll();
682a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        return "";
683a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    });
684748ca3bf2d170708f263693e8579e6722389d0efmtklein}
685748ca3bf2d170708f263693e8579e6722389d0efmtklein
686b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
687b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein
688b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein// Draw the Src into two pictures, then draw the second picture into the wrapped Sink.
689b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein// This tests that any shortcuts we may take while recording that second picture are legal.
690b7e8d69fc21a3043348fd9b76876471e0a6ae7femtkleinError ViaSecondPicture::draw(
691b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
692a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    auto size = src.size();
693a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
694a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkPictureRecorder recorder;
695a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        SkAutoTUnref<SkPicture> pic;
696a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        for (int i = 0; i < 2; i++) {
697a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein            Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
698a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                                                         SkIntToScalar(size.height())));
699a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein            if (!err.isEmpty()) {
700a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein                return err;
701b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein            }
702a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein            pic.reset(recorder.endRecordingAsPicture());
703b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein        }
704a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        canvas->drawPicture(pic);
705a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein        return "";
706a16e69ec6ccbaf81671f66ee77ca3b0c07100041mtklein    });
707b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein}
708b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein
709d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
710d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
7116fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein// Draw the Src twice.  This can help exercise caching.
7126fbf4b3a7f0a3304649c482ab0a911dc147a6825mtkleinError ViaTwice::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
7136fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein    return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error {
7146fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein        for (int i = 0; i < 2; i++) {
7156fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein            SkAutoCanvasRestore acr(canvas, true/*save now*/);
7166fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein            canvas->clear(SK_ColorTRANSPARENT);
7176fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein            Error err = src.draw(canvas);
7186fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein            if (err.isEmpty()) {
7196fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein                return err;
7206fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein            }
7216fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein        }
7226fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein        return "";
7236fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein    });
7246fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein}
7256fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein
7266fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
7276fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein
728d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein// This is like SkRecords::Draw, in that it plays back SkRecords ops into a Canvas.
729d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein// Unlike SkRecords::Draw, it builds a single-op sub-picture out of each Draw-type op.
730d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein// This is an only-slightly-exaggerated simluation of Blink's Slimming Paint pictures.
731d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtkleinstruct DrawsAsSingletonPictures {
732d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    SkCanvas* fCanvas;
733d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
734d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    SK_CREATE_MEMBER_DETECTOR(paint);
735d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
736d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    template <typename T>
737d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    void draw(const T& op, SkCanvas* canvas) {
738d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        // We must pass SkMatrix::I() as our initial matrix.
739d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        // By default SkRecords::Draw() uses the canvas' matrix as its initial matrix,
740d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        // which would have the funky effect of applying transforms over and over.
741d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        SkRecords::Draw(canvas, nullptr, nullptr, 0, &SkMatrix::I())(op);
742d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    }
743d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
744d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    // Most things that have paints are Draw-type ops.  Create sub-pictures for each.
745d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    template <typename T>
746d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    SK_WHEN(HasMember_paint<T>, void) operator()(const T& op) {
747d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        SkPictureRecorder rec;
748d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        this->draw(op, rec.beginRecording(SkRect::MakeLargest()));
749d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        SkAutoTUnref<SkPicture> pic(rec.endRecordingAsPicture());
750d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        fCanvas->drawPicture(pic);
751d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    }
752d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
753d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    // If you don't have a paint or are a SaveLayer, you're not a Draw-type op.
754d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    // We cannot make subpictures out of these because they affect state.  Draw them directly.
755d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    template <typename T>
756d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    SK_WHEN(!HasMember_paint<T>, void) operator()(const T& op) { this->draw(op, fCanvas); }
757d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    void operator()(const SkRecords::SaveLayer& op)            { this->draw(op, fCanvas); }
758d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein};
759d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
760d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein// Record Src into a picture, then record it into a macro picture with a sub-picture for each draw.
761d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein// Then play back that macro picture into our wrapped sink.
762d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtkleinError ViaSingletonPictures::draw(
763d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
764d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    auto size = src.size();
765d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
766d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        // Use low-level (Skia-private) recording APIs so we can read the SkRecord.
767d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        SkRecord skr;
768d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        SkRecorder recorder(&skr, size.width(), size.height());
769d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        Error err = src.draw(&recorder);
770d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        if (!err.isEmpty()) {
771d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein            return err;
772d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        }
773d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
774d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        // Record our macro-picture, with each draw op as its own sub-picture.
775d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        SkPictureRecorder macroRec;
776d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        SkCanvas* macroCanvas = macroRec.beginRecording(SkIntToScalar(size.width()),
777d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein                                                        SkIntToScalar(size.height()));
778d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        DrawsAsSingletonPictures drawsAsSingletonPictures = { macroCanvas };
779d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        for (unsigned i = 0; i < skr.count(); i++) {
780d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein            skr.visit<void>(i, drawsAsSingletonPictures);
781d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        }
782d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture());
783d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
784d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        canvas->drawPicture(macroPic);
785d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein        return "";
786d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    });
787d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein}
788d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein
789748ca3bf2d170708f263693e8579e6722389d0efmtklein}  // namespace DM
790