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