cfe4e217d4279340190fe514d2ba9d7a59e75b16
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / renderers / image / image-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 "image-renderer.h"
20
21 #include <dali-toolkit/internal/controls/renderers/renderer-factory-impl.h>
22 #include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
23 #include <dali-toolkit/internal/controls/renderers/control-renderer-impl.h>
24 #include <dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h>
25 #include <dali/public-api/images/resource-image.h>
26
27 namespace Dali
28 {
29
30 namespace Toolkit
31 {
32
33 namespace Internal
34 {
35
36 namespace
37 {
38
39
40 const char * const IMAGE_URL_NAME("image-url");
41 const char * const IMAGE_FITTING_MODE("image-fitting-mode");
42 const char * const IMAGE_SAMPLING_MODE("image-sampling-mode");
43 const char * const IMAGE_DESIRED_WIDTH("image-desired-width");
44 const char * const IMAGE_DESIRED_HEIGHT("image-desired-height");
45
46 std::string TEXTURE_UNIFORM_NAME = "sTexture";
47
48 #define MAKE_SHADER(A)#A
49
50 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
51   attribute mediump vec2 aPosition;\n
52   varying mediump vec2 vTexCoord;\n
53   uniform mediump mat4 uMvpMatrix;\n
54   uniform mediump vec3 uSize;\n
55   \n
56   void main()\n
57   {\n
58     mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
59     vertexPosition.xyz *= uSize;\n
60     vertexPosition = uMvpMatrix * vertexPosition;\n
61     \n
62     vTexCoord = aPosition + vec2(0.5);\n
63     gl_Position = vertexPosition;\n
64   }\n
65 );
66
67 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
68   varying mediump vec2 vTexCoord;\n
69   uniform sampler2D sTexture;\n
70   uniform lowp vec4 uColor;\n
71   \n
72   void main()\n
73   {\n
74     gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
75   }\n
76 );
77
78 } //unnamed namespace
79
80 ImageRenderer::ImageRenderer()
81 : ControlRenderer(),
82   mDesiredSize(),
83   mFittingMode( FittingMode::DEFAULT ),
84   mSamplingMode( SamplingMode::DEFAULT )
85 {
86 }
87
88 ImageRenderer::~ImageRenderer()
89 {
90 }
91
92 void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
93 {
94   mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
95   if( !(mImpl->mGeometry) )
96   {
97     mImpl->mGeometry =  factoryCache.CreateQuadGeometry();
98     factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry );
99   }
100
101   mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
102   if( !mImpl->mShader )
103   {
104     mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
105     factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader );
106   }
107
108   mDesiredSize = ImageDimensions();
109   mFittingMode = FittingMode::DEFAULT;
110   mSamplingMode = SamplingMode::DEFAULT;
111   mImageUrl.clear();
112
113   Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME );
114   if( imageURLValue )
115   {
116     imageURLValue->Get( mImageUrl );
117
118     Property::Value* fittingValue = propertyMap.Find( IMAGE_FITTING_MODE );
119     if( fittingValue )
120     {
121       std::string fitting;
122       fittingValue->Get( fitting );
123
124       mFittingMode = FittingMode::DEFAULT;
125       if( fitting == "shrink-to-fit" )
126       {
127         mFittingMode = FittingMode::SHRINK_TO_FIT;
128       }
129       else if( fitting == "scale-to-fill" )
130       {
131         mFittingMode = FittingMode::SCALE_TO_FILL;
132       }
133       else if( fitting == "fit-width" )
134       {
135         mFittingMode = FittingMode::FIT_WIDTH;
136       }
137       else if( fitting == "fit-height" )
138       {
139         mFittingMode = FittingMode::FIT_HEIGHT;
140       }
141       else if( fitting == "default" )
142       {
143         mFittingMode = FittingMode::DEFAULT;
144       }
145       else
146       {
147         DALI_ASSERT_ALWAYS("Unknown fitting mode");
148       }
149     }
150
151     Property::Value* samplingValue = propertyMap.Find( IMAGE_SAMPLING_MODE );
152     if( samplingValue )
153     {
154       std::string sampling;
155       samplingValue->Get( sampling );
156
157       mSamplingMode = SamplingMode::DEFAULT;
158       if( sampling == "box" )
159       {
160         mSamplingMode = SamplingMode::BOX;
161       }
162       else if( sampling == "nearest" )
163       {
164         mSamplingMode = SamplingMode::NEAREST;
165       }
166       else if( sampling == "linear" )
167       {
168         mSamplingMode = SamplingMode::LINEAR;
169       }
170       else if( sampling == "box-then-nearest" )
171       {
172         mSamplingMode = SamplingMode::BOX_THEN_NEAREST;
173       }
174       else if( sampling == "box-then-linear" )
175       {
176         mSamplingMode = SamplingMode::BOX_THEN_LINEAR;
177       }
178       else if( sampling == "no-filter" )
179       {
180         mSamplingMode = SamplingMode::NO_FILTER;
181       }
182       else if( sampling == "dont-care" )
183       {
184         mSamplingMode = SamplingMode::DONT_CARE;
185       }
186       else if( sampling == "default" )
187       {
188         mSamplingMode = SamplingMode::DEFAULT;
189       }
190       else
191       {
192         DALI_ASSERT_ALWAYS("Unknown sampling mode");
193       }
194     }
195
196     int desiredWidth = 0;
197     Property::Value* desiredWidthValue = propertyMap.Find( IMAGE_DESIRED_WIDTH );
198     if( desiredWidthValue )
199     {
200       desiredWidthValue->Get( desiredWidth );
201     }
202
203     int desiredHeight = 0;
204     Property::Value* desiredHeightValue = propertyMap.Find( IMAGE_DESIRED_HEIGHT );
205     if( desiredHeightValue )
206     {
207       desiredHeightValue->Get( desiredHeight );
208     }
209
210     mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
211   }
212
213   mImage.Reset();
214 }
215
216 void ImageRenderer::SetSize( const Vector2& size )
217 {
218   ControlRenderer::SetSize( size );
219   // ToDo: renderer responds to the size change
220 }
221
222 void ImageRenderer::SetClipRect( const Rect<int>& clipRect )
223 {
224   ControlRenderer::SetClipRect( clipRect );
225   //ToDo: renderer responds to the clipRect change
226 }
227
228 void ImageRenderer::SetOffset( const Vector2& offset )
229 {
230   //ToDo: renderer applies the offset
231 }
232
233 void ImageRenderer::DoSetOnStage( Actor& actor )
234 {
235   if( !mImageUrl.empty() && !mImage )
236   {
237     mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode );
238   }
239
240   ApplyImageToSampler();
241 }
242
243 void ImageRenderer::DoSetOffStage( Actor& actor )
244 {
245   //If we own the image then make sure we release it when we go off stage
246   if( !mImageUrl.empty() )
247   {
248     mImage.Reset();
249   }
250
251   ControlRenderer::SetOffStage( actor );
252 }
253
254 void ImageRenderer::SetImage( const std::string& imageUrl )
255 {
256   SetImage( imageUrl, 0, 0, Dali::FittingMode::DEFAULT, Dali::SamplingMode::DEFAULT );
257 }
258
259 void ImageRenderer::SetImage( const std::string& imageUrl, int desiredWidth, int desiredHeight, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode )
260 {
261   if( mImageUrl != imageUrl )
262   {
263     mImageUrl = imageUrl;
264     mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
265     mFittingMode = fittingMode;
266     mSamplingMode = samplingMode;
267
268     if( !mImageUrl.empty() && mImpl->mIsOnStage )
269     {
270       mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode );
271       ApplyImageToSampler();
272     }
273     else
274     {
275       mImage.Reset();
276     }
277   }
278 }
279
280 void ImageRenderer::SetImage( Image image )
281 {
282   if( mImage != image )
283   {
284     mImageUrl.clear();
285     mDesiredSize = ImageDimensions();
286     mFittingMode = FittingMode::DEFAULT;
287     mSamplingMode = SamplingMode::DEFAULT;
288     mImage = image;
289
290     if( mImage && mImpl->mIsOnStage )
291     {
292       ApplyImageToSampler();
293     }
294   }
295 }
296
297 void ImageRenderer::ApplyImageToSampler()
298 {
299   if( mImage )
300   {
301     Material material = mImpl->mRenderer.GetMaterial();
302     if( material )
303     {
304       for( std::size_t i = 0; i < material.GetNumberOfSamplers(); ++i )
305       {
306         Sampler sampler = material.GetSamplerAt( i );
307         if( sampler.GetUniformName() == TEXTURE_UNIFORM_NAME )
308         {
309           sampler.SetImage( mImage );
310           return;
311         }
312       }
313
314       Sampler sampler = Sampler::New( mImage, TEXTURE_UNIFORM_NAME );
315       material.AddSampler( sampler );
316     }
317   }
318 }
319
320 } // namespace Internal
321
322 } // namespace Toolkit
323
324 } // namespace Dali