• 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(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