182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com/* 282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com * Copyright 2012 The Android Open Source Project 382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com * 482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com * found in the LICENSE file. 682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com */ 782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "SkMagnifierImageFilter.h" 9b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 10b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips#include "SkBitmap.h" 1182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "SkColorPriv.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 13b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips#include "SkSpecialImage.h" 148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 15c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h" 1682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 1803245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#if SK_SUPPORT_GPU 19b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips#include "GrContext.h" 208e1c4e672553ecae2745168514240705f3516773Robert Phillips#include "effects/GrProxyMove.h" 2182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "effects/GrSingleTextureEffect.h" 22b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman#include "glsl/GrGLSLColorSpaceXformHelper.h" 2364c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h" 242d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 25018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 267ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h" 2794efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon#include "../private/GrGLSL.h" 288e1c4e672553ecae2745168514240705f3516773Robert Phillips#endif 298e1c4e672553ecae2745168514240705f3516773Robert Phillips 308e1c4e672553ecae2745168514240705f3516773Robert Phillipssk_sp<SkImageFilter> SkMagnifierImageFilter::Make(const SkRect& srcRect, SkScalar inset, 318e1c4e672553ecae2745168514240705f3516773Robert Phillips sk_sp<SkImageFilter> input, 328e1c4e672553ecae2745168514240705f3516773Robert Phillips const CropRect* cropRect) { 338e1c4e672553ecae2745168514240705f3516773Robert Phillips if (!SkScalarIsFinite(inset) || !SkIsValidRect(srcRect)) { 348e1c4e672553ecae2745168514240705f3516773Robert Phillips return nullptr; 358e1c4e672553ecae2745168514240705f3516773Robert Phillips } 368e1c4e672553ecae2745168514240705f3516773Robert Phillips if (inset < 0) { 378e1c4e672553ecae2745168514240705f3516773Robert Phillips return nullptr; 388e1c4e672553ecae2745168514240705f3516773Robert Phillips } 398e1c4e672553ecae2745168514240705f3516773Robert Phillips // Negative numbers in src rect are not supported 408e1c4e672553ecae2745168514240705f3516773Robert Phillips if (srcRect.fLeft < 0 || srcRect.fTop < 0) { 418e1c4e672553ecae2745168514240705f3516773Robert Phillips return nullptr; 428e1c4e672553ecae2745168514240705f3516773Robert Phillips } 438e1c4e672553ecae2745168514240705f3516773Robert Phillips return sk_sp<SkImageFilter>(new SkMagnifierImageFilter(srcRect, inset, 448e1c4e672553ecae2745168514240705f3516773Robert Phillips std::move(input), 458e1c4e672553ecae2745168514240705f3516773Robert Phillips cropRect)); 468e1c4e672553ecae2745168514240705f3516773Robert Phillips} 4782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 488e1c4e672553ecae2745168514240705f3516773Robert Phillips#if SK_SUPPORT_GPU 4982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comclass GrMagnifierEffect : public GrSingleTextureEffect { 5082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.compublic: 51296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider, 528e1c4e672553ecae2745168514240705f3516773Robert Phillips sk_sp<GrTextureProxy> proxy, 538e1c4e672553ecae2745168514240705f3516773Robert Phillips sk_sp<GrColorSpaceXform> colorSpaceXform, 548e1c4e672553ecae2745168514240705f3516773Robert Phillips const SkIRect& bounds, 558e1c4e672553ecae2745168514240705f3516773Robert Phillips const SkRect& srcRect, 568e1c4e672553ecae2745168514240705f3516773Robert Phillips float xInvZoom, 578e1c4e672553ecae2745168514240705f3516773Robert Phillips float yInvZoom, 588e1c4e672553ecae2745168514240705f3516773Robert Phillips float xInvInset, 598e1c4e672553ecae2745168514240705f3516773Robert Phillips float yInvInset) { 60296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips return sk_sp<GrFragmentProcessor>(new GrMagnifierEffect(resourceProvider, 618e1c4e672553ecae2745168514240705f3516773Robert Phillips std::move(proxy), 628e1c4e672553ecae2745168514240705f3516773Robert Phillips std::move(colorSpaceXform), 638e1c4e672553ecae2745168514240705f3516773Robert Phillips bounds, srcRect, 6406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman xInvZoom, yInvZoom, 6506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman xInvInset, yInvInset)); 660ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com } 6782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 68fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein ~GrMagnifierEffect() override {} 6982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 7036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "Magnifier"; } 71eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 728e1c4e672553ecae2745168514240705f3516773Robert Phillips const SkIRect& bounds() const { return fBounds; } // Bounds of source image. 738e1c4e672553ecae2745168514240705f3516773Robert Phillips const SkRect& srcRect() const { return fSrcRect; } 74d0d37cace08f12abf8d316e6949e947551d418e6senorblanco 75d0d37cace08f12abf8d316e6949e947551d418e6senorblanco // Scale to apply to zoomed pixels (srcRect size / bounds size). 76b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips float xInvZoom() const { return fXInvZoom; } 77b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips float yInvZoom() const { return fYInvZoom; } 78d0d37cace08f12abf8d316e6949e947551d418e6senorblanco 79d0d37cace08f12abf8d316e6949e947551d418e6senorblanco // 1/radius over which to transition from unzoomed to zoomed pixels (bounds size / inset). 80b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips float xInvInset() const { return fXInvInset; } 81b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips float yInvInset() const { return fYInvInset; } 8282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 8382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comprivate: 84296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips GrMagnifierEffect(GrResourceProvider* resourceProvider, 858e1c4e672553ecae2745168514240705f3516773Robert Phillips sk_sp<GrTextureProxy> proxy, 868e1c4e672553ecae2745168514240705f3516773Robert Phillips sk_sp<GrColorSpaceXform> colorSpaceXform, 878e1c4e672553ecae2745168514240705f3516773Robert Phillips const SkIRect& bounds, 888e1c4e672553ecae2745168514240705f3516773Robert Phillips const SkRect& srcRect, 898e1c4e672553ecae2745168514240705f3516773Robert Phillips float xInvZoom, 908e1c4e672553ecae2745168514240705f3516773Robert Phillips float yInvZoom, 918e1c4e672553ecae2745168514240705f3516773Robert Phillips float xInvInset, 928e1c4e672553ecae2745168514240705f3516773Robert Phillips float yInvInset) 93296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips : INHERITED{resourceProvider, 948e1c4e672553ecae2745168514240705f3516773Robert Phillips ModulationFlags(proxy->config()), 958e1c4e672553ecae2745168514240705f3516773Robert Phillips GR_PROXY_MOVE(proxy), 968e1c4e672553ecae2745168514240705f3516773Robert Phillips std::move(colorSpaceXform), 978e1c4e672553ecae2745168514240705f3516773Robert Phillips SkMatrix::I()} // TODO: no GrSamplerParams::kBilerp_FilterMode? 988e1c4e672553ecae2745168514240705f3516773Robert Phillips , fBounds(bounds) 998e1c4e672553ecae2745168514240705f3516773Robert Phillips , fSrcRect(srcRect) 100587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon , fXInvZoom(xInvZoom) 101587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon , fYInvZoom(yInvZoom) 102587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon , fXInvInset(xInvInset) 103587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon , fYInvInset(yInvInset) { 104eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt this->initClassID<GrMagnifierEffect>(); 105eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 1060ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 10757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 108b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix 10994efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 1104b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix 11136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrFragmentProcessor&) const override; 11268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com 113b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 11482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1158e1c4e672553ecae2745168514240705f3516773Robert Phillips SkIRect fBounds; 1168e1c4e672553ecae2745168514240705f3516773Robert Phillips SkRect fSrcRect; 117f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fXInvZoom; 118f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fYInvZoom; 119f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fXInvInset; 120f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fYInvInset; 12182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 12282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com typedef GrSingleTextureEffect INHERITED; 12382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com}; 12482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 12582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com// For brevity 126018fb62d12d1febf121fe265da5b6117b86a6541egdanieltypedef GrGLSLProgramDataManager::UniformHandle UniformHandle; 12782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 12864c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GrGLMagnifierEffect : public GrGLSLFragmentProcessor { 12982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.compublic: 1309cdb9920fcad286ecf7875ea19902022b644fbdcrobertphillips void emitCode(EmitArgs&) override; 13182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 132b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman static inline void GenKey(const GrProcessor& effect, const GrShaderCaps&, 133b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman GrProcessorKeyBuilder* b) { 134b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman const GrMagnifierEffect& zoom = effect.cast<GrMagnifierEffect>(); 135b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman b->add32(GrColorSpaceXform::XformKey(zoom.colorSpaceXform())); 136b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman } 137b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman 138b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected: 139018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; 14082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 14182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comprivate: 14217fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com UniformHandle fOffsetVar; 143f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org UniformHandle fInvZoomVar; 144f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org UniformHandle fInvInsetVar; 145d0d37cace08f12abf8d316e6949e947551d418e6senorblanco UniformHandle fBoundsVar; 146c624d9d212c4168fc6c202a8535ddff8a3bfb16aBrian Osman GrGLSLColorSpaceXformHelper fColorSpaceHelper; 14717fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com 14864c4728c70001ed074fecf5c4e083781987b12e9egdaniel typedef GrGLSLFragmentProcessor INHERITED; 14982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com}; 15082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1517c157a988845fb00f9024d6db6dda142c3458033wangyixvoid GrGLMagnifierEffect::emitCode(EmitArgs& args) { 1527ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 1535e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fOffsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag, 1547ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec2f_GrSLType, kDefault_GrSLPrecision, 1557ea439b2203855db97330b25945b87dd4b170b8begdaniel "Offset"); 1565e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fInvZoomVar = uniformHandler->addUniform(kFragment_GrShaderFlag, 1577ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec2f_GrSLType, kDefault_GrSLPrecision, 1587ea439b2203855db97330b25945b87dd4b170b8begdaniel "InvZoom"); 1595e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fInvInsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag, 1607ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec2f_GrSLType, kDefault_GrSLPrecision, 1617ea439b2203855db97330b25945b87dd4b170b8begdaniel "InvInset"); 1625e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fBoundsVar = uniformHandler->addUniform(kFragment_GrShaderFlag, 1637ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec4f_GrSLType, kDefault_GrSLPrecision, 1647ea439b2203855db97330b25945b87dd4b170b8begdaniel "Bounds"); 16582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 166b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman const GrMagnifierEffect& zoom = args.fFp.cast<GrMagnifierEffect>(); 167c624d9d212c4168fc6c202a8535ddff8a3bfb16aBrian Osman fColorSpaceHelper.emitCode(uniformHandler, zoom.colorSpaceXform()); 168b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman 1698528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 1701a1aa9303484106a955e5549bf8ae24950f54e7absalomon SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); 1714ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); 1724ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n", 1737ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler->getUniformCStr(fOffsetVar), 1744ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel coords2D.c_str(), 1757ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler->getUniformCStr(fInvZoomVar)); 1767ea439b2203855db97330b25945b87dd4b170b8begdaniel const char* bounds = uniformHandler->getUniformCStr(fBoundsVar); 1774ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds); 1784ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tdelta = min(delta, vec2(1.0, 1.0) - delta);\n"); 1794ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tdelta = delta * %s;\n", 1807ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler->getUniformCStr(fInvInsetVar)); 1814ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1824ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tfloat weight = 0.0;\n"); 1834ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); 1844ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); 1854ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n"); 1864ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); 1874ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); 1884ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t} else {\n"); 1894ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tvec2 delta_squared = delta * delta;\n"); 1904ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n"); 1914ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t}\n"); 1924ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1934ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n"); 1944ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tvec4 output_color = "); 195b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord", kVec2f_GrSLType, 196c624d9d212c4168fc6c202a8535ddff8a3bfb16aBrian Osman &fColorSpaceHelper); 1974ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(";\n"); 1984ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1994ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\t%s = output_color;", args.fOutputColor); 200f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com SkString modulate; 2017c157a988845fb00f9024d6db6dda142c3458033wangyix GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); 2024ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(modulate.c_str()); 20382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 20482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 205018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLMagnifierEffect::onSetData(const GrGLSLProgramDataManager& pdman, 206018fb62d12d1febf121fe265da5b6117b86a6541egdaniel const GrProcessor& effect) { 20749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrMagnifierEffect& zoom = effect.cast<GrMagnifierEffect>(); 2088e1c4e672553ecae2745168514240705f3516773Robert Phillips 2098e1c4e672553ecae2745168514240705f3516773Robert Phillips GrTexture* tex = zoom.textureSampler(0).texture(); 2108e1c4e672553ecae2745168514240705f3516773Robert Phillips SkASSERT(tex); 2118e1c4e672553ecae2745168514240705f3516773Robert Phillips 2128e1c4e672553ecae2745168514240705f3516773Robert Phillips SkScalar invW = 1.0f / tex->width(); 2138e1c4e672553ecae2745168514240705f3516773Robert Phillips SkScalar invH = 1.0f / tex->height(); 2148e1c4e672553ecae2745168514240705f3516773Robert Phillips 2158e1c4e672553ecae2745168514240705f3516773Robert Phillips { 2168e1c4e672553ecae2745168514240705f3516773Robert Phillips SkScalar y = zoom.srcRect().y() * invH; 2178e1c4e672553ecae2745168514240705f3516773Robert Phillips if (tex->origin() != kTopLeft_GrSurfaceOrigin) { 2188e1c4e672553ecae2745168514240705f3516773Robert Phillips y = 1.0f - (zoom.srcRect().height() / zoom.bounds().height()) - y; 2198e1c4e672553ecae2745168514240705f3516773Robert Phillips } 2208e1c4e672553ecae2745168514240705f3516773Robert Phillips 2218e1c4e672553ecae2745168514240705f3516773Robert Phillips pdman.set2f(fOffsetVar, zoom.srcRect().x() * invW, y); 2228e1c4e672553ecae2745168514240705f3516773Robert Phillips } 2238e1c4e672553ecae2745168514240705f3516773Robert Phillips 224b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips pdman.set2f(fInvZoomVar, zoom.xInvZoom(), zoom.yInvZoom()); 225b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips pdman.set2f(fInvInsetVar, zoom.xInvInset(), zoom.yInvInset()); 2268e1c4e672553ecae2745168514240705f3516773Robert Phillips 2278e1c4e672553ecae2745168514240705f3516773Robert Phillips { 2288e1c4e672553ecae2745168514240705f3516773Robert Phillips SkScalar y = zoom.bounds().y() * invH; 2298e1c4e672553ecae2745168514240705f3516773Robert Phillips if (tex->origin() != kTopLeft_GrSurfaceOrigin) { 2308e1c4e672553ecae2745168514240705f3516773Robert Phillips y = 1.0f - zoom.bounds().height() * invH; 2318e1c4e672553ecae2745168514240705f3516773Robert Phillips } 2328e1c4e672553ecae2745168514240705f3516773Robert Phillips 2338e1c4e672553ecae2745168514240705f3516773Robert Phillips pdman.set4f(fBoundsVar, 2348e1c4e672553ecae2745168514240705f3516773Robert Phillips zoom.bounds().x() * invW, 2358e1c4e672553ecae2745168514240705f3516773Robert Phillips y, 2368e1c4e672553ecae2745168514240705f3516773Robert Phillips SkIntToScalar(tex->width()) / zoom.bounds().width(), 2378e1c4e672553ecae2745168514240705f3516773Robert Phillips SkIntToScalar(tex->height()) / zoom.bounds().height()); 2388e1c4e672553ecae2745168514240705f3516773Robert Phillips } 2398e1c4e672553ecae2745168514240705f3516773Robert Phillips 240b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman if (SkToBool(zoom.colorSpaceXform())) { 241c624d9d212c4168fc6c202a8535ddff8a3bfb16aBrian Osman fColorSpaceHelper.setData(pdman, zoom.colorSpaceXform()); 242b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman } 24382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 24482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 24582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com///////////////////////////////////////////////////////////////////// 24682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 24794efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid GrMagnifierEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, 24857d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 249eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrGLMagnifierEffect::GenKey(*this, caps, b); 250eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 251eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 25257d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* GrMagnifierEffect::onCreateGLSLInstance() const { 2539cdb9920fcad286ecf7875ea19902022b644fbdcrobertphillips return new GrGLMagnifierEffect; 254eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 255eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 256b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMagnifierEffect); 25782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2586f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 25906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemansk_sp<GrFragmentProcessor> GrMagnifierEffect::TestCreate(GrProcessorTestData* d) { 2608e1c4e672553ecae2745168514240705f3516773Robert Phillips sk_sp<GrTextureProxy> proxy = d->textureProxy(0); 26182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxWidth = 200; 26282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxHeight = 200; 2638e1c4e672553ecae2745168514240705f3516773Robert Phillips const SkScalar kMaxInset = 20.0f; 2640067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt uint32_t width = d->fRandom->nextULessThan(kMaxWidth); 2650067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt uint32_t height = d->fRandom->nextULessThan(kMaxHeight); 2668e1c4e672553ecae2745168514240705f3516773Robert Phillips SkScalar inset = d->fRandom->nextRangeScalar(1.0f, kMaxInset); 2678e1c4e672553ecae2745168514240705f3516773Robert Phillips sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(d->fRandom); 2688e1c4e672553ecae2745168514240705f3516773Robert Phillips 2698e1c4e672553ecae2745168514240705f3516773Robert Phillips SkIRect bounds = SkIRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight)); 2708e1c4e672553ecae2745168514240705f3516773Robert Phillips SkRect srcRect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); 2711aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org 27206ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman sk_sp<GrFragmentProcessor> effect(GrMagnifierEffect::Make( 273296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips d->resourceProvider(), 2748e1c4e672553ecae2745168514240705f3516773Robert Phillips std::move(proxy), 275b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman std::move(colorSpaceXform), 2768e1c4e672553ecae2745168514240705f3516773Robert Phillips bounds, 2778e1c4e672553ecae2745168514240705f3516773Robert Phillips srcRect, 2788e1c4e672553ecae2745168514240705f3516773Robert Phillips srcRect.width() / bounds.width(), 2798e1c4e672553ecae2745168514240705f3516773Robert Phillips srcRect.height() / bounds.height(), 2808e1c4e672553ecae2745168514240705f3516773Robert Phillips bounds.width() / inset, 2818e1c4e672553ecae2745168514240705f3516773Robert Phillips bounds.height() / inset)); 28249f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(effect); 283021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com return effect; 28482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 2856f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#endif 28682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 28782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 28882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2890e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrMagnifierEffect::onIsEqual(const GrFragmentProcessor& sBase) const { 29049586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrMagnifierEffect& s = sBase.cast<GrMagnifierEffect>(); 291d0d37cace08f12abf8d316e6949e947551d418e6senorblanco return (this->fBounds == s.fBounds && 2928e1c4e672553ecae2745168514240705f3516773Robert Phillips this->fSrcRect == s.fSrcRect && 293f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fXInvZoom == s.fXInvZoom && 294f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fYInvZoom == s.fYInvZoom && 295f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fXInvInset == s.fXInvInset && 296f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fYInvInset == s.fYInvInset); 29782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 29882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 29903245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#endif 30003245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com 30182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 3029fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 303b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillipsSkMagnifierImageFilter::SkMagnifierImageFilter(const SkRect& srcRect, 304b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkScalar inset, 305b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips sk_sp<SkImageFilter> input, 306b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips const CropRect* cropRect) 307b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips : INHERITED(&input, 1, cropRect) 30811171f3b66ba6aba561fcaafbc51eaa354b73353robertphillips , fSrcRect(srcRect) 30911171f3b66ba6aba561fcaafbc51eaa354b73353robertphillips , fInset(inset) { 3108e1c4e672553ecae2745168514240705f3516773Robert Phillips SkASSERT(srcRect.left() >= 0 && srcRect.top() >= 0 && inset >= 0); 31182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 31282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 31360c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkMagnifierImageFilter::CreateProc(SkReadBuffer& buffer) { 3149fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 3159fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkRect src; 3169fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&src); 317b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips return Make(src, buffer.readScalar(), common.getInput(0), &common.cropRect()); 3189fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 3199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 3208b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkMagnifierImageFilter::flatten(SkWriteBuffer& buffer) const { 32182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->INHERITED::flatten(buffer); 3229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.writeRect(fSrcRect); 32382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com buffer.writeScalar(fInset); 32482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 32582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 326b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillipssk_sp<SkSpecialImage> SkMagnifierImageFilter::onFilterImage(SkSpecialImage* source, 327b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips const Context& ctx, 328b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkIPoint* offset) const { 329b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkIPoint inputOffset = SkIPoint::Make(0, 0); 330b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset)); 331b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips if (!input) { 332b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips return nullptr; 333b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips } 334b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 335b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(), 336b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips input->width(), input->height()); 337b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 338b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkIRect bounds; 339b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips if (!this->applyCropRect(ctx, inputBounds, &bounds)) { 340b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips return nullptr; 341b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips } 342b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 343b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkScalar invInset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; 344b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 345b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkScalar invXZoom = fSrcRect.width() / bounds.width(); 346b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkScalar invYZoom = fSrcRect.height() / bounds.height(); 347b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 348b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 349b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips#if SK_SUPPORT_GPU 350b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips if (source->isTextureBacked()) { 351b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips GrContext* context = source->getContext(); 352b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 3538e1c4e672553ecae2745168514240705f3516773Robert Phillips sk_sp<GrTextureProxy> inputProxy(input->asTextureProxyRef(context)); 3548e1c4e672553ecae2745168514240705f3516773Robert Phillips SkASSERT(inputProxy); 355b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 356b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips offset->fX = bounds.left(); 357b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips offset->fY = bounds.top(); 358b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips bounds.offset(-inputOffset); 359b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 360b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman SkColorSpace* dstColorSpace = ctx.outputProperties().colorSpace(); 361b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(input->getColorSpace(), 362b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman dstColorSpace); 36306ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman sk_sp<GrFragmentProcessor> fp(GrMagnifierEffect::Make( 364296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips context->resourceProvider(), 3658e1c4e672553ecae2745168514240705f3516773Robert Phillips std::move(inputProxy), 366b44bb31137787b9dcc530d9061e3a08cf261da23Brian Osman std::move(colorSpaceXform), 3678e1c4e672553ecae2745168514240705f3516773Robert Phillips bounds, 3688e1c4e672553ecae2745168514240705f3516773Robert Phillips fSrcRect, 369b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips invXZoom, 370b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips invYZoom, 371b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips bounds.width() * invInset, 372b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips bounds.height() * invInset)); 373b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips if (!fp) { 374b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips return nullptr; 375b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips } 376b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 3772a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman return DrawWithFP(context, std::move(fp), bounds, ctx.outputProperties()); 37882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 379b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips#endif 38082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 381b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkBitmap inputBM; 382b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 383b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips if (!input->getROPixels(&inputBM)) { 384b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips return nullptr; 38582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 38682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 387b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips if ((inputBM.colorType() != kN32_SkColorType) || 388b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips (fSrcRect.width() >= inputBM.width()) || (fSrcRect.height() >= inputBM.height())) { 389b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips return nullptr; 390b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips } 391b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 392b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkAutoLockPixels alp(inputBM); 393b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkASSERT(inputBM.getPixels()); 394b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips if (!inputBM.getPixels() || inputBM.width() <= 0 || inputBM.height() <= 0) { 395b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips return nullptr; 396cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org } 397cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org 398b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()); 39982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 400b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkBitmap dst; 401b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips if (!dst.tryAllocPixels(info)) { 402b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips return nullptr; 403b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips } 40482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 405b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkAutoLockPixels dstLock(dst); 406b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 407b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkColor* dptr = dst.getAddr32(0, 0); 408b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips int dstWidth = dst.width(), dstHeight = dst.height(); 409b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips for (int y = 0; y < dstHeight; ++y) { 410b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips for (int x = 0; x < dstWidth; ++x) { 411b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkScalar x_dist = SkMin32(x, dstWidth - x - 1) * invInset; 412b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips SkScalar y_dist = SkMin32(y, dstHeight - y - 1) * invInset; 4135d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar weight = 0; 4145d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com 4155d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com static const SkScalar kScalar2 = SkScalar(2); 41682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 41782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com // To create a smooth curve at the corners, we need to work on 41882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com // a square twice the size of the inset. 4195d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com if (x_dist < kScalar2 && y_dist < kScalar2) { 4205d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com x_dist = kScalar2 - x_dist; 4215d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com y_dist = kScalar2 - y_dist; 4225d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com 4235d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar dist = SkScalarSqrt(SkScalarSquare(x_dist) + 4245d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalarSquare(y_dist)); 4255d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com dist = SkMaxScalar(kScalar2 - dist, 0); 4265d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com weight = SkMinScalar(SkScalarSquare(dist), SK_Scalar1); 42782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } else { 4285d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar sqDist = SkMinScalar(SkScalarSquare(x_dist), 4295d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalarSquare(y_dist)); 4305d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com weight = SkMinScalar(sqDist, SK_Scalar1); 43182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 43282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 4338be952ad8c9deefe19cff36f9ad217563400f817Mike Reed SkScalar x_interp = weight * (fSrcRect.x() + x * invXZoom) + (1 - weight) * x; 4348be952ad8c9deefe19cff36f9ad217563400f817Mike Reed SkScalar y_interp = weight * (fSrcRect.y() + y * invYZoom) + (1 - weight) * y; 43582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 436b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips int x_val = SkTPin(bounds.x() + SkScalarFloorToInt(x_interp), 0, inputBM.width() - 1); 437b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips int y_val = SkTPin(bounds.y() + SkScalarFloorToInt(y_interp), 0, inputBM.height() - 1); 43882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 439b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips *dptr = *inputBM.getAddr32(x_val, y_val); 44082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com dptr++; 44182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 44282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 443b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips 444b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips offset->fX = bounds.left(); 445b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips offset->fY = bounds.top(); 4463e302275b324172c845627cbd00cee8a06571bafrobertphillips return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), 447b2a4dc6a350abe3b18ecac719e499600f739a6e2robertphillips dst); 44882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 449f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 450f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING 451f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkMagnifierImageFilter::toString(SkString* str) const { 452f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("SkMagnifierImageFilter: ("); 453f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("src: (%f,%f,%f,%f) ", 454f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBottom); 455f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("inset: %f", fInset); 456f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append(")"); 457f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips} 458f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif 459