Implemented custom shader in ImageRenderer and changed Dissolve-effect to utilise... 87/48787/6
authorChu Hoang <c.hoang@samsung.com>
Mon, 28 Sep 2015 15:55:44 +0000 (16:55 +0100)
committerChu Hoang <c.hoang@samsung.com>
Thu, 1 Oct 2015 16:27:26 +0000 (17:27 +0100)
Change-Id: I3275449610040b533cca265445c4c1a65a35b404

22 files changed:
automated-tests/src/dali-toolkit/utc-Dali-ShaderEffects.cpp
dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp
dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h
dali-toolkit/devel-api/shader-effects/dissolve-effect.h
dali-toolkit/internal/controls/image-view/image-view-impl.cpp
dali-toolkit/internal/controls/renderers/border/border-renderer.cpp
dali-toolkit/internal/controls/renderers/border/border-renderer.h
dali-toolkit/internal/controls/renderers/color/color-renderer.cpp
dali-toolkit/internal/controls/renderers/color/color-renderer.h
dali-toolkit/internal/controls/renderers/control-renderer-data-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h
dali-toolkit/internal/controls/renderers/control-renderer-impl.cpp
dali-toolkit/internal/controls/renderers/control-renderer-impl.h
dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp
dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.h
dali-toolkit/internal/controls/renderers/image/image-renderer.cpp
dali-toolkit/internal/controls/renderers/image/image-renderer.h
dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp
dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h
dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp
dali-toolkit/internal/controls/renderers/renderer-factory-impl.h
dali-toolkit/internal/file.list

index cc5195d..33dfee4 100644 (file)
@@ -123,24 +123,69 @@ int UtcDaliCreateDisplacementEffectFixed(void)
   END_TEST;
 }
 
-int UtcDaliCreateDissolveEffect(void)
+int UtcDaliCreateDissolveEffect( bool highPrecision )
 {
   ToolkitTestApplication application;
 
-  ShaderEffect effect = Toolkit::CreateDissolveEffect();
-  DALI_TEST_CHECK( effect );
+  Property::Map effect = Toolkit::CreateDissolveEffect( highPrecision );
+  DALI_TEST_CHECK( !effect.Empty() );
+
+  Property::Value* customShaderValue = effect.Find( "shader" );
+  DALI_TEST_CHECK( customShaderValue );
+
+  Property::Map customShader;
+  DALI_TEST_CHECK( customShaderValue->Get( customShader ) );
+
+  Property::Value* vertexShaderValue = customShader.Find( "vertex-shader" );
+  DALI_TEST_CHECK( vertexShaderValue );
+
+  std::string vertexShader;
+  DALI_TEST_CHECK( vertexShaderValue->Get( vertexShader ) );
+  DALI_TEST_CHECK( !vertexShader.empty() );
+
+  Property::Value* fragmentShaderValue = customShader.Find( "fragment-shader" );
+  DALI_TEST_CHECK( fragmentShaderValue );
+
+  std::string fragmentShader;
+  DALI_TEST_CHECK( fragmentShaderValue->Get( fragmentShader ) );
+  DALI_TEST_CHECK( !fragmentShader.empty() );
+
+  Property::Value* gridXValue = customShader.Find( "subdivide-grid-x" );
+  DALI_TEST_CHECK( gridXValue );
+
+  int gridX = 0;
+  DALI_TEST_CHECK( gridXValue->Get( gridX ) );
+  DALI_TEST_CHECK( gridX > 1 );
+
+  Property::Value* gridYValue = customShader.Find( "subdivide-grid-y" );
+  DALI_TEST_CHECK( gridYValue );
+
+  int gridY = 0;
+  DALI_TEST_CHECK( gridYValue->Get( gridY ) );
+  DALI_TEST_CHECK( gridY > 1 );
+
+  Property::Value* hintsValue = customShader.Find( "hints" );
+  DALI_TEST_CHECK( hintsValue );
+
+  std::string hints;
+  DALI_TEST_CHECK( hintsValue->Get( hints ) );
+  DALI_TEST_CHECK( hints == "output-is-transparent" );
+
+  Actor actor = Actor::New();
+  Toolkit::DissolveEffectSetCentralLine( actor, Vector2::ONE, Vector2::ONE, 0.0f );
+  DALI_TEST_CHECK( actor.GetPropertyIndex( "uPercentage" ) != Property::INVALID_INDEX );
 
   END_TEST;
 }
 
-int UtcDaliCreateDissolveEffectMediumPrecision(void)
+int UtcDaliCreateDissolveEffectHighPrecision(void)
 {
-  ToolkitTestApplication application;
-
-  ShaderEffect effect = Toolkit::CreateDissolveEffect(false);
-  DALI_TEST_CHECK( effect );
+  return UtcDaliCreateDissolveEffect(true);
+}
 
-  END_TEST;
+int UtcDaliCreateDissolveEffectMediumPrecision(void)
+{
+  return UtcDaliCreateDissolveEffect(false);
 }
 
 int UtcDaliCreateDissolveLocalEffect(void)
index ce70893..3f7ef6c 100644 (file)
@@ -122,6 +122,11 @@ bool RendererFactory::ResetRenderer( ControlRenderer& renderer, const std::strin
   return GetImplementation( *this ).ResetRenderer( renderer, url );
 }
 
+bool RendererFactory::ResetRenderer( ControlRenderer& renderer, const Property::Map& propertyMap )
+{
+  return GetImplementation( *this ).ResetRenderer( renderer, propertyMap );
+}
+
 } // namespace Toolkit
 
 } // namespace Dali
index c4ac6a4..13242f4 100644 (file)
@@ -163,6 +163,19 @@ public:
    */
   bool ResetRenderer( ControlRenderer& renderer, const std::string& url );
 
+
+  /**
+   * @brief Request the current control renderer from the property map, merging the property map with the renderer
+   *
+   * if the current renderer is capable of merging with the property map the reset the renderer with the merged properties
+   * else the renderer would be a handle to a newly created internal renderer.
+   *
+   * @param[in] propertyMap The map contains the properties required by the control renderer
+   *            Depends on the content of the map, different kind of renderer would be returned.
+   * @return Whether a new internal control renderer is created.
+   */
+  bool ResetRenderer( ControlRenderer& renderer, const Property::Map& propertyMap );
+
 private:
 
   explicit DALI_INTERNAL RendererFactory(Internal::RendererFactory *impl);
index 4aee8cc..95cccc8 100644 (file)
  */
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/shader-effects/shader-effect.h>
+#include <string.h>
+#include <dali/devel-api/rendering/shader.h>
+
+namespace
+{
+  template < typename T>
+  void SafeSetCustomProperty( Dali::Actor& actor, const std::string& name, const T& value )
+  {
+    Dali::Property::Index index = actor.GetPropertyIndex( name );
+    if ( Dali::Property::INVALID_INDEX == index )
+    {
+      index = actor.RegisterProperty( name, value );
+    }
+    else
+    {
+      actor.SetProperty( index, value );
+    }
+  }
+
+  template < typename T>
+  void SafeSetCustomProperty( Dali::Actor& actor, const std::string& name, const T& value, Dali::Property::AccessMode accessMode )
+  {
+    Dali::Property::Index index = actor.GetPropertyIndex( name );
+    if ( Dali::Property::INVALID_INDEX == index )
+    {
+      index = actor.RegisterProperty( name, value, accessMode );
+    }
+    else
+    {
+      actor.SetProperty( index, value );
+    }
+  }
+
+};
 
 namespace Dali
 {
@@ -34,11 +67,11 @@ namespace Toolkit
  * As we use the texture coordinate as pixel position to calculate random offset,
  * the line should passing through rectangle {(0,0),(0,1),(1,0),(1,1)},
  * so make the position parameter with two component values between 0.0 to 1.0
- * @param[in] dissolveEffect The shader effect
  * @param[in] position The point ( locates within rectangle {(0,0),(0,1),(1,0),(1,1)} ) passed through by the central line
  * @param[in] displacement The direction of the central line
+ * @param[in] initialProgress, the normalised initial progress of the shader
  */
-inline void DissolveEffectSetCentralLine( ShaderEffect& dissolveEffect, const Vector2& position, const Vector2& displacement )
+inline void DissolveEffectSetCentralLine( Actor& actor, const Vector2& position, const Vector2& displacement, float initialProgress )
 {
   // the line passes through 'position' and has the direction of 'displacement'
     float coefA, coefB, coefC; //line equation: Ax+By+C=0;
@@ -102,10 +135,11 @@ inline void DissolveEffectSetCentralLine( ShaderEffect& dissolveEffect, const Ve
     rotation = Vector2(-displacement.x, displacement.y);
     rotation.Normalize();
 
-    dissolveEffect.SetUniform( "uSaddleParam", saddleParam );
-    dissolveEffect.SetUniform( "uTranslation", translation );
-    dissolveEffect.SetUniform( "uRotation", rotation );
-    dissolveEffect.SetUniform( "uToNext", toNext );
+    SafeSetCustomProperty( actor, "uSaddleParam", saddleParam );
+    SafeSetCustomProperty( actor, "uTranslation", translation );
+    SafeSetCustomProperty( actor, "uRotation", rotation );
+    SafeSetCustomProperty( actor, "uToNext", toNext );
+    SafeSetCustomProperty( actor, "uPercentage", initialProgress, Dali::Property::ANIMATABLE );
 }
 /**
  * @brief Create a new Dissolve effect
@@ -119,69 +153,108 @@ inline void DissolveEffectSetCentralLine( ShaderEffect& dissolveEffect, const Ve
  *  @return A handle to a newly allocated ShaderEffect
  */
 
-inline ShaderEffect CreateDissolveEffect(bool useHighPrecision = true)
+inline Property::Map CreateDissolveEffect( bool useHighPrecision = true )
 {
-  std::string prefixHighPrecision( "precision highp float;\n");
-    std::string prefixMediumPrecision( "precision mediump float;\n" );
-    std::string vertexShader(
-      "uniform float uPercentage;\n"
-      "uniform vec3 uSaddleParam;\n"
-      "uniform vec2 uTranslation;\n"
-      "uniform vec2 uRotation; \n"
-      "uniform float uToNext;\n"
-      "varying float vPercentage;\n"
-      "void main()\n"
-      "{\n"
-        "gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n"
-        "vTexCoord = aTexCoord;\n"
-        //Calculate the distortion value given the dissolve central line
-        "vec2 texCoor = vec2( (aTexCoord.s - sTextureRect.s ) / (sTextureRect.p - sTextureRect.s), (aTexCoord.t- sTextureRect.t)/(sTextureRect.q - sTextureRect.t) ); \n"
-        "vec2 value = texCoor + uTranslation; \n"
-        "mat2 rotateMatrix = mat2( uRotation.s, uRotation.t, -uRotation.t, uRotation.s ); \n"
-        "value = rotateMatrix * value; \n"
-        "if(uToNext == 1.0)  \n"
-        "  value.s = uSaddleParam[2] + value.s; \n"
-        "float delay = value.t*value.t / uSaddleParam[0] - value.s*value.s/uSaddleParam[1];\n"
-        "vPercentage = clamp( uPercentage*2.0 - 0.5*sin(delay*1.571) - 0.5, 0.0, 1.0 ); \n"
-      "}\n");
-    std::string fragmentShader(
-      "varying float vPercentage;\n"
-      "float rand(vec2 co) \n"
-      "{\n"
-      "  return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); \n"
-      "}\n"
-      "void main()\n"
-      "{\n"
-        //Calculate the randomness
-        "float offsetS = rand( vTexCoord * vPercentage ) * (sTextureRect.p - sTextureRect.s) - vTexCoord.s  + sTextureRect.s; \n"
-        "float offsetT = rand( vec2(vTexCoord.t*vPercentage, vTexCoord.s * vPercentage) ) * (sTextureRect.q - sTextureRect.t) - vTexCoord.t + sTextureRect.t; \n"
-        "vec2 lookupCoord = vTexCoord + vec2(offsetS, offsetT) * vPercentage; \n"
-        "gl_FragColor = texture2D( sTexture, lookupCoord ) * uColor; \n"
-        "gl_FragColor.a *= 1.0 - vPercentage; \n"
-      "}" );
-
-    // Create the implementation, temporarily owned on stack,
-    Dali::ShaderEffect shaderEffect;
-    if( useHighPrecision )
-    {
-      shaderEffect =  Dali::ShaderEffect::New(
-          prefixHighPrecision+vertexShader, prefixHighPrecision + fragmentShader,
-          ShaderEffect::GeometryHints( ShaderEffect::HINT_GRID | ShaderEffect::HINT_BLENDING ) );
-    }
-    else
-    {
-      shaderEffect =  Dali::ShaderEffect::New(
-          prefixMediumPrecision+vertexShader, prefixMediumPrecision + fragmentShader,
-          ShaderEffect::GeometryHints( ShaderEffect::HINT_GRID | ShaderEffect::HINT_BLENDING ) );
-    }
+  const char* prefixHighPrecision( "precision highp float;\n");
+  const char* prefixMediumPrecision( "precision mediump float;\n" );
+
+  const char* vertexShader( DALI_COMPOSE_SHADER(
+    attribute mediump vec2 aPosition;\n
+    \n
+    uniform mediump mat4 uMvpMatrix;\n
+    uniform vec3 uSize;\n
+    uniform vec4 uTextureRect;
+    \n
+    uniform float uPercentage;\n
+    uniform vec3 uSaddleParam;\n
+    uniform vec2 uTranslation;\n
+    uniform vec2 uRotation; \n
+    uniform float uToNext;\n
+    \n
+    varying float vPercentage;\n
+    varying vec2 vTexCoord;\n
+
+    void main()\n
+    {\n
+      mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
+      vertexPosition.xyz *= uSize;\n
+      vertexPosition = uMvpMatrix * vertexPosition;\n
+      gl_Position = vertexPosition;\n
+
+      vec2 texCoord = aPosition + vec2(0.5);
+      vTexCoord = texCoord;\n
+      //Calculate the distortion value given the dissolve central line
+      vec2 value = texCoord + uTranslation; \n
+      mat2 rotateMatrix = mat2( uRotation.s, uRotation.t, -uRotation.t, uRotation.s ); \n
+      value = rotateMatrix * value; \n
+      if(uToNext == 1.0)  \n
+        value.s = uSaddleParam[2] + value.s; \n
+      float delay = value.t*value.t / uSaddleParam[0] - value.s*value.s/uSaddleParam[1];\n
+      vPercentage = clamp( uPercentage*2.0 - 0.5*sin(delay*1.571) - 0.5, 0.0, 1.0 ); \n
+    })
+  );
+
+  const char* fragmentShader( DALI_COMPOSE_SHADER(
+    varying float vPercentage;\n
+    varying mediump vec2 vTexCoord;\n
+    \n
+    uniform sampler2D sTexture;\n
+    uniform lowp vec4 uColor;\n
+    uniform vec4 uTextureRect;
+    \n
+    float rand(vec2 co) \n
+    {\n
+      return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); \n
+    }\n
+    \n
+    void main()\n
+    {\n
+
+      //Calculate the randomness
+      float offsetS = rand( vTexCoord * vPercentage ) - vTexCoord.s; \n
+      float offsetT = rand( vec2(vTexCoord.t*vPercentage, vTexCoord.s * vPercentage) ) - vTexCoord.t; \n
+      vec2 lookupCoord = vTexCoord + vec2(offsetS, offsetT) * vPercentage; \n
+      gl_FragColor = texture2D( sTexture, lookupCoord ) * uColor; \n
+      gl_FragColor.a *= 1.0 - vPercentage; \n
+    } )
+  );
+
+  Property::Map map;
+
+  Property::Map customShader;
+
+  std::string vertexShaderString;
+  std::string fragmentShaderString;
+  if( useHighPrecision )
+  {
+    vertexShaderString.reserve(strlen( prefixHighPrecision ) + strlen( vertexShader ));
+    vertexShaderString.append( prefixHighPrecision );
+
+    fragmentShaderString.reserve(strlen( prefixHighPrecision ) + strlen( fragmentShader ));
+    fragmentShaderString.append( prefixHighPrecision );
+  }
+  else
+  {
+    vertexShaderString.reserve(strlen( prefixMediumPrecision ) + strlen( vertexShader ));
+    vertexShaderString.append( prefixMediumPrecision );
+
+    fragmentShaderString.reserve(strlen( prefixMediumPrecision ) + strlen( fragmentShader ));
+    fragmentShaderString.append( prefixMediumPrecision );
+  }
+
+  vertexShaderString.append( vertexShader );
+  fragmentShaderString.append( fragmentShader );
 
-    shaderEffect.SetUniform( "uPercentage", 0.0f );
-    shaderEffect.SetProperty( ShaderEffect::Property::GRID_DENSITY, Dali::Property::Value(50.0f) );
+  customShader[ "vertex-shader" ] = vertexShaderString;
+  customShader[ "fragment-shader" ] = fragmentShaderString;
 
-    DissolveEffectSetCentralLine( shaderEffect, Vector2(1.0f,0.5f), Vector2(-1.0f, 0.0f) );
+  customShader[ "subdivide-grid-x" ] = 20;
+  customShader[ "subdivide-grid-y" ] = 20;
 
-    return shaderEffect;
+  customShader[ "hints" ] = "output-is-transparent";
 
+  map[ "shader" ] = customShader;
+  return map;
 }
 
 } // namespace Toolkit
index 76493a6..554469b 100644 (file)
@@ -97,16 +97,23 @@ void ImageView::SetImage( Image image )
 
 void ImageView::SetImage( Property::Map map )
 {
-  mImage.Reset();
-  mUrl.clear();
   mPropertyMap = map;
 
-  mRenderer = Toolkit::RendererFactory::Get().GetControlRenderer( mPropertyMap );
+  bool newRendererCreated = false;
+  if( mRenderer )
+  {
+    newRendererCreated = Toolkit::RendererFactory::Get().ResetRenderer( mRenderer, mPropertyMap );
+  }
+  else
+  {
+    mRenderer = Toolkit::RendererFactory::Get().GetControlRenderer( mPropertyMap );
+    newRendererCreated = true;
+  }
 
   //we need to inform any newly created renderers if it is on stage
-  if( Self().OnStage() )
+  CustomActor self = Self();
+  if( newRendererCreated && self.OnStage() )
   {
-    CustomActor self = Self();
     mRenderer.SetOnStage( self );
   }
 
index 423afc2..6542a2c 100644 (file)
@@ -88,7 +88,7 @@ BorderRenderer::~BorderRenderer()
 {
 }
 
-void BorderRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void BorderRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
 {
   Initialize( factoryCache );
 
@@ -122,7 +122,7 @@ void BorderRenderer::DoSetOnStage( Actor& actor )
   mBorderSizeIndex = (mImpl->mRenderer).RegisterProperty( SIZE_UNIFORM_NAME, mBorderSize );
 }
 
-void BorderRenderer::CreatePropertyMap( Property::Map& map ) const
+void BorderRenderer::DoCreatePropertyMap( Property::Map& map ) const
 {
   map.Clear();
   map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE );
index c05ea1c..9c53935 100644 (file)
@@ -60,9 +60,9 @@ public:
 public:  // from ControlRenderer
 
   /**
-   * @copydoc ControlRenderer::Initialize
+   * @copydoc ControlRenderer::DoInitialize
    */
-  virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
+  virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
 
   /**
    * @copydoc ControlRenderer::SetClipRect
@@ -78,7 +78,7 @@ protected:
   /**
    * @copydoc ControlRenderer::CreatePropertyMap
    */
-  virtual void CreatePropertyMap( Property::Map& map ) const;
+  virtual void DoCreatePropertyMap( Property::Map& map ) const;
 
 public:
 
index 0da8112..68164ea 100644 (file)
@@ -77,7 +77,7 @@ ColorRenderer::~ColorRenderer()
 {
 }
 
-void ColorRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void ColorRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
 {
   Initialize( factoryCache );
 
@@ -107,7 +107,7 @@ void ColorRenderer::SetOffset( const Vector2& offset )
   //ToDo: renderer applies the offset
 }
 
-void ColorRenderer::CreatePropertyMap( Property::Map& map ) const
+void ColorRenderer::DoCreatePropertyMap( Property::Map& map ) const
 {
   map.Clear();
   map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE );
index cec5b3a..ae5ccca 100644 (file)
@@ -56,9 +56,9 @@ public:
 public:  // from ControlRenderer
 
   /**
-   * @copydoc ControlRenderer::Initialize
+   * @copydoc ControlRenderer::DoInitialize
    */
-  virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
+  virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
 
   /**
    * @copydoc ControlRenderer::SetSize
@@ -78,7 +78,7 @@ public:  // from ControlRenderer
   /**
    * @copydoc ControlRenderer::CreatePropertyMap
    */
-  virtual void CreatePropertyMap( Property::Map& map ) const;
+  virtual void DoCreatePropertyMap( Property::Map& map ) const;
 
 protected:
   /**
diff --git a/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.cpp b/dali-toolkit/internal/controls/renderers/control-renderer-data-impl.cpp
new file mode 100644 (file)
index 0000000..6a58cfb
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "control-renderer-data-impl.h"
+
+// EXTERNAL HEADER
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/object/property-array.h>
+
+// EXTERNAL HEADER
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+//custom shader
+const char * const CUSTOM_SHADER( "shader" );
+const char * const CUSTOM_VERTEX_SHADER( "vertex-shader" );
+const char * const CUSTOM_FRAGMENT_SHADER( "fragment-shader" );
+const char * const CUSTOM_SUBDIVIDE_GRID_X( "subdivide-grid-x" );
+const char * const CUSTOM_SUBDIVIDE_GRID_Y( "subdivide-grid-y" );
+const char * const CUSTOM_SHADER_HINTS( "hints" ); ///< type STRING for a hint from the below hint strings or an ARRAY of of hint strings
+
+/**
+ * where hints should be contain strings of the following shader hints:
+ *   "none"                       | corresponds to HINT_NONE
+ *   "requires-self-depth-test"   | corresponds to HINT_REQUIRES_SELF_DEPTH_TEST
+ *   "output-is-transparent"      | corresponds to HINT_OUTPUT_IS_TRANSPARENT
+ *   "output-is-opaque"           | corresponds to HINT_OUTPUT_IS_OPAQUE
+ *   "modifies-geometry"          | corresponds to HINT_MODIFIES_GEOMETRY
+ */
+
+Shader::ShaderHints HintFromString( std::string hintString )
+{
+  if( hintString == "none" )
+  {
+    return Shader::HINT_NONE;
+  }
+  else if( hintString == "requires-self-depth-test" )
+  {
+    return Shader::HINT_REQUIRES_SELF_DEPTH_TEST;
+  }
+  else if( hintString == "output-is-transparent" )
+  {
+    return Shader::HINT_OUTPUT_IS_TRANSPARENT;
+  }
+  else if( hintString == "output-is-opaque" )
+  {
+    return Shader::HINT_OUTPUT_IS_OPAQUE;
+  }
+  else if( hintString == "modifies-geometry" )
+  {
+    return Shader::HINT_MODIFIES_GEOMETRY;
+  }
+  else
+  {
+    DALI_LOG_ERROR( "'%s' hint string is not recognised", hintString.c_str() );
+  }
+
+  return Shader::HINT_NONE;
+}
+
+}// unnamed namespace
+
+Internal::ControlRenderer::Impl::Impl()
+: mCustomShader(NULL),
+  mDepthIndex( 0.0f ),
+  mIsOnStage( false )
+{
+}
+
+Internal::ControlRenderer::Impl::~Impl()
+{
+  delete mCustomShader;
+}
+
+Internal::ControlRenderer::Impl::CustomShader::CustomShader( const Property::Map& map )
+: mGridSize( 1, 1 ),
+  mHints( Shader::HINT_NONE )
+{
+  SetPropertyMap( map );
+}
+
+void Internal::ControlRenderer::Impl::CustomShader::SetPropertyMap( const Property::Map& propertyMap )
+{
+  Property::Value* shaderValue = propertyMap.Find( CUSTOM_SHADER );
+  if( shaderValue )
+  {
+    mVertexShader.clear();
+    mFragmentShader.clear();
+    mGridSize = ImageDimensions( 1, 1 );
+    mHints = Shader::HINT_NONE;
+
+    Property::Map shaderMap;
+    if( shaderValue->Get( shaderMap ) )
+    {
+      Property::Value* vertexShaderValue = shaderMap.Find( CUSTOM_VERTEX_SHADER );
+      if( vertexShaderValue )
+      {
+        if( !vertexShaderValue->Get( mVertexShader ) )
+        {
+          DALI_LOG_ERROR( "'%s' parameter does not correctly specify a string", CUSTOM_VERTEX_SHADER );
+        }
+      }
+
+      Property::Value* fragmentShaderValue = shaderMap.Find( CUSTOM_FRAGMENT_SHADER );
+      if( fragmentShaderValue )
+      {
+        if( !fragmentShaderValue->Get( mFragmentShader ) )
+        {
+          DALI_LOG_ERROR( "'%s' parameter does not correctly specify a string", CUSTOM_FRAGMENT_SHADER );
+        }
+      }
+
+      Property::Value* subdivideXValue = shaderMap.Find( CUSTOM_SUBDIVIDE_GRID_X );
+      if( subdivideXValue )
+      {
+        int subdivideX;
+        if( !subdivideXValue->Get( subdivideX ) || subdivideX < 1 )
+        {
+          DALI_LOG_ERROR( "'%s' parameter does not correctly specify a value greater than 1", CUSTOM_SUBDIVIDE_GRID_X );
+        }
+        else
+        {
+          mGridSize = ImageDimensions( subdivideX, mGridSize.GetY() );
+        }
+      }
+
+      Property::Value* subdivideYValue = shaderMap.Find( CUSTOM_SUBDIVIDE_GRID_Y );
+      if( subdivideYValue )
+      {
+        int subdivideY;
+        if( !subdivideYValue->Get( subdivideY ) || subdivideY < 1 )
+        {
+          DALI_LOG_ERROR( "'%s' parameter does not correctly specify a value greater than 1", CUSTOM_SUBDIVIDE_GRID_Y );
+        }
+        else
+        {
+          mGridSize = ImageDimensions( mGridSize.GetX(), subdivideY );
+        }
+      }
+
+      Property::Value* hintsValue = shaderMap.Find( CUSTOM_SHADER_HINTS );
+      if( hintsValue )
+      {
+        std::string hintString;
+        Property::Array hintsArray;
+
+        if( hintsValue->Get( hintString ) )
+        {
+          mHints = HintFromString( hintString );
+        }
+        else if( hintsValue->Get( hintsArray ) )
+        {
+          int hints = Shader::HINT_NONE;
+          for( Property::Array::SizeType i = 0; i < hintsArray.Count(); ++i)
+          {
+            Property::Value hintValue = hintsArray[ i ];
+            if( hintValue.Get( hintString ) )
+            {
+              hints |= static_cast< int >( HintFromString( hintString ) );
+            }
+            else
+            {
+              DALI_LOG_ERROR( "'%s' parameter does not correctly specify an hint string at index %d", CUSTOM_SHADER_HINTS, i );
+            }
+
+            mHints = static_cast< Shader::ShaderHints >( hints );
+          }
+        }
+        else
+        {
+          DALI_LOG_ERROR( "'%s' parameter does not correctly specify a hint string or an array of hint strings", CUSTOM_SHADER_HINTS );
+        }
+      }
+    }
+    else
+    {
+      //use value with no type to mean reseting the shader back to default
+      if( shaderValue->GetType() != Dali::Property::NONE )
+      {
+        DALI_LOG_ERROR( "'%s' parameter does not correctly specify a property map", CUSTOM_SHADER );
+      }
+    }
+  }
+}
+
+void Internal::ControlRenderer::Impl::CustomShader::CreatePropertyMap( Property::Map& map ) const
+{
+  if( !mVertexShader.empty() || !mFragmentShader.empty() )
+  {
+    Property::Map customShader;
+    if( !mVertexShader.empty() )
+    {
+      customShader.Insert(CUSTOM_VERTEX_SHADER, mVertexShader );
+    }
+    if( !mFragmentShader.empty() )
+    {
+      customShader.Insert(CUSTOM_FRAGMENT_SHADER, mFragmentShader );
+    }
+
+    if( mGridSize.GetWidth() != 1 )
+    {
+      customShader.Insert(CUSTOM_SUBDIVIDE_GRID_X, mGridSize.GetWidth() );
+    }
+    if( mGridSize.GetHeight() != 1 )
+    {
+      customShader.Insert(CUSTOM_SUBDIVIDE_GRID_Y, mGridSize.GetHeight() );
+    }
+
+    if( mHints != Dali::Shader::HINT_NONE )
+    {
+      customShader.Insert(CUSTOM_SHADER_HINTS, static_cast< int >(mHints) );
+    }
+
+    map.Insert( CUSTOM_SHADER, customShader );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
index e865a0e..47095c9 100644 (file)
  *
  */
 
-// INTERNAL INCLUDES
+// EXTERNAL INCLUDES
 #include <dali/public-api/math/vector2.h>
 #include <dali/devel-api/rendering/renderer.h>
 
+#include <dali-toolkit/internal/controls/renderers/control-renderer-impl.h>
+
 namespace Dali
 {
 
@@ -33,15 +35,32 @@ namespace Internal
 
 struct Internal::ControlRenderer::Impl
 {
+  struct CustomShader
+  {
+    std::string mVertexShader;
+    std::string mFragmentShader;
+    Dali::ImageDimensions mGridSize;
+    Dali::Shader::ShaderHints mHints; //(bitfield) values from enum Shader::Hints
+
+    CustomShader( const Property::Map& map );
+    void SetPropertyMap( const Property::Map& map );
+    void CreatePropertyMap( Property::Map& map ) const;
+  };
+
   Geometry mGeometry;
   Shader   mShader;
   Renderer mRenderer;
 
+  CustomShader* mCustomShader;
+
   Vector2   mSize;
   Vector2   mOffset;
   Rect<int> mClipRect;
   float     mDepthIndex;
   bool      mIsOnStage;
+
+  Impl();
+  ~Impl();
 };
 
 } // namespace Internal
index 1fa7bf3..91343a4 100644 (file)
 
 // EXTERNAL HEADER
 #include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/debug.h>
 
 //INTERNAL HEARDER
 #include <dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h>
 
+namespace
+{
+//custom shader
+const char * const CUSTOM_SHADER( "shader" );
+const char * const CUSTOM_VERTEX_SHADER( "vertex-shader" );
+const char * const CUSTOM_FRAGMENT_SHADER( "fragment-shader" );
+const char * const CUSTOM_SUBDIVIDE_GRID_X( "subdivide-grid-x" );
+const char * const CUSTOM_SUBDIVIDE_GRID_Y( "subdivide-grid-y" );
+const char * const CUSTOM_SHADER_HINTS( "hints" ); ///< type INTEGER; (bitfield) values from enum Shader::Hints
+}
+
 namespace Dali
 {
 
@@ -36,7 +48,6 @@ namespace Internal
 ControlRenderer::ControlRenderer()
 : mImpl( new Impl() )
 {
-  mImpl->mIsOnStage = false;
 }
 
 ControlRenderer::~ControlRenderer()
@@ -44,6 +55,27 @@ ControlRenderer::~ControlRenderer()
   delete mImpl;
 }
 
+void ControlRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+{
+  if( mImpl->mCustomShader )
+  {
+    mImpl->mCustomShader->SetPropertyMap( propertyMap );
+  }
+  else
+  {
+    Property::Value* customShaderValue = propertyMap.Find( CUSTOM_SHADER );
+    if( customShaderValue )
+    {
+      Property::Map customShader;
+      if( customShaderValue->Get( customShader ) )
+      {
+        mImpl->mCustomShader = new Impl::CustomShader( propertyMap );
+      }
+    }
+  }
+  DoInitialize( factoryCache, propertyMap );
+}
+
 void ControlRenderer::SetSize( const Vector2& size )
 {
   mImpl->mSize = size;
@@ -115,6 +147,15 @@ void ControlRenderer::DoSetOffStage( Actor& actor )
 {
 }
 
+void ControlRenderer::CreatePropertyMap( Property::Map& map ) const
+{
+  if( mImpl->mCustomShader )
+  {
+    mImpl->mCustomShader->CreatePropertyMap( map );
+  }
+  DoCreatePropertyMap( map );
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 773e7c0..4dea2d9 100644 (file)
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/object/base-object.h>
+#include <dali/public-api/images/image-operations.h>
+#include <dali/devel-api/rendering/shader.h>
 
+// INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
 #include <dali-toolkit/devel-api/controls/renderer-factory/control-renderer.h>
 
@@ -40,6 +43,21 @@ class RendererFactoryCache;
  * Base class for all Control rendering logic. A control may have multiple control renderers.
  *
  * Note: The control renderer responds to the the Actor::COLOR by blending it with the 'Multiply' operator.
+ *
+ * The following properties are optional
+ *
+ * | %Property Name            | Type             |
+ * |---------------------------|------------------|
+ * | custom-shader             | MAP              |
+ *
+ * where custom-shader is a map with the following properties:
+ * | %Property Name            | Type             |
+ * |---------------------------|------------------|
+ * | vertex-shader             | STRING           |
+ * | fragment-shader           | STRING           |
+ * | subdivide-grid-x          | INT              |
+ * | subdivide-grid-y          | INT              |
+ * | shader-hints              | INT              |
  */
 class ControlRenderer : public BaseObject
 {
@@ -53,7 +71,7 @@ public:
    * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
    * @param[in] propertyMap The properties for the requested ControlRenderer object.
    */
-  virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ) = 0;
+  void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
 
   /**
    * @copydoc Toolkit::ControlRenderer::SetSize
@@ -113,7 +131,7 @@ public:
   /**
    * @copydoc Toolkit::ControlRenderer::CreatePropertyMap
    */
-  virtual void CreatePropertyMap( Property::Map& map ) const = 0;
+  void CreatePropertyMap( Property::Map& map ) const;
 
 protected:
 
@@ -128,16 +146,32 @@ protected:
   virtual ~ControlRenderer();
 
 protected:
+  /**
+   * @brief Called by CreatePropertyMap() allowing sub classes to respond to the CreatePropertyMap event
+   *
+   * @param[out] map The renderer property map.
+   */
+  virtual void DoCreatePropertyMap( Property::Map& map ) const = 0;
 
   /**
-   * Called by SetOnStage() allowing sub classes to respond to the SetOnStage event
+   * @brief Called by Initialize() allowing sub classes to respond to the Initialize event
+   *
+   * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object
+   * @param[in] propertyMap The properties for the requested ControlRenderer object.
+   */
+  virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ) = 0;
+
+protected:
+
+  /**
+   * @brief Called by SetOnStage() allowing sub classes to respond to the SetOnStage event
    *
    * @param[in] actor The actor applying this renderer.
    */
   virtual void DoSetOnStage( Actor& actor );
 
   /**
-   * Called by SetOffStage() allowing sub classes to respond to the SetOffStage event
+   * @brief Called by SetOffStage() allowing sub classes to respond to the SetOffStage event
    *
    * @param[in] actor The actor applying this renderer.
    */
@@ -152,7 +186,6 @@ private:
   ControlRenderer& operator=( const ControlRenderer& renderer );
 
 protected:
-
   struct Impl;
   Impl* mImpl;
 };
index 396ded3..0e502da 100644 (file)
@@ -143,7 +143,7 @@ GradientRenderer::~GradientRenderer()
 {
 }
 
-void GradientRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void GradientRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
 {
   mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
   if( !(mImpl->mGeometry) )
@@ -214,7 +214,7 @@ void GradientRenderer::SetOffset( const Vector2& offset )
   //ToDo: renderer applies the offset
 }
 
-void GradientRenderer::CreatePropertyMap( Property::Map& map ) const
+void GradientRenderer::DoCreatePropertyMap( Property::Map& map ) const
 {
   map.Clear();
   map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE );
index e35b5db..1ee3f36 100644 (file)
@@ -84,9 +84,9 @@ public:
 public:  // from ControlRenderer
 
   /**
-   * @copydoc ControlRenderer::Initialize
+   * @copydoc ControlRenderer::DoInitialize
    */
-  virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
+  virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
 
   /**
    * @copydoc ControlRenderer::SetSize
@@ -106,7 +106,7 @@ public:  // from ControlRenderer
   /**
    * @copydoc ControlRenderer::CreatePropertyMap
    */
-  virtual void CreatePropertyMap( Property::Map& map ) const;
+  virtual void DoCreatePropertyMap( Property::Map& map ) const;
 
 protected:
   /**
index b84b5f5..4770960 100644 (file)
 // CLASS HEADER
 #include "image-renderer.h"
 
+// EXTERNAL HEADER
+#include <dali/public-api/images/resource-image.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL HEADER
 #include <dali-toolkit/internal/controls/renderers/renderer-factory-impl.h>
 #include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
 #include <dali-toolkit/internal/controls/renderers/control-renderer-impl.h>
 #include <dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h>
-#include <dali/public-api/images/resource-image.h>
 
 namespace Dali
 {
@@ -39,11 +43,11 @@ const char * const RENDERER_TYPE("renderer-type");
 const char * const RENDERER_TYPE_VALUE("image-renderer");
 
 // property names
-const char * const IMAGE_URL_NAME("image-url");
-const char * const IMAGE_FITTING_MODE("image-fitting-mode");
-const char * const IMAGE_SAMPLING_MODE("image-sampling-mode");
-const char * const IMAGE_DESIRED_WIDTH("image-desired-width");
-const char * const IMAGE_DESIRED_HEIGHT("image-desired-height");
+const char * const IMAGE_URL_NAME( "image-url" );
+const char * const IMAGE_FITTING_MODE( "image-fitting-mode" );
+const char * const IMAGE_SAMPLING_MODE( "image-sampling-mode" );
+const char * const IMAGE_DESIRED_WIDTH( "image-desired-width" );
+const char * const IMAGE_DESIRED_HEIGHT( "image-desired-height" );
 
 // fitting modes
 const char * const SHRINK_TO_FIT("shrink-to-fit");
@@ -91,6 +95,93 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
   }\n
 );
 
+void AddQuadIndices( Vector< unsigned int >& indices, unsigned int rowIdx, unsigned int nextRowIdx )
+{
+  indices.PushBack( rowIdx );
+  indices.PushBack( nextRowIdx + 1 );
+  indices.PushBack( rowIdx + 1 );
+
+  indices.PushBack( rowIdx );
+  indices.PushBack( nextRowIdx );
+  indices.PushBack( nextRowIdx + 1 );
+}
+
+Geometry GenerateGeometry( const Vector< Vector2 >& vertices, const Vector< unsigned int >& indices )
+{
+  Property::Map vertexFormat;
+  vertexFormat[ "aPosition" ] = Property::VECTOR2;
+  PropertyBuffer vertexPropertyBuffer = PropertyBuffer::New( vertexFormat, vertices.Size() );
+  if( vertices.Size() > 0 )
+  {
+    vertexPropertyBuffer.SetData( &vertices[ 0 ] );
+  }
+
+  Property::Map indexFormat;
+  indexFormat[ "indices" ] = Property::INTEGER;
+  PropertyBuffer indexPropertyBuffer = PropertyBuffer::New( indexFormat, indices.Size() );
+  if( indices.Size() > 0 )
+  {
+    indexPropertyBuffer.SetData( &indices[ 0 ] );
+  }
+
+  // Create the geometry object
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexPropertyBuffer );
+  geometry.SetIndexBuffer( indexPropertyBuffer );
+
+  return geometry;
+}
+
+Geometry CreateGeometry( RendererFactoryCache& factoryCache, ImageDimensions gridSize )
+{
+  Geometry geometry;
+
+  if( gridSize == ImageDimensions( 1, 1 ) )
+  {
+    geometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
+    if( !geometry )
+    {
+      geometry =  factoryCache.CreateQuadGeometry();
+      factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry );
+    }
+  }
+  else
+  {
+    uint16_t gridWidth = gridSize.GetWidth();
+    uint16_t gridHeight = gridSize.GetHeight();
+
+    // Create vertices
+    Vector< Vector2 > vertices;
+    vertices.Reserve( ( gridWidth + 1 ) * ( gridHeight + 1 ) );
+
+    for( int y = 0; y < gridHeight + 1; ++y )
+    {
+      for( int x = 0; x < gridWidth + 1; ++x )
+      {
+        vertices.PushBack( Vector2( (float)x/gridWidth - 0.5f, (float)y/gridHeight  - 0.5f) );
+      }
+    }
+
+    // Create indices
+    Vector< unsigned int > indices;
+    indices.Reserve( gridWidth * gridHeight * 6 );
+
+    unsigned int rowIdx     = 0;
+    unsigned int nextRowIdx = gridWidth + 1;
+    for( int y = 0; y < gridHeight; ++y, ++nextRowIdx, ++rowIdx )
+    {
+      for( int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx )
+      {
+        AddQuadIndices( indices, rowIdx, nextRowIdx );
+      }
+    }
+
+    return GenerateGeometry( vertices, indices );
+  }
+
+  return geometry;
+}
+
 } //unnamed namespace
 
 ImageRenderer::ImageRenderer()
@@ -105,7 +196,7 @@ ImageRenderer::~ImageRenderer()
 {
 }
 
-void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void ImageRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
 {
   Initialize(factoryCache);
 
@@ -113,6 +204,10 @@ void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Proper
   if( imageURLValue )
   {
     imageURLValue->Get( mImageUrl );
+    if( !mImageUrl.empty() )
+    {
+      mImage.Reset();
+    }
 
     Property::Value* fittingValue = propertyMap.Find( IMAGE_FITTING_MODE );
     if( fittingValue )
@@ -208,8 +303,6 @@ void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Proper
 
     mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
   }
-
-  mImage.Reset();
 }
 
 void ImageRenderer::SetSize( const Vector2& size )
@@ -270,7 +363,7 @@ void ImageRenderer::DoSetOffStage( Actor& actor )
   }
 }
 
-void ImageRenderer::CreatePropertyMap( Property::Map& map ) const
+void ImageRenderer::DoCreatePropertyMap( Property::Map& map ) const
 {
   map.Clear();
   map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE );
@@ -368,24 +461,49 @@ void ImageRenderer::CreatePropertyMap( Property::Map& map ) const
 
 void ImageRenderer::Initialize( RendererFactoryCache& factoryCache )
 {
-  mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
-  if( !(mImpl->mGeometry) )
+  if( !mImpl->mCustomShader )
   {
-    mImpl->mGeometry =  factoryCache.CreateQuadGeometry();
-    factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry );
-  }
+    mImpl->mGeometry = CreateGeometry( factoryCache, ImageDimensions( 1, 1 ) );
+
+    mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
 
-  mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
-  if( !mImpl->mShader )
+    if( !mImpl->mShader )
+    {
+      mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+      factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader );
+    }
+  }
+  else
   {
-    mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
-    factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader );
+    mImpl->mGeometry = CreateGeometry( factoryCache, mImpl->mCustomShader->mGridSize );
+
+    if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() )
+    {
+      mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
+
+      if( !mImpl->mShader )
+      {
+        mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+        factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader );
+      }
+    }
+    else
+    {
+      mImpl->mShader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
+                                    mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER : mImpl->mCustomShader->mFragmentShader,
+                                    mImpl->mCustomShader->mHints );
+    }
   }
 
-  mDesiredSize = ImageDimensions();
-  mFittingMode = FittingMode::DEFAULT;
-  mSamplingMode = SamplingMode::DEFAULT;
-  mImageUrl.clear();
+  if( mImpl->mRenderer )
+  {
+    mImpl->mRenderer.SetGeometry( mImpl->mGeometry );
+    Material material = mImpl->mRenderer.GetMaterial();
+    if( material )
+    {
+      material.SetShader( mImpl->mShader );
+    }
+  }
 }
 
 void ImageRenderer::SetImage( const std::string& imageUrl )
index fd88df0..367ae31 100644 (file)
@@ -85,9 +85,9 @@ public:
 public:  // from ControlRenderer
 
   /**
-   * @copydoc ControlRenderer::Initialize
+   * @copydoc ControlRenderer::DoInitialize
    */
-  virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
+  virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
 
   /**
    * @copydoc ControlRenderer::SetSize
@@ -112,7 +112,7 @@ public:  // from ControlRenderer
   /**
    * @copydoc ControlRenderer::CreatePropertyMap
    */
-  virtual void CreatePropertyMap( Property::Map& map ) const;
+  virtual void DoCreatePropertyMap( Property::Map& map ) const;
 
 protected:
   /**
index aa52f3e..842a099 100644 (file)
@@ -160,7 +160,7 @@ NPatchRenderer::~NPatchRenderer()
 {
 }
 
-void NPatchRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void NPatchRenderer::DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
 {
   Initialize(factoryCache);
 
@@ -243,7 +243,7 @@ void NPatchRenderer::DoSetOffStage( Actor& actor )
   mCroppedImage.Reset();
 }
 
-void NPatchRenderer::CreatePropertyMap( Property::Map& map ) const
+void NPatchRenderer::DoCreatePropertyMap( Property::Map& map ) const
 {
   map.Clear();
   map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE );
index 0bcd28a..6e5bd5d 100644 (file)
@@ -66,9 +66,9 @@ public:
 public:  // from ControlRenderer
 
   /**
-   * @copydoc ControlRenderer::Initialize
+   * @copydoc ControlRenderer::DoInitialize
    */
-  virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
+  virtual void DoInitialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
 
   /**
    * @copydoc ControlRenderer::GetNaturalSize
@@ -88,7 +88,7 @@ public:  // from ControlRenderer
   /**
    * @copydoc ControlRenderer::CreatePropertyMap
    */
-  virtual void CreatePropertyMap( Property::Map& map ) const;
+  virtual void DoCreatePropertyMap( Property::Map& map ) const;
 
 protected:
   /**
index 92fd3bf..afcc452 100644 (file)
@@ -274,6 +274,48 @@ bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const s
   }
 }
 
+bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const Property::Map& propertyMap )
+{
+  Property::Value* type = propertyMap.Find( RENDERER_TYPE_NAME );
+  std::string typeValue ;
+  if( type && type->Get( typeValue ))
+  {
+    //If there's been a renderer type change then we have to return a new shader
+    if( typeValue ==  COLOR_RENDERER && typeid( renderer ) != typeid( ColorRenderer ) )
+    {
+      renderer = GetControlRenderer( propertyMap );
+      return true;
+    }
+    else if( typeValue ==  GRADIENT_RENDERER && typeid( renderer ) != typeid( GradientRenderer ) )
+    {
+      renderer = GetControlRenderer( propertyMap );
+      return true;
+    }
+    else if( typeValue ==  IMAGE_RENDERER && typeid( renderer ) != typeid( ImageRenderer ) )
+    {
+      renderer = GetControlRenderer( propertyMap );
+      return true;
+    }
+    else if( typeValue ==  N_PATCH_RENDERER && typeid( renderer ) != typeid( NPatchRenderer ) )
+    {
+      renderer = GetControlRenderer( propertyMap );
+      return true;
+    }
+    else if( typeValue ==  BORDER_RENDERER && typeid( renderer ) != typeid( BorderRenderer ) )
+    {
+      renderer = GetControlRenderer( propertyMap );
+      return true;
+    }
+  }
+
+  if( !mFactoryCache )
+  {
+    mFactoryCache = new RendererFactoryCache();
+  }
+  GetImplementation( renderer ).Initialize( *( mFactoryCache.Get() ), propertyMap );
+  return false;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 4ed7e7f..99ef2b8 100644 (file)
@@ -52,7 +52,12 @@ public:
   /**
    * @copydoc Toolkit::RenderFactory::GetControlRenderer( const Property::Map& )
    */
-  Toolkit::ControlRenderer GetControlRenderer( const Property::Map& propertyMap  );
+  Toolkit::ControlRenderer GetControlRenderer( const Property::Map& propertyMap );
+
+  /**
+   * @copydoc Toolkit::RenderFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const Property::Map& propertyMap )
+   */
+  bool ResetRenderer( Toolkit::ControlRenderer& renderer, const Property::Map& propertyMap );
 
   /**
    * @copydoc Toolkit::RenderFactory::GetControlRenderer( const Vector4& )
index 6c8c9b7..9ecd378 100644 (file)
@@ -13,6 +13,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/builder/tree-node-manipulator.cpp \
    $(toolkit_src_dir)/builder/replacement.cpp \
    $(toolkit_src_dir)/controls/renderers/control-renderer-impl.cpp \
+   $(toolkit_src_dir)/controls/renderers/control-renderer-data-impl.cpp \
    $(toolkit_src_dir)/controls/renderers/renderer-factory-cache.cpp \
    $(toolkit_src_dir)/controls/renderers/renderer-factory-impl.cpp \
    $(toolkit_src_dir)/controls/renderers/border/border-renderer.cpp \