1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "DMSrcSink.h" 9#include "SamplePipeControllers.h" 10#include "SkCodec.h" 11#include "SkCommonFlags.h" 12#include "SkData.h" 13#include "SkDeferredCanvas.h" 14#include "SkDocument.h" 15#include "SkError.h" 16#include "SkFunction.h" 17#include "SkImageGenerator.h" 18#include "SkMultiPictureDraw.h" 19#include "SkNullCanvas.h" 20#include "SkOSFile.h" 21#include "SkPictureData.h" 22#include "SkPictureRecorder.h" 23#include "SkRandom.h" 24#include "SkRecordDraw.h" 25#include "SkRecorder.h" 26#include "SkSVGCanvas.h" 27#include "SkScanlineDecoder.h" 28#include "SkStream.h" 29#include "SkXMLWriter.h" 30 31DEFINE_bool(multiPage, false, "For document-type backends, render the source" 32 " into multiple pages"); 33 34static bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) { 35 SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size)); 36 return encoded && SkInstallDiscardablePixelRef(encoded, dst); 37} 38 39namespace DM { 40 41GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {} 42 43Error GMSrc::draw(SkCanvas* canvas) const { 44 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL)); 45 canvas->concat(gm->getInitialTransform()); 46 gm->draw(canvas); 47 return ""; 48} 49 50SkISize GMSrc::size() const { 51 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL)); 52 return gm->getISize(); 53} 54 55Name GMSrc::name() const { 56 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL)); 57 return gm->getName(); 58} 59 60/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 61 62CodecSrc::CodecSrc(Path path, Mode mode, DstColorType dstColorType) 63 : fPath(path) 64 , fMode(mode) 65 , fDstColorType(dstColorType) 66{} 67 68Error CodecSrc::draw(SkCanvas* canvas) const { 69 SkImageInfo canvasInfo; 70 if (NULL == canvas->peekPixels(&canvasInfo, NULL)) { 71 // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferred decode to 72 // let the GPU handle it. 73 return Error::Nonfatal("No need to test decoding to non-raster backend."); 74 } 75 76 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 77 if (!encoded) { 78 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); 79 } 80 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); 81 if (NULL == codec.get()) { 82 return SkStringPrintf("Couldn't create codec for %s.", fPath.c_str()); 83 } 84 85 // Choose the color type to decode to 86 SkImageInfo decodeInfo = codec->getInfo(); 87 SkColorType canvasColorType = canvasInfo.colorType(); 88 switch (fDstColorType) { 89 case kIndex8_Always_DstColorType: 90 decodeInfo = codec->getInfo().makeColorType(kIndex_8_SkColorType); 91 if (kRGB_565_SkColorType == canvasColorType) { 92 return Error::Nonfatal("Testing non-565 to 565 is uninteresting."); 93 } 94 break; 95 case kGrayscale_Always_DstColorType: 96 decodeInfo = codec->getInfo().makeColorType(kGray_8_SkColorType); 97 if (kRGB_565_SkColorType == canvasColorType) { 98 return Error::Nonfatal("Testing non-565 to 565 is uninteresting."); 99 } 100 break; 101 default: 102 decodeInfo = decodeInfo.makeColorType(canvasColorType); 103 break; 104 } 105 106 // Construct a color table for the decode if necessary 107 SkAutoTUnref<SkColorTable> colorTable(NULL); 108 SkPMColor* colorPtr = NULL; 109 int* colorCountPtr = NULL; 110 int maxColors = 256; 111 if (kIndex_8_SkColorType == decodeInfo.colorType()) { 112 SkPMColor colors[256]; 113 colorTable.reset(SkNEW_ARGS(SkColorTable, (colors, maxColors))); 114 colorPtr = const_cast<SkPMColor*>(colorTable->readColors()); 115 colorCountPtr = &maxColors; 116 } 117 118 // FIXME: Currently we cannot draw unpremultiplied sources. 119 if (decodeInfo.alphaType() == kUnpremul_SkAlphaType) { 120 decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType); 121 } 122 123 SkBitmap bitmap; 124 if (!bitmap.tryAllocPixels(decodeInfo, NULL, colorTable.get())) { 125 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(), 126 decodeInfo.width(), decodeInfo.height()); 127 } 128 129 switch (fMode) { 130 case kNormal_Mode: 131 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), NULL, 132 colorPtr, colorCountPtr)) { 133 case SkImageGenerator::kSuccess: 134 // We consider incomplete to be valid, since we should still decode what is 135 // available. 136 case SkImageGenerator::kIncompleteInput: 137 break; 138 case SkImageGenerator::kInvalidConversion: 139 return Error::Nonfatal("Incompatible colortype conversion"); 140 default: 141 // Everything else is considered a failure. 142 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str()); 143 } 144 break; 145 case kScanline_Mode: { 146 SkScanlineDecoder* scanlineDecoder = codec->getScanlineDecoder(decodeInfo, NULL, 147 colorPtr, colorCountPtr); 148 if (NULL == scanlineDecoder) { 149 return Error::Nonfatal("Cannot use scanline decoder for all images"); 150 } 151 for (int y = 0; y < decodeInfo.height(); ++y) { 152 const SkImageGenerator::Result result = scanlineDecoder->getScanlines( 153 bitmap.getAddr(0, y), 1, 0); 154 switch (result) { 155 case SkImageGenerator::kSuccess: 156 case SkImageGenerator::kIncompleteInput: 157 break; 158 default: 159 return SkStringPrintf("%s failed after %d scanlines with error message %d", 160 fPath.c_str(), y-1, (int) result); 161 } 162 } 163 break; 164 } 165 } 166 canvas->drawBitmap(bitmap, 0, 0); 167 return ""; 168} 169 170SkISize CodecSrc::size() const { 171 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 172 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded)); 173 if (NULL != codec) { 174 return codec->getInfo().dimensions(); 175 } else { 176 return SkISize::Make(0, 0); 177 } 178} 179 180Name CodecSrc::name() const { 181 return SkOSPath::Basename(fPath.c_str()); 182} 183 184/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 185 186ImageSrc::ImageSrc(Path path, int divisor) : fPath(path), fDivisor(divisor) {} 187 188Error ImageSrc::draw(SkCanvas* canvas) const { 189 SkImageInfo canvasInfo; 190 if (NULL == canvas->peekPixels(&canvasInfo, NULL)) { 191 // TODO: Instead, use lazy decoding to allow the GPU to handle cases like YUV. 192 return Error::Nonfatal("No need to test decoding to non-raster backend."); 193 } 194 195 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 196 if (!encoded) { 197 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); 198 } 199 const SkColorType dstColorType = canvasInfo.colorType(); 200 if (fDivisor == 0) { 201 // Decode the full image. 202 SkBitmap bitmap; 203 if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap, 204 dstColorType, SkImageDecoder::kDecodePixels_Mode)) { 205 return SkStringPrintf("Couldn't decode %s.", fPath.c_str()); 206 } 207 if (kRGB_565_SkColorType == dstColorType && !bitmap.isOpaque()) { 208 // Do not draw a bitmap with alpha to a destination without alpha. 209 return Error::Nonfatal("Uninteresting to decode image with alpha into 565."); 210 } 211 encoded.reset((SkData*)NULL); // Might as well drop this when we're done with it. 212 canvas->drawBitmap(bitmap, 0,0); 213 return ""; 214 } 215 // Decode subsets. This is a little involved. 216 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded)); 217 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream.get())); 218 if (!decoder) { 219 return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str()); 220 } 221 stream->rewind(); 222 int w,h; 223 if (!decoder->buildTileIndex(stream.detach(), &w, &h) || w*h == 1) { 224 return Error::Nonfatal("Subset decoding not supported."); 225 } 226 227 // Divide the image into subsets that cover the entire image. 228 if (fDivisor > w || fDivisor > h) { 229 return SkStringPrintf("divisor %d is too big for %s with dimensions (%d x %d)", 230 fDivisor, fPath.c_str(), w, h); 231 } 232 const int subsetWidth = w / fDivisor, 233 subsetHeight = h / fDivisor; 234 for (int y = 0; y < h; y += subsetHeight) { 235 for (int x = 0; x < w; x += subsetWidth) { 236 SkBitmap subset; 237 SkIRect rect = SkIRect::MakeXYWH(x, y, subsetWidth, subsetHeight); 238 if (!decoder->decodeSubset(&subset, rect, dstColorType)) { 239 return SkStringPrintf("Could not decode subset (%d, %d, %d, %d).", 240 x, y, x+subsetWidth, y+subsetHeight); 241 } 242 if (kRGB_565_SkColorType == dstColorType && !subset.isOpaque()) { 243 // Do not draw a bitmap with alpha to a destination without alpha. 244 // This is not an error, but there is nothing interesting to show. 245 246 // This should only happen on the first iteration through the loop. 247 SkASSERT(0 == x && 0 == y); 248 249 return Error::Nonfatal("Uninteresting to decode image with alpha into 565."); 250 } 251 canvas->drawBitmap(subset, SkIntToScalar(x), SkIntToScalar(y)); 252 } 253 } 254 return ""; 255} 256 257SkISize ImageSrc::size() const { 258 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); 259 SkBitmap bitmap; 260 if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(), 261 encoded->size(), 262 &bitmap, 263 kUnknown_SkColorType, 264 SkImageDecoder::kDecodeBounds_Mode)) { 265 return SkISize::Make(0,0); 266 } 267 return bitmap.dimensions(); 268} 269 270Name ImageSrc::name() const { 271 return SkOSPath::Basename(fPath.c_str()); 272} 273 274/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 275 276static const SkRect kSKPViewport = {0,0, 1000,1000}; 277 278SKPSrc::SKPSrc(Path path) : fPath(path) {} 279 280Error SKPSrc::draw(SkCanvas* canvas) const { 281 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str())); 282 if (!stream) { 283 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); 284 } 285 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream, &lazy_decode_bitmap)); 286 if (!pic) { 287 return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str()); 288 } 289 stream.reset((SkStream*)NULL); // Might as well drop this when we're done with it. 290 291 canvas->clipRect(kSKPViewport); 292 canvas->drawPicture(pic); 293 return ""; 294} 295 296SkISize SKPSrc::size() const { 297 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str())); 298 if (!stream) { 299 return SkISize::Make(0,0); 300 } 301 SkPictInfo info; 302 if (!SkPicture::InternalOnly_StreamIsSKP(stream, &info)) { 303 return SkISize::Make(0,0); 304 } 305 SkRect viewport = kSKPViewport; 306 if (!viewport.intersect(info.fCullRect)) { 307 return SkISize::Make(0,0); 308 } 309 return viewport.roundOut().size(); 310} 311 312Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); } 313 314/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 315 316Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const { 317 SkAutoTDelete<SkCanvas> canvas(SkCreateNullCanvas()); 318 return src.draw(canvas); 319} 320 321/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 322 323DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?"); 324 325GPUSink::GPUSink(GrContextFactory::GLContextType ct, 326 GrGLStandard api, 327 int samples, 328 bool dfText, 329 bool threaded) 330 : fContextType(ct) 331 , fGpuAPI(api) 332 , fSampleCount(samples) 333 , fUseDFText(dfText) 334 , fThreaded(threaded) {} 335 336int GPUSink::enclave() const { 337 return fThreaded ? kAnyThread_Enclave : kGPU_Enclave; 338} 339 340void PreAbandonGpuContextErrorHandler(SkError, void*) {} 341 342Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const { 343 GrContextFactory factory; 344 const SkISize size = src.size(); 345 const SkImageInfo info = 346 SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType); 347 SkAutoTUnref<SkSurface> surface( 348 NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText)); 349 if (!surface) { 350 return "Could not create a surface."; 351 } 352 if (FLAGS_preAbandonGpuContext) { 353 SkSetErrorCallback(&PreAbandonGpuContextErrorHandler, NULL); 354 factory.abandonContexts(); 355 } 356 SkCanvas* canvas = surface->getCanvas(); 357 Error err = src.draw(canvas); 358 if (!err.isEmpty()) { 359 return err; 360 } 361 canvas->flush(); 362 if (FLAGS_gpuStats) { 363 canvas->getGrContext()->dumpCacheStats(log); 364 canvas->getGrContext()->dumpGpuStats(log); 365 } 366 dst->allocPixels(info); 367 canvas->readPixels(dst, 0, 0); 368 if (FLAGS_abandonGpuContext) { 369 factory.abandonContexts(); 370 } 371 return ""; 372} 373 374/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 375 376static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) { 377 // Print the given DM:Src to a document, breaking on 8.5x11 pages. 378 SkASSERT(doc); 379 int width = src.size().width(), 380 height = src.size().height(); 381 382 if (FLAGS_multiPage) { 383 const int kLetterWidth = 612, // 8.5 * 72 384 kLetterHeight = 792; // 11 * 72 385 const SkRect letter = SkRect::MakeWH(SkIntToScalar(kLetterWidth), 386 SkIntToScalar(kLetterHeight)); 387 388 int xPages = ((width - 1) / kLetterWidth) + 1; 389 int yPages = ((height - 1) / kLetterHeight) + 1; 390 391 for (int y = 0; y < yPages; ++y) { 392 for (int x = 0; x < xPages; ++x) { 393 int w = SkTMin(kLetterWidth, width - (x * kLetterWidth)); 394 int h = SkTMin(kLetterHeight, height - (y * kLetterHeight)); 395 SkCanvas* canvas = 396 doc->beginPage(SkIntToScalar(w), SkIntToScalar(h)); 397 if (!canvas) { 398 return "SkDocument::beginPage(w,h) returned NULL"; 399 } 400 canvas->clipRect(letter); 401 canvas->translate(-letter.width() * x, -letter.height() * y); 402 Error err = src.draw(canvas); 403 if (!err.isEmpty()) { 404 return err; 405 } 406 doc->endPage(); 407 } 408 } 409 } else { 410 SkCanvas* canvas = 411 doc->beginPage(SkIntToScalar(width), SkIntToScalar(height)); 412 if (!canvas) { 413 return "SkDocument::beginPage(w,h) returned NULL"; 414 } 415 Error err = src.draw(canvas); 416 if (!err.isEmpty()) { 417 return err; 418 } 419 doc->endPage(); 420 } 421 if (!doc->close()) { 422 return "SkDocument::close() returned false"; 423 } 424 dst->flush(); 425 return ""; 426} 427 428PDFSink::PDFSink() {} 429 430Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const { 431 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst)); 432 if (!doc) { 433 return "SkDocument::CreatePDF() returned NULL"; 434 } 435 return draw_skdocument(src, doc.get(), dst); 436} 437 438/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 439 440XPSSink::XPSSink() {} 441 442Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const { 443 SkAutoTUnref<SkDocument> doc(SkDocument::CreateXPS(dst)); 444 if (!doc) { 445 return "SkDocument::CreateXPS() returned NULL"; 446 } 447 return draw_skdocument(src, doc.get(), dst); 448} 449/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 450 451SKPSink::SKPSink() {} 452 453Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const { 454 SkSize size; 455 size = src.size(); 456 SkPictureRecorder recorder; 457 Error err = src.draw(recorder.beginRecording(size.width(), size.height())); 458 if (!err.isEmpty()) { 459 return err; 460 } 461 SkAutoTUnref<SkPicture> pic(recorder.endRecording()); 462 pic->serialize(dst); 463 return ""; 464} 465 466/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 467 468SVGSink::SVGSink() {} 469 470Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const { 471 SkAutoTDelete<SkXMLWriter> xmlWriter(SkNEW_ARGS(SkXMLStreamWriter, (dst))); 472 SkAutoTUnref<SkCanvas> canvas(SkSVGCanvas::Create( 473 SkRect::MakeWH(SkIntToScalar(src.size().width()), SkIntToScalar(src.size().height())), 474 xmlWriter)); 475 return src.draw(canvas); 476} 477 478/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 479 480RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {} 481 482Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const { 483 const SkISize size = src.size(); 484 // If there's an appropriate alpha type for this color type, use it, otherwise use premul. 485 SkAlphaType alphaType = kPremul_SkAlphaType; 486 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType); 487 488 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType)); 489 dst->eraseColor(SK_ColorTRANSPARENT); 490 SkCanvas canvas(*dst); 491 return src.draw(&canvas); 492} 493 494/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 495 496// Handy for front-patching a Src. Do whatever up-front work you need, then call draw_to_canvas(), 497// passing the Sink draw() arguments, a size, and a function draws into an SkCanvas. 498// Several examples below. 499 500static Error draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, SkString* log, 501 SkISize size, SkFunction<Error(SkCanvas*)> draw) { 502 class ProxySrc : public Src { 503 public: 504 ProxySrc(SkISize size, SkFunction<Error(SkCanvas*)> draw) : fSize(size), fDraw(draw) {} 505 Error draw(SkCanvas* canvas) const override { return fDraw(canvas); } 506 Name name() const override { sk_throw(); return ""; } // Won't be called. 507 SkISize size() const override { return fSize; } 508 private: 509 SkISize fSize; 510 SkFunction<Error(SkCanvas*)> fDraw; 511 }; 512 return sink->draw(ProxySrc(size, draw), bitmap, stream, log); 513} 514 515/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 516 517static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) { 518 SkRect bounds = SkRect::MakeIWH(srcW, srcH); 519 matrix->mapRect(&bounds); 520 matrix->postTranslate(-bounds.x(), -bounds.y()); 521 return SkISize::Make(SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height())); 522} 523 524ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {} 525 526Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 527 SkMatrix matrix = fMatrix; 528 SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height()); 529 return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) { 530 canvas->concat(matrix); 531 return src.draw(canvas); 532 }); 533} 534 535// Undoes any flip or 90 degree rotate without changing the scale of the bitmap. 536// This should be pixel-preserving. 537ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : Via(sink), fMatrix(matrix) {} 538 539Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 540 Error err = fSink->draw(src, bitmap, stream, log); 541 if (!err.isEmpty()) { 542 return err; 543 } 544 545 SkMatrix inverse; 546 if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) { 547 return "Cannot upright --matrix."; 548 } 549 SkMatrix upright = SkMatrix::I(); 550 upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX())); 551 upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY())); 552 upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX())); 553 upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY())); 554 555 SkBitmap uprighted; 556 SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height()); 557 uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height())); 558 559 SkCanvas canvas(uprighted); 560 canvas.concat(upright); 561 SkPaint paint; 562 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 563 canvas.drawBitmap(*bitmap, 0, 0, &paint); 564 565 *bitmap = uprighted; 566 bitmap->lockPixels(); 567 return ""; 568} 569 570/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 571 572Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 573 auto size = src.size(); 574 return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) { 575 PipeController controller(canvas, &SkImageDecoder::DecodeMemory); 576 SkGPipeWriter pipe; 577 const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags. 578 return src.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height())); 579 }); 580} 581 582/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 583 584Error ViaDeferred::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 585 // We draw via a deferred canvas into a surface that's compatible with the original canvas, 586 // then snap that surface as an image and draw it into the original canvas. 587 return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error { 588 SkAutoTUnref<SkSurface> surface(canvas->newSurface(canvas->imageInfo())); 589 if (!surface.get()) { 590 return "can't make surface for deferred canvas"; 591 } 592 SkAutoTDelete<SkDeferredCanvas> defcan(SkDeferredCanvas::Create(surface)); 593 Error err = src.draw(defcan); 594 if (!err.isEmpty()) { 595 return err; 596 } 597 SkAutoTUnref<SkImage> image(defcan->newImageSnapshot()); 598 if (!image) { 599 return "failed to create deferred image snapshot"; 600 } 601 canvas->drawImage(image, 0, 0, NULL); 602 return ""; 603 }); 604} 605 606/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 607 608Error ViaSerialization::draw( 609 const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 610 // Record our Src into a picture. 611 auto size = src.size(); 612 SkPictureRecorder recorder; 613 Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()), 614 SkIntToScalar(size.height()))); 615 if (!err.isEmpty()) { 616 return err; 617 } 618 SkAutoTUnref<SkPicture> pic(recorder.endRecording()); 619 620 // Serialize it and then deserialize it. 621 SkDynamicMemoryWStream wStream; 622 pic->serialize(&wStream); 623 SkAutoTDelete<SkStream> rStream(wStream.detachAsStream()); 624 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream, &lazy_decode_bitmap)); 625 626 return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) { 627 canvas->drawPicture(deserialized); 628 return ""; 629 }); 630} 631 632/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 633 634ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink) 635 : Via(sink) 636 , fW(w) 637 , fH(h) 638 , fFactory(factory) {} 639 640Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 641 auto size = src.size(); 642 SkPictureRecorder recorder; 643 Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()), 644 SkIntToScalar(size.height()), 645 fFactory.get())); 646 if (!err.isEmpty()) { 647 return err; 648 } 649 SkAutoTUnref<SkPicture> pic(recorder.endRecordingAsPicture()); 650 651 return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) { 652 const int xTiles = (size.width() + fW - 1) / fW, 653 yTiles = (size.height() + fH - 1) / fH; 654 SkMultiPictureDraw mpd(xTiles*yTiles); 655 SkTDArray<SkSurface*> surfaces; 656 surfaces.setReserve(xTiles*yTiles); 657 658 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH); 659 for (int j = 0; j < yTiles; j++) { 660 for (int i = 0; i < xTiles; i++) { 661 // This lets our ultimate Sink determine the best kind of surface. 662 // E.g., if it's a GpuSink, the surfaces and images are textures. 663 SkSurface* s = canvas->newSurface(info); 664 if (!s) { 665 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces. 666 } 667 surfaces.push(s); 668 SkCanvas* c = s->getCanvas(); 669 c->translate(SkIntToScalar(-i * fW), 670 SkIntToScalar(-j * fH)); // Line up the canvas with this tile. 671 mpd.add(c, pic); 672 } 673 } 674 mpd.draw(); 675 for (int j = 0; j < yTiles; j++) { 676 for (int i = 0; i < xTiles; i++) { 677 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot()); 678 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH)); 679 } 680 } 681 surfaces.unrefAll(); 682 return ""; 683 }); 684} 685 686/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 687 688// Draw the Src into two pictures, then draw the second picture into the wrapped Sink. 689// This tests that any shortcuts we may take while recording that second picture are legal. 690Error ViaSecondPicture::draw( 691 const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 692 auto size = src.size(); 693 return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error { 694 SkPictureRecorder recorder; 695 SkAutoTUnref<SkPicture> pic; 696 for (int i = 0; i < 2; i++) { 697 Error err = src.draw(recorder.beginRecording(SkIntToScalar(size.width()), 698 SkIntToScalar(size.height()))); 699 if (!err.isEmpty()) { 700 return err; 701 } 702 pic.reset(recorder.endRecordingAsPicture()); 703 } 704 canvas->drawPicture(pic); 705 return ""; 706 }); 707} 708 709/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 710 711// Draw the Src twice. This can help exercise caching. 712Error ViaTwice::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 713 return draw_to_canvas(fSink, bitmap, stream, log, src.size(), [&](SkCanvas* canvas) -> Error { 714 for (int i = 0; i < 2; i++) { 715 SkAutoCanvasRestore acr(canvas, true/*save now*/); 716 canvas->clear(SK_ColorTRANSPARENT); 717 Error err = src.draw(canvas); 718 if (err.isEmpty()) { 719 return err; 720 } 721 } 722 return ""; 723 }); 724} 725 726/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 727 728// This is like SkRecords::Draw, in that it plays back SkRecords ops into a Canvas. 729// Unlike SkRecords::Draw, it builds a single-op sub-picture out of each Draw-type op. 730// This is an only-slightly-exaggerated simluation of Blink's Slimming Paint pictures. 731struct DrawsAsSingletonPictures { 732 SkCanvas* fCanvas; 733 734 SK_CREATE_MEMBER_DETECTOR(paint); 735 736 template <typename T> 737 void draw(const T& op, SkCanvas* canvas) { 738 // We must pass SkMatrix::I() as our initial matrix. 739 // By default SkRecords::Draw() uses the canvas' matrix as its initial matrix, 740 // which would have the funky effect of applying transforms over and over. 741 SkRecords::Draw(canvas, nullptr, nullptr, 0, &SkMatrix::I())(op); 742 } 743 744 // Most things that have paints are Draw-type ops. Create sub-pictures for each. 745 template <typename T> 746 SK_WHEN(HasMember_paint<T>, void) operator()(const T& op) { 747 SkPictureRecorder rec; 748 this->draw(op, rec.beginRecording(SkRect::MakeLargest())); 749 SkAutoTUnref<SkPicture> pic(rec.endRecordingAsPicture()); 750 fCanvas->drawPicture(pic); 751 } 752 753 // If you don't have a paint or are a SaveLayer, you're not a Draw-type op. 754 // We cannot make subpictures out of these because they affect state. Draw them directly. 755 template <typename T> 756 SK_WHEN(!HasMember_paint<T>, void) operator()(const T& op) { this->draw(op, fCanvas); } 757 void operator()(const SkRecords::SaveLayer& op) { this->draw(op, fCanvas); } 758}; 759 760// Record Src into a picture, then record it into a macro picture with a sub-picture for each draw. 761// Then play back that macro picture into our wrapped sink. 762Error ViaSingletonPictures::draw( 763 const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const { 764 auto size = src.size(); 765 return draw_to_canvas(fSink, bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error { 766 // Use low-level (Skia-private) recording APIs so we can read the SkRecord. 767 SkRecord skr; 768 SkRecorder recorder(&skr, size.width(), size.height()); 769 Error err = src.draw(&recorder); 770 if (!err.isEmpty()) { 771 return err; 772 } 773 774 // Record our macro-picture, with each draw op as its own sub-picture. 775 SkPictureRecorder macroRec; 776 SkCanvas* macroCanvas = macroRec.beginRecording(SkIntToScalar(size.width()), 777 SkIntToScalar(size.height())); 778 DrawsAsSingletonPictures drawsAsSingletonPictures = { macroCanvas }; 779 for (unsigned i = 0; i < skr.count(); i++) { 780 skr.visit<void>(i, drawsAsSingletonPictures); 781 } 782 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); 783 784 canvas->drawPicture(macroPic); 785 return ""; 786 }); 787} 788 789} // namespace DM 790