/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
#include <typeinfo>
#include <dali/integration-api/debug.h>
#include <dali/public-api/common/dali-vector.h>
-#include <dali/public-api/images/buffer-image.h>
#include <dali/public-api/object/property-array.h>
#include <dali/devel-api/scripting/enum-helper.h>
#include <dali/devel-api/scripting/scripting.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/visuals/gradient-visual-properties.h>
-#include <dali-toolkit/devel-api/visual-factory/devel-visual-properties.h>
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
#include <dali-toolkit/internal/visuals/visual-string-constants.h>
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 )
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 )
+VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[][4] =
{
- 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::GRADIENT_SHADER_LINEAR_USER_SPACE,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER
+ },
{
- return VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE;
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER
}
-
- return VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX;
-}
+};
const char* VERTEX_SHADER[] =
{
// vertex shader for gradient units as OBJECT_BOUNDING_BOX
- DALI_COMPOSE_SHADER(
+DALI_COMPOSE_SHADER(
attribute mediump vec2 aPosition;\n
- uniform mediump mat4 uMvpMatrix;\n
- uniform mediump vec3 uSize;\n
+ uniform highp mat4 uMvpMatrix;\n
+ uniform highp 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 highp vec2 size;\n
uniform mediump vec4 offsetSizeMode;\n
uniform mediump vec2 origin;\n
uniform mediump vec2 anchorPoint;\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 highp mat4 uMvpMatrix;\n
+ uniform highp vec3 uSize;\n
+ uniform mediump mat3 uAlignmentMatrix;\n
+ varying mediump vec2 vTexCoord;\n
+ \n
+
+ //Visual size and offset
+ uniform mediump vec2 offset;\n
+ uniform highp 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
+),
+
+// vertex shader for gradient units as OBJECT_BOUNDING_BOX with corner radius
+DALI_COMPOSE_SHADER(
+ attribute mediump vec2 aPosition;\n
+ uniform highp mat4 uMvpMatrix;\n
+ uniform highp vec3 uSize;\n
uniform mediump mat3 uAlignmentMatrix;\n
varying mediump vec2 vTexCoord;\n
+ varying mediump vec2 vPosition;\n
+ varying mediump vec2 vRectSize;\n
+ varying mediump float vCornerRadius;\n
\n
+ //Visual size and offset
+ uniform mediump vec2 offset;\n
+ uniform highp vec2 size;\n
+ uniform mediump vec4 offsetSizeMode;\n
+ uniform mediump vec2 origin;\n
+ uniform mediump vec2 anchorPoint;\n
+ uniform mediump float cornerRadius;\n
+ uniform mediump float cornerRadiusPolicy;\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
+ mediump float minSize = min( visualSize.x, visualSize.y );\n
+ vCornerRadius = mix( cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);\n
+ vCornerRadius = min( vCornerRadius, minSize * 0.5 );\n
+ vRectSize = visualSize * 0.5 - vCornerRadius;\n
+ vPosition = aPosition * visualSize;\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 with corner radius
+DALI_COMPOSE_SHADER(
+ attribute mediump vec2 aPosition;\n
+ uniform highp mat4 uMvpMatrix;\n
+ uniform highp vec3 uSize;\n
+ uniform mediump mat3 uAlignmentMatrix;\n
+ varying mediump vec2 vTexCoord;\n
+ varying mediump vec2 vPosition;\n
+ varying mediump vec2 vRectSize;\n
+ varying mediump float vCornerRadius;\n
+ \n
//Visual size and offset
uniform mediump vec2 offset;\n
- uniform mediump vec2 size;\n
+ uniform highp vec2 size;\n
uniform mediump vec4 offsetSizeMode;\n
uniform mediump vec2 origin;\n
uniform mediump vec2 anchorPoint;\n
+ uniform mediump float cornerRadius;\n
+ uniform mediump float cornerRadiusPolicy;\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
+ mediump float minSize = min( visualSize.x, visualSize.y );\n
+ vCornerRadius = mix( cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);\n
+ vCornerRadius = min( vCornerRadius, minSize * 0.5 );\n
+ vRectSize = visualSize * 0.5 - vCornerRadius;\n
+ vPosition = aPosition * visualSize;\n
return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n
}\n
DALI_COMPOSE_SHADER(
uniform sampler2D sTexture;\n // sampler1D?
uniform lowp vec4 uColor;\n
+ uniform lowp vec3 mixColor;\n
varying mediump vec2 vTexCoord;\n
\n
void main()\n
{\n
- gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * uColor;\n
+ gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * vec4(mixColor, 1.0) * uColor;\n
}\n
),
DALI_COMPOSE_SHADER(
uniform sampler2D sTexture;\n // sampler1D?
uniform lowp vec4 uColor;\n
+ uniform lowp vec3 mixColor;\n
+ varying mediump vec2 vTexCoord;\n
+ \n
+ void main()\n
+ {\n
+ gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * vec4(mixColor, 1.0) * uColor;\n
+ }\n
+),
+
+// fragment shader for linear gradient with corner radius
+DALI_COMPOSE_SHADER(
+ uniform sampler2D sTexture;\n // sampler1D?
+ uniform lowp vec4 uColor;\n
+ uniform lowp vec3 mixColor;\n
+ varying mediump vec2 vTexCoord;\n
+ varying mediump vec2 vPosition;\n
+ varying mediump vec2 vRectSize;\n
+ varying mediump float vCornerRadius;\n
+ \n
+ void main()\n
+ {\n
+ mediump float dist = length( max( abs( vPosition ), vRectSize ) - vRectSize ) - vCornerRadius;\n
+ gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * vec4(mixColor, 1.0) * uColor;\n
+ gl_FragColor *= 1.0 - smoothstep( -1.0, 1.0, dist );\n
+ }\n
+),
+
+// fragment shader for radial gradient with corner radius
+DALI_COMPOSE_SHADER(
+ uniform sampler2D sTexture;\n // sampler1D?
+ uniform lowp vec4 uColor;\n
+ uniform lowp vec3 mixColor;\n
varying mediump vec2 vTexCoord;\n
+ varying mediump vec2 vPosition;\n
+ varying mediump vec2 vRectSize;\n
+ varying mediump float vCornerRadius;\n
\n
void main()\n
{\n
- gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * uColor;\n
+ mediump float dist = length( max( abs( vPosition ), vRectSize ) - vRectSize ) - vCornerRadius;\n
+ gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * vec4(mixColor, 1.0) * uColor;\n
+ gl_FragColor *= 1.0 - smoothstep( -1.0, 1.0, dist );\n
}\n
)
};
} // unnamed namespace
-GradientVisualPtr GradientVisual::New( VisualFactoryCache& factoryCache )
+GradientVisualPtr GradientVisual::New( VisualFactoryCache& factoryCache, const Property::Map& properties )
{
- return new GradientVisual( factoryCache );
+ GradientVisualPtr gradientVisualPtr( new GradientVisual( factoryCache ) );
+ gradientVisualPtr->SetProperties( properties );
+ return gradientVisualPtr;
}
GradientVisual::GradientVisual( VisualFactoryCache& factoryCache )
-: Visual::Base( factoryCache ),
+: Visual::Base( factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::GRADIENT ),
mGradientType( LINEAR ),
mIsOpaque( true )
{
}
}
-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 );
+}
+
+void GradientVisual::UpdateShader()
+{
+ if(mImpl->mRenderer)
+ {
+ Shader shader = GetShader();
+ mImpl->mRenderer.SetShader(shader);
+ }
}
void GradientVisual::DoCreatePropertyMap( Property::Map& map ) const
{
map.Clear();
- map.Insert( Toolkit::VisualProperty::TYPE, Toolkit::Visual::GRADIENT );
+ map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::GRADIENT );
map.Insert( Toolkit::GradientVisual::Property::UNITS, mGradient->GetGradientUnits() );
map.Insert( Toolkit::GradientVisual::Property::SPREAD_METHOD, mGradient->GetSpreadMethod() );
}
}
-void GradientVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue )
-{
- // TODO
-}
-
-Dali::Property::Value GradientVisual::DoGetProperty( Dali::Property::Index index )
+void GradientVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
{
- // TODO
- return Dali::Property::Value();
+ // Do nothing
}
void GradientVisual::InitializeRenderer()
{
Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
- if( !geometry )
- {
- geometry = VisualFactoryCache::CreateQuadGeometry();
- mFactoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry );
- }
-
- 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 );
- }
+ Shader shader = GetShader();
//Set up the texture set
TextureSet textureSet = TextureSet::New();
mImpl->mRenderer = Renderer::New( geometry, shader );
mImpl->mRenderer.SetTextures( textureSet );
- // If opaque then no need to have blending
+ // If opaque and then no need to have blending
if( mIsOpaque )
{
mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::OFF );
return true;
}
+Shader GradientVisual::GetShader()
+{
+ Toolkit::GradientVisual::Units::Type gradientUnits = mGradient->GetGradientUnits();
+ int roundedCorner = IsRoundedCornerRequired() ? 1 : 0;
+ VisualFactoryCache::ShaderType shaderType = SHADER_TYPE_TABLE[mGradientType][gradientUnits + roundedCorner * 2];
+ Shader shader = mFactoryCache.GetShader(shaderType);
+ if(!shader)
+ {
+ shader = Shader::New(VERTEX_SHADER[gradientUnits + roundedCorner * 2], FRAGMENT_SHADER[mGradientType + roundedCorner * 2]);
+ mFactoryCache.SaveShader(shaderType, shader);
+ }
+
+ return shader;
+}
+
void GradientVisual::GetStopOffsets(const Property::Value* value, Vector<float>& stopOffsets)
{
}
case Property::ARRAY:
{
- Property::Array* offsetArray = value->GetArray();
+ const Property::Array* offsetArray = value->GetArray();
if( offsetArray )
{
unsigned int numStop = offsetArray->Count();