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 #ifndef DMSrcSink_DEFINED 9 #define DMSrcSink_DEFINED 10 11 #include "gm/gm.h" 12 #include "include/core/SkBBHFactory.h" 13 #include "include/core/SkBitmap.h" 14 #include "include/core/SkCanvas.h" 15 #include "include/core/SkData.h" 16 #include "include/core/SkPicture.h" 17 #include "src/utils/SkMultiPictureDocument.h" 18 #include "tools/flags/CommonFlagsConfig.h" 19 #include "tools/gpu/MemoryCache.h" 20 21 #include <functional> 22 23 //#define TEST_VIA_SVG 24 25 namespace skiagm { 26 namespace verifiers { 27 class VerifierList; 28 } // namespace verifiers 29 } // namespace skiagm 30 31 namespace DM { 32 33 // This is just convenience. It lets you use either return "foo" or return SkStringPrintf(...). 34 struct ImplicitString : public SkString { 35 template <typename T> ImplicitStringImplicitString36 ImplicitString(const T& s) : SkString(s) {} ImplicitStringImplicitString37 ImplicitString() : SkString("") {} 38 }; 39 typedef ImplicitString Name; 40 typedef ImplicitString Path; 41 42 class Result { 43 public: 44 enum class Status : int { Ok, Fatal, Skip }; 45 Result(Status status,SkString msg)46 Result(Status status, SkString msg) : fMsg(std::move(msg)), fStatus(status) {} 47 48 Result(const Result&) = default; 49 Result& operator=(const Result&) = default; 50 Ok()51 static Result Ok() { return Result{Status::Ok, {}}; } 52 Fatal(const char * fmt,...)53 static Result Fatal(const char* fmt, ...) SK_PRINTF_LIKE(1, 2) { 54 SkString msg; 55 va_list args; 56 va_start(args, fmt); 57 msg.printVAList(fmt, args); 58 va_end(args); 59 60 return Result{Status::Fatal, std::move(msg)}; 61 } 62 Skip(const char * fmt,...)63 static Result Skip(const char* fmt, ...) SK_PRINTF_LIKE(1, 2) { 64 SkString msg; 65 va_list args; 66 va_start(args, fmt); 67 msg.printVAList(fmt, args); 68 va_end(args); 69 70 return Result{Status::Skip, std::move(msg)}; 71 } 72 isOk()73 bool isOk() { return fStatus == Status::Ok; } isFatal()74 bool isFatal() { return fStatus == Status::Fatal; } isSkip()75 bool isSkip() { return fStatus == Status::Skip; } 76 c_str()77 const char* c_str() const { return fMsg.c_str(); } status()78 Status status() const { return fStatus; } 79 80 private: 81 SkString fMsg; 82 Status fStatus; 83 }; 84 85 struct SinkFlags { 86 enum Type { kNull, kGPU, kVector, kRaster } type; 87 enum Approach { kDirect, kIndirect } approach; 88 enum Multisampled { kNotMultisampled, kMultisampled } multisampled; 89 SinkFlags(Type t, Approach a, Multisampled ms = kNotMultisampled) typeSinkFlags90 : type(t), approach(a), multisampled(ms) {} 91 }; 92 93 struct Src { ~SrcSrc94 virtual ~Src() {} 95 virtual Result SK_WARN_UNUSED_RESULT draw(GrDirectContext* context, SkCanvas* canvas) const = 0; 96 virtual SkISize size() const = 0; 97 virtual Name name() const = 0; modifyGrContextOptionsSrc98 virtual void modifyGrContextOptions(GrContextOptions* options) const {} vetoSrc99 virtual bool veto(SinkFlags) const { return false; } 100 pageCountSrc101 virtual int pageCount() const { return 1; } drawSrc102 virtual Result SK_WARN_UNUSED_RESULT draw([[maybe_unused]] int page, GrDirectContext* context, 103 SkCanvas* canvas) const { 104 return this->draw(context, canvas); 105 } sizeSrc106 virtual SkISize size([[maybe_unused]] int page) const { return this->size(); } 107 // Force Tasks using this Src to run on the main thread? serialSrc108 virtual bool serial() const { return false; } 109 110 /** Return a list of verifiers for the src, or null if no verifiers should be run .*/ getVerifiersSrc111 virtual std::unique_ptr<skiagm::verifiers::VerifierList> getVerifiers() const { 112 return nullptr; 113 } 114 }; 115 116 struct Sink { ~SinkSink117 virtual ~Sink() {} 118 // You may write to either the bitmap or stream. If you write to log, we'll print that out. 119 virtual Result SK_WARN_UNUSED_RESULT draw(const Src&, SkBitmap*, SkWStream*, SkString* log) 120 const = 0; 121 122 // Override the color space of this Sink, after creation setColorSpaceSink123 virtual void setColorSpace(sk_sp<SkColorSpace>) {} 124 125 // Force Tasks using this Sink to run on the main thread? serialSink126 virtual bool serial() const { return false; } 127 128 // File extension for the content draw() outputs, e.g. "png", "pdf". 129 virtual const char* fileExtension() const = 0; 130 131 virtual SinkFlags flags() const = 0; 132 133 /** Returns the color type and space used by the sink. */ colorInfoSink134 virtual SkColorInfo colorInfo() const { return SkColorInfo(); } 135 }; 136 137 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 138 139 class GMSrc : public Src { 140 public: 141 explicit GMSrc(skiagm::GMFactory); 142 143 Result draw(GrDirectContext*, SkCanvas*) const override; 144 SkISize size() const override; 145 Name name() const override; 146 void modifyGrContextOptions(GrContextOptions* options) const override; 147 148 std::unique_ptr<skiagm::verifiers::VerifierList> getVerifiers() const override; 149 150 private: 151 skiagm::GMFactory fFactory; 152 }; 153 154 class CodecSrc : public Src { 155 public: 156 enum Mode { 157 kCodec_Mode, 158 // We choose to test only one mode with zero initialized memory. 159 // This will exercise all of the interesting cases in SkSwizzler 160 // without doubling the size of our test suite. 161 kCodecZeroInit_Mode, 162 kScanline_Mode, 163 kStripe_Mode, // Tests the skipping of scanlines 164 kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization 165 kSubset_Mode, // For codecs that support subsets directly. 166 kAnimated_Mode, // For codecs that support animation. 167 }; 168 enum DstColorType { 169 kGetFromCanvas_DstColorType, 170 kGrayscale_Always_DstColorType, 171 kNonNative8888_Always_DstColorType, 172 }; 173 CodecSrc(Path, Mode, DstColorType, SkAlphaType, float); 174 175 Result draw(GrDirectContext*, SkCanvas*) const override; 176 SkISize size() const override; 177 Name name() const override; veto(SinkFlags)178 bool veto(SinkFlags) const override; 179 bool serial() const override { return fRunSerially; } 180 private: 181 Path fPath; 182 Mode fMode; 183 DstColorType fDstColorType; 184 SkAlphaType fDstAlphaType; 185 float fScale; 186 bool fRunSerially; 187 }; 188 189 class AndroidCodecSrc : public Src { 190 public: 191 AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize); 192 193 Result draw(GrDirectContext*, SkCanvas*) const override; 194 SkISize size() const override; 195 Name name() const override; veto(SinkFlags)196 bool veto(SinkFlags) const override; 197 bool serial() const override { return fRunSerially; } 198 private: 199 Path fPath; 200 CodecSrc::DstColorType fDstColorType; 201 SkAlphaType fDstAlphaType; 202 int fSampleSize; 203 bool fRunSerially; 204 }; 205 206 #ifdef SK_ENABLE_ANDROID_UTILS 207 // Allows for testing of various implementations of Android's BitmapRegionDecoder 208 class BRDSrc : public Src { 209 public: 210 enum Mode { 211 // Decode the entire image as one region. 212 kFullImage_Mode, 213 // Splits the image into multiple regions using a divisor and decodes the regions 214 // separately. Also, this test adds a border of a few pixels to each of the regions 215 // that it is decoding. This tests the behavior when a client asks for a region that 216 // does not fully fit in the image. 217 kDivisor_Mode, 218 }; 219 220 BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t); 221 222 Result draw(GrDirectContext*, SkCanvas*) const override; 223 SkISize size() const override; 224 Name name() const override; 225 bool veto(SinkFlags) const override; 226 private: 227 Path fPath; 228 Mode fMode; 229 CodecSrc::DstColorType fDstColorType; 230 uint32_t fSampleSize; 231 }; 232 #endif 233 234 class ImageGenSrc : public Src { 235 public: 236 enum Mode { 237 kCodec_Mode, // Use CodecImageGenerator 238 kPlatform_Mode, // Uses CG or WIC 239 }; 240 ImageGenSrc(Path, Mode, SkAlphaType, bool); 241 242 Result draw(GrDirectContext*, SkCanvas*) const override; 243 SkISize size() const override; 244 Name name() const override; veto(SinkFlags)245 bool veto(SinkFlags) const override; 246 bool serial() const override { return fRunSerially; } 247 private: 248 Path fPath; 249 Mode fMode; 250 SkAlphaType fDstAlphaType; 251 bool fIsGpu; 252 bool fRunSerially; 253 }; 254 255 class ColorCodecSrc : public Src { 256 public: 257 ColorCodecSrc(Path, bool decode_to_dst); 258 259 Result draw(GrDirectContext*, SkCanvas*) const override; 260 SkISize size() const override; 261 Name name() const override; 262 bool veto(SinkFlags) const override; 263 private: 264 Path fPath; 265 bool fDecodeToDst; 266 }; 267 268 class SKPSrc : public Src { 269 public: 270 explicit SKPSrc(Path path); 271 272 Result draw(GrDirectContext*, SkCanvas*) const override; 273 SkISize size() const override; 274 Name name() const override; 275 private: 276 Path fPath; 277 }; 278 279 // This class extracts all the paths from an SKP and then removes unwanted paths according to the 280 // provided l/r trail. It then just draws the remaining paths. (Non-path draws are thrown out.) It 281 // is useful for finding a reduced repo case for path drawing bugs. 282 class BisectSrc : public SKPSrc { 283 public: 284 explicit BisectSrc(Path path, const char* trail); 285 286 Result draw(GrDirectContext*, SkCanvas*) const override; 287 288 private: 289 SkString fTrail; 290 291 using INHERITED = SKPSrc; 292 }; 293 294 #if defined(SK_ENABLE_SKOTTIE) 295 class SkottieSrc final : public Src { 296 public: 297 explicit SkottieSrc(Path path); 298 299 Result draw(GrDirectContext*, SkCanvas*) const override; 300 SkISize size() const override; 301 Name name() const override; 302 bool veto(SinkFlags) const override; 303 304 private: 305 // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames. 306 inline static constexpr int kTileCount = 5; 307 308 // Fit kTileCount x kTileCount frames to a 1000x1000 film strip. 309 inline static constexpr SkScalar kTargetSize = 1000; 310 inline static constexpr SkScalar kTileSize = kTargetSize / kTileCount; 311 312 Path fPath; 313 }; 314 #endif 315 316 #if defined(SK_ENABLE_SKRIVE) 317 class SkRiveSrc final : public Src { 318 public: 319 explicit SkRiveSrc(Path path); 320 321 Result draw(GrDirectContext*, SkCanvas*) const override; 322 SkISize size() const override; 323 Name name() const override; 324 bool veto(SinkFlags) const override; 325 326 private: 327 // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames. 328 inline static constexpr int kTileCount = 5; 329 330 // Fit kTileCount x kTileCount frames to a 1000x1000 film strip. 331 inline static constexpr SkScalar kTargetSize = 1000; 332 inline static constexpr SkScalar kTileSize = kTargetSize / kTileCount; 333 334 const Path fPath; 335 }; 336 #endif 337 338 #if defined(SK_ENABLE_SVG) 339 } // namespace DM 340 341 class SkSVGDOM; 342 343 namespace DM { 344 345 class SVGSrc : public Src { 346 public: 347 explicit SVGSrc(Path path); 348 349 Result draw(GrDirectContext*, SkCanvas*) const override; 350 SkISize size() const override; 351 Name name() const override; 352 bool veto(SinkFlags) const override; 353 354 private: 355 Name fName; 356 sk_sp<SkSVGDOM> fDom; 357 SkScalar fScale; 358 359 using INHERITED = Src; 360 }; 361 #endif // SK_ENABLE_SVG 362 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 363 364 class MSKPSrc : public Src { 365 public: 366 explicit MSKPSrc(Path path); 367 368 int pageCount() const override; 369 Result draw(GrDirectContext*, SkCanvas* c) const override; 370 Result draw(int, GrDirectContext*, SkCanvas*) const override; 371 SkISize size() const override; 372 SkISize size(int) const override; 373 Name name() const override; 374 375 private: 376 Path fPath; 377 mutable SkTArray<SkDocumentPage> fPages; 378 }; 379 380 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 381 382 class NullSink : public Sink { 383 public: NullSink()384 NullSink() {} 385 386 Result draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()387 const char* fileExtension() const override { return ""; } flags()388 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; } 389 }; 390 391 class GPUSink : public Sink { 392 public: 393 GPUSink(const SkCommandLineConfigGpu*, const GrContextOptions&); 394 395 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 396 Result onDraw(const Src&, SkBitmap*, SkWStream*, SkString*, 397 const GrContextOptions& baseOptions, 398 std::function<void(GrDirectContext*)> initContext = nullptr) const; 399 contextType()400 sk_gpu_test::GrContextFactory::ContextType contextType() const { return fContextType; } contextOverrides()401 const sk_gpu_test::GrContextFactory::ContextOverrides& contextOverrides() const { 402 return fContextOverrides; 403 } surfType()404 SkCommandLineConfigGpu::SurfType surfType() const { return fSurfType; } serial()405 bool serial() const override { return true; } fileExtension()406 const char* fileExtension() const override { return "png"; } flags()407 SinkFlags flags() const override { 408 SinkFlags::Multisampled ms = fSampleCount > 1 ? SinkFlags::kMultisampled 409 : SinkFlags::kNotMultisampled; 410 return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms }; 411 } baseContextOptions()412 const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; } setColorSpace(sk_sp<SkColorSpace> colorSpace)413 void setColorSpace(sk_sp<SkColorSpace> colorSpace) override { fColorSpace = colorSpace; } colorInfo()414 SkColorInfo colorInfo() const override { 415 return SkColorInfo(fColorType, fAlphaType, fColorSpace); 416 } 417 418 protected: 419 sk_sp<SkSurface> createDstSurface(GrDirectContext*, SkISize size) const; 420 bool readBack(SkSurface*, SkBitmap* dst) const; 421 422 private: 423 sk_gpu_test::GrContextFactory::ContextType fContextType; 424 sk_gpu_test::GrContextFactory::ContextOverrides fContextOverrides; 425 SkCommandLineConfigGpu::SurfType fSurfType; 426 int fSampleCount; 427 uint32_t fSurfaceFlags; 428 SkColorType fColorType; 429 SkAlphaType fAlphaType; 430 sk_sp<SkColorSpace> fColorSpace; 431 GrContextOptions fBaseContextOptions; 432 sk_gpu_test::MemoryCache fMemoryCache; 433 }; 434 435 class GPUThreadTestingSink : public GPUSink { 436 public: 437 GPUThreadTestingSink(const SkCommandLineConfigGpu*, const GrContextOptions&); 438 439 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 440 fileExtension()441 const char* fileExtension() const override { 442 // Suppress writing out results from this config - we just want to do our matching test 443 return nullptr; 444 } 445 446 private: 447 std::unique_ptr<SkExecutor> fExecutor; 448 449 using INHERITED = GPUSink; 450 }; 451 452 class GPUPersistentCacheTestingSink : public GPUSink { 453 public: 454 GPUPersistentCacheTestingSink(const SkCommandLineConfigGpu*, const GrContextOptions&); 455 456 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 457 fileExtension()458 const char* fileExtension() const override { 459 // Suppress writing out results from this config - we just want to do our matching test 460 return nullptr; 461 } 462 463 private: 464 int fCacheType; 465 466 using INHERITED = GPUSink; 467 }; 468 469 class GPUPrecompileTestingSink : public GPUSink { 470 public: 471 GPUPrecompileTestingSink(const SkCommandLineConfigGpu*, const GrContextOptions&); 472 473 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 474 fileExtension()475 const char* fileExtension() const override { 476 // Suppress writing out results from this config - we just want to do our matching test 477 return nullptr; 478 } 479 480 private: 481 using INHERITED = GPUSink; 482 }; 483 484 // This sink attempts to emulate Chrome's OOP-R behavior. It: 485 // doesn't use promise images 486 // uses only a single thread for both DDL creation & drawing 487 class GPUOOPRSink : public GPUSink { 488 public: 489 GPUOOPRSink(const SkCommandLineConfigGpu*, const GrContextOptions&); 490 491 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 492 493 private: 494 Result ooprDraw(const Src&, sk_sp<SkSurface> dstSurface, GrDirectContext*) const; 495 496 using INHERITED = GPUSink; 497 }; 498 499 // This sink attempts to better simulate the Chrome DDL use-case. It: 500 // creates the DDLs on separate recording threads 501 // performs all the GPU work on a separate GPU thread 502 // In the future this should be expanded to: 503 // upload on a utility thread w/ access to a shared context 504 // compile the programs on the utility thread 505 // perform fine grained scheduling of gpu tasks based on their image and program prerequisites 506 // create a single "compositing" DDL that is replayed last 507 class GPUDDLSink : public GPUSink { 508 public: 509 GPUDDLSink(const SkCommandLineConfigGpu*, const GrContextOptions&); 510 511 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 512 513 private: 514 Result ddlDraw(const Src&, 515 sk_sp<SkSurface> dstSurface, 516 SkTaskGroup* recordingTaskGroup, 517 SkTaskGroup* gpuTaskGroup, 518 sk_gpu_test::TestContext* gpuTestCtx, 519 GrDirectContext* gpuThreadCtx) const; 520 521 std::unique_ptr<SkExecutor> fRecordingExecutor; 522 std::unique_ptr<SkExecutor> fGPUExecutor; 523 524 using INHERITED = GPUSink; 525 }; 526 527 class PDFSink : public Sink { 528 public: PDFSink(bool pdfa,SkScalar rasterDpi)529 PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {} 530 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()531 const char* fileExtension() const override { return "pdf"; } flags()532 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 533 bool fPDFA; 534 SkScalar fRasterDpi; 535 }; 536 537 class XPSSink : public Sink { 538 public: 539 XPSSink(); 540 541 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()542 const char* fileExtension() const override { return "xps"; } flags()543 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 544 }; 545 546 class RasterSink : public Sink { 547 public: 548 explicit RasterSink(SkColorType); 549 550 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()551 const char* fileExtension() const override { return "png"; } flags()552 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; } setColorSpace(sk_sp<SkColorSpace> colorSpace)553 void setColorSpace(sk_sp<SkColorSpace> colorSpace) override { fColorSpace = colorSpace; } 554 555 private: 556 SkColorType fColorType; 557 sk_sp<SkColorSpace> fColorSpace; 558 }; 559 560 class SKPSink : public Sink { 561 public: 562 SKPSink(); 563 564 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()565 const char* fileExtension() const override { return "skp"; } flags()566 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 567 }; 568 569 class DebugSink : public Sink { 570 public: 571 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()572 const char* fileExtension() const override { return "json"; } flags()573 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 574 }; 575 576 class SVGSink : public Sink { 577 public: 578 SVGSink(int pageIndex = 0); 579 580 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; fileExtension()581 const char* fileExtension() const override { return "svg"; } flags()582 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; } 583 584 private: 585 int fPageIndex; 586 }; 587 588 #ifdef SK_GRAPHITE_ENABLED 589 590 class GraphiteSink : public Sink { 591 public: 592 using ContextType = skiatest::graphite::ContextFactory::ContextType; 593 594 GraphiteSink(const SkCommandLineConfigGraphite*); 595 596 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; serial()597 bool serial() const override { return true; } fileExtension()598 const char* fileExtension() const override { return "png"; } flags()599 SinkFlags flags() const override { return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect }; } 600 601 private: 602 ContextType fContextType; 603 SkColorType fColorType; 604 SkAlphaType fAlphaType; 605 bool fTestPrecompile; 606 }; 607 608 #endif 609 610 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 611 612 class Via : public Sink { 613 public: Via(Sink * sink)614 explicit Via(Sink* sink) : fSink(sink) {} fileExtension()615 const char* fileExtension() const override { return fSink->fileExtension(); } serial()616 bool serial() const override { return fSink->serial(); } flags()617 SinkFlags flags() const override { 618 SinkFlags flags = fSink->flags(); 619 flags.approach = SinkFlags::kIndirect; 620 return flags; 621 } setColorSpace(sk_sp<SkColorSpace> colorSpace)622 void setColorSpace(sk_sp<SkColorSpace> colorSpace) override { 623 fSink->setColorSpace(colorSpace); 624 } 625 protected: 626 std::unique_ptr<Sink> fSink; 627 }; 628 629 class ViaMatrix : public Via { 630 public: 631 ViaMatrix(SkMatrix, Sink*); 632 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 633 private: 634 const SkMatrix fMatrix; 635 }; 636 637 class ViaUpright : public Via { 638 public: 639 ViaUpright(SkMatrix, Sink*); 640 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 641 private: 642 const SkMatrix fMatrix; 643 }; 644 645 class ViaSerialization : public Via { 646 public: ViaSerialization(Sink * sink)647 explicit ViaSerialization(Sink* sink) : Via(sink) {} 648 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 649 }; 650 651 class ViaPicture : public Via { 652 public: ViaPicture(Sink * sink)653 explicit ViaPicture(Sink* sink) : Via(sink) {} 654 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 655 }; 656 657 class ViaRuntimeBlend : public Via { 658 public: ViaRuntimeBlend(Sink * sink)659 explicit ViaRuntimeBlend(Sink* sink) : Via(sink) {} 660 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 661 }; 662 663 class ViaSVG : public Via { 664 public: ViaSVG(Sink * sink)665 explicit ViaSVG(Sink* sink) : Via(sink) {} 666 Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; 667 }; 668 669 } // namespace DM 670 671 #endif//DMSrcSink_DEFINED 672