Home | History | Annotate | Download | only in tools
      1 /*
      2  * Copyright 2014 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 image_expectations_DEFINED
      9 #define image_expectations_DEFINED
     10 
     11 #include "SkBitmap.h"
     12 #include "SkJSONCPP.h"
     13 #include "SkOSFile.h"
     14 #include "SkRefCnt.h"
     15 
     16 namespace sk_tools {
     17 
     18     /**
     19      * The digest of an image (either an image we have generated locally, or an image expectation).
     20      *
     21      * Currently, this is always a uint64_t hash digest of an SkBitmap.
     22      */
     23     class ImageDigest : public SkRefCnt {
     24     public:
     25         /**
     26          * Create an ImageDigest of a bitmap.
     27          *
     28          * Note that this is an expensive operation, because it has to examine all pixels in
     29          * the bitmap.  You may wish to consider using the BitmapAndDigest class, which will
     30          * compute the ImageDigest lazily.
     31          *
     32          * @param bitmap image to get the digest of
     33          */
     34         explicit ImageDigest(const SkBitmap &bitmap);
     35 
     36         /**
     37          * Create an ImageDigest using a hashType/hashValue pair.
     38          *
     39          * @param hashType the algorithm used to generate the hash; for now, only
     40          *     kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5 is allowed.
     41          * @param hashValue the value generated by the hash algorithm for a particular image.
     42          */
     43         explicit ImageDigest(const SkString &hashType, uint64_t hashValue);
     44 
     45         /**
     46          * Returns the hash digest type as an SkString.
     47          *
     48          * For now, this always returns kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5 .
     49          */
     50         SkString getHashType() const;
     51 
     52         /**
     53          * Returns the hash digest value as a uint64_t.
     54          */
     55         uint64_t getHashValue() const;
     56 
     57     private:
     58         uint64_t fHashValue;
     59     };
     60 
     61     /**
     62      * Container that holds a reference to an SkBitmap and computes its ImageDigest lazily.
     63      *
     64      * Computing the ImageDigest can be expensive, so this can help you postpone (or maybe even
     65      * avoid) that work.
     66      */
     67     class BitmapAndDigest {
     68     public:
     69         explicit BitmapAndDigest(const SkBitmap &bitmap);
     70 
     71         const ImageDigest *getImageDigestPtr();
     72         const SkBitmap *getBitmapPtr() const;
     73     private:
     74         const SkBitmap fBitmap;
     75         SkAutoTUnref<ImageDigest> fImageDigestRef;
     76     };
     77 
     78     /**
     79      * Collects ImageDigests of actually rendered images, perhaps comparing to expectations.
     80      */
     81     class ImageResultsAndExpectations {
     82     public:
     83         /**
     84          * Adds expectations from a JSON file, returning true if successful.
     85          *
     86          * If the file exists but is empty, it succeeds, and there will be no expectations.
     87          * If the file does not exist, this will fail.
     88          *
     89          * Reasoning:
     90          * Generating expectations the first time can be a tricky chicken-and-egg
     91          * proposition.  "I need actual results to turn into expectations... but the only
     92          * way to get actual results is to run the tool, and the tool won't run without
     93          * expectations!"
     94          * We could make the tool run even if there is no expectations file at all, but it's
     95          * better for the tool to fail if the expectations file is not found--that will tell us
     96          * quickly if files are not being copied around as they should be.
     97          * Creating an empty file is an easy way to break the chicken-and-egg cycle and generate
     98          * the first real expectations.
     99          */
    100         bool readExpectationsFile(const char *jsonPath);
    101 
    102         /**
    103          * Adds this image to the summary of results.
    104          *
    105          * @param sourceName name of the source file that generated this result
    106          * @param fileName relative path to the image output file on local disk
    107          * @param digest description of the image's contents
    108          * @param tileNumber if not NULL, pointer to tile number
    109          */
    110         void add(const char *sourceName, const char *fileName, const ImageDigest &digest,
    111                  const int *tileNumber=NULL);
    112 
    113         /**
    114          * Returns true if this test result matches its expectations.
    115          * If there are no expectations for this test result, this will return false.
    116          *
    117          * @param sourceName name of the source file that generated this result
    118          * @param digest description of the image's contents
    119          * @param tileNumber if not NULL, pointer to tile number
    120          */
    121         bool matchesExpectation(const char *sourceName, const ImageDigest &digest,
    122                                 const int *tileNumber=NULL);
    123 
    124         /**
    125          * Writes the summary (as constructed so far) to a file.
    126          *
    127          * @param filename path to write the summary to
    128          */
    129         void writeToFile(const char *filename) const;
    130 
    131     private:
    132 
    133         /**
    134          * Read the file contents from filePtr and parse them into jsonRoot.
    135          *
    136          * It is up to the caller to close filePtr after this is done.
    137          *
    138          * Returns true if successful.
    139          */
    140         static bool Parse(SkFILE* filePtr, Json::Value *jsonRoot);
    141 
    142         Json::Value fActualResults;
    143         Json::Value fExpectedJsonRoot;
    144         Json::Value fExpectedResults;
    145     };
    146 
    147 } // namespace sk_tools
    148 
    149 #endif  // image_expectations_DEFINED
    150