X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fgradient%2Fgradient-visual.cpp;h=f3028c4651c20194ecef91c26b1218065d3fc858;hp=7f58d66f04dadb95efb5d24199d217260e250a0c;hb=1d71a8f7d7abd7729aa645ad062e530958097214;hpb=d6f1c901d74aef4e66ffb6565bb61de952a090a3 diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp index 7f58d66..f3028c4 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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,183 +19,84 @@ #include "gradient-visual.h" // EXTERNAL INCLUDES -#include +#include +#include +#include #include #include -#include #include -#include -#include +#include // INTERNAL INCLUDES -#include -#include -#include -#include -#include +#include #include #include #include +#include +#include +#include +#include +#include namespace Dali { - namespace Toolkit { - namespace Internal { - namespace { -// properties: linear gradient -const char * const START_POSITION_NAME("startPosition"); // Property::VECTOR2 -const char * const END_POSITION_NAME("endPosition"); // Property::VECTOR2 - -// properties: radial gradient -const char * const CENTER_NAME("center"); // Property::VECTOR2 -const char * const RADIUS_NAME("radius"); // Property::FLOAT - -// properties: linear&radial gradient -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" - -DALI_ENUM_TO_STRING_TABLE_BEGIN( UNITS ) -DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::Units, OBJECT_BOUNDING_BOX ) -DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::Units, USER_SPACE ) -DALI_ENUM_TO_STRING_TABLE_END( UNITS ) - -DALI_ENUM_TO_STRING_TABLE_BEGIN( SPREAD_METHOD ) -DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::SpreadMethod, PAD ) -DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::SpreadMethod, REFLECT ) -DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::SpreadMethod, REPEAT ) -DALI_ENUM_TO_STRING_TABLE_END( SPREAD_METHOD ) +const int CUSTOM_PROPERTY_COUNT(11); // 5 transform properties + alignment + corner/border + +DALI_ENUM_TO_STRING_TABLE_BEGIN(UNITS) + DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::Units, OBJECT_BOUNDING_BOX) + DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::Units, USER_SPACE) +DALI_ENUM_TO_STRING_TABLE_END(UNITS) + +DALI_ENUM_TO_STRING_TABLE_BEGIN(SPREAD_METHOD) + DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::SpreadMethod, PAD) + DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::SpreadMethod, REFLECT) + DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::SpreadMethod, REPEAT) +DALI_ENUM_TO_STRING_TABLE_END(SPREAD_METHOD) // uniform names -const char * const UNIFORM_ALIGNMENT_MATRIX_NAME( "uAlignmentMatrix" ); +const char* const UNIFORM_ALIGNMENT_MATRIX_NAME("uAlignmentMatrix"); // default offset value const unsigned int DEFAULT_OFFSET_MINIMUM = 0.0f; const unsigned int DEFAULT_OFFSET_MAXIMUM = 1.0f; -VisualFactoryCache::ShaderType GetShaderType( GradientVisual::Type type, Toolkit::GradientVisual::Units::Type units ) -{ - if( type == GradientVisual::LINEAR ) - { - if( units == Toolkit::GradientVisual::Units::USER_SPACE ) - { - return VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE; - } - return VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX; - } - else if( units == Toolkit::GradientVisual::Units::USER_SPACE ) +VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[16] = { - return VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE; - } - - return VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX; -} - -const char* VERTEX_SHADER[] = -{ -// 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 - - //Visual size and offset - uniform mediump vec2 offset;\n - uniform mediump vec2 size;\n - uniform mediump vec4 offsetSizeMode;\n - uniform mediump vec2 origin;\n - uniform mediump vec2 anchorPoint;\n - - vec4 ComputeVertexPosition()\n - {\n - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n - vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n - return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n - }\n - - void main()\n - {\n - mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n - vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;\n - \n - gl_Position = uMvpMatrix * ComputeVertexPosition();\n - }\n -), - -// vertex shader for gradient units as USER_SPACE -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 - - //Visual size and offset - uniform mediump vec2 offset;\n - uniform mediump vec2 size;\n - uniform mediump vec4 offsetSizeMode;\n - uniform mediump vec2 origin;\n - uniform mediump vec2 anchorPoint;\n - - vec4 ComputeVertexPosition()\n - {\n - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n - vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n - return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n - }\n - - void main()\n - {\n - mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n - vertexPosition.xyz *= uSize;\n - gl_Position = uMvpMatrix * ComputeVertexPosition();\n - \n - vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;\n - }\n -) + VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_BORDERLINE, + VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_BORDERLINE, }; -const char* FRAGMENT_SHADER[] = +// enum of required list when we select shader +enum GradientVisualRequireFlag { -// fragment shader for linear gradient -DALI_COMPOSE_SHADER( - uniform sampler2D sTexture;\n // sampler1D? - uniform lowp vec4 uColor;\n - uniform lowp vec4 mixColor;\n - varying mediump vec2 vTexCoord;\n - \n - void main()\n - {\n - gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * vec4(mixColor.rgb*mixColor.a, mixColor.a) * uColor;\n - }\n -), - -// fragment shader for radial gradient -DALI_COMPOSE_SHADER( - uniform sampler2D sTexture;\n // sampler1D? - uniform lowp vec4 uColor;\n - uniform lowp vec4 mixColor;\n - varying mediump vec2 vTexCoord;\n - \n - void main()\n - {\n - gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * vec4(mixColor.rgb*mixColor.a, mixColor.a) * uColor;\n - }\n -) + DEFAULT = 0, + ROUNDED_CORNER = 1 << 0, + BORDERLINE = 1 << 1, + USER_SPACE = 1 << 2, + RADIAL = 1 << 3, }; -Dali::WrapMode::Type GetWrapMode( Toolkit::GradientVisual::SpreadMethod::Type spread ) +Dali::WrapMode::Type GetWrapMode(Toolkit::GradientVisual::SpreadMethod::Type spread) { switch(spread) { @@ -217,17 +118,18 @@ Dali::WrapMode::Type GetWrapMode( Toolkit::GradientVisual::SpreadMethod::Type sp } // unnamed namespace -GradientVisualPtr GradientVisual::New( VisualFactoryCache& factoryCache, const Property::Map& properties ) +GradientVisualPtr GradientVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties) { - GradientVisualPtr gradientVisualPtr( new GradientVisual( factoryCache ) ); - gradientVisualPtr->SetProperties( properties ); + GradientVisualPtr gradientVisualPtr(new GradientVisual(factoryCache)); + gradientVisualPtr->SetProperties(properties); + gradientVisualPtr->Initialize(); return gradientVisualPtr; } -GradientVisual::GradientVisual( VisualFactoryCache& factoryCache ) -: Visual::Base( factoryCache ), - mGradientType( LINEAR ), - mIsOpaque( true ) +GradientVisual::GradientVisual(VisualFactoryCache& factoryCache) +: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::GRADIENT), + mGradientType(LINEAR), + mIsOpaque(true) { mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA; } @@ -236,157 +138,163 @@ GradientVisual::~GradientVisual() { } -void GradientVisual::DoSetProperties( const Property::Map& propertyMap ) +void GradientVisual::DoSetProperties(const Property::Map& propertyMap) { Toolkit::GradientVisual::Units::Type gradientUnits = Toolkit::GradientVisual::Units::OBJECT_BOUNDING_BOX; - Property::Value* unitsValue = propertyMap.Find( Toolkit::GradientVisual::Property::UNITS, UNITS_NAME ); - if( unitsValue ) + Property::Value* unitsValue = propertyMap.Find(Toolkit::GradientVisual::Property::UNITS, UNITS_NAME); + if(unitsValue) { - Scripting::GetEnumerationProperty( *unitsValue, UNITS_TABLE, UNITS_TABLE_COUNT, gradientUnits ); + Scripting::GetEnumerationProperty(*unitsValue, UNITS_TABLE, UNITS_TABLE_COUNT, gradientUnits); } - mGradientType = LINEAR; - if( propertyMap.Find( Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME ) ) + mGradientType = Type::LINEAR; + if(propertyMap.Find(Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME)) { - mGradientType = RADIAL; + mGradientType = Type::RADIAL; } - if( NewGradient( mGradientType, propertyMap ) ) + if(NewGradient(mGradientType, propertyMap)) { - mGradient->SetGradientUnits( gradientUnits ); + mGradient->SetGradientUnits(gradientUnits); mGradientTransform = mGradient->GetAlignmentTransform(); } else { - DALI_LOG_ERROR( "Fail to provide valid properties to create a GradientVisual object\n" ); + DALI_LOG_ERROR("Fail to provide valid properties to create a GradientVisual object\n"); } } void GradientVisual::OnSetTransform() { - if( mImpl->mRenderer ) + if(mImpl->mRenderer) { - mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); + mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT); } } -void GradientVisual::DoSetOnStage( Actor& actor ) +void GradientVisual::DoSetOnScene(Actor& actor) { - InitializeRenderer(); + actor.AddRenderer(mImpl->mRenderer); + + // Gradient Visual generated and ready to display + ResourceReady(Toolkit::Visual::ResourceStatus::READY); +} - actor.AddRenderer( mImpl->mRenderer ); +void GradientVisual::UpdateShader() +{ + if(mImpl->mRenderer) + { + Shader shader = GenerateShader(); + mImpl->mRenderer.SetShader(shader); + } } -void GradientVisual::DoCreatePropertyMap( Property::Map& map ) const +void GradientVisual::DoCreatePropertyMap(Property::Map& map) const { map.Clear(); - map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::Visual::GRADIENT ); - map.Insert( Toolkit::GradientVisual::Property::UNITS, mGradient->GetGradientUnits() ); - map.Insert( Toolkit::GradientVisual::Property::SPREAD_METHOD, mGradient->GetSpreadMethod() ); - - const Vector& stops( mGradient->GetStops() ); - Property::Array offsets; - Property::Array colors; - for( unsigned int i=0; iGetGradientUnits()); + map.Insert(Toolkit::GradientVisual::Property::SPREAD_METHOD, mGradient->GetSpreadMethod()); + + const Vector& stops(mGradient->GetStops()); + Property::Array offsets; + Property::Array colors; + for(unsigned int i = 0; i < stops.Count(); i++) { - offsets.PushBack( stops[i].mOffset ); - if( EqualsZero(stops[i].mStopColor.a) ) + offsets.PushBack(stops[i].mOffset); + if(EqualsZero(stops[i].mStopColor.a)) { - colors.PushBack( Vector4::ZERO ); + colors.PushBack(Vector4::ZERO); } else { - colors.PushBack( Vector4( stops[i].mStopColor.r / stops[i].mStopColor.a, - stops[i].mStopColor.g / stops[i].mStopColor.a, - stops[i].mStopColor.b / stops[i].mStopColor.a, - stops[i].mStopColor.a)); + colors.PushBack(Vector4(stops[i].mStopColor.r / stops[i].mStopColor.a, + stops[i].mStopColor.g / stops[i].mStopColor.a, + stops[i].mStopColor.b / stops[i].mStopColor.a, + stops[i].mStopColor.a)); } } - map.Insert( Toolkit::GradientVisual::Property::STOP_OFFSET, offsets ); - map.Insert( Toolkit::GradientVisual::Property::STOP_COLOR, colors ); + map.Insert(Toolkit::GradientVisual::Property::STOP_OFFSET, offsets); + map.Insert(Toolkit::GradientVisual::Property::STOP_COLOR, colors); - if( &typeid( *mGradient ) == &typeid(LinearGradient) ) + if(&typeid(*mGradient) == &typeid(LinearGradient)) { - LinearGradient* gradient = static_cast( mGradient.Get() ); - map.Insert( Toolkit::GradientVisual::Property::START_POSITION, gradient->GetStartPosition() ); - map.Insert( Toolkit::GradientVisual::Property::END_POSITION, gradient->GetEndPosition() ); + LinearGradient* gradient = static_cast(mGradient.Get()); + map.Insert(Toolkit::GradientVisual::Property::START_POSITION, gradient->GetStartPosition()); + map.Insert(Toolkit::GradientVisual::Property::END_POSITION, gradient->GetEndPosition()); } else // if( &typeid( *mGradient ) == &typeid(RadialGradient) ) { - RadialGradient* gradient = static_cast( mGradient.Get() ); - map.Insert( Toolkit::GradientVisual::Property::CENTER, gradient->GetCenter() ); - map.Insert( Toolkit::GradientVisual::Property::RADIUS, gradient->GetRadius() ); + RadialGradient* gradient = static_cast(mGradient.Get()); + map.Insert(Toolkit::GradientVisual::Property::CENTER, gradient->GetCenter()); + map.Insert(Toolkit::GradientVisual::Property::RADIUS, gradient->GetRadius()); } } -void GradientVisual::InitializeRenderer() +void GradientVisual::DoCreateInstancePropertyMap(Property::Map& map) const { - Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); + // Do nothing +} - Toolkit::GradientVisual::Units::Type gradientUnits = mGradient->GetGradientUnits(); - VisualFactoryCache::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 ); - } +void GradientVisual::OnInitialize() +{ + Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); + Shader shader = GenerateShader(); //Set up the texture set - TextureSet textureSet = TextureSet::New(); + 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 ); - textureSet.SetSampler( 0u, sampler ); - - mImpl->mRenderer = Renderer::New( geometry, shader ); - mImpl->mRenderer.SetTextures( textureSet ); - - // If opaque then no need to have blending - if( mIsOpaque ) + textureSet.SetTexture(0u, lookupTexture); + Dali::WrapMode::Type wrap = GetWrapMode(mGradient->GetSpreadMethod()); + Sampler sampler = Sampler::New(); + sampler.SetWrapMode(wrap, wrap); + textureSet.SetSampler(0u, sampler); + + mImpl->mRenderer = Renderer::New(geometry, shader); + mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT); + mImpl->mRenderer.SetTextures(textureSet); + + // If opaque and then no need to have blending + if(mIsOpaque) { - mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::OFF ); + mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::OFF); } - mImpl->mRenderer.RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform ); + mImpl->mRenderer.RegisterUniqueProperty(UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform); //Register transform properties - mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); + mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT); } bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propertyMap) { - if( gradientType == LINEAR ) + if(gradientType == Type::LINEAR) { - Property::Value* startPositionValue = propertyMap.Find( Toolkit::GradientVisual::Property::START_POSITION, START_POSITION_NAME ); - Property::Value* endPositionValue = propertyMap.Find( Toolkit::GradientVisual::Property::END_POSITION, END_POSITION_NAME ); - Vector2 startPosition; - Vector2 endPosition; + Property::Value* startPositionValue = propertyMap.Find(Toolkit::GradientVisual::Property::START_POSITION, START_POSITION_NAME); + Property::Value* endPositionValue = propertyMap.Find(Toolkit::GradientVisual::Property::END_POSITION, END_POSITION_NAME); + Vector2 startPosition; + Vector2 endPosition; - if( startPositionValue && startPositionValue->Get(startPosition) - && endPositionValue && endPositionValue->Get( endPosition ) ) + if(startPositionValue && startPositionValue->Get(startPosition) && endPositionValue && endPositionValue->Get(endPosition)) { - mGradient = new LinearGradient( startPosition, endPosition ); + mGradient = new LinearGradient(startPosition, endPosition); } else { return false; } } - else // type==RADIAL + else // type==Type::RADIAL { - Property::Value* centerValue = propertyMap.Find( Toolkit::GradientVisual::Property::CENTER, CENTER_NAME ); - Property::Value* radiusValue = propertyMap.Find( Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME ); - Vector2 center; - float radius; - if( centerValue && centerValue->Get(center) - && radiusValue && radiusValue->Get(radius) ) + Property::Value* centerValue = propertyMap.Find(Toolkit::GradientVisual::Property::CENTER, CENTER_NAME); + Property::Value* radiusValue = propertyMap.Find(Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME); + Vector2 center; + float radius; + if(centerValue && centerValue->Get(center) && radiusValue && radiusValue->Get(radius)) { - mGradient = new RadialGradient( center, radius ); + mGradient = new RadialGradient(center, radius); } else { @@ -394,26 +302,25 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert } } - unsigned int numValidStop = 0u; - Property::Value* stopOffsetValue = propertyMap.Find( Toolkit::GradientVisual::Property::STOP_OFFSET, STOP_OFFSET_NAME ); - Property::Value* stopColorValue = propertyMap.Find( Toolkit::GradientVisual::Property::STOP_COLOR, STOP_COLOR_NAME ); - if( stopColorValue ) + unsigned int numValidStop = 0u; + Property::Value* stopOffsetValue = propertyMap.Find(Toolkit::GradientVisual::Property::STOP_OFFSET, STOP_OFFSET_NAME); + Property::Value* stopColorValue = propertyMap.Find(Toolkit::GradientVisual::Property::STOP_COLOR, STOP_COLOR_NAME); + if(stopColorValue) { - Vector offsetArray; + Vector offsetArray; Property::Array* colorArray = stopColorValue->GetArray(); - if( colorArray ) + if(colorArray) { - GetStopOffsets( stopOffsetValue, offsetArray ); - unsigned int numStop = offsetArray.Count() < colorArray->Count() ? - offsetArray.Count() : colorArray->Count(); - Vector4 color; - for( unsigned int i=0; iCount() ? offsetArray.Count() : colorArray->Count(); + Vector4 color; + for(unsigned int i = 0; i < numStop; i++) { - if( (colorArray->GetElementAt(i)).Get(color) ) + if((colorArray->GetElementAt(i)).Get(color)) { - mGradient->AddStop( offsetArray[i], Vector4(color.r*color.a, color.g*color.a, color.b*color.a, color.a)); + mGradient->AddStop(offsetArray[i], Vector4(color.r * color.a, color.g * color.a, color.b * color.a, color.a)); numValidStop++; - if( ! Equals( color.a, 1.0f, Math::MACHINE_EPSILON_1 ) ) + if(!Equals(color.a, 1.0f, Math::MACHINE_EPSILON_1)) { mIsOpaque = false; } @@ -422,71 +329,129 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert } } - if( numValidStop < 1u ) // no valid stop + if(numValidStop < 1u) // no valid stop { return false; } - Property::Value* spread = propertyMap.Find( Toolkit::GradientVisual::Property::SPREAD_METHOD, SPREAD_METHOD_NAME ); + Property::Value* spread = propertyMap.Find(Toolkit::GradientVisual::Property::SPREAD_METHOD, SPREAD_METHOD_NAME); // The default spread method is PAD. Only need to set new spread if it's anything else. - if( spread ) + if(spread) { Toolkit::GradientVisual::SpreadMethod::Type spreadMethod = Toolkit::GradientVisual::SpreadMethod::PAD; - if( Scripting::GetEnumerationProperty( *spread, SPREAD_METHOD_TABLE, SPREAD_METHOD_TABLE_COUNT, spreadMethod ) ) + if(Scripting::GetEnumerationProperty(*spread, SPREAD_METHOD_TABLE, SPREAD_METHOD_TABLE_COUNT, spreadMethod)) { - mGradient->SetSpreadMethod( spreadMethod ); + mGradient->SetSpreadMethod(spreadMethod); } } return true; } -void GradientVisual::GetStopOffsets(const Property::Value* value, Vector& stopOffsets) +Shader GradientVisual::GenerateShader() const { + bool userspaceUnit = (mGradient->GetGradientUnits() == Toolkit::GradientVisual::Units::USER_SPACE); + bool roundedCorner = IsRoundedCornerRequired(); + bool borderline = IsBorderlineRequired(); + bool radialGradient = (mGradientType == Type::RADIAL); + + int shaderTypeFlag = GradientVisualRequireFlag::DEFAULT; + if(roundedCorner) + { + shaderTypeFlag |= GradientVisualRequireFlag::ROUNDED_CORNER; + } + if(borderline) + { + shaderTypeFlag |= GradientVisualRequireFlag::BORDERLINE; + } + if(userspaceUnit) + { + shaderTypeFlag |= GradientVisualRequireFlag::USER_SPACE; + } + if(radialGradient) + { + shaderTypeFlag |= GradientVisualRequireFlag::RADIAL; + } + + VisualFactoryCache::ShaderType shaderType = SHADER_TYPE_TABLE[shaderTypeFlag]; + Shader shader = mFactoryCache.GetShader(shaderType); + if(!shader) + { + std::string vertexShaderPrefixList; + std::string fragmentShaderPrefixList; + + if(roundedCorner) + { + vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n"; + } + if(borderline) + { + vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n"; + fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n"; + } + if(radialGradient) + { + fragmentShaderPrefixList += "#define RADIAL 1\n"; + } + if(userspaceUnit) + { + vertexShaderPrefixList += "#define USER_SPACE 1\n"; + } + + shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_GRADIENT_VISUAL_SHADER_VERT.data(), + Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_GRADIENT_VISUAL_SHADER_FRAG.data()); + mFactoryCache.SaveShader(shaderType, shader); + } - if ( value ) // Only check valve type if a valid Property has been passed in + return shader; +} + +void GradientVisual::GetStopOffsets(const Property::Value* value, Vector& stopOffsets) +{ + if(value) // Only check valve type if a valid Property has been passed in { - switch ( value->GetType() ) + switch(value->GetType()) { case Property::VECTOR2: { Vector2 offset2; - value->Get( offset2 ); - stopOffsets.PushBack( offset2.x ); - stopOffsets.PushBack( offset2.y ); + 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 ); + 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 ); + 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 ) + const Property::Array* offsetArray = value->GetArray(); + if(offsetArray) { unsigned int numStop = offsetArray->Count(); - float offset; - for( unsigned int i=0; iGetElementAt(i).Get(offset) ) + if(offsetArray->GetElementAt(i).Get(offset)) { - stopOffsets.PushBack( offset ); + stopOffsets.PushBack(offset); } } } @@ -500,11 +465,11 @@ void GradientVisual::GetStopOffsets(const Property::Value* value, Vector& } } - if ( stopOffsets.Empty() ) + 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 ); + stopOffsets.PushBack(DEFAULT_OFFSET_MINIMUM); + stopOffsets.PushBack(DEFAULT_OFFSET_MAXIMUM); } }