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