support medium and high quality

Change-Id: I4ed750932cd6c768e21ca9f4a9e7f5f2408cfa4d
Reviewed-on: https://skia-review.googlesource.com/5323
Commit-Queue: Mike Klein <mtklein@chromium.org>
Reviewed-by: Mike Klein <mtklein@chromium.org>
diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp
index 4415521..16b8eb6 100644
--- a/src/image/SkImageShader.cpp
+++ b/src/image/SkImageShader.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "SkBitmapController.h"
 #include "SkBitmapProcShader.h"
 #include "SkBitmapProvider.h"
 #include "SkColorShader.h"
@@ -274,20 +275,28 @@
 
 bool SkImageShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* dst, SkFallbackAlloc* scratch,
                                    const SkMatrix& ctm, const SkPaint& paint) const {
-    SkPixmap pm;
-    if (!fImage->peekPixels(&pm)) {
-        return false;
-    }
-    auto info = pm.info();
-
-
     auto matrix = SkMatrix::Concat(ctm, this->getLocalMatrix());
     if (!matrix.invert(&matrix)) {
         return false;
     }
-
     auto quality = paint.getFilterQuality();
 
+    auto mode = (dst == nullptr) ? SkDestinationSurfaceColorMode::kLegacy
+                                 : SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware;
+    SkBitmapProvider provider(fImage.get(), mode);
+    SkDefaultBitmapController controller(mode);
+    std::unique_ptr<SkBitmapController::State> state {
+        controller.requestBitmap(provider, matrix, quality)
+    };
+    if (!state) {
+        return false;
+    }
+
+    const SkPixmap& pm = state->pixmap();
+    matrix  = state->invMatrix();
+    quality = state->quality();
+    auto info = pm.info();
+
     // When the matrix is just an integer translate, bilerp == nearest neighbor.
     if (matrix.getType() <= SkMatrix::kTranslate_Mask &&
         matrix.getTranslateX() == (int)matrix.getTranslateX() &&
@@ -295,11 +304,6 @@
         quality = kNone_SkFilterQuality;
     }
 
-    // TODO: front-patch with SkDefaultBitmapControllerState, then assert we're kNone or kLow.
-    if (quality > kLow_SkFilterQuality) {
-        return false;
-    }
-
     // See skia:4649 and the GM image_scale_aligned.
     if (quality == kNone_SkFilterQuality) {
         if (matrix.getScaleX() >= 0) {
@@ -313,6 +317,7 @@
     }
 
     auto ctx = scratch->make<SkImageShaderContext>();
+    ctx->state   = std::move(state);  // Extend lifetime to match the pipeline's.
     ctx->pixels  = pm.addr();
     ctx->ctable  = pm.ctable();
     ctx->color4f = SkColor4f_from_SkColor(paint.getColor(), dst);
diff --git a/src/image/SkImageShaderContext.h b/src/image/SkImageShaderContext.h
index 1b28bf6..7e50286 100644
--- a/src/image/SkImageShaderContext.h
+++ b/src/image/SkImageShaderContext.h
@@ -8,13 +8,17 @@
 #ifndef SkImageShaderContext_DEFINED
 #define SkImageShaderContext_DEFINED
 
+#include "SkBitmapController.h"
 #include "SkColor.h"
-class SkColorTable;
+#include "SkColorTable.h"
+#include <memory>
 
 // Definition used by SkImageShader.cpp and SkRasterPipeline_opts.h.
 // Otherwise, completely uninteresting.
 
 struct SkImageShaderContext {
+    std::unique_ptr<SkBitmapController::State> state;
+
     const void*   pixels;
     SkColorTable* ctable;
     SkColor4f     color4f;