diff options
Diffstat (limited to 'src/effects/SkMagnifierImageFilter.cpp')
-rw-r--r-- | src/effects/SkMagnifierImageFilter.cpp | 51 |
1 files changed, 40 insertions, 11 deletions
diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp index 622713d796..6d2ee01d52 100644 --- a/src/effects/SkMagnifierImageFilter.cpp +++ b/src/effects/SkMagnifierImageFilter.cpp @@ -25,6 +25,7 @@ class GrMagnifierEffect : public GrSingleTextureEffect { public: static GrFragmentProcessor* Create(GrTexture* texture, + const SkRect& bounds, float xOffset, float yOffset, float xInvZoom, @@ -32,6 +33,7 @@ public: float xInvInset, float yInvInset) { return SkNEW_ARGS(GrMagnifierEffect, (texture, + bounds, xOffset, yOffset, xInvZoom, @@ -48,15 +50,22 @@ public: GrGLFragmentProcessor* createGLInstance() const override; + const SkRect& bounds() const { return fBounds; } // Bounds of source image. + // Offset to apply to zoomed pixels, (srcRect position / texture size). float x_offset() const { return fXOffset; } float y_offset() const { return fYOffset; } + + // Scale to apply to zoomed pixels (srcRect size / bounds size). float x_inv_zoom() const { return fXInvZoom; } float y_inv_zoom() const { return fYInvZoom; } + + // 1/radius over which to transition from unzoomed to zoomed pixels (bounds size / inset). float x_inv_inset() const { return fXInvInset; } float y_inv_inset() const { return fYInvInset; } private: GrMagnifierEffect(GrTexture* texture, + const SkRect& bounds, float xOffset, float yOffset, float xInvZoom, @@ -64,6 +73,7 @@ private: float xInvInset, float yInvInset) : GrSingleTextureEffect(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) + , fBounds(bounds) , fXOffset(xOffset) , fYOffset(yOffset) , fXInvZoom(xInvZoom) @@ -79,6 +89,7 @@ private: GR_DECLARE_FRAGMENT_PROCESSOR_TEST; + SkRect fBounds; float fXOffset; float fYOffset; float fXInvZoom; @@ -109,6 +120,7 @@ private: UniformHandle fOffsetVar; UniformHandle fInvZoomVar; UniformHandle fInvInsetVar; + UniformHandle fBoundsVar; typedef GrGLFragmentProcessor INHERITED; }; @@ -134,6 +146,10 @@ void GrGLMagnifierEffect::emitCode(GrGLFPBuilder* builder, GrGLProgramBuilder::kFragment_Visibility | GrGLProgramBuilder::kVertex_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "InvInset"); + fBoundsVar = builder->addUniform( + GrGLProgramBuilder::kFragment_Visibility | + GrGLProgramBuilder::kVertex_Visibility, + kVec4f_GrSLType, kDefault_GrSLPrecision, "Bounds"); GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); @@ -142,9 +158,9 @@ void GrGLMagnifierEffect::emitCode(GrGLFPBuilder* builder, builder->getUniformCStr(fOffsetVar), coords2D.c_str(), builder->getUniformCStr(fInvZoomVar)); - - fsBuilder->codeAppend("\t\tvec2 delta = min(coord, vec2(1.0, 1.0) - coord);\n"); - + const char* bounds = builder->getUniformCStr(fBoundsVar); + fsBuilder->codeAppendf("\t\tvec2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds); + fsBuilder->codeAppendf("\t\tdelta = min(delta, vec2(1.0, 1.0) - delta);\n"); fsBuilder->codeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(fInvInsetVar)); fsBuilder->codeAppend("\t\tfloat weight = 0.0;\n"); @@ -175,6 +191,8 @@ void GrGLMagnifierEffect::setData(const GrGLProgramDataManager& pdman, pdman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset()); pdman.set2f(fInvZoomVar, zoom.x_inv_zoom(), zoom.y_inv_zoom()); pdman.set2f(fInvInsetVar, zoom.x_inv_inset(), zoom.y_inv_inset()); + pdman.set4f(fBoundsVar, zoom.bounds().x(), zoom.bounds().y(), + zoom.bounds().width(), zoom.bounds().height()); } ///////////////////////////////////////////////////////////////////// @@ -206,6 +224,7 @@ GrFragmentProcessor* GrMagnifierEffect::TestCreate(SkRandom* random, GrFragmentProcessor* effect = GrMagnifierEffect::Create( texture, + SkRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight)), (float) width / texture->width(), (float) height / texture->height(), texture->width() / (float) x, @@ -220,7 +239,8 @@ GrFragmentProcessor* GrMagnifierEffect::TestCreate(SkRandom* random, bool GrMagnifierEffect::onIsEqual(const GrFragmentProcessor& sBase) const { const GrMagnifierEffect& s = sBase.cast<GrMagnifierEffect>(); - return (this->fXOffset == s.fXOffset && + return (this->fBounds == s.fBounds && + this->fXOffset == s.fXOffset && this->fYOffset == s.fYOffset && this->fXInvZoom == s.fXInvZoom && this->fYInvZoom == s.fYInvZoom && @@ -258,18 +278,27 @@ SkMagnifierImageFilter::SkMagnifierImageFilter(const SkRect& srcRect, SkScalar i #if SK_SUPPORT_GPU bool SkMagnifierImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, GrTexture* texture, - const SkMatrix&, const SkIRect&) const { + const SkMatrix&, const SkIRect&bounds) const { if (fp) { - SkScalar yOffset = (texture->origin() == kTopLeft_GrSurfaceOrigin) ? fSrcRect.y() : - (texture->height() - (fSrcRect.y() + fSrcRect.height())); + SkScalar yOffset = texture->origin() == kTopLeft_GrSurfaceOrigin ? fSrcRect.y() : + texture->height() - fSrcRect.height() * texture->height() / bounds.height() + - fSrcRect.y(); + int boundsY = (texture->origin() == kTopLeft_GrSurfaceOrigin) ? bounds.y() : + (texture->height() - bounds.height()); + SkRect effectBounds = SkRect::MakeXYWH( + SkIntToScalar(bounds.x()) / texture->width(), + SkIntToScalar(boundsY) / texture->height(), + SkIntToScalar(texture->width()) / bounds.width(), + SkIntToScalar(texture->height()) / bounds.height()); SkScalar invInset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; *fp = GrMagnifierEffect::Create(texture, + effectBounds, fSrcRect.x() / texture->width(), yOffset / texture->height(), - fSrcRect.width() / texture->width(), - fSrcRect.height() / texture->height(), - texture->width() * invInset, - texture->height() * invInset); + fSrcRect.width() / bounds.width(), + fSrcRect.height() / bounds.height(), + bounds.width() * invInset, + bounds.height() * invInset); } return true; } |