[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / npatch / npatch-visual.cpp
1 /*
2  * Copyright (c) 2024 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 <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23 #include <dali/devel-api/common/stage.h>
24 #include <dali/devel-api/rendering/renderer-devel.h>
25 #include <dali/integration-api/debug.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/devel-api/utility/npatch-helper.h>
29 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
30 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
31 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
32 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
33 #include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
34 #include <dali-toolkit/internal/visuals/npatch-loader.h>
35 #include <dali-toolkit/internal/visuals/rendering-addon.h>
36 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
37 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
38 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
39 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
40 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
41 #include <dali-toolkit/public-api/visuals/visual-properties.h>
42
43 namespace Dali
44 {
45 namespace Toolkit
46 {
47 namespace Internal
48 {
49 namespace
50 {
51 const int CUSTOM_PROPERTY_COUNT(5); // fixed(3),stretch,aux
52 }
53
54 /////////////////NPatchVisual////////////////
55
56 NPatchVisualPtr NPatchVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl, const Property::Map& properties)
57 {
58   NPatchVisualPtr nPatchVisual(new NPatchVisual(factoryCache, shaderFactory));
59   nPatchVisual->mImageUrl = imageUrl;
60   nPatchVisual->SetProperties(properties);
61   nPatchVisual->Initialize();
62   return nPatchVisual;
63 }
64
65 NPatchVisualPtr NPatchVisual::New(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const VisualUrl& imageUrl)
66 {
67   NPatchVisualPtr nPatchVisual(new NPatchVisual(factoryCache, shaderFactory));
68   nPatchVisual->mImageUrl = imageUrl;
69   nPatchVisual->Initialize();
70   return nPatchVisual;
71 }
72
73 void NPatchVisual::LoadImages()
74 {
75   TextureManager& textureManager     = mFactoryCache.GetTextureManager();
76   bool            synchronousLoading = mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
77
78   if(mId == NPatchData::INVALID_NPATCH_DATA_ID)
79   {
80     bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
81     mId                    = mLoader.Load(textureManager, this, mImageUrl, mBorder, preMultiplyOnLoad, synchronousLoading);
82
83     NPatchDataPtr data;
84     if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
85     {
86       EnablePreMultipliedAlpha(data->IsPreMultiplied());
87     }
88   }
89
90   if(mAuxiliaryTextureId == TextureManager::INVALID_TEXTURE_ID && mAuxiliaryUrl.IsValid())
91   {
92     auto preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader
93                                ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
94                                : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
95
96     TextureManager::MaskingDataPointer maskingDataPtr       = nullptr;
97     ImageAtlasManagerPtr               imageAtlasManagerPtr = nullptr;
98
99     bool atlasing      = false;
100     auto atlasRect     = Vector4::ZERO;
101     auto atlasRectSize = Dali::ImageDimensions();
102
103     bool loadingStatus = false;
104
105     // Load the auxiliary image
106     mAuxiliaryTextureSet = textureManager.LoadTexture(mAuxiliaryUrl, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, maskingDataPtr, synchronousLoading, mAuxiliaryTextureId, atlasRect, atlasRectSize, atlasing, loadingStatus, this, nullptr, imageAtlasManagerPtr, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad);
107
108     // If synchronousLoading is true, we can check the auxiliaryResource's status now.
109     if(synchronousLoading)
110     {
111       mAuxiliaryResourceStatus = (mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u) ? Toolkit::Visual::ResourceStatus::READY : Toolkit::Visual::ResourceStatus::FAILED;
112     }
113   }
114 }
115
116 void NPatchVisual::GetNaturalSize(Vector2& naturalSize)
117 {
118   naturalSize.x = 0u;
119   naturalSize.y = 0u;
120
121   // load now if not already loaded
122   NPatchDataPtr data;
123   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
124   {
125     naturalSize.x = data->GetCroppedWidth();
126     naturalSize.y = data->GetCroppedHeight();
127   }
128   else
129   {
130     if(mImageUrl.IsValid())
131     {
132       ImageDimensions dimensions = Dali::GetOriginalImageSize(mImageUrl.GetUrl());
133       if(dimensions != ImageDimensions(0, 0))
134       {
135         naturalSize.x = dimensions.GetWidth();
136         naturalSize.y = dimensions.GetHeight();
137       }
138     }
139   }
140
141   if(mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u)
142   {
143     naturalSize.x = std::max(naturalSize.x, float(mAuxiliaryTextureSet.GetTexture(0u).GetWidth()));
144     naturalSize.y = std::max(naturalSize.y, float(mAuxiliaryTextureSet.GetTexture(0u).GetHeight()));
145   }
146 }
147
148 void NPatchVisual::DoSetProperties(const Property::Map& propertyMap)
149 {
150   // URL is already passed in via constructor
151
152   Property::Value* borderOnlyValue = propertyMap.Find(Toolkit::ImageVisual::Property::BORDER_ONLY, BORDER_ONLY);
153   if(borderOnlyValue)
154   {
155     borderOnlyValue->Get(mBorderOnly);
156   }
157
158   Property::Value* borderValue = propertyMap.Find(Toolkit::ImageVisual::Property::BORDER, BORDER);
159   if(borderValue && !borderValue->Get(mBorder)) // If value exists and is rect, just set mBorder
160   {
161     // Not a rect so try vector4
162     Vector4 border;
163     if(borderValue->Get(border))
164     {
165       mBorder.left   = static_cast<int>(border.x);
166       mBorder.right  = static_cast<int>(border.y);
167       mBorder.bottom = static_cast<int>(border.z);
168       mBorder.top    = static_cast<int>(border.w);
169     }
170   }
171
172   Property::Value* auxImage = propertyMap.Find(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, AUXILIARY_IMAGE_NAME);
173   if(auxImage)
174   {
175     std::string url;
176     if(auxImage->Get(url))
177     {
178       mAuxiliaryUrl = url;
179     }
180   }
181
182   Property::Value* auxImageAlpha = propertyMap.Find(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, AUXILIARY_IMAGE_ALPHA_NAME);
183   if(auxImageAlpha)
184   {
185     auxImageAlpha->Get(mAuxiliaryImageAlpha);
186   }
187
188   Property::Value* synchronousLoading = propertyMap.Find(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, SYNCHRONOUS_LOADING);
189   if(synchronousLoading)
190   {
191     bool sync = false;
192     synchronousLoading->Get(sync);
193     if(sync)
194     {
195       mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
196     }
197     else
198     {
199       mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
200     }
201   }
202
203   Property::Value* releasePolicy = propertyMap.Find(Toolkit::ImageVisual::Property::RELEASE_POLICY, RELEASE_POLICY_NAME);
204   if(releasePolicy)
205   {
206     releasePolicy->Get(mReleasePolicy);
207   }
208 }
209
210 void NPatchVisual::DoSetOnScene(Actor& actor)
211 {
212   // load when first go on stage
213   LoadImages();
214
215   // Set mPlacementActor now, because some case, LoadImages can use this information in LoadComplete API.
216   // at this case, we try to SetResouce to mPlaceActor twice. so, we should avoid that case.
217   mPlacementActor = actor;
218
219   NPatchDataPtr data;
220   if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
221   {
222     // If mAuxiliaryUrl need to be loaded, we should wait it until LoadComplete called.
223     if(!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING)
224     {
225       SetResource();
226     }
227   }
228 }
229
230 void NPatchVisual::DoSetOffScene(Actor& actor)
231 {
232   if(mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED)
233   {
234     if(mId != NPatchData::INVALID_NPATCH_DATA_ID)
235     {
236       mLoader.RequestRemove(mId, this);
237       mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
238       mId                    = NPatchData::INVALID_NPATCH_DATA_ID;
239     }
240     if(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID)
241     {
242       TextureManager& textureManager = mFactoryCache.GetTextureManager();
243       textureManager.RequestRemove(mAuxiliaryTextureId, this);
244       mAuxiliaryTextureId      = TextureManager::INVALID_TEXTURE_ID;
245       mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
246       mAuxiliaryTextureSet.Reset();
247     }
248   }
249
250   actor.RemoveRenderer(mImpl->mRenderer);
251   mPlacementActor.Reset();
252 }
253
254 void NPatchVisual::OnSetTransform()
255 {
256   if(mImpl->mRenderer)
257   {
258     mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
259   }
260 }
261
262 void NPatchVisual::DoCreatePropertyMap(Property::Map& map) const
263 {
264   map.Clear();
265   bool sync = IsSynchronousLoadingRequired();
266   map.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, sync);
267   map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::N_PATCH);
268   map.Insert(Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl());
269   map.Insert(Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly);
270   map.Insert(Toolkit::ImageVisual::Property::BORDER, mBorder);
271   map.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy);
272
273   if(mAuxiliaryUrl.IsValid())
274   {
275     map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, mAuxiliaryUrl.GetUrl());
276     map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, mAuxiliaryImageAlpha);
277   }
278 }
279
280 void NPatchVisual::DoCreateInstancePropertyMap(Property::Map& map) const
281 {
282   if(mAuxiliaryUrl.IsValid())
283   {
284     map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, mAuxiliaryUrl.GetUrl());
285     map.Insert(Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, mAuxiliaryImageAlpha);
286   }
287 }
288
289 NPatchVisual::NPatchVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory)
290 : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::N_PATCH),
291   mPlacementActor(),
292   mLoader(factoryCache.GetNPatchLoader()),
293   mImageVisualShaderFactory(shaderFactory),
294   mImageUrl(),
295   mAuxiliaryUrl(),
296   mId(NPatchData::INVALID_NPATCH_DATA_ID),
297   mAuxiliaryTextureSet(),
298   mAuxiliaryTextureId(TextureManager::INVALID_TEXTURE_ID),
299   mAuxiliaryResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
300   mBorderOnly(false),
301   mBorder(),
302   mAuxiliaryImageAlpha(0.0f),
303   mReleasePolicy(Toolkit::ImageVisual::ReleasePolicy::DETACHED)
304 {
305   EnablePreMultipliedAlpha(mFactoryCache.GetPreMultiplyOnLoad());
306 }
307
308 NPatchVisual::~NPatchVisual()
309 {
310   if(Stage::IsInstalled())
311   {
312     if(mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER)
313     {
314       if(mId != NPatchData::INVALID_NPATCH_DATA_ID)
315       {
316         mLoader.RequestRemove(mId, this);
317         mId = NPatchData::INVALID_NPATCH_DATA_ID;
318       }
319       if(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID)
320       {
321         TextureManager& textureManager = mFactoryCache.GetTextureManager();
322
323         textureManager.RequestRemove(mAuxiliaryTextureId, this);
324         mAuxiliaryTextureId = TextureManager::INVALID_TEXTURE_ID;
325         mAuxiliaryTextureSet.Reset();
326       }
327     }
328   }
329 }
330
331 void NPatchVisual::OnInitialize()
332 {
333   // Get basic geometry and shader
334   Geometry geometry                        = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
335   auto     imageVisualShaderFeatureBuilder = ImageVisualShaderFeatureBuilder();
336   Shader   shader                          = mImageVisualShaderFactory.GetShader(
337     mFactoryCache,
338     imageVisualShaderFeatureBuilder);
339
340   mImpl->mRenderer = VisualRenderer::New(geometry, shader);
341   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
342
343   //Register transform properties
344   mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
345 }
346
347 Geometry NPatchVisual::CreateGeometry()
348 {
349   Geometry      geometry;
350   NPatchDataPtr data;
351   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
352   {
353     if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
354     {
355       if(DALI_UNLIKELY(mBorderOnly))
356       {
357         geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY);
358       }
359       else
360       {
361         if(data->GetRenderingMap())
362         {
363           uint32_t elementCount[2];
364           geometry = RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), Uint16Pair(3, 3), elementCount);
365           if(mImpl->mRenderer)
366           {
367             RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
368           }
369         }
370         else
371         {
372           geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
373         }
374       }
375     }
376     else if(data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
377     {
378       Uint16Pair gridSize(2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1);
379       if(!data->GetRenderingMap())
380       {
381         geometry = !mBorderOnly ? NPatchHelper::CreateGridGeometry(gridSize) : NPatchHelper::CreateBorderGeometry(gridSize);
382       }
383       else
384       {
385         uint32_t elementCount[2];
386         geometry = !mBorderOnly ? RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), gridSize, elementCount) : NPatchHelper::CreateBorderGeometry(gridSize);
387         if(mImpl->mRenderer)
388         {
389           RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
390         }
391       }
392     }
393   }
394   else
395   {
396     // no N patch data so use default geometry
397     geometry = GetNinePatchGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
398   }
399   return geometry;
400 }
401
402 Shader NPatchVisual::CreateShader()
403 {
404   Shader        shader;
405   NPatchDataPtr data;
406   // 0 is either no data (load failed?) or no stretch regions on image
407   // for both cases we use the default shader
408   NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
409   NPatchUtility::StretchRanges::SizeType yStretchCount = 0;
410
411   auto fragmentShader = mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY ? SHADER_NPATCH_VISUAL_MASK_SHADER_FRAG
412                                                                                            : SHADER_NPATCH_VISUAL_SHADER_FRAG;
413   auto shaderType     = mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY ? VisualFactoryCache::NINE_PATCH_MASK_SHADER
414                                                                                            : VisualFactoryCache::NINE_PATCH_SHADER;
415
416   // ask loader for the regions
417   if(mLoader.GetNPatchData(mId, data))
418   {
419     xStretchCount = data->GetStretchPixelsX().Count();
420     yStretchCount = data->GetStretchPixelsY().Count();
421   }
422
423   if(DALI_LIKELY(!mImpl->mCustomShader))
424   {
425     if(DALI_LIKELY((xStretchCount == 1 && yStretchCount == 1) ||
426                    (xStretchCount == 0 && yStretchCount == 0)))
427     {
428       shader = mFactoryCache.GetShader(shaderType);
429       if(DALI_UNLIKELY(!shader))
430       {
431         shader = mFactoryCache.GenerateAndSaveShader(shaderType, SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, fragmentShader);
432       }
433     }
434     else if(xStretchCount > 0 || yStretchCount > 0)
435     {
436       std::stringstream shaderName;
437       shaderName << "N_PATCH_" << xStretchCount << "x" << yStretchCount;
438
439       std::stringstream vertexShader;
440       vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
441                    << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
442                    << SHADER_NPATCH_VISUAL_SHADER_VERT;
443
444       shader = Shader::New(vertexShader.str(), fragmentShader, Dali::Shader::Hint::NONE, shaderName.str());
445     }
446   }
447   else
448   {
449     Dali::Shader::Hint::Value hints = Dali::Shader::Hint::NONE;
450
451     if(!mImpl->mCustomShader->mFragmentShader.empty())
452     {
453       fragmentShader = mImpl->mCustomShader->mFragmentShader.c_str();
454     }
455     hints = mImpl->mCustomShader->mHints;
456
457     /* Apply Custom Vertex Shader only if image is 9-patch */
458     if((xStretchCount == 1 && yStretchCount == 1) ||
459        (xStretchCount == 0 && yStretchCount == 0))
460     {
461       const char* vertexShader = SHADER_NPATCH_VISUAL_3X3_SHADER_VERT.data();
462
463       if(!mImpl->mCustomShader->mVertexShader.empty())
464       {
465         vertexShader = mImpl->mCustomShader->mVertexShader.c_str();
466       }
467       shader = Shader::New(vertexShader, fragmentShader, hints);
468     }
469     else if(xStretchCount > 0 || yStretchCount > 0)
470     {
471       std::stringstream shaderName;
472       shaderName << "N_PATCH_" << xStretchCount << "x" << yStretchCount;
473
474       std::stringstream vertexShader;
475       vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
476                    << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
477                    << SHADER_NPATCH_VISUAL_SHADER_VERT;
478
479       shader = Shader::New(vertexShader.str(), fragmentShader, hints, shaderName.str());
480     }
481   }
482
483   return shader;
484 }
485
486 void NPatchVisual::ApplyTextureAndUniforms()
487 {
488   NPatchDataPtr data;
489   TextureSet    textureSet;
490
491   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
492   {
493     textureSet = data->GetTextures();
494     NPatchHelper::ApplyTextureAndUniforms(mImpl->mRenderer, data.Get());
495
496     if(mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY)
497     {
498       DALI_ASSERT_ALWAYS(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID);
499       DALI_ASSERT_ALWAYS(mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u);
500
501       // TODO : This code exist due to the texture cache manager hold TextureSet, not Texture.
502       // If we call textureSet.SetTexture(1, texture) directly, the cached TextureSet also be changed.
503       // We should make pass utc-Dali-VisualFactory.cpp UtcDaliNPatchVisualAuxiliaryImage02().
504       TextureSet tempTextureSet = TextureSet::New();
505       tempTextureSet.SetTexture(1, mAuxiliaryTextureSet.GetTexture(0));
506       tempTextureSet.SetTexture(0, textureSet.GetTexture(0));
507       textureSet = tempTextureSet;
508
509       mImpl->mRenderer.RegisterProperty(DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA,
510                                         AUXILIARY_IMAGE_ALPHA_NAME,
511                                         mAuxiliaryImageAlpha);
512     }
513     mImpl->mRenderer.SetTextures(textureSet);
514   }
515   else
516   {
517     DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.GetUrl().c_str());
518     Actor   actor     = mPlacementActor.GetHandle();
519     Vector2 imageSize = Vector2::ZERO;
520     if(actor)
521     {
522       imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
523     }
524     mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize, false);
525   }
526
527   // Register transform properties
528   mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
529 }
530
531 Geometry NPatchVisual::GetNinePatchGeometry(VisualFactoryCache::GeometryType subType)
532 {
533   Geometry geometry = mFactoryCache.GetGeometry(subType);
534   if(!geometry)
535   {
536     if(DALI_LIKELY(VisualFactoryCache::NINE_PATCH_GEOMETRY == subType))
537     {
538       geometry = NPatchHelper::CreateGridGeometry(Uint16Pair(3, 3));
539     }
540     else if(VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY == subType)
541     {
542       geometry = NPatchHelper::CreateBorderGeometry(Uint16Pair(3, 3));
543     }
544     mFactoryCache.SaveGeometry(subType, geometry);
545   }
546   return geometry;
547 }
548
549 void NPatchVisual::SetResource()
550 {
551   NPatchDataPtr data;
552   if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data))
553   {
554     Geometry geometry = CreateGeometry();
555     Shader   shader   = CreateShader();
556
557     mImpl->mRenderer.SetGeometry(geometry);
558     mImpl->mRenderer.SetShader(shader);
559
560     if(RenderingAddOn::Get().IsValid())
561     {
562       RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
563     }
564     Actor actor = mPlacementActor.GetHandle();
565     if(actor)
566     {
567       ApplyTextureAndUniforms();
568       actor.AddRenderer(mImpl->mRenderer);
569       mPlacementActor.Reset();
570     }
571
572     // npatch loaded and ready to display
573     if(data->GetLoadingState() != NPatchData::LoadingState::LOAD_COMPLETE)
574     {
575       ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
576     }
577     else
578     {
579       ResourceReady(Toolkit::Visual::ResourceStatus::READY);
580     }
581   }
582 }
583
584 void NPatchVisual::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
585 {
586   if(textureInformation.url.length() > 0) // For the Url.
587   {
588     if(DALI_UNLIKELY(mId == NPatchData::INVALID_NPATCH_DATA_ID))
589     {
590       // Special case when mLoader.Load call LoadComplete function before mId setup.
591       // We can overwrite mId.
592       mId = static_cast<NPatchData::NPatchDataId>(textureInformation.textureId);
593     }
594     if(loadSuccess)
595     {
596       EnablePreMultipliedAlpha(textureInformation.preMultiplied);
597     }
598   }
599   else // For the AuxiliaryUrl
600   {
601     if(DALI_UNLIKELY(mAuxiliaryTextureId == TextureManager::INVALID_TEXTURE_ID))
602     {
603       // Special case when TextureManager.LoadTexture call LoadComplete function before mAuxiliaryTextureId setup.
604       // We can overwrite mAuxiliaryTextureId.
605       mAuxiliaryTextureId = textureInformation.textureId;
606     }
607     if(loadSuccess)
608     {
609       mAuxiliaryTextureSet     = textureInformation.textureSet;
610       mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::READY;
611     }
612     else
613     {
614       mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
615     }
616   }
617
618   // If auxiliaryUrl didn't required OR auxiliaryUrl load done.
619   if(!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING)
620   {
621     NPatchDataPtr data;
622     // and.. If Url loading done.
623     if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
624     {
625       SetResource();
626     }
627   }
628 }
629
630 } // namespace Internal
631
632 } // namespace Toolkit
633
634 } // namespace Dali