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