| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
| 9 #include "SkBitmapHasher.h" | 9 #include "SkBitmapHasher.h" |
| 10 #include "SkData.h" | 10 #include "SkData.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 const static char kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5[] = "bitmap-
64bitMD5"; | 46 const static char kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5[] = "bitmap-
64bitMD5"; |
| 47 const static char kJsonValue_Image_ComparisonResult_Failed[] = "failed"; | 47 const static char kJsonValue_Image_ComparisonResult_Failed[] = "failed"; |
| 48 const static char kJsonValue_Image_ComparisonResult_FailureIgnored[] = "failure-
ignored"; | 48 const static char kJsonValue_Image_ComparisonResult_FailureIgnored[] = "failure-
ignored"; |
| 49 const static char kJsonValue_Image_ComparisonResult_NoComparison[] = "no-compari
son"; | 49 const static char kJsonValue_Image_ComparisonResult_NoComparison[] = "no-compari
son"; |
| 50 const static char kJsonValue_Image_ComparisonResult_Succeeded[] = "succeeded"; | 50 const static char kJsonValue_Image_ComparisonResult_Succeeded[] = "succeeded"; |
| 51 | 51 |
| 52 namespace sk_tools { | 52 namespace sk_tools { |
| 53 | 53 |
| 54 // ImageDigest class... | 54 // ImageDigest class... |
| 55 | 55 |
| 56 ImageDigest::ImageDigest(const SkBitmap &bitmap) { | 56 ImageDigest::ImageDigest(const SkBitmap &bitmap) : |
| 57 if (!SkBitmapHasher::ComputeDigest(bitmap, &fHashValue)) { | 57 fBitmap(bitmap), fHashValue(0), fComputedHashValue(false) {} |
| 58 SkFAIL("unable to compute image digest"); | 58 |
| 59 ImageDigest::ImageDigest(const SkString &hashType, uint64_t hashValue) : |
| 60 fBitmap(), fHashValue(hashValue), fComputedHashValue(true) { |
| 61 if (!hashType.equals(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5))
{ |
| 62 SkDebugf("unsupported hashType '%s'\n", hashType.c_str()); |
| 63 SkFAIL("unsupported hashType (see above)"); |
| 59 } | 64 } |
| 60 } | 65 } |
| 61 | 66 |
| 62 ImageDigest::ImageDigest(const SkString &hashType, uint64_t hashValue) { | 67 bool ImageDigest::equals(ImageDigest &other) { |
| 63 if (!hashType.equals(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5))
{ | 68 // TODO(epoger): The current implementation assumes that this |
| 64 SkFAIL((SkString("unsupported hashType ")+=hashType).c_str()); | 69 // and other always have hashType kJsonKey_Hashtype_Bitmap_64bitMD5 |
| 65 } else { | 70 return (this->getHashValue() == other.getHashValue()); |
| 66 fHashValue = hashValue; | |
| 67 } | |
| 68 } | 71 } |
| 69 | 72 |
| 70 SkString ImageDigest::getHashType() const { | 73 SkString ImageDigest::getHashType() { |
| 71 // TODO(epoger): The current implementation assumes that the | 74 // TODO(epoger): The current implementation assumes that the |
| 72 // result digest is always of type kJsonValue_Image_ChecksumAlgorithm_Bi
tmap64bitMD5 . | 75 // result digest is always of type kJsonValue_Image_ChecksumAlgorithm_Bi
tmap64bitMD5 . |
| 73 return SkString(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5); | 76 return SkString(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5); |
| 74 } | 77 } |
| 75 | 78 |
| 76 uint64_t ImageDigest::getHashValue() const { | 79 uint64_t ImageDigest::getHashValue() { |
| 77 return fHashValue; | 80 if (!this->fComputedHashValue) { |
| 81 if (!SkBitmapHasher::ComputeDigest(this->fBitmap, &this->fHashValue)
) { |
| 82 SkFAIL("unable to compute image digest"); |
| 83 } |
| 84 this->fComputedHashValue = true; |
| 85 } |
| 86 return this->fHashValue; |
| 78 } | 87 } |
| 79 | 88 |
| 80 // BitmapAndDigest class... | 89 // BitmapAndDigest class... |
| 81 | 90 |
| 82 BitmapAndDigest::BitmapAndDigest(const SkBitmap &bitmap) : fBitmap(bitmap) { | 91 BitmapAndDigest::BitmapAndDigest(const SkBitmap &bitmap) : |
| 83 } | 92 fBitmap(bitmap), fImageDigest(bitmap) {} |
| 84 | 93 |
| 85 const ImageDigest *BitmapAndDigest::getImageDigestPtr() { | 94 const SkBitmap *BitmapAndDigest::getBitmapPtr() const {return &fBitmap;} |
| 86 if (NULL == fImageDigestRef.get()) { | |
| 87 fImageDigestRef.reset(SkNEW_ARGS(ImageDigest, (fBitmap))); | |
| 88 } | |
| 89 return fImageDigestRef.get(); | |
| 90 } | |
| 91 | 95 |
| 92 const SkBitmap *BitmapAndDigest::getBitmapPtr() const { | 96 ImageDigest *BitmapAndDigest::getImageDigestPtr() {return &fImageDigest;} |
| 93 return &fBitmap; | 97 |
| 98 // Expectation class... |
| 99 |
| 100 // For when we need a valid ImageDigest, but we don't care what it is. |
| 101 static const ImageDigest kDummyImageDigest( |
| 102 SkString(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5), 0); |
| 103 |
| 104 Expectation::Expectation(bool ignoreFailure) : |
| 105 fIsEmpty(true), fIgnoreFailure(ignoreFailure), fImageDigest(kDummyImageD
igest) {} |
| 106 |
| 107 Expectation::Expectation(const SkString &hashType, uint64_t hashValue, bool
ignoreFailure) : |
| 108 fIsEmpty(false), fIgnoreFailure(ignoreFailure), fImageDigest(hashType, h
ashValue) {} |
| 109 |
| 110 Expectation::Expectation(const SkBitmap& bitmap, bool ignoreFailure) : |
| 111 fIsEmpty(false), fIgnoreFailure(ignoreFailure), fImageDigest(bitmap) {} |
| 112 |
| 113 bool Expectation::ignoreFailure() const { return this->fIgnoreFailure; } |
| 114 |
| 115 bool Expectation::empty() const { return this->fIsEmpty; } |
| 116 |
| 117 bool Expectation::matches(ImageDigest &imageDigest) { |
| 118 return !(this->fIsEmpty) && (this->fImageDigest.equals(imageDigest)); |
| 94 } | 119 } |
| 95 | 120 |
| 96 // ImageResultsAndExpectations class... | 121 // ImageResultsAndExpectations class... |
| 97 | 122 |
| 98 bool ImageResultsAndExpectations::readExpectationsFile(const char *jsonPath)
{ | 123 bool ImageResultsAndExpectations::readExpectationsFile(const char *jsonPath)
{ |
| 99 if (NULL == jsonPath) { | 124 if (NULL == jsonPath) { |
| 100 SkDebugf("JSON expectations filename not specified\n"); | 125 SkDebugf("JSON expectations filename not specified\n"); |
| 101 return false; | 126 return false; |
| 102 } | 127 } |
| 103 SkFILE* filePtr = sk_fopen(jsonPath, kRead_SkFILE_Flag); | 128 SkFILE* filePtr = sk_fopen(jsonPath, kRead_SkFILE_Flag); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 129 if (headerRevision.asInt() != kJsonValue_Header_Revision) { | 154 if (headerRevision.asInt() != kJsonValue_Header_Revision) { |
| 130 SkDebugf("JSON expectations file '%s': expected headerRevision %d, f
ound %d\n", | 155 SkDebugf("JSON expectations file '%s': expected headerRevision %d, f
ound %d\n", |
| 131 jsonPath, kJsonValue_Header_Revision, headerRevision.asInt(
)); | 156 jsonPath, kJsonValue_Header_Revision, headerRevision.asInt(
)); |
| 132 return false; | 157 return false; |
| 133 } | 158 } |
| 134 fExpectedResults = fExpectedJsonRoot[kJsonKey_ExpectedResults]; | 159 fExpectedResults = fExpectedJsonRoot[kJsonKey_ExpectedResults]; |
| 135 return true; | 160 return true; |
| 136 } | 161 } |
| 137 | 162 |
| 138 void ImageResultsAndExpectations::add(const char *sourceName, const char *fi
leName, | 163 void ImageResultsAndExpectations::add(const char *sourceName, const char *fi
leName, |
| 139 const ImageDigest &digest, const int *
tileNumber) { | 164 ImageDigest &digest, const int *tileNu
mber) { |
| 140 // Get expectation, if any. | 165 // Get expectation, if any. |
| 141 Json::Value expectedImage; | 166 Expectation expectation = this->getExpectation(sourceName, tileNumber); |
| 142 if (!fExpectedResults.isNull()) { | |
| 143 if (NULL == tileNumber) { | |
| 144 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_Who
leImage]; | |
| 145 } else { | |
| 146 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_Til
edImages] | |
| 147 [*tileNumber]; | |
| 148 } | |
| 149 } | |
| 150 | 167 |
| 151 // Fill in info about the actual result itself. | 168 // Fill in info about the actual result. |
| 152 Json::Value actualChecksumAlgorithm = digest.getHashType().c_str(); | 169 Json::Value actualChecksumAlgorithm = digest.getHashType().c_str(); |
| 153 Json::Value actualChecksumValue = Json::UInt64(digest.getHashValue()); | 170 Json::Value actualChecksumValue = Json::UInt64(digest.getHashValue()); |
| 154 Json::Value actualImage; | 171 Json::Value actualImage; |
| 155 actualImage[kJsonKey_Image_ChecksumAlgorithm] = actualChecksumAlgorithm; | 172 actualImage[kJsonKey_Image_ChecksumAlgorithm] = actualChecksumAlgorithm; |
| 156 actualImage[kJsonKey_Image_ChecksumValue] = actualChecksumValue; | 173 actualImage[kJsonKey_Image_ChecksumValue] = actualChecksumValue; |
| 157 actualImage[kJsonKey_Image_Filepath] = fileName; | 174 actualImage[kJsonKey_Image_Filepath] = fileName; |
| 158 | 175 |
| 159 // Compare against expectedImage to fill in comparisonResult. | 176 // Compare against expectedImage to fill in comparisonResult. |
| 160 Json::Value comparisonResult = kJsonValue_Image_ComparisonResult_NoCompa
rison; | 177 Json::Value comparisonResult; |
| 161 if (!expectedImage.isNull()) { | 178 if (expectation.empty()) { |
| 162 if ((actualChecksumAlgorithm == expectedImage[kJsonKey_Image_Checksu
mAlgorithm]) && | 179 comparisonResult = kJsonValue_Image_ComparisonResult_NoComparison; |
| 163 (actualChecksumValue == expectedImage[kJsonKey_Image_ChecksumVal
ue])) { | 180 } else if (expectation.matches(digest)) { |
| 164 comparisonResult = kJsonValue_Image_ComparisonResult_Succeeded; | 181 comparisonResult = kJsonValue_Image_ComparisonResult_Succeeded; |
| 165 } else if (expectedImage[kJsonKey_Image_IgnoreFailure] == true) { | 182 } else if (expectation.ignoreFailure()) { |
| 166 comparisonResult = kJsonValue_Image_ComparisonResult_FailureIgno
red; | 183 comparisonResult = kJsonValue_Image_ComparisonResult_FailureIgnored; |
| 167 } else { | 184 } else { |
| 168 comparisonResult = kJsonValue_Image_ComparisonResult_Failed; | 185 comparisonResult = kJsonValue_Image_ComparisonResult_Failed; |
| 169 } | |
| 170 } | 186 } |
| 171 actualImage[kJsonKey_Image_ComparisonResult] = comparisonResult; | 187 actualImage[kJsonKey_Image_ComparisonResult] = comparisonResult; |
| 172 | 188 |
| 173 // Add this actual result to our collection. | 189 // Add this actual result to our collection. |
| 174 if (NULL == tileNumber) { | 190 if (NULL == tileNumber) { |
| 175 fActualResults[sourceName][kJsonKey_Source_WholeImage] = actualImage
; | 191 fActualResults[sourceName][kJsonKey_Source_WholeImage] = actualImage
; |
| 176 } else { | 192 } else { |
| 177 fActualResults[sourceName][kJsonKey_Source_TiledImages][*tileNumber]
= actualImage; | 193 fActualResults[sourceName][kJsonKey_Source_TiledImages][*tileNumber]
= actualImage; |
| 178 } | 194 } |
| 179 } | 195 } |
| 180 | 196 |
| 181 void ImageResultsAndExpectations::addDescription(const char *key, const char
*value) { | 197 void ImageResultsAndExpectations::addDescription(const char *key, const char
*value) { |
| 182 fDescriptions[key] = value; | 198 fDescriptions[key] = value; |
| 183 } | 199 } |
| 184 | 200 |
| 185 bool ImageResultsAndExpectations::matchesExpectation(const char *sourceName, | 201 Expectation ImageResultsAndExpectations::getExpectation(const char *sourceNa
me, |
| 186 const ImageDigest &dige
st, | 202 const int *tileNumbe
r) { |
| 187 const int *tileNumber)
{ | |
| 188 if (fExpectedResults.isNull()) { | 203 if (fExpectedResults.isNull()) { |
| 189 return false; | 204 return Expectation(); |
| 190 } | 205 } |
| 191 | 206 |
| 192 Json::Value expectedImage; | 207 Json::Value expectedImage; |
| 193 if (NULL == tileNumber) { | 208 if (NULL == tileNumber) { |
| 194 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_WholeIm
age]; | 209 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_WholeIm
age]; |
| 195 } else { | 210 } else { |
| 196 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_TiledIm
ages][*tileNumber]; | 211 expectedImage = fExpectedResults[sourceName][kJsonKey_Source_TiledIm
ages][*tileNumber]; |
| 197 } | 212 } |
| 198 if (expectedImage.isNull()) { | 213 if (expectedImage.isNull()) { |
| 199 return false; | 214 return Expectation(); |
| 200 } | 215 } |
| 201 | 216 |
| 202 Json::Value actualChecksumAlgorithm = digest.getHashType().c_str(); | 217 bool ignoreFailure = (expectedImage[kJsonKey_Image_IgnoreFailure] == tru
e); |
| 203 Json::Value actualChecksumValue = Json::UInt64(digest.getHashValue()); | 218 return Expectation(SkString(expectedImage[kJsonKey_Image_ChecksumAlgorit
hm].asCString()), |
| 204 return ((actualChecksumAlgorithm == expectedImage[kJsonKey_Image_Checksu
mAlgorithm]) && | 219 expectedImage[kJsonKey_Image_ChecksumValue].asUInt64(
), |
| 205 (actualChecksumValue == expectedImage[kJsonKey_Image_ChecksumVal
ue])); | 220 ignoreFailure); |
| 206 } | 221 } |
| 207 | 222 |
| 208 void ImageResultsAndExpectations::writeToFile(const char *filename) const { | 223 void ImageResultsAndExpectations::writeToFile(const char *filename) const { |
| 209 Json::Value header; | 224 Json::Value header; |
| 210 header[kJsonKey_Header_Type] = kJsonValue_Header_Type; | 225 header[kJsonKey_Header_Type] = kJsonValue_Header_Type; |
| 211 header[kJsonKey_Header_Revision] = kJsonValue_Header_Revision; | 226 header[kJsonKey_Header_Revision] = kJsonValue_Header_Revision; |
| 212 Json::Value root; | 227 Json::Value root; |
| 213 root[kJsonKey_ActualResults] = fActualResults; | 228 root[kJsonKey_ActualResults] = fActualResults; |
| 214 root[kJsonKey_Descriptions] = fDescriptions; | 229 root[kJsonKey_Descriptions] = fDescriptions; |
| 215 root[kJsonKey_Header] = header; | 230 root[kJsonKey_Header] = header; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 229 size_t size = dataRef.get()->size(); | 244 size_t size = dataRef.get()->size(); |
| 230 Json::Reader reader; | 245 Json::Reader reader; |
| 231 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { | 246 if (!reader.parse(bytes, bytes+size, *jsonRoot)) { |
| 232 return false; | 247 return false; |
| 233 } | 248 } |
| 234 | 249 |
| 235 return true; | 250 return true; |
| 236 } | 251 } |
| 237 | 252 |
| 238 } // namespace sk_tools | 253 } // namespace sk_tools |
| OLD | NEW |