• 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 };
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