Add filter-quality to imageshader factory

The old factories (makeShader) will behave as before: they will inherit
the filter-quality from the paint.

The new factory takes an explicit filter setting, and will use that
regardless of the paint.

Big follow-ups:
- update callers to not rely on setting in SkPaint
- revise/enhance settings in imageshader
    - settings for scaling up and down
    - control over trilerp, etc.
    - other: 4x4 kernels? trilerp bias?
- move mipmaps to always be explicit requests a SkImage factory time


Bug: skia:10344
Change-Id: If87b06d4fd6eafd8b9cdecda7c00d69897066ef8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/295086
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/tests/ShaderOpacityTest.cpp b/tests/ShaderOpacityTest.cpp
index bfdf3e7..13357b3 100644
--- a/tests/ShaderOpacityTest.cpp
+++ b/tests/ShaderOpacityTest.cpp
@@ -6,10 +6,13 @@
  */
 
 #include "include/core/SkBitmap.h"
+#include "include/core/SkCanvas.h"
 #include "include/core/SkShader.h"
+#include "include/core/SkSurface.h"
 #include "include/effects/SkGradientShader.h"
 #include "src/shaders/SkColorShader.h"
 #include "tests/Test.h"
+#include "tools/ToolUtils.h"
 
 static void test_bitmap(skiatest::Reporter* reporter) {
     SkImageInfo info = SkImageInfo::MakeN32Premul(2, 2);
@@ -95,3 +98,51 @@
     test_color(reporter);
     test_bitmap(reporter);
 }
+
+DEF_TEST(image_shader_filtering, reporter) {
+    auto make_checker_img = [](int w, int h) {
+        auto info = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
+        auto surf = SkSurface::MakeRaster(info);
+        ToolUtils::draw_checkerboard(surf->getCanvas(), SK_ColorRED, SK_ColorBLUE, 2);
+        return surf->makeImageSnapshot();
+    };
+
+    auto img = make_checker_img(4, 4);
+
+    const SkFilterQuality quals[] = {
+        kNone_SkFilterQuality,
+        kLow_SkFilterQuality,
+        kMedium_SkFilterQuality,
+        kHigh_SkFilterQuality,
+    };
+    const SkScalar scales[] = { 3.0f, 1.0f, 0.5f, 0.25f, 0.125f };
+
+    auto make_img = [&](const SkPaint& paint) {
+        auto info = SkImageInfo::Make(70, 70, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+        auto surf = SkSurface::MakeRaster(info);
+        auto canvas = surf->getCanvas();
+        canvas->scale(1.06f, 1.06f);    // nicely exaggerates noise when not filtering
+        canvas->drawRect({0, 0, 64, 64}, paint);
+        return surf->makeImageSnapshot();
+    };
+
+    SkPaint paint;
+    for (auto q : quals) {
+        for (auto scale : scales) {
+            SkMatrix m = SkMatrix::Scale(scale, scale);
+            paint.setFilterQuality(kNone_SkFilterQuality); // this setting should be ignored
+            paint.setShader(img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &m, q));
+            auto img0 = make_img(paint);
+
+            paint.setFilterQuality(q);  // this should (still) be ignored
+            auto img1 = make_img(paint);
+
+            // make legacy form of shader, relying on the paint's filter-quality (q)
+            paint.setShader(img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &m));
+            auto img2 = make_img(paint);
+
+            REPORTER_ASSERT(reporter, ToolUtils::equal_pixels(img0.get(), img1.get()));
+            REPORTER_ASSERT(reporter, ToolUtils::equal_pixels(img0.get(), img2.get()));
+        }
+    }
+}