[Tizen] Support to use NPatchImage in brokenImage
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / visual-factory-impl.cpp
1 /*
2  * Copyright (c) 2021 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 <dali-toolkit/internal/visuals/visual-factory-impl.h>
19
20 // EXTERNAL INCLUDES
21 #include <dali/devel-api/scripting/scripting.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/object/property-array.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/public-api/object/type-registry.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
29 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
30 #include <dali-toolkit/internal/visuals/animated-gradient/animated-gradient-visual.h>
31 #include <dali-toolkit/internal/visuals/animated-image/animated-image-visual.h>
32 #include <dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h>
33 #include <dali-toolkit/internal/visuals/arc/arc-visual.h>
34 #include <dali-toolkit/internal/visuals/border/border-visual.h>
35 #include <dali-toolkit/internal/visuals/color/color-visual.h>
36 #include <dali-toolkit/internal/visuals/gradient/gradient-visual.h>
37 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
38 #include <dali-toolkit/internal/visuals/image/image-visual.h>
39 #include <dali-toolkit/internal/visuals/mesh/mesh-visual.h>
40 #include <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
41 #include <dali-toolkit/internal/visuals/primitive/primitive-visual.h>
42 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
43 #include <dali-toolkit/internal/visuals/text/text-visual.h>
44 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
45 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
46 #include <dali-toolkit/internal/visuals/visual-url.h>
47 #include <dali-toolkit/internal/visuals/wireframe/wireframe-visual.h>
48 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
49 #include <dali-toolkit/public-api/visuals/text-visual-properties.h>
50 #include <dali-toolkit/public-api/visuals/visual-properties.h>
51
52 namespace Dali
53 {
54 namespace Toolkit
55 {
56 namespace Internal
57 {
58 namespace
59 {
60 #if defined(DEBUG_ENABLED)
61 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
62 #endif
63
64 static constexpr int32_t COUNT_BROKEN_IMAGE_MAX = 3;
65
66 BaseHandle Create()
67 {
68   BaseHandle handle = Toolkit::VisualFactory::Get();
69
70   return handle;
71 }
72
73 DALI_TYPE_REGISTRATION_BEGIN_CREATE(Toolkit::VisualFactory, Dali::BaseHandle, Create, true)
74 DALI_TYPE_REGISTRATION_END()
75 const char* const BROKEN_IMAGE_FILE_NAME = "broken.png"; ///< The file name of the broken image.
76
77 } // namespace
78
79 VisualFactory::VisualFactory(bool debugEnabled)
80 : mFactoryCache(),
81   mImageVisualShaderFactory(),
82   mSlotDelegate(this),
83   mDebugEnabled(debugEnabled),
84   mPreMultiplyOnLoad(true)
85 {
86 }
87
88 VisualFactory::~VisualFactory()
89 {
90 }
91
92 void VisualFactory::OnStyleChangedSignal(Toolkit::StyleManager styleManager, StyleChange::Type type)
93 {
94   if(type == StyleChange::THEME_CHANGE)
95   {
96     SetBrokenImageUrl(styleManager);
97   }
98 }
99
100 Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyMap)
101 {
102   Visual::BasePtr visualPtr;
103
104   Property::Value*           typeValue  = propertyMap.Find(Toolkit::Visual::Property::TYPE, VISUAL_TYPE);
105   Toolkit::DevelVisual::Type visualType = Toolkit::DevelVisual::IMAGE; // Default to IMAGE type.
106   if(typeValue)
107   {
108     Scripting::GetEnumerationProperty(*typeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, visualType);
109   }
110
111   switch(visualType)
112   {
113     case Toolkit::Visual::BORDER:
114     {
115       visualPtr = BorderVisual::New(GetFactoryCache(), propertyMap);
116       break;
117     }
118
119     case Toolkit::Visual::COLOR:
120     {
121       visualPtr = ColorVisual::New(GetFactoryCache(), propertyMap);
122       break;
123     }
124
125     case Toolkit::Visual::GRADIENT:
126     {
127       visualPtr = GradientVisual::New(GetFactoryCache(), propertyMap);
128       break;
129     }
130
131     case Toolkit::Visual::IMAGE:
132     {
133       Property::Value* imageURLValue = propertyMap.Find(Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME);
134       std::string      imageUrl;
135       if(imageURLValue)
136       {
137         if(imageURLValue->Get(imageUrl))
138         {
139           if(!imageUrl.empty())
140           {
141             VisualUrl visualUrl(imageUrl);
142
143             switch(visualUrl.GetType())
144             {
145               case VisualUrl::N_PATCH:
146               {
147                 visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap);
148                 break;
149               }
150               case VisualUrl::SVG:
151               {
152                 visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap);
153                 break;
154               }
155               case VisualUrl::GIF:
156               case VisualUrl::WEBP:
157               {
158                 visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap);
159                 break;
160               }
161               case VisualUrl::JSON:
162               {
163                 visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
164                 break;
165               }
166               case VisualUrl::REGULAR_IMAGE:
167               {
168                 visualPtr = ImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap);
169                 break;
170               }
171             }
172           }
173         }
174         else
175         {
176           Property::Array* array = imageURLValue->GetArray();
177           if(array)
178           {
179             visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), *array, propertyMap);
180           }
181         }
182       }
183       break;
184     }
185
186     case Toolkit::Visual::MESH:
187     {
188       visualPtr = MeshVisual::New(GetFactoryCache(), propertyMap);
189       break;
190     }
191
192     case Toolkit::Visual::PRIMITIVE:
193     {
194       visualPtr = PrimitiveVisual::New(GetFactoryCache(), propertyMap);
195       break;
196     }
197
198     case Toolkit::Visual::WIREFRAME:
199     {
200       visualPtr = WireframeVisual::New(GetFactoryCache(), propertyMap);
201       break;
202     }
203
204     case Toolkit::Visual::TEXT:
205     {
206       visualPtr = TextVisual::New(GetFactoryCache(), propertyMap);
207       break;
208     }
209
210     case Toolkit::Visual::N_PATCH:
211     {
212       Property::Value* imageURLValue = propertyMap.Find(Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME);
213       std::string      imageUrl;
214       if(imageURLValue && imageURLValue->Get(imageUrl))
215       {
216         visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
217       }
218       break;
219     }
220
221     case Toolkit::Visual::SVG:
222     {
223       Property::Value* imageURLValue = propertyMap.Find(Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME);
224       std::string      imageUrl;
225       if(imageURLValue && imageURLValue->Get(imageUrl))
226       {
227         visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
228       }
229       break;
230     }
231
232     case Toolkit::Visual::ANIMATED_IMAGE:
233     {
234       Property::Value* imageURLValue = propertyMap.Find(Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME);
235       std::string      imageUrl;
236       if(imageURLValue)
237       {
238         if(imageURLValue->Get(imageUrl))
239         {
240           visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
241         }
242         else
243         {
244           Property::Array* array = imageURLValue->GetArray();
245           if(array)
246           {
247             visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), *array, propertyMap);
248           }
249         }
250       }
251       break;
252     }
253
254     case Toolkit::DevelVisual::ANIMATED_GRADIENT:
255     {
256       visualPtr = AnimatedGradientVisual::New(GetFactoryCache(), propertyMap);
257       break;
258     }
259
260     case Toolkit::DevelVisual::ANIMATED_VECTOR_IMAGE:
261     {
262       Property::Value* imageURLValue = propertyMap.Find(Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME);
263       std::string      imageUrl;
264       if(imageURLValue && imageURLValue->Get(imageUrl))
265       {
266         visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
267       }
268       break;
269     }
270
271     case Toolkit::DevelVisual::ARC:
272     {
273       visualPtr = ArcVisual::New(GetFactoryCache(), propertyMap);
274       break;
275     }
276   }
277
278   DALI_LOG_INFO(gLogFilter, Debug::Concise, "VisualFactory::CreateVisual( VisualType:%s %s%s)\n", Scripting::GetEnumerationName<Toolkit::DevelVisual::Type>(visualType, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT), (visualType == Toolkit::DevelVisual::IMAGE) ? "url:" : "", (visualType == Toolkit::DevelVisual::IMAGE) ? (([&]() {
279                   // Return URL if present in PropertyMap else return "not found message"
280                   Property::Value* imageURLValue = propertyMap.Find(Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME);
281                   return (imageURLValue) ? imageURLValue->Get<std::string>().c_str() : "url not found in PropertyMap";
282                 })())
283                                                                                                                                                                                                                                                                                                                             : "");
284
285   if(!visualPtr)
286   {
287     DALI_LOG_ERROR("VisualType unknown\n");
288   }
289
290   if(mDebugEnabled && visualType != Toolkit::DevelVisual::WIREFRAME)
291   {
292     //Create a WireframeVisual if we have debug enabled
293     visualPtr = WireframeVisual::New(GetFactoryCache(), visualPtr, propertyMap);
294   }
295
296   return Toolkit::Visual::Base(visualPtr.Get());
297 }
298
299 Toolkit::Visual::Base VisualFactory::CreateVisual(const std::string& url, ImageDimensions size)
300 {
301   Visual::BasePtr visualPtr;
302
303   if(!url.empty())
304   {
305     // first resolve url type to know which visual to create
306     VisualUrl visualUrl(url);
307     switch(visualUrl.GetType())
308     {
309       case VisualUrl::N_PATCH:
310       {
311         visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
312         break;
313       }
314       case VisualUrl::SVG:
315       {
316         visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
317         break;
318       }
319       case VisualUrl::GIF:
320       case VisualUrl::WEBP:
321       {
322         visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
323         break;
324       }
325       case VisualUrl::JSON:
326       {
327         visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
328         break;
329       }
330       case VisualUrl::REGULAR_IMAGE:
331       {
332         visualPtr = ImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, size);
333         break;
334       }
335     }
336   }
337
338   if(mDebugEnabled)
339   {
340     //Create a WireframeVisual if we have debug enabled
341     visualPtr = WireframeVisual::New(GetFactoryCache(), visualPtr);
342   }
343
344   return Toolkit::Visual::Base(visualPtr.Get());
345 }
346
347 void VisualFactory::SetPreMultiplyOnLoad(bool preMultiply)
348 {
349   if(mPreMultiplyOnLoad != preMultiply)
350   {
351     GetFactoryCache().SetPreMultiplyOnLoad(preMultiply);
352   }
353   mPreMultiplyOnLoad = preMultiply;
354 }
355
356 bool VisualFactory::GetPreMultiplyOnLoad() const
357 {
358   return mPreMultiplyOnLoad;
359 }
360
361 Internal::TextureManager& VisualFactory::GetTextureManager()
362 {
363   return GetFactoryCache().GetTextureManager();
364 }
365
366 void VisualFactory::SetBrokenImageUrl(Toolkit::StyleManager& styleManager)
367 {
368   const std::string imageDirPath   = AssetManager::GetDaliImagePath();
369   std::string       brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
370   std::string       customBrokenImageUrl[COUNT_BROKEN_IMAGE_MAX];
371
372   if(styleManager)
373   {
374     Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
375     config["brokenImageUrl"].Get(brokenImageUrl);
376     styleManager.StyleChangedSignal().Connect(mSlotDelegate, &VisualFactory::OnStyleChangedSignal);
377
378     bool findCustomBrokenImage = false;
379     for(int i=0;i<COUNT_BROKEN_IMAGE_MAX;i++)
380     {
381       customBrokenImageUrl[i] = Toolkit::DevelStyleManager::GetBrokenImageUrl(styleManager,Toolkit::DevelStyleManager::BrokenImageType(i));
382       if(!customBrokenImageUrl[i].empty())
383       {
384         findCustomBrokenImage = true;
385       }
386     }
387
388     if(findCustomBrokenImage)
389     {
390       std::string customDefaultBrokenUrl = "";
391       mFactoryCache->EnableCustomBrokenImage(true);
392       customDefaultBrokenUrl = customBrokenImageUrl[0];
393
394       for(int i=0;i<COUNT_BROKEN_IMAGE_MAX;i++)
395       {
396         if(customDefaultBrokenUrl.empty())
397         {
398           if(!customBrokenImageUrl[i].empty())
399           {
400             customDefaultBrokenUrl = customBrokenImageUrl[i];
401             mFactoryCache->SetBrokenImageUrl(Toolkit::Internal::VisualFactoryCache::BrokenImageType::SMALL, customBrokenImageUrl[i]);
402           }
403         }
404         mFactoryCache->SetBrokenImageUrl(Toolkit::Internal::VisualFactoryCache::BrokenImageType(i), customBrokenImageUrl[i]);
405       }
406     }
407     else
408     {
409       mFactoryCache->SetBrokenImageUrl(Toolkit::Internal::VisualFactoryCache::BrokenImageType::SMALL, brokenImageUrl);
410     }
411   }
412   else
413   {
414     mFactoryCache->SetBrokenImageUrl(Toolkit::Internal::VisualFactoryCache::BrokenImageType::SMALL, brokenImageUrl);
415   }
416 }
417
418 Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
419 {
420   if(!mFactoryCache)
421   {
422     mFactoryCache = std::unique_ptr<VisualFactoryCache>(new VisualFactoryCache(mPreMultiplyOnLoad));
423     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
424     SetBrokenImageUrl(styleManager);
425   }
426   return *mFactoryCache;
427 }
428
429 ImageVisualShaderFactory& VisualFactory::GetImageVisualShaderFactory()
430 {
431   if(!mImageVisualShaderFactory)
432   {
433     mImageVisualShaderFactory = std::unique_ptr<ImageVisualShaderFactory>(new ImageVisualShaderFactory());
434   }
435   return *mImageVisualShaderFactory;
436 }
437
438 } // namespace Internal
439
440 } // namespace Toolkit
441
442 } // namespace Dali