Merge "Stop using ImageActor in PageTurnView" into devel/master
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 12 Apr 2016 15:13:39 +0000 (08:13 -0700)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Tue, 12 Apr 2016 15:13:39 +0000 (08:13 -0700)
14 files changed:
automated-tests/src/dali-toolkit/utc-Dali-PageTurnView.cpp
dali-toolkit/internal/controls/page-turn-view/page-turn-book-spine-effect.h
dali-toolkit/internal/controls/page-turn-view/page-turn-effect.cpp
dali-toolkit/internal/controls/page-turn-view/page-turn-effect.h
dali-toolkit/internal/controls/page-turn-view/page-turn-landscape-view-impl.cpp
dali-toolkit/internal/controls/page-turn-view/page-turn-landscape-view-impl.h
dali-toolkit/internal/controls/page-turn-view/page-turn-portrait-view-impl.cpp
dali-toolkit/internal/controls/page-turn-view/page-turn-portrait-view-impl.h
dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.cpp
dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.h
dali-toolkit/internal/controls/renderers/image/image-renderer.cpp
dali-toolkit/internal/controls/renderers/renderer-factory-cache.cpp
dali-toolkit/internal/controls/renderers/renderer-factory-cache.h
dali-toolkit/public-api/controls/page-turn-view/page-factory.h

index cb6eefa..1142c4c 100644 (file)
@@ -21,6 +21,7 @@
 #include <sstream>
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali/integration-api/events/pan-gesture-event.h>
+#include <dali/public-api/images/buffer-image.h>
 #include <dali-toolkit/public-api/controls/page-turn-view/page-factory.h>
 #include <dali-toolkit/public-api/controls/page-turn-view/page-turn-landscape-view.h>
 #include <dali-toolkit/public-api/controls/page-turn-view/page-turn-portrait-view.h>
@@ -193,7 +194,6 @@ public:
   TestPageFactory(ToolkitTestApplication& application)
   : mApplication( application )
   {
-    mSourceActors.resize(TOTAL_PAGE_NUMBER);
     mTotalPageNumber = TOTAL_PAGE_NUMBER;
   }
 
@@ -207,40 +207,17 @@ public:
   }
 
   /**
-   * Create an image actor to represent a page.
+   * Create an image to represent a page content.
    * @param[in] pageId The ID of the page to create.
-   * @return An image actor, or an uninitialized pointer if the ID is out of range.
+   * @return An image, or an empty handle if the ID is out of range.
    */
-  virtual Actor NewPage( unsigned int pageId )
+  virtual Image NewPage( unsigned int pageId )
   {
-    if(!mSourceActors[pageId])
-    {
-      Actor actor = CreateSolidColorImageActor(mApplication, Color::BLUE,IMAGE_WIDTH,IMAGE_HEIGHT);
-      actor.SetName( static_cast<std::ostringstream*>( &(std::ostringstream() << pageId) )->str()  );
-
-      actor.SetParentOrigin( ParentOrigin::CENTER );
-      actor.SetAnchorPoint( AnchorPoint::CENTER );
-
-      ImageActor backPageActor = CreateSolidColorImageActor(mApplication, Color::BLUE,IMAGE_WIDTH,IMAGE_HEIGHT);
-      backPageActor.SetParentOrigin( ParentOrigin::CENTER );
-      backPageActor.SetAnchorPoint( AnchorPoint::CENTER );
-      actor.Add( backPageActor );
-
-      mSourceActors[pageId] = actor;
-    }
-
-    return mSourceActors[pageId];
-  }
-
-  void DeletePage( unsigned int pageId )
-  {
-    mSourceActors.erase( mSourceActors.begin() + pageId );
-    mTotalPageNumber--;
+    return BufferImage::WHITE();
   }
 
 private:
   ToolkitTestApplication& mApplication;
-  std::vector<Actor>      mSourceActors;
   unsigned int            mTotalPageNumber;
 };
 
@@ -706,3 +683,11 @@ int UtcDaliPageTurnLanscapeViewSignals(void)
   DALI_TEST_EQUALS( landscapeView.GetProperty(PageTurnView::Property::CURRENT_PAGE_ID).Get<int>(), 0, TEST_LOCATION );
   END_TEST;
 }
+
+int UtcDaliPageImageFactoryGetExtention(void)
+{
+  ToolkitTestApplication application;
+  TestPageFactory factory(application);
+  DALI_TEST_CHECK( factory.GetExtension() == NULL );
+  END_TEST;
+}
index efe112c..f9e87fb 100644 (file)
@@ -18,8 +18,7 @@
  *
  */
 
-// EXTERNAL INCLUDES
-#include <dali/public-api/shader-effects/shader-effect.h>
+#define DALI_COMPOSE_SHADER(STR) #STR
 
 namespace Dali
 {
@@ -42,50 +41,68 @@ namespace Internal
  *
  * Animatable/Constrainable uniforms:
  *  "uSpineShadowParameter" - The two parameters are the major&minor radius (in pixels) to form an ellipse shape. The top-left
- *                            quarter of this ellipse is used to calculate spine normal for simulating shadow
- *  "uIsBackImageVisible"   - Set whether the current page is with its backside visible. Need to pass the parameter as true for
- *                            the page which is turned over but still visible in Landscape
- *  "uPageWidth"            - The page width of the PageTurnBookSpineEffect
+ *                            quarter of this ellipse is used to calculate spine normal for simulating shadow *
+ *  "uTextureWidth" - 1.0 for single sided page,
+ *                    2.0 for double sided image which has left half part as page front side and right half part as page back side.
  *
- * @return A handle to a newly allocated ShaderEffect
+ * @return The newly created Property::Map with the page turn book spine effect
  **/
-inline ShaderEffect CreatePageTurnBookSpineEffect()
+inline Property::Map CreatePageTurnBookSpineEffect()
 {
+  const char* vertexSource = DALI_COMPOSE_SHADER(
+      precision mediump float;\n
+      attribute mediump vec2 aPosition;\n
+      uniform mediump mat4 uMvpMatrix;\n
+      uniform vec3 uSize;\n
+      uniform float uTextureWidth;\n
+      varying vec2 vTexCoord;\n
+      void main()\n
+      {\n
+        mediump vec4 vertexPosition = vec4(aPosition*uSize.xy, 0.0, 1.0);\n
+        gl_Position = uMvpMatrix * vertexPosition;\n
+        vTexCoord = aPosition + vec2(0.5);\n
+        vTexCoord.x /= uTextureWidth;
+      }\n);
+
   // the simplified version of the fragment shader of page turn effect
-  std::string fragmentSource = DALI_COMPOSE_SHADER(
+  const char* fragmentSource = DALI_COMPOSE_SHADER(
       precision mediump float;\n
-      uniform float uIsBackImageVisible;\n
-      uniform float uPageWidth;\n
+      varying mediump vec2 vTexCoord;\n
+      uniform vec3 uSize;\n
       uniform vec2 uSpineShadowParameter;\n
+      uniform sampler2D sTexture;\n
+      uniform lowp vec4 uColor;\n
+
       void main()\n
       {\n
-      // flip the image horizontally by changing the x component of the texture coordinate
-        if( uIsBackImageVisible == 1.0 )\n
-          gl_FragColor = texture2D( sTexture, vec2( sTextureRect.p+sTextureRect.s-vTexCoord.x, vTexCoord.y ) ) * uColor; \n
-        else\n
-        gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
-      // display book spine, a stripe of shadowed texture
-        float pixelPos = (vTexCoord.x-sTextureRect.s)*uPageWidth; \n
-        if(pixelPos < uSpineShadowParameter.x) \n
+        if( gl_FrontFacing )\n // display front side
+        {\n
+          gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
+        }\n
+        else\n // display back side, flip the image horizontally by changing the x component of the texture coordinate
+        {\n
+          gl_FragColor = texture2D( sTexture, vec2( 1.0 - vTexCoord.x, vTexCoord.y ) ) * uColor;\n
+        }\n
+        // display book spine, a stripe of shadowed texture
+        float pixelPos = vTexCoord.x * uSize.x;\n
+        if( pixelPos < uSpineShadowParameter.x )\n
         {\n
           float x = pixelPos - uSpineShadowParameter.x;\n
           float y = sqrt( uSpineShadowParameter.x*uSpineShadowParameter.x - x*x );\n
           vec2 spineNormal = normalize(vec2(uSpineShadowParameter.y*x/uSpineShadowParameter.x, y));\n
           gl_FragColor.rgb *= spineNormal.y; \n
-        }
+        }\n
       } );
 
-  const Vector2 DEFAULT_SPINE_SHADOW_PARAMETER(50.0f, 20.0f);
-
-  ShaderEffect shaderEffect = ShaderEffect::New( "", fragmentSource );
+  Property::Map map;
 
-  shaderEffect.SetUniform( "uIsBackImageVisible", -1.f );
-  shaderEffect.SetUniform( "uSpineShadowParameter", DEFAULT_SPINE_SHADOW_PARAMETER );
+  Property::Map customShader;
 
-  float defaultPageWidth = Dali::Stage::GetCurrent().GetSize().x;
-  shaderEffect.SetUniform( "uPageWidth", defaultPageWidth );
+  customShader[ "vertexShader" ] = vertexSource;
+  customShader[ "fragmentShader" ] = fragmentSource;
 
-  return shaderEffect;
+  map[ "shader" ] = customShader;
+  return map;
 }
 
 } //namespace Internal
index f4ada4f..f4d1126 100644 (file)
  *
  */
 
+//EXTERNAL INCLUDES
+#include <string.h>
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/object/property-map.h>
+
+//INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/page-turn-view/page-turn-effect.h>
-#include <dali/public-api/math/matrix.h>
 
 using namespace Dali;
 using namespace Dali::Toolkit;
 
-void CommonParametersConstraint( Dali::Matrix& current, const PropertyInputContainer& inputs )
+namespace
 {
-  const Vector2& originalCenter = inputs[0]->GetVector2();
-  Vector2 currentCenter = inputs[1]->GetVector2();
-  const Vector2& pageSize = inputs[2]->GetVector2();
+#define DALI_COMPOSE_SHADER(STR) #STR
+const char * const PROPERTY_COMMON_PARAMETERS( "uCommonParameters" );
+const char * const PROPERTY_ORIGINAL_CENTER( "originalCenter" );
+const char * const PROPERTY_CURRENT_CENTER( "currentCenter" );
+}
 
-  // calculate the curve direction and the vanishing point
-  // here, the vanishing point is the intersection of spine with the line passing through original center and vertical to curve direction
-  Vector2 curveDirection( currentCenter - originalCenter );
-  curveDirection.Normalize();
-  if( fabs(curveDirection.y) < 0.01f) // eliminate the possibility of division by zero in the next step
-  {
-    curveDirection.y = 0.01f;
-  }
-  float vanishingPointY = originalCenter.y + curveDirection.x * originalCenter.x / curveDirection.y;
+/**
+ * This constraint updates the common parameter values used by every vertex.
+ * By using constraint, they are calculate once in CPU then pass into the vertex shader as uniforms
+ */
+struct CommonParametersConstraint
+{
+  CommonParametersConstraint( float pageHeight )
+  : mPageHeight( pageHeight )
+  {}
 
-  float curveEndY, cosTheta ,sinTheta ,translateX, translateY;
-  // when the vanishing point is very far away, make it infinitely, in this case, the page bent horizontally
-  const float THRESHOLD(20.0);
-  if( fabs(vanishingPointY-pageSize.y*0.5f) >= pageSize.y*THRESHOLD )
+  void operator()( Dali::Matrix& current, const PropertyInputContainer& inputs )
   {
-    curveDirection = Vector2(-1.f,0.f);
-    currentCenter.y = originalCenter.y;
+    const Vector2& originalCenter = inputs[0]->GetVector2();
+    Vector2 currentCenter = inputs[1]->GetVector2();
 
-    curveEndY = originalCenter.y;
-    cosTheta = 1.f;
-    sinTheta = 0.f;
-    translateX = currentCenter.x - originalCenter.x;
-    translateY = vanishingPointY;
-  }
-  else
-  {
-    curveEndY = currentCenter.y - curveDirection.y * (currentCenter.x/curveDirection.x) ;
-    Vector2 v1( currentCenter.x, currentCenter.y - vanishingPointY );
-    v1.Normalize();
-    Vector2 v2( originalCenter.x, originalCenter.y - vanishingPointY );
-    v2.Normalize();
-    cosTheta = v1.x*v2.x + v1.y*v2.y;
-    sinTheta = ( vanishingPointY > pageSize.y*0.5f ) ? sqrt(1.0-cosTheta*cosTheta) : -sqrt(1.0-cosTheta*cosTheta);
-    translateX = currentCenter.x - cosTheta*originalCenter.x - sinTheta*( originalCenter.y-vanishingPointY );
-    translateY = currentCenter.y + sinTheta*originalCenter.x - cosTheta*( originalCenter.y-vanishingPointY );
-  }
+    // calculate the curve direction and the vanishing point
+    // here, the vanishing point is the intersection of spine with the line passing through original center and vertical to curve direction
+    Vector2 curveDirection( currentCenter - originalCenter );
+    curveDirection.Normalize();
+    if( fabs(curveDirection.y) < 0.01f) // eliminate the possibility of division by zero in the next step
+    {
+      curveDirection.y = 0.01f;
+    }
+    float vanishingPointY = originalCenter.y + curveDirection.x * originalCenter.x / curveDirection.y;
 
-  float originalLength = fabs(originalCenter.x/curveDirection.x);
-  float currentLength = fabs(currentCenter.x/curveDirection.x);
-  float curveHeight = 0.45f*sqrt(originalLength*originalLength - currentLength*currentLength);
+    float curveEndY, cosTheta ,sinTheta ,translateX, translateY;
+    // when the vanishing point is very far away, make it infinitely, in this case, the page bent horizontally
+    const float THRESHOLD(20.0);
+    if( fabs(vanishingPointY-mPageHeight*0.5f) >= mPageHeight*THRESHOLD )
+    {
+      curveDirection = Vector2(-1.f,0.f);
+      currentCenter.y = originalCenter.y;
 
-  float* parameterArray = current.AsFloat();
-  parameterArray[0] = cosTheta;
-  parameterArray[1] = -sinTheta;
-  parameterArray[2] = originalCenter.x;
-  parameterArray[3] = originalCenter.y;
-  parameterArray[4] = sinTheta;
-  parameterArray[5] = cosTheta;
-  parameterArray[6] = currentCenter.x;
-  parameterArray[7] = currentCenter.y;
-  parameterArray[8] = translateX;
-  parameterArray[9] = translateY;
-  parameterArray[10] = vanishingPointY;
-  parameterArray[11] = curveEndY;
-  parameterArray[12] = curveDirection.x;
-  parameterArray[13] = curveDirection.y;
-  parameterArray[14] = curveHeight;
-  parameterArray[15] = currentLength;
-}
+      curveEndY = originalCenter.y;
+      cosTheta = 1.f;
+      sinTheta = 0.f;
+      translateX = currentCenter.x - originalCenter.x;
+      translateY = vanishingPointY;
+    }
+    else
+    {
+      curveEndY = currentCenter.y - curveDirection.y * (currentCenter.x/curveDirection.x) ;
+      Vector2 v1( currentCenter.x, currentCenter.y - vanishingPointY );
+      v1.Normalize();
+      Vector2 v2( originalCenter.x, originalCenter.y - vanishingPointY );
+      v2.Normalize();
+      cosTheta = v1.x*v2.x + v1.y*v2.y;
+      sinTheta = ( vanishingPointY > mPageHeight*0.5f ) ? sqrt(1.0-cosTheta*cosTheta) : -sqrt(1.0-cosTheta*cosTheta);
+      translateX = currentCenter.x - cosTheta*originalCenter.x - sinTheta*( originalCenter.y-vanishingPointY );
+      translateY = currentCenter.y + sinTheta*originalCenter.x - cosTheta*( originalCenter.y-vanishingPointY );
+    }
+
+    float originalLength = fabs(originalCenter.x/curveDirection.x);
+    float currentLength = fabs(currentCenter.x/curveDirection.x);
+    float curveHeight = 0.45f*sqrt(originalLength*originalLength - currentLength*currentLength);
+
+    float* parameterArray = current.AsFloat();
+    parameterArray[0] = cosTheta;
+    parameterArray[1] = -sinTheta;
+    parameterArray[2] = originalCenter.x;
+    parameterArray[3] = originalCenter.y;
+    parameterArray[4] = sinTheta;
+    parameterArray[5] = cosTheta;
+    parameterArray[6] = currentCenter.x;
+    parameterArray[7] = currentCenter.y;
+    parameterArray[8] = translateX;
+    parameterArray[9] = translateY;
+    parameterArray[10] = vanishingPointY;
+    parameterArray[11] = curveEndY;
+    parameterArray[12] = curveDirection.x;
+    parameterArray[13] = curveDirection.y;
+    parameterArray[14] = curveHeight;
+    parameterArray[15] = currentLength;
+  }
+
+  float mPageHeight;
+};
 
-void Dali::Toolkit::Internal::PageTurnApplyInternalConstraint( ShaderEffect& shaderEffect)
+void Dali::Toolkit::Internal::PageTurnApplyInternalConstraint( Actor& actor, float pageHeight )
 {
-  Constraint constraint = Constraint::New<Dali::Matrix>( shaderEffect, shaderEffect.GetPropertyIndex( "uCommonParameters" ), CommonParametersConstraint );
-  constraint.AddSource( LocalSource( shaderEffect.GetPropertyIndex( "uOriginalCenter" ) ) );
-  constraint.AddSource( LocalSource( shaderEffect.GetPropertyIndex( "uCurrentCenter" ) ) );
-  constraint.AddSource( LocalSource( shaderEffect.GetPropertyIndex( "uPageSize" ) ) );
+  Constraint constraint = Constraint::New<Dali::Matrix>( actor, actor.GetPropertyIndex( PROPERTY_COMMON_PARAMETERS ) , CommonParametersConstraint( pageHeight ) );
+  constraint.AddSource( LocalSource( actor.GetPropertyIndex( PROPERTY_ORIGINAL_CENTER ) ) );
+  constraint.AddSource( LocalSource( actor.GetPropertyIndex( PROPERTY_CURRENT_CENTER ) ) );
   constraint.Apply();
 }
 
-ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
+Property::Map Dali::Toolkit::Internal::CreatePageTurnEffect()
 {
-  std::string vertexShader = DALI_COMPOSE_SHADER(
+  const char* vertexShader = DALI_COMPOSE_SHADER(
       /*
        * The common parameters for all the vertices, calculate in CPU then pass into the shader as uniforms
        *
@@ -117,17 +142,25 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
        * ([3][3]) float currentLength: The length from the current center to the curveEnd.
        */
       precision mediump float;\n
+      \n
+      attribute mediump vec2 aPosition;\n
+      \n
+      uniform mediump mat4 uMvpMatrix;\n
+      uniform mediump mat3 uNormalMatrix;\n
+      uniform mediump mat4 uModelView;\n
+      \n
       uniform mat4 uCommonParameters;\n
       \n
-      uniform vec2 uPageSize;\n
+      uniform vec3 uSize;\n
       uniform float uIsTurningBack;\n
+      uniform float uTextureWidth;\n
       varying vec3 vNormal;\n
       varying vec4 vPosition;\n
-      varying float vEdgeShadow;\n
+      varying mediump vec2 vTexCoord;\n
       \n
       void main()\n
       {\n
-        vec4 position = vec4( aPosition, 1.0);\n
+        vec4 position = vec4( aPosition*uSize.xy, 0.0, 1.0);\n
         vec2 currentCenter = vec2( uCommonParameters[1][2], uCommonParameters[1][3]);\n
         vec2 originalCenter = vec2( uCommonParameters[0][2], uCommonParameters[0][3]);\n
         vec3 normal = vec3(0.0,0.0,1.0);\n
@@ -135,7 +168,7 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
         if(currentCenter.x < originalCenter.x)\n
         {\n
           // change the coordinate origin from the center of the page to its top-left
-          position.xy += uPageSize * 0.5;\n
+          position.xy += uSize.xy * 0.5;\n
           vec2 curveDirection = vec2( uCommonParameters[3]);\n
           vec3 vanishingPoint = vec3(0.0, uCommonParameters[2][2], 0.0);\n
           // first part of the page, (outside the the line passing through original center and vertical to curve direction)
@@ -164,7 +197,7 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
             }\n
             \n
             // define the control points of hermite curve, composed with two segments
-            // calulation is carried out on the 2D plane which is passing through both current and original center and vertical to the image plane
+            // calculation is carried out on the 2D plane which is passing through both current and original center and vertical to the image plane
             float currentLength = uCommonParameters[3][3];\n
             float originalLength =  abs(originalCenter.x/curveDirection.x);\n
             float height = uCommonParameters[3][2];\n
@@ -178,7 +211,7 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
             vec2 SegmentTwoTangentVector0 = SegmentOneTangentVector1;\n
             vec2 SegmentTwoTangentVector1 = SegmentOneTangentVector1;\n
             \n
-            // calulate the corresponding curve point position and its tangent vector
+            // calculate the corresponding curve point position and its tangent vector
             // it is a linear mapping onto nonlinear curves, might cause some unwanted deformation
             // but as there are no analytical method to calculate the curve length on arbitrary segment
             // no efficient way to solve this nonlinear mapping, Numerical approximation would cost too much computation in shader
@@ -207,7 +240,7 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
               // a trick to eliminate some optical illusion caused by the gradient matter of normal in per-fragment shading
               // which is caused by linear interpolation of normal vs. nonlinear lighting
               // will notice some artifact in the areas with dramatically normal changes, so compress the normal differences here
-              tangent.y *=  min(1.0, length(position.xyz - vanishingPoint) / uPageSize.y ); \n
+              tangent.y *=  min(1.0, length(position.xyz - vanishingPoint) / uSize.y ); \n
             }\n
             vec3 curvePoint = vec3(curveEnd - curvePoint2D.x*curveDirection,max(0.0,curvePoint2D.y));\n
             vec3 tangentVector = vec3(-tangent.x*curveDirection,tangent.y);\n
@@ -244,69 +277,67 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
             normal.xy *= -uIsTurningBack;\n
           }\n
           // change the coordinate origin from the top-left of the page to its center
-          position.xy -= uPageSize * 0.5; \n
+          position.xy -= uSize.xy * 0.5; \n
         }\n
-        gl_Position = uMvpMatrix * position;\n
+        vNormal =  uNormalMatrix * normal;\n
+        gl_Position = uMvpMatrix * position;
         // varying parameters for fragment shader
-        vTexCoord = mix( sTextureRect.xy, sTextureRect.zw, aTexCoord );\n;
-        vNormal = uNormalMatrix*normal;\n
+        vTexCoord = aPosition + vec2(0.5);\n
+        vTexCoord.x /= uTextureWidth;
         vPosition = uModelView * position;\n
       }\n
   );
 
-  std::string fragmentShader = DALI_COMPOSE_SHADER(
+  const char* fragmentShader = DALI_COMPOSE_SHADER(
       precision mediump float;\n
-      uniform vec2 uPageSize;\n
+      \n
+      varying mediump vec2 vTexCoord;\n
+      \n
+      uniform sampler2D sTexture;\n
+      uniform lowp vec4 uColor;\n
+      uniform vec3 uSize;\n
       uniform vec2 uSpineShadowParameter;\n
       varying vec3 vNormal;\n
       varying vec4 vPosition;\n
-      varying float vEdgeShadow;\n
       \n
       void main()\n
       {\n
         // need to re-normalize the interpolated normal
-        vec3 normal = normalize(vNormal);\n
-        vec4 texel;\n
-        float spineShadowCoef = 1.0; \n
+        vec3 normal = normalize( vNormal );\n
         // display page content
+        vec4 texel;
         // display back image of the page, flip the texture
-        if(  dot(vPosition.xyz, normal) > 0.0 ) texel = texture2D( sTexture, vec2( sTextureRect.p+sTextureRect.s-vTexCoord.x, vTexCoord.y ) );\n
+        if(  dot(vPosition.xyz, normal) > 0.0 ) texel = texture2D( sTexture, vec2( 1.0 - vTexCoord.x, vTexCoord.y ) );\n
         // display front image of the page
         else texel = texture2D( sTexture, vTexCoord );\n
+
         // display book spine, a stripe of shadowed texture
-        float pixelPos = (vTexCoord.x-sTextureRect.s)*uPageSize.x; \n
-        if(pixelPos < uSpineShadowParameter.x) \n
+        float pixelPos = vTexCoord.x * uSize.x; \n
+        float spineShadowCoef = 1.0; \n
+        if( pixelPos < uSpineShadowParameter.x ) \n
         {\n
           float x = pixelPos - uSpineShadowParameter.x;\n
-          float y = sqrt( uSpineShadowParameter.x*uSpineShadowParameter.x - x*x);\n
+          float y = sqrt( uSpineShadowParameter.x*uSpineShadowParameter.x - x*x );\n
           spineShadowCoef = normalize( vec2( uSpineShadowParameter.y*x/uSpineShadowParameter.x, y ) ).y;\n
         }\n
         // calculate the lighting
         // set the ambient color as vec3(0.4);
         float lightColor = abs( normal.z ) * 0.6 + 0.4;\n
-        gl_FragColor = vec4( ( spineShadowCoef* lightColor)* texel.rgb , texel.a ) * uColor;\n
+        gl_FragColor = vec4( ( spineShadowCoef * lightColor ) * texel.rgb , texel.a ) * uColor;\n
       }
   );
 
-  // Create the implementation, temporarily owned on stack,
-  Dali::ShaderEffect shaderEffectCustom = Dali::ShaderEffect::New( vertexShader, fragmentShader,ShaderEffect::HINT_GRID );
-
-  static const Vector2 DEFAULT_SPINE_SHADOW_PARAMETER(50.0f, 20.0f);
-
-  Vector2 defaultPageSize = Dali::Stage::GetCurrent().GetSize();
-  Dali::Matrix zeroMatrix(true);
-  shaderEffectCustom.SetUniform( "uCommonParameters", zeroMatrix );
-  shaderEffectCustom.SetUniform( "uPageSize", defaultPageSize );
-  shaderEffectCustom.SetUniform( "uSpineShadowParameter", DEFAULT_SPINE_SHADOW_PARAMETER );
+  Property::Map map;
 
-  shaderEffectCustom.RegisterProperty( "uOriginalCenter", Vector2( defaultPageSize[0], defaultPageSize[1]*0.5f ) );
-  shaderEffectCustom.RegisterProperty( "uCurrentCenter", Vector2( defaultPageSize[0], defaultPageSize[1]*0.5f ) );
+  Property::Map customShader;
 
-  PageTurnApplyInternalConstraint(shaderEffectCustom);
+  customShader[ "vertexShader" ] = vertexShader;
+  customShader[ "fragmentShader" ] = fragmentShader;
+  customShader[ "subdivideGridX" ] = 20;
+  customShader[ "subdivideGridY" ] = 20;
 
-  // setting isTurningBack to -1.0f here means turning page forward
-  shaderEffectCustom.SetUniform( "uIsTurningBack", -1.0f );
+  map[ "shader" ] = customShader;
+  return map;
 
-  return shaderEffectCustom;
 }
 
index 59a4603..1025d2d 100644 (file)
  */
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/animation/constraint.h>
-#include <dali/public-api/common/stage.h>
-#include <dali/public-api/object/property-input.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
-#include <sstream>
 
 namespace Dali
 {
@@ -37,15 +32,16 @@ namespace Internal
 
 /**
  * @brief Re-applies PageTurnEffect internal constraints
- * The internal constraint uses the OriginalCenter property and the CurrentCenter Property
+ * The internal constraint uses the OriginalCenter property and the CURRENT_CENTER Property
  * to update the variety of common parameters which are with the same value for all the vertices.
  * Note: For each actor, the constraints are applied in the same order as the calls to Actor::ApplyConstraint().
- * So if there are other contraints applied to the OriginalCenter or CurrentCenter while when using this effect,
+ * So if there are other contraints applied to the ORIGINAL_CENTER or CURRENT_CENTER while when using this effect,
  * call this method to get the internal constraints and re-apply it afterwards.
  *
- * @param[in] shaderEffect The page turn effect to which internal constraints should be re-applied
+ * @param[in] actor The page turn actor to which internal constraints should be re-applied
+ * @param[in] pageHeight The page height.
  */
-void PageTurnApplyInternalConstraint( ShaderEffect& shaderEffect);
+void PageTurnApplyInternalConstraint( Actor& actor, float pageHeight );
 
 /**
  * @brief Create a new PageTurnEffect
@@ -54,33 +50,33 @@ void PageTurnApplyInternalConstraint( ShaderEffect& shaderEffect);
  * Usage example:-
  *
  * // create shader used for doing page-turn effect\n
- * ShaderEffect pageTurnEffect = CreatePageTurnEffect();
+ * Property::Map pageTurnEffect = CreatePageTurnEffect();
  *
- * // set image actor shader to the page-turn one\n
+ * // set image view custom shader to the page-turn one\n
  * // for portrait view, one image actor for each page\n
  * // for landscape view, the page turned over is still visible, so back image is needed \n
  * //     in this case, create another image Actor using the back image and added to the page actor \n
- * ImageActor pageActor = ImageActor::New(....); \n
- * ImageActor backImageActor = ImageActor::New(....); \n
- * pageActor.Add(backPageActor);\n
- * pageActor.SetShaderEffect ( pageTurnEffect ); \n
+ * ImageView page = ImageView::New(....); \n
+ * page.SetProperty ( ImageView::Property::IMAGE, pageTurnEffect ); \n
  *
  * //set initial values
- * pageTurnEffect.SetUniform("uPageSize", Vector2);\n
- * pageTurnEffect.SetUniform("uOriginalCenter", Vector2);\n
- * pageTurnEffect.SetUniform("uIsTurningBack", bool);\n
- * pageTurnEffect.SetUniform("uCurrentCenter",Vector2);\n
+ * page.SetProperty( page.GetPropertyIndex("uIsTurningBack",) bool );\n
+ * page.SetProperty( page.GetPropertyIndex("uSpineShadowParameter",) Vector2 );\n
+ * page.SetProperty( page.GetPropertyIndex("ORIGINAL_CENTER"), Vector2 );\n
+ * page.SetProperty( page.GetPropertyIndex("CURRENT_CENTER"), Vector2 );\n
+ * page.SetProperty( page.GetPropertyIndex("uCommonParameters"), Matrix );\n
+ * page.SetProperty( page.GetPropertyIndex("uTextureWidth"), float ); // Set to 1.0 for single-sided or 2.0 for double-sided \n
+ * PageTurnApplyInternalConstraint( page );\n
  *
  * //Animate it with the current center property\n
- * Animation animation[mAnimationIndex] = Animation::New( ... );\n
- * animation.AnimateTo(Property( pageTurnEffect, "uCurrentCenter" ),
- *                            currentCenter,
- *                            AlphaFunction::...);\n
- * animation[mAnimationIndex].Play(); \n
+ * Animation animation = Animation::New( ... );\n
+ * animation.AnimateTo(Property( page, "CURRENT_CENTER" ),
+ *                               currentCenter,
+ *                               AlphaFunction::...);\n
+ * animation.Play(); \n
  *
- * Animatable/Constrainable uniforms:
  */
-ShaderEffect CreatePageTurnEffect();
+Property::Map CreatePageTurnEffect();
 
 } // namespace Internal
 
index df0db93..bbaf508 100644 (file)
@@ -34,7 +34,6 @@ namespace Internal
 
 namespace
 {
-using namespace Dali;
 
 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::PageTurnLandscapeView, Toolkit::PageTurnView, NULL )
 DALI_TYPE_REGISTRATION_END()
@@ -66,33 +65,22 @@ Toolkit::PageTurnLandscapeView PageTurnLandscapeView::New( PageFactory& pageFact
 
 void PageTurnLandscapeView::OnPageTurnViewInitialize()
 {
+  mTurnEffectShader.RegisterProperty(PROPERTY_TEXTURE_WIDTH, 2.f );
+  mSpineEffectShader.RegisterProperty(PROPERTY_TEXTURE_WIDTH, 2.f );
+
   mControlSize = Vector2( mPageSize.width * 2.f,  mPageSize.height  );
   Self().SetSize( mControlSize );
   mTurningPageLayer.SetParentOrigin( ParentOrigin::CENTER );
 }
 
-void PageTurnLandscapeView::OnAddPage( ImageActor newPage, bool isLeftSide )
+void PageTurnLandscapeView::OnAddPage( Actor newPage, bool isLeftSide )
 {
   newPage.SetParentOrigin( ParentOrigin::CENTER );
-  SetCullFace( newPage, CullBack );
-
-  if( 0 < newPage.GetChildCount() )
-  {
-     ImageActor backImage = ImageActor::DownCast( newPage.GetChildAt( 0 ) );
-     backImage.SetParentOrigin( ParentOrigin::CENTER );
-     backImage.SetSize( mPageSize );
-     SetCullFace( backImage, CullFront );
-     backImage.SetZ( 0.25f * STATIC_PAGE_INTERVAL_DISTANCE );
-  }
-  if( isLeftSide )
-  {
-    SetShaderEffect( newPage, mSpineEffectBack );
-  }
 }
 
 Vector2 PageTurnLandscapeView::SetPanPosition( const Vector2& gesturePosition )
 {
-  if( mIsTurnBack[mPanActor] )
+  if( mPages[mIndex].isTurnBack )
   {
     return Vector2( mPageSize.width - gesturePosition.x, gesturePosition.y );
   }
@@ -104,31 +92,17 @@ Vector2 PageTurnLandscapeView::SetPanPosition( const Vector2& gesturePosition )
 
 void PageTurnLandscapeView::SetPanActor( const Vector2& panPosition )
 {
-  if( panPosition.x > mPageSize.width  && mCurrentPageIndex < mTotalPageCount-1 )
+  if( panPosition.x > mPageSize.width  && mCurrentPageIndex < mTotalPageCount )
   {
-    mPanActor = mPageActors[mCurrentPageIndex%NUMBER_OF_CACHED_PAGES]; // right side page
     mTurningPageIndex = mCurrentPageIndex;
   }
   else if( panPosition.x <= mPageSize.width && mCurrentPageIndex > 0 )
   {
-    mPanActor = mPageActors[ (mCurrentPageIndex-1)%NUMBER_OF_CACHED_PAGES ]; // left side page
     mTurningPageIndex = mCurrentPageIndex - 1;
   }
   else
   {
-    mPanActor.Reset();
-  }
-}
-
-void PageTurnLandscapeView::SetSpineEffect(ImageActor actor, bool isLeftSide)
-{
-  if(isLeftSide)
-  {
-    SetShaderEffect( actor, mSpineEffectBack );
-  }
-  else
-  {
-    SetShaderEffect( actor, mSpineEffectFront );
+    mTurningPageIndex = -1;
   }
 }
 
index 2033649..6f29d67 100644 (file)
@@ -36,15 +36,16 @@ class PageTurnLandscapeView : public PageTurnView
 public:
 
   /**
-   * Create a new PageTurnLandscapeView
-   * @return A handle to the newly allocated PageTurnLandscapeView
+   * @copydoc Toolkit::PageTurnLandscapeView::New( PageFactory&, const Vector2& )
    */
   static Toolkit::PageTurnLandscapeView New( PageFactory& pageFactory, const Vector2& pageSize );
 
 protected:
   /**
    * Constructor.
-   * It initializes the PageTurnLandscapeView members
+   * It initializes the PageTurnPortraitView members
+   * @param[in] pageFactory The factory which provides image actors to PageTurnView as the page content.
+   * @param[in] pageSize The size of the page
    */
   PageTurnLandscapeView( PageFactory& pageFactory, const Vector2& pageSize );
 
@@ -63,7 +64,7 @@ protected: // From PageTurnView
   /**
    * @copydoc PageTurnView::OnAddPage
    */
-  virtual void OnAddPage( ImageActor newPage, bool isLeftSide );
+  virtual void OnAddPage( Actor newPage, bool isLeftSide );
 
   /**
    * @copydoc PageTurnView::SetPanPosition
@@ -75,11 +76,6 @@ protected: // From PageTurnView
    */
   virtual void SetPanActor( const Vector2& panPosition );
 
-  /**
-   * @copydoc PageTurnView::SetSpineEffect
-   */
-  virtual void SetSpineEffect(ImageActor actor, bool isLeftSide);
-
 private:
 
   //Undefined
index 9fe3a00..45d3d98 100644 (file)
@@ -38,8 +38,6 @@ namespace Internal
 
 namespace
 {
-using namespace Dali;
-
 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::PageTurnPortraitView, Toolkit::PageTurnView, NULL )
 DALI_TYPE_REGISTRATION_END()
 
@@ -54,7 +52,6 @@ const float PAGE_TURN_OVER_ANIMATION_DURATION(0.5f);
 PageTurnPortraitView::PageTurnPortraitView( PageFactory& pageFactory, const Vector2& pageSize )
 : PageTurnView( pageFactory, pageSize )
 {
-
 }
 
 PageTurnPortraitView::~PageTurnPortraitView()
@@ -78,6 +75,9 @@ Toolkit::PageTurnPortraitView PageTurnPortraitView::New( PageFactory& pageFactor
 
 void PageTurnPortraitView::OnPageTurnViewInitialize()
 {
+  mTurnEffectShader.RegisterProperty(PROPERTY_TEXTURE_WIDTH, 1.f );
+  mSpineEffectShader.RegisterProperty(PROPERTY_TEXTURE_WIDTH, 1.f );
+
   mControlSize = mPageSize;
   Self().SetSize( mPageSize );
   mTurningPageLayer.SetParentOrigin( ParentOrigin::CENTER_LEFT );
@@ -92,24 +92,11 @@ void PageTurnPortraitView::SetPanActor( const Vector2& panPosition )
 {
   if( mCurrentPageIndex < mTotalPageCount )
   {
-    mPanActor = mPageActors[mCurrentPageIndex%NUMBER_OF_CACHED_PAGES];
     mTurningPageIndex = mCurrentPageIndex;
   }
   else
   {
-    mPanActor.Reset();
-  }
-}
-
-void PageTurnPortraitView::SetSpineEffect(ImageActor actor, bool isLeftSide)
-{
-  if(isLeftSide)
-  {
-    actor.RemoveShaderEffect();
-  }
-  else
-  {
-    actor.SetShaderEffect( mSpineEffectFront );
+    mTurningPageIndex = -1;
   }
 }
 
@@ -119,7 +106,8 @@ void PageTurnPortraitView::OnPossibleOutwardsFlick( const Vector2& panPosition,
   // There is previous page and an outwards flick is detected
   if( mCurrentPageIndex > 0 && gestureSpeed > GESTURE_SPEED_THRESHOLD && offset.x > fabs( offset.y ))
   {
-    ImageActor actor = mPageActors[ (mCurrentPageIndex-1) % NUMBER_OF_CACHED_PAGES ];
+    int actorIndex = (mCurrentPageIndex-1) % NUMBER_OF_CACHED_PAGES;
+    Actor actor = mPages[ actorIndex ].actor;
     if(actor.GetParent() != Self())
     {
       return;
@@ -136,40 +124,34 @@ void PageTurnPortraitView::OnPossibleOutwardsFlick( const Vector2& panPosition,
     RemovePage( mCurrentPageIndex+NUMBER_OF_CACHED_PAGES_EACH_SIDE );
     AddPage( mCurrentPageIndex-NUMBER_OF_CACHED_PAGES_EACH_SIDE );
     OrganizePageDepth();
+    mPageUpdated = true;
 
-    mPageActors[mTurningPageIndex%NUMBER_OF_CACHED_PAGES].SetVisible(true);
+    actor.SetVisible(true);
 
     // Add the page to tuning page layer and set up PageTurnEffect
     mShadowView.Add( actor );
-    actor.SetShaderEffect( mTurnEffect[mIndex] );
-    PageTurnApplyInternalConstraint(mTurnEffect[mIndex]);
-    mIsAnimating[mIndex] = true;
-    mTurnEffect[mIndex].SetUniform("uIsTurningBack", 1.f );
+    mPages[actorIndex].UseEffect( mTurnEffectShader );
+    mAnimatingCount++;
     Vector2 originalCenter( mPageSize.width*1.5f, 0.5f*mPageSize.height );
-    mTurnEffect[mIndex].SetUniform("uOriginalCenter", originalCenter );
-    mTurnEffect[mIndex].SetUniform("uCurrentCenter", Vector2( mPageSize.width*0.5f, mPageSize.height*0.5f ) );
+    mPages[actorIndex].SetOriginalCenter( originalCenter );
+    mPages[actorIndex].SetCurrentCenter( Vector2( mPageSize.width*0.5f, mPageSize.height*0.5f ) );
+    PageTurnApplyInternalConstraint(actor, mPageSize.height);
 
     // Start an animation to turn the previous page back
     Animation animation = Animation::New( PAGE_TURN_OVER_ANIMATION_DURATION );
     mAnimationPageIdPair[animation] = mCurrentPageIndex;
-    mAnimationIndexPair[animation] = mIndex;
 
-    animation.AnimateTo( Property( mTurnEffect[mIndex], "uCurrentCenter" ),
+    animation.AnimateTo( Property( actor, mPages[actorIndex].propertyCurrentCenter ),
                          originalCenter,
                          AlphaFunction::EASE_OUT, TimePeriod(PAGE_TURN_OVER_ANIMATION_DURATION*0.75f) );
     animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), AngleAxis( Degree( 180.0f ), Vector3::YAXIS ) ,AlphaFunction::EASE_OUT );
     animation.Play();
 
-    ImageActor imageActor = ImageActor::DownCast(actor);
-    if( imageActor )
-    {
-      SetCullFace( imageActor, CullBack );
-    }
     animation.FinishedSignal().Connect( this, &PageTurnPortraitView::TurnedOverBackwards );
   }
 }
 
-void PageTurnPortraitView::OnTurnedOver( ImageActor actor, bool isLeftSide )
+void PageTurnPortraitView::OnTurnedOver( Actor actor, bool isLeftSide )
 {
   if( isLeftSide )
   {
@@ -179,11 +161,6 @@ void PageTurnPortraitView::OnTurnedOver( ImageActor actor, bool isLeftSide )
 
 void PageTurnPortraitView::TurnedOverBackwards( Animation& animation )
 {
-  ImageActor imageActor =  mPageActors[mAnimationPageIdPair[animation] % NUMBER_OF_CACHED_PAGES];
-  if( imageActor )
-  {
-    SetCullFace( imageActor, CullNone );
-  }
   TurnedOver( animation );
 }
 
index 0adb4e5..6fb4c62 100644 (file)
@@ -39,8 +39,7 @@ class PageTurnPortraitView : public PageTurnView
 public:
 
   /**
-   * Create a new PageTurnPortraitView
-   * @return A handle to the newly allocated PageTurnPortraitView
+   * @copydoc Toolkit::PageTurnPortraitView::New( PageFactory&, const Vector2& )
    */
   static Toolkit::PageTurnPortraitView New( PageFactory& pageFactory, const Vector2& pageSize );
 
@@ -49,6 +48,8 @@ protected:
   /**
    * Constructor.
    * It initializes the PageTurnPortraitView members
+   * @param[in] pageFactory The factory which provides image actors to PageTurnView as the page content.
+   * @param[in] pageSize The size of the page
    */
   PageTurnPortraitView( PageFactory& pageFactory, const Vector2& pageSize );
 
@@ -75,16 +76,14 @@ protected: // From PageTurnView
   virtual void SetPanActor( const Vector2& panPosition );
 
   /**
-   * @copydoc PageTurnView::SetSpineEffect
-   */
-  virtual void SetSpineEffect(ImageActor actor, bool isLeftSide);
-
-  /**
    * @copydoc PageTurnView::OnPossibleOutwardsFlick
    */
   virtual void OnPossibleOutwardsFlick( const Vector2& panPosition, float gestureSpeed );
 
-  virtual void OnTurnedOver( ImageActor actor, bool isLeftSide );
+  /**
+   * @copydoc PageTurnView::OnTurnedOver
+   */
+  virtual void OnTurnedOver( Actor actor, bool isLeftSide );
 
 private:
 
index 6db3956..19e8421 100644 (file)
 #include <cstring> // for strcmp
 #include <dali/public-api/animation/animation.h>
 #include <dali/public-api/animation/constraint.h>
-#include <dali/devel-api/events/hit-test-algorithm.h>
+#include <dali/public-api/images/resource-image.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/devel-api/object/type-registry-helper.h>
-#include <dali/public-api/render-tasks/render-task-list.h>
-#include <dali/devel-api/rendering/cull-face.h>
+#include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/page-turn-view/page-turn-effect.h>
 #include <dali-toolkit/internal/controls/page-turn-view/page-turn-book-spine-effect.h>
+#include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
+
+// headers needed for backward compatibility of PageFactory::NewPage(pageId) API
+#include <dali/public-api/actors/image-actor.h>
 
 using namespace Dali;
 
 namespace //Unnamed namespace
 {
-// default grid density for page turn effect, 10 pixels by 10 pixels
-const float DEFAULT_GRID_DENSITY(10.0f);
+// broken image is loaded if there is no valid image provided for the page
+const char * const BROKEN_IMAGE_URL( DALI_IMAGE_DIR "broken.png");
+
+// names of shader property map
+const char * const CUSTOM_SHADER( "shader" );
+const char * const CUSTOM_VERTEX_SHADER( "vertexShader" );
+const char * const CUSTOM_FRAGMENT_SHADER( "fragmentShader" );
+
+// name of the texture in material
+const char * const TEXTURE_NAME( "sTexture" );
+
+// properties set on shader, these properties have the constant value in regardless of the page status
+const char * const PROPERTY_SPINE_SHADOW ( "uSpineShadowParameter" ); // uniform for both spine and turn effect
+
+// properties set on actor, the value of these properties varies depending on the page status
+//    properties used in turn effect
+const char * const PROPERTY_TURN_DIRECTION( "uIsTurningBack" ); // uniform
+const char * const PROPERTY_COMMON_PARAMETERS( "uCommonParameters" ); //uniform
+
+const char * const PROPERTY_PAN_DISPLACEMENT( "panDisplacement" );// property used to constrain the uniforms
+const char * const PROPERTY_PAN_CENTER( "panCenter" );// property used to constrain the uniforms
+
+// default grid density for page turn effect, 20 pixels by 20 pixels
+const float DEFAULT_GRID_DENSITY(20.0f);
 
 // to bent the page, the minimal horizontal pan start position is pageSize.x * MINIMUM_START_POSITION_RATIO
 const float MINIMUM_START_POSITION_RATIO(0.6f);
@@ -163,7 +188,7 @@ struct CurrentCenterConstraint
       const Vector2& centerOrigin = inputs[1]->GetVector2();
       Vector2 direction = centerOrigin - Vector2(mThres, centerPosition.y);
       float coef = 1.f+(centerPosition.x*2.f / mPageWidth);
-      // Todo: when coef <= 0, the page is flat, slow down the last moment of the page stretch by 10 times to avoid a small bounce
+      // when coef <= 0, the page is flat, slow down the last moment of the page stretch by 10 times to avoid a small bounce
       if(coef < 0.025f)
       {
         coef = (coef+0.225f)/10.0f;
@@ -239,38 +264,115 @@ DALI_TYPE_REGISTRATION_END()
 }
 
 // these several constants are also used in the derived classes
+const char * const PageTurnView::PROPERTY_TEXTURE_WIDTH( "uTextureWidth" ); // uniform name
+const char * const PageTurnView::PROPERTY_ORIGINAL_CENTER( "originalCenter" ); // property used to constrain the uniform
+const char * const PageTurnView::PROPERTY_CURRENT_CENTER( "currentCenter" );// property used to constrain the uniform
 const int PageTurnView::MAXIMUM_TURNING_NUM = 4;
 const int PageTurnView::NUMBER_OF_CACHED_PAGES_EACH_SIDE = MAXIMUM_TURNING_NUM + 1;
 const int PageTurnView::NUMBER_OF_CACHED_PAGES = NUMBER_OF_CACHED_PAGES_EACH_SIDE*2;
 const float PageTurnView::STATIC_PAGE_INTERVAL_DISTANCE = 1.0f;
 
+PageTurnView::Page::Page()
+: isTurnBack( false )
+{
+  actor = Actor::New();
+  actor.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
+  actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
+  actor.SetVisible( false );
+
+  propertyPanDisplacement = actor.RegisterProperty( PROPERTY_PAN_DISPLACEMENT, 0.f );
+  propertyPanCenter = actor.RegisterProperty(PROPERTY_PAN_CENTER, Vector2::ZERO);
+
+  propertyOriginalCenter = actor.RegisterProperty(PROPERTY_ORIGINAL_CENTER, Vector2::ZERO);
+  propertyCurrentCenter = actor.RegisterProperty(PROPERTY_CURRENT_CENTER, Vector2::ZERO);
+  Matrix zeroMatrix(true);
+  actor.RegisterProperty(PROPERTY_COMMON_PARAMETERS, zeroMatrix);
+  propertyTurnDirection = actor.RegisterProperty(PROPERTY_TURN_DIRECTION, -1.f);
+}
+
+void PageTurnView::Page::SetImage( Image image  )
+{
+  if( material.GetNumberOfTextures() > 0  )
+  {
+    material.SetTextureImage( 0u, image );
+  }
+  else
+  {
+    material.AddTexture(image, TEXTURE_NAME);
+  }
+}
+
+void PageTurnView::Page::UseEffect(Shader shader)
+{
+  if( material )
+  {
+    material.SetShader( shader );
+  }
+  else
+  {
+    material = Material::New( shader );
+  }
+}
+
+void PageTurnView::Page::UseEffect(Shader shader, Geometry geometry)
+{
+  UseEffect( shader );
+
+  if( !renderer )
+  {
+    renderer = Renderer::New( geometry, material );
+    actor.AddRenderer( renderer );
+  }
+}
+
+void PageTurnView::Page::ChangeTurnDirection()
+{
+  isTurnBack = !isTurnBack;
+  actor.SetProperty( propertyTurnDirection, isTurnBack ? 1.f : -1.f );
+}
+
+void PageTurnView::Page::SetPanDisplacement(float value)
+{
+ actor.SetProperty( propertyPanDisplacement, value );
+}
+
+void PageTurnView::Page::SetPanCenter( const Vector2& value )
+{
+  actor.SetProperty( propertyPanCenter, value );
+}
+
+void PageTurnView::Page::SetOriginalCenter( const Vector2& value )
+{
+  actor.SetProperty( propertyOriginalCenter, value );
+}
+
+void PageTurnView::Page::SetCurrentCenter( const Vector2& value )
+{
+  actor.SetProperty( propertyCurrentCenter, value );
+}
+
 PageTurnView::PageTurnView( PageFactory& pageFactory, const Vector2& pageSize )
 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
-  mPageFactory( pageFactory ),
+  mPageFactory( &pageFactory ),
   mPageSize( pageSize ),
-  mTotalPageCount( 0 ),
-  mPanning( false ),
   mSpineShadowParameter( DEFAULT_SPINE_SHADOW_PARAMETER ),
+  mDistanceUpCorner( 0.f ),
+  mDistanceBottomCorner( 0.f ),
+  mPanDisplacement( 0.f ),
+  mTotalPageCount( 0 ),
   mCurrentPageIndex( 0 ),
   mTurningPageIndex( 0 ),
   mIndex( 0 ),
+  mSlidingCount( 0 ),
+  mAnimatingCount( 0 ),
+  mConstraints( false ),
   mPress( false ),
   mPageUpdated( true ),
-  mDistanceUpCorner( 0.f ),
-  mDistanceBottomCorner( 0.f ),
-  mPanDisplacement( 0.f ),
-  mConstraints( false ),
   mPageTurnStartedSignal(),
   mPageTurnFinishedSignal(),
   mPagePanStartedSignal(),
   mPagePanFinishedSignal()
 {
-  mPageActors.resize( NUMBER_OF_CACHED_PAGES );
-  mIsAnimating.resize( MAXIMUM_TURNING_NUM );
-  mIsSliding.resize( MAXIMUM_TURNING_NUM );
-  mTurnEffect.resize( MAXIMUM_TURNING_NUM );
-  mPropertyPanDisplacement.resize( MAXIMUM_TURNING_NUM );
-  mPropertyCurrentCenter.resize( MAXIMUM_TURNING_NUM );
 }
 
 PageTurnView::~PageTurnView()
@@ -279,58 +381,82 @@ PageTurnView::~PageTurnView()
 
 void PageTurnView::OnInitialize()
 {
-   // create the two book spine effect for static images, left and right side pages respectively
-  mSpineEffectFront = CreatePageTurnBookSpineEffect();
-  mSpineEffectFront.SetUniform("uIsBackImageVisible", -1.f );
-  mSpineEffectFront.SetUniform("uPageWidth", mPageSize.width );
-  mSpineEffectFront.SetUniform("uShadowWidth", 0.f );
-  mSpineEffectFront.SetUniform("uSpineShadowParameter", mSpineShadowParameter );
-
-  mSpineEffectBack = CreatePageTurnBookSpineEffect();
-  mSpineEffectBack.SetUniform("uIsBackImageVisible", 1.f );
-  mSpineEffectBack.SetUniform("uPageWidth", mPageSize.width );
-  mSpineEffectBack.SetUniform("uShadowWidth", 0.f );
-  mSpineEffectBack.SetUniform("uSpineShadowParameter", mSpineShadowParameter );
-
-  // create the page turn effect objects
-  for( int i = 0; i < MAXIMUM_TURNING_NUM; i++ )
+   // create the book spine effect for static pages
+  Property::Map spineEffectMap = CreatePageTurnBookSpineEffect();
+  mSpineEffectShader = CreateShader( spineEffectMap );
+  mSpineEffectShader.RegisterProperty(PROPERTY_SPINE_SHADOW, mSpineShadowParameter );
+  // create the turn effect for turning pages
+  Property::Map turnEffectMap = CreatePageTurnEffect();
+  mTurnEffectShader = CreateShader( turnEffectMap );
+  mTurnEffectShader.RegisterProperty(PROPERTY_SPINE_SHADOW, mSpineShadowParameter );
+
+  // create the grid geometry for pages
+  uint16_t width = static_cast<uint16_t>(mPageSize.width / DEFAULT_GRID_DENSITY + 0.5f);
+  uint16_t height = static_cast<uint16_t>(mPageSize.height / DEFAULT_GRID_DENSITY + 0.5f);
+  mGeometry = RendererFactoryCache::CreateGridGeometry( Uint16Pair( width, height ) );
+  mGeometry.SetRequiresDepthTesting( true );
+
+  mPages.reserve( NUMBER_OF_CACHED_PAGES );
+  for( int i = 0; i < NUMBER_OF_CACHED_PAGES; i++ )
   {
-    mTurnEffect[i] = CreatePageTurnEffect();
-    mTurnEffect[i].SetProperty( ShaderEffect::Property::GRID_DENSITY, Property::Value( DEFAULT_GRID_DENSITY ) );
-    mTurnEffect[i].SetUniform( "uPageSize", mPageSize );
-    mTurnEffect[i].SetUniform( "uShadowWidth", 0.f);
-    mTurnEffect[i].SetUniform( "uSpineShadowParameter", mSpineShadowParameter );
-    mIsAnimating[i] = false;
-    mIsSliding[i] = false;
-    mPropertyPanDisplacement[i] = Self().RegisterProperty("PAN_DISPLACEMENT_PROPERTY_"+i, 0.0f);
-    mPropertyCurrentCenter[i] = Self().RegisterProperty("CURRENT_CENTER_PROPERTY_"+i, Vector2(0.0f,0.0f));
+    mPages.push_back( Page() );
+    mPages[i].actor.SetSize( mPageSize );
+    Self().Add( mPages[i].actor );
   }
 
+  // create the layer for turning images
   mTurningPageLayer = Layer::New();
   mTurningPageLayer.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
   mTurningPageLayer.SetBehavior(Layer::LAYER_3D);
+  mTurningPageLayer.Raise();
 
   // Set control size and the parent origin of page layers
   OnPageTurnViewInitialize();
 
   Self().Add(mTurningPageLayer);
 
-  mTotalPageCount = static_cast<int>( mPageFactory.GetNumberOfPages() );
+  mTotalPageCount = static_cast<int>( mPageFactory->GetNumberOfPages() );
   // add pages to the scene, and set depth for the stacked pages
   for( int i = 0; i < NUMBER_OF_CACHED_PAGES_EACH_SIDE; i++ )
   {
     AddPage( i );
-    if(mPageActors[i])
-    {
-      mPageActors[i].SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
-    }
+    mPages[i].actor.SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
   }
-  mPageActors[0].SetVisible(true);
+  mPages[0].actor.SetVisible(true);
 
   // enable the pan gesture which is attached to the control
   EnableGestureDetection(Gesture::Type(Gesture::Pan));
 }
 
+Shader PageTurnView::CreateShader( const Property::Map& shaderMap )
+{
+  Shader shader;
+  Property::Value* shaderValue = shaderMap.Find( CUSTOM_SHADER );
+  Property::Map shaderSource;
+  if( shaderValue && shaderValue->Get( shaderSource ) )
+  {
+    std::string vertexShader;
+    Property::Value* vertexShaderValue = shaderSource.Find( CUSTOM_VERTEX_SHADER );
+    if( !vertexShaderValue || !vertexShaderValue->Get( vertexShader ) )
+    {
+      DALI_LOG_ERROR("PageTurnView::CreateShader failed: vertex shader source is not available.\n");
+    }
+    std::string fragmentShader;
+    Property::Value* fragmentShaderValue = shaderSource.Find( CUSTOM_FRAGMENT_SHADER );
+    if( !fragmentShaderValue || !fragmentShaderValue->Get( fragmentShader ) )
+    {
+      DALI_LOG_ERROR("PageTurnView::CreateShader failed: fragment shader source is not available.\n");
+    }
+    shader = Shader::New( vertexShader, fragmentShader );
+  }
+  else
+  {
+    DALI_LOG_ERROR("PageTurnView::CreateShader failed: shader source is not available.\n");
+  }
+
+  return shader;
+}
+
 void PageTurnView::SetupShadowView()
 {
   mShadowView = Toolkit::ShadowView::New( 0.25f, 0.25f );
@@ -362,31 +488,20 @@ void PageTurnView::OnStageConnection( int depth )
   Control::OnStageConnection( depth );
 
   SetupShadowView();
-  mTurningPageLayer.Raise();
 }
 
 void PageTurnView::OnStageDisconnection()
 {
   if(mShadowView)
   {
+    mShadowView.RemoveConstraints();
     mPointLight.Unparent();
     mShadowPlaneBackground.Unparent();
     mShadowView.Unparent();
   }
 
   // make sure the status of the control is updated correctly when the pan gesture is interrupted
-  if(mPanning)
-  {
-    mPanning = false;
-
-    Self().Add(mPanActor);
-    mIsAnimating[mIndex] = false;
-    mPanActor.RemoveConstraints();
-    mTurnEffect[mIndex].RemoveConstraints();
-    mPageUpdated = true;
-
-    SetSpineEffect( mPanActor, mIsTurnBack[mPanActor] );
-  }
+  StopTurning();
 
   Control::OnStageDisconnection();
 }
@@ -394,28 +509,15 @@ void PageTurnView::OnStageDisconnection()
 void PageTurnView::SetPageSize( const Vector2& pageSize )
 {
   mPageSize = pageSize;
-  mSpineEffectFront.SetUniform("uPageWidth", mPageSize.width );
-  mSpineEffectBack.SetUniform("uPageWidth", mPageSize.width );
-  for( int i = 0; i < MAXIMUM_TURNING_NUM; i++ )
-  {
-    mTurnEffect[i].SetUniform( "uPageSize", mPageSize );
-  }
 
   if( mPointLight )
   {
     mPointLight.SetPosition( 0.f, 0.f, mPageSize.width*POINT_LIGHT_HEIGHT_RATIO );
   }
 
-  for( size_t i=0; i<mPageActors.size(); i++ )
+  for( size_t i=0; i<mPages.size(); i++ )
   {
-    if( mPageActors[i] )
-    {
-      mPageActors[i].SetSize( mPageSize );
-      if( mPageActors[i].GetChildCount()>0 )
-      {
-        mPageActors[i].GetChildAt(0).SetSize( mPageSize );
-      }
-    }
+    mPages[i].actor.SetSize( mPageSize );
   }
 
   OnPageTurnViewInitialize();
@@ -436,12 +538,8 @@ void PageTurnView::SetSpineShadowParameter( const Vector2& spineShadowParameter
   mSpineShadowParameter = spineShadowParameter;
 
   // set spine shadow parameter to all the shader effects
-  mSpineEffectFront.SetUniform("uSpineShadowParameter", mSpineShadowParameter );
-  mSpineEffectBack.SetUniform("uSpineShadowParameter", mSpineShadowParameter );
-  for( int i = 0; i < MAXIMUM_TURNING_NUM; i++ )
-  {
-    mTurnEffect[i].SetUniform("uSpineShadowParameter", mSpineShadowParameter );
-  }
+  mSpineEffectShader.RegisterProperty(PROPERTY_SPINE_SHADOW, mSpineShadowParameter );
+  mTurnEffectShader.RegisterProperty(PROPERTY_SPINE_SHADOW, mSpineShadowParameter );
 }
 
 Vector2 PageTurnView::GetSpineShadowParameter()
@@ -458,18 +556,12 @@ void PageTurnView::GoToPage( unsigned int pageId )
     return;
   }
 
+  // if any animation ongoing, stop it.
+  StopTurning();
+
   // record the new current page index
   mCurrentPageIndex = pageIdx;
 
-  // clear the old pages
-  for(int i = 0; i < NUMBER_OF_CACHED_PAGES; i++ )
-  {
-    if( mPageActors[i] )
-    {
-      mPageActors[i].Unparent();
-      mPageActors[i].Reset();
-    }
-  }
 
   // add the current page and the pages right before and after it
   for( int i = pageIdx - NUMBER_OF_CACHED_PAGES_EACH_SIDE; i < pageIdx + NUMBER_OF_CACHED_PAGES_EACH_SIDE; i++ )
@@ -477,10 +569,10 @@ void PageTurnView::GoToPage( unsigned int pageId )
     AddPage( i );
   }
 
-  mPageActors[pageId%NUMBER_OF_CACHED_PAGES].SetVisible(true);
+  mPages[pageId%NUMBER_OF_CACHED_PAGES].actor.SetVisible(true);
   if( pageId > 0 )
   {
-    mPageActors[(pageId-1)%NUMBER_OF_CACHED_PAGES].SetVisible(true);
+    mPages[(pageId-1)%NUMBER_OF_CACHED_PAGES].actor.SetVisible(true);
   }
   // set ordered depth to the stacked pages
   OrganizePageDepth();
@@ -497,32 +589,30 @@ void PageTurnView::AddPage( int pageIndex )
   if(pageIndex > -1  && pageIndex < mTotalPageCount) // whether the page is available from the page factory
   {
     int index = pageIndex % NUMBER_OF_CACHED_PAGES;
-    ImageActor newPage= ImageActor::DownCast( mPageFactory.NewPage( pageIndex ) );
-     DALI_ASSERT_ALWAYS( newPage );
 
-    newPage.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
-    newPage.SetParentOrigin( ParentOrigin::CENTER_LEFT );
-    newPage.SetSize( mPageSize );
-    Self().Add( newPage );
-    mPageActors[index] = newPage;
+    Image newPageImage;
+    newPageImage = mPageFactory->NewPage( pageIndex );
 
-    bool isLeftSide = ( pageIndex < mCurrentPageIndex );
-    mIsTurnBack[ newPage ] = isLeftSide;
-    if( isLeftSide )
+    if( !newPageImage ) // load the broken image
     {
-      // new page is added to the left side, so need to rotate it 180 degrees
-      newPage.RotateBy( Degree(-180.0f ), Vector3::YAXIS );
+      newPageImage = ResourceImage::New( BROKEN_IMAGE_URL );
     }
-    else
+
+    bool isLeftSide = ( pageIndex < mCurrentPageIndex );
+    if( mPages[index].isTurnBack != isLeftSide )
     {
-      newPage.SetShaderEffect(mSpineEffectFront);
+      mPages[index].ChangeTurnDirection();
     }
 
-    newPage.SetVisible( false );
+    float degree = isLeftSide ? 180.f :0.f;
+    mPages[index].actor.SetOrientation( Degree( degree ), Vector3::YAXIS );
+    mPages[index].actor.SetVisible( false );
+    mPages[index].UseEffect( mSpineEffectShader, mGeometry );
+    mPages[index].SetImage( newPageImage );
 
     // For Portrait, nothing to do
-    // For Landscape, set spineEffectBack to the new effect if it is in the left side, and set properties to the back image actor if it exists
-    OnAddPage( newPage, isLeftSide );
+    // For Landscape, set the parent origin to CENTER
+     OnAddPage( mPages[index].actor, isLeftSide );
   }
 }
 
@@ -531,9 +621,7 @@ void PageTurnView::RemovePage( int pageIndex )
   if( pageIndex > -1 && pageIndex < mTotalPageCount)
   {
     int index = pageIndex % NUMBER_OF_CACHED_PAGES;
-    mPageActors[index].Unparent();
-    mIsTurnBack.erase( mPageActors[index] );
-    mPageActors[index].Reset();
+    mPages[index].actor.SetVisible(false);
   }
 }
 
@@ -544,38 +632,19 @@ void PageTurnView::OnPan( const PanGesture& gesture )
   {
     case Gesture::Started:
     {
-      mPanning = true;
-      // to find out whether the undergoing turning page number already reaches the maximum allowed
-      // and get one idle index when it is animatable
-      bool animatable = false;
-      for( int i = 0; i < MAXIMUM_TURNING_NUM; i++ )
-      {
-        if( !mIsAnimating[mIndex] )
-        {
-          animatable = true;
-          break;
-        }
-        if( mIsSliding[mIndex] )
-        {
-          animatable = false;
-          break;
-        }
-        mIndex++;
-        mIndex = mIndex % MAXIMUM_TURNING_NUM;
-      }
-
-      if( mPageUpdated && animatable )
+      // check whether the undergoing turning page number already reaches the maximum allowed
+      if( mPageUpdated && mAnimatingCount< MAXIMUM_TURNING_NUM && mSlidingCount < 1 )
       {
         SetPanActor( gesture.position ); // determine which page actor is panned
-        if(mPanActor && mPanActor.GetParent() != Self()) // if the page is added to turning layer,it is undergoing an animation currently
+        if( mTurningPageIndex != -1 && mPages[mTurningPageIndex % NUMBER_OF_CACHED_PAGES].actor.GetParent() != Self()) // if the page is added to turning layer,it is undergoing an animation currently
         {
-          mPanActor.Reset();
+          mTurningPageIndex = -1;
         }
         PanStarted( SetPanPosition( gesture.position ) );  // pass in the pan position in the local page coordinate
       }
       else
       {
-        mPanActor.Reset();
+        mTurningPageIndex = -1;
       }
       break;
     }
@@ -587,7 +656,6 @@ void PageTurnView::OnPan( const PanGesture& gesture )
     case Gesture::Finished:
     case Gesture::Cancelled:
     {
-      mPanning = false;
       PanFinished( SetPanPosition( gesture.position ), gesture.GetSpeed() );
       break;
     }
@@ -604,13 +672,14 @@ void PageTurnView::PanStarted( const Vector2& gesturePosition )
 {
   mPressDownPosition = gesturePosition;
 
-  if( !mPanActor )
+  if( mTurningPageIndex == -1 )
   {
     return;
   }
 
+  mIndex = mTurningPageIndex % NUMBER_OF_CACHED_PAGES;
+
   mOriginalCenter = gesturePosition;
-  mTurnEffect[mIndex].SetUniform("uIsTurningBack", mIsTurnBack[ mPanActor] ? 1.f : -1.f);
   mPress = false;
   mPageUpdated = false;
 
@@ -621,7 +690,7 @@ void PageTurnView::PanStarted( const Vector2& gesturePosition )
 
 void PageTurnView::PanContinuing( const Vector2& gesturePosition )
 {
-  if( !mPanActor )
+  if( mTurningPageIndex == -1  )
   {
     return;
   }
@@ -645,31 +714,31 @@ void PageTurnView::PanContinuing( const Vector2& gesturePosition )
     {
       mDistanceUpCorner = mOriginalCenter.Length();
       mDistanceBottomCorner = ( mOriginalCenter - Vector2( 0.0f, mPageSize.height ) ).Length();
-      mShadowView.Add( mPanActor );
-      SetShaderEffect( mPanActor, mTurnEffect[mIndex] );
-      mTurnEffect[mIndex].SetUniform("uOriginalCenter", mOriginalCenter );
+      mShadowView.Add( mPages[mIndex].actor );
+      mPages[mIndex].UseEffect( mTurnEffectShader );
+      mPages[mIndex].SetOriginalCenter( mOriginalCenter );
       mCurrentCenter = mOriginalCenter;
-      mTurnEffect[mIndex].SetUniform("uCurrentCenter", mCurrentCenter );
+      mPages[mIndex].SetCurrentCenter( mCurrentCenter );
       mPanDisplacement = 0.f;
-      mConstraints = true;
+      mConstraints = false;
       mPress = true;
-      mIsAnimating[mIndex] = true;
+      mAnimatingCount++;
 
-      mPageTurnStartedSignal.Emit( handle, static_cast<unsigned int>(mTurningPageIndex), !mIsTurnBack[mPanActor] );
-      int id = mTurningPageIndex + (mIsTurnBack[mPanActor]? -1 : 1);
+      mPageTurnStartedSignal.Emit( handle, static_cast<unsigned int>(mTurningPageIndex), !mPages[mIndex].isTurnBack );
+      int id = mTurningPageIndex + (mPages[mIndex].isTurnBack ? -1 : 1);
       if( id >=0 && id < mTotalPageCount )
       {
-        mPageActors[id%NUMBER_OF_CACHED_PAGES].SetVisible(true);
+        mPages[id%NUMBER_OF_CACHED_PAGES].actor.SetVisible(true);
       }
 
       mShadowView.RemoveConstraints();
       Actor self = Self();
-      self.SetProperty( mPropertyPanDisplacement[mIndex], 0.f );
+      mPages[mIndex].SetPanDisplacement( 0.f );
 
       Constraint shadowBlurStrengthConstraint = Constraint::New<float>( mShadowView, mShadowView.GetBlurStrengthPropertyIndex(), ShadowBlurStrengthConstraint( mPageSize.width*PAGE_TURN_OVER_THRESHOLD_RATIO ) );
-      shadowBlurStrengthConstraint.AddSource( Source(mTurnEffect[mIndex],  mTurnEffect[mIndex].GetPropertyIndex("uCurrentCenter")) );
-      shadowBlurStrengthConstraint.AddSource( Source(mTurnEffect[mIndex],  mTurnEffect[mIndex].GetPropertyIndex("uOriginalCenter")) );
-      shadowBlurStrengthConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) );
+      shadowBlurStrengthConstraint.AddSource( Source(mPages[mIndex].actor,  mPages[mIndex].propertyCurrentCenter) );
+      shadowBlurStrengthConstraint.AddSource( Source(mPages[mIndex].actor,  mPages[mIndex].propertyOriginalCenter) );
+      shadowBlurStrengthConstraint.AddSource( Source(mPages[mIndex].actor,  mPages[mIndex].propertyPanDisplacement) );
       shadowBlurStrengthConstraint.Apply();
     }
   }
@@ -709,12 +778,12 @@ void PageTurnView::PanContinuing( const Vector2& gesturePosition )
     {
       // set the property values used by the constraints
       mPanDisplacement = mPageSize.width*PAGE_TURN_OVER_THRESHOLD_RATIO - currentCenter.x;
-      Self().SetProperty( mPropertyPanDisplacement[mIndex], mPanDisplacement );
-      Self().SetProperty( mPropertyCurrentCenter[mIndex], currentCenter );
+      mPages[mIndex].SetPanDisplacement( mPanDisplacement );
+      mPages[mIndex].SetPanCenter( currentCenter );
 
       // set up the OriginalCenterConstraint and CurrentCebterConstraint to the PageTurnEdffect
       // also set up the RotationConstraint to the page actor
-      if( mConstraints )
+      if( !mConstraints )
       {
         Vector2 corner;
         // the corner position need to be a little far away from the page edge to ensure the whole page is lift up
@@ -733,41 +802,38 @@ void PageTurnView::PanContinuing( const Vector2& gesturePosition )
         offset *= k;
         Actor self = Self();
 
-        Property::Index shaderOriginalCenterPropertyIndex = mTurnEffect[mIndex].GetPropertyIndex("uOriginalCenter");
-        Constraint originalCenterConstraint = Constraint::New<Vector2>( mTurnEffect[mIndex], shaderOriginalCenterPropertyIndex, OriginalCenterConstraint( mOriginalCenter, offset ));
-        originalCenterConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) );
+        Constraint originalCenterConstraint = Constraint::New<Vector2>( mPages[mIndex].actor, mPages[mIndex].propertyOriginalCenter, OriginalCenterConstraint( mOriginalCenter, offset ));
+        originalCenterConstraint.AddSource( Source( mPages[mIndex].actor, mPages[mIndex].propertyPanDisplacement ) );
         originalCenterConstraint.Apply();
 
-        Property::Index shaderCurrentCenterPropertyIndex = mTurnEffect[mIndex].GetPropertyIndex("uCurrentCenter");
-        Constraint currentCenterConstraint = Constraint::New<Vector2>( mTurnEffect[mIndex], shaderCurrentCenterPropertyIndex, CurrentCenterConstraint(mPageSize.width));
-        currentCenterConstraint.AddSource( Source(self, mPropertyCurrentCenter[mIndex]) );
-        currentCenterConstraint.AddSource( Source(mTurnEffect[mIndex], shaderOriginalCenterPropertyIndex) );
+        Constraint currentCenterConstraint = Constraint::New<Vector2>( mPages[mIndex].actor, mPages[mIndex].propertyCurrentCenter, CurrentCenterConstraint(mPageSize.width));
+        currentCenterConstraint.AddSource( Source( mPages[mIndex].actor, mPages[mIndex].propertyPanCenter ) );
+        currentCenterConstraint.AddSource( Source( mPages[mIndex].actor, mPages[mIndex].propertyOriginalCenter ) );
         currentCenterConstraint.Apply();
 
-        PageTurnApplyInternalConstraint(mTurnEffect[mIndex]);
+        PageTurnApplyInternalConstraint( mPages[mIndex].actor, mPageSize.height );
 
         float distance = offset.Length();
-        Constraint rotationConstraint = Constraint::New<Quaternion>( mPanActor, Actor::Property::ORIENTATION, RotationConstraint(distance, mPageSize.width, mIsTurnBack[mPanActor]));
-        rotationConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) );
+        Constraint rotationConstraint = Constraint::New<Quaternion>( mPages[mIndex].actor, Actor::Property::ORIENTATION, RotationConstraint(distance, mPageSize.width, mPages[mIndex].isTurnBack));
+        rotationConstraint.AddSource( Source( mPages[mIndex].actor, mPages[mIndex].propertyPanDisplacement ) );
         rotationConstraint.Apply();
 
-        mConstraints = false;
+        mConstraints = true;
       }
     }
     else
     {
-      if(!mConstraints) // remove the constraint is the pan position move back to far away from the spine
+      if(mConstraints) // remove the constraint is the pan position move back to far away from the spine
       {
-        mPanActor.RemoveConstraints();
-        mTurnEffect[mIndex].RemoveConstraints();
-        mTurnEffect[mIndex].SetUniform("uOriginalCenter",mOriginalCenter );
-        mConstraints = true;
+        mPages[mIndex].actor.RemoveConstraints();
+        mPages[mIndex].SetOriginalCenter(mOriginalCenter );
+        mConstraints = false;
         mPanDisplacement = 0.f;
       }
 
-      mTurnEffect[mIndex].SetUniform("uCurrentCenter", currentCenter );
+      mPages[mIndex].SetCurrentCenter( currentCenter );
       mCurrentCenter = currentCenter;
-      PageTurnApplyInternalConstraint(mTurnEffect[mIndex]);
+      PageTurnApplyInternalConstraint(mPages[mIndex].actor, mPageSize.height );
     }
   }
 }
@@ -777,25 +843,25 @@ void PageTurnView::PanFinished( const Vector2& gesturePosition, float gestureSpe
   // Guard against destruction during signal emission
   Toolkit::PageTurnView handle( GetOwner() );
 
-  if( !mPanActor )
+  if( mTurningPageIndex == -1  )
   {
-    if(!mIsAnimating[mIndex])
+    if( mAnimatingCount< MAXIMUM_TURNING_NUM && mSlidingCount < 1)
     {
       OnPossibleOutwardsFlick( gesturePosition, gestureSpeed );
     }
+
     return;
   }
 
   mPagePanFinishedSignal.Emit( handle );
 
-  ImageActor actor = mPanActor;
   if(mPress)
   {
-    if(!mConstraints) // if with constraints, the pan finished position is near spine, set up an animation to turn the page over
+    if(mConstraints) // if with constraints, the pan finished position is near spine, set up an animation to turn the page over
     {
       // update the pages here instead of in the TurnedOver callback function
       // as new page is allowed to respond to the pan gesture before other pages finishing animation
-      if(mIsTurnBack[actor])
+      if(mPages[mIndex].isTurnBack)
       {
         mCurrentPageIndex--;
         RemovePage( mCurrentPageIndex+NUMBER_OF_CACHED_PAGES_EACH_SIDE );
@@ -810,30 +876,27 @@ void PageTurnView::PanFinished( const Vector2& gesturePosition, float gestureSpe
       OrganizePageDepth();
 
       // set up an animation to turn the page over
-      Actor self = Self();
       float width = mPageSize.width*(1.f+PAGE_TURN_OVER_THRESHOLD_RATIO);
       Animation animation = Animation::New( std::max(0.1f,PAGE_TURN_OVER_ANIMATION_DURATION * (1.0f - mPanDisplacement / width)) );
-      animation.AnimateTo( Property(self, mPropertyPanDisplacement[mIndex]),
+      animation.AnimateTo( Property(mPages[mIndex].actor, mPages[mIndex].propertyPanDisplacement),
                            width,AlphaFunction::EASE_OUT_SINE);
-      animation.AnimateTo( Property(self, mPropertyCurrentCenter[mIndex]),
+      animation.AnimateTo( Property(mPages[mIndex].actor, mPages[mIndex].propertyPanCenter),
                            Vector2(-mPageSize.width*1.1f, 0.5f*mPageSize.height), AlphaFunction::EASE_OUT_SINE);
       mAnimationPageIdPair[animation] = mTurningPageIndex;
-      mAnimationIndexPair[animation] = mIndex;
       animation.Play();
       animation.FinishedSignal().Connect( this, &PageTurnView::TurnedOver );
     }
     else // the pan finished position is far away from the spine, set up an animation to slide the page back instead of turning over
     {
       Animation animation= Animation::New( PAGE_SLIDE_BACK_ANIMATION_DURATION * (mOriginalCenter.x - mCurrentCenter.x) / mPageSize.width / PAGE_TURN_OVER_THRESHOLD_RATIO );
-      animation.AnimateTo( Property( mTurnEffect[mIndex], "uCurrentCenter" ),
+      animation.AnimateTo( Property( mPages[mIndex].actor, mPages[mIndex].propertyCurrentCenter ),
                            mOriginalCenter, AlphaFunction::LINEAR );
       mAnimationPageIdPair[animation] = mTurningPageIndex;
-      mAnimationIndexPair[animation] = mIndex;
       animation.Play();
-      mIsSliding[mIndex] = true;
+      mSlidingCount++;
       animation.FinishedSignal().Connect( this, &PageTurnView::SliddenBack );
 
-      mPageTurnStartedSignal.Emit( handle, static_cast<unsigned int>(mTurningPageIndex), mIsTurnBack[actor] );
+      mPageTurnStartedSignal.Emit( handle, static_cast<unsigned int>(mTurningPageIndex), mPages[mIndex].isTurnBack );
     }
   }
   else
@@ -842,60 +905,57 @@ void PageTurnView::PanFinished( const Vector2& gesturePosition, float gestureSpe
     // In landscape view, nothing to do
     OnPossibleOutwardsFlick( gesturePosition, gestureSpeed );
   }
-
   mPageUpdated = true;
 }
 
 void PageTurnView::TurnedOver( Animation& animation )
 {
   int pageId = mAnimationPageIdPair[animation];
-  ImageActor actor = mPageActors[pageId % NUMBER_OF_CACHED_PAGES];
-  mIsTurnBack[actor] = !mIsTurnBack[actor];
-  actor.RemoveConstraints();
-  Self().Add(actor);
-  int index = mAnimationIndexPair[animation];
-  mIsAnimating[index] = false;
-  mTurnEffect[index].RemoveConstraints();
-  mAnimationIndexPair.erase( animation );
+  int index = pageId%NUMBER_OF_CACHED_PAGES;
+
+  mPages[index].ChangeTurnDirection();
+  mPages[index].actor.RemoveConstraints();
+  Self().Add(mPages[index].actor);
+  mAnimatingCount--;
   mAnimationPageIdPair.erase( animation );
 
-  SetSpineEffect( actor, mIsTurnBack[actor] );
+  float degree = mPages[index].isTurnBack ? 180.f : 0.f;
+  mPages[index].actor.SetOrientation( Degree(degree), Vector3::YAXIS );
+  mPages[index].UseEffect( mSpineEffectShader );
 
-  int id = pageId + (mIsTurnBack[actor]? -1 : 1);
+  int id = pageId + (mPages[index].isTurnBack ? -1 : 1);
   if( id >=0 && id < mTotalPageCount )
   {
-    mPageActors[id%NUMBER_OF_CACHED_PAGES].SetVisible(false);
+    mPages[id%NUMBER_OF_CACHED_PAGES].actor.SetVisible(false);
   }
 
-  OnTurnedOver( actor, mIsTurnBack[actor] );
+  OnTurnedOver( mPages[index].actor, mPages[index].isTurnBack );
 
   // Guard against destruction during signal emission
   Toolkit::PageTurnView handle( GetOwner() );
-  mPageTurnFinishedSignal.Emit( handle, static_cast<unsigned int>(pageId), mIsTurnBack[actor] );
+  mPageTurnFinishedSignal.Emit( handle, static_cast<unsigned int>(pageId), mPages[index].isTurnBack );
 }
 
 void PageTurnView::SliddenBack( Animation& animation )
 {
   int pageId = mAnimationPageIdPair[animation];
-  ImageActor actor = mPageActors[pageId % NUMBER_OF_CACHED_PAGES];
-  Self().Add(actor);
-  int index = mAnimationIndexPair[animation];
-  mIsSliding[index] = false;
-  mIsAnimating[index] = false;
-  mAnimationIndexPair.erase( animation );
+  int index = pageId%NUMBER_OF_CACHED_PAGES;
+  Self().Add(mPages[index].actor);
+  mSlidingCount--;
+  mAnimatingCount--;
   mAnimationPageIdPair.erase( animation );
 
-  SetSpineEffect( actor, mIsTurnBack[actor] );
+  mPages[index].UseEffect( mSpineEffectShader );
 
-  int id = pageId + (mIsTurnBack[actor]? -1 : 1);
+  int id = pageId + (mPages[index].isTurnBack ? -1 : 1);
   if( id >=0 && id < mTotalPageCount )
   {
-    mPageActors[id%NUMBER_OF_CACHED_PAGES].SetVisible(false);
+    mPages[id%NUMBER_OF_CACHED_PAGES].actor.SetVisible(false);
   }
 
   // Guard against destruction during signal emission
   Toolkit::PageTurnView handle( GetOwner() );
-  mPageTurnFinishedSignal.Emit( handle, static_cast<unsigned int>(pageId), mIsTurnBack[actor] );
+  mPageTurnFinishedSignal.Emit( handle, static_cast<unsigned int>(pageId), mPages[index].isTurnBack );
 }
 
 void PageTurnView::OrganizePageDepth()
@@ -904,18 +964,38 @@ void PageTurnView::OrganizePageDepth()
   {
     if(mCurrentPageIndex+i < mTotalPageCount)
     {
-      mPageActors[( mCurrentPageIndex+i )%NUMBER_OF_CACHED_PAGES].SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
+      mPages[( mCurrentPageIndex+i )%NUMBER_OF_CACHED_PAGES].actor.SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
     }
     if( mCurrentPageIndex >= i + 1 )
     {
-      mPageActors[( mCurrentPageIndex-i-1 )%NUMBER_OF_CACHED_PAGES].SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
+      mPages[( mCurrentPageIndex-i-1 )%NUMBER_OF_CACHED_PAGES].actor.SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
     }
   }
 }
 
-void PageTurnView::SetShaderEffect( ImageActor actor, ShaderEffect shaderEffect )
+void PageTurnView::StopTurning()
 {
-  SetShaderEffectRecursively( actor, shaderEffect );
+  mAnimatingCount = 0;
+  mSlidingCount = 0;
+
+  if( !mPageUpdated )
+  {
+    int index = mTurningPageIndex % NUMBER_OF_CACHED_PAGES;
+    Self().Add( mPages[ index ].actor );
+    mPages[ index ].actor.RemoveConstraints();
+    mPages[ index ].UseEffect( mSpineEffectShader );
+    float degree = mTurningPageIndex==mCurrentPageIndex ? 0.f :180.f;
+    mPages[index].actor.SetOrientation( Degree(degree), Vector3::YAXIS );
+    mPageUpdated = true;
+  }
+
+  if( !mAnimationPageIdPair.empty() )
+  {
+    for (std::map<Animation,int>::iterator it=mAnimationPageIdPair.begin(); it!=mAnimationPageIdPair.end(); ++it)
+    {
+      static_cast<Animation>(it->first).SetCurrentProgress( 1.f );
+    }
+  }
 }
 
 Toolkit::PageTurnView::PageTurnSignal& PageTurnView::PageTurnStartedSignal()
index 91a714f..e17f2a0 100644 (file)
 // EXTERNAL INCLUDES
 #include <dali/devel-api/common/map-wrapper.h>
 #include <dali/public-api/actors/layer.h>
-#include <dali/public-api/actors/camera-actor.h>
-#include <dali/public-api/actors/image-actor.h>
-#include <dali/public-api/images/frame-buffer-image.h>
-#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/devel-api/rendering/renderer.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-impl.h>
@@ -46,6 +43,82 @@ class PageTurnView : public Control
 protected:
 
   /**
+   * The book page class
+   */
+  struct Page
+  {
+    /**
+     * Constructor
+     */
+    Page();
+    /**
+     * Destructor
+     */
+    ~Page(){};
+
+    /**
+     * Set the page image content
+     * @param[in] image The content of the page.
+     */
+    void SetImage( Image image );
+
+    /**
+     * Apply an effect onto the page actor.
+     * @param[in] shader The shader for rendering effect.
+     */
+    void UseEffect(Shader shader);
+
+    /**
+     * Apply an effect onto the page actor.
+     * @param[in] shader The shader for rendering effect.
+     * @param[in] geometry The geometry for rendering effect.
+     */
+    void UseEffect(Shader shader, Geometry geometry);
+
+    /**
+     * Change the page turning direction.
+     */
+    void ChangeTurnDirection();
+
+    /**
+     * Set the pan displacement property
+     * @param[in] value The property value
+     */
+    void SetPanDisplacement(float value);
+
+    /**
+     * Set the pan center property
+     * @param[in] value The property value
+     */
+    void SetPanCenter( const Vector2& value );
+
+    /**
+     * Set the original center property to be used by shader
+     * @param[in] value The property value
+     */
+    void SetOriginalCenter( const Vector2& value );
+
+    /**
+     * Set the current center property to be used by shader
+     * @param[in] value The property value
+     */
+    void SetCurrentCenter( const Vector2& value );
+
+    Actor actor;                              ///< The page actor
+    Material material;                        ///< The material of the actor
+    Renderer renderer;                        ///< The renderer of the actor
+    bool isTurnBack;                          ///< The turning direction
+    Property::Index propertyPanDisplacement;  ///< The horizontal displacement of the pan
+    Property::Index propertyPanCenter;        ///< The current pan position
+    Property::Index propertyOriginalCenter;   ///< The original center to be used by the shader
+    Property::Index propertyCurrentCenter;    ///< The current center to be used by the shader
+    Property::Index propertyTurnDirection;    ///< The turning direction property
+  };
+
+
+protected:
+
+  /**
    * Constructor.
    * It initializes the PageTurnView members
    */
@@ -125,15 +198,14 @@ protected:
    */
   void OrganizePageDepth();
 
+private:
+
   /**
-   * Set shader Effect to the actor.
-   * If the actor has children, the shader effect is also applied to its first child
-   * @param[in] actor The actor which the shader effect would be applied onto
-   * @param[in] shaderEffect The shader effect to be set to the actor
+   * Create shader from a property map.
+   * @param[in] shaderMap The shader property map;
+   * @return The created shader.
    */
-  void SetShaderEffect( ImageActor actor, ShaderEffect shaderEffect );
-
-private:
+  Shader CreateShader( const Property::Map& shaderMap );
 
  /**
   * Set up the shadow view control to cast shadow
@@ -166,6 +238,11 @@ private:
    */
   void SliddenBack( Animation& animation );
 
+  /**
+   * Stop the page turning animation and contraint.
+   * This method should be called when taking off stage or jump to a specified page.
+   */
+  void StopTurning();
 
 private: // from Control
 
@@ -204,7 +281,7 @@ private: // implemented differently by PageTurnLandscapeView and PageTurnPortrai
    * @param[in] newPage The added page actor
    * @param[in] isLeftSide Which side the new page is added to
    */
-  virtual void OnAddPage( ImageActor newPage, bool isLeftSide ) { }
+  virtual void OnAddPage( Actor newPage, bool isLeftSide ) { }
 
   /**
    * This method is called when pan started or continuing
@@ -223,15 +300,6 @@ private: // implemented differently by PageTurnLandscapeView and PageTurnPortrai
   virtual void SetPanActor( const Vector2& panPosition ) = 0;
 
   /**
-   * This method is called when a page is turned over or slidden back
-   * Remove PageTurnEffect and use a proper PageTurnBookSpineEffect
-   * Implemented in subclasses to provide specific behaviour.
-   * @param[in] actor The current page actor
-   * @param[in] isLeftSide Which side the current page is located
-   */
-  virtual void SetSpineEffect(ImageActor actor, bool isLeftSide) = 0;
-
-  /**
    * This method is called when pan finished to detect outwards flick
    * In portrait view, start an animation of turning previous page back when outwards flick is detected
    * In landscape view, nothing to do
@@ -246,7 +314,7 @@ private: // implemented differently by PageTurnLandscapeView and PageTurnPortrai
    * @param[in] actor The page actor
    * @param[in] isLeftSide Which side the page is turned to
    */
-  virtual void OnTurnedOver( ImageActor actor, bool isLeftSide ) { }
+  virtual void OnTurnedOver( Actor actor, bool isLeftSide ) { }
 
 public: //signal and property
 
@@ -309,53 +377,50 @@ private:
 
 protected:
 
-  Vector2                        mControlSize;             ///< The size of the control, it is decided by the page size, the SetSize from application can not change it
   Layer                          mTurningPageLayer;        ///< The layer for the turning page, to avoid possible depth conflict
   Toolkit::ShadowView            mShadowView;              ///< The shadow view control for shadow casting
   Actor                          mShadowPlaneBackground;   ///< The plane for the shadow to cast on
   Actor                          mPointLight;              ///< The point light used for shadow casting
 
-  PageFactory&                   mPageFactory;             ///< The page factory which provides the page actors
-  Vector2                        mPageSize;                ///< The page size
-  int                            mTotalPageCount;          ///< The total number of pages provided by the page factory
+  PageFactory* const             mPageFactory;             ///< The factory which provides the page actors
+  Shader                         mTurnEffectShader;        ///< The group of PageTurnEffects
+  Shader                         mSpineEffectShader;       ///< The book spine shader effect
+  Geometry                       mGeometry;                ///< The grid geometry for pages
 
-  bool                           mPanning;                 ///< The boolean to indicate whether the pan gesture is continuing
+  std::vector<Page>              mPages;                   ///< The vector of pages on stage
+  std::map<Animation,int>        mAnimationPageIdPair;     ///< The map to keep track which page actor is the animation act on
 
-  std::vector<ShaderEffect>      mTurnEffect;              ///< The group of PageTurnEffects
-  ShaderEffect                   mSpineEffectFront;        ///< The book spine shader effect without flipping image content
-  ShaderEffect                   mSpineEffectBack;         ///< The book spine shader effect with image content flipped
+  Vector2                        mPageSize;                ///< The page size
+  Vector2                        mControlSize;             ///< The size of the control, it is decided by the page size, the SetSize from application can not change it
   Vector2                        mSpineShadowParameter;    ///< The spine shadow parameter for all the above shader effects
   Vector2                        mOriginalCenter;          ///< The original center set to the PageTurnEffect
   Vector2                        mCurrentCenter;           ///< The current center set to the PageTurnEffect
-
-  std::vector<ImageActor>        mPageActors;              ///< The vector of pages on stage
-  int                            mCurrentPageIndex;        ///< The index of the current page, between 0 ~ mTotalPageCount-1
-  int                            mTurningPageIndex;        ///< The index of the turning page
-  std::map<ImageActor,bool>      mIsTurnBack;              ///< The map to keep track the page actor's turning direction
-  std::map<Animation,int>        mAnimationPageIdPair;     ///< The map to keep track which page actor is the animation act on
-  std::map<Animation, int>       mAnimationIndexPair;      ///< The map to keep track which PageTurnEffect, PanDisplacementProperty, CurrentCenterProperty is used for the animation
-  int                            mIndex;                   ///< The index to keep track which PageTurnEffect, PanDisplacementProperty, CurrentCenterProperty is used for the current panning page
-  std::vector<bool>              mIsAnimating;             ///< The boolean vector to keep track which PageTurnEffect, PanDisplacementProperty, CurrentCenterProperty is available for using
-  std::vector<bool>              mIsSliding;               ///< The boolean vector to keep track whether there are animating pages sliding back
-
-  ImageActor                     mPanActor;                ///< The page being panned by the pan gesture
   Vector2                        mPressDownPosition;       ///< The first press down position of the pan gesture
-  bool                           mPress;                   ///< The boolean to keep track the state of the pageTurnEffect is activated or not
-  bool                           mPageUpdated;             ///< The boolean to keep track whether is page is updated after any turning activity
 
   float                          mDistanceUpCorner;        ///< The distance between the original center of PageTurnEffect and the top-left corner of the page
   float                          mDistanceBottomCorner;    ///< The distance between the original center of PageTurnEffect and the bottom-left corner of the page
-
-  std::vector<Property::Index>   mPropertyPanDisplacement; ///< The pan displacement property group
-  std::vector<Property::Index>   mPropertyCurrentCenter;   ///< The current center property group
   float                          mPanDisplacement;         ///< The displacement of the pan after the constrains are applied
+
+  int                            mTotalPageCount;          ///< The total number of pages provided by the page factory
+  int                            mCurrentPageIndex;        ///< The index of the current page, between 0 ~ mTotalPageCount-1
+  int                            mTurningPageIndex;        ///< The index of the turning page
+  int                            mIndex;                   ///< The index to keep track which PanDisplacementProperty, CurrentCenterProperty is used for the current panning page
+  int                            mSlidingCount;            ///< The boolean vector to keep track whether there are animating pages sliding back
+  int                            mAnimatingCount;          ///< The boolean vector to keep track which PageTurnEffect, PanDisplacementProperty, CurrentCenterProperty is available for using
+
   bool                           mConstraints;             ///< The boolean to keep track the constrains are applied or not
+  bool                           mPress;                   ///< The boolean to keep track the state of the pageTurnEffect is activated or not
+  bool                           mPageUpdated;             ///< The boolean to keep track whether is page is updated after any turning activity
 
   Toolkit::PageTurnView::PageTurnSignal   mPageTurnStartedSignal;   ///< The signal to notify that a page has started turning
   Toolkit::PageTurnView::PageTurnSignal   mPageTurnFinishedSignal;  ///< The signal to notify that a page has finished turning
   Toolkit::PageTurnView::PagePanSignal    mPagePanStartedSignal;    ///< The signal to notify that a page has started panning
   Toolkit::PageTurnView::PagePanSignal    mPagePanFinishedSignal;   ///< The signal to notify that a page has finished panning
 
+  static const char * const PROPERTY_TEXTURE_WIDTH;     ///< The uniform name of texture width
+  static const char * const PROPERTY_ORIGINAL_CENTER;   ///< The property name of original center, which is used to constrain the uniforms
+  static const char * const PROPERTY_CURRENT_CENTER;    ///< The property name of current center, which is used to constrain the uniforms
+
   static const int               MAXIMUM_TURNING_NUM;                  ///< How many pages are allowed to animating in the same time
   static const int               NUMBER_OF_CACHED_PAGES_EACH_SIDE;     ///< The maximum number of pages kept, (MAXIMUM_ANIMATION_NUM+1) pages for each side
   static const int               NUMBER_OF_CACHED_PAGES;               ///< The maximum number of pages kept, (MAXIMUM_ANIMATION_NUM+1)*2 pages in total
index b8c6343..17eae58 100644 (file)
@@ -109,34 +109,6 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
   }\n
 );
 
-
-Geometry GenerateGeometry( const Vector< Vector2 >& vertices, const Vector< unsigned int >& indices )
-{
-  Property::Map vertexFormat;
-  vertexFormat[ "aPosition" ] = Property::VECTOR2;
-  PropertyBuffer vertexPropertyBuffer = PropertyBuffer::New( vertexFormat );
-  if( vertices.Size() > 0 )
-  {
-    vertexPropertyBuffer.SetData( &vertices[ 0 ], vertices.Size() );
-  }
-
-  Property::Map indexFormat;
-  indexFormat[ "indices" ] = Property::INTEGER;
-  PropertyBuffer indexPropertyBuffer = PropertyBuffer::New( indexFormat );
-  if( indices.Size() > 0 )
-  {
-    indexPropertyBuffer.SetData( &indices[ 0 ], indices.Size() );
-  }
-
-  // Create the geometry object
-  Geometry geometry = Geometry::New();
-  geometry.AddVertexBuffer( vertexPropertyBuffer );
-  geometry.SetIndexBuffer( indexPropertyBuffer );
-  geometry.SetGeometryType( Geometry::TRIANGLE_STRIP );
-
-  return geometry;
-}
-
 Geometry CreateGeometry( RendererFactoryCache& factoryCache, ImageDimensions gridSize )
 {
   Geometry geometry;
@@ -146,54 +118,13 @@ Geometry CreateGeometry( RendererFactoryCache& factoryCache, ImageDimensions gri
     geometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
     if( !geometry )
     {
-      geometry =  factoryCache.CreateQuadGeometry();
+      geometry =  RendererFactoryCache::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+2)*gridHeight*2 - 2);
-
-    for( unsigned int row = 0u; row < gridHeight; ++row )
-    {
-      unsigned int rowStartIndex = row*(gridWidth+1u);
-      unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u;
-
-      if( row != 0u ) // degenerate index on non-first row
-      {
-        indices.PushBack( rowStartIndex );
-      }
-
-      for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip
-      {
-        indices.PushBack( rowStartIndex + column);
-        indices.PushBack( nextRowStartIndex + column);
-      }
-
-      if( row != gridHeight-1u ) // degenerate index on non-last row
-      {
-        indices.PushBack( nextRowStartIndex + gridWidth );
-      }
-    }
-
-    return GenerateGeometry( vertices, indices );
+    geometry = RendererFactoryCache::CreateGridGeometry( gridSize );
   }
 
   return geometry;
index ecfc6b5..3a6b79f 100644 (file)
@@ -161,8 +161,8 @@ Geometry RendererFactoryCache::CreateQuadGeometry()
   QuadVertex quadVertexData[4] =
   {
       { Vector2(-halfWidth, -halfHeight) },
-      { Vector2( halfWidth, -halfHeight) },
       { Vector2(-halfWidth, halfHeight)  },
+      { Vector2( halfWidth, -halfHeight) },
       { Vector2( halfWidth, halfHeight)  }
   };
 
@@ -197,6 +197,74 @@ void RendererFactoryCache::ApplyRasterizedSVGToSampler()
   }
 }
 
+Geometry RendererFactoryCache::CreateGridGeometry( Uint16Pair gridSize )
+{
+  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+2)*gridHeight*2 - 2);
+
+  for( unsigned int row = 0u; row < gridHeight; ++row )
+  {
+    unsigned int rowStartIndex = row*(gridWidth+1u);
+    unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u;
+
+    if( row != 0u ) // degenerate index on non-first row
+    {
+      indices.PushBack( rowStartIndex );
+    }
+
+    for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip
+    {
+      indices.PushBack( rowStartIndex + column);
+      indices.PushBack( nextRowStartIndex + column);
+    }
+
+    if( row != gridHeight-1u ) // degenerate index on non-last row
+    {
+      indices.PushBack( nextRowStartIndex + gridWidth );
+    }
+  }
+
+  Property::Map vertexFormat;
+  vertexFormat[ "aPosition" ] = Property::VECTOR2;
+  PropertyBuffer vertexPropertyBuffer = PropertyBuffer::New( vertexFormat );
+  if( vertices.Size() > 0 )
+  {
+    vertexPropertyBuffer.SetData( &vertices[ 0 ], vertices.Size() );
+  }
+
+  Property::Map indexFormat;
+  indexFormat[ "indices" ] = Property::INTEGER;
+  PropertyBuffer indexPropertyBuffer = PropertyBuffer::New( indexFormat );
+  if( indices.Size() > 0 )
+  {
+    indexPropertyBuffer.SetData( &indices[ 0 ], indices.Size() );
+  }
+
+  // Create the geometry object
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexPropertyBuffer );
+  geometry.SetIndexBuffer( indexPropertyBuffer );
+  geometry.SetGeometryType( Geometry::TRIANGLE_STRIP );
+
+  return geometry;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 89334c5..f6fd573 100644 (file)
@@ -21,6 +21,7 @@
 #include "svg/svg-rasterize-thread.h"
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/math/uint-16-pair.h>
 #include <dali/public-api/object/ref-object.h>
 #include <dali/devel-api/rendering/geometry.h>
 #include <dali/devel-api/rendering/shader.h>
@@ -114,6 +115,13 @@ public:
    */
   static Geometry CreateQuadGeometry();
 
+  /**
+   * Create the grid geometry.
+   * @param[in] gridSize The size of the grid.
+   * @return The created grid geometry.
+   */
+  static Geometry CreateGridGeometry( Uint16Pair gridSize );
+
 public:
 
   /**
index 99d036a..16bfdca 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 
 /**
  * @brief PageFactory is an abstract interface for providing image actors to PageTurnView
- * Each image actor is identified by a unique ID, and has a linear order from 0 to GetNumberOfPages()-1
+ * Each page is identified by a unique ID, and has a linear order from 0 to GetNumberOfPages()-1
  *
  * @SINCE_1_1.4
  */
@@ -37,6 +37,8 @@ class DALI_IMPORT_API PageFactory
 {
 public:
 
+  class Extension; ///< Forward declare future extension interface
+
   /**
    * @brief Virtual destructor
    * @SINCE_1_1.4
@@ -45,18 +47,35 @@ public:
 
   /**
    * @brief Query the number of pages available from the factory.
+   *
    * The maximum available page has an ID of GetNumberOfPages()-1.
    * @SINCE_1_1.4
+   * @return The page count.
    */
   virtual unsigned int GetNumberOfPages() = 0;
 
   /**
    * @brief Create an actor to represent the page content.
-   * @SINCE_1_1.4
+   * @SINCE_1_1.30
+   *
+   * If no valid image provided, a broken image is displayed.
+   * For double-sided page( PageTurnLandscapeView ), the left half of image is used as page front side, and the right half as page back side.
+   *
    * @param[in] pageId The ID of the page to create.
    * @return An actor, or an uninitialized pointer if the ID is out of range.
    */
-  virtual Actor NewPage( unsigned int pageId ) = 0;
+  virtual Image NewPage( unsigned int pageId ) = 0;
+
+  /**
+   * @brief Retrieve the extension for this factory
+   * @SINCE_1_1.30
+   *
+   * @return The extension if available, NULL otherwise.
+   */
+  virtual Extension* GetExtension()
+  {
+    return NULL;
+  }
 };
 
 } // namespace Toolkit