Fix SkLocalMatrixShader::isAImage() to respect local matrix and image local matrix
authorMatt Sarett <msarett@google.com>
Wed, 12 Apr 2017 15:52:47 +0000 (11:52 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Wed, 12 Apr 2017 16:36:51 +0000 (16:36 +0000)
Fixes cts tests.

b/37161109
b/37237678

CQ_INCLUDE_TRYBOTS=skia.primary:Test-Ubuntu-Clang-GCE-CPU-AVX2-x86_64-Debug-MSAN

Bug: skia:
Change-Id: I438b8b17f4c7c5bfcb50dfa22af1ddb97b905088
Reviewed-on: https://skia-review.googlesource.com/13261
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Matt Sarett <msarett@google.com>

gm/localmatriximageshader.cpp [new file with mode: 0644]
gn/gm.gni
src/core/SkLocalMatrixShader.cpp
src/core/SkLocalMatrixShader.h

diff --git a/gm/localmatriximageshader.cpp b/gm/localmatriximageshader.cpp
new file mode 100644 (file)
index 0000000..2c9fcd2
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkSurface.h"
+
+static sk_sp<SkImage> make_image(SkCanvas* rootCanvas, SkColor color) {
+    SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
+    auto surface(rootCanvas->makeSurface(info));
+    if (!surface) {
+        surface = SkSurface::MakeRaster(info);
+    }
+
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setColor(color);
+    surface->getCanvas()->drawIRect(SkIRect::MakeXYWH(25, 25, 50, 50), paint);
+    return surface->makeImageSnapshot();
+}
+
+DEF_SIMPLE_GM(localmatriximageshader, canvas, 250, 250) {
+    sk_sp<SkImage> redImage = make_image(canvas, SK_ColorRED);
+    SkMatrix translate = SkMatrix::MakeTrans(100.0f, 0.0f);
+    SkMatrix rotate;
+    rotate.setRotate(45.0f);
+    sk_sp<SkShader> redImageShader = redImage->makeShader(SkShader::TileMode::kClamp_TileMode,
+            SkShader::TileMode::kClamp_TileMode, &translate);
+    sk_sp<SkShader> redLocalMatrixShader = redImageShader->makeWithLocalMatrix(rotate);
+
+    // Rotate about the origin will happen first.
+    SkPaint paint;
+    paint.setShader(redLocalMatrixShader);
+    canvas->drawIRect(SkIRect::MakeWH(250, 250), paint);
+
+    sk_sp<SkImage> blueImage = make_image(canvas, SK_ColorBLUE);
+    sk_sp<SkShader> blueImageShader = blueImage->makeShader(SkShader::TileMode::kClamp_TileMode,
+            SkShader::TileMode::kClamp_TileMode, &rotate);
+    sk_sp<SkShader> blueLocalMatrixShader = blueImageShader->makeWithLocalMatrix(translate);
+
+    // Translate will happen first.
+    paint.setShader(blueLocalMatrixShader);
+    canvas->drawIRect(SkIRect::MakeWH(250, 250), paint);
+
+    canvas->translate(100.0f, 0.0f);
+
+    // Use isAImage() and confirm that the shaders will draw exactly the same (to the right by 100).
+    SkShader::TileMode mode[2];
+    SkMatrix matrix;
+    SkImage* image = redLocalMatrixShader->isAImage(&matrix, mode);
+    paint.setShader(image->makeShader(mode[0], mode[1], &matrix));
+    canvas->drawIRect(SkIRect::MakeWH(250, 250), paint);
+    image = blueLocalMatrixShader->isAImage(&matrix, mode);
+    paint.setShader(image->makeShader(mode[0], mode[1], &matrix));
+    canvas->drawIRect(SkIRect::MakeWH(250, 250), paint);
+}
index 65c6766..67d2ced 100644 (file)
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -188,6 +188,7 @@ gm_sources = [
   "$_gm/lightingshaderbevel.cpp",
   "$_gm/linepaths.cpp",
   "$_gm/localmatriximagefilter.cpp",
+  "$_gm/localmatriximageshader.cpp",
   "$_gm/lumafilter.cpp",
   "$_gm/manypaths.cpp",
   "$_gm/matrixconvolution.cpp",
index 9d9e109..33472f1 100644 (file)
@@ -51,6 +51,17 @@ SkShader::Context* SkLocalMatrixShader::onMakeContext(
     return fProxyShader->makeContext(newRec, alloc);
 }
 
+SkImage* SkLocalMatrixShader::onIsAImage(SkMatrix* outMatrix, enum TileMode* mode) const {
+    SkMatrix imageMatrix;
+    SkImage* image = fProxyShader->isAImage(&imageMatrix, mode);
+    if (image && outMatrix) {
+        // Local matrix must be applied first so it is on the right side of the concat.
+        *outMatrix = SkMatrix::Concat(imageMatrix, this->getLocalMatrix());
+    }
+
+    return image;
+}
+
 bool SkLocalMatrixShader::onAppendStages(SkRasterPipeline* p,
                                          SkColorSpace* dst,
                                          SkArenaAlloc* scratch,
index 5c04240..cba1409 100644 (file)
@@ -45,9 +45,7 @@ protected:
 
     Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
 
-    SkImage* onIsAImage(SkMatrix* matrix, TileMode* mode) const override {
-        return fProxyShader->isAImage(matrix, mode);
-    }
+    SkImage* onIsAImage(SkMatrix* matrix, TileMode* mode) const override;
 
     bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
                         const SkMatrix&, const SkPaint&, const SkMatrix*) const override;