Changed ImageView to use a unit square mesh and instead to size the mesh in the shade...
[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     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 = 0.5f;
63   const float halfHeight = 0.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   //TODO: replace with triangle strip when Geometry supports it
78   unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 };
79   Property::Map indexFormat;
80   indexFormat["indices"] = Property::INTEGER;
81   PropertyBuffer indices = PropertyBuffer::New( indexFormat, 6 );
82   indices.SetData(indexData);
83
84   // Create the geometry object
85   Geometry texturedQuadGeometry = Geometry::New();
86   texturedQuadGeometry.AddVertexBuffer( texturedQuadVertices );
87   texturedQuadGeometry.SetIndexBuffer( indices );
88
89   return texturedQuadGeometry;
90 }
91
92 BaseHandle Create()
93 {
94   return Toolkit::ImageView::New();
95 }
96
97 // Setup properties, signals and actions using the type-registry.
98 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ImageView, Toolkit::Control, Create );
99 DALI_PROPERTY_REGISTRATION( Toolkit, ImageView, "resource-url", STRING, RESOURCE_URL )
100 DALI_TYPE_REGISTRATION_END()
101
102 } // anonymous namespace
103
104 using namespace Dali;
105
106 ImageView::ImageView()
107 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) )
108 {
109 }
110
111 ImageView::~ImageView()
112 {
113 }
114
115 Toolkit::ImageView ImageView::New()
116 {
117   ImageView* impl = new ImageView();
118
119   Dali::Toolkit::ImageView handle = Dali::Toolkit::ImageView( *impl );
120
121   // Second-phase init of the implementation
122   // This can only be done after the CustomActor connection has been made...
123   impl->Initialize();
124
125   return handle;
126 }
127
128 /////////////////////////////////////////////////////////////
129
130 void ImageView::SetImage( Image image )
131 {
132   mImage = image;
133
134   ResourceImage resourceImage = ResourceImage::DownCast( mImage );
135   if( resourceImage )
136   {
137     mImageUrl = resourceImage.GetUrl();
138   }
139   else
140   {
141     mImageUrl.clear();
142   }
143
144   if( mImage )
145   {
146     if( Self().OnStage() )
147     {
148       AttachImage();
149     }
150     RelayoutRequest();
151   }
152   else
153   {
154     if( mRenderer )
155     {
156       Self().RemoveRenderer( mRenderer );
157     }
158     mSampler.Reset();
159     mMaterial.Reset();
160     mMesh.Reset();
161     mRenderer.Reset();
162   }
163 }
164
165 Image ImageView::GetImage() const
166 {
167   return mImage;
168 }
169
170 Vector3 ImageView::GetNaturalSize()
171 {
172   // if no image then use Control's natural size
173   Vector3 size;
174
175   if( mImage )
176   {
177     size.x = mImage.GetWidth();
178     size.y = mImage.GetHeight();
179     size.z = std::min(size.x, size.y);
180   }
181   else
182   {
183     size = Control::GetNaturalSize();
184   }
185   return size;
186 }
187
188 float ImageView::GetHeightForWidth( float width )
189 {
190   if( mImage )
191   {
192     return GetHeightForWidthBase( width );
193   }
194   else
195   {
196     return Control::GetHeightForWidth( width );
197   }
198 }
199
200 float ImageView::GetWidthForHeight( float height )
201 {
202   if( mImage )
203   {
204     return GetWidthForHeightBase( height );
205   }
206   else
207   {
208     return Control::GetWidthForHeight( height );
209   }
210 }
211
212 ///////////////////////////////////////////////////////////
213 //
214 // Private methods
215 //
216
217 void ImageView::AttachImage()
218 {
219   if( !mRenderer )
220   {
221     Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
222     mMaterial = Material::New( shader );
223
224     mSampler = Sampler::New( mImage, "sTexture" );
225     mMaterial.AddSampler( mSampler );
226
227     Vector3 size = Self().GetCurrentSize();
228     mMesh = CreateGeometry( size.width, size.height );
229     mRenderer = Renderer::New( mMesh, mMaterial );
230     Self().AddRenderer( mRenderer );
231   }
232   else
233   {
234     mSampler.SetImage( mImage );
235   }
236 }
237
238 void ImageView::OnRelayout( const Vector2& size, RelayoutContainer& container )
239 {
240   Control::OnRelayout( size, container );
241
242   if( mRenderer )
243   {
244     mMesh = CreateGeometry( size.width, size.height );
245     mRenderer.SetGeometry( mMesh );
246   }
247 }
248
249 void ImageView::OnStageConnection( int depth )
250 {
251   if( mImage )
252   {
253     AttachImage();
254   }
255 }
256
257 ///////////////////////////////////////////////////////////
258 //
259 // Properties
260 //
261
262 void ImageView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
263 {
264   Toolkit::ImageView imageView = Toolkit::ImageView::DownCast( Dali::BaseHandle( object ) );
265
266   if ( imageView )
267   {
268     switch ( index )
269     {
270       case Toolkit::ImageView::Property::RESOURCE_URL:
271       {
272         std::string imageUrl;
273         if( value.Get( imageUrl ) )
274         {
275           ImageView& impl = GetImpl( imageView );
276           impl.mImageUrl = imageUrl;
277
278           Image image = ResourceImage::New( imageUrl );
279           impl.SetImage( image );
280         }
281         break;
282       }
283     }
284   }
285 }
286
287 Property::Value ImageView::GetProperty( BaseObject* object, Property::Index propertyIndex )
288 {
289   Property::Value value;
290
291   Toolkit::ImageView imageview = Toolkit::ImageView::DownCast( Dali::BaseHandle( object ) );
292
293   if ( imageview )
294   {
295     switch ( propertyIndex )
296     {
297       case Toolkit::ImageView::Property::RESOURCE_URL:
298       {
299         value = GetImpl( imageview ).mImageUrl;
300         break;
301       }
302     }
303   }
304
305   return value;
306 }
307
308 } // namespace Internal
309 } // namespace Toolkit
310 } // namespace Dali