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 "SkBitmap.h" 982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "SkMagnifierImageFilter.h" 1082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "SkColorPriv.h" 111d3ff434954189e194c468f429598465146dcf4bsenorblanco#include "SkDevice.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 14c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h" 1582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 1703245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#if SK_SUPPORT_GPU 18eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrInvariantOutput.h" 1982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "effects/GrSingleTextureEffect.h" 2064c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h" 212d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 22018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 237ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h" 2482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comclass GrMagnifierEffect : public GrSingleTextureEffect { 2682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.compublic: 284a339529612a43871d021877e58698e067d6c4cdbsalomon static GrFragmentProcessor* Create(GrTexture* texture, 29d0d37cace08f12abf8d316e6949e947551d418e6senorblanco const SkRect& bounds, 30b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float xOffset, 31b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float yOffset, 32b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float xInvZoom, 33b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float yInvZoom, 34b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float xInvInset, 35b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float yInvInset) { 364a339529612a43871d021877e58698e067d6c4cdbsalomon return new GrMagnifierEffect(texture, bounds, xOffset, yOffset, xInvZoom, yInvZoom, xInvInset, 374a339529612a43871d021877e58698e067d6c4cdbsalomon yInvInset); 380ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com } 3982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 4082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com virtual ~GrMagnifierEffect() {}; 4182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 4236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein const char* name() const override { return "Magnifier"; } 43eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 44d0d37cace08f12abf8d316e6949e947551d418e6senorblanco const SkRect& bounds() const { return fBounds; } // Bounds of source image. 45d0d37cace08f12abf8d316e6949e947551d418e6senorblanco // Offset to apply to zoomed pixels, (srcRect position / texture size). 4682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float x_offset() const { return fXOffset; } 4782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float y_offset() const { return fYOffset; } 48d0d37cace08f12abf8d316e6949e947551d418e6senorblanco 49d0d37cace08f12abf8d316e6949e947551d418e6senorblanco // Scale to apply to zoomed pixels (srcRect size / bounds size). 50f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float x_inv_zoom() const { return fXInvZoom; } 51f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float y_inv_zoom() const { return fYInvZoom; } 52d0d37cace08f12abf8d316e6949e947551d418e6senorblanco 53d0d37cace08f12abf8d316e6949e947551d418e6senorblanco // 1/radius over which to transition from unzoomed to zoomed pixels (bounds size / inset). 54f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float x_inv_inset() const { return fXInvInset; } 55f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float y_inv_inset() const { return fYInvInset; } 5682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 5782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comprivate: 584a339529612a43871d021877e58698e067d6c4cdbsalomon GrMagnifierEffect(GrTexture* texture, 59d0d37cace08f12abf8d316e6949e947551d418e6senorblanco const SkRect& bounds, 600ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com float xOffset, 610ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com float yOffset, 62f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float xInvZoom, 63f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float yInvZoom, 64f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float xInvInset, 65f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float yInvInset) 664a339529612a43871d021877e58698e067d6c4cdbsalomon : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) 67d0d37cace08f12abf8d316e6949e947551d418e6senorblanco , fBounds(bounds) 680ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com , fXOffset(xOffset) 690ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com , fYOffset(yOffset) 70f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org , fXInvZoom(xInvZoom) 71f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org , fYInvZoom(yInvZoom) 72f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org , fXInvInset(xInvInset) 73eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt , fYInvInset(yInvInset) { 74eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt this->initClassID<GrMagnifierEffect>(); 75eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 760ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 7757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 78b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix 7957d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override; 804b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix 8136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrFragmentProcessor&) const override; 8268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com 8336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onComputeInvariantOutput(GrInvariantOutput* inout) const override; 841a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel 85b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 8682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 87d0d37cace08f12abf8d316e6949e947551d418e6senorblanco SkRect fBounds; 8882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fXOffset; 8982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fYOffset; 90f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fXInvZoom; 91f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fYInvZoom; 92f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fXInvInset; 93f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fYInvInset; 9482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 9582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com typedef GrSingleTextureEffect INHERITED; 9682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com}; 9782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 9882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com// For brevity 99018fb62d12d1febf121fe265da5b6117b86a6541egdanieltypedef GrGLSLProgramDataManager::UniformHandle UniformHandle; 10082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 10164c4728c70001ed074fecf5c4e083781987b12e9egdanielclass GrGLMagnifierEffect : public GrGLSLFragmentProcessor { 10282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.compublic: 1039cdb9920fcad286ecf7875ea19902022b644fbdcrobertphillips void emitCode(EmitArgs&) override; 10482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 105b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected: 106018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; 10782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 10882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comprivate: 10917fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com UniformHandle fOffsetVar; 110f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org UniformHandle fInvZoomVar; 111f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org UniformHandle fInvInsetVar; 112d0d37cace08f12abf8d316e6949e947551d418e6senorblanco UniformHandle fBoundsVar; 11317fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com 11464c4728c70001ed074fecf5c4e083781987b12e9egdaniel typedef GrGLSLFragmentProcessor INHERITED; 11582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com}; 11682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1177c157a988845fb00f9024d6db6dda142c3458033wangyixvoid GrGLMagnifierEffect::emitCode(EmitArgs& args) { 1187ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 1195e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fOffsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag, 1207ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec2f_GrSLType, kDefault_GrSLPrecision, 1217ea439b2203855db97330b25945b87dd4b170b8begdaniel "Offset"); 1225e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fInvZoomVar = uniformHandler->addUniform(kFragment_GrShaderFlag, 1237ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec2f_GrSLType, kDefault_GrSLPrecision, 1247ea439b2203855db97330b25945b87dd4b170b8begdaniel "InvZoom"); 1255e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fInvInsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag, 1267ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec2f_GrSLType, kDefault_GrSLPrecision, 1277ea439b2203855db97330b25945b87dd4b170b8begdaniel "InvInset"); 1285e58ceea8569f0d90ff7e3daf5de2def50407212cdalton fBoundsVar = uniformHandler->addUniform(kFragment_GrShaderFlag, 1297ea439b2203855db97330b25945b87dd4b170b8begdaniel kVec4f_GrSLType, kDefault_GrSLPrecision, 1307ea439b2203855db97330b25945b87dd4b170b8begdaniel "Bounds"); 13182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1328528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 1334ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0); 1344ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); 1354ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n", 1367ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler->getUniformCStr(fOffsetVar), 1374ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel coords2D.c_str(), 1387ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler->getUniformCStr(fInvZoomVar)); 1397ea439b2203855db97330b25945b87dd4b170b8begdaniel const char* bounds = uniformHandler->getUniformCStr(fBoundsVar); 1404ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tvec2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds); 1414ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tdelta = min(delta, vec2(1.0, 1.0) - delta);\n"); 1424ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\tdelta = delta * %s;\n", 1437ea439b2203855db97330b25945b87dd4b170b8begdaniel uniformHandler->getUniformCStr(fInvInsetVar)); 1444ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1454ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tfloat weight = 0.0;\n"); 1464ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); 1474ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); 1484ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n"); 1494ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); 1504ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); 1514ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t} else {\n"); 1524ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tvec2 delta_squared = delta * delta;\n"); 1534ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n"); 1544ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\t}\n"); 1554ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1564ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n"); 1574ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend("\t\tvec4 output_color = "); 1584ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->appendTextureLookup(args.fSamplers[0], "mix_coord"); 1594ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(";\n"); 1604ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel 1614ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppendf("\t\t%s = output_color;", args.fOutputColor); 162f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com SkString modulate; 1637c157a988845fb00f9024d6db6dda142c3458033wangyix GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); 1644ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel fragBuilder->codeAppend(modulate.c_str()); 16582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 16682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 167018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLMagnifierEffect::onSetData(const GrGLSLProgramDataManager& pdman, 168018fb62d12d1febf121fe265da5b6117b86a6541egdaniel const GrProcessor& effect) { 16949586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrMagnifierEffect& zoom = effect.cast<GrMagnifierEffect>(); 1707510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset()); 1717510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fInvZoomVar, zoom.x_inv_zoom(), zoom.y_inv_zoom()); 1727510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fInvInsetVar, zoom.x_inv_inset(), zoom.y_inv_inset()); 173d0d37cace08f12abf8d316e6949e947551d418e6senorblanco pdman.set4f(fBoundsVar, zoom.bounds().x(), zoom.bounds().y(), 174d0d37cace08f12abf8d316e6949e947551d418e6senorblanco zoom.bounds().width(), zoom.bounds().height()); 17582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 17682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 17782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com///////////////////////////////////////////////////////////////////// 17882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 17957d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielvoid GrMagnifierEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 18057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 181eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrGLMagnifierEffect::GenKey(*this, caps, b); 182eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 183eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 18457d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* GrMagnifierEffect::onCreateGLSLInstance() const { 1859cdb9920fcad286ecf7875ea19902022b644fbdcrobertphillips return new GrGLMagnifierEffect; 186eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 187eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 188b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMagnifierEffect); 18982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 190c21b09eec91c9e263cb0b88467ea44e348ed4962bsalomonconst GrFragmentProcessor* GrMagnifierEffect::TestCreate(GrProcessorTestData* d) { 1910067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt GrTexture* texture = d->fTextures[0]; 19282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxWidth = 200; 19382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxHeight = 200; 19482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxInset = 20; 1950067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt uint32_t width = d->fRandom->nextULessThan(kMaxWidth); 1960067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt uint32_t height = d->fRandom->nextULessThan(kMaxHeight); 1970067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt uint32_t x = d->fRandom->nextULessThan(kMaxWidth - width); 1980067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt uint32_t y = d->fRandom->nextULessThan(kMaxHeight - height); 1990067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt uint32_t inset = d->fRandom->nextULessThan(kMaxInset); 2001aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org 201b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor* effect = GrMagnifierEffect::Create( 2021aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org texture, 203d0d37cace08f12abf8d316e6949e947551d418e6senorblanco SkRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight)), 2041aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org (float) width / texture->width(), 2051aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org (float) height / texture->height(), 2061aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org texture->width() / (float) x, 2071aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org texture->height() / (float) y, 2081aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org (float) inset / texture->width(), 2091aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org (float) inset / texture->height()); 21049f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(effect); 211021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com return effect; 21282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 21382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 21482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 21582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2160e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrMagnifierEffect::onIsEqual(const GrFragmentProcessor& sBase) const { 21749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrMagnifierEffect& s = sBase.cast<GrMagnifierEffect>(); 218d0d37cace08f12abf8d316e6949e947551d418e6senorblanco return (this->fBounds == s.fBounds && 219d0d37cace08f12abf8d316e6949e947551d418e6senorblanco this->fXOffset == s.fXOffset && 22082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->fYOffset == s.fYOffset && 221f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fXInvZoom == s.fXInvZoom && 222f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fYInvZoom == s.fYInvZoom && 223f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fXInvInset == s.fXInvInset && 224f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fYInvInset == s.fYInvInset); 22582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 22682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 227605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielvoid GrMagnifierEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 2281a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel this->updateInvariantOutputForModulation(inout); 22968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com} 23068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com 23103245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#endif 23203245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com 23382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 2349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkMagnifierImageFilter::Create(const SkRect& srcRect, SkScalar inset, 2369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkImageFilter* input) { 2373f3b3d003527861dc0bd89733857576408906431mtklein 2389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!SkScalarIsFinite(inset) || !SkIsValidRect(srcRect)) { 23996fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 2419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed // Negative numbers in src rect are not supported 2429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (srcRect.fLeft < 0 || srcRect.fTop < 0) { 24396fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 245385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new SkMagnifierImageFilter(srcRect, inset, input); 2469fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 2479fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2499ea3d57fde28a5fe4487a111dc3dd49418235e5esenorblancoSkMagnifierImageFilter::SkMagnifierImageFilter(const SkRect& srcRect, SkScalar inset, 2509ea3d57fde28a5fe4487a111dc3dd49418235e5esenorblanco SkImageFilter* input) 2519ea3d57fde28a5fe4487a111dc3dd49418235e5esenorblanco : INHERITED(1, &input), fSrcRect(srcRect), fInset(inset) { 25282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0); 25382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 25482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 25503245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#if SK_SUPPORT_GPU 2565f10b5c1b5744106312e24835d235b72fdba5802joshualittbool SkMagnifierImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, 25785ff25e8d905502ec09d057ecc6245f487bf94cejoshualitt GrTexture* texture, const SkMatrix&, 25885ff25e8d905502ec09d057ecc6245f487bf94cejoshualitt const SkIRect&bounds) const { 259b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (fp) { 260d0d37cace08f12abf8d316e6949e947551d418e6senorblanco SkScalar yOffset = texture->origin() == kTopLeft_GrSurfaceOrigin ? fSrcRect.y() : 261d0d37cace08f12abf8d316e6949e947551d418e6senorblanco texture->height() - fSrcRect.height() * texture->height() / bounds.height() 262d0d37cace08f12abf8d316e6949e947551d418e6senorblanco - fSrcRect.y(); 263d0d37cace08f12abf8d316e6949e947551d418e6senorblanco int boundsY = (texture->origin() == kTopLeft_GrSurfaceOrigin) ? bounds.y() : 264d0d37cace08f12abf8d316e6949e947551d418e6senorblanco (texture->height() - bounds.height()); 265d0d37cace08f12abf8d316e6949e947551d418e6senorblanco SkRect effectBounds = SkRect::MakeXYWH( 266d0d37cace08f12abf8d316e6949e947551d418e6senorblanco SkIntToScalar(bounds.x()) / texture->width(), 267d0d37cace08f12abf8d316e6949e947551d418e6senorblanco SkIntToScalar(boundsY) / texture->height(), 268d0d37cace08f12abf8d316e6949e947551d418e6senorblanco SkIntToScalar(texture->width()) / bounds.width(), 269d0d37cace08f12abf8d316e6949e947551d418e6senorblanco SkIntToScalar(texture->height()) / bounds.height()); 270f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org SkScalar invInset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; 2714a339529612a43871d021877e58698e067d6c4cdbsalomon *fp = GrMagnifierEffect::Create(texture, 272d0d37cace08f12abf8d316e6949e947551d418e6senorblanco effectBounds, 273b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fSrcRect.x() / texture->width(), 274b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt yOffset / texture->height(), 275d0d37cace08f12abf8d316e6949e947551d418e6senorblanco fSrcRect.width() / bounds.width(), 276d0d37cace08f12abf8d316e6949e947551d418e6senorblanco fSrcRect.height() / bounds.height(), 277d0d37cace08f12abf8d316e6949e947551d418e6senorblanco bounds.width() * invInset, 278d0d37cace08f12abf8d316e6949e947551d418e6senorblanco bounds.height() * invInset); 27982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 28082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return true; 28182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 282d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif 28382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkMagnifierImageFilter::CreateProc(SkReadBuffer& buffer) { 2859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 2869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkRect src; 2879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&src); 2889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return Create(src, buffer.readScalar(), common.getInput(0)); 2899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 2909fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2918b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkMagnifierImageFilter::flatten(SkWriteBuffer& buffer) const { 29282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->INHERITED::flatten(buffer); 2939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.writeRect(fSrcRect); 29482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com buffer.writeScalar(fInset); 29582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 29682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 29748e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillipsbool SkMagnifierImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& src, 29848e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips const Context&, SkBitmap* dst, 29948e78468f5f6b900d476e616bdb1ba457c8f0b2arobertphillips SkIPoint* offset) const { 30028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org if ((src.colorType() != kN32_SkColorType) || 301cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org (fSrcRect.width() >= src.width()) || 302cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org (fSrcRect.height() >= src.height())) { 30382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return false; 30482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 30582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 30682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkAutoLockPixels alp(src); 30782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(src.getPixels()); 30882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) { 30982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return false; 31082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 31182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 3121d3ff434954189e194c468f429598465146dcf4bsenorblanco SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.height())); 3131d3ff434954189e194c468f429598465146dcf4bsenorblanco if (!device) { 314cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org return false; 315cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org } 3161d3ff434954189e194c468f429598465146dcf4bsenorblanco *dst = device->accessBitmap(false); 3171d3ff434954189e194c468f429598465146dcf4bsenorblanco SkAutoLockPixels alp_dst(*dst); 318cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org 3195d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_inset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; 32082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 3215d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_x_zoom = fSrcRect.width() / src.width(); 3225d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_y_zoom = fSrcRect.height() / src.height(); 32382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 32482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkColor* sptr = src.getAddr32(0, 0); 32582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkColor* dptr = dst->getAddr32(0, 0); 32682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com int width = src.width(), height = src.height(); 32782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com for (int y = 0; y < height; ++y) { 32882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com for (int x = 0; x < width; ++x) { 3295d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar x_dist = SkMin32(x, width - x - 1) * inv_inset; 3305d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar y_dist = SkMin32(y, height - y - 1) * inv_inset; 3315d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar weight = 0; 3325d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com 3335d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com static const SkScalar kScalar2 = SkScalar(2); 33482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 33582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com // To create a smooth curve at the corners, we need to work on 33682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com // a square twice the size of the inset. 3375d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com if (x_dist < kScalar2 && y_dist < kScalar2) { 3385d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com x_dist = kScalar2 - x_dist; 3395d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com y_dist = kScalar2 - y_dist; 3405d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com 3415d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar dist = SkScalarSqrt(SkScalarSquare(x_dist) + 3425d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalarSquare(y_dist)); 3435d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com dist = SkMaxScalar(kScalar2 - dist, 0); 3445d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com weight = SkMinScalar(SkScalarSquare(dist), SK_Scalar1); 34582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } else { 3465d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar sqDist = SkMinScalar(SkScalarSquare(x_dist), 3475d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalarSquare(y_dist)); 3485d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com weight = SkMinScalar(sqDist, SK_Scalar1); 34982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 35082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 3515d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar x_interp = SkScalarMul(weight, (fSrcRect.x() + x * inv_x_zoom)) + 3525d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com (SK_Scalar1 - weight) * x; 3535d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar y_interp = SkScalarMul(weight, (fSrcRect.y() + y * inv_y_zoom)) + 3545d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com (SK_Scalar1 - weight) * y; 35582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 35662ce0303fb3f9857ee3ab8df05934642c226b1a3bungeman int x_val = SkTPin(SkScalarFloorToInt(x_interp), 0, width - 1); 35762ce0303fb3f9857ee3ab8df05934642c226b1a3bungeman int y_val = SkTPin(SkScalarFloorToInt(y_interp), 0, height - 1); 35882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 35982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com *dptr = sptr[y_val * width + x_val]; 36082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com dptr++; 36182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 36282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 36382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return true; 36482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 365f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 366f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING 367f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkMagnifierImageFilter::toString(SkString* str) const { 368f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("SkMagnifierImageFilter: ("); 369f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("src: (%f,%f,%f,%f) ", 370f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fSrcRect.fLeft, fSrcRect.fTop, fSrcRect.fRight, fSrcRect.fBottom); 371f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("inset: %f", fInset); 372f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append(")"); 373f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips} 374f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif 375