• 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 "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     enum Mode {
216         // Mimic legacy behavior and apply no color correction.
217         kBaseline_Mode,
218 
219         // Color correct images into a specific dst color space.  If you happen to have this
220         // monitor, you're in luck!  The unmarked outputs of this test should display
221         // correctly on this monitor in the Chrome browser.  If not, it's useful to know
222         // that this monitor has a profile that is fairly similar to Adobe RGB.
223         kDst_HPZR30w_Mode,
224 
225         kDst_sRGB_Mode,
226     };
227 
228     ColorCodecSrc(Path, Mode, SkColorType);
229 
230     Error draw(SkCanvas*) const override;
231     SkISize size() const override;
232     Name name() const override;
233     bool veto(SinkFlags) const override;
234 private:
235     Path                    fPath;
236     Mode                    fMode;
237     SkColorType             fColorType;
238 };
239 
240 class SKPSrc : public Src {
241 public:
242     explicit SKPSrc(Path path);
243 
244     Error draw(SkCanvas*) const override;
245     SkISize size() const override;
246     Name name() const override;
247 private:
248     Path fPath;
249 };
250 
251 // This class extracts all the paths from an SKP and then removes unwanted paths according to the
252 // provided l/r trail. It then just draws the remaining paths. (Non-path draws are thrown out.) It
253 // is useful for finding a reduced repo case for path drawing bugs.
254 class BisectSrc : public SKPSrc {
255 public:
256     explicit BisectSrc(Path path, const char* trail);
257 
258     Error draw(SkCanvas*) const override;
259 
260 private:
261     SkString fTrail;
262 
263     typedef SKPSrc INHERITED;
264 };
265 
266 
267 #if defined(SK_ENABLE_SKOTTIE)
268 class SkottieSrc final : public Src {
269 public:
270     explicit SkottieSrc(Path path);
271 
272     Error draw(SkCanvas*) const override;
273     SkISize size() const override;
274     Name name() const override;
275     bool veto(SinkFlags) const override;
276 
277 private:
278     // Generates a kTileCount x kTileCount filmstrip with evenly distributed frames.
279     static constexpr int      kTileCount = 5;
280 
281     // Fit kTileCount x kTileCount frames to a 1000x1000 film strip.
282     static constexpr SkScalar kTargetSize = 1000;
283     static constexpr SkScalar kTileSize = kTargetSize / kTileCount;
284 
285     Path                      fPath;
286 };
287 #endif
288 
289 #if defined(SK_XML)
290 } // namespace DM
291 
292 class SkSVGDOM;
293 
294 namespace DM {
295 
296 class SVGSrc : public Src {
297 public:
298     explicit SVGSrc(Path path);
299 
300     Error draw(SkCanvas*) const override;
301     SkISize size() const override;
302     Name name() const override;
303     bool veto(SinkFlags) const override;
304 
305 private:
306     Name            fName;
307     sk_sp<SkSVGDOM> fDom;
308     SkScalar        fScale;
309 
310     typedef Src INHERITED;
311 };
312 #endif // SK_XML
313 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
314 
315 class MSKPSrc : public Src {
316 public:
317     explicit MSKPSrc(Path path);
318 
319     int pageCount() const override;
320     Error draw(SkCanvas* c) const override;
321     Error draw(int, SkCanvas*) const override;
322     SkISize size() const override;
323     SkISize size(int) const override;
324     Name name() const override;
325 
326 private:
327     Path fPath;
328     mutable SkTArray<SkDocumentPage> fPages;
329 };
330 
331 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
332 
333 class NullSink : public Sink {
334 public:
NullSink()335     NullSink() {}
336 
337     Error draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()338     const char* fileExtension() const override { return ""; }
flags()339     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kNull, SinkFlags::kDirect }; }
340 };
341 
342 class GPUSink : public Sink {
343 public:
344     GPUSink(sk_gpu_test::GrContextFactory::ContextType,
345             sk_gpu_test::GrContextFactory::ContextOverrides,
346             SkCommandLineConfigGpu::SurfType surfType, int samples, bool diText,
347             SkColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace,
348             bool threaded, const GrContextOptions& grCtxOptions);
349 
350     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
351     Error onDraw(const Src&, SkBitmap*, SkWStream*, SkString*,
352                  const GrContextOptions& baseOptions) const;
353 
contextType()354     sk_gpu_test::GrContextFactory::ContextType contextType() const { return fContextType; }
contextOverrides()355     const sk_gpu_test::GrContextFactory::ContextOverrides& contextOverrides() {
356         return fContextOverrides;
357     }
surfType()358     SkCommandLineConfigGpu::SurfType surfType() const { return fSurfType; }
useDIText()359     bool useDIText() const { return fUseDIText; }
serial()360     bool serial() const override { return !fThreaded; }
fileExtension()361     const char* fileExtension() const override { return "png"; }
flags()362     SinkFlags flags() const override {
363         SinkFlags::Multisampled ms = fSampleCount > 1 ? SinkFlags::kMultisampled
364                                                       : SinkFlags::kNotMultisampled;
365         return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms };
366     }
baseContextOptions()367     const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; }
368 
369 private:
370     sk_gpu_test::GrContextFactory::ContextType        fContextType;
371     sk_gpu_test::GrContextFactory::ContextOverrides   fContextOverrides;
372     SkCommandLineConfigGpu::SurfType                  fSurfType;
373     int                                               fSampleCount;
374     bool                                              fUseDIText;
375     SkColorType                                       fColorType;
376     SkAlphaType                                       fAlphaType;
377     sk_sp<SkColorSpace>                               fColorSpace;
378     bool                                              fThreaded;
379     GrContextOptions                                  fBaseContextOptions;
380 };
381 
382 class GPUThreadTestingSink : public GPUSink {
383 public:
384     GPUThreadTestingSink(sk_gpu_test::GrContextFactory::ContextType,
385                          sk_gpu_test::GrContextFactory::ContextOverrides,
386                          SkCommandLineConfigGpu::SurfType surfType, int samples, bool diText,
387                          SkColorType colorType, SkAlphaType alphaType,
388                          sk_sp<SkColorSpace> colorSpace, bool threaded,
389                          const GrContextOptions& grCtxOptions);
390 
391     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
392 
fileExtension()393     const char* fileExtension() const override {
394         // Suppress writing out results from this config - we just want to do our matching test
395         return nullptr;
396     }
397 
398 private:
399     std::unique_ptr<SkExecutor> fExecutor;
400 
401     typedef GPUSink INHERITED;
402 };
403 
404 class GPUPersistentCacheTestingSink : public GPUSink {
405 public:
406     GPUPersistentCacheTestingSink(sk_gpu_test::GrContextFactory::ContextType,
407                                   sk_gpu_test::GrContextFactory::ContextOverrides,
408                                   SkCommandLineConfigGpu::SurfType surfType, int samples,
409                                   bool diText, SkColorType colorType, SkAlphaType alphaType,
410                                   sk_sp<SkColorSpace> colorSpace, bool threaded,
411                                   const GrContextOptions& grCtxOptions);
412 
413     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
414 
fileExtension()415     const char* fileExtension() const override {
416         // Suppress writing out results from this config - we just want to do our matching test
417         return nullptr;
418     }
419 
420 private:
421     typedef GPUSink INHERITED;
422 };
423 
424 class PDFSink : public Sink {
425 public:
PDFSink(bool pdfa,SkScalar rasterDpi)426     PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {}
427     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()428     const char* fileExtension() const override { return "pdf"; }
flags()429     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
430     bool fPDFA;
431     SkScalar fRasterDpi;
432 };
433 
434 class XPSSink : public Sink {
435 public:
436     XPSSink();
437 
438     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()439     const char* fileExtension() const override { return "xps"; }
flags()440     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
441 };
442 
443 class RasterSink : public Sink {
444 public:
445     explicit RasterSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
446 
447     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()448     const char* fileExtension() const override { return "png"; }
flags()449     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kRaster, SinkFlags::kDirect }; }
450 
451 private:
452     SkColorType         fColorType;
453     sk_sp<SkColorSpace> fColorSpace;
454 };
455 
456 class ThreadedSink : public RasterSink {
457 public:
458     explicit ThreadedSink(SkColorType, sk_sp<SkColorSpace> = nullptr);
459     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
460 };
461 
462 class SKPSink : public Sink {
463 public:
464     SKPSink();
465 
466     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()467     const char* fileExtension() const override { return "skp"; }
flags()468     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
469 };
470 
471 class DebugSink : public Sink {
472 public:
473     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()474     const char* fileExtension() const override { return "json"; }
flags()475     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
476 };
477 
478 class SVGSink : public Sink {
479 public:
480     SVGSink(int pageIndex = 0);
481 
482     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
fileExtension()483     const char* fileExtension() const override { return "svg"; }
flags()484     SinkFlags flags() const override { return SinkFlags{ SinkFlags::kVector, SinkFlags::kDirect }; }
485 
486 private:
487     int fPageIndex;
488 };
489 
490 
491 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
492 
493 class Via : public Sink {
494 public:
Via(Sink * sink)495     explicit Via(Sink* sink) : fSink(sink) {}
fileExtension()496     const char* fileExtension() const override { return fSink->fileExtension(); }
serial()497     bool               serial() const override { return fSink->serial(); }
flags()498     SinkFlags flags() const override {
499         SinkFlags flags = fSink->flags();
500         flags.approach = SinkFlags::kIndirect;
501         return flags;
502     }
503 protected:
504     std::unique_ptr<Sink> fSink;
505 };
506 
507 class ViaMatrix : public Via {
508 public:
509     ViaMatrix(SkMatrix, Sink*);
510     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
511 private:
512     const SkMatrix fMatrix;
513 };
514 
515 class ViaUpright : public Via {
516 public:
517     ViaUpright(SkMatrix, Sink*);
518     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
519 private:
520     const SkMatrix fMatrix;
521 };
522 
523 class ViaSerialization : public Via {
524 public:
ViaSerialization(Sink * sink)525     explicit ViaSerialization(Sink* sink) : Via(sink) {}
526     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
527 };
528 
529 class ViaPicture : public Via {
530 public:
ViaPicture(Sink * sink)531     explicit ViaPicture(Sink* sink) : Via(sink) {}
532     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
533 };
534 
535 class ViaTiles : public Via {
536 public:
537     ViaTiles(int w, int h, SkBBHFactory*, Sink*);
538     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
539 private:
540     const int                   fW, fH;
541     std::unique_ptr<SkBBHFactory> fFactory;
542 };
543 
544 class ViaDDL : public Via {
545 public:
546     ViaDDL(int numReplays, int numDivisions, Sink* sink);
547     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
548 private:
549     const int fNumReplays;
550     const int fNumDivisions;
551 };
552 
553 class ViaSVG : public Via {
554 public:
ViaSVG(Sink * sink)555     explicit ViaSVG(Sink* sink) : Via(sink) {}
556     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
557 };
558 
559 class ViaLite : public Via {
560 public:
ViaLite(Sink * sink)561     explicit ViaLite(Sink* sink) : Via(sink) {}
562     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
563 };
564 
565 class ViaCSXform : public Via {
566 public:
567     explicit ViaCSXform(Sink*, sk_sp<SkColorSpace>, bool colorSpin);
568     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
569 private:
570     sk_sp<SkColorSpace> fCS;
571     bool                fColorSpin;
572 };
573 
574 }  // namespace DM
575 
576 #endif//DMSrcSink_DEFINED
577