7cfdb0776bb6d9657536a6ef7d99df519503fc62
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / image-view / image-view-impl.cpp
1 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
2
3 // CLASS HEADER
4 #include "image-view-impl.h"
5
6 // INTERNAL INCLUDES
7 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
8
9 // EXTERNAL INCLUDES
10 #include <dali/public-api/images/resource-image.h>
11 #include <dali/public-api/object/type-registry.h>
12 #include <dali/devel-api/object/type-registry-helper.h>
13 #include <dali/devel-api/scripting/scripting.h>
14
15 namespace Dali
16 {
17
18 namespace Toolkit
19 {
20
21 namespace Internal
22 {
23
24 namespace
25 {
26
27 #define MAKE_SHADER(A)#A
28
29 const char* VERTEX_SHADER = MAKE_SHADER(
30   attribute mediump vec2 aPosition;
31   attribute highp vec2 aTexCoord;
32   varying mediump vec2 vTexCoord;
33   uniform mediump mat4 uMvpMatrix;
34   uniform mediump vec3 uSize;
35
36   void main()
37   {
38     mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
39     // TODO scale by the actor size when we are using RendererFactor generated renderers with a shared unit sized mesh: vertexPosition.xyz *= uSize;
40     vertexPosition = uMvpMatrix * vertexPosition;
41
42     vTexCoord = aTexCoord;
43     gl_Position = vertexPosition;
44   }
45 );
46
47 const char* FRAGMENT_SHADER = MAKE_SHADER(
48   varying mediump vec2 vTexCoord;
49   uniform sampler2D sTexture;
50   uniform lowp vec4 uColor;
51
52   void main()
53   {
54     gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;
55   }
56 );
57
58 //TODO: remove when RendererFactory is implemented, so if there are multiple images that render as quads we only end up with one instance of geometry
59 Geometry CreateGeometry( int width, int height )
60 {
61   // Create vertices
62   const float halfWidth = width * .5f;
63   const float halfHeight = height * .5f;
64   struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; };
65     TexturedQuadVertex texturedQuadVertexData[4] = { { Vector2(-halfWidth, -halfHeight), Vector2(0.f, 0.f) },
66                                                      { Vector2( halfWidth, -halfHeight), Vector2(1.f, 0.f) },
67                                                      { Vector2(-halfWidth, halfHeight), Vector2(0.f, 1.f) },
68                                                      { Vector2( halfWidth, halfHeight), Vector2(1.f, 1.f) } };
69
70   Property::Map texturedQuadVertexFormat;
71   texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
72   texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
73   PropertyBuffer texturedQuadVertices = PropertyBuffer::New( texturedQuadVertexFormat, 4 );
74   texturedQuadVertices.SetData(texturedQuadVertexData);
75
76   // Create indices
77   unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 };
78   Property::Map indexFormat;
79   indexFormat["indices"] = Property::INTEGER;
80   PropertyBuffer indices = PropertyBuffer::New( indexFormat, 6 );
81   indices.SetData(indexData);
82
83   // Create the geometry object
84   Geometry texturedQuadGeometry = Geometry::New();
85   texturedQuadGeometry.AddVertexBuffer( texturedQuadVertices );
86   texturedQuadGeometry.SetIndexBuffer( indices );
87
88   return texturedQuadGeometry;
89 }
90
91 BaseHandle Create()
92 {
93   return Toolkit::ImageView::New();
94 }
95
96 // Setup properties, signals and actions using the type-registry.
97 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ImageView, Toolkit::Control, Create );
98 DALI_PROPERTY_REGISTRATION( Toolkit, ImageView, "resource-url", STRING, RESOURCE_URL )
99 DALI_TYPE_REGISTRATION_END()
100
101 } // anonymous namespace
102
103 using namespace Dali;
104
105 ImageView::ImageView()
106 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) )
107 {
108 }
109
110 ImageView::~ImageView()
111 {
112 }
113
114 Toolkit::ImageView ImageView::New()
115 {
116   ImageView* impl = new ImageView();
117
118   Dali::Toolkit::ImageView handle = Dali::Toolkit::ImageView( *impl );
119
120   // Second-phase init of the implementation
121   // This can only be done after the CustomActor connection has been made...
122   impl->Initialize();
123
124   return handle;
125 }
126
127 /////////////////////////////////////////////////////////////
128
129 void ImageView::SetImage( Image image )
130 {
131   mImage = image;
132
133   ResourceImage resourceImage = ResourceImage::DownCast( mImage );
134   if( resourceImage )
135   {
136     mImageUrl = resourceImage.GetUrl();
137   }
138   else
139   {
140     mImageUrl.clear();
141   }
142
143   if( mImage )
144   {
145     if( Self().OnStage() )
146     {
147       AttachImage();
148     }
149     RelayoutRequest();
150   }
151   else
152   {
153     if( mRenderer )
154     {
155       Self().RemoveRenderer( mRenderer );
156     }
157     mSampler.Reset();
158     mMaterial.Reset();
159     mMesh.Reset();
160     mRenderer.Reset();
161   }
162 }
163
164 Image ImageView::GetImage() const
165 {
166   return mImage;
167 }
168
169 Vector3 ImageView::GetNaturalSize()
170 {
171   // if no image then use Control's natural size
172   Vector3 size;
173
174   if( mImage )
175   {
176     size.x = mImage.GetWidth();
177     size.y = mImage.GetHeight();
178     size.z = std::min(size.x, size.y);
179   }
180   else
181   {
182     size = Control::GetNaturalSize();
183   }
184   return size;
185 }
186
187 float ImageView::GetHeightForWidth( float width )
188 {
189   if( mImage )
190   {
191     return GetHeightForWidthBase( width );
192   }
193   else
194   {
195     return Control::GetHeightForWidth( width );
196   }
197 }
198
199 float ImageView::GetWidthForHeight( float height )
200 {
201   if( mImage )
202   {
203     return GetWidthForHeightBase( height );
204   }
205   else
206   {
207     return Control::GetWidthForHeight( height );
208   }
209 }
210
211 ///////////////////////////////////////////////////////////
212 //
213 // Private methods
214 //
215
216 void ImageView::AttachImage()
217 {
218   if( !mRenderer )
219   {
220     Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
221     mMaterial = Material::New( shader );
222
223     mSampler = Sampler::New( mImage, "sTexture" );
224     mMaterial.AddSampler( mSampler );
225
226     Vector3 size = Self().GetCurrentSize();
227     mMesh = CreateGeometry( size.width, size.height );
228     mRenderer = Renderer::New( mMesh, mMaterial );
229     Self().AddRenderer( mRenderer );
230   }
231   else
232   {
233     mSampler.SetImage( mImage );
234   }
235 }
236
237 void ImageView::OnRelayout( const Vector2& size, RelayoutContainer& container )
238 {
239   Control::OnRelayout( size, container );
240
241   if( mRenderer )
242   {
243     mMesh = CreateGeometry( size.width, size.height );
244     mRenderer.SetGeometry( mMesh );
245   }
246 }
247
248 void ImageView::OnStageConnection( int depth )
249 {
250   if( mImage )
251   {
252     AttachImage();
253   }
254 }
255
256 ///////////////////////////////////////////////////////////
257 //
258 // Properties
259 //
260
261 void ImageView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
262 {
263   Toolkit::ImageView imageView = Toolkit::ImageView::DownCast( Dali::BaseHandle( object ) );
264
265   if ( imageView )
266   {
267     switch ( index )
268     {
269       case Toolkit::ImageView::Property::RESOURCE_URL:
270       {
271         std::string imageUrl;
272         if( value.Get( imageUrl ) )
273         {
274           ImageView& impl = GetImpl( imageView );
275           impl.mImageUrl = imageUrl;
276
277           Image image = ResourceImage::New( imageUrl );
278           impl.SetImage( image );
279         }
280         break;
281       }
282     }
283   }
284 }
285
286 Property::Value ImageView::GetProperty( BaseObject* object, Property::Index propertyIndex )
287 {
288   Property::Value value;
289
290   Toolkit::ImageView imageview = Toolkit::ImageView::DownCast( Dali::BaseHandle( object ) );
291
292   if ( imageview )
293   {
294     switch ( propertyIndex )
295     {
296       case Toolkit::ImageView::Property::RESOURCE_URL:
297       {
298         value = GetImpl( imageview ).mImageUrl;
299         break;
300       }
301     }
302   }
303
304   return value;
305 }
306
307 } // namespace Internal
308 } // namespace Toolkit
309 } // namespace Dali