summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/tools/skdiff.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/tools/skdiff.h')
-rw-r--r--chromium/third_party/skia/tools/skdiff.h272
1 files changed, 272 insertions, 0 deletions
diff --git a/chromium/third_party/skia/tools/skdiff.h b/chromium/third_party/skia/tools/skdiff.h
new file mode 100644
index 00000000000..6abaf6c4056
--- /dev/null
+++ b/chromium/third_party/skia/tools/skdiff.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef skdiff_DEFINED
+#define skdiff_DEFINED
+
+#include "SkBitmap.h"
+#include "SkColor.h"
+#include "SkColorPriv.h"
+#include "SkString.h"
+#include "SkTDArray.h"
+
+#if SK_BUILD_FOR_WIN32
+ #define PATH_DIV_STR "\\"
+ #define PATH_DIV_CHAR '\\'
+#else
+ #define PATH_DIV_STR "/"
+ #define PATH_DIV_CHAR '/'
+#endif
+
+#define MAX2(a,b) (((b) < (a)) ? (a) : (b))
+#define MAX3(a,b,c) (((b) < (a)) ? MAX2((a), (c)) : MAX2((b), (c)))
+
+
+struct DiffResource {
+ enum Status {
+ /** The resource was specified, exists, read, and decoded. */
+ kDecoded_Status,
+ /** The resource was specified, exists, read, but could not be decoded. */
+ kCouldNotDecode_Status,
+
+ /** The resource was specified, exists, and read. */
+ kRead_Status,
+ /** The resource was specified, exists, but could not be read. */
+ kCouldNotRead_Status,
+
+ /** The resource was specified and exists. */
+ kExists_Status,
+ /** The resource was specified, but does not exist. */
+ kDoesNotExist_Status,
+
+ /** The resource was specified. */
+ kSpecified_Status,
+ /** The resource was not specified. */
+ kUnspecified_Status,
+
+ /** Nothing is yet known about the resource. */
+ kUnknown_Status,
+
+ /** NOT A VALID VALUE -- used to set up arrays and to represent an unknown value. */
+ kStatusCount
+ };
+ static char const * const StatusNames[DiffResource::kStatusCount];
+
+ /** Returns the Status with this name.
+ * If there is no Status with this name, returns kStatusCount.
+ */
+ static Status getStatusByName(const char *name);
+
+ /** Returns a text description of the given Status type. */
+ static const char *getStatusDescription(Status status);
+
+ /** Returns true if the Status indicates some kind of failure. */
+ static bool isStatusFailed(Status status);
+
+ /** Sets statuses[i] if it is implied by selector, unsets it if not.
+ * Selector may be a comma delimited list of status names, "any", or "failed".
+ * Returns true if the selector was entirely understood, false otherwise.
+ */
+ static bool getMatchingStatuses(char* selector, bool statuses[kStatusCount]);
+
+ DiffResource() : fFilename(), fFullPath(), fBitmap(), fStatus(kUnknown_Status) { };
+
+ /** If isEmpty() indicates no filename available. */
+ SkString fFilename;
+ /** If isEmpty() indicates no path available. */
+ SkString fFullPath;
+ /** If empty() indicates the bitmap could not be created. */
+ SkBitmap fBitmap;
+ Status fStatus;
+};
+
+struct DiffRecord {
+
+ // Result of comparison for each pair of files.
+ // Listed from "better" to "worse", for sorting of results.
+ enum Result {
+ kEqualBits_Result,
+ kEqualPixels_Result,
+ kDifferentPixels_Result,
+ kDifferentSizes_Result,
+ kCouldNotCompare_Result,
+ kUnknown_Result,
+
+ kResultCount // NOT A VALID VALUE--used to set up arrays. Must be last.
+ };
+ static char const * const ResultNames[DiffRecord::kResultCount];
+
+ /** Returns the Result with this name.
+ * If there is no Result with this name, returns kResultCount.
+ */
+ static Result getResultByName(const char *name);
+
+ /** Returns a text description of the given Result type. */
+ static const char *getResultDescription(Result result);
+
+ DiffRecord()
+ : fBase()
+ , fComparison()
+ , fDifference()
+ , fWhite()
+ , fFractionDifference(0)
+ , fWeightedFraction(0)
+ , fAverageMismatchA(0)
+ , fAverageMismatchR(0)
+ , fAverageMismatchG(0)
+ , fAverageMismatchB(0)
+ , fTotalMismatchA(0)
+ , fMaxMismatchA(0)
+ , fMaxMismatchR(0)
+ , fMaxMismatchG(0)
+ , fMaxMismatchB(0)
+ , fResult(kUnknown_Result) {
+ };
+
+ DiffResource fBase;
+ DiffResource fComparison;
+ DiffResource fDifference;
+ DiffResource fWhite;
+
+ /// Arbitrary floating-point metric to be used to sort images from most
+ /// to least different from baseline; values of 0 will be omitted from the
+ /// summary webpage.
+ float fFractionDifference;
+ float fWeightedFraction;
+
+ float fAverageMismatchA;
+ float fAverageMismatchR;
+ float fAverageMismatchG;
+ float fAverageMismatchB;
+
+ uint32_t fTotalMismatchA;
+
+ uint32_t fMaxMismatchA;
+ uint32_t fMaxMismatchR;
+ uint32_t fMaxMismatchG;
+ uint32_t fMaxMismatchB;
+
+ /// Which category of diff result.
+ Result fResult;
+};
+
+typedef SkTDArray<DiffRecord*> RecordArray;
+
+/// A wrapper for any sortProc (comparison routine) which applies a first-order
+/// sort beforehand, and a tiebreaker if the sortProc returns 0.
+template<typename T> static int compare(const void* untyped_lhs, const void* untyped_rhs) {
+ const DiffRecord* lhs = *reinterpret_cast<DiffRecord* const *>(untyped_lhs);
+ const DiffRecord* rhs = *reinterpret_cast<DiffRecord* const *>(untyped_rhs);
+
+ // First-order sort... these comparisons should be applied before comparing
+ // pixel values, no matter what.
+ if (lhs->fResult != rhs->fResult) {
+ return (lhs->fResult < rhs->fResult) ? 1 : -1;
+ }
+
+ // Passed first-order sort, so call the pixel comparison routine.
+ int result = T::comparePixels(lhs, rhs);
+ if (result != 0) {
+ return result;
+ }
+
+ // Tiebreaker... if we got to this point, we don't really care
+ // which order they are sorted in, but let's at least be consistent.
+ return strcmp(lhs->fBase.fFilename.c_str(), rhs->fBase.fFilename.c_str());
+}
+
+/// Comparison routine for qsort; sorts by fFractionDifference
+/// from largest to smallest.
+class CompareDiffMetrics {
+public:
+ static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) {
+ if (lhs->fFractionDifference < rhs->fFractionDifference) {
+ return 1;
+ }
+ if (rhs->fFractionDifference < lhs->fFractionDifference) {
+ return -1;
+ }
+ return 0;
+ }
+};
+
+class CompareDiffWeighted {
+public:
+ static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) {
+ if (lhs->fWeightedFraction < rhs->fWeightedFraction) {
+ return 1;
+ }
+ if (lhs->fWeightedFraction > rhs->fWeightedFraction) {
+ return -1;
+ }
+ return 0;
+ }
+};
+
+/// Comparison routine for qsort; sorts by max(fAverageMismatch{RGB})
+/// from largest to smallest.
+class CompareDiffMeanMismatches {
+public:
+ static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) {
+ float leftValue = MAX3(lhs->fAverageMismatchR,
+ lhs->fAverageMismatchG,
+ lhs->fAverageMismatchB);
+ float rightValue = MAX3(rhs->fAverageMismatchR,
+ rhs->fAverageMismatchG,
+ rhs->fAverageMismatchB);
+ if (leftValue < rightValue) {
+ return 1;
+ }
+ if (rightValue < leftValue) {
+ return -1;
+ }
+ return 0;
+ }
+};
+
+/// Comparison routine for qsort; sorts by max(fMaxMismatch{RGB})
+/// from largest to smallest.
+class CompareDiffMaxMismatches {
+public:
+ static int comparePixels(const DiffRecord* lhs, const DiffRecord* rhs) {
+ uint32_t leftValue = MAX3(lhs->fMaxMismatchR,
+ lhs->fMaxMismatchG,
+ lhs->fMaxMismatchB);
+ uint32_t rightValue = MAX3(rhs->fMaxMismatchR,
+ rhs->fMaxMismatchG,
+ rhs->fMaxMismatchB);
+ if (leftValue < rightValue) {
+ return 1;
+ }
+ if (rightValue < leftValue) {
+ return -1;
+ }
+
+ return CompareDiffMeanMismatches::comparePixels(lhs, rhs);
+ }
+};
+
+
+/// Parameterized routine to compute the color of a pixel in a difference image.
+typedef SkPMColor (*DiffMetricProc)(SkPMColor, SkPMColor);
+
+// from gm
+static inline SkPMColor compute_diff_pmcolor(SkPMColor c0, SkPMColor c1) {
+ int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
+ int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
+ int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);
+
+ return SkPackARGB32(0xFF, SkAbs32(dr), SkAbs32(dg), SkAbs32(db));
+}
+
+/** When finished, dr->fResult should have some value other than kUnknown_Result.
+ * Expects dr->fWhite.fBitmap and dr->fDifference.fBitmap to have the same bounds as
+ * dr->fBase.fBitmap and have a valid pixelref.
+ */
+void compute_diff(DiffRecord* dr, DiffMetricProc diffFunction, const int colorThreshold);
+
+#endif