Implement SkHighContrastFilter

This is a color filter to apply several contrast adjustments for users
with low vision, including inverting the colors (in either RGB or HSL
space), applying gamma correction, converting to grayscale, and increasing
the contrast.

BUG=skia:6235

CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD

Change-Id: Icb8f3e290932d8bcd9387fb1f39dd20767e15cf6
Reviewed-on: https://skia-review.googlesource.com/7460
Commit-Queue: Mike Klein <mtklein@chromium.org>
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
diff --git a/tests/HighContrastFilterTest.cpp b/tests/HighContrastFilterTest.cpp
new file mode 100644
index 0000000..35b0c9f
--- /dev/null
+++ b/tests/HighContrastFilterTest.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCanvas.h"
+#include "SkHighContrastFilter.h"
+#include "Test.h"
+
+DEF_TEST(HighContrastFilter_FilterImage, reporter) {
+    SkHighContrastConfig config;
+    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertLightness;
+
+    int w = 10, h = 10;
+    SkBitmap filterResult, paintResult;
+
+    filterResult.allocN32Pixels(w, h);
+    SkCanvas canvasFilter(filterResult);
+    canvasFilter.clear(0x00000000);
+
+    paintResult.allocN32Pixels(w, h);
+    SkCanvas canvasPaint(paintResult);
+    canvasPaint.clear(0x00000000);
+
+    SkPaint paint;
+    paint.setColor(SK_ColorBLUE);
+    SkRect r = SkRect::MakeLTRB(SkIntToScalar(2), SkIntToScalar(2),
+                                SkIntToScalar(8), SkIntToScalar(8));
+    canvasPaint.drawRect(r, paint);
+
+    paint.setColorFilter(SkHighContrastFilter::Make(config));
+    canvasFilter.drawRect(r, paint);
+
+    paintResult.lockPixels();
+    filterResult.lockPixels();
+    for (int y = r.top(); y < r.bottom(); ++y) {
+        for (int x = r.left(); x < r.right(); ++x) {
+            SkColor paintColor = paintResult.getColor(x, y);
+            SkColor filterColor = filterResult.getColor(x, y);
+            REPORTER_ASSERT(
+                reporter, filterColor ==
+                paint.getColorFilter()->filterColor(paintColor));
+        }
+    }
+    paintResult.unlockPixels();
+    filterResult.unlockPixels();
+}
+
+DEF_TEST(HighContrastFilter_SanityCheck, reporter) {
+    SkHighContrastConfig config;
+    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertLightness;
+    sk_sp<SkColorFilter> filter = SkHighContrastFilter::Make(config);
+
+    SkColor white_inverted = filter->filterColor(SK_ColorWHITE);
+    REPORTER_ASSERT(reporter, white_inverted == SK_ColorBLACK);
+
+    SkColor black_inverted = filter->filterColor(SK_ColorBLACK);
+    REPORTER_ASSERT(reporter, black_inverted == SK_ColorWHITE);
+}
+
+DEF_TEST(HighContrastFilter_InvalidInputs, reporter) {
+    SkHighContrastConfig config;
+    REPORTER_ASSERT(reporter, config.isValid());
+
+    // Valid invert style
+    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertBrightness;
+    REPORTER_ASSERT(reporter, config.isValid());
+    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertLightness;
+    REPORTER_ASSERT(reporter, config.isValid());
+    sk_sp<SkColorFilter> filter = SkHighContrastFilter::Make(config);
+    REPORTER_ASSERT(reporter, filter);
+
+    // Invalid invert style
+    config.fInvertStyle = static_cast<SkHighContrastConfig::InvertStyle>(999);
+    REPORTER_ASSERT(reporter, !config.isValid());
+    filter = SkHighContrastFilter::Make(config);
+    REPORTER_ASSERT(reporter, !filter);
+
+    // Valid contrast
+    config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertBrightness;
+    config.fContrast = 0.5f;
+    REPORTER_ASSERT(reporter, config.isValid());
+    filter = SkHighContrastFilter::Make(config);
+    REPORTER_ASSERT(reporter, filter);
+
+    // Invalid contrast
+    config.fContrast = 1.1f;
+    REPORTER_ASSERT(reporter, !config.isValid());
+    filter = SkHighContrastFilter::Make(config);
+    REPORTER_ASSERT(reporter, !filter);
+}