Support to use NPatchImage in brokenImage 72/260572/28
authorSunghyun Kim <scholb.kim@samsung.com>
Tue, 29 Jun 2021 07:38:09 +0000 (16:38 +0900)
committertscholb <scholb.kim@samsung.com>
Thu, 14 Oct 2021 08:08:51 +0000 (17:08 +0900)
Support to use NpatchImage in broken Image.
Application can use custom broken image from this patch.
when they set 3 type of broken image(small,normal,large),
dali show the proper broken image considering size.

Change-Id: I7e2be85d4715d07356fd2782be2d011931fde5c2

18 files changed:
automated-tests/resources/broken_l.9.png [new file with mode: 0755]
automated-tests/resources/broken_m.9.png [new file with mode: 0755]
automated-tests/resources/broken_s.9.png [new file with mode: 0755]
automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
dali-toolkit/devel-api/styling/style-manager-devel.cpp
dali-toolkit/devel-api/styling/style-manager-devel.h
dali-toolkit/internal/styling/style-manager-impl.cpp
dali-toolkit/internal/styling/style-manager-impl.h
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/npatch-loader.cpp
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/visual-factory-cache.cpp
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-factory-impl.h

diff --git a/automated-tests/resources/broken_l.9.png b/automated-tests/resources/broken_l.9.png
new file mode 100755 (executable)
index 0000000..48f6078
Binary files /dev/null and b/automated-tests/resources/broken_l.9.png differ
diff --git a/automated-tests/resources/broken_m.9.png b/automated-tests/resources/broken_m.9.png
new file mode 100755 (executable)
index 0000000..fd99939
Binary files /dev/null and b/automated-tests/resources/broken_m.9.png differ
diff --git a/automated-tests/resources/broken_s.9.png b/automated-tests/resources/broken_s.9.png
new file mode 100755 (executable)
index 0000000..d2fd5fa
Binary files /dev/null and b/automated-tests/resources/broken_s.9.png differ
index 46d77a4141629249eefdfd8024b19a48c51eb64c..e8dd77e1f141042e880cc3c9842621445c7e8fc1 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
 #include <dali-toolkit/public-api/image-loader/image-url.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
 
 #include <test-native-image.h>
 #include <test-encoded-image-buffer.h>
@@ -61,6 +62,13 @@ const char* TEST_IMAGE_FILE_NAME2 =  "gallery_image_02.jpg";
 const char* TEST_IMAGE_1 = TEST_RESOURCE_DIR "/TB-gloss.png";
 const char* TEST_IMAGE_2 = TEST_RESOURCE_DIR "/tb-norm.png";
 
+const char* TEST_BROKEN_IMAGE_DEFAULT = TEST_RESOURCE_DIR "/broken.png";
+const char* TEST_BROKEN_IMAGE_S = TEST_RESOURCE_DIR "/broken_s.9.png";
+const char* TEST_BROKEN_IMAGE_M = TEST_RESOURCE_DIR "/broken_m.9.png";
+const char* TEST_BROKEN_IMAGE_L = TEST_RESOURCE_DIR "/broken_l.9.png";
+const char* TEST_BROKEN_IMAGE_01 =  TEST_RESOURCE_DIR "/button-up.9.png";
+const char* TEST_BROKEN_IMAGE_02 =  TEST_RESOURCE_DIR "/heartsframe.9.png";
+
 // resolution: 34*34, pixel format: RGBA8888
 static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
 // resolution: 600*600, pixel format: RGB888
@@ -2903,6 +2911,95 @@ int UtcDaliImageViewTVGLoading(void)
   }
   END_TEST;
 }
+int UtcDaliImageViewImageLoadFailure01(void)
+{
+  ToolkitTestApplication application;
+
+  Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_S);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_M);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE, TEST_BROKEN_IMAGE_L);
+
+  std::string brokenUrl;
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_S, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_M, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_L, brokenUrl, TEST_LOCATION);
+
+  ImageView imageView = ImageView::New("invalidUrl.png");
+  imageView.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+
+  application.GetScene().Add( imageView );
+  application.SendNotification();
+  application.Render(16);
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageViewImageLoadFailure02(void)
+{
+  ToolkitTestApplication application;
+
+  Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_DEFAULT);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_M);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE, TEST_BROKEN_IMAGE_L);
+
+  std::string brokenUrl;
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_DEFAULT, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_M, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_L, brokenUrl, TEST_LOCATION);
+
+  ImageView imageView = ImageView::New("invalidUrl.png");
+  imageView.SetProperty( Actor::Property::SIZE, Vector2( 30.f, 30.f ) );
+  application.GetScene().Add( imageView );
+  application.SendNotification();
+  application.Render(16);
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageViewImageLoadFailure03(void)
+{
+  ToolkitTestApplication application;
+
+  Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_01);
+  DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_02);
+
+  std::string brokenUrl;
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_01, brokenUrl, TEST_LOCATION);
+
+  brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+  DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_02, brokenUrl, TEST_LOCATION);
+
+  ImageView imageView = ImageView::New("invalidUrl.png");
+  imageView.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 100.f ) );
+  application.GetScene().Add( imageView );
+  application.SendNotification();
+  application.Render(16);
+
+  // loading started, this waits for the loader thread
+  DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+  END_TEST;
+}
 
 namespace
 {
index 29f0e8bc53743701633eed0c60b4e562a4173137..cc96d45ff5adbcde3c09d08ca74472933f73cdcf 100644 (file)
@@ -30,6 +30,26 @@ const Property::Map GetConfigurations(StyleManager styleManager)
   return GetImpl(styleManager).GetConfigurations();
 }
 
+void SetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
+{
+  return GetImpl(styleManager).SetBrokenImageUrl(brokenImageType, brokenImageUrl);
+}
+
+std::string GetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType)
+{
+  return GetImpl(styleManager).GetBrokenImageUrl(brokenImageType);
+}
+
+std::vector<std::string> GetBrokenImageUrlList(StyleManager styleManager)
+{
+  return GetImpl(styleManager).GetBrokenImageUrlList();
+}
+
+BrokenImageChangedSignalType& BrokenImageChangedSignal(StyleManager styleManager)
+{
+  return GetImpl(styleManager).BrokenImageChangedSignal();
+}
+
 } // namespace DevelStyleManager
 
 } // namespace Toolkit
index efcff7d5b9ccd8ef8b14faeb8cd782fbb0b8fba4..f1e05d7fc04da2016ce9f41a958ab24113df8aa9 100644 (file)
@@ -27,6 +27,18 @@ namespace Toolkit
 {
 namespace DevelStyleManager
 {
+/**
+ * @brief The Type of BrokenImage
+ */
+enum class BrokenImageType
+{
+  SMALL,
+  NORMAL,
+  LARGE
+};
+
+using BrokenImageChangedSignalType = Signal<void(StyleManager)>;
+
 /**
  * @brief Gets all currently defined configurations.
  *
@@ -36,6 +48,43 @@ namespace DevelStyleManager
 **/
 DALI_TOOLKIT_API const Property::Map GetConfigurations(StyleManager styleManager);
 
+/**
+   * @brief Sets an image to be used when a visual has failed to correctly render
+   * @param[in] styleManager The instance of StyleManager
+   * @param[in] brokenImageType The type of broken image
+   * @param[in] brokenImageUrl The broken image url
+   */
+DALI_TOOLKIT_API void SetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl);
+
+/**
+   * @brief Gets an image to be used when a visual has failed to correctly render
+   * @param[in] styleManager The instance of StyleManager
+   * @param[in] brokenImageType BrokenImage type
+   */
+DALI_TOOLKIT_API std::string GetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType);
+
+/**
+ * @brief Get the Broken Image Url List
+ *
+ * This list is broken images stored in order of SMALL, NORMAL, and LARGE values except if the value is empty.
+ * This API just makes the list without comparing size, so the application must set a value that matches the size.
+ * @param styleManager The instance of StyleManager
+ * @return A List of Broken Image Url
+ */
+DALI_TOOLKIT_API std::vector<std::string> GetBrokenImageUrlList(StyleManager styleManager);
+
+/**
+ * @brief This signal is emitted when the URL of the broken image is set
+ *
+ * A callback of the following type may be connected:
+ * @code
+ *   void YourCallbackName(StyleManager styleManager)
+ * @endcode
+ * @param styleManager The instance of StyleManager
+ * @return The signal to connect to
+ */
+DALI_TOOLKIT_API BrokenImageChangedSignalType& BrokenImageChangedSignal(StyleManager styleManager);
+
 } // namespace DevelStyleManager
 
 } // namespace Toolkit
index 0968081cb16e1ece5a6a56b7b9272a41922469e7..959724b26e2f0f5e254c67ff43f15db3202f8d26 100644 (file)
@@ -45,6 +45,8 @@ const char* APPLICATION_RESOURCE_PATH_KEY = "APPLICATION_RESOURCE_PATH";
 
 const char* DEFAULT_TOOLKIT_PACKAGE_PATH = "/toolkit/";
 
+static constexpr int32_t COUNT_BROKEN_IMAGE_MAX = 3;
+
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_STYLE");
 #endif
@@ -125,6 +127,9 @@ StyleManager::StyleManager()
 
   // Sound & haptic style
   mFeedbackStyle = new FeedbackStyle();
+
+  // Initialize BrokenImages
+  mBrokenImageUrls.assign(COUNT_BROKEN_IMAGE_MAX, "");
 }
 
 StyleManager::~StyleManager()
@@ -230,6 +235,11 @@ Toolkit::StyleManager::StyleChangedSignalType& StyleManager::ControlStyleChangeS
   return mControlStyleChangeSignal;
 }
 
+Toolkit::DevelStyleManager::BrokenImageChangedSignalType& StyleManager::BrokenImageChangedSignal()
+{
+  return mBrokenImageChangedSignal;
+}
+
 void StyleManager::SetTheme(const std::string& themeFile)
 {
   bool themeLoaded = false;
@@ -309,6 +319,34 @@ const Property::Map StyleManager::GetConfigurations()
   return result;
 }
 
+void StyleManager::SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
+{
+  int brokenType = static_cast<int>(brokenImageType);
+  mBrokenImageUrls[brokenType] = brokenImageUrl;
+  Toolkit::StyleManager styleManager = StyleManager::Get();
+  mBrokenImageChangedSignal.Emit(styleManager);
+}
+
+std::string StyleManager::GetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType)
+{
+  int brokenType = static_cast<int>(brokenImageType);
+  return mBrokenImageUrls[brokenType];
+}
+
+std::vector<std::string> StyleManager::GetBrokenImageUrlList()
+{
+  // create a list for brokenImage
+  std::vector<std::string> brokenImageUrlList;
+  for(int i = 0; i < COUNT_BROKEN_IMAGE_MAX; i++)
+  {
+    if(!mBrokenImageUrls[i].empty())
+    {
+      brokenImageUrlList.push_back(mBrokenImageUrls[i]);
+    }
+  }
+  return brokenImageUrlList;
+}
+
 bool StyleManager::LoadFile(const std::string& filename, std::string& stringOut)
 {
   DALI_ASSERT_DEBUG(0 != filename.length());
index b6eaff56986756f3052beed75b29e2c2555d08a2..56e61f04ca0f09011a59b02370ae516c6f50e05f 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/devel-api/builder/builder.h>
 #include <dali-toolkit/internal/builder/style.h>
 #include <dali-toolkit/public-api/styling/style-manager.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
 
 namespace Dali
 {
@@ -94,6 +95,21 @@ public: // Public API
    */
   const Property::Map GetConfigurations();
 
+  /**
+   * @copydoc Toolkit::DevelStyleManager::SetBrokenImageUrl
+   */
+  void SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl);
+
+  /**
+   * @copydoc Toolkit::DevelStyleManager::GetBrokenImageUrl
+   */
+  std::string GetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType);
+
+  /**
+   * @copydoc Toolkit::DevelStyleManager::GetBrokenImageUrlList
+   */
+  std::vector<std::string> GetBrokenImageUrlList();
+
   /**
    * @brief Apply the theme style to a control.
    *
@@ -136,6 +152,12 @@ public:
    */
   Toolkit::StyleManager::StyleChangedSignalType& ControlStyleChangeSignal();
 
+  /**
+   * This signal is sent to the visual factory following a broken image change.
+   * It should not be exposed in the public API
+   */
+  Toolkit::DevelStyleManager::BrokenImageChangedSignalType& BrokenImageChangedSignal();
+
 private:
   typedef std::vector<std::string> StringList;
 
@@ -233,9 +255,12 @@ private:
 
   Toolkit::Internal::FeedbackStyle* mFeedbackStyle; ///< Feedback style
 
+  std::vector<std::string> mBrokenImageUrls;    ///< Broken Image Urls received from user
+
   // Signals
-  Toolkit::StyleManager::StyleChangedSignalType mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
-  Toolkit::StyleManager::StyleChangedSignalType mStyleChangedSignal;       ///< Emitted after the controls have been styled
+  Toolkit::StyleManager::StyleChangedSignalType            mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
+  Toolkit::StyleManager::StyleChangedSignalType            mStyleChangedSignal;       ///< Emitted after the controls have been styled
+  Toolkit::DevelStyleManager::BrokenImageChangedSignalType mBrokenImageChangedSignal; ///< Emitted after brokenImageChangedSignal
 };
 
 } // namespace Internal
index da54e1e3e1b0d0f3dc06704a80d30c9ea581648b..9693cc834ffa57bc63ced05006c9403064e7cd3c 100644 (file)
@@ -807,9 +807,14 @@ TextureSet AnimatedImageVisual::SetLoadingFailed()
   DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n");
   ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
 
-  TextureSet textureSet  = TextureSet::New();
-  Texture    brokenImage = mFactoryCache.GetBrokenVisualImage();
-  textureSet.SetTexture(0u, brokenImage);
+  Actor actor = mPlacementActor.GetHandle();
+  Vector2 imageSize = Vector2::ZERO;
+  if(actor)
+  {
+    imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+  }
+  mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+  TextureSet textureSet = mImpl->mRenderer.GetTextures();
 
   if(mFrameDelayTimer)
   {
index 35d7456b892031f0533a4bf1eaa93d2fca6453d9..89d02e8e6304a2ae4c32a9501b60e0a17bdaefa0 100644 (file)
@@ -305,14 +305,10 @@ void AnimatedVectorImageVisual::DoSetOnScene(Actor& actor)
 
   if(mLoadFailed)
   {
-    TextureSet textureSet = TextureSet::New();
-    mImpl->mRenderer.SetTextures(textureSet);
-
-    Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-    textureSet.SetTexture(0u, brokenImage);
-
+    Vector2 imageSize = Vector2::ZERO;
+    imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
     actor.AddRenderer(mImpl->mRenderer);
-
     ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
   }
   else
index 0251a1dad2199d68b11b357e73b0ddb4c5f66660..7e404ca060949a81494f45f3bbee2033f3216c30 100644 (file)
@@ -513,8 +513,14 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
       }
       else
       {
-        Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
+        Actor actor = mPlacementActor.GetHandle();
+        Vector2 imageSize = Vector2::ZERO;
+        if(actor)
+        {
+          imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+        }
+        mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+        Texture brokenImage = mImpl->mRenderer.GetTextures().GetTexture(0);
         naturalSize.x = brokenImage.GetWidth();
         naturalSize.y = brokenImage.GetWidth();
       }
@@ -710,12 +716,12 @@ void ImageVisual::DoSetOnScene(Actor& actor)
   }
   else if(mLoadState == TextureManager::LoadState::LOAD_FAILED)
   {
-    Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
-    mTextures = TextureSet::New();
-    mTextures.SetTexture(0u, brokenImage);
-    mImpl->mRenderer.SetTextures(mTextures);
-
+    Vector2 imageSize = Vector2::ZERO;
+    if(actor)
+    {
+      imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    }
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
     actor.AddRenderer(mImpl->mRenderer);
     mPlacementActor.Reset();
 
@@ -860,26 +866,30 @@ void ImageVisual::UploadComplete(bool loadingSuccess, int32_t textureId, Texture
     EnablePreMultipliedAlpha(preMultiplied);
 
     Actor actor = mPlacementActor.GetHandle();
-    if(actor)
+    if(!loadingSuccess)
     {
-      actor.AddRenderer(mImpl->mRenderer);
-      // reset the weak handle so that the renderer only get added to actor once
-      mPlacementActor.Reset();
+      Vector2 imageSize = Vector2::ZERO;
+      if(actor)
+      {
+        imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+      }
+      mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+      textureSet = mImpl->mRenderer.GetTextures();
     }
-
-    if(!loadingSuccess)
+    else
     {
-      Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
-      textureSet = TextureSet::New();
-      textureSet.SetTexture(0u, brokenImage);
+      Sampler sampler = Sampler::New();
+      sampler.SetWrapMode(mWrapModeU, mWrapModeV);
+      textureSet.SetSampler(0u, sampler);
       mImpl->mRenderer.SetTextures(textureSet);
     }
 
-    Sampler sampler = Sampler::New();
-    sampler.SetWrapMode(mWrapModeU, mWrapModeV);
-    textureSet.SetSampler(0u, sampler);
-    mImpl->mRenderer.SetTextures(textureSet);
+    if(actor)
+    {
+      actor.AddRenderer(mImpl->mRenderer);
+      // reset the weak handle so that the renderer only get added to actor once
+      mPlacementActor.Reset();
+    }
   }
 
   // Storing TextureSet needed when renderer staged.
index 5f8ddff06db9b39d46fce4d8c041aaecd099defd..cb2850d2f3e2b9da56504ddaaa4f934c22513f25 100644 (file)
@@ -104,7 +104,6 @@ std::size_t NPatchLoader::Load(TextureManager& textureManager, TextureUploadObse
             newData->AddObserver(textureObserver);
 
             mCache.PushBack(newData);
-
             return newData->GetId(); // valid ids start from 1u
           }
         }
@@ -133,7 +132,6 @@ std::size_t NPatchLoader::Load(TextureManager& textureManager, TextureUploadObse
     preMultiplyOnLoad = (preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? true : false;
     data->SetLoadedNPatchData(pixelBuffer, preMultiplyOnLoad);
   }
-
   return data->GetId();
 }
 
index d9c26aa680b1bf789a14857624c59632660ec1dc..e87e2442af0f5808ac51f76dfe14e17b139ff3f7 100644 (file)
@@ -562,7 +562,14 @@ void NPatchVisual::ApplyTextureAndUniforms()
     DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.GetUrl().c_str());
     textureSet = TextureSet::New();
 
-    Texture croppedImage = mFactoryCache.GetBrokenVisualImage();
+    Actor actor = mPlacementActor.GetHandle();
+    Vector2 imageSize = Vector2::ZERO;
+    if(actor)
+    {
+      imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    }
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+    Texture croppedImage = mImpl->mRenderer.GetTextures().GetTexture(0);
     textureSet.SetTexture(0u, croppedImage);
     mImpl->mRenderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
     mImpl->mRenderer.RegisterProperty("uFixed[1]", Vector2::ZERO);
index 67fd4355dc1cc9912306be26b1668d177efc61f9..5d1fff16cacbf2f79c9a6809fb2a6f624332dfc7 100644 (file)
@@ -157,9 +157,9 @@ void SvgVisual::DoSetOnScene(Actor& actor)
 
   if(mLoadFailed)
   {
-    Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-    textureSet.SetTexture(0u, brokenImage);
-
+    Vector2 imageSize = Vector2::ZERO;
+    imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
     actor.AddRenderer(mImpl->mRenderer);
 
     ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
@@ -327,11 +327,9 @@ void SvgVisual::ApplyRasterizedImage(VectorImageRenderer vectorRenderer, PixelDa
     Actor actor = mPlacementActor.GetHandle();
     if(actor)
     {
-      TextureSet textureSet = mImpl->mRenderer.GetTextures();
-
-      Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-      textureSet.SetTexture(0u, brokenImage);
-
+      Vector2 imageSize = Vector2::ZERO;
+      imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+      mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
       actor.AddRenderer(mImpl->mRenderer);
     }
 
index b4fde0a814c4b71127f3ef375c3ca2b6ed4902b2..febd2855c08da159bcf8bb77cc41aca93f1143d1 100644 (file)
@@ -26,6 +26,8 @@
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali/integration-api/debug.h>
 
 namespace Dali
 {
@@ -33,11 +35,73 @@ namespace Toolkit
 {
 namespace Internal
 {
+namespace
+{
+
+/**
+ * @brief Creates the geometry formed from the vertices and indices
+ *
+ * @param[in]  vertices             The vertices to generate the geometry from
+ * @param[in]  indices              The indices to generate the geometry from
+ * @return The geometry formed from the vertices and indices
+ */
+Geometry GenerateGeometry(const Vector<Vector2>& vertices, const Vector<unsigned short>& indices)
+{
+  Property::Map vertexFormat;
+  vertexFormat["aPosition"] = Property::VECTOR2;
+  VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
+  if(vertices.Size() > 0)
+  {
+    vertexBuffer.SetData(&vertices[0], vertices.Size());
+  }
+
+  // Create the geometry object
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer(vertexBuffer);
+  if(indices.Size() > 0)
+  {
+    geometry.SetIndexBuffer(&indices[0], indices.Size());
+  }
+
+  return geometry;
+}
+
+/**
+ * @brief Adds the indices to form a quad composed off two triangles where the indices are organised in a grid
+ *
+ * @param[out] indices     The indices to add to
+ * @param[in]  rowIdx      The row index to start the quad
+ * @param[in]  nextRowIdx  The index to the next row
+ */
+void AddQuadIndices(Vector<unsigned short>& indices, unsigned int rowIdx, unsigned int nextRowIdx)
+{
+  indices.PushBack(rowIdx);
+  indices.PushBack(nextRowIdx + 1);
+  indices.PushBack(rowIdx + 1);
+
+  indices.PushBack(rowIdx);
+  indices.PushBack(nextRowIdx);
+  indices.PushBack(nextRowIdx + 1);
+}
+
+/**
+ * @brief Adds the vertices to create for npatch
+ * @param[out] vertices The vertices to add to
+ * @param[in]  x        The x value of vector
+ * @param[in]  y        The y value of vector
+ */
+void AddVertex(Vector<Vector2>& vertices, unsigned int x, unsigned int y)
+{
+  vertices.PushBack(Vector2(x, y));
+}
+
+} //unnamed namespace
+
 VisualFactoryCache::VisualFactoryCache(bool preMultiplyOnLoad)
 : mSvgRasterizeThread(NULL),
   mVectorAnimationManager(),
-  mBrokenImageUrl(""),
-  mPreMultiplyOnLoad(preMultiplyOnLoad)
+  mPreMultiplyOnLoad(preMultiplyOnLoad),
+  mBrokenImageInfoContainer()
 {
 }
 
@@ -104,7 +168,10 @@ ImageAtlasManagerPtr VisualFactoryCache::GetAtlasManager()
   if(!mAtlasManager)
   {
     mAtlasManager = new ImageAtlasManager();
-    mAtlasManager->SetBrokenImage(mBrokenImageUrl);
+    if(!mBrokenImageInfoContainer.empty())
+    {
+      mAtlasManager->SetBrokenImage(mBrokenImageInfoContainer[0].url);
+    }
   }
 
   return mAtlasManager;
@@ -207,20 +274,22 @@ Geometry VisualFactoryCache::CreateGridGeometry(Uint16Pair gridSize)
   return geometry;
 }
 
-Texture VisualFactoryCache::GetBrokenVisualImage()
+Texture VisualFactoryCache::GetBrokenVisualImage(uint32_t brokenIndex)
 {
-  if(!mBrokenImageTexture && mBrokenImageUrl.size())
+  if(!(mBrokenImageInfoContainer[brokenIndex].texture))
   {
-    PixelData          data;
-    Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageUrl);
+    PixelData          pixelData;
+    Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageInfoContainer[brokenIndex].url);
     if(pixelBuffer)
     {
-      data                = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
-      mBrokenImageTexture = Texture::New(Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), data.GetWidth(), data.GetHeight());
-      mBrokenImageTexture.Upload(data);
+      pixelData                = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+      mBrokenImageInfoContainer[brokenIndex].texture  = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+      mBrokenImageInfoContainer[brokenIndex].texture.Upload(pixelData);
+      mBrokenImageInfoContainer[brokenIndex].width = pixelData.GetWidth();
+      mBrokenImageInfoContainer[brokenIndex].height = pixelData.GetHeight();
     }
   }
-  return mBrokenImageTexture;
+  return mBrokenImageInfoContainer[brokenIndex].texture;
 }
 
 void VisualFactoryCache::SetPreMultiplyOnLoad(bool preMultiply)
@@ -233,16 +302,274 @@ bool VisualFactoryCache::GetPreMultiplyOnLoad()
   return mPreMultiplyOnLoad;
 }
 
-void VisualFactoryCache::SetBrokenImageUrl(const std::string& brokenImageUrl)
+void VisualFactoryCache::SetBrokenImageUrl(const std::vector<std::string>& brokenImageUrlList)
 {
-  mBrokenImageUrl = brokenImageUrl;
+  mBrokenImageInfoContainer.clear();
+  mBrokenImageInfoContainer.assign(brokenImageUrlList.size(), BrokenImageInfo());
+  for(unsigned int i = 0; i < brokenImageUrlList.size(); i++)
+  {
+    mBrokenImageInfoContainer[i].url = brokenImageUrlList[i];
+  }
+}
 
-  if(!mAtlasManager)
+VisualUrl::Type VisualFactoryCache::GetBrokenImageVisualType(int index)
+{
+  return mBrokenImageInfoContainer[index].visualType;
+}
+
+Geometry VisualFactoryCache::CreateNPatchGeometry(Uint16Pair gridSize)
+{
+  uint16_t gridWidth  = gridSize.GetWidth();
+  uint16_t gridHeight = gridSize.GetHeight();
+
+  // Create vertices
+  Vector<Vector2> vertices;
+  vertices.Reserve((gridWidth + 1) * (gridHeight + 1));
+
+  for(int y = 0; y < gridHeight + 1; ++y)
   {
-    mAtlasManager = new ImageAtlasManager();
+    for(int x = 0; x < gridWidth + 1; ++x)
+    {
+      AddVertex(vertices, x, y);
+    }
+  }
+
+  // Create indices
+  Vector<unsigned short> indices;
+  indices.Reserve(gridWidth * gridHeight * 6);
+
+  unsigned int rowIdx     = 0;
+  unsigned int nextRowIdx = gridWidth + 1;
+  for(int y = 0; y < gridHeight; ++y, ++nextRowIdx, ++rowIdx)
+  {
+    for(int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
+    {
+      AddQuadIndices(indices, rowIdx, nextRowIdx);
+    }
+  }
+
+  return GenerateGeometry(vertices, indices);
+}
+
+Geometry VisualFactoryCache::GetNPatchGeometry(int index)
+{
+  Geometry          geometry;
+  const NPatchData* data;
+  if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+  {
+    if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
+    {
+      geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
+      if(!geometry)
+      {
+        geometry = CreateNPatchGeometry(Uint16Pair(3,3));
+        SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
+      }
+    }
+    else if(data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
+    {
+      Uint16Pair gridSize(2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1);
+      geometry = CreateNPatchGeometry(gridSize);
+    }
+  }
+  else
+  {
+    // no N patch data so use default geometry
+    geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
+    if(!geometry)
+    {
+      geometry = CreateNPatchGeometry(Uint16Pair(3,3));
+      SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
+    }
+  }
+  return geometry;
+}
+
+Shader VisualFactoryCache::GetNPatchShader(int index)
+{
+  Shader            shader;
+  const NPatchData* data;
+  // 0 is either no data (load failed?) or no stretch regions on image
+  // for both cases we use the default shader
+  NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
+  NPatchUtility::StretchRanges::SizeType yStretchCount = 0;
+
+  // ask loader for the regions
+  if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data))
+  {
+    xStretchCount = data->GetStretchPixelsX().Count();
+    yStretchCount = data->GetStretchPixelsY().Count();
+  }
+
+  if(DALI_LIKELY((xStretchCount == 0 && yStretchCount == 0)))
+  {
+    shader = GetShader(VisualFactoryCache::NINE_PATCH_SHADER);
+    if(DALI_UNLIKELY(!shader))
+    {
+      shader = Shader::New(SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, SHADER_NPATCH_VISUAL_SHADER_FRAG);
+
+      // Only cache vanilla 9 patch shaders
+      SaveShader(VisualFactoryCache::NINE_PATCH_SHADER, shader);
+    }
+  }
+  else if(xStretchCount > 0 || yStretchCount > 0)
+  {
+    std::stringstream vertexShader;
+    vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
+                 << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
+                 << SHADER_NPATCH_VISUAL_SHADER_VERT;
+    shader = Shader::New(vertexShader.str(), SHADER_NPATCH_VISUAL_SHADER_FRAG);
+  }
+  return shader;
+}
+
+void VisualFactoryCache::RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent)
+{
+  uint16_t     prevEnd     = 0;
+  uint16_t     prevFix     = 0;
+  uint16_t     prevStretch = 0;
+  unsigned int i           = 1;
+  for(NPatchUtility::StretchRanges::ConstIterator it = stretchPixels.Begin(); it != stretchPixels.End(); ++it, ++i)
+  {
+    uint16_t start = it->GetX();
+    uint16_t end   = it->GetY();
+
+    uint16_t fix     = prevFix + start - prevEnd;
+    uint16_t stretch = prevStretch + end - start;
+
+    std::stringstream uniform;
+    uniform << uniformName << "[" << i << "]";
+    renderer.RegisterProperty(uniform.str(), Vector2(fix, stretch));
+
+    prevEnd     = end;
+    prevFix     = fix;
+    prevStretch = stretch;
+  }
+
+  {
+    prevFix += imageExtent - prevEnd;
+    std::stringstream uniform;
+    uniform << uniformName << "[" << i << "]";
+    renderer.RegisterProperty(uniform.str(), Vector2(prevFix, prevStretch));
+  }
+}
+
+void VisualFactoryCache::ApplyTextureAndUniforms(Renderer& renderer, int index)
+{
+  const NPatchData* data;
+  TextureSet        textureSet;
+  if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+  {
+    textureSet = data->GetTextures();
+    mBrokenImageInfoContainer[index].texture = data->GetTextures().GetTexture(0);
+
+    if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
+    {
+      //special case for 9 patch
+      Uint16Pair stretchX = data->GetStretchPixelsX()[0];
+      Uint16Pair stretchY = data->GetStretchPixelsY()[0];
+
+      uint16_t stretchWidth  = (stretchX.GetY() >= stretchX.GetX()) ? stretchX.GetY() - stretchX.GetX() : 0;
+      uint16_t stretchHeight = (stretchY.GetY() >= stretchY.GetX()) ? stretchY.GetY() - stretchY.GetX() : 0;
+
+      renderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
+      renderer.RegisterProperty("uFixed[1]", Vector2(stretchX.GetX(), stretchY.GetX()));
+      renderer.RegisterProperty("uFixed[2]", Vector2(data->GetCroppedWidth() - stretchWidth, data->GetCroppedHeight() - stretchHeight));
+      renderer.RegisterProperty("uStretchTotal", Vector2(stretchWidth, stretchHeight));
+    }
+    else
+    {
+      renderer.RegisterProperty("uNinePatchFactorsX[0]", Vector2::ZERO);
+      renderer.RegisterProperty("uNinePatchFactorsY[0]", Vector2::ZERO);
+
+      RegisterStretchProperties(renderer, "uNinePatchFactorsX", data->GetStretchPixelsX(), data->GetCroppedWidth());
+      RegisterStretchProperties(renderer, "uNinePatchFactorsY", data->GetStretchPixelsY(), data->GetCroppedHeight());
+    }
+    renderer.SetTextures(textureSet);
+  }
+}
+
+void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size)
+{
+  // Load Information for broken image
+  for(uint32_t index = 0; index < mBrokenImageInfoContainer.size(); index++)
+  {
+    if(mBrokenImageInfoContainer[index].width == 0 && mBrokenImageInfoContainer[index].height == 0)
+    {
+      if(!mBrokenImageInfoContainer[index].url.empty())
+      {
+        VisualUrl visualUrl(mBrokenImageInfoContainer[index].url);
+        mBrokenImageInfoContainer[index].visualType = visualUrl.GetType();
+        if(mBrokenImageInfoContainer[index].visualType == VisualUrl::Type::N_PATCH)
+        {
+          const NPatchData* data;
+          Rect<int> border;
+          mBrokenImageInfoContainer[index].npatchId = mNPatchLoader.Load( mTextureManager, NULL, mBrokenImageInfoContainer[index].url, border, mPreMultiplyOnLoad, true);
+          if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+          {
+            mBrokenImageInfoContainer[index].width = data->GetCroppedWidth();
+            mBrokenImageInfoContainer[index].height = data->GetCroppedHeight();
+          }
+          else
+          {
+            DALI_LOG_ERROR("Can't update renderer for broken image. maybe image loading is failed [path:%s] \n",mBrokenImageInfoContainer[index].url.c_str());
+          }
+        }
+        else
+        {
+          GetBrokenVisualImage(index);
+        }
+      }
+    }
+  }
+
+  // Set Texutre to renderer
+  int brokenIndex = GetProperBrokenImageIndex(size);
+  if(GetBrokenImageVisualType(brokenIndex) == VisualUrl::N_PATCH)
+  {
+    // Set geometry and shader for npatch
+    Geometry geometry = GetNPatchGeometry(brokenIndex);
+    Shader shader = GetNPatchShader(brokenIndex);
+    renderer.SetGeometry(geometry);
+    renderer.SetShader(shader);
+    ApplyTextureAndUniforms(renderer, brokenIndex);
+  }
+  else
+  {
+    Texture brokenImage = GetBrokenVisualImage(brokenIndex);
+    TextureSet textureSet = TextureSet::New();
+    textureSet.SetTexture(0u, brokenImage);
+    renderer.SetTextures(textureSet);
+  }
+}
+
+int32_t VisualFactoryCache::GetProperBrokenImageIndex(const Vector2& size)
+{
+  // Sets the default broken type
+  int32_t returnIndex = 0;
+  if((size.width == 0 || size.height == 0))
+  {
+    // To do : Need to add observer about size
+    return returnIndex;
+  }
+
+  // Find the proper value if we know the size of the image
+  for(int32_t index = static_cast<int32_t>(mBrokenImageInfoContainer.size()) - 1; index >= 0; index--)
+  {
+    // Skip if the value is not set
+    if(mBrokenImageInfoContainer[index].width == 0 || mBrokenImageInfoContainer[index].height == 0)
+    {
+      continue;
+    }
+
+    if(mBrokenImageInfoContainer[index].width < size.width && mBrokenImageInfoContainer[index].height < size.height)
+    {
+      returnIndex = index;
+      break;
+    }
   }
 
-  mAtlasManager->SetBrokenImage(mBrokenImageUrl);
+  return returnIndex;
 }
 
 } // namespace Internal
index 6e8f37dd06cf861796e7c20014662eb615366b99..b23c0101cd3f08bedffc2a34f382f1960a0b63fb 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali-toolkit/internal/visuals/npatch-loader.h>
 #include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
 #include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
 
 namespace Dali
 {
@@ -176,12 +177,6 @@ public:
    */
   static Geometry CreateGridGeometry(Uint16Pair gridSize);
 
-  /**
-   * @brief Returns a new Texture to use when a visual has failed to correctly render
-   * @return The broken image texture.
-   */
-  Texture GetBrokenVisualImage();
-
   /**
    * @copydoc Toolkit::VisualFactory::SetPreMultiplyOnLoad()
    */
@@ -194,9 +189,16 @@ public:
 
   /**
    * @brief Set an image to be used when a visual has failed to correctly render
-   * @param[in] brokenImageUrl The broken image url.
+   * @param[in] brokenImageUrlList The broken image url list
    */
-  void SetBrokenImageUrl(const std::string& brokenImageUrl);
+  void SetBrokenImageUrl(const std::vector<std::string>& brokenImageUrlList);
+
+  /**
+   * @brief Update the broken image Renderer object
+   * @param[in,out] renderer renderer for broken image
+   * @param[in] size the size of actor
+   */
+  void UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size);
 
 public:
   /**
@@ -241,17 +243,108 @@ protected:
   VisualFactoryCache& operator=(const VisualFactoryCache& rhs);
 
 private:
+  /**
+   * @brief Returns a cached Texture to use when a visual has failed to correctly render
+   * @param[in] brokenIndex The index of broken image
+   *
+   * @return The broken image texture.
+   */
+  Texture GetBrokenVisualImage(uint32_t brokenIndex);
+
+  /**
+   * @brief Gets the Proper broken image index
+   * @param[in] size The size of actor
+   *
+   * @return The index of broken image
+   */
+  int32_t GetProperBrokenImageIndex(const Vector2& size);
+
+  /**
+   * @brief Apply a texture and uniforms
+   *
+   * @param[in,out] renderer The renderer for broken image
+   * @param[in] index The index of broken image
+   */
+  void ApplyTextureAndUniforms(Renderer& renderer, int index);
+
+  /**
+   * @brief Creates a Npatch Geometry object
+   *
+   * @param[in] gridSize The gridSize for creating a geometry
+   * @return The Geometry for NPatch
+   */
+  Geometry CreateNPatchGeometry(Uint16Pair gridSize);
+
+  /**
+   * @brief Gets a geometry for npatch image
+   *
+   * @param[in] index the index of broken image
+   * @return The Geometry for NPatch
+   */
+  Geometry GetNPatchGeometry(int index);
+
+  /**
+   * @brief Gets the Npatch Shader object
+   *
+   * @param[in] index The index of broken image
+   * @return The Shader for NPatch
+   */
+  Shader GetNPatchShader(int index);
+
+  /**
+   * @brief Registers a properties for Stretch Ranges
+   *
+   * @param[in,out] renderer The renderer for broken image
+   * @param[in] uniformName The name of the uniform
+   * @param[in] stretchPixels The stretchable pixels in the cropped image space
+   * @param[in] imageExtent The imageExtent
+   */
+  void RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent);
+
+  /**
+   * @brief Returns a broken image type
+   * @param[in] index BrokenImage index
+   * @return The broken image type.
+   */
+  VisualUrl::Type GetBrokenImageVisualType(int index);
+
+private:
+  struct BrokenImageInfo
+  {
+    BrokenImageInfo()
+    :visualType(),
+     url(""),
+     npatchId(NPatchData::INVALID_NPATCH_DATA_ID),
+     texture(),
+     width(0),
+     height(0)
+    {
+    }
+
+    ~BrokenImageInfo()
+    {
+    }
+
+    // Data
+    VisualUrl::Type                         visualType;
+    std::string                             url;
+    NPatchData::NPatchDataId                npatchId;
+    Texture                                 texture;
+    uint32_t                                width;
+    uint32_t                                height;
+  };
+
   Geometry mGeometry[GEOMETRY_TYPE_MAX + 1];
   Shader   mShader[SHADER_TYPE_MAX + 1];
 
   ImageAtlasManagerPtr                    mAtlasManager;
   TextureManager                          mTextureManager;
   NPatchLoader                            mNPatchLoader;
-  Texture                                 mBrokenImageTexture;
+
   SvgRasterizeThread*                     mSvgRasterizeThread;
   std::unique_ptr<VectorAnimationManager> mVectorAnimationManager;
-  std::string                             mBrokenImageUrl;
   bool                                    mPreMultiplyOnLoad;
+  std::vector<BrokenImageInfo>            mBrokenImageInfoContainer;
 };
 
 } // namespace Internal
index b86dcf0dd5faffabdecb05c563e565a53b049f36..112fdd39f48bc871e11b5488ce079749f946ac33 100644 (file)
@@ -91,19 +91,15 @@ void VisualFactory::OnStyleChangedSignal(Toolkit::StyleManager styleManager, Sty
 {
   if(type == StyleChange::THEME_CHANGE)
   {
-    const std::string imageDirPath   = AssetManager::GetDaliImagePath();
-    std::string       brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
-
-    Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
-    config["brokenImageUrl"].Get(brokenImageUrl);
-
-    if(mFactoryCache)
-    {
-      mFactoryCache->SetBrokenImageUrl(brokenImageUrl);
-    }
+    SetBrokenImageUrl(styleManager);
   }
 }
 
+void VisualFactory::OnBrokenImageChangedSignal(Toolkit::StyleManager styleManager)
+{
+  SetBrokenImageUrl(styleManager);
+}
+
 Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyMap)
 {
   Visual::BasePtr visualPtr;
@@ -372,24 +368,43 @@ Internal::TextureManager& VisualFactory::GetTextureManager()
   return GetFactoryCache().GetTextureManager();
 }
 
+void VisualFactory::SetBrokenImageUrl(Toolkit::StyleManager& styleManager)
+{
+  const std::string imageDirPath   = AssetManager::GetDaliImagePath();
+  std::string       brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
+  std::vector<std::string> customBrokenImageUrlList;
+
+  if(styleManager)
+  {
+    customBrokenImageUrlList = Toolkit::DevelStyleManager::GetBrokenImageUrlList(styleManager);
+    if(customBrokenImageUrlList.size() == 0)
+    {
+      Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
+      config["brokenImageUrl"].Get(brokenImageUrl);
+      customBrokenImageUrlList.push_back(brokenImageUrl);
+    }
+    mFactoryCache->SetBrokenImageUrl(customBrokenImageUrlList);
+  }
+  else
+  {
+    // Set default image
+    customBrokenImageUrlList.push_back(brokenImageUrl);
+    mFactoryCache->SetBrokenImageUrl(customBrokenImageUrlList);
+  }
+}
+
 Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
 {
   if(!mFactoryCache)
   {
     mFactoryCache = std::unique_ptr<VisualFactoryCache>(new VisualFactoryCache(mPreMultiplyOnLoad));
-
-    const std::string imageDirPath   = AssetManager::GetDaliImagePath();
-    std::string       brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
-
     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
     if(styleManager)
     {
-      Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
-      config["brokenImageUrl"].Get(brokenImageUrl);
       styleManager.StyleChangedSignal().Connect(mSlotDelegate, &VisualFactory::OnStyleChangedSignal);
+      Toolkit::DevelStyleManager::BrokenImageChangedSignal(styleManager).Connect(mSlotDelegate, &VisualFactory::OnBrokenImageChangedSignal);
     }
-
-    mFactoryCache->SetBrokenImageUrl(brokenImageUrl);
+    SetBrokenImageUrl(styleManager);
   }
   return *mFactoryCache;
 }
index f038301252c978c057cf2ff07caed3d07c06cb1e..a5ecda81bcc1431c43d8bf0840fe79e366e2c5e6 100644 (file)
@@ -57,6 +57,13 @@ public:
    */
   void OnStyleChangedSignal(Toolkit::StyleManager styleManager, StyleChange::Type type);
 
+  /**
+   * @brief BrokenImageChanged callback
+   *
+   * @param[in] styleManager Handle for style manager.
+   */
+  void OnBrokenImageChangedSignal(Toolkit::StyleManager styleManager);
+
   /**
    * @copydoc Toolkit::VisualFactory::CreateVisual( const Property::Map& )
    */
@@ -89,6 +96,12 @@ protected:
   ~VisualFactory() override;
 
 private:
+  /**
+   * @brief Set the Broken Image url
+   * @param[in] styleManager The instance of StyleManager
+   */
+  void SetBrokenImageUrl(Toolkit::StyleManager& styleManager);
+
   /**
    * Get the factory cache, creating it if necessary.
    */