SkMagnifierImageFilter.cpp revision d698f77c13d97c61109b861eac4d25b14a5de935
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" 1182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "SkFlattenableBuffers.h" 1282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include <algorithm> 1482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 1603245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#if SK_SUPPORT_GPU 1782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "effects/GrSingleTextureEffect.h" 18d698f77c13d97c61109b861eac4d25b14a5de935bsalomon@google.com#include "gl/GrGLEffect.h" 1982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "gl/GrGLSL.h" 2082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "gl/GrGLTexture.h" 2182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "GrProgramStageFactory.h" 2282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comclass GrGLMagnifierEffect; 2482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comclass GrMagnifierEffect : public GrSingleTextureEffect { 2682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.compublic: 2882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrMagnifierEffect(GrTexture* texture, 2982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float xOffset, 3082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float yOffset, 3182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float xZoom, 3282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float yZoom, 3382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float xInset, 3482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float yInset) 3582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com : GrSingleTextureEffect(texture) 3682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fXOffset(xOffset) 3782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fYOffset(yOffset) 3882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fXZoom(xZoom) 3982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fYZoom(yZoom) 4082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fXInset(xInset) 4182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fYInset(yInset) {} 4282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 4382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com virtual ~GrMagnifierEffect() {}; 4482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 4582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com static const char* Name() { return "Magnifier"; } 4682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 4782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE; 48a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com virtual bool isEqual(const GrEffect&) const SK_OVERRIDE; 4982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 5082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float x_offset() const { return fXOffset; } 5182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float y_offset() const { return fYOffset; } 5282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float x_zoom() const { return fXZoom; } 5382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float y_zoom() const { return fYZoom; } 5482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float x_inset() const { return fXInset; } 5582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float y_inset() const { return fYInset; } 5682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 5782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com typedef GrGLMagnifierEffect GLProgramStage; 5882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 5982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comprivate: 60f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.com GR_DECLARE_EFFECT_TEST; 6182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 6282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fXOffset; 6382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fYOffset; 6482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fXZoom; 6582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fYZoom; 6682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fXInset; 6782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fYInset; 6882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 6982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com typedef GrSingleTextureEffect INHERITED; 7082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com}; 7182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 7282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com// For brevity 7382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comtypedef GrGLUniformManager::UniformHandle UniformHandle; 7482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 75374e75956e7a56bbbd2da5509f9c4117512515d2bsalomon@google.comclass GrGLMagnifierEffect : public GrGLLegacyProgramStage { 7682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.compublic: 7782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrGLMagnifierEffect(const GrProgramStageFactory& factory, 78021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com const GrEffect& effect); 7982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 8082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com virtual void setupVariables(GrGLShaderBuilder* state) SK_OVERRIDE; 8182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com virtual void emitVS(GrGLShaderBuilder* state, 8282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const char* vertexCoords) SK_OVERRIDE; 8382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com virtual void emitFS(GrGLShaderBuilder* state, 8482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const char* outputColor, 8582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const char* inputColor, 86f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com const TextureSamplerArray&) SK_OVERRIDE; 8782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 8882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com virtual void setData(const GrGLUniformManager& uman, 89a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com const GrEffect& data) SK_OVERRIDE; 9082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 91a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com static inline StageKey GenKey(const GrEffect&, const GrGLCaps&); 9282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 9382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comprivate: 9482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 9582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com UniformHandle fOffsetVar; 9682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com UniformHandle fZoomVar; 9782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com UniformHandle fInsetVar; 9882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 99374e75956e7a56bbbd2da5509f9c4117512515d2bsalomon@google.com typedef GrGLLegacyProgramStage INHERITED; 10082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com}; 10182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 10282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comGrGLMagnifierEffect::GrGLMagnifierEffect(const GrProgramStageFactory& factory, 103021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com const GrEffect& effect) 104374e75956e7a56bbbd2da5509f9c4117512515d2bsalomon@google.com : INHERITED(factory) 10582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fOffsetVar(GrGLUniformManager::kInvalidUniformHandle) 10682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fZoomVar(GrGLUniformManager::kInvalidUniformHandle) 10782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com , fInsetVar(GrGLUniformManager::kInvalidUniformHandle) { 10882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 10982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 11082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comvoid GrGLMagnifierEffect::setupVariables(GrGLShaderBuilder* state) { 11182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com fOffsetVar = state->addUniform( 11282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrGLShaderBuilder::kFragment_ShaderType | 11382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrGLShaderBuilder::kVertex_ShaderType, 11482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com kVec2f_GrSLType, "uOffset"); 11582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com fZoomVar = state->addUniform( 11682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrGLShaderBuilder::kFragment_ShaderType | 11782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrGLShaderBuilder::kVertex_ShaderType, 11882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com kVec2f_GrSLType, "uZoom"); 11982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com fInsetVar = state->addUniform( 12082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrGLShaderBuilder::kFragment_ShaderType | 12182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrGLShaderBuilder::kVertex_ShaderType, 12282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com kVec2f_GrSLType, "uInset"); 12382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 12482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 12582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comvoid GrGLMagnifierEffect::emitVS(GrGLShaderBuilder* state, 12682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const char* vertexCoords) { 12782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 12882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 12982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comvoid GrGLMagnifierEffect::emitFS(GrGLShaderBuilder* state, 13082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const char* outputColor, 13182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const char* inputColor, 132f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com const TextureSamplerArray& samplers) { 13382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkString* code = &state->fFSCode; 13482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 13534bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com code->appendf("\t\tvec2 coord = %s;\n", state->defaultTexCoordsName()); 13682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\tvec2 zoom_coord = %s + %s / %s;\n", 13782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com state->getUniformCStr(fOffsetVar), 13834bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com state->defaultTexCoordsName(), 13982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com state->getUniformCStr(fZoomVar)); 14082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 14182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\tvec2 delta = min(coord, vec2(1.0, 1.0) - coord);\n"); 14282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 14382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf( 14482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com "\t\tdelta = delta / %s;\n", state->getUniformCStr(fInsetVar)); 14582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 14682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\tfloat weight = 0.0;\n"); 14782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); 14882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); 14982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\t\tfloat dist = length(delta);\n"); 15082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\t\tdist = max(2.0 - dist, 0.0);\n"); 15182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\t\tweight = min(dist * dist, 1.0);\n"); 15282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\t} else {\n"); 15382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\t\tvec2 delta_squared = delta * delta;\n"); 15482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf( 15582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com "\t\t\tweight = min(min(delta_squared.s, delta_squared.y), 1.0);\n"); 15682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\t}\n"); 15782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 15882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n"); 15982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\tvec4 output_color = "); 160f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com state->appendTextureLookup(code, samplers[0], "mix_coord"); 161868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com code->append(";\n"); 16282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 16382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com code->appendf("\t\t%s = output_color;", outputColor); 164868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com GrGLSLMulVarBy4f(code, 2, outputColor, inputColor); 16582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 16682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 16782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comvoid GrGLMagnifierEffect::setData(const GrGLUniformManager& uman, 168a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com const GrEffect& data) { 16982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const GrMagnifierEffect& zoom = 17082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com static_cast<const GrMagnifierEffect&>(data); 17182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 17282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com uman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset()); 17382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com uman.set2f(fZoomVar, zoom.x_zoom(), zoom.y_zoom()); 17482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com uman.set2f(fInsetVar, zoom.x_inset(), zoom.y_inset()); 17582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 17682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 177d698f77c13d97c61109b861eac4d25b14a5de935bsalomon@google.comGrGLEffect::StageKey GrGLMagnifierEffect::GenKey(const GrEffect& s, 17882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const GrGLCaps& caps) { 17982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return 0; 18082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 18182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 18282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com///////////////////////////////////////////////////////////////////// 18382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 184f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.comGR_DEFINE_EFFECT_TEST(GrMagnifierEffect); 18582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 186a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.comGrEffect* GrMagnifierEffect::TestCreate(SkRandom* random, 187a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com GrContext* context, 188a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com GrTexture** textures) { 18982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxWidth = 200; 19082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxHeight = 200; 19182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxInset = 20; 1925d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com uint32_t width = random->nextULessThan(kMaxWidth); 1935d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com uint32_t height = random->nextULessThan(kMaxHeight); 1945d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com uint32_t x = random->nextULessThan(kMaxWidth - width); 1955d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com uint32_t y = random->nextULessThan(kMaxHeight - height); 1965d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inset = SkIntToScalar(random->nextULessThan(kMaxInset)); 19782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 19882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkAutoTUnref<SkImageFilter> filter( 19982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com new SkMagnifierImageFilter( 2005d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y), 2015d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkIntToScalar(width), SkIntToScalar(height)), 20282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com inset)); 20382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com GrSamplerState sampler; 204021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com GrEffect* effect; 205021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com filter->asNewEffect(&effect, textures[0]); 206021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com GrAssert(NULL != effect); 207021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com return effect; 20882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 20982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 21082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 21182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 21282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comconst GrProgramStageFactory& GrMagnifierEffect::getFactory() const { 21382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return GrTProgramStageFactory<GrMagnifierEffect>::getInstance(); 21482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 21582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 216a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.combool GrMagnifierEffect::isEqual(const GrEffect& sBase) const { 21782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const GrMagnifierEffect& s = 21882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com static_cast<const GrMagnifierEffect&>(sBase); 21982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return (this->fXOffset == s.fXOffset && 22082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->fYOffset == s.fYOffset && 22182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->fXZoom == s.fXZoom && 22282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->fYZoom == s.fYZoom && 22382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->fXInset == s.fXInset && 22482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->fYInset == s.fYInset); 22582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 22682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 22703245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#endif 22803245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com 22982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 23082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comSkMagnifierImageFilter::SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer) 23182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com : INHERITED(buffer) { 23282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float x = buffer.readScalar(); 23382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float y = buffer.readScalar(); 23482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float width = buffer.readScalar(); 23582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float height = buffer.readScalar(); 23682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com fSrcRect = SkRect::MakeXYWH(x, y, width, height); 23782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com fInset = buffer.readScalar(); 23882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 23982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2409f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org// FIXME: implement single-input semantics 24182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comSkMagnifierImageFilter::SkMagnifierImageFilter(SkRect srcRect, SkScalar inset) 2429f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org : INHERITED(0), fSrcRect(srcRect), fInset(inset) { 24382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0); 24482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 24582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 246021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.combool SkMagnifierImageFilter::asNewEffect(GrEffect** effect, 2478ea78d83dc4e8243c16eedf8100a3987c54123fabsalomon@google.com GrTexture* texture) const { 24803245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#if SK_SUPPORT_GPU 249021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com if (effect) { 250021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com *effect = SkNEW_ARGS(GrMagnifierEffect, (texture, 251021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com fSrcRect.x() / texture->width(), 252021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com fSrcRect.y() / texture->height(), 253021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com texture->width() / fSrcRect.width(), 254021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com texture->height() / fSrcRect.height(), 255021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com fInset / texture->width(), 256021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com fInset / texture->height())); 25782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 25882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return true; 25903245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#else 26003245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com return false; 26103245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#endif 26282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 26382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 26482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comvoid SkMagnifierImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 26582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->INHERITED::flatten(buffer); 26682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com buffer.writeScalar(fSrcRect.x()); 26782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com buffer.writeScalar(fSrcRect.y()); 26882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com buffer.writeScalar(fSrcRect.width()); 26982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com buffer.writeScalar(fSrcRect.height()); 27082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com buffer.writeScalar(fInset); 27182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 27282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 27382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.combool SkMagnifierImageFilter::onFilterImage(Proxy*, const SkBitmap& src, 27482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const SkMatrix&, SkBitmap* dst, 27582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkIPoint* offset) { 27682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(src.config() == SkBitmap::kARGB_8888_Config); 27782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(fSrcRect.width() < src.width()); 27882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(fSrcRect.height() < src.height()); 27982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 28082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com if (src.config() != SkBitmap::kARGB_8888_Config) { 28182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return false; 28282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 28382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 28482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkAutoLockPixels alp(src); 28582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(src.getPixels()); 28682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) { 28782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return false; 28882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 28982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2905d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_inset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; 29182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2925d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_x_zoom = fSrcRect.width() / src.width(); 2935d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_y_zoom = fSrcRect.height() / src.height(); 29482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 29582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com dst->setConfig(src.config(), src.width(), src.height()); 29682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com dst->allocPixels(); 29782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkColor* sptr = src.getAddr32(0, 0); 29882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkColor* dptr = dst->getAddr32(0, 0); 29982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com int width = src.width(), height = src.height(); 30082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com for (int y = 0; y < height; ++y) { 30182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com for (int x = 0; x < width; ++x) { 3025d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar x_dist = SkMin32(x, width - x - 1) * inv_inset; 3035d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar y_dist = SkMin32(y, height - y - 1) * inv_inset; 3045d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar weight = 0; 3055d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com 3065d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com static const SkScalar kScalar2 = SkScalar(2); 30782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 30882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com // To create a smooth curve at the corners, we need to work on 30982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com // a square twice the size of the inset. 3105d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com if (x_dist < kScalar2 && y_dist < kScalar2) { 3115d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com x_dist = kScalar2 - x_dist; 3125d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com y_dist = kScalar2 - y_dist; 3135d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com 3145d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar dist = SkScalarSqrt(SkScalarSquare(x_dist) + 3155d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalarSquare(y_dist)); 3165d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com dist = SkMaxScalar(kScalar2 - dist, 0); 3175d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com weight = SkMinScalar(SkScalarSquare(dist), SK_Scalar1); 31882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } else { 3195d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar sqDist = SkMinScalar(SkScalarSquare(x_dist), 3205d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalarSquare(y_dist)); 3215d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com weight = SkMinScalar(sqDist, SK_Scalar1); 32282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 32382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 3245d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar x_interp = SkScalarMul(weight, (fSrcRect.x() + x * inv_x_zoom)) + 3255d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com (SK_Scalar1 - weight) * x; 3265d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar y_interp = SkScalarMul(weight, (fSrcRect.y() + y * inv_y_zoom)) + 3275d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com (SK_Scalar1 - weight) * y; 32882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 3295d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com int x_val = SkMin32(SkScalarFloorToInt(x_interp), width - 1); 3305d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com int y_val = SkMin32(SkScalarFloorToInt(y_interp), height - 1); 33182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 33282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com *dptr = sptr[y_val * width + x_val]; 33382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com dptr++; 33482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 33582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 33682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return true; 33782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 338