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 "SkBBHFactory.h"
12 #include "SkBBoxHierarchy.h"
13 #include "SkBitmap.h"
14 #include "SkBitmapRegionDecoder.h"
15 #include "SkCanvas.h"
16 #include "SkCommonFlagsConfig.h"
17 #include "SkData.h"
18 #include "SkMultiPictureDocument.h"
19 #include "SkPicture.h"
20 #include "gm.h"
21 
22 //#define TEST_VIA_SVG
23 
24 namespace DM {
25 
26 // This is just convenience.  It lets you use either return "foo" or return SkStringPrintf(...).
27 struct ImplicitString : public SkString {
28     template <typename T>
ImplicitStringImplicitString29     ImplicitString(const T& s) : SkString(s) {}
ImplicitStringImplicitString30     ImplicitString() : SkString("") {}
31 };
32 typedef ImplicitString Name;
33 typedef ImplicitString Path;
34 
35 class Error {
36 public:
Error(const SkString & s)37     Error(const SkString& s) : fMsg(s), fFatal(!this->isEmpty()) {}
Error(const char * s)38     Error(const char* s)     : fMsg(s), fFatal(!this->isEmpty()) {}
39 
40     Error(const Error&)            = default;
41     Error& operator=(const Error&) = default;
42 
Nonfatal(const SkString & s)43     static Error Nonfatal(const SkString& s) { return Nonfatal(s.c_str()); }
Nonfatal(const char * s)44     static Error Nonfatal(const char* s) {
45         Error e(s);
46         e.fFatal = false;
47         return e;
48     }
49 
c_str()50     const char* c_str() const { return fMsg.c_str(); }
isEmpty()51     bool isEmpty() const { return fMsg.isEmpty(); }
isFatal()52     bool isFatal() const { return fFatal; }
53 
54 private:
55     SkString fMsg;
56     bool     fFatal;
57 };
58 
59 struct SinkFlags {
60     enum Type { kNull, kGPU, kVector, kRaster } type;
61     enum Approach { kDirect, kIndirect } approach;
62     enum Multisampled { kNotMultisampled, kMultisampled } multisampled;
63     SinkFlags(Type t, Approach a, Multisampled ms = kNotMultisampled)
typeSinkFlags64             : type(t), approach(a), multisampled(ms) {}
65 };
66 
67 struct Src {
~SrcSrc68     virtual ~Src() {}
69     virtual Error SK_WARN_UNUSED_RESULT draw(SkCanvas*) const = 0;
70     virtual SkISize size() const = 0;
71     virtual Name name() const = 0;
modifyGrContextOptionsSrc72     virtual void modifyGrContextOptions(GrContextOptions* options) const {}
vetoSrc73     virtual bool veto(SinkFlags) const { return false; }
74 
pageCountSrc75     virtual int pageCount() const { return 1; }
drawSrc76     virtual Error SK_WARN_UNUSED_RESULT draw(int, SkCanvas* canvas) const {
77         return this->draw(canvas);
78     }
sizeSrc79     virtual SkISize size(int) const { return this->size(); }
80     // Force Tasks using this Src to run on the main thread?
serialSrc81     virtual bool serial() const { return false; }
82 };
83 
84 struct Sink {
~SinkSink85     virtual ~Sink() {}
86     // You may write to either the bitmap or stream.  If you write to log, we'll print that out.
87     virtual Error SK_WARN_UNUSED_RESULT draw(const Src&, SkBitmap*, SkWStream*, SkString* log)
88         const = 0;
89 
90     // Force Tasks using this Sink to run on the main thread?
serialSink91     virtual bool serial() const { return false; }
92 
93     // File extension for the content draw() outputs, e.g. "png", "pdf".
94     virtual const char* fileExtension() const  = 0;
95 
96     virtual SinkFlags flags() const = 0;
97 };
98 
99 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
100 
101 class GMSrc : public Src {
102 public:
103     explicit GMSrc(skiagm::GMFactory);
104 
105     Error draw(SkCanvas*) const override;
106     SkISize size() const override;
107     Name name() const override;
108     void modifyGrContextOptions(GrContextOptions* options) const override;
109 
110 private:
111     skiagm::GMFactory fFactory;
112 };
113 
114 class CodecSrc : public Src {
115 public:
116     enum Mode {
117         kCodec_Mode,
118         // We choose to test only one mode with zero initialized memory.
119         // This will exercise all of the interesting cases in SkSwizzler
120         // without doubling the size of our test suite.
121         kCodecZeroInit_Mode,
122         kScanline_Mode,
123         kStripe_Mode, // Tests the skipping of scanlines
124         kCroppedScanline_Mode, // Tests (jpeg) cropped scanline optimization
125         kSubset_Mode, // For codecs that support subsets directly.
126         kAnimated_Mode, // For codecs that support animation.
127     };
128     enum DstColorType {
129         kGetFromCanvas_DstColorType,
130         kGrayscale_Always_DstColorType,
131         kNonNative8888_Always_DstColorType,
132     };
133     CodecSrc(Path, Mode, DstColorType, SkAlphaType, float);
134 
135     Error draw(SkCanvas*) const override;
136     SkISize size() const override;
137     Name name() const override;
veto(SinkFlags)138     bool veto(SinkFlags) const override;
139     bool serial() const override { return fRunSerially; }
140 private:
141     Path                    fPath;
142     Mode                    fMode;
143     DstColorType            fDstColorType;
144     SkAlphaType             fDstAlphaType;
145     float                   fScale;
146     bool                    fRunSerially;
147 };
148 
149 class AndroidCodecSrc : public Src {
150 public:
151     AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
152 
153     Error draw(SkCanvas*) const override;
154     SkISize size() const override;
155     Name name() const override;
veto(SinkFlags)156     bool veto(SinkFlags) const override;
157     bool serial() const override { return fRunSerially; }
158 private:
159     Path                    fPath;
160     CodecSrc::DstColorType  fDstColorType;
161     SkAlphaType             fDstAlphaType;
162     int                     fSampleSize;
163     bool                    fRunSerially;
164 };
165 
166 // Allows for testing of various implementations of Android's BitmapRegionDecoder
167 class BRDSrc : public Src {
168 public:
169     enum Mode {
170         // Decode the entire image as one region.
171         kFullImage_Mode,
172         // Splits the image into multiple regions using a divisor and decodes the regions
173         // separately.  Also, this test adds a border of a few pixels to each of the regions
174         // that it is decoding.  This tests the behavior when a client asks for a region that
175         // does not fully fit in the image.
176         kDivisor_Mode,
177     };
178 
179     BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t);
180 
181     Error draw(SkCanvas*) const override;
182     SkISize size() const override;
183     Name name() const override;
184     bool veto(SinkFlags) const override;
185 private:
186     Path                                     fPath;
187     Mode                                     fMode;
188     CodecSrc::DstColorType                   fDstColorType;
189     uint32_t                                 fSampleSize;
190 };
191 
192 class ImageGenSrc : public Src {
193 public:
194     enum Mode {
195         kCodec_Mode,    // Use CodecImageGenerator
196         kPlatform_Mode, // Uses CG or WIC
197     };
198     ImageGenSrc(Path, Mode, SkAlphaType, bool);
199 
200     Error draw(SkCanvas*) const override;
201     SkISize size() const override;
202     Name name() const override;
veto(SinkFlags)203     bool veto(SinkFlags) const override;
204     bool serial() const override { return fRunSerially; }
205 private:
206     Path        fPath;
207     Mode        fMode;
208     SkAlphaType fDstAlphaType;
209     bool        fIsGpu;
210     bool        fRunSerially;
211 };
212 
213 class ColorCodecSrc : public Src {
214 public:
215     ColorCodecSrc(Path, bool decode_to_dst);
216 
217     Error draw(SkCanvas*) const override;
218     SkISize size() const override;
219     Name name() const override;
220     bool veto(SinkFlags) const override;
221 private:
222     Path fPath;
223     bool fDecodeToDst;
224 };
225 
226 class SKPSrc : public Src {
227 public:
228     explicit SKPSrc(Path path);
229 
230     Error draw(SkCanvas*) const override;
231     SkISize size() const override;
232     Name name() const override;
233 private:
234     Path fPath;
235 };
236 
237 // This class extracts all the paths from an SKP and then removes unwanted paths according to the
238 // provided l/r trail. It then just draws the remaining paths. (Non-path draws are thrown out.) It
239 // is useful for finding a reduced repo case for path drawing bugs.
240 class BisectSrc : public SKPSrc {
241 public:
242     explicit BisectSrc(Path path, const char* trail);
243 
244     Error draw(SkCanvas*) const override;
245 
246 private:
247     SkString fTrail;
248 
249     typedef SKPSrc INHERITED;
250 };
251 
252 
253 #if defined(SK_ENABLE_SKOTTIE)
254 class SkottieSrc final : public Src {
255 public:
256     explicit SkottieSrc(Path path);
257 
258     Error draw(SkCanvas*) const override;
259     SkISize size() const override;
260     Name name() const override;
261     bool veto(SinkFlags) const override;
262 
263 private:
264     // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames.
265     static constexpr int      kTileCount = 5;
266 
267     // Fit kTileCount x kTileCount frames to a 1000x1000 film strip.
268     static constexpr SkScalar kTargetSize = 1000;
269     static constexpr SkScalar kTileSize = kTargetSize / kTileCount;
270 
271     Path                      fPath;
272 };
273 #endif
274 
275 #if defined(SK_XML)
276 } // namespace DM
277 
278 class SkSVGDOM;
279 
280 namespace DM {
281 
282 class SVGSrc : public Src {
283 public:
284     explicit SVGSrc(Path path);
285 
286     Error draw(SkCanvas*) const override;
287     SkISize size() const override;
288     Name name() const override;
289     bool veto(SinkFlags) const override;
290 
291 private:
292     Name            fName;
293     sk_sp<SkSVGDOM> fDom;
294     SkScalar        fScale;
295 
296     typedef Src INHERITED;
297 };
298 #endif // SK_XML
299 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
300 
301 class MSKPSrc : public Src {
302 public:
303     explicit MSKPSrc(Path path);
304 
305     int pageCount() const override;
306     Error draw(SkCanvas* c) const override;
307     Error draw(int, SkCanvas*) const override;
308     SkISize size() const override;
309     SkISize size(int) const override;
310     Name name() const override;
311 
312 private:
313     Path fPath;
314     mutable SkTArray<SkDocumentPage> fPages;
315 };
316 
317 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
318 
319 class NullSink : public Sink {
320 public:
NullSink()321     NullSink() {}
322 
323     Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()324     const char* fileExtension() const override { return ""; }
flags()325     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
326 };
327 
328 class GPUSink : public Sink {
329 public:
330     GPUSink(sk_gpu_test::GrContextFactory::ContextType,
331             sk_gpu_test::GrContextFactory::ContextOverrides,
332             SkCommandLineConfigGpu::SurfType surfType, int samples, bool diText,
333             SkColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace,
334             bool threaded, const GrContextOptions& grCtxOptions);
335 
336     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
337     Error onDraw(const Src&, SkBitmap*, SkWStream*, SkString*,
338                  const GrContextOptions& baseOptions) const;
339 
contextType()340     sk_gpu_test::GrContextFactory::ContextType contextType() const { return fContextType; }
contextOverrides()341     const sk_gpu_test::GrContextFactory::ContextOverrides& contextOverrides() {
342         return fContextOverrides;
343     }
surfType()344     SkCommandLineConfigGpu::SurfType surfType() const { return fSurfType; }
useDIText()345     bool useDIText() const { return fUseDIText; }
serial()346     bool serial() const override { return !fThreaded; }
fileExtension()347     const char* fileExtension() const override { return "png"; }
flags()348     SinkFlags flags() const override {
349         SinkFlags::Multisampled ms = fSampleCount > 1 ? SinkFlags::kMultisampled
350                                                       : SinkFlags::kNotMultisampled;
351         return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms };
352     }
baseContextOptions()353     const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; }
354 
355 private:
356     sk_gpu_test::GrContextFactory::ContextType        fContextType;
357     sk_gpu_test::GrContextFactory::ContextOverrides   fContextOverrides;
358     SkCommandLineConfigGpu::SurfType                  fSurfType;
359     int                                               fSampleCount;
360     bool                                              fUseDIText;
361     SkColorType                                       fColorType;
362     SkAlphaType                                       fAlphaType;
363     sk_sp<SkColorSpace>                               fColorSpace;
364     bool                                              fThreaded;
365     GrContextOptions                                  fBaseContextOptions;
366 };
367 
368 class GPUThreadTestingSink : public GPUSink {
369 public:
370     GPUThreadTestingSink(sk_gpu_test::GrContextFactory::ContextType,
371                          sk_gpu_test::GrContextFactory::ContextOverrides,
372                          SkCommandLineConfigGpu::SurfType surfType, int samples, bool diText,
373                          SkColorType colorType, SkAlphaType alphaType,
374                          sk_sp<SkColorSpace> colorSpace, bool threaded,
375                          const GrContextOptions& grCtxOptions);
376 
377     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
378 
fileExtension()379     const char* fileExtension() const override {
380         // Suppress writing out results from this config - we just want to do our matching test
381         return nullptr;
382     }
383 
384 private:
385     std::unique_ptr<SkExecutor> fExecutor;
386 
387     typedef GPUSink INHERITED;
388 };
389 
390 class GPUPersistentCacheTestingSink : public GPUSink {
391 public:
392     GPUPersistentCacheTestingSink(sk_gpu_test::GrContextFactory::ContextType,
393                                   sk_gpu_test::GrContextFactory::ContextOverrides,
394                                   SkCommandLineConfigGpu::SurfType surfType, int samples,
395                                   bool diText, SkColorType colorType, SkAlphaType alphaType,
396                                   sk_sp<SkColorSpace> colorSpace, bool threaded,
397                                   const GrContextOptions& grCtxOptions);
398 
399     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
400 
fileExtension()401     const char* fileExtension() const override {
402         // Suppress writing out results from this config - we just want to do our matching test
403         return nullptr;
404     }
405 
406 private:
407     typedef GPUSink INHERITED;
408 };
409 
410 class PDFSink : public Sink {
411 public:
PDFSink(bool pdfa,SkScalar rasterDpi)412     PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {}
413     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()414     const char* fileExtension() const override { return "pdf"; }
flags()415     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
416     bool fPDFA;
417     SkScalar fRasterDpi;
418 };
419 
420 class XPSSink : public Sink {
421 public:
422     XPSSink();
423 
424     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()425     const char* fileExtension() const override { return "xps"; }
flags()426     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
427 };
428 
429 class RasterSink : public Sink {
430 public:
431     explicit RasterSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
432 
433     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()434     const char* fileExtension() const override { return "png"; }
flags()435     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
436 
437 private:
438     SkColorType         fColorType;
439     sk_sp<SkColorSpace> fColorSpace;
440 };
441 
442 class ThreadedSink : public RasterSink {
443 public:
444     explicit ThreadedSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
445     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
446 };
447 
448 class SKPSink : public Sink {
449 public:
450     SKPSink();
451 
452     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()453     const char* fileExtension() const override { return "skp"; }
flags()454     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
455 };
456 
457 class DebugSink : public Sink {
458 public:
459     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()460     const char* fileExtension() const override { return "json"; }
flags()461     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
462 };
463 
464 class SVGSink : public Sink {
465 public:
466     SVGSink(int pageIndex = 0);
467 
468     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()469     const char* fileExtension() const override { return "svg"; }
flags()470     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
471 
472 private:
473     int fPageIndex;
474 };
475 
476 
477 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
478 
479 class Via : public Sink {
480 public:
Via(Sink * sink)481     explicit Via(Sink* sink) : fSink(sink) {}
fileExtension()482     const char* fileExtension() const override { return fSink->fileExtension(); }
serial()483     bool               serial() const override { return fSink->serial(); }
flags()484     SinkFlags flags() const override {
485         SinkFlags flags = fSink->flags();
486         flags.approach = SinkFlags::kIndirect;
487         return flags;
488     }
489 protected:
490     std::unique_ptr<Sink> fSink;
491 };
492 
493 class ViaMatrix : public Via {
494 public:
495     ViaMatrix(SkMatrix, Sink*);
496     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
497 private:
498     const SkMatrix fMatrix;
499 };
500 
501 class ViaUpright : public Via {
502 public:
503     ViaUpright(SkMatrix, Sink*);
504     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
505 private:
506     const SkMatrix fMatrix;
507 };
508 
509 class ViaSerialization : public Via {
510 public:
ViaSerialization(Sink * sink)511     explicit ViaSerialization(Sink* sink) : Via(sink) {}
512     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
513 };
514 
515 class ViaPicture : public Via {
516 public:
ViaPicture(Sink * sink)517     explicit ViaPicture(Sink* sink) : Via(sink) {}
518     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
519 };
520 
521 class ViaTiles : public Via {
522 public:
523     ViaTiles(int w, int h, SkBBHFactory*, Sink*);
524     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
525 private:
526     const int                   fW, fH;
527     std::unique_ptr<SkBBHFactory> fFactory;
528 };
529 
530 class ViaDDL : public Via {
531 public:
532     ViaDDL(int numReplays, int numDivisions, Sink* sink);
533     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
534 private:
535     const int fNumReplays;
536     const int fNumDivisions;
537 };
538 
539 class ViaSVG : public Via {
540 public:
ViaSVG(Sink * sink)541     explicit ViaSVG(Sink* sink) : Via(sink) {}
542     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
543 };
544 
545 class ViaLite : public Via {
546 public:
ViaLite(Sink * sink)547     explicit ViaLite(Sink* sink) : Via(sink) {}
548     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
549 };
550 
551 class ViaCSXform : public Via {
552 public:
553     explicit ViaCSXform(Sink*, sk_sp<SkColorSpace>, bool colorSpin);
554     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
555 private:
556     sk_sp<SkColorSpace> fCS;
557     bool                fColorSpin;
558 };
559 
560 }  // namespace DM
561 
562 #endif//DMSrcSink_DEFINED
563