1 /* 2 * Copyright 2020 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 gmverifier_DEFINED 9 #define gmverifier_DEFINED 10 11 #include "include/core/SkColor.h" 12 #include "include/core/SkRect.h" 13 #include "include/core/SkString.h" 14 15 #include <vector> 16 17 class SkBitmap; 18 class SkColorInfo; 19 20 namespace skiagm { 21 22 class GM; 23 24 namespace verifiers { 25 26 /** Result type for GM verifiers. */ 27 class VerifierResult { 28 public: 29 VerifierResult(); 30 31 /** Returns true if the result is ok (non-error). */ 32 bool ok() const; 33 34 /** Returns reference to any message associated with the result. */ 35 const SkString& message() const; 36 37 /** Constructs an "ok" (non-error) result. */ 38 static VerifierResult Ok(); 39 40 /** Constructs a "fail" (error) result with a specific message. */ 41 static VerifierResult Fail(const SkString& msg); 42 43 private: 44 /** Underlying error code. */ 45 enum class Code { 46 kOk, kFail 47 }; 48 49 /** Result code */ 50 Code fCode; 51 52 /** Result message (may be empty). */ 53 SkString fMessage; 54 55 /** Private constructor for a result with a specific code and message. */ 56 VerifierResult(Code code, const SkString& msg); 57 }; 58 59 /** 60 * Abstract base class for GM verifiers. A verifier checks the rendered output image of a GM. 61 * 62 * Different verifiers perform different types of transforms and checks. Verifiers may check the 63 * output of a GM against a given "golden" image which represents the correct output, or just 64 * check the output image of the GM by itself. 65 * 66 * Most verifiers have configurable fuzziness in the comparisons performed against the golden image. 67 * 68 * Subclasses should inherit from one of StandaloneVerifier or GoldImageVerifier instead of 69 * directly from this base class. 70 */ 71 class GMVerifier { 72 public: 73 GMVerifier() = delete; 74 75 virtual ~GMVerifier(); 76 77 /** Returns the human-friendly name of the verifier. */ 78 virtual SkString name() const = 0; 79 80 /** Returns true if this verifier needs the gold image as input. */ 81 bool needsGoldImage() const; 82 83 /** 84 * Runs the verifier. This method should be used if the verifier needs the gold image as input. 85 * 86 * @param gold Bitmap containing the "correct" image. 87 * @param actual Bitmap containing rendered output of a GM. 88 * @return Ok if the verification passed, or an error if not. 89 */ 90 VerifierResult verify(const SkBitmap& gold, const SkBitmap& actual); 91 92 /** 93 * Runs the verifier. 94 * 95 * @param actual Bitmap containing rendered output of a GM. 96 * @return Ok if the verification passed, or an error if not. 97 */ 98 VerifierResult verify(const SkBitmap& actual); 99 100 /** Renders the GM using the "golden" configuration. This is common across all GMs/verifiers. */ 101 static SkBitmap RenderGoldBmp(skiagm::GM* gm, const SkColorInfo& colorInfo); 102 103 /** 104 * Gets the color information that all verifier inputs should be transformed into. 105 * 106 * The primary reason for having a single shared colorspace/color type is making per-pixel 107 * comparisons easier. Both the image under test and gold image are transformed into a shared 108 * colorspace which allows for getting per-pixel colors in SkColor4f. 109 */ 110 static SkColorInfo VerifierColorInfo(); 111 112 protected: 113 /** The type of input required for the verifier. */ 114 enum class InputType { 115 kGoldImageRequired, kStandalone 116 }; 117 118 /** Set depending if the verifier needs a golden image as an input. */ 119 InputType fInputType; 120 121 /** Constructor. */ 122 GMVerifier(InputType inputType); 123 124 /** Implementation of the verification. */ 125 virtual VerifierResult verifyWithGold( 126 const SkIRect& region, const SkBitmap& gold, const SkBitmap& actual) = 0; 127 128 /** Implementation of the verification. */ 129 virtual VerifierResult verify(const SkIRect& region, const SkBitmap& actual) = 0; 130 131 /** Returns an error result formatted appropriately. */ 132 VerifierResult makeError(const SkString& msg) const; 133 }; 134 135 /** 136 * A verifier that operates standalone on the given input image (no comparison against a golden 137 * image). 138 */ 139 class StandaloneVerifier : public GMVerifier { 140 public: StandaloneVerifier()141 StandaloneVerifier() : GMVerifier(InputType::kStandalone) {} 142 143 protected: verifyWithGold(const SkIRect &,const SkBitmap &,const SkBitmap &)144 VerifierResult verifyWithGold(const SkIRect&, const SkBitmap&, const SkBitmap&) final { 145 return makeError(SkString("Verifier does not accept gold image input")); 146 } 147 }; 148 149 /** 150 * A verifier that operates compares input image against a golden image. 151 */ 152 class GoldImageVerifier : public GMVerifier { 153 public: GoldImageVerifier()154 GoldImageVerifier() : GMVerifier(InputType::kGoldImageRequired) {} 155 156 protected: verify(const SkIRect &,const SkBitmap &)157 VerifierResult verify(const SkIRect&, const SkBitmap&) final { 158 return makeError(SkString("Verifier does not accept standalone input")); 159 } 160 }; 161 162 /** A list of GM verifiers. */ 163 class VerifierList { 164 public: 165 /** Constructs a VerifierList with the given gm instance. */ 166 explicit VerifierList(GM* gm); 167 168 /** Adds a verifier to the list of verifiers. */ 169 void add(std::unique_ptr<GMVerifier> verifier); 170 171 /** 172 * Runs all verifiers against the given input. If any verifiers fail, returns the first error. 173 * Else, returns ok. This version can be used if no verifiers in the list require the gold 174 * image as input. 175 */ 176 VerifierResult verifyAll(const SkColorInfo& colorInfo, const SkBitmap& actual); 177 178 private: 179 /** The parent GM instance of this VerifierList. */ 180 GM* fGM; 181 182 /** The list of verifiers. */ 183 std::vector<std::unique_ptr<GMVerifier>> fVerifiers; 184 185 /** After running, set to the first verifier that failed, or nullptr if none failed. */ 186 const GMVerifier* fFailedVerifier; 187 188 /** Returns true if any verifiers in the list need the gold image as input. */ 189 bool needsGoldImage() const; 190 }; 191 192 } // namespace verifiers 193 } // namespace skiagm 194 195 #endif 196