Fix for slider labels
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / public-api / shader-effects / soft-button-effect.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
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
18 // EXTERNAL INCLUDES
19 #include <dali/public-api/animation/active-constraint.h>
20 #include <dali/public-api/animation/constraint.h>
21 #include <dali/public-api/object/property-input.h>
22
23 // INTERNAL INCLUDES
24 #include <dali-toolkit/public-api/shader-effects/soft-button-effect.h>
25
26 namespace Dali
27 {
28
29 namespace Toolkit
30 {
31
32 namespace
33 {
34
35 const std::string SOFT_BUTTON_LIGHTING_INDENTATION_AMOUNT_PROPERTY_NAME( "uLightingIndentationAmount" );
36 const std::string SOFT_BUTTON_TEXTURE_DISTORTION_AMOUNT_PROPERTY_NAME( "uTextureDistortAmount" );
37 const std::string SOFT_BUTTON_AMBIENT_LIGHT_AMOUNT_PROPERTY_NAME( "uAmbientLight" );
38 const std::string SOFT_BUTTON_DIFFUSE_LIGHT_PROPERTY_NAME( "uDiffuseLight" );
39 const std::string SOFT_BUTTON_LIGHTING_MULTIPLIER_PROPERTY_NAME( "uLightMultiplier" );
40 const std::string SOFT_BUTTON_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME( "uInsideCircleSizeScale" );
41 const std::string SOFT_BUTTON_RECIP_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME( "uRecipInsideCircleSizeScale" );
42 const std::string SOFT_BUTTON_OUTSIDE_SHAPE_DEPTH_PROPERTY_NAME( "uOutsideCircleDepth" );
43 const std::string SOFT_BUTTON_EFFECT_PIXEL_AREA_PROPERTY_NAME( "uEffectRegion" );
44 const std::string SOFT_BUTTON_RECTANGLE_SIZE_SCALE_PROPERTY_NAME( "uRectangleSizeScale" );
45
46
47 // factors that scale the look, defaults
48 const float SOFT_BUTTON_LIGHTING_INDENTATION_AMOUNT_DEFAULT = 0.0f;
49 const float SOFT_BUTTON_TEXTURE_DISTORTION_AMOUNT_DEFAULT = 0.0f;
50 const float SOFT_BUTTON_AMBIENT_LIGHT_AMOUNT_DEFAULT = 0.15f;
51 const Vector3 SOFT_BUTTON_DIFFUSE_LIGHT_DEFAULT = Vector3(0.0f, 0.7070168f, 0.7071068f);
52 const float SOFT_BUTTON_LIGHTING_MULTIPLIER_DEFAULT = 1.2f;
53 const float SOFT_BUTTON_INSIDE_SHAPE_SIZE_SCALE_DEFAULT = 0.75f;
54 const float SOFT_BUTTON_OUTSIDE_SHAPE_DEPTH_DEFAULT = Math::PI * 0.05f;
55 const Vector4 SOFT_BUTTON_EFFECT_PIXEL_AREA_DEFAULT = Vector4(0.0f, 0.0f, 1.0f, 1.0f);
56 const float SOFT_BUTTON_RECTANGLE_SIZE_SCALE_DEFAULT = 0.5f;
57
58 } // namespace
59
60 /**
61  * ReciprocalConstraint
62  *
63  * f(current, property) = 1.0 / property
64  */
65 struct ReciprocalConstraint
66 {
67   ReciprocalConstraint(){}
68
69   float operator()(const float current, const PropertyInput& property)
70   {
71     return 1.0f / property.GetFloat();
72   }
73 };
74
75
76 ////////////////////////////////////////////////////
77 //
78 // Soft button shader / actor tweaking parameters
79 //
80
81
82 SoftButtonEffect::SoftButtonEffect()
83 {
84 }
85
86 //Call the Parent copy constructor to add reference to the implementation for this object
87 SoftButtonEffect::SoftButtonEffect(ShaderEffect handle)
88 :ShaderEffect(handle)
89 {
90 }
91
92 SoftButtonEffect::~SoftButtonEffect()
93 {
94 }
95
96 SoftButtonEffect SoftButtonEffect::New(Type type)
97 {
98   std::string vertexSource;
99   vertexSource =  "precision mediump float;\n"
100     "uniform vec3 uDiffuseLight;\n"
101     "uniform float uAmbientLight;\n"
102     "uniform float uLightMultiplier;\n"
103     "uniform vec4 uEffectRegion;\n"
104     "varying vec2 vCentredCoord;\n"
105
106     "const vec3 norm = vec3(0.0, 0.0, 1.0);\n"
107
108     "void main()\n"
109     "{\n"
110     "  vTexCoord = aTexCoord;\n"
111     // Get the rect coords of the effect region in -1..1 range, i.e. circle centred around the center of the rect
112     // Done in the vertex shader itself to make use of gl interpolation for varying.
113     "  vCentredCoord = vec2( ( (vTexCoord.x - uEffectRegion.x)/(uEffectRegion.z - uEffectRegion.x) * 2.0 - 1.0 ), ( (vTexCoord.y - uEffectRegion.y)/(uEffectRegion.w - uEffectRegion.y) * 2.0 - 1.0  ) );\n"
114     "  gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n"
115     "}\n";
116
117   std::string fragmentSourceFixed;
118   fragmentSourceFixed =  "precision mediump float;\n"
119
120     "uniform vec3 uDiffuseLight;\n"
121     "uniform float uAmbientLight;\n"
122     "uniform float uLightMultiplier;\n"
123     "varying vec2 vCentredCoord;\n"
124
125     "const vec3 norm = vec3(0.0, 0.0, 1.0);\n"
126
127     "void main()\n"
128     "{\n"
129     "   vec4 col = texture2D(sTexture, vTexCoord);\n"
130     // calc lighting
131     "   float lighting = (dot(uDiffuseLight, norm) + uAmbientLight) * uLightMultiplier;\n"
132     // output col = image * light
133     // use the lighting value for colors only
134     "   gl_FragColor = vec4(col.rgb * uColor.rgb * lighting, col.a * uColor.a);\n"
135     "}\n";
136
137   std::string fragmentSourceElliptical;
138   fragmentSourceElliptical =  "precision mediump float;\n"
139
140     "uniform float uLightingIndentationAmount;\n"
141     "uniform float uTextureDistortAmount;\n"
142     "uniform vec3 uDiffuseLight;\n"
143     "uniform float uAmbientLight;\n"
144     "uniform float uLightMultiplier;\n"
145     "uniform float uInsideCircleSizeScale;\n"
146     "uniform float uRecipInsideCircleSizeScale;\n"
147     "uniform float uOutsideCircleDepth;\n"
148     "uniform vec4 uEffectRegion;\n"
149     "varying vec2 vCentredCoord;\n"
150
151     "const float PI = 3.1415927;\n"
152
153     "void main()\n"
154     "{\n"
155       // Apply distortion only if the pixel is within the rect specified
156       "if( (vTexCoord.x > uEffectRegion.x) && (vTexCoord.x < uEffectRegion.z) && (vTexCoord.y > uEffectRegion.y) && (vTexCoord.y < uEffectRegion.w) )\n"
157       "{\n"
158       "   vec2 coord = vCentredCoord;\n"
159
160       // find a coordinate representing distance from circle centre, such that we split into inside / outside circles that can have different gradients / normals
161       "   float realDistFromCentre = length(coord);\n"
162       "   realDistFromCentre = min(1.0, realDistFromCentre);\n" // clamp corners of square to vertical normal
163       "   float distFromCentre;\n"
164       "   if(realDistFromCentre <= uInsideCircleSizeScale)\n"
165       "   {\n"
166       "     distFromCentre = realDistFromCentre * uRecipInsideCircleSizeScale * (1.0 - uOutsideCircleDepth);\n" // inside circle indent, up to outline depth
167       "   }\n"
168       "   else                                                                                                                      \n"
169       "   {\n"
170       "     distFromCentre = mix(1.0 - uOutsideCircleDepth, 1.0, (realDistFromCentre - ( uInsideCircleSizeScale)) / (1.0 - uInsideCircleSizeScale));\n" // outside circle
171       "   }\n"
172
173       // get coords in -PI..PI range, i.e. scale the circle for use by trig functions
174       "  coord *= PI;\n"
175
176       // get a z value for the distorted surface in 0..1 range, using cos for a smooth curve (note, we ignore inside / outside circles since the difference isn't noticeable visually)
177       "   vec2 cosThetaCoord = (cos(coord) * 0.5) + 0.5;\n"
178       "   float z = cosThetaCoord.x * cosThetaCoord.y;\n"
179
180       // get the normal for the distorted surface, using the fact that the derivative of cos is -sin, finding tangent vector from slope and then normal by cross product...
181       "   float sinThetaCoord = sin(distFromCentre*PI) * uLightingIndentationAmount;\n" // slope, so tangent vec is (1.0, -sin)
182       // ...2D normal vector along distFromCentre vec is (sin, 1.0), convert to components in 3D.
183       "   vec3 norm = normalize(vec3(coord.x * sinThetaCoord, coord.y * sinThetaCoord, 1.0));\n"
184
185       // form surface z and project texture onto it.
186       "   float indentAmount = 1.0 / (1.0 - (z * uTextureDistortAmount));\n"
187       "   vec2 distortedCoord = vCentredCoord * indentAmount;\n"
188
189       // Convert the rect coordinates in -1 to 1 range back to the original coordinates
190       "   vec2 texCoord = vec2( ( (distortedCoord.x + 1.0)*(0.5) * (uEffectRegion.z - uEffectRegion.x) + uEffectRegion.x ), ( (distortedCoord.y + 1.0)*(0.5) * (uEffectRegion.w - uEffectRegion.y) + uEffectRegion.y  ) );  \n"
191       "   vec4 col = texture2D(sTexture, texCoord);\n"
192
193       // calc lighting
194       "   float lighting = (dot(uDiffuseLight, norm) + uAmbientLight) * uLightMultiplier;\n"
195       "  gl_FragColor = vec4(col.rgb * uColor.rgb * lighting, col.a * uColor.a);\n"
196       "}\n"
197       "else\n"
198       "{\n"
199       "  vec4 col = texture2D(sTexture, vTexCoord);\n"
200       "  float lighting = (dot(uDiffuseLight, vec3(0.0, 0.0, 1.0)) + uAmbientLight) * uLightMultiplier;\n"
201       "  gl_FragColor = vec4(col.rgb * uColor.rgb * lighting, col.a * uColor.a);\n"
202       "}\n"
203     "}\n";
204
205   std::string fragmentSourceRectangular;
206   fragmentSourceRectangular =  "precision mediump float;\n"
207
208     "uniform float uLightingIndentationAmount;\n"
209     "uniform float uTextureDistortAmount;\n"
210     "uniform vec3 uDiffuseLight;\n"
211     "uniform float uAmbientLight;\n"
212     "uniform float uLightMultiplier;\n"
213     "uniform float uInsideCircleSizeScale;\n"
214     "uniform float uRecipInsideCircleSizeScale;\n"
215     "uniform float uOutsideCircleDepth;\n"
216     "uniform float uRectangleSizeScale;\n"
217     "uniform vec4 uEffectRegion;\n"
218     "varying vec2 vCentredCoord;\n"
219
220     "const float PI = 3.1415927;\n"
221
222     "void main()\n"
223     "{\n"
224       // Apply distortion only if the pixel is within the rect specified
225       "if( (vTexCoord.x > uEffectRegion.x) && (vTexCoord.x < uEffectRegion.z) && (vTexCoord.y > uEffectRegion.y) && (vTexCoord.y < uEffectRegion.w) )\n"
226       "{ \n"
227         // get the rect coords to -1..1 range, i.e. circle centred around the center of the rect
228         "   vec2 centredCoord = vCentredCoord;\n"
229         // clamp coords such that the circle is split into 4 pieces that lie in the corners of the actor. uRectangleScale is the distance along each axis from the centre
230         // of the actor, e.g. 0.5 is half way along an axis from centre to actor edge.
231         "   vec2 clampedCoord;\n"
232         "   if(centredCoord.x > 0.0)\n"
233         "   {\n"
234         "     if(centredCoord.x < uRectangleSizeScale)\n"
235         "     {\n"
236                 // we are in a rectangular region along this axis, clamp coord to be same as centre pixel
237         "       clampedCoord.x = 0.0;\n"
238         "     }\n"
239         "     else\n"
240         "     {\n"
241                 // we are outside rectangular region along this axis, so we want curvature.
242         "       clampedCoord.x = smoothstep(0.0, 1.0, (centredCoord.x - uRectangleSizeScale) / (1.0 - uRectangleSizeScale));\n"
243         "     }\n"
244         "   }\n"
245         "   else\n"
246         "   {\n"
247         "     if(centredCoord.x > -uRectangleSizeScale)\n"
248         "     {\n"
249                 // we are in a rectangular region along this axis, clamp coord to be same as centre pixel
250         "       clampedCoord.x = 0.0;\n"
251         "     }\n"
252         "     else\n"
253         "     {\n"
254                 // we are outside rectangular region along this axis, so we want curvature.
255         "       clampedCoord.x = -smoothstep(0.0, 1.0, (centredCoord.x + uRectangleSizeScale) / (uRectangleSizeScale - 1.0));\n"
256         "     }\n"
257         "   }\n"
258         "   if(centredCoord.y > 0.0)\n"
259         "   {\n"
260         "     if(centredCoord.y < uRectangleSizeScale)\n"
261         "     {\n"
262                 // we are in a rectangular region along this axis, clamp coord to be same as centre pixel
263         "       clampedCoord.y = 0.0;\n"
264         "     }\n"
265         "     else\n"
266         "     {\n"
267                 // we are outside rectangular region along this axis, so we want curvature.
268         "       clampedCoord.y = smoothstep(0.0, 1.0, (centredCoord.y - uRectangleSizeScale) / (1.0 - uRectangleSizeScale));\n"
269         "     }\n"
270         "   }\n"
271         "   else\n"
272         "   {\n"
273         "     if(centredCoord.y > -uRectangleSizeScale)\n"
274         "     {\n"
275                 // we are in a rectangular region along this axis, clamp coord to be same as centre pixel
276         "       clampedCoord.y = 0.0;\n"
277         "     }\n"
278         "     else\n"
279         "     {\n"
280                 // we are outside rectangular region along this axis, so we want curvature.
281         "       clampedCoord.y = -smoothstep(0.0, 1.0, (centredCoord.y + uRectangleSizeScale) / (uRectangleSizeScale - 1.0));\n"
282         "     }\n"
283         "   }\n"
284         // get coords in -PI..PI range, i.e. scale above circle for use by trig functions
285         "   vec2 thetaCoord = clampedCoord * PI;\n"
286         // get a z value for the distorted surface in 0..1 range, using cos for a smooth curve (note, we ignore inside / outside circles since the difference isn't noticeable visually)
287         "   vec2 cosThetaCoord = (cos(thetaCoord) * 0.5) + 0.5;\n"
288         "   float z = cosThetaCoord.x * cosThetaCoord.y;\n"
289         // find a coordinate representing distance from circle centre, such that we split into inside / outside circles that can have different gradients / normals
290         "   float realDistFromCentre = length(thetaCoord);\n"
291         "   realDistFromCentre = min(PI, realDistFromCentre);\n" // clamp corners of square to vertical normal
292         "   float distFromCentre;\n"
293         "   if(realDistFromCentre <= PI * uInsideCircleSizeScale)\n"
294         "   {\n"
295         "     distFromCentre = realDistFromCentre * uRecipInsideCircleSizeScale * (PI - (uOutsideCircleDepth * PI)) / PI;\n" // inside circle indent, up to outline depth
296         "   }\n"
297         "   else\n"
298         "   {\n"
299         "     distFromCentre = mix(PI - (uOutsideCircleDepth * PI), PI, (realDistFromCentre - ( PI * uInsideCircleSizeScale)) / (PI - (PI * uInsideCircleSizeScale)));\n" // outside circle
300         "   }\n"
301         // get the normal for the distorted surface, using the fact that the derivative of cos is -sin, finding tangent vector from slope and then normal by cross product...
302         "   float sinThetaCoord = sin(distFromCentre) * uLightingIndentationAmount;\n" // slope, so tangent vec is (1.0, -sin)
303         // ...2D normal vector along distFromCentre vec is (sin, 1.0), convert to components in 3D.
304         "   vec3 norm = normalize(vec3(thetaCoord.x * sinThetaCoord, thetaCoord.y * sinThetaCoord, 1.0));\n"
305         // form surface z and project texture onto it.
306         "   float indentAmount = 1.0 / (1.0 - (z * uTextureDistortAmount));\n"
307         "   vec2 distortedCoord = centredCoord * indentAmount;\n"
308         // Convert the rect coordinates in -1 to 1 range back to the original coordinates
309         "   vec2 texCoord = vec2( ( (distortedCoord.x + 1.0)/(2.0) * (uEffectRegion.z - uEffectRegion.x) + uEffectRegion.x ), ( (distortedCoord.y + 1.0)/(2.0) * (uEffectRegion.w - uEffectRegion.y) + uEffectRegion.y  ) );\n"
310         "   vec4 col = texture2D(sTexture, texCoord);\n"
311         // calc lighting
312         "   float lighting = (dot(uDiffuseLight, norm) + uAmbientLight) * uLightMultiplier;\n"
313         // output col = image * light
314         // use the lighting value for colors only
315         "   gl_FragColor = vec4(col.rgb * uColor.rgb * lighting, col.a * uColor.a);\n"
316
317       "}\n"
318       "else\n"
319       "{\n"
320         "   vec4 col = texture2D(sTexture, vTexCoord);\n"
321         "   float lighting = (dot(uDiffuseLight, vec3(0.0, 0.0, 1.0)) + uAmbientLight) * uLightMultiplier;\n"
322         "   gl_FragColor = vec4(col.rgb * uColor.rgb * lighting, col.a * uColor.a);\n"
323       "} \n"
324     "}\n";
325
326
327   //////////////////////////////////////
328   // Create shader effect
329   //
330   //
331
332   ShaderEffect shader;
333   switch(type)
334   {
335     case RECTANGULAR:
336       shader = ShaderEffect::New( vertexSource, fragmentSourceRectangular, GeometryType( GEOMETRY_TYPE_IMAGE ), ShaderEffect::GeometryHints( ShaderEffect::HINT_NONE ));
337       break;
338
339     case ELLIPTICAL:
340       shader = ShaderEffect::New( vertexSource, fragmentSourceElliptical, GeometryType( GEOMETRY_TYPE_IMAGE ), ShaderEffect::GeometryHints( ShaderEffect::HINT_NONE ));
341       break;
342
343     case FIXED:
344     default:
345       shader = ShaderEffect::New( vertexSource, fragmentSourceFixed, GeometryType( GEOMETRY_TYPE_IMAGE ), ShaderEffect::GeometryHints( ShaderEffect::HINT_NONE ));
346       break;
347   }
348   SoftButtonEffect handle( shader );
349
350
351   //////////////////////////////////////
352   // Register uniform properties
353   //
354   //
355
356   // factors that scale the look, defaults
357   handle.SetUniform(SOFT_BUTTON_AMBIENT_LIGHT_AMOUNT_PROPERTY_NAME, SOFT_BUTTON_AMBIENT_LIGHT_AMOUNT_DEFAULT);
358   handle.SetUniform(SOFT_BUTTON_DIFFUSE_LIGHT_PROPERTY_NAME, SOFT_BUTTON_DIFFUSE_LIGHT_DEFAULT);
359   handle.SetUniform(SOFT_BUTTON_LIGHTING_MULTIPLIER_PROPERTY_NAME, SOFT_BUTTON_LIGHTING_MULTIPLIER_DEFAULT);
360   if(FIXED != type)
361   {
362     handle.SetUniform(SOFT_BUTTON_LIGHTING_INDENTATION_AMOUNT_PROPERTY_NAME, SOFT_BUTTON_LIGHTING_INDENTATION_AMOUNT_DEFAULT);
363     handle.SetUniform(SOFT_BUTTON_TEXTURE_DISTORTION_AMOUNT_PROPERTY_NAME, SOFT_BUTTON_TEXTURE_DISTORTION_AMOUNT_DEFAULT);
364     handle.SetUniform(SOFT_BUTTON_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME, SOFT_BUTTON_INSIDE_SHAPE_SIZE_SCALE_DEFAULT);
365     handle.SetUniform(SOFT_BUTTON_RECIP_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME, 1.0f / SOFT_BUTTON_INSIDE_SHAPE_SIZE_SCALE_DEFAULT);
366     handle.SetUniform(SOFT_BUTTON_OUTSIDE_SHAPE_DEPTH_PROPERTY_NAME, SOFT_BUTTON_OUTSIDE_SHAPE_DEPTH_DEFAULT);
367     handle.SetUniform(SOFT_BUTTON_EFFECT_PIXEL_AREA_PROPERTY_NAME, SOFT_BUTTON_EFFECT_PIXEL_AREA_DEFAULT);
368     if(RECTANGULAR == type)
369     {
370       handle.SetUniform(SOFT_BUTTON_RECTANGLE_SIZE_SCALE_PROPERTY_NAME, SOFT_BUTTON_RECTANGLE_SIZE_SCALE_DEFAULT);
371     }
372
373     // precalc 1.0 / uInsideCircleSizeScale on CPU to save shader insns, using constraint to tie to the normal property
374     Dali::Property::Index insideCircleSizeScalePropertyIndex = handle.GetPropertyIndex(SOFT_BUTTON_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME);
375     Dali::Property::Index recipInsideCircleSizeScalePropertyIndex = handle.GetPropertyIndex(SOFT_BUTTON_RECIP_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME);
376     Constraint constraint = Constraint::New<float>( recipInsideCircleSizeScalePropertyIndex, LocalSource(insideCircleSizeScalePropertyIndex), ReciprocalConstraint());
377     handle.ApplyConstraint(constraint);
378   }
379
380   return handle;
381 }
382
383 const std::string& SoftButtonEffect::GetLightingIndentationAmountPropertyName() const
384 {
385   return SOFT_BUTTON_LIGHTING_INDENTATION_AMOUNT_PROPERTY_NAME;
386 }
387
388 const std::string& SoftButtonEffect::GetTextureDistortionAmountPropertyName() const
389 {
390   return SOFT_BUTTON_TEXTURE_DISTORTION_AMOUNT_PROPERTY_NAME;
391 }
392
393 const std::string& SoftButtonEffect::GetAmbientLightAmountPropertyName() const
394 {
395   return SOFT_BUTTON_AMBIENT_LIGHT_AMOUNT_PROPERTY_NAME;
396 }
397
398 const std::string& SoftButtonEffect::GetDiffuseLightPropertyName() const
399 {
400   return SOFT_BUTTON_DIFFUSE_LIGHT_PROPERTY_NAME;
401 }
402
403 const std::string& SoftButtonEffect::GetLightingMultiplierPropertyName() const
404 {
405   return SOFT_BUTTON_LIGHTING_MULTIPLIER_PROPERTY_NAME;
406 }
407
408 const std::string& SoftButtonEffect::GetInsideShapeSizeScalePropertyName() const
409 {
410   return SOFT_BUTTON_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME;
411 }
412
413 const std::string& SoftButtonEffect::GetOutsideShapeDepthPropertyName() const
414 {
415   return SOFT_BUTTON_OUTSIDE_SHAPE_DEPTH_PROPERTY_NAME;
416 }
417
418 const std::string& SoftButtonEffect::GetEffectPixelAreaPropertyName() const
419 {
420   return SOFT_BUTTON_EFFECT_PIXEL_AREA_PROPERTY_NAME;
421 }
422
423 const std::string& SoftButtonEffect::GetRectangleSizeScalePropertyName() const
424 {
425   return SOFT_BUTTON_RECTANGLE_SIZE_SCALE_PROPERTY_NAME;
426 }
427
428 }
429
430 }