Add 'ExclusiveArch: armv7l' limit build to arm architecture
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / shader-effects / page-turn-effect-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // CLASS HEADER
18 #include "page-turn-effect-impl.h"
19
20 // EXTERNAL HEADERS
21 #include <sstream>
22
23
24 namespace Dali
25 {
26
27 namespace Toolkit
28 {
29
30 namespace Internal
31 {
32
33 namespace
34 {
35 #define MAKE_STRING(A)#A
36
37 const std::string CURRENT_CENTER_PROPERTY_NAME("uCurrentCenter");
38 const std::string ORIGINAL_CENTER_PROPERTY_NAME("uOriginalCenter");
39 const std::string PAGE_SIZE_PROPERTY_NAME("uPageSize");
40 const std::string IS_TURNING_BACK_PROPERTY_NAME("uIsTurningBack");
41 const std::string SHADOW_WIDTH_PROPERTY_NAME("uShadowWidth");
42 const std::string SPINE_SHADOW_PARAMETER_PROPERTY_NAME("uSpineShadowParameter");
43
44 // fake shadow is used to enhance the effect, with its default maximum width to be pageSize * 0.15
45 const float DEFAULT_SHADOW_WIDTH(0.15f);
46
47 // the major&minor radius (in pixels) to form an ellipse shape
48 // the top-left quarter of this ellipse is used to calculate spine normal for simulating shadow
49 const Vector2 DEFAULT_SPINE_SHADOW_PARAMETER(50.0f, 20.0f);
50
51 // when the vanishing point is very far away(pageHeight*THRESHOLD), make it infinitely, in this case, the page bent horizontally
52 const float THRESHOLD(20.0);
53
54 struct CommonParametersConstraint
55 {
56   Matrix operator()( const Matrix& current,
57                      const PropertyInput& originalCenterProperty,
58                      const PropertyInput& currentCenterProperty,
59                      const PropertyInput& pageSizeProperty)
60   {
61     const Vector2& originalCenter = originalCenterProperty.GetVector2();
62     Vector2 currentCenter = currentCenterProperty.GetVector2();
63     const Vector2& pageSize = pageSizeProperty.GetVector2();
64
65     // calculate the curve direction and the vanishing point
66     // here, the vanishing point is the intersection of spine with the line passing through original center and vertical to curve direction
67     Vector2 curveDirection( currentCenter - originalCenter );
68     curveDirection.Normalize();
69     if( fabs(curveDirection.y) < 0.01f) // eliminate the possibility of division by zero in the next step
70     {
71       curveDirection.y = 0.01f;
72     }
73     float vanishingPointY = originalCenter.y + curveDirection.x * originalCenter.x / curveDirection.y;
74
75     float curveEndY, cosTheta ,sinTheta ,translateX, translateY;
76     // when the vanishing point is very far away, make it infinitely, in this case, the page bent horizontally
77     if( fabs(vanishingPointY-pageSize.y*0.5f) >= pageSize.y*THRESHOLD )
78     {
79       curveDirection = Vector2(-1.f,0.f);
80       currentCenter.y = originalCenter.y;
81
82       curveEndY = originalCenter.y;
83       cosTheta = 1.f;
84       sinTheta = 0.f;
85       translateX = currentCenter.x - originalCenter.x;
86       translateY = vanishingPointY;
87     }
88     else
89     {
90       curveEndY = currentCenter.y - curveDirection.y * (currentCenter.x/curveDirection.x) ;
91       Vector2 v1( currentCenter.x, currentCenter.y - vanishingPointY );
92       v1.Normalize();
93       Vector2 v2( originalCenter.x, originalCenter.y - vanishingPointY );
94       v2.Normalize();
95       cosTheta = v1.x*v2.x + v1.y*v2.y;
96       sinTheta = ( vanishingPointY > pageSize.y*0.5f ) ? sqrt(1.0-cosTheta*cosTheta) : -sqrt(1.0-cosTheta*cosTheta);
97       translateX = currentCenter.x - cosTheta*originalCenter.x - sinTheta*( originalCenter.y-vanishingPointY );
98       translateY = currentCenter.y + sinTheta*originalCenter.x - cosTheta*( originalCenter.y-vanishingPointY );
99     }
100
101     float originalLength = fabs(originalCenter.x/curveDirection.x);
102     float currentLength = fabs(currentCenter.x/curveDirection.x);
103     float curveHeight = 0.45f*sqrt(originalLength*originalLength - currentLength*currentLength);
104
105     Matrix commonParameters( false );
106     float* parameterArray = commonParameters.AsFloat();
107     parameterArray[0] = cosTheta;
108     parameterArray[1] = -sinTheta;
109     parameterArray[2] = originalCenter.x;
110     parameterArray[3] = originalCenter.y;
111     parameterArray[4] = sinTheta;
112     parameterArray[5] = cosTheta;
113     parameterArray[6] = currentCenter.x;
114     parameterArray[7] = currentCenter.y;
115     parameterArray[8] = translateX;
116     parameterArray[9] = translateY;
117     parameterArray[10] = vanishingPointY;
118     parameterArray[11] = curveEndY;
119     parameterArray[12] = curveDirection.x;
120     parameterArray[13] = curveDirection.y;
121     parameterArray[14] = curveHeight;
122     parameterArray[15] = currentLength;
123
124     return commonParameters;
125   }
126 };
127
128 }//namespace
129
130 PageTurnEffect::PageTurnEffect()
131 {
132 }
133
134 PageTurnEffect::~PageTurnEffect()
135 {
136 }
137
138 Toolkit::PageTurnEffect PageTurnEffect::CreateShaderEffect( bool enableBlending )
139 {
140   std::string vertexShader = MAKE_STRING(
141     /*
142      * The common parameters for all the vertices, calculate in CPU then pass into the shader as uniforms
143      *
144      *  first part of the page, (outside the the line passing through original center and vertical to curve direction)
145      * no Z change, only 2D rotation and translation
146      * ([0][0],[0][1],[1][0],[1][1]) mat2 rotateMatrix
147      * ([2][0],[2][1]) vec2 translationVector
148      *
149      * ([0][2],[0][3]) vec2 originalCenter: Typically the press down position of the Pan Gesture
150      * ([1][2],[1][3]) vec2 currentCenter: Typically the current position of the Pan Gesture
151      * ([3][0],[3][1]) vec2 curveDirection: The normalized vector pointing from original center to current center
152      * ([2][2]) float vanishingPointY: The Y coordinate of the intersection of the spine
153      *                                 and the line which goes through the original center and is vertical to the curveDirection
154      * ([2][3]) float curveEndY: The Y coordinate of intersection of the spine and the line through both original and current center
155      * ([3][2]) float curveHeight: The height of the interpolated hermite curve.
156      * ([3][3]) float currentLength: The length from the current center to the curveEnd.
157      */
158     uniform mat4 uCommonParameters;\n
159     \n
160     uniform vec2 uPageSize;\n
161     uniform float uIsTurningBack;\n
162     uniform float uShadowWidth;\n
163     varying vec3 vNormal;\n
164     varying vec4 vPosition;\n
165     varying float vEdgeShadow;\n
166     \n
167     void main()\n
168     {\n
169       vec4 position = vec4( aPosition.xy, 0.0, 1.0);\n
170       vec2 currentCenter = vec2( uCommonParameters[1][2], uCommonParameters[1][3]);\n
171       vec2 originalCenter = vec2( uCommonParameters[0][2], uCommonParameters[0][3]);\n
172       vec3 normal = vec3(0.0,0.0,1.0);\n
173       \n
174       if(currentCenter.x < originalCenter.x)\n
175       {\n
176         // change the coordinate origin from the center of the page to its top-left
177         position.xy += uPageSize * 0.5;\n
178         vec2 curveDirection = vec2( uCommonParameters[3]);\n
179         vec3 vanishingPoint = vec3(0.0, uCommonParameters[2][2], 0.0);\n
180         // first part of the page, (outside the the line passing through original center and vertical to curve direction)
181         //no Z change, only 2D rotation and translation
182         if( dot(curveDirection, position.xy - originalCenter) < 0.0 )
183         {\n
184           position.y -= vanishingPoint.y;\n
185           position.xy = mat2(uCommonParameters)*position.xy + vec2( uCommonParameters[2]);\n
186         }\n
187          // second part of the page, bent as a ruled surface
188         else\n
189         {\n
190           // calculate on the flat plane, between
191           // the first line passing through current vertex and vanishing point
192           // the second line passing through original center and current center
193           vec2 curveEnd = vec2( 0.0, uCommonParameters[2][3] );\n
194           vec2 curFlatDirection = vec2(0.0,1.0);\n
195           float lengthFromCurve = position.y - originalCenter.y;\n
196           float lengthOnCurve = position.x;\n
197           if(currentCenter.y != originalCenter.y)\n
198           {\n
199             curFlatDirection = normalize(position.xy - vanishingPoint.xy);\n
200             lengthFromCurve = (curveEnd.x*curveDirection.y-curveEnd.y*curveDirection.x-position.x*curveDirection.y+position.y*curveDirection.x)
201                             / (curFlatDirection.x*curveDirection.y-curFlatDirection.y*curveDirection.x);\n
202             lengthOnCurve = length(position.xy+lengthFromCurve*curFlatDirection-curveEnd);\n
203           }\n
204           \n
205           // define the control points of hermite curve, composed with two segments
206           // calulation is carried out on the 2D plane which is passing through both current and original center and vertical to the image plane
207           float currentLength = uCommonParameters[3][3];\n
208           float originalLength =  abs(originalCenter.x/curveDirection.x);\n
209           float height = uCommonParameters[3][2];\n
210           float percentage = currentLength/originalLength;\n
211           //vec2 SegmentOneControlPoint0 = vec2(0.0, 0.0);
212           vec2 SegmentOneControlPoint1 = vec2((0.65*percentage - 0.15)*originalLength, (0.8 + 0.2 * percentage)*height); \n
213           vec2 SegmentTwoControlPoint0 = SegmentOneControlPoint1;\n
214           vec2 SegmentTwoControlPoint1 = vec2(currentLength, 0.0); \n
215           vec2 SegmentOneTangentVector0 = SegmentOneControlPoint1;\n
216           vec2 SegmentOneTangentVector1 = vec2(0.5*originalLength,0.0);\n
217           vec2 SegmentTwoTangentVector0 = SegmentOneTangentVector1;\n
218           vec2 SegmentTwoTangentVector1 = SegmentOneTangentVector1;\n
219           \n
220           // calulate the corresponding curve point position and its tangent vector
221           // it is a linear mapping onto nonlinear curves, might cause some unwanted deformation
222           // but as there are no analytical method to calculate the curve length on arbitrary segment
223           // no efficient way to solve this nonlinear mapping, Numerical approximation would cost too much computation in shader
224           vec2 curvePoint2D;\n
225           vec2 tangent;\n
226           float t0 = lengthOnCurve / originalLength;\n
227           if(t0<=0.5)\n
228           {\n
229             float t = 2.0*t0;\n
230             float t_2 = t*t;\n
231             float t_3 = t*t_2;\n
232             curvePoint2D = (-2.0*t_3+3.0*t_2)*SegmentOneControlPoint1
233                          + (t_3-2.0*t_2+t)*SegmentOneTangentVector0 + (t_3-t_2)*SegmentOneTangentVector1;\n
234             tangent = (-6.0*t_2+6.0*t)*SegmentOneControlPoint1
235                     + (3.0*t_2-4.0*t+1.0)*SegmentOneTangentVector0 + (3.0*t_2-2.0*t)*SegmentOneTangentVector1;\n
236           }\n
237           else\n
238           {\n
239             float t = 2.0*t0-1.0;\n
240             float t_2 = t*t;\n
241             float t_3 = t*t_2;\n
242             curvePoint2D = (2.0*t_3-3.0*t_2+1.0)*SegmentTwoControlPoint0 + (-2.0*t_3+3.0*t_2)*SegmentTwoControlPoint1
243                          + (t_3-2.0*t_2+t)*SegmentTwoTangentVector0 + (t_3-t_2)*SegmentTwoTangentVector1;\n
244             tangent = (6.0*t_2-6.0*t)*SegmentTwoControlPoint0 + (-6.0*t_2+6.0*t)*SegmentTwoControlPoint1
245                     + (3.0*t_2-4.0*t+1.0)*SegmentTwoTangentVector0 + (3.0*t_2-2.0*t)*SegmentTwoTangentVector1;\n
246             // a trick to eliminate some optical illusion caused by the gradient matter of normal in per-fragment shading
247             // which is caused by linear interpolation of normal vs. nonlinear lighting
248             // will notice some artifact in the areas with dramatically normal changes, so compress the normal differences here
249             tangent.y *=  min(1.0, length(position.xyz - vanishingPoint) / uPageSize.y ); \n
250           }\n
251           vec3 curvePoint = vec3(curveEnd - curvePoint2D.x*curveDirection,max(0.0,curvePoint2D.y));\n
252           vec3 tangentVector = vec3(-tangent.x*curveDirection,tangent.y);\n
253           \n
254           // locate the new vertex position on the line passing through both vanishing point and the calculated curve point position
255           vec3 curLiftDirection = vec3(0.0,-1.0,0.0);\n
256           if(currentCenter.y != originalCenter.y)\n
257           {\n
258             curLiftDirection = normalize(curvePoint - vanishingPoint);\n
259             tangentVector *= (curveDirection.y > 0.0) ? -1.0 : 1.0;\n
260           // an heuristic adjustment here, to compensate the linear parameter mapping onto the nonlinear curve
261             float Y0 = position.y - curveDirection.y * (position.x/curveDirection.x); \n
262             float proportion;
263             float refLength;\n
264             if(abs(Y0-vanishingPoint.y) > abs(curveEnd.y-vanishingPoint.y)) \n
265             {\n
266               proportion = abs(curveEnd.y - Y0) / (abs(curveEnd.y-Y0)+abs(curveEnd.y - vanishingPoint.y)); \n
267               refLength = proportion*length(originalCenter-vanishingPoint.xy) / (proportion-1.0); \n
268             }\n
269             else\n
270             {\n
271               proportion = abs(curveEnd.y - Y0) / abs(curveEnd.y - vanishingPoint.y);\n
272               refLength = proportion*length(originalCenter-vanishingPoint.xy); \n
273             }\n
274             float Y1 = currentCenter.y - (normalize(currentCenter-vanishingPoint.xy)).y * refLength; \n
275             position.y = mix(Y0, Y1, t0); \n
276           }\n
277           position.xz = curvePoint.xz - lengthFromCurve*curLiftDirection.xz;\n
278           // calculate the normal vector, will be used for lighting
279           normal = cross(curLiftDirection, normalize(tangentVector));\n
280           // the signature of Z is decided by the page turning direction:
281           // from left to right(negative); from right to left (positive)
282           position.z *= -uIsTurningBack;\n
283           normal.xy *= -uIsTurningBack;\n
284         }\n
285         // change the coordinate origin from the top-left of the page to its center
286         position.xy -= uPageSize * 0.5; \n
287       }\n
288       position.z += aPosition.z;\n
289       gl_Position = uMvpMatrix * position;\n
290      // varying parameters for fragment shader
291       vTexCoord = aTexCoord;
292       vNormal = uNormalMatrix*normal;\n
293       vPosition = uModelView * position;\n
294   );
295
296   std::string vertexShaderWithFakedShadow = MAKE_STRING(
297       // display shadow, the fake shadow value is calculated according to the height and the distance from page edge
298       vTexCoord.x = (aTexCoord.x-sTextureRect.s) /( 1.0 - uShadowWidth ) + sTextureRect.s;\n
299       vTexCoord.y = ( aTexCoord.y-sTextureRect.t-0.5*uShadowWidth*(sTextureRect.q-sTextureRect.t) )/( 1.0 - uShadowWidth ) + sTextureRect.t;\n
300       float heightCoef = (1.0 + position.z*uIsTurningBack*3.0 / uPageSize.x) * 0.6;
301       vEdgeShadow = clamp(0.9 - heightCoef, 0.0, 0.9 ); \n
302       if( vTexCoord.y >= sTextureRect.q || vTexCoord.y <= sTextureRect.t || vTexCoord.x >= sTextureRect.p  )\n
303       {\n
304         float inversedShadowWidth = (1.0-uShadowWidth) / uShadowWidth ;\n
305         float alpha1 = (vTexCoord.x-sTextureRect.p) * inversedShadowWidth / (sTextureRect.p - sTextureRect.s);\n
306         inversedShadowWidth = 2.0 * inversedShadowWidth  / (sTextureRect.q - sTextureRect.t); \n
307         float alpha2 = (vTexCoord.y-sTextureRect.q) * inversedShadowWidth;\n
308         float alpha3 = (sTextureRect.t-vTexCoord.y) * inversedShadowWidth;\n
309         float alpha;\n
310         if(alpha1 > 0.0 && alpha2 > 0.0) alpha = sqrt(alpha2*alpha2+alpha1*alpha1)/sqrt(1.0 + max(alpha1,alpha2)*max(alpha1,alpha2));\n //bottom-right corner
311         else if(alpha1 > 0.0 && alpha3 > 0.0) alpha = sqrt(alpha3*alpha3+alpha1*alpha1)/sqrt(1.0+max(alpha1,alpha3)*max(alpha1,alpha3));\n //top-right corner
312         else alpha = max(alpha1,max(alpha2,alpha3)); \n
313         alpha = 0.9 - alpha*0.9;\n
314         vEdgeShadow = clamp(alpha - heightCoef, 0.0, 0.9 ); \n
315       }\n
316   );
317
318   std::string vertexShaderEnd("}");
319
320   std::string fragmentShaderPartOne = MAKE_STRING(
321     uniform vec2 uPageSize;\n
322     uniform vec2 uSpineShadowParameter;\n
323     varying vec3 vNormal;\n
324     varying vec4 vPosition;\n
325     varying float vEdgeShadow;\n
326     \n
327     void main()\n
328     {\n
329       // need to re-normalize the interpolated normal
330       vec3 normal = normalize(vNormal);\n
331       vec4 texel;\n
332       float spineShadowCoef = 1.0; \n
333    );
334
335   std::string fragmentShaderWithFakedShadow = MAKE_STRING(
336       if( vTexCoord.y > sTextureRect.q || vTexCoord.y < sTextureRect.t || vTexCoord.x > sTextureRect.p  )\n
337          texel = vec4(0.0,0.0,0.0,vEdgeShadow);
338       else \n
339   );
340
341   std::string fragmentShaderPartTwo = MAKE_STRING(
342       { \n
343         // display page content
344         // display back image of the page, flip the texture
345         if(  dot(vPosition.xyz, normal) > 0.0 ) texel = texture2D( sTexture, vec2( sTextureRect.p+sTextureRect.s-vTexCoord.x, vTexCoord.y ) );\n
346         // display front image of the page
347         else texel = texture2D( sTexture, vTexCoord );\n
348         // display book spine, a stripe of shadowed texture
349         float pixelPos = (vTexCoord.x-sTextureRect.s)*uPageSize.x; \n
350         if(pixelPos < uSpineShadowParameter.x) \n
351         {\n
352           float x = pixelPos - uSpineShadowParameter.x;\n
353           float y = sqrt( uSpineShadowParameter.x*uSpineShadowParameter.x - x*x);\n
354           spineShadowCoef = normalize( vec2( uSpineShadowParameter.y*x/uSpineShadowParameter.x, y ) ).y;\n
355         }\n
356       }\n
357     // calculate the lighting
358     // set the ambient color as vec3(0.4);
359       float lightColor = abs( normal.z ) * 0.6 + 0.4;\n
360       gl_FragColor = vec4( ( spineShadowCoef* lightColor)* texel.rgb , texel.a ) * uColor;\n
361     }
362   );
363
364   // Create the implementation, temporarily owned on stack,
365   Dali::ShaderEffect shaderEffectCustom;
366   std::ostringstream vertexShaderStringStream;
367   std::ostringstream fragmentShaderStringStream;
368   if( enableBlending )
369   {
370     vertexShaderStringStream<< vertexShader << vertexShaderWithFakedShadow << vertexShaderEnd;
371     fragmentShaderStringStream<< fragmentShaderPartOne << fragmentShaderWithFakedShadow << fragmentShaderPartTwo;
372     shaderEffectCustom = Dali::ShaderEffect::New( vertexShaderStringStream.str(), fragmentShaderStringStream.str(), GeometryType( GEOMETRY_TYPE_IMAGE ),
373             ShaderEffect::GeometryHints( ShaderEffect::HINT_GRID | ShaderEffect::HINT_DEPTH_BUFFER | ShaderEffect::HINT_BLENDING) );
374   }
375   else
376   {
377     vertexShaderStringStream<< vertexShader << vertexShaderEnd;
378     fragmentShaderStringStream<< fragmentShaderPartOne << fragmentShaderPartTwo;
379     shaderEffectCustom = Dali::ShaderEffect::New( vertexShaderStringStream.str(), fragmentShaderStringStream.str(), GeometryType( GEOMETRY_TYPE_IMAGE ),
380             ShaderEffect::GeometryHints( ShaderEffect::HINT_GRID | ShaderEffect::HINT_DEPTH_BUFFER ) );
381   }
382
383   PageTurnEffect* shaderImpl = new PageTurnEffect();
384   Dali::Toolkit::PageTurnEffect handle = Toolkit::PageTurnEffect( shaderEffectCustom, shaderImpl );
385
386   shaderImpl->Initialize( handle );
387
388   Vector2 defaultPageSize = Dali::Stage::GetCurrent().GetSize();
389   Matrix zeroMatrix(true);
390   handle.SetUniform( "uCommonParameters", zeroMatrix );
391   handle.SetUniform( PAGE_SIZE_PROPERTY_NAME, defaultPageSize/(1.f-DEFAULT_SHADOW_WIDTH) );
392   handle.SetUniform( SHADOW_WIDTH_PROPERTY_NAME, DEFAULT_SHADOW_WIDTH );
393   handle.SetUniform( SPINE_SHADOW_PARAMETER_PROPERTY_NAME, DEFAULT_SPINE_SHADOW_PARAMETER );
394
395   shaderImpl->mOriginalCenterPropertyIndex = handle.RegisterProperty( ORIGINAL_CENTER_PROPERTY_NAME, Vector2( defaultPageSize[0], defaultPageSize[1]*0.5f ) );
396   shaderImpl->mCurrentCenterPropertyIndex = handle.RegisterProperty( CURRENT_CENTER_PROPERTY_NAME, Vector2( defaultPageSize[0], defaultPageSize[1]*0.5f ) );
397   shaderImpl->mInternalConstraint = Constraint::New<Matrix>( handle.GetPropertyIndex( "uCommonParameters" ),
398                                                         LocalSource( shaderImpl->mOriginalCenterPropertyIndex ),
399                                                         LocalSource( shaderImpl->mCurrentCenterPropertyIndex ),
400                                                         LocalSource( handle.GetPropertyIndex( PAGE_SIZE_PROPERTY_NAME ) ),
401                                                         CommonParametersConstraint() );
402   handle.ApplyConstraint( shaderImpl->mInternalConstraint );
403
404   // setting isTurningBack to -1.0f here means turning page forward
405   handle.SetUniform( IS_TURNING_BACK_PROPERTY_NAME, -1.0f );
406
407   return handle;
408 }
409
410 void PageTurnEffect::SetPageSize(const Vector2& pageSize)
411 {
412   mShaderEffect.SetUniform(PAGE_SIZE_PROPERTY_NAME, pageSize);
413 }
414
415 void PageTurnEffect::SetOriginalCenter(const Vector2& originalCenter)
416 {
417   mShaderEffect.SetProperty( mOriginalCenterPropertyIndex, originalCenter );
418 }
419
420 void PageTurnEffect::SetCurrentCenter(const Vector2& currentCenter)
421 {
422   mShaderEffect.SetProperty( mCurrentCenterPropertyIndex, currentCenter );
423 }
424
425 void PageTurnEffect::SetIsTurningBack(bool isTurningBack)
426 {
427   float direction = isTurningBack ? 1.0f : -1.0f;
428   mShaderEffect.SetUniform(IS_TURNING_BACK_PROPERTY_NAME, direction);
429 }
430
431 void PageTurnEffect::SetShadowWidth(float shadowWidth)
432 {
433   mShaderEffect.SetUniform( SHADOW_WIDTH_PROPERTY_NAME, shadowWidth );
434 }
435
436 void PageTurnEffect::SetSpineShadowParameter(const Vector2& spineShadowParameter)
437 {
438   mShaderEffect.SetUniform( SPINE_SHADOW_PARAMETER_PROPERTY_NAME, spineShadowParameter);
439 }
440
441 void PageTurnEffect::ApplyInternalConstraint()
442 {
443   mShaderEffect.ApplyConstraint( mInternalConstraint );
444 }
445
446 const std::string& PageTurnEffect::GetPageSizePropertyName() const
447 {
448   return PAGE_SIZE_PROPERTY_NAME;
449 }
450
451 const std::string& PageTurnEffect::GetOriginalCenterPropertyName() const
452 {
453   return ORIGINAL_CENTER_PROPERTY_NAME;
454 }
455
456 const std::string& PageTurnEffect::GetCurrentCenterPropertyName() const
457 {
458   return CURRENT_CENTER_PROPERTY_NAME;
459 }
460
461 void PageTurnEffect::Initialize( Dali::ShaderEffect shaderEffect )
462 {
463   // Save a reference to the shader handle
464   mShaderEffect = shaderEffect;
465 }
466
467 } // namespace Internal
468
469 } // namespace Toolkit
470
471 } // namespace Dali