Implementation of BorderRenderer and apply it to Magnifier
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / renderers / border / border-renderer.cpp
1 /*
2  * Copyright (c) 2015 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 // CLASS HEADER
19 #include "border-renderer.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 //INTERNAL INCLUDES
25 #include <dali-toolkit/internal/controls/renderers/renderer-factory-impl.h>
26 #include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
27 #include <dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h>
28
29 namespace Dali
30 {
31
32 namespace Toolkit
33 {
34
35 namespace Internal
36 {
37
38 namespace
39 {
40 const char * const COLOR_NAME("border-color");
41 const char * const COLOR_UNIFORM_NAME("uBorderColor");
42 const char * const SIZE_NAME("border-size");
43 const char * const SIZE_UNIFORM_NAME("uBorderSize");
44
45 const char * const POSITION_ATTRIBUTE_NAME("aPosition");
46 const char * const DRIFT_ATTRIBUTE_NAME("aDrift");
47 const char * const INDEX_NAME("indices");
48
49
50 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
51   attribute mediump vec2 aPosition;\n
52   attribute mediump vec2 aDrift;\n
53   uniform mediump mat4 uMvpMatrix;\n
54   uniform mediump vec3 uSize;\n
55   uniform mediump float uBorderSize;\n
56   \n
57   void main()\n
58   {\n
59     vec2 position = aPosition*uSize.xy + aDrift*uBorderSize;\n
60     gl_Position = uMvpMatrix * vec4(position, 0.0, 1.0);\n
61   }\n
62 );
63
64 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
65   uniform lowp vec4 uColor;\n
66   uniform lowp vec4 uBorderColor;\n
67   \n
68   void main()\n
69   {\n
70     gl_FragColor = uBorderColor*uColor;\n
71   }\n
72 );
73 }
74
75 BorderRenderer::BorderRenderer()
76 : ControlRenderer(),
77   mBorderColor( Color::TRANSPARENT ),
78   mBorderSize( 0.f ),
79   mBorderColorIndex( Property::INVALID_INDEX ),
80   mBorderSizeIndex( Property::INVALID_INDEX )
81 {
82 }
83
84 BorderRenderer::~BorderRenderer()
85 {
86 }
87
88 void BorderRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
89 {
90   Initialize( factoryCache );
91
92   Property::Value* color = propertyMap.Find( COLOR_NAME );
93   if( !( color && color->Get(mBorderColor) ) )
94   {
95     DALI_LOG_ERROR( "Fail to provide a border color to the BorderRenderer object" );
96   }
97
98   Property::Value* size = propertyMap.Find( SIZE_NAME );
99   if( !( size && size->Get(mBorderSize) ) )
100   {
101     DALI_LOG_ERROR( "Fail to provide a border size to the BorderRenderer object" );
102   }
103 }
104
105 void BorderRenderer::SetClipRect( const Rect<int>& clipRect )
106 {
107   ControlRenderer::SetClipRect( clipRect );
108
109   //ToDo: renderer responds to the clipRect change
110 }
111
112 void BorderRenderer::DoSetOnStage( Actor& actor )
113 {
114   mBorderColorIndex = (mImpl->mRenderer).RegisterProperty( COLOR_UNIFORM_NAME, mBorderColor );
115   if( mBorderColor.a < 1.f )
116   {
117     (mImpl->mRenderer).GetMaterial().SetBlendMode( BlendingMode::ON );
118   }
119   mBorderSizeIndex = (mImpl->mRenderer).RegisterProperty( SIZE_UNIFORM_NAME, mBorderSize );
120 }
121
122 void BorderRenderer::Initialize( RendererFactoryCache& factoryCache)
123 {
124   mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::BORDER_GEOMETRY );
125   if( !(mImpl->mGeometry) )
126   {
127     mImpl->mGeometry =  CreateBorderGeometry();
128     factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry );
129   }
130
131   mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::BORDER_SHADER );
132   if( !(mImpl->mShader) )
133   {
134     mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
135     factoryCache.SaveShader( RendererFactoryCache::COLOR_SHADER, mImpl->mShader );
136   }
137 }
138
139 void BorderRenderer::SetBorderColor(const Vector4& color)
140 {
141   mBorderColor = color;
142
143   if( mImpl->mIsOnStage )
144   {
145     (mImpl->mRenderer).SetProperty( mBorderColorIndex, color );
146     if( color.a < 1.f &&  (mImpl->mRenderer).GetMaterial().GetBlendMode() != BlendingMode::ON)
147     {
148       (mImpl->mRenderer).GetMaterial().SetBlendMode( BlendingMode::ON );
149     }
150   }
151 }
152
153 void BorderRenderer::SetBorderSize( float size )
154 {
155   mBorderSize = size;
156
157   if( mImpl->mIsOnStage )
158   {
159     (mImpl->mRenderer).SetProperty( mBorderSizeIndex, size );
160   }
161 }
162
163 /**
164  * Vertices and triangles of the border geometry:
165  *
166  * vertex position = aPosition*uSize.xy + aDrift*uBorderSize;
167  *
168  * 0--1--2--3
169  * | /| /| /|
170  * |/ |/ |/ |
171  * 4--5--6--7
172  * | /|  | /|
173  * |/ |  |/ |
174  * 8--9--10-11
175  * | /| /| /|
176  * |/ |/ |/ |
177  * 12-13-14-15
178  */
179 Geometry BorderRenderer::CreateBorderGeometry()
180 {
181   const float halfWidth = 0.5f;
182   const float halfHeight = 0.5f;
183   struct BorderVertex { Vector2 position; Vector2 drift;};
184   BorderVertex borderVertexData[16] =
185   {
186       { Vector2(-halfWidth, -halfHeight), Vector2(0.f, 0.f) },
187       { Vector2(-halfWidth, -halfHeight), Vector2(1.f, 0.f) },
188       { Vector2(halfWidth, -halfHeight),  Vector2(-1.f, 0.f) },
189       { Vector2(halfWidth, -halfHeight),  Vector2(0.f, 0.f) },
190
191       { Vector2(-halfWidth, -halfHeight), Vector2(0.f, 1.f) },
192       { Vector2(-halfWidth, -halfHeight), Vector2(1.f, 1.f) },
193       { Vector2(halfWidth, -halfHeight),  Vector2(-1.f, 1.f) },
194       { Vector2(halfWidth, -halfHeight),  Vector2(0.f, 1.f) },
195
196       { Vector2(-halfWidth, halfHeight), Vector2(0.f, -1.f) },
197       { Vector2(-halfWidth, halfHeight), Vector2(1.f, -1.f) },
198       { Vector2(halfWidth, halfHeight),  Vector2(-1.f, -1.f) },
199       { Vector2(halfWidth, halfHeight),  Vector2(0.f, -1.f) },
200
201       { Vector2(-halfWidth, halfHeight), Vector2(0.f, 0.f) },
202       { Vector2(-halfWidth, halfHeight), Vector2(1.f, 0.f) },
203       { Vector2(halfWidth, halfHeight),  Vector2(-1.f, 0.f) },
204       { Vector2(halfWidth, halfHeight),  Vector2(0.f, 0.f) },
205   };
206
207   Property::Map borderVertexFormat;
208   borderVertexFormat[POSITION_ATTRIBUTE_NAME] = Property::VECTOR2;
209   borderVertexFormat[DRIFT_ATTRIBUTE_NAME] = Property::VECTOR2;
210   PropertyBuffer borderVertices = PropertyBuffer::New( borderVertexFormat, 16 );
211   borderVertices.SetData(borderVertexData);
212
213   // Create indices
214   unsigned int indexData[48] = { 0, 4, 1, 1, 4, 5, 1, 5, 2, 2, 5, 6, 2, 6,3, 3, 6, 7,
215                                  4, 8, 5, 5, 8, 9, 6, 10, 7, 7, 10, 11,
216                                  8, 12, 9, 9, 12, 13, 9, 13, 10, 10, 13, 14, 10, 11, 14, 11, 14, 15};
217
218   Property::Map indexFormat;
219   indexFormat[INDEX_NAME] = Property::INTEGER;
220   PropertyBuffer indices = PropertyBuffer::New( indexFormat, 48 );
221   indices.SetData(indexData);
222
223   // Create the geometry object
224   Geometry geometry = Geometry::New();
225   geometry.AddVertexBuffer( borderVertices );
226   geometry.SetIndexBuffer( indices );
227
228   return geometry;
229 }
230
231 } // namespace Internal
232
233 } // namespace Toolkit
234
235 } // namespace Dali