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