diff options
-rw-r--r-- | gm/emboss.cpp | 61 | ||||
-rw-r--r-- | gyp/gmslides.gypi | 1 | ||||
-rw-r--r-- | include/core/SkShader.h | 3 | ||||
-rw-r--r-- | src/core/SkBitmapProcShader.h | 2 | ||||
-rw-r--r-- | src/core/SkBlitter.cpp | 20 | ||||
-rw-r--r-- | src/core/SkFilterShader.h | 5 |
6 files changed, 81 insertions, 11 deletions
diff --git a/gm/emboss.cpp b/gm/emboss.cpp new file mode 100644 index 0000000000..c2ee49723f --- /dev/null +++ b/gm/emboss.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2014 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 "SkBlurMaskFilter.h" +#include "SkCanvas.h" +#include "SkColorFilter.h" + +#include "SkColorFilter.h" +static SkBitmap make_bm() { + SkBitmap bm; + bm.allocN32Pixels(100, 100); + + SkCanvas canvas(bm); + canvas.clear(0); + SkPaint paint; + paint.setAntiAlias(true); + canvas.drawCircle(50, 50, 50, paint); + return bm; +} + +class EmbossGM : public skiagm::GM { +public: + EmbossGM() { + } + +protected: + virtual SkString onShortName() SK_OVERRIDE { + return SkString("emboss"); + } + + virtual SkISize onISize() SK_OVERRIDE { + return SkISize::Make(600, 120); + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + SkPaint paint; + SkBitmap bm = make_bm(); + canvas->drawBitmap(bm, 10, 10, &paint); + + const SkScalar dir[] = { 1, 1, 1 }; + paint.setMaskFilter(SkBlurMaskFilter::CreateEmboss(3, dir, 0.3f, 0.1f))->unref(); + canvas->translate(bm.width() + SkIntToScalar(10), 0); + canvas->drawBitmap(bm, 10, 10, &paint); + + // this combination of emboss+colorfilter used to crash -- so we exercise it to + // confirm that we have a fix. + paint.setColorFilter(SkColorFilter::CreateModeFilter(0xFFFF0000, SkXfermode::kSrcATop_Mode))->unref(); + canvas->translate(bm.width() + SkIntToScalar(10), 0); + canvas->drawBitmap(bm, 10, 10, &paint); + } + +private: + typedef skiagm::GM INHERITED; +}; + +DEF_GM( return SkNEW(EmbossGM); ) diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index c8f9c2f65c..f3d7b80a7b 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -71,6 +71,7 @@ '../gm/drrect.cpp', '../gm/etc1bitmap.cpp', '../gm/extractbitmap.cpp', + '../gm/emboss.cpp', '../gm/emptypath.cpp', '../gm/fatpathfill.cpp', '../gm/factory.cpp', diff --git a/include/core/SkShader.h b/include/core/SkShader.h index 8530023671..6effe797f7 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -185,6 +185,9 @@ public: return SkShader::CanCallShadeSpan16(this->getFlags()); } + // Notification from blitter::blitMask in case we need to see the non-alpha channels + virtual void set3DMask(const SkMask*) {} + protected: // Reference to shader, so we don't have to dupe information. const SkShader& fShader; diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h index d445f56f14..d293c50303 100644 --- a/src/core/SkBitmapProcShader.h +++ b/src/core/SkBitmapProcShader.h @@ -73,7 +73,7 @@ private: // an Sk3DBlitter in SkDraw.cpp // Note that some contexts may contain other contexts (e.g. for compose shaders), but we've not // yet found a situation where the size below isn't big enough. -typedef SkSmallAllocator<3, 768> SkTBlitterAllocator; +typedef SkSmallAllocator<3, 1024> SkTBlitterAllocator; // If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive // the SkShader. diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index b9e9917891..f4669d5959 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -620,7 +620,7 @@ public: } } - void setMask(const SkMask* mask) { fMask = mask; } + virtual void set3DMask(const SkMask* mask) SK_OVERRIDE { fMask = mask; } virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { if (fProxyContext) { @@ -740,9 +740,9 @@ SkFlattenable* Sk3DShader::CreateProc(SkReadBuffer& buffer) { class Sk3DBlitter : public SkBlitter { public: - Sk3DBlitter(SkBlitter* proxy, Sk3DShader::Sk3DShaderContext* shaderContext) + Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext) : fProxy(proxy) - , f3DShaderContext(shaderContext) + , fShaderContext(shaderContext) {} virtual void blitH(int x, int y, int width) { @@ -764,13 +764,13 @@ public: virtual void blitMask(const SkMask& mask, const SkIRect& clip) { if (mask.fFormat == SkMask::k3D_Format) { - f3DShaderContext->setMask(&mask); + fShaderContext->set3DMask(&mask); ((SkMask*)&mask)->fFormat = SkMask::kA8_Format; fProxy->blitMask(mask, clip); ((SkMask*)&mask)->fFormat = SkMask::k3D_Format; - f3DShaderContext->setMask(NULL); + fShaderContext->set3DMask(NULL); } else { fProxy->blitMask(mask, clip); } @@ -778,8 +778,8 @@ public: private: // Both pointers are unowned. They will be deleted by SkSmallAllocator. - SkBlitter* fProxy; - Sk3DShader::Sk3DShaderContext* f3DShaderContext; + SkBlitter* fProxy; + SkShader::Context* fShaderContext; }; /////////////////////////////////////////////////////////////////////////////// @@ -987,9 +987,9 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, if (shader3D) { SkBlitter* innerBlitter = blitter; // innerBlitter was allocated by allocator, which will delete it. - // We know shaderContext is of type Sk3DShaderContext because it belongs to shader3D. - blitter = allocator->createT<Sk3DBlitter>(innerBlitter, - static_cast<Sk3DShader::Sk3DShaderContext*>(shaderContext)); + // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to + // wrapper the blitter to notify it when we see an emboss mask. + blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shaderContext); } return blitter; } diff --git a/src/core/SkFilterShader.h b/src/core/SkFilterShader.h index 2ff6cdaf63..b98fc839a6 100644 --- a/src/core/SkFilterShader.h +++ b/src/core/SkFilterShader.h @@ -30,6 +30,11 @@ public: virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE; + virtual void set3DMask(const SkMask* mask) SK_OVERRIDE { + // forward to our proxy + fShaderContext->set3DMask(mask); + } + private: SkShader::Context* fShaderContext; |