/* * Copyright 2014 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef image_expectations_DEFINED #define image_expectations_DEFINED #include "SkBitmap.h" #include "SkJSONCPP.h" #include "SkOSFile.h" #include "SkRefCnt.h" namespace sk_tools { /** * The digest of an image (either an image we have generated locally, or an image expectation). * * Currently, this is always a uint64_t hash digest of an SkBitmap. */ class ImageDigest : public SkRefCnt { public: /** * Create an ImageDigest of a bitmap. * * Note that this is an expensive operation, because it has to examine all pixels in * the bitmap. You may wish to consider using the BitmapAndDigest class, which will * compute the ImageDigest lazily. * * @param bitmap image to get the digest of */ explicit ImageDigest(const SkBitmap &bitmap); /** * Create an ImageDigest using a hashType/hashValue pair. * * @param hashType the algorithm used to generate the hash; for now, only * kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5 is allowed. * @param hashValue the value generated by the hash algorithm for a particular image. */ explicit ImageDigest(const SkString &hashType, uint64_t hashValue); /** * Returns the hash digest type as an SkString. * * For now, this always returns kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5 . */ SkString getHashType() const; /** * Returns the hash digest value as a uint64_t. */ uint64_t getHashValue() const; private: uint64_t fHashValue; }; /** * Container that holds a reference to an SkBitmap and computes its ImageDigest lazily. * * Computing the ImageDigest can be expensive, so this can help you postpone (or maybe even * avoid) that work. */ class BitmapAndDigest { public: explicit BitmapAndDigest(const SkBitmap &bitmap); const ImageDigest *getImageDigestPtr(); const SkBitmap *getBitmapPtr() const; private: const SkBitmap fBitmap; SkAutoTUnref fImageDigestRef; }; /** * Collects ImageDigests of actually rendered images, perhaps comparing to expectations. */ class ImageResultsAndExpectations { public: /** * Adds expectations from a JSON file, returning true if successful. * * If the file exists but is empty, it succeeds, and there will be no expectations. * If the file does not exist, this will fail. * * Reasoning: * Generating expectations the first time can be a tricky chicken-and-egg * proposition. "I need actual results to turn into expectations... but the only * way to get actual results is to run the tool, and the tool won't run without * expectations!" * We could make the tool run even if there is no expectations file at all, but it's * better for the tool to fail if the expectations file is not found--that will tell us * quickly if files are not being copied around as they should be. * Creating an empty file is an easy way to break the chicken-and-egg cycle and generate * the first real expectations. */ bool readExpectationsFile(const char *jsonPath); /** * Adds this image to the summary of results. * * @param sourceName name of the source file that generated this result * @param fileName relative path to the image output file on local disk * @param digest description of the image's contents * @param tileNumber if not NULL, pointer to tile number */ void add(const char *sourceName, const char *fileName, const ImageDigest &digest, const int *tileNumber=NULL); /** * Adds a key/value pair to the descriptions dict within the summary of results. * * @param key key within the descriptions dict * @param value value to associate with that key */ void addDescription(const char *key, const char *value); /** * Returns true if this test result matches its expectations. * If there are no expectations for this test result, this will return false. * * @param sourceName name of the source file that generated this result * @param digest description of the image's contents * @param tileNumber if not NULL, pointer to tile number */ bool matchesExpectation(const char *sourceName, const ImageDigest &digest, const int *tileNumber=NULL); /** * Writes the summary (as constructed so far) to a file. * * @param filename path to write the summary to */ void writeToFile(const char *filename) const; private: /** * Read the file contents from filePtr and parse them into jsonRoot. * * It is up to the caller to close filePtr after this is done. * * Returns true if successful. */ static bool Parse(SkFILE* filePtr, Json::Value *jsonRoot); Json::Value fActualResults; Json::Value fDescriptions; Json::Value fExpectedJsonRoot; Json::Value fExpectedResults; }; } // namespace sk_tools #endif // image_expectations_DEFINED