(Mostly) respect FilterQuality in draw[stretchy]

Bug: b/77917978

For
  drawImageLattice
  drawBitmapLattice
  drawImageNine
  drawBitmapNine
, respect the SkFilterQuality on the SkPaint. Previously the GPU used
the lowest quality to avoid a bleeding effect, leading to ugly nine-
patches on Android.

For all backends, cap the filter quality at kLow_SkFilterQuality.
Update SkCanvas' documentation to specify this.

Change-Id: Id28c7753834975f039170f14bc51be4f2bd44d41
Reviewed-on: https://skia-review.googlesource.com/121891
Reviewed-by: Cary Clark <caryclark@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
Auto-Submit: Leon Scroggins <scroggo@google.com>
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 7398f28..fa2c08a 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1725,6 +1725,29 @@
                         constraint);
 }
 
+namespace {
+class NoneOrLowQualityFilterPaint : SkNoncopyable {
+public:
+    NoneOrLowQualityFilterPaint(const SkPaint* origPaint) {
+        if (origPaint && origPaint->getFilterQuality() > kLow_SkFilterQuality) {
+            fLazyPaint.set(*origPaint);
+            fLazyPaint.get()->setFilterQuality(kLow_SkFilterQuality);
+            fPaint = fLazyPaint.get();
+        } else {
+            fPaint = origPaint;
+        }
+    }
+
+    const SkPaint* get() const {
+        return fPaint;
+    }
+
+private:
+    const SkPaint* fPaint;
+    SkLazyPaint fLazyPaint;
+};
+} // namespace
+
 void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
                              const SkPaint* paint) {
     TRACE_EVENT0("skia", TRACE_FUNC);
@@ -1733,7 +1756,8 @@
         return;
     }
     if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
-        this->onDrawImageNine(image, center, dst, paint);
+        NoneOrLowQualityFilterPaint lowPaint(paint);
+        this->onDrawImageNine(image, center, dst, lowPaint.get());
     } else {
         this->drawImageRect(image, dst, paint);
     }
@@ -1755,7 +1779,8 @@
     }
 
     if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
-        this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
+        NoneOrLowQualityFilterPaint lowPaint(paint);
+        this->onDrawImageLattice(image, latticePlusBounds, dst, lowPaint.get());
     } else {
         this->drawImageRect(image, dst, paint);
     }
@@ -1796,7 +1821,8 @@
         return;
     }
     if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
-        this->onDrawBitmapNine(bitmap, center, dst, paint);
+        NoneOrLowQualityFilterPaint lowPaint(paint);
+        this->onDrawBitmapNine(bitmap, center, dst, lowPaint.get());
     } else {
         this->drawBitmapRect(bitmap, dst, paint);
     }
@@ -1817,7 +1843,8 @@
     }
 
     if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
-        this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
+        NoneOrLowQualityFilterPaint lowPaint(paint);
+        this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, lowPaint.get());
     } else {
         this->drawBitmapRect(bitmap, dst, paint);
     }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 3a48e8c..138d41f 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1350,6 +1350,15 @@
     }
 }
 
+// When drawing nine-patches or n-patches, cap the filter quality at kBilerp.
+static GrSamplerState::Filter compute_lattice_filter_mode(const SkPaint& paint) {
+    if (paint.getFilterQuality() == kNone_SkFilterQuality) {
+        return GrSamplerState::Filter::kNearest;
+    }
+
+    return GrSamplerState::Filter::kBilerp;
+}
+
 void SkGpuDevice::drawProducerNine(GrTextureProducer* producer,
                                    const SkIRect& center, const SkRect& dst, const SkPaint& paint) {
     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerNine", fContext.get());
@@ -1371,7 +1380,7 @@
         return;
     }
 
-    static const GrSamplerState::Filter kMode = GrSamplerState::Filter::kNearest;
+    const GrSamplerState::Filter kMode = compute_lattice_filter_mode(paint);
     auto fp = producer->createFragmentProcessor(
             SkMatrix::I(), SkRect::MakeIWH(producer->width(), producer->height()),
             GrTextureProducer::kNo_FilterConstraint, true, &kMode,
@@ -1426,7 +1435,7 @@
                                       const SkPaint& paint) {
     GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawProducerLattice", fContext.get());
 
-    static const GrSamplerState::Filter kMode = GrSamplerState::Filter::kNearest;
+    const GrSamplerState::Filter kMode = compute_lattice_filter_mode(paint);
     std::unique_ptr<GrFragmentProcessor> fp(producer->createFragmentProcessor(
             SkMatrix::I(), SkRect::MakeIWH(producer->width(), producer->height()),
             GrTextureProducer::kNo_FilterConstraint, true, &kMode,