X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Frenderers%2Fgradient%2Fgradient-renderer.cpp;h=f64ad61a11b6084834611848b42f19c1e557bf57;hp=9ba7369c2177d745a64a716207f39f83f7f9fed9;hb=36ac338ff7e9c299ce45818d77aa8f71c63a45aa;hpb=c560f95435d40fd3980cd5f92da65c9f28f440e7 diff --git a/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp b/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp index 9ba7369..f64ad61 100644 --- a/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ #include "gradient-renderer.h" // EXTERNAL INCLUDES +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include @@ -43,30 +45,55 @@ namespace Internal namespace { // properties: linear gradient -const char * const GRADIENT_START_POSITION_NAME("gradient-start-position"); // Property::VECTOR2 -const char * const GRADIENT_END_POSITION_NAME("gradient-end-position"); // Property::VECTOR2 +const char * const START_POSITION_NAME("startPosition"); // Property::VECTOR2 +const char * const END_POSITION_NAME("endPosition"); // Property::VECTOR2 // properties: radial gradient -const char * const GRADIENT_CENTER_NAME("gradient-center"); // Property::VECTOR2 -const char * const GRADIENT_RADIUS_NAME("gradient-radius"); // Property::FLOAT +const char * const CENTER_NAME("center"); // Property::VECTOR2 +const char * const RADIUS_NAME("radius"); // Property::FLOAT // properties: linear&radial gradient -const char * const GRADIENT_STOP_OFFSET_NAME("gradient-stop-offset"); // Property::Array FLOAT -const char * const GRADIENT_STOP_COLOR_NAME("gradient-stop-color"); // Property::Array VECTOR4 -const char * const GRADIENT_UNITS_NAME("gradient-units"); // Property::String "userSpaceOnUse | objectBoundingBox" -const char * const GRADIENT_SPREAD_METHOD_NAME("gradient-spread-method"); // Property::String "pad | reflect | repeat" +const char * const STOP_OFFSET_NAME("stopOffset"); // Property::Array FLOAT +const char * const STOP_COLOR_NAME("stopColor"); // Property::Array VECTOR4 +const char * const UNITS_NAME("units"); // Property::String "userSpaceOnUse | objectBoundingBox" +const char * const SPREAD_METHOD_NAME("spreadMethod"); // Property::String "pad | reflect | repeat" // string values -const char * const UNIT_USER_SPACE("user-space"); +const char * const UNIT_USER_SPACE("userSpace"); +const char * const UNIT_BOUNDING_BOX("objectBoundingBox"); +const char * const SPREAD_PAD("pad"); const char * const SPREAD_REFLECT("reflect"); const char * const SPREAD_REPEAT("repeat"); // uniform names const char * const UNIFORM_ALIGNMENT_MATRIX_NAME( "uAlignmentMatrix" ); -const char * const UNIFORM_TEXTULRE_NAME("sTexture"); +// default offset value +const unsigned int DEFAULT_OFFSET_MINIMUM = 0.0f; +const unsigned int DEFAULT_OFFSET_MAXIMUM = 1.0f; -const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( +RendererFactoryCache::ShaderType GetShaderType( GradientRenderer::Type type, Gradient::GradientUnits units) +{ + if( type==GradientRenderer::LINEAR ) + { + if( units == Gradient::USER_SPACE_ON_USE ) + { + return RendererFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE; + } + return RendererFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX; + } + else if( units == Gradient::USER_SPACE_ON_USE ) + { + return RendererFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE; + } + + return RendererFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX; +} + +const char* VERTEX_SHADER[] = +{ +// vertex shader for gradient units as USER_SPACE_ON_USE +DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n uniform mediump mat4 uMvpMatrix;\n uniform mediump vec3 uSize;\n @@ -81,9 +108,31 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( \n vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;\n }\n -); +), + +// vertex shader for gradient units as OBJECT_BOUNDING_BOX + DALI_COMPOSE_SHADER( + attribute mediump vec2 aPosition;\n + uniform mediump mat4 uMvpMatrix;\n + uniform mediump vec3 uSize;\n + uniform mediump mat3 uAlignmentMatrix;\n + varying mediump vec2 vTexCoord;\n + \n + void main()\n + {\n + mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n + vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;\n + \n + vertexPosition.xyz *= uSize;\n + gl_Position = uMvpMatrix * vertexPosition;\n + }\n +) +}; -const char* FRAGMENT_SHADER_LINEAR = DALI_COMPOSE_SHADER( +const char* FRAGMENT_SHADER[] = +{ +// fragment shader for linear gradient +DALI_COMPOSE_SHADER( uniform sampler2D sTexture;\n // sampler1D? uniform lowp vec4 uColor;\n varying mediump vec2 vTexCoord;\n @@ -92,9 +141,10 @@ const char* FRAGMENT_SHADER_LINEAR = DALI_COMPOSE_SHADER( {\n gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * uColor;\n }\n -); +), -const char* FRAGMENT_SHADER_RADIAL = DALI_COMPOSE_SHADER( +// fragment shader for radial gradient +DALI_COMPOSE_SHADER( uniform sampler2D sTexture;\n // sampler1D? uniform lowp vec4 uColor;\n varying mediump vec2 vTexCoord;\n @@ -103,24 +153,25 @@ const char* FRAGMENT_SHADER_RADIAL = DALI_COMPOSE_SHADER( {\n gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * uColor;\n }\n -); +) +}; -Sampler::WrapMode GetWrapMode( Gradient::SpreadMethod spread ) +Dali::WrapMode::Type GetWrapMode( Gradient::SpreadMethod spread ) { switch(spread) { case Gradient::REPEAT: { - return Sampler::REPEAT; + return Dali::WrapMode::REPEAT; } case Gradient::REFLECT: { - return Sampler::MIRRORED_REPEAT; + return Dali::WrapMode::MIRRORED_REPEAT; } case Gradient::PAD: default: { - return Sampler::CLAMP_TO_EDGE; + return Dali::WrapMode::CLAMP_TO_EDGE; } } } @@ -128,48 +179,38 @@ Sampler::WrapMode GetWrapMode( Gradient::SpreadMethod spread ) } -GradientRenderer::GradientRenderer() -:mGradientTransformIndex( Property::INVALID_INDEX ) +GradientRenderer::GradientRenderer( RendererFactoryCache& factoryCache ) +: ControlRenderer( factoryCache ), + mGradientType( LINEAR ) { + mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA; } GradientRenderer::~GradientRenderer() { } -void GradientRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ) +void GradientRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap ) { - mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY ); - if( !(mImpl->mGeometry) ) + Gradient::GradientUnits gradientUnits = Gradient::OBJECT_BOUNDING_BOX; + Property::Value* unitsValue = propertyMap.Find( UNITS_NAME ); + std::string units; + // The default unit is OBJECT_BOUNDING_BOX. + // Only need to set new units if 'user-space' + if( unitsValue && unitsValue->Get( units ) && units == UNIT_USER_SPACE ) { - mImpl->mGeometry = RendererFactoryCache::CreateQuadGeometry(); - factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry ); + gradientUnits = Gradient::USER_SPACE_ON_USE; } - Type gradientType; - if( propertyMap.Find( GRADIENT_RADIUS_NAME )) + mGradientType = LINEAR; + if( propertyMap.Find( RADIUS_NAME )) { - mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::GRADIENT_SHADER_RADIAL ); - if( !(mImpl->mShader) ) - { - mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_RADIAL ); - factoryCache.SaveShader( RendererFactoryCache::GRADIENT_SHADER_RADIAL, mImpl->mShader ); - } - gradientType = RADIAL; - } - else - { - mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::GRADIENT_SHADER_LINEAR ); - if( !(mImpl->mShader) ) - { - mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_LINEAR ); - factoryCache.SaveShader( RendererFactoryCache::GRADIENT_SHADER_LINEAR, mImpl->mShader ); - } - gradientType = LINEAR; + mGradientType = RADIAL; } - if( NewGradient(gradientType, propertyMap) ) + if( NewGradient( mGradientType, propertyMap ) ) { + mGradient->SetGradientUnits( gradientUnits ); mGradientTransform = mGradient->GetAlignmentTransform(); } else @@ -181,19 +222,6 @@ void GradientRenderer::Initialize( RendererFactoryCache& factoryCache, const Pro void GradientRenderer::SetSize( const Vector2& size ) { ControlRenderer::SetSize( size ); - - if( mGradient->GetGradientUnits() == Gradient::OBJECT_BOUNDING_BOX ) - { - // Apply scaling - Matrix3 scaling( 1.f/(size.x+Math::MACHINE_EPSILON_100), 0.f, 0.f, - 0.f, 1.f/(size.y+Math::MACHINE_EPSILON_100), 0.f, 0.5f, 0.5f, 1.f ); - Matrix3::Multiply( mGradientTransform, scaling, mGradient->GetAlignmentTransform() ); - - if( mImpl->mRenderer ) - { - (mImpl->mRenderer).SetProperty( mGradientTransformIndex, mGradientTransform ); - } - } } void GradientRenderer::SetClipRect( const Rect& clipRect ) @@ -208,25 +236,115 @@ void GradientRenderer::SetOffset( const Vector2& offset ) //ToDo: renderer applies the offset } -void GradientRenderer::SetOnStage( Actor& actor ) +void GradientRenderer::DoSetOnStage( Actor& actor ) { - ControlRenderer::SetOnStage(actor); + InitializeRenderer(); +} + +void GradientRenderer::DoCreatePropertyMap( Property::Map& map ) const +{ + map.Clear(); + map.Insert( RENDERER_TYPE, GRADIENT_RENDERER ); + + Gradient::GradientUnits units = mGradient->GetGradientUnits(); + if( units == Gradient::USER_SPACE_ON_USE ) + { + map.Insert( UNITS_NAME, UNIT_USER_SPACE ); + } + else // if( units == Gradient::OBJECT_BOUNDING_BOX ) + { + map.Insert( UNITS_NAME, UNIT_BOUNDING_BOX ); + } - mGradientTransformIndex = (mImpl->mRenderer).RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform ); + Gradient::SpreadMethod spread = mGradient->GetSpreadMethod(); + if( spread == Gradient::PAD ) + { + map.Insert( SPREAD_METHOD_NAME, SPREAD_PAD ); + } + else if( spread == Gradient::REFLECT ) + { + map.Insert( SPREAD_METHOD_NAME, SPREAD_REFLECT ); + } + else // if( units == Gradient::REPEAT ) + { + map.Insert( SPREAD_METHOD_NAME, SPREAD_REPEAT ); + } - Dali::BufferImage lookupTexture = mGradient->GenerateLookupTexture(); - Sampler sampler = Sampler::New( lookupTexture, UNIFORM_TEXTULRE_NAME ); - Sampler::WrapMode wrap = GetWrapMode( mGradient->GetSpreadMethod() ); + const Vector& stops( mGradient->GetStops() ); + Property::Array offsets; + Property::Array colors; + for( unsigned int i=0; i( mGradient.Get() ); + map.Insert( START_POSITION_NAME, gradient->GetStartPosition() ); + map.Insert( END_POSITION_NAME, gradient->GetEndPosition() ); + } + else // if( &typeid( *mGradient ) == &typeid(RadialGradient) ) + { + RadialGradient* gradient = static_cast( mGradient.Get() ); + map.Insert( CENTER_NAME, gradient->GetCenter() ); + map.Insert( RADIUS_NAME, gradient->GetRadius() ); + } +} + +void GradientRenderer::InitializeRenderer() +{ + Geometry geometry = mFactoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY ); + if( !geometry ) + { + geometry = Geometry::QUAD(); + mFactoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry ); + } + + Gradient::GradientUnits gradientUnits = mGradient->GetGradientUnits(); + RendererFactoryCache::ShaderType shaderType = GetShaderType( mGradientType, gradientUnits ); + Shader shader = mFactoryCache.GetShader( shaderType ); + if( !shader ) + { + shader = Shader::New( VERTEX_SHADER[gradientUnits], FRAGMENT_SHADER[ mGradientType ] ); + mFactoryCache.SaveShader( shaderType, shader ); + } + + //Set up the texture set + TextureSet textureSet = TextureSet::New(); + Dali::Texture lookupTexture = mGradient->GenerateLookupTexture(); + textureSet.SetTexture( 0u, lookupTexture ); + Dali::WrapMode::Type wrap = GetWrapMode( mGradient->GetSpreadMethod() ); + Sampler sampler = Sampler::New(); sampler.SetWrapMode( wrap, wrap ); - ((mImpl->mRenderer).GetMaterial()).AddSampler( sampler ); + textureSet.SetSampler( 0u, sampler ); + + mImpl->mRenderer = Renderer::New( geometry, shader ); + mImpl->mRenderer.SetTextures( textureSet ); + + mImpl->mRenderer.RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform ); } bool GradientRenderer::NewGradient(Type gradientType, const Property::Map& propertyMap) { if( gradientType==LINEAR ) { - Property::Value* startPositionValue = propertyMap.Find( GRADIENT_START_POSITION_NAME ); - Property::Value* endPositionValue = propertyMap.Find( GRADIENT_END_POSITION_NAME ); + Property::Value* startPositionValue = propertyMap.Find( START_POSITION_NAME ); + Property::Value* endPositionValue = propertyMap.Find( END_POSITION_NAME ); Vector2 startPosition; Vector2 endPosition; @@ -242,8 +360,8 @@ bool GradientRenderer::NewGradient(Type gradientType, const Property::Map& prope } else // type==RADIAL { - Property::Value* centerValue = propertyMap.Find( GRADIENT_CENTER_NAME ); - Property::Value* radiusValue = propertyMap.Find( GRADIENT_RADIUS_NAME ); + Property::Value* centerValue = propertyMap.Find( CENTER_NAME ); + Property::Value* radiusValue = propertyMap.Find( RADIUS_NAME ); Vector2 center; float radius; if( centerValue && centerValue->Get(center) @@ -258,44 +376,35 @@ bool GradientRenderer::NewGradient(Type gradientType, const Property::Map& prope } unsigned int numValidStop = 0u; - Property::Value* stopOffsetValue = propertyMap.Find( GRADIENT_STOP_OFFSET_NAME ); - Property::Value* stopColorValue = propertyMap.Find( GRADIENT_STOP_COLOR_NAME ); - if( stopOffsetValue && stopColorValue ) + Property::Value* stopOffsetValue = propertyMap.Find( STOP_OFFSET_NAME ); + Property::Value* stopColorValue = propertyMap.Find( STOP_COLOR_NAME ); + if( stopColorValue ) { - Property::Array* offsetArray = stopOffsetValue->GetArray(); + Vector offsetArray; Property::Array* colorArray = stopColorValue->GetArray(); - if( offsetArray && colorArray ) + if( colorArray ) { - unsigned int numStop = offsetArray->Count() < colorArray->Count() ? - offsetArray->Count() : colorArray->Count(); - float offset; + GetStopOffsets( stopOffsetValue, offsetArray ); + unsigned int numStop = offsetArray.Count() < colorArray->Count() ? + offsetArray.Count() : colorArray->Count(); Vector4 color; for( unsigned int i=0; iGetElementAt(i)).Get(offset) - && (colorArray->GetElementAt(i)).Get(color) ) + if( (colorArray->GetElementAt(i)).Get(color) ) { - mGradient->AddStop( offset, color); + mGradient->AddStop( offsetArray[i], Vector4(color.r*color.a, color.g*color.a, color.b*color.a, color.a)); numValidStop++; } } } } + if( numValidStop < 1u ) // no valid stop { return false; } - Property::Value* unitsValue = propertyMap.Find( GRADIENT_UNITS_NAME ); - std::string units; - // The default unit is OBJECT_BOUNDING_BOX. - // Only need to set new units if 'user-space' - if( unitsValue && unitsValue->Get( units ) && units == UNIT_USER_SPACE ) - { - mGradient->SetGradientUnits( Gradient::USER_SPACE_ON_USE ); - } - - Property::Value* spread = propertyMap.Find( GRADIENT_SPREAD_METHOD_NAME ); + Property::Value* spread = propertyMap.Find( SPREAD_METHOD_NAME ); std::string stringValue ; // The default spread method is PAD. // Only need to set new spread if 'reflect' or 'repeat" @@ -314,6 +423,73 @@ bool GradientRenderer::NewGradient(Type gradientType, const Property::Map& prope return true; } +void GradientRenderer::GetStopOffsets(const Property::Value* value, Vector& stopOffsets) +{ + + if ( value ) // Only check valve type if a valid Property has been passed in + { + switch ( value->GetType() ) + { + case Property::VECTOR2: + { + Vector2 offset2; + value->Get( offset2 ); + stopOffsets.PushBack( offset2.x ); + stopOffsets.PushBack( offset2.y ); + break; + } + case Property::VECTOR3: + { + Vector3 offset3; + value->Get( offset3 ); + stopOffsets.PushBack( offset3.x ); + stopOffsets.PushBack( offset3.y ); + stopOffsets.PushBack( offset3.z ); + break; + } + case Property::VECTOR4: + { + Vector4 offset4; + value->Get( offset4 ); + stopOffsets.PushBack( offset4.x ); + stopOffsets.PushBack( offset4.y ); + stopOffsets.PushBack( offset4.z ); + stopOffsets.PushBack( offset4.w ); + break; + } + case Property::ARRAY: + { + Property::Array* offsetArray = value->GetArray(); + if( offsetArray ) + { + unsigned int numStop = offsetArray->Count(); + float offset; + for( unsigned int i=0; iGetElementAt(i).Get(offset) ) + { + stopOffsets.PushBack( offset ); + } + } + } + break; + } + default: + { + DALI_LOG_WARNING("GetStopOffsets passed unsupported Property Map\n"); + // Unsupported Type + } + } + } + + if ( stopOffsets.Empty() ) + { + // Set default offset if none set by Property system, need a minimum and maximum + stopOffsets.PushBack( DEFAULT_OFFSET_MINIMUM ); + stopOffsets.PushBack( DEFAULT_OFFSET_MAXIMUM ); + } +} + } // namespace Internal } // namespace Toolkit