diff options
-rw-r--r-- | gm/localmatrixshader.cpp | 101 | ||||
-rw-r--r-- | gn/gm.gni | 1 | ||||
-rw-r--r-- | src/shaders/SkLocalMatrixShader.cpp | 20 |
3 files changed, 113 insertions, 9 deletions
diff --git a/gm/localmatrixshader.cpp b/gm/localmatrixshader.cpp new file mode 100644 index 0000000000..bbd2775b7c --- /dev/null +++ b/gm/localmatrixshader.cpp @@ -0,0 +1,101 @@ +/* + * Copyright 2018 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 "SkShader.h" +#include "SkSurface.h" +#include "sk_tool_utils.h" + +static sk_sp<SkImage> make_image(SkCanvas* rootCanvas) { + static constexpr SkScalar kSize = 50; + SkImageInfo info = SkImageInfo::MakeN32Premul(kSize, kSize); + auto surface = sk_tool_utils::makeSurface(rootCanvas, info); + + SkPaint p; + p.setAntiAlias(true); + p.setColor(SK_ColorGREEN); + + surface->getCanvas()->drawCircle(kSize / 2, kSize / 2, kSize / 2, p); + + p.setStyle(SkPaint::kStroke_Style); + p.setColor(SK_ColorRED); + surface->getCanvas()->drawLine(kSize * .25f, kSize * .50f, kSize * .75f, kSize * .50f, p); + surface->getCanvas()->drawLine(kSize * .50f, kSize * .25f, kSize * .50f, kSize * .75f, p); + + return surface->makeImageSnapshot(); +} + +DEF_SIMPLE_GM(localmatrixshader_nested, canvas, 450, 1200) { + auto image = make_image(canvas); + + using FactoryT = sk_sp<SkShader> (*)(const sk_sp<SkImage>&, + const SkMatrix& inner, + const SkMatrix& outer); + static const FactoryT gFactories[] = { + // SkLocalMatrixShader(SkImageShader(inner), outer) + [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) { + return img->makeShader(&inner)->makeWithLocalMatrix(outer); + }, + + // SkLocalMatrixShader(SkLocalMatrixShader(SkImageShader(I), inner), outer) + [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) { + return img->makeShader()->makeWithLocalMatrix(inner)->makeWithLocalMatrix(outer); + }, + + // SkLocalMatrixShader(SkComposeShader(SkImageShader(inner)), outer) + [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) { + return SkShader::MakeCompose(SkShader::MakeColorShader(SK_ColorTRANSPARENT), + img->makeShader(&inner), + SkBlendMode::kSrcOver) + ->makeWithLocalMatrix(outer); + }, + + // SkLocalMatrixShader(SkComposeShader(SkLocalMatrixShader(SkImageShader(I), inner)), outer) + [](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) { + return SkShader::MakeCompose(SkShader::MakeColorShader(SK_ColorTRANSPARENT), + img->makeShader()->makeWithLocalMatrix(inner), + SkBlendMode::kSrcOver) + ->makeWithLocalMatrix(outer); + }, + }; + + static const auto inner = SkMatrix::MakeScale(2, 2), + outer = SkMatrix::MakeTrans(20, 20); + + SkPaint border; + border.setAntiAlias(true); + border.setStyle(SkPaint::kStroke_Style); + + auto rect = SkRect::Make(image->bounds()); + SkAssertResult(SkMatrix::Concat(inner, outer).mapRect(&rect)); + + const auto drawColumn = [&]() { + SkAutoCanvasRestore acr(canvas, true); + for (const auto& f : gFactories) { + SkPaint p; + p.setShader(f(image, inner, outer)); + + canvas->drawRect(rect, p); + canvas->drawRect(rect, border); + + canvas->translate(0, rect.height() * 1.5f); + } + }; + + drawColumn(); + + { + SkAutoCanvasRestore acr(canvas, true); + canvas->translate(0, rect.height() * SK_ARRAY_COUNT(gFactories) * 1.5f); + drawColumn(); + } + + canvas->translate(rect.width() * 1.5f, 0); + canvas->scale(2, 2); + drawColumn(); +} @@ -201,6 +201,7 @@ gm_sources = [ "$_gm/linepaths.cpp", "$_gm/localmatriximagefilter.cpp", "$_gm/localmatriximageshader.cpp", + "$_gm/localmatrixshader.cpp", "$_gm/lumafilter.cpp", "$_gm/makecolorspace.cpp", "$_gm/makeRasterImage.cpp", diff --git a/src/shaders/SkLocalMatrixShader.cpp b/src/shaders/SkLocalMatrixShader.cpp index a08fea14a5..e352d31299 100644 --- a/src/shaders/SkLocalMatrixShader.cpp +++ b/src/shaders/SkLocalMatrixShader.cpp @@ -6,6 +6,7 @@ */ #include "SkLocalMatrixShader.h" +#include "SkTLazy.h" #if SK_SUPPORT_GPU #include "GrFragmentProcessor.h" @@ -42,14 +43,14 @@ void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const { SkShaderBase::Context* SkLocalMatrixShader::onMakeContext( const ContextRec& rec, SkArenaAlloc* alloc) const { - ContextRec newRec(rec); - SkMatrix tmp; + SkTCopyOnFirstWrite<SkMatrix> lm(this->getLocalMatrix()); if (rec.fLocalMatrix) { - tmp.setConcat(*rec.fLocalMatrix, this->getLocalMatrix()); - newRec.fLocalMatrix = &tmp; - } else { - newRec.fLocalMatrix = &this->getLocalMatrix(); + lm.writable()->preConcat(*rec.fLocalMatrix); } + + ContextRec newRec(rec); + newRec.fLocalMatrix = lm; + return as_SB(fProxyShader)->makeContext(newRec, alloc); } @@ -65,12 +66,13 @@ SkImage* SkLocalMatrixShader::onIsAImage(SkMatrix* outMatrix, enum TileMode* mod } bool SkLocalMatrixShader::onAppendStages(const StageRec& rec) const { - SkMatrix tmp; + SkTCopyOnFirstWrite<SkMatrix> lm(this->getLocalMatrix()); if (rec.fLocalM) { - tmp.setConcat(*rec.fLocalM, this->getLocalMatrix()); + lm.writable()->preConcat(*rec.fLocalM); } + StageRec newRec = rec; - newRec.fLocalM = rec.fLocalM ? &tmp : &this->getLocalMatrix(); + newRec.fLocalM = lm; return as_SB(fProxyShader)->appendStages(newRec); } |