8ac1b744530b8a2f2def292c94711e8545ffc78b
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / renderers / renderer-factory-impl.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 // CLASS HEADER
18 #include "renderer-factory-impl.h"
19
20 // EXTERNAL INCLUDES
21 #include <dali/integration-api/debug.h>
22 #include <dali/public-api/images/image.h>
23 #include <dali/public-api/object/property-array.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/devel-api/object/type-registry-helper.h>
26
27 // Internal HEADER
28 #include <dali-toolkit/internal/controls/renderers/border/border-renderer.h>
29 #include <dali-toolkit/internal/controls/renderers/color/color-renderer.h>
30 #include <dali-toolkit/internal/controls/renderers/debug/debug-renderer.h>
31 #include <dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.h>
32 #include <dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h>
33 #include <dali-toolkit/internal/controls/renderers/image/image-renderer.h>
34 #include <dali-toolkit/internal/controls/renderers/svg/svg-renderer.h>
35 #include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
36 #include <dali-toolkit/internal/controls/renderers/renderer-string-constants.h>
37 #include <dali-toolkit/internal/controls/renderers/image-atlas-manager.h>
38
39 namespace
40 {
41 const char * const BROKEN_RENDERER_IMAGE_URL( DALI_IMAGE_DIR "broken.png");
42 }
43
44 namespace Dali
45 {
46
47 namespace Toolkit
48 {
49
50 namespace Internal
51 {
52
53 namespace
54 {
55
56 BaseHandle Create()
57 {
58   BaseHandle handle = Toolkit::RendererFactory::Get();
59
60   return handle;
61 }
62
63 DALI_TYPE_REGISTRATION_BEGIN_CREATE( Toolkit::RendererFactory, Dali::BaseHandle, Create, true )
64 DALI_TYPE_REGISTRATION_END()
65
66 } // namespace
67
68 RendererFactory::RendererFactory( bool debugEnabled )
69 :mDebugEnabled( debugEnabled )
70 {
71 }
72
73 RendererFactory::~RendererFactory()
74 {
75 }
76
77 RendererFactory::RendererType RendererFactory::GetRendererType( const Property::Map& propertyMap )
78 {
79   RendererType rendererType = UNDEFINED;
80
81   Property::Value* type = propertyMap.Find( RENDERER_TYPE );
82   std::string typeValue ;
83   if( type && type->Get( typeValue ))
84   {
85     if( typeValue ==  COLOR_RENDERER )
86     {
87       rendererType = COLOR;
88     }
89     else if( typeValue == BORDER_RENDERER )
90     {
91       rendererType = BORDER;
92     }
93     else if( typeValue ==  GRADIENT_RENDERER )
94     {
95       rendererType = GRADIENT;
96     }
97     else if( typeValue ==  IMAGE_RENDERER )
98     {
99       rendererType = IMAGE;
100     }
101   }
102
103   // check the url if exist, to decide the renderer type
104   if( rendererType == IMAGE || rendererType == UNDEFINED )
105   {
106     Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME );
107     std::string imageUrl;
108     if( imageURLValue && imageURLValue->Get( imageUrl ))
109     {
110       if( NinePatchImage::IsNinePatchUrl( imageUrl ) )
111       {
112         rendererType = N_PATCH;
113       }
114       else if( SvgRenderer::IsSvgUrl( imageUrl ) )
115       {
116         rendererType = SVG;
117       }
118       else
119       {
120         rendererType = IMAGE;
121       }
122     }
123   }
124
125   return rendererType;
126 }
127
128 Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Property::Map& propertyMap )
129 {
130   ControlRenderer* rendererPtr = NULL;
131
132   RendererType type = GetRendererType( propertyMap );
133   if( type != UNDEFINED)
134   {
135     if( !mFactoryCache )
136     {
137       mFactoryCache = new RendererFactoryCache();
138     }
139
140     if( mDebugEnabled )
141     {
142       return Toolkit::ControlRenderer( new DebugRenderer( *( mFactoryCache.Get() ) ) );
143     }
144   }
145
146   switch( type )
147   {
148     case COLOR:
149     {
150       rendererPtr = new ColorRenderer( *( mFactoryCache.Get() ) );
151       break;
152     }
153      case GRADIENT:
154      {
155        rendererPtr = new GradientRenderer( *( mFactoryCache.Get() ) );
156        break;
157      }
158     case BORDER:
159     {
160       rendererPtr = new BorderRenderer( *( mFactoryCache.Get() ) );
161       break;
162     }
163     case IMAGE:
164     {
165       CreateAtlasManager();
166       rendererPtr = new ImageRenderer( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
167       break;
168     }
169     case N_PATCH:
170     {
171       rendererPtr = new NPatchRenderer( *( mFactoryCache.Get() ) );
172       break;
173     }
174     case SVG:
175     {
176       CreateAtlasManager();
177       rendererPtr = new SvgRenderer( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
178       break;
179     }
180     case UNDEFINED:
181     default:
182     {
183       break;
184     }
185   }
186
187   if( rendererPtr )
188   {
189     Actor actor;
190     rendererPtr->Initialize( actor, propertyMap );
191   }
192   else
193   {
194     DALI_LOG_ERROR( "Renderer type unknown" );
195   }
196
197   return Toolkit::ControlRenderer( rendererPtr );
198 }
199
200 Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Vector4& color )
201 {
202   if( !mFactoryCache )
203   {
204     mFactoryCache = new RendererFactoryCache();
205   }
206
207   if( mDebugEnabled )
208   {
209     return Toolkit::ControlRenderer( new DebugRenderer( *( mFactoryCache.Get() ) ) );
210   }
211
212   ColorRenderer* rendererPtr = new ColorRenderer( *( mFactoryCache.Get() ) );
213   rendererPtr->SetColor( color );
214
215   return Toolkit::ControlRenderer( rendererPtr );
216 }
217
218 void RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Vector4& color )
219 {
220   if( mDebugEnabled && renderer )
221   {
222     return;
223   }
224
225   if( renderer )
226   {
227     ColorRenderer* rendererPtr = dynamic_cast< ColorRenderer* >( &GetImplementation( renderer ) );
228     if( rendererPtr )
229     {
230       rendererPtr->SetColor( color );
231       return;
232     }
233
234     renderer.RemoveAndReset( actor );
235   }
236
237   renderer = GetControlRenderer( color );
238   if( actor && actor.OnStage() )
239   {
240     renderer.SetOnStage( actor );
241   }
242 }
243
244 Toolkit::ControlRenderer RendererFactory::GetControlRenderer( float borderSize, const Vector4& borderColor, bool antiAliasing )
245 {
246   if( !mFactoryCache )
247   {
248     mFactoryCache = new RendererFactoryCache();
249   }
250
251   if( mDebugEnabled )
252   {
253     return Toolkit::ControlRenderer( new DebugRenderer( *( mFactoryCache.Get() ) ) );
254   }
255
256   BorderRenderer* rendererPtr = new BorderRenderer( *mFactoryCache.Get() );
257
258   rendererPtr->SetBorderSize( borderSize );
259   rendererPtr->SetBorderColor( borderColor );
260   rendererPtr->RequireAntiAliasing( antiAliasing );
261
262   return Toolkit::ControlRenderer( rendererPtr );
263 }
264
265 Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Image& image )
266 {
267   if( !mFactoryCache )
268   {
269     mFactoryCache = new RendererFactoryCache();
270   }
271
272   if( mDebugEnabled )
273   {
274     return Toolkit::ControlRenderer( new DebugRenderer( *( mFactoryCache.Get() ) ) );
275   }
276
277   NinePatchImage npatchImage = NinePatchImage::DownCast( image );
278   if( npatchImage )
279   {
280     NPatchRenderer* rendererPtr = new NPatchRenderer( *( mFactoryCache.Get() ) );
281     rendererPtr->SetImage( npatchImage );
282
283     return Toolkit::ControlRenderer( rendererPtr );
284   }
285   else
286   {
287     CreateAtlasManager();
288     ImageRenderer* rendererPtr = new ImageRenderer( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
289     Actor actor;
290     rendererPtr->SetImage( actor, image );
291
292     return Toolkit::ControlRenderer( rendererPtr );
293   }
294 }
295
296 void RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Image& image )
297 {
298   if( mDebugEnabled && renderer )
299   {
300     return;
301   }
302
303   if( renderer )
304   {
305     if( ! image )
306     {
307       // If the image is empty, then reset the renderer and return
308       renderer.RemoveAndReset( actor );
309       return;
310     }
311
312     NinePatchImage npatchImage = NinePatchImage::DownCast( image );
313     if( npatchImage )
314     {
315       NPatchRenderer* rendererPtr = dynamic_cast< NPatchRenderer* >( &GetImplementation( renderer ) );
316       if( rendererPtr )
317       {
318         rendererPtr->SetImage( npatchImage );
319         return;
320       }
321     }
322     else
323     {
324       ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) );
325       if( rendererPtr )
326       {
327         rendererPtr->SetImage( actor, image );
328         return;
329       }
330     }
331
332     renderer.RemoveAndReset( actor );
333   }
334
335   renderer = GetControlRenderer( image );
336   if( actor && actor.OnStage() )
337   {
338     renderer.SetOnStage( actor );
339   }
340 }
341
342 Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const std::string& url, ImageDimensions size )
343 {
344   if( !mFactoryCache )
345   {
346     mFactoryCache = new RendererFactoryCache();
347   }
348
349   if( mDebugEnabled )
350   {
351     return Toolkit::ControlRenderer( new DebugRenderer( *( mFactoryCache.Get() ) ) );
352   }
353
354   if( NinePatchImage::IsNinePatchUrl( url ) )
355   {
356     NPatchRenderer* rendererPtr = new NPatchRenderer( *( mFactoryCache.Get() ) );
357     rendererPtr->SetImage( url );
358
359     return Toolkit::ControlRenderer( rendererPtr );
360   }
361   else if( SvgRenderer::IsSvgUrl( url ) )
362   {
363     CreateAtlasManager();
364     SvgRenderer* rendererPtr = new SvgRenderer( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
365     rendererPtr->SetImage( url, size );
366     return Toolkit::ControlRenderer( rendererPtr );
367   }
368   else
369   {
370     CreateAtlasManager();
371     ImageRenderer* rendererPtr = new ImageRenderer( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
372     Actor actor;
373     rendererPtr->SetImage( actor, url, size );
374
375     return Toolkit::ControlRenderer( rendererPtr );
376   }
377 }
378
379 void RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const std::string& url, ImageDimensions size )
380 {
381   if( mDebugEnabled && renderer )
382   {
383     return;
384   }
385
386   if( renderer )
387   {
388     if( url.empty() )
389     {
390       // If the URL is empty, then reset the renderer and return
391       renderer.RemoveAndReset( actor );
392       return;
393     }
394     else if( NinePatchImage::IsNinePatchUrl( url ) )
395     {
396       NPatchRenderer* rendererPtr = dynamic_cast< NPatchRenderer* >( &GetImplementation( renderer ) );
397       if( rendererPtr )
398       {
399         rendererPtr->SetImage( url );
400         return;
401       }
402     }
403     else if( SvgRenderer::IsSvgUrl( url ) )
404     {
405       SvgRenderer* rendererPtr = dynamic_cast< SvgRenderer* >( &GetImplementation( renderer ) );
406       if( rendererPtr )
407       {
408         rendererPtr->SetImage( url, size );
409         return;
410       }
411     }
412     else
413     {
414       ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) );
415       if( rendererPtr )
416       {
417         rendererPtr->SetImage( actor, url, size );
418         return;
419       }
420     }
421
422     renderer.RemoveAndReset( actor );
423   }
424
425   renderer = GetControlRenderer( url, size );
426   if( actor && actor.OnStage() )
427   {
428     renderer.SetOnStage( actor );
429   }
430 }
431
432 void RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, Actor& actor, const Property::Map& propertyMap )
433 {
434   if( mDebugEnabled && renderer )
435   {
436     return;
437   }
438
439   if( renderer )
440   {
441     ControlRenderer& controlRenderer = GetImplementation( renderer );
442
443     RendererType type = GetRendererType( propertyMap );
444
445     //If there's no renderer type specified or if there hasn't been a renderer type change then we can reuse the renderer
446     if( type == UNDEFINED ||
447         ( type == IMAGE    && typeid( controlRenderer ) == typeid( ImageRenderer ) ) ||
448         ( type == N_PATCH  && typeid( controlRenderer ) == typeid( NPatchRenderer ) ) ||
449         ( type == COLOR    && typeid( controlRenderer ) == typeid( ColorRenderer ) )||
450         ( type == GRADIENT && typeid( controlRenderer ) == typeid( GradientRenderer ) ) ||
451         ( type == BORDER   && typeid( controlRenderer ) == typeid( BorderRenderer ) ) ||
452         ( type == SVG      && typeid( controlRenderer ) == typeid( SvgRenderer ) ) )
453     {
454       controlRenderer.Initialize( actor, propertyMap );
455       return;
456     }
457
458     renderer.RemoveAndReset( actor );
459   }
460
461   renderer = GetControlRenderer( propertyMap );
462   if( renderer && actor && actor.OnStage() )
463   {
464     renderer.SetOnStage( actor );
465   }
466 }
467
468 Image RendererFactory::GetBrokenRendererImage()
469 {
470   return ResourceImage::New( BROKEN_RENDERER_IMAGE_URL );
471 }
472
473 void RendererFactory::CreateAtlasManager()
474 {
475   if( !mAtlasManager )
476   {
477     Shader shader = ImageRenderer::GetImageShader( *( mFactoryCache.Get() ) );
478     mAtlasManager = new ImageAtlasManager();
479     mAtlasManager->SetBrokenImage( BROKEN_RENDERER_IMAGE_URL );
480   }
481 }
482
483 } // namespace Internal
484
485 } // namespace Toolkit
486
487 } // namespace Dali
488