• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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