Move image/ text / npatch relative class under each visual folder 04/312604/1
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 12 Jun 2024 06:03:38 +0000 (15:03 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Wed, 12 Jun 2024 06:36:57 +0000 (15:36 +0900)
For example, npatch-loader only be used for npatch-helper and npatch-visual,
we don't need to keep it under 'visuals' folder directly.

Similarly, text-visual-shader-factory only be used at text-visual.

image-visual-shader used several visuals, but all of them are used for image,
so move them  under image folder is not a bad job.

To make clear ownership of logic, let we move files into each folder.

Change-Id: Iaa1223c687425041a9a62e11792b0940ea8429cb
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
49 files changed:
automated-tests/src/dali-toolkit-internal/addons/test-rendering-addon.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-ImageVisualShaderFeatureBuilder.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp
automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp
dali-toolkit/devel-api/utility/npatch-helper.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/texture-manager/texture-manager-impl.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp
dali-toolkit/internal/visuals/image-atlas-manager.cpp [deleted file]
dali-toolkit/internal/visuals/image-atlas-manager.h [deleted file]
dali-toolkit/internal/visuals/image-visual-shader-debug.cpp [deleted file]
dali-toolkit/internal/visuals/image-visual-shader-debug.h [deleted file]
dali-toolkit/internal/visuals/image-visual-shader-factory.cpp [deleted file]
dali-toolkit/internal/visuals/image-visual-shader-factory.h [deleted file]
dali-toolkit/internal/visuals/image-visual-shader-feature-builder.cpp [deleted file]
dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h [deleted file]
dali-toolkit/internal/visuals/image/image-atlas-manager.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-atlas-manager.h [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual-shader-debug.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual-shader-debug.h [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual-shader-factory.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual-shader-factory.h [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h [new file with mode: 0644]
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/npatch-data.cpp [deleted file]
dali-toolkit/internal/visuals/npatch-data.h [deleted file]
dali-toolkit/internal/visuals/npatch-loader.cpp [deleted file]
dali-toolkit/internal/visuals/npatch-loader.h [deleted file]
dali-toolkit/internal/visuals/npatch/npatch-data.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/npatch/npatch-data.h [new file with mode: 0644]
dali-toolkit/internal/visuals/npatch/npatch-loader.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/npatch/npatch-loader.h [new file with mode: 0644]
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/text-visual-shader-factory.cpp [deleted file]
dali-toolkit/internal/visuals/text-visual-shader-factory.h [deleted file]
dali-toolkit/internal/visuals/text/text-visual-shader-factory.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/text/text-visual-shader-factory.h [new file with mode: 0644]
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/internal/visuals/text/text-visual.h
dali-toolkit/internal/visuals/visual-factory-cache.cpp
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/internal/visuals/visual-factory-impl.cpp

index a94f92b1c6914527c8eaaa1b32ede16d04ec2610..d78e7407f243a375865fcb07b43b321da198a5ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-
 // EXTERNAL HEADERS
-#include <dali/devel-api/addons/addon-base.h>
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/devel-api/addons/addon-base.h>
 #include <dali/public-api/rendering/geometry.h>
 #include <dali/public-api/rendering/renderer.h>
 
 // INTERNAL HEADERS
 // Needed to access the private class members
 #define private public
+#include <dali-toolkit/internal/visuals/npatch/npatch-loader.h>
 #include <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
-#include <dali-toolkit/internal/visuals/npatch-loader.h>
 #undef private
 
-
 using Dali::Toolkit::Internal::TextureManager;
 
 namespace Dali
 {
 namespace AddOns
 {
-
 struct DummyTiler
 {
 };
 
-void* CreateInstance( TextureManager* textureManager )
+void* CreateInstance(TextureManager* textureManager)
 {
   fprintf(stderr, "AddOn::CreateInstance( %p )\n", textureManager);
   return new DummyTiler;
@@ -50,53 +47,53 @@ namespace GeometryTiler
 {
 std::vector<std::string> gCallStack;
 
-static Geometry GetGeometryInternal(TextureManager::TextureId textureId, uint32_t& o0, uint32_t& o1 )
+static Geometry GetGeometryInternal(TextureManager::TextureId textureId, uint32_t& o0, uint32_t& o1)
 {
-  gCallStack.emplace_back( "GetGeometry" );
+  gCallStack.emplace_back("GetGeometry");
   o0 = 10;
   o1 = 5;
   fprintf(stderr, "AddOn::GetGeometryInternal()\n");
   return Dali::Geometry::New();
 }
 
-static Geometry CreateGeometryInternal(TextureManager::TextureId textureId, const Devel::PixelBuffer& pixelBuffer )
+static Geometry CreateGeometryInternal(TextureManager::TextureId textureId, const Devel::PixelBuffer& pixelBuffer)
 {
-  gCallStack.emplace_back( "CreateGeometry" );
+  gCallStack.emplace_back("CreateGeometry");
   fprintf(stderr, "AddOn::CreateGeometryInternal()\n");
   return Dali::Geometry::New();
 }
 
-static Geometry CreateGeometryMapInternal(const void* opacityMap,
+static Geometry CreateGeometryMapInternal(const void*       opacityMap,
                                           const Uint16Pair& gridSize,
-                                          uint32_t *outElements)
+                                          uint32_t*         outElements)
 {
-  gCallStack.emplace_back( "CreateGeometryGrid" );
+  gCallStack.emplace_back("CreateGeometryGrid");
   outElements[0] = 2;
   outElements[1] = 3;
   return Dali::Geometry::New();
 }
 
-static void* NPatchBuildInternal(const Devel::PixelBuffer& pixelBuffer, Toolkit::Internal::NPatchData* data )
+static void* NPatchBuildInternal(const Devel::PixelBuffer& pixelBuffer, Toolkit::Internal::NPatchData* data)
 {
-  gCallStack.emplace_back( "BuildNPatch" );
+  gCallStack.emplace_back("BuildNPatch");
   fprintf(stderr, "AddOn::NPatchBuild()\n");
   static char dummyData;
   return &dummyData;
 }
 
-static void NPatchDestroyInternal(void* object )
+static void NPatchDestroyInternal(void* object)
 {
-  gCallStack.emplace_back( "DestroyNPatch" );
+  gCallStack.emplace_back("DestroyNPatch");
   fprintf(stderr, "AddOn::NPatchDestroy()\n");
 }
 
-static void SubmitInternal(Renderer& renderer, const void* object  )
+static void SubmitInternal(Renderer& renderer, const void* object)
 {
-  gCallStack.emplace_back( "SubmitRenderTask" );
+  gCallStack.emplace_back("SubmitRenderTask");
   fprintf(stderr, "AddOn::SubmitInternal()\n");
 }
 
-static std::vector<std::string> GetCallStack( bool clear )
+static std::vector<std::string> GetCallStack(bool clear)
 {
   auto retval = gCallStack;
   if(clear)
@@ -106,10 +103,9 @@ static std::vector<std::string> GetCallStack( bool clear )
   return retval;
 }
 
-
-}
-}
-}
+} // namespace GeometryTiler
+} // namespace AddOns
+} // namespace Dali
 
 /**
  * OverdrawingAddOn implementation
@@ -117,13 +113,12 @@ static std::vector<std::string> GetCallStack( bool clear )
 class TestRenderingAddOn : public Dali::AddOns::AddOnBase
 {
 public:
-
-  void GetAddOnInfo( Dali::AddOnInfo& info ) override
+  void GetAddOnInfo(Dali::AddOnInfo& info) override
   {
-    info.type = Dali::AddOnType::GENERIC;
-    info.name = "oo-rendering";
-    info.version = Dali::DALI_ADDON_VERSION( 1, 0, 0 );
-    info.next = nullptr;
+    info.type    = Dali::AddOnType::GENERIC;
+    info.name    = "oo-rendering";
+    info.version = Dali::DALI_ADDON_VERSION(1, 0, 0);
+    info.next    = nullptr;
   }
 
   /**
@@ -133,7 +128,7 @@ public:
   Dali::AddOns::DispatchTable* GetGlobalDispatchTable() override
   {
     static Dali::AddOns::DispatchTable dispatchTable{};
-    if( dispatchTable.Empty() )
+    if(dispatchTable.Empty())
     {
       dispatchTable["Initialize"]         = Dali::AddOns::CreateInstance;
       dispatchTable["CreateGeometry"]     = Dali::AddOns::GeometryTiler::CreateGeometryInternal;
@@ -177,4 +172,4 @@ public:
   }
 };
 
-REGISTER_ADDON_CLASS( TestRenderingAddOn );
+REGISTER_ADDON_CLASS(TestRenderingAddOn);
index 4041450c4ce80bb63c10da140e318c5bd4754257..34122a2768404b1e3898036d218042513d4f3d9b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
-#include <iostream>
 #include <stdlib.h>
+#include <iostream>
 
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include <toolkit-event-thread-callback.h>
 #include <toolkit-text-utils.h>
 
-#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
 
 #include <../dali-toolkit/dali-toolkit-test-utils/dummy-control.h>
 #include <dummy-visual.h>
index a4e177c1f45c54da8c39546f3b4e511f4c0a3d45..bd7c6e395cd750cb1fb3f3348ad35ec8db01cc4e 100644 (file)
@@ -27,7 +27,7 @@
 #include <dali-toolkit/internal/texture-manager/texture-async-loading-helper.h>
 #include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
 #include <dali-toolkit/internal/texture-manager/texture-upload-observer.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/visual-factory-impl.h> ///< For VisualFactory's member TextureManager.
 #include <dali-toolkit/public-api/image-loader/image-url.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
index 00087299678bc136be482e3a872ead7b0a4f0103..3ad2bb062d31d0fbd7b1d83c8339e7282d3f59f7 100644 (file)
@@ -26,7 +26,7 @@
 #include <dali-toolkit/devel-api/utility/npatch-utilities.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
-#include <dali-toolkit/internal/visuals/npatch-loader.h>
+#include <dali-toolkit/internal/visuals/npatch/npatch-loader.h>
 #include <dali/devel-api/adaptor-framework/image-loading.h>
 #include <dali/integration-api/adaptor-framework/shader-precompiler.h>
 #include <dali/integration-api/debug.h>
index fed5316c9af8f4b8aebf6d9553d3e48620d71295..280eedf25e83305accf87e92f1b4251dfbf45673 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2023 Samsung Electronics Co., Ltd.
+* Copyright (c) 2024 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/npatch-data.h>
+#include <dali-toolkit/internal/visuals/npatch/npatch-data.h>
 
 namespace Dali
 {
index e9ae5b73209b029d9636b31d56866f2984a15d22..c73620a3e062f3d1978309a05af70b7ce314c371 100644 (file)
@@ -41,21 +41,21 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/visuals/gradient/linear-gradient.cpp
    ${toolkit_src_dir}/visuals/gradient/radial-gradient.cpp
    ${toolkit_src_dir}/visuals/animated-gradient/animated-gradient-visual.cpp
-   ${toolkit_src_dir}/visuals/image-atlas-manager.cpp
+   ${toolkit_src_dir}/visuals/image/image-atlas-manager.cpp
    ${toolkit_src_dir}/visuals/image/image-visual.cpp
+   ${toolkit_src_dir}/visuals/image/image-visual-shader-debug.cpp
+   ${toolkit_src_dir}/visuals/image/image-visual-shader-factory.cpp
+   ${toolkit_src_dir}/visuals/image/image-visual-shader-feature-builder.cpp
    ${toolkit_src_dir}/visuals/mesh/mesh-visual.cpp
-   ${toolkit_src_dir}/visuals/npatch-data.cpp
-   ${toolkit_src_dir}/visuals/npatch-loader.cpp
+   ${toolkit_src_dir}/visuals/npatch/npatch-data.cpp
+   ${toolkit_src_dir}/visuals/npatch/npatch-loader.cpp
    ${toolkit_src_dir}/visuals/npatch/npatch-visual.cpp
    ${toolkit_src_dir}/visuals/primitive/primitive-visual.cpp
    ${toolkit_src_dir}/visuals/svg/svg-task.cpp
    ${toolkit_src_dir}/visuals/svg/svg-visual.cpp
-   ${toolkit_src_dir}/visuals/text-visual-shader-factory.cpp
+   ${toolkit_src_dir}/visuals/text/text-visual-shader-factory.cpp
    ${toolkit_src_dir}/visuals/text/text-visual.cpp
    ${toolkit_src_dir}/visuals/transition-data-impl.cpp
-   ${toolkit_src_dir}/visuals/image-visual-shader-debug.cpp
-   ${toolkit_src_dir}/visuals/image-visual-shader-factory.cpp
-   ${toolkit_src_dir}/visuals/image-visual-shader-feature-builder.cpp
    ${toolkit_src_dir}/visuals/visual-base-data-impl.cpp
    ${toolkit_src_dir}/visuals/visual-base-impl.cpp
    ${toolkit_src_dir}/visuals/visual-factory-cache.cpp
index 39725674526cfaa3ca9d305ed9b9155fa711699b..f2ff1e3eb943c7c352c97a02aafbac92d399b7be 100644 (file)
@@ -29,7 +29,7 @@
 // INTERNAL HEADERS
 #include <dali-toolkit/internal/texture-manager/texture-async-loading-helper.h>
 #include <dali-toolkit/internal/texture-manager/texture-cache-manager.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/rendering-addon.h>
 
 namespace
index d94e0b50e7252e44d2921176ddd98b9ba847dd27..0b96cf50bd036ce4345c8350e9dec9702c2dee43 100644 (file)
@@ -32,8 +32,8 @@
 #include <dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h>
 #include <dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h>
 #include <dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
index e51870b9c2c01d50dfbd9d4dab02d1858bda80c8..96f0f3e41c53377ad1b9ce6887507f036afc0f1b 100644 (file)
@@ -18,7 +18,7 @@
 #include <dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h>
 
 // INTERNAL HEADERS
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h> // For ImageAtlasManagerPtr
 
 // EXTERNAL HEADERS
 #include <dali/integration-api/adaptor-framework/adaptor.h>
index 3ece4cb38d011201faeb451a6e9283d52e90a569..0cffcd01cf11e98ba885568fb418ef6c26a47ae5 100644 (file)
@@ -19,7 +19,7 @@
 
 // INTERNAL HEADERS
 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h> // For ImageAtlasManagerPtr
 #include <dali/integration-api/adaptor-framework/adaptor.h>
 #include <dali/integration-api/debug.h>
 
index d81841759d656dc466d162a2dc388a53df187f40..c83161cacaa6430d4d21bb79b90b3ffb71d0b341 100644 (file)
@@ -18,7 +18,7 @@
 #include <dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h>
 
 // INTERNAL HEADERS
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h> // For ImageAtlasManagerPtr
 
 // EXTERNAL HEADERS
 #include <dali/integration-api/adaptor-framework/adaptor.h>
index 506bd80e6a495095a4fb2e1416153ec81e5c0cc4..ce8ee703b35c1739c8762f3b42f42a106a3d8b12 100644 (file)
@@ -32,8 +32,8 @@
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
index ac448c022638886aba975689b0f162254d5d649a..fc2dac53cb1f6dd7e1d504205dca9b7c230e890b 100644 (file)
@@ -28,7 +28,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
 
 #ifdef TRACE_ENABLED
 #include <chrono>
diff --git a/dali-toolkit/internal/visuals/image-atlas-manager.cpp b/dali-toolkit/internal/visuals/image-atlas-manager.cpp
deleted file mode 100644 (file)
index 25fff39..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include "image-atlas-manager.h"
-
-// EXTERNAL HEADER
-#include <dali/devel-api/adaptor-framework/image-loading.h>
-
-// INTERNAL HEADERS
-#include <dali-toolkit/internal/image-loader/image-atlas-impl.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace
-{
-const uint32_t DEFAULT_ATLAS_SIZE(1024u); // this size can fit 8 by 8 images of average size 128*128
-const uint32_t MAX_ITEM_SIZE(512u);
-const uint32_t MAX_ITEM_AREA(MAX_ITEM_SIZE* MAX_ITEM_SIZE);
-} // namespace
-
-ImageAtlasManager::ImageAtlasManager()
-: mBrokenImageUrl("")
-{
-}
-
-ImageAtlasManager::~ImageAtlasManager()
-{
-}
-
-bool ImageAtlasManager::CheckAtlasAvailable(const VisualUrl& url, const ImageDimensions& size) const
-{
-  ImageDimensions dimensions = size;
-  ImageDimensions zero;
-  if(size == zero)
-  {
-    dimensions = Dali::GetClosestImageSize(url.GetUrl());
-  }
-
-  // big image, atlasing is not applied
-  if(static_cast<uint32_t>(dimensions.GetWidth()) * static_cast<uint32_t>(dimensions.GetHeight()) > MAX_ITEM_AREA || dimensions.GetWidth() > DEFAULT_ATLAS_SIZE || dimensions.GetHeight() > DEFAULT_ATLAS_SIZE)
-  {
-    return false;
-  }
-  return true;
-}
-
-TextureSet ImageAtlasManager::Add(Vector4&             textureRect,
-                                  const VisualUrl&     url,
-                                  ImageDimensions&     size,
-                                  FittingMode::Type    fittingMode,
-                                  bool                 orientationCorrection,
-                                  AtlasUploadObserver* atlasUploadObserver)
-{
-  ImageDimensions dimensions = size;
-  ImageDimensions zero;
-  if(size == zero)
-  {
-    dimensions = Dali::GetClosestImageSize(url.GetUrl());
-  }
-
-  // big image, atlasing is not applied
-  if(static_cast<uint32_t>(dimensions.GetWidth()) * static_cast<uint32_t>(dimensions.GetHeight()) > MAX_ITEM_AREA || dimensions.GetWidth() > DEFAULT_ATLAS_SIZE || dimensions.GetHeight() > DEFAULT_ATLAS_SIZE)
-  {
-    return TextureSet();
-  }
-  size = dimensions;
-
-  uint32_t i = 0;
-  for(AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
-  {
-    if(GetImplementation(*iter).Upload(textureRect, url, size, fittingMode, orientationCorrection, atlasUploadObserver))
-    {
-      return mTextureSetList[i];
-    }
-    i++;
-  }
-
-  CreateNewAtlas();
-  GetImplementation(mAtlasList.back()).Upload(textureRect, url, size, fittingMode, orientationCorrection, atlasUploadObserver);
-  return mTextureSetList.back();
-}
-
-TextureSet ImageAtlasManager::Add(Vector4&                  textureRect,
-                                  const EncodedImageBuffer& encodedImageBuffer,
-                                  const ImageDimensions&    size,
-                                  FittingMode::Type         fittingMode,
-                                  bool                      orientationCorrection,
-                                  AtlasUploadObserver*      atlasUploadObserver)
-{
-  // big image, atlasing is not applied
-  if(static_cast<uint32_t>(size.GetWidth()) * static_cast<uint32_t>(size.GetHeight()) > MAX_ITEM_AREA || size.GetWidth() > DEFAULT_ATLAS_SIZE || size.GetHeight() > DEFAULT_ATLAS_SIZE)
-  {
-    return TextureSet();
-  }
-
-  uint32_t i = 0;
-  for(AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
-  {
-    if(GetImplementation(*iter).Upload(textureRect, encodedImageBuffer, size, fittingMode, orientationCorrection, atlasUploadObserver))
-    {
-      return mTextureSetList[i];
-    }
-    i++;
-  }
-
-  CreateNewAtlas();
-  GetImplementation(mAtlasList.back()).Upload(textureRect, encodedImageBuffer, size, fittingMode, orientationCorrection, atlasUploadObserver);
-  return mTextureSetList.back();
-}
-
-TextureSet ImageAtlasManager::Add(Vector4&  textureRect,
-                                  PixelData pixelData)
-{
-  // big buffer, atlasing is not applied
-  if(static_cast<uint32_t>(pixelData.GetWidth()) * static_cast<uint32_t>(pixelData.GetHeight()) > MAX_ITEM_AREA || pixelData.GetWidth() > DEFAULT_ATLAS_SIZE || pixelData.GetHeight() > DEFAULT_ATLAS_SIZE)
-  {
-    return TextureSet();
-  }
-
-  uint32_t i = 0;
-  for(AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
-  {
-    if((*iter).Upload(textureRect, pixelData))
-    {
-      return mTextureSetList[i];
-    }
-    i++;
-  }
-
-  CreateNewAtlas();
-  mAtlasList.back().Upload(textureRect, pixelData);
-  return mTextureSetList.back();
-}
-
-void ImageAtlasManager::Remove(TextureSet textureSet, const Vector4& textureRect)
-{
-  uint32_t i = 0;
-  for(TextureSetContainer::iterator iter = mTextureSetList.begin(); iter != mTextureSetList.end(); ++iter)
-  {
-    if((*iter) == textureSet)
-    {
-      mAtlasList[i].Remove(textureRect);
-      return;
-    }
-    i++;
-  }
-}
-
-void ImageAtlasManager::SetBrokenImage(const std::string& brokenImageUrl)
-{
-  if(!brokenImageUrl.empty())
-  {
-    mBrokenImageUrl = brokenImageUrl;
-  }
-}
-
-void ImageAtlasManager::CreateNewAtlas()
-{
-  Toolkit::ImageAtlas newAtlas = Toolkit::ImageAtlas::New(DEFAULT_ATLAS_SIZE, DEFAULT_ATLAS_SIZE);
-  if(!mBrokenImageUrl.empty())
-  {
-    newAtlas.SetBrokenImage(mBrokenImageUrl);
-  }
-  mAtlasList.push_back(newAtlas);
-  TextureSet textureSet = TextureSet::New();
-  textureSet.SetTexture(0u, newAtlas.GetAtlas());
-  mTextureSetList.push_back(textureSet);
-}
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image-atlas-manager.h b/dali-toolkit/internal/visuals/image-atlas-manager.h
deleted file mode 100644 (file)
index ec7a402..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef DALI_TOOLKIT_IMAGE_ATLAS_MANAGER_H
-#define DALI_TOOLKIT_IMAGE_ATLAS_MANAGER_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
-#include <dali/public-api/common/vector-wrapper.h>
-#include <dali/public-api/object/ref-object.h>
-#include <dali/public-api/rendering/texture-set.h>
-#include <string>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
-#include <dali-toolkit/internal/visuals/visual-url.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-class AtlasUploadObserver;
-
-namespace Internal
-{
-/**
- * The manager for automatic image atlasing. Owned by VisualFactory
- */
-class ImageAtlasManager : public RefObject
-{
-public:
-  typedef std::vector<Toolkit::ImageAtlas> AtlasContainer;
-  typedef std::vector<TextureSet>          TextureSetContainer;
-
-public:
-  /**
-   * Construtor
-   *
-   */
-  ImageAtlasManager();
-
-  /**
-   * @brief Check whether the image of url could be Atlas or not.
-   *
-   * @param [in] url The URL of the resource image file to use.
-   * @param [in] size The width and height to fit the loaded image to.
-   * @return True if the image could be Atlas.
-   */
-  bool CheckAtlasAvailable(const VisualUrl& url, const ImageDimensions& size) const;
-
-  /**
-   * @brief Add an image to the atlas.
-   *
-   * @note To make the atlasing efficient, an valid size should be provided.
-   *       If size is not provided, then the image file will be opened to read the actual size for loading.
-   *
-   * SamplingMode::BOX_THEN_LINEAR is used to sampling pixels from the input image while fitting it to desired size.
-   *
-   * @param [out] textureRect The texture area of the resource image in the atlas.
-   * @param [in] url The URL of the resource image file to use.
-   * @param [in, out] size The width and height to fit the loaded image to.
-   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
-   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
-   * @param [in] atlasUploadObserver The object to observe the uploading state inside ImageAtlas.
-   * @return The texture set containing the image.
-   */
-  TextureSet Add(Vector4&             textureRect,
-                 const VisualUrl&     url,
-                 ImageDimensions&     size,
-                 FittingMode::Type    fittingMode           = FittingMode::DEFAULT,
-                 bool                 orientationCorrection = true,
-                 AtlasUploadObserver* atlasUploadObserver   = NULL);
-
-  /**
-   * @brief Add an image to the atlas.
-   *
-   * @note To make the atlasing efficient, an valid size should be provided.
-   *
-   * SamplingMode::BOX_THEN_LINEAR is used to sampling pixels from the input image while fitting it to desired size.
-   *
-   * @param [out] textureRect The texture area of the resource image in the atlas.
-   * @param [in] encodedImageBuffer The encoded buffer of the resource image file to use.
-   * @param [in] size The width and height to fit the loaded image to.
-   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
-   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
-   * @param [in] atlasUploadObserver The object to observe the uploading state inside ImageAtlas.
-   * @return The texture set containing the image.
-   */
-  TextureSet Add(Vector4&                  textureRect,
-                 const EncodedImageBuffer& encodedImageBuffer,
-                 const ImageDimensions&    size,
-                 FittingMode::Type         fittingMode           = FittingMode::DEFAULT,
-                 bool                      orientationCorrection = true,
-                 AtlasUploadObserver*      atlasUploadObserver   = NULL);
-
-  /**
-   * @brief Add a pixel buffer to the atlas
-   *
-   * @param [out] textureRect The texture area of the resource image in the atlas.
-   * @param [in] pixelData The pixel data.
-   * @return The texture set containing the image.
-   */
-  TextureSet Add(Vector4&  textureRect,
-                 PixelData pixelData);
-
-  /**
-   * Remove the image at the given rectangle from the texture set.
-   *
-   * @param [in] textureSet The texture set containing the atlas image.
-   * @param [in] textureRect The texture area to be removed.
-   */
-  void Remove(TextureSet textureSet, const Vector4& textureRect);
-
-  /**
-   * @brief Set the broken image which is used to replace the image if loading fails.
-   *
-   * @param[in] brokenImageUrl The url of the broken image.
-   */
-  void SetBrokenImage(const std::string& brokenImageUrl);
-
-  /**
-   * @brief Get shader
-   */
-  Shader GetShader() const;
-
-private:
-  /**
-   * @brief Create a new atlas.
-   *
-   * This method is called when the newly added image or pixel buffer cannot fit into the current atlas list.
-   */
-  void CreateNewAtlas();
-
-protected:
-  /**
-   * Destructor
-   */
-  ~ImageAtlasManager() override;
-
-  /**
-   * Undefined copy constructor.
-   */
-  ImageAtlasManager(const ImageAtlasManager&);
-
-  /**
-   * Undefined assignment operator.
-   */
-  ImageAtlasManager& operator=(const ImageAtlasManager& rhs);
-
-private:
-  AtlasContainer      mAtlasList;
-  TextureSetContainer mTextureSetList;
-  std::string         mBrokenImageUrl;
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_ATLAS_MANAGER_H
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-debug.cpp b/dali-toolkit/internal/visuals/image-visual-shader-debug.cpp
deleted file mode 100644 (file)
index bc2f930..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/visuals/image-visual-shader-debug.h>
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/environment-variable.h>
-#include <dali/devel-api/adaptor-framework/style-monitor.h> ///< for load json file.
-#include <dali/public-api/common/vector-wrapper.h>
-
-#include <regex> ///< for redefine shader
-#include <string_view>
-
-#include <dali/integration-api/debug.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
-#include <dali-toolkit/devel-api/builder/json-parser.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace
-{
-constexpr auto DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV = "DALI_DEBUG_IMAGE_VISUAL_SHADER";
-
-bool DebugImageVisualShaderEnvironmentEnabled()
-{
-  static bool enabled       = false;
-  static bool enabledSetted = false;
-  if(!enabledSetted)
-  {
-    enabledSetted           = true;
-    auto debugEnabledString = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV);
-    enabled                 = debugEnabledString ? std::atoi(debugEnabledString) : false;
-  }
-  return enabled;
-}
-
-constexpr auto DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV = "DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME";
-constexpr auto DEFAULT_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME  = "debug-image-visual-shader-script.json";
-
-const std::string& GetScriptFilename()
-{
-  // Set the full path for the default script file.
-  const static std::string styleDirPath{AssetManager::GetDaliStylePath()};
-  static std::string       mScriptFileName{};
-
-  if(DALI_UNLIKELY(mScriptFileName.empty()))
-  {
-    // Use user's own script if exist.
-    auto environmentScriptFilename = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV);
-
-    mScriptFileName = environmentScriptFilename ? std::string(environmentScriptFilename) : styleDirPath + std::string(DEFAULT_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME);
-
-    DALI_ASSERT_DEBUG(0 != mScriptFileName.length());
-  }
-
-  return mScriptFileName;
-}
-
-bool LoadJsonScript(std::string& stringOut)
-{
-  auto styleMonitor = StyleMonitor::Get();
-
-  // as toolkit is platform agnostic, it cannot load files from filesystem
-  // ask style monitor to load the style sheet
-  if(styleMonitor)
-  {
-    try
-    {
-      return styleMonitor.LoadThemeFile(GetScriptFilename(), stringOut);
-    }
-    catch(const std::exception& e)
-    {
-      DALI_LOG_ERROR("Something system exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
-      DALI_LOG_ERROR("Error message : [%s]\n", e.what());
-    }
-    catch(const Dali::DaliException& e)
-    {
-      DALI_LOG_ERROR("Something Dali exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
-      DALI_LOG_ERROR("Error message : [%s]\n", e.condition);
-    }
-    catch(...)
-    {
-      DALI_LOG_ERROR("Something unkown exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
-    }
-  }
-
-  return false;
-}
-// Json keywords what we will get information from json.
-constexpr std::string_view DEBUG_SCRIPT_VERSION_JSON_KEY = "version";
-
-constexpr std::string_view DEBUG_EXTRA_ATTRIBUTES_JSON_KEY    = "extraAttributes";
-constexpr std::string_view DEBUG_EXTRA_VARYINGS_JSON_KEY      = "extraVaryings";
-constexpr std::string_view DEBUG_EXTRA_UNIFORMS_JSON_KEY      = "extraUniforms";
-constexpr std::string_view DEBUG_APPLY_VARYINGS_CODE_JSON_KEY = "applyVaryingsCode";
-
-constexpr std::string_view MINIMUM_DEBUG_COLOR_RATE_JSON_KEY = "minimumColorRate";
-constexpr std::string_view MAXIMUM_DEBUG_COLOR_RATE_JSON_KEY = "maximumColorRate";
-
-constexpr std::string_view DEBUG_RED_CHANNEL_CODE_JSON_KEY   = "redChannelCodes";
-constexpr std::string_view DEBUG_GREEN_CHANNEL_CODE_JSON_KEY = "greenChannelCodes";
-constexpr std::string_view DEBUG_BLUE_CHANNEL_CODE_JSON_KEY  = "blueChannelCodes";
-constexpr std::string_view DEBUG_TRIGGER_CODE_JSON_KEY       = "triggerCode";
-constexpr std::string_view DEBUG_RATIO_CODE_JSON_KEY         = "ratioCode";
-
-// Macro keywords what we will replace at vertex/fragment shader.
-constexpr std::string_view DEBUG_EXTRA_ATTRIBUTES_MACRO_KEY    = "DEBUG_EXTRA_ATTRIBUTES";
-constexpr std::string_view DEBUG_EXTRA_VARYINGS_MACRO_KEY      = "DEBUG_EXTRA_VARYINGS";
-constexpr std::string_view DEBUG_EXTRA_UNIFORMS_MACRO_KEY      = "DEBUG_EXTRA_UNIFORMS";
-constexpr std::string_view DEBUG_APPLY_VARYINGS_CODE_MACRO_KEY = "DEBUG_APPLY_VARYING_CODE";
-
-constexpr std::string_view MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY = "MINIMUM_DEBUG_COLOR_RATE";
-constexpr std::string_view MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY = "MAXIMUM_DEBUG_COLOR_RATE";
-
-constexpr std::string_view DEBUG_TRIGGER_RED_CODE_MACRO_KEY   = "DEBUG_TRIGGER_RED_CODE";
-constexpr std::string_view DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY = "DEBUG_TRIGGER_GREEN_CODE";
-constexpr std::string_view DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY  = "DEBUG_TRIGGER_BLUE_CODE";
-constexpr std::string_view DEBUG_RATIO_RED_CODE_MACRO_KEY     = "DEBUG_RATIO_RED_CODE";
-constexpr std::string_view DEBUG_RATIO_GREEN_CODE_MACRO_KEY   = "DEBUG_RATIO_GREEN_CODE";
-constexpr std::string_view DEBUG_RATIO_BLUE_CODE_MACRO_KEY    = "DEBUG_RATIO_BLUE_CODE";
-
-// Default macro keywords when we fail to parse script.
-constexpr std::string_view DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE          = "0.0";
-constexpr std::string_view DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE        = "return false;";
-constexpr std::string_view DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE          = "return 0.0;";
-constexpr std::string_view DEFAULT_DEBUG_APPLY_VARYINGS_CODE_MACRO_VALUE = "return;";
-
-constexpr std::string_view EMPTY_STRING                    = "";
-constexpr std::string_view VERTEX_SHADER_ATTRIBUTES_PREFIX = "INPUT";
-constexpr std::string_view VERTEX_SHADER_VARYINGS_PREFIX   = "OUTPUT";
-constexpr std::string_view FRAGMENT_SHADER_VARYINGS_PREFIX = "INPUT";
-constexpr std::string_view UNIFORMS_PREFIX                 = "uniform";
-
-bool ParseScriptInfomation(Property::Map& vertexResult, Property::Map& fragmentResult)
-{
-  std::string stringOut;
-  if(!LoadJsonScript(stringOut))
-  {
-    DALI_LOG_ERROR("Fail to load script file [%s]\n", GetScriptFilename().c_str());
-    return false;
-  }
-
-  Toolkit::JsonParser parser = Toolkit::JsonParser::New();
-
-  if(!parser.Parse(stringOut))
-  {
-    std::ostringstream stream;
-    if(parser.ParseError())
-    {
-      stream << "position: " << parser.GetErrorPosition() << ", line: " << parser.GetErrorLineNumber() << ", column: " << parser.GetErrorColumn() << ", description: " << parser.GetErrorDescription() << ".";
-    }
-    DALI_LOG_ERROR("Fail to parse json script\nError : %s\nJson : %s\n", stream.str().c_str(), stringOut.c_str());
-    return false;
-  }
-
-  const auto* rootNode = parser.GetRoot();
-  if(!rootNode)
-  {
-    DALI_LOG_ERROR("Fail to get root node\n");
-    return false;
-  }
-
-  auto InsertScriptMap = [](Property::Map& result, const TreeNode* node, const std::string_view& jsonKey, const std::string_view& macroKey, const std::string_view& defaultValue, const std::string_view& prefixString) {
-    std::ostringstream oss;
-    oss.clear();
-
-    if(node)
-    {
-      const auto* childNode = node->GetChild(jsonKey);
-
-      if(childNode)
-      {
-        if(childNode->GetType() == TreeNode::FLOAT)
-        {
-          oss << childNode->GetFloat();
-        }
-        else if(childNode->GetType() == TreeNode::STRING)
-        {
-          if(!prefixString.empty())
-          {
-            oss << prefixString << " ";
-          }
-          oss << childNode->GetString();
-        }
-        else if(childNode->GetType() == TreeNode::ARRAY)
-        {
-          // Concat strings with line feed
-          bool isFirst = true;
-          for(auto iter = childNode->CBegin(), endIter = childNode->CEnd(); iter != endIter; ++iter)
-          {
-            if((*iter).second.GetType() == TreeNode::STRING)
-            {
-              if(isFirst)
-              {
-                isFirst = false;
-              }
-              else
-              {
-                oss << "\n";
-              }
-              if(!prefixString.empty())
-              {
-                oss << prefixString << " ";
-              }
-              oss << (*iter).second.GetString();
-            }
-          }
-        }
-      }
-    }
-
-    if(oss.str().empty() && !defaultValue.empty())
-    {
-      oss << defaultValue;
-    }
-
-    if(!oss.str().empty())
-    {
-      result.Insert(std::string(macroKey), oss.str());
-    }
-  };
-
-  auto InsertChannelScriptMap = [&InsertScriptMap](Property::Map& result, const TreeNode* node, const std::string_view& channelJsonKey, const std::string_view& triggerMacroKey, const std::string_view& ratioMacroKey) {
-    const auto* channelNode = node->GetChild(channelJsonKey);
-    InsertScriptMap(result, channelNode, DEBUG_TRIGGER_CODE_JSON_KEY, triggerMacroKey, DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE, EMPTY_STRING);
-    InsertScriptMap(result, channelNode, DEBUG_RATIO_CODE_JSON_KEY, ratioMacroKey, DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE, EMPTY_STRING);
-  };
-
-  // Get attribute value code
-  InsertScriptMap(vertexResult, rootNode, DEBUG_EXTRA_ATTRIBUTES_JSON_KEY, DEBUG_EXTRA_ATTRIBUTES_MACRO_KEY, EMPTY_STRING, VERTEX_SHADER_ATTRIBUTES_PREFIX);
-
-  // Get varying value code
-  InsertScriptMap(vertexResult, rootNode, DEBUG_EXTRA_VARYINGS_JSON_KEY, DEBUG_EXTRA_VARYINGS_MACRO_KEY, EMPTY_STRING, VERTEX_SHADER_VARYINGS_PREFIX);
-  InsertScriptMap(fragmentResult, rootNode, DEBUG_EXTRA_VARYINGS_JSON_KEY, DEBUG_EXTRA_VARYINGS_MACRO_KEY, EMPTY_STRING, FRAGMENT_SHADER_VARYINGS_PREFIX);
-
-  // Get uniform value code
-  InsertScriptMap(vertexResult, rootNode, DEBUG_EXTRA_UNIFORMS_JSON_KEY, DEBUG_EXTRA_UNIFORMS_MACRO_KEY, EMPTY_STRING, UNIFORMS_PREFIX);
-  InsertScriptMap(fragmentResult, rootNode, DEBUG_EXTRA_UNIFORMS_JSON_KEY, DEBUG_EXTRA_UNIFORMS_MACRO_KEY, EMPTY_STRING, UNIFORMS_PREFIX);
-
-  // Get apply varying code
-  InsertScriptMap(vertexResult, rootNode, DEBUG_APPLY_VARYINGS_CODE_JSON_KEY, DEBUG_APPLY_VARYINGS_CODE_MACRO_KEY, DEFAULT_DEBUG_APPLY_VARYINGS_CODE_MACRO_VALUE, EMPTY_STRING);
-
-  // Get color rate
-  InsertScriptMap(fragmentResult, rootNode, MINIMUM_DEBUG_COLOR_RATE_JSON_KEY, MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY, DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE, EMPTY_STRING);
-  InsertScriptMap(fragmentResult, rootNode, MAXIMUM_DEBUG_COLOR_RATE_JSON_KEY, MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY, DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE, EMPTY_STRING);
-
-  // Get each color ChannelCodes
-  InsertChannelScriptMap(fragmentResult, rootNode, DEBUG_RED_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_RED_CODE_MACRO_KEY, DEBUG_RATIO_RED_CODE_MACRO_KEY);
-  InsertChannelScriptMap(fragmentResult, rootNode, DEBUG_GREEN_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY, DEBUG_RATIO_GREEN_CODE_MACRO_KEY);
-  InsertChannelScriptMap(fragmentResult, rootNode, DEBUG_BLUE_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY, DEBUG_RATIO_BLUE_CODE_MACRO_KEY);
-
-  return true;
-}
-
-const std::vector<Property::Map>& GetScriptInfomation()
-{
-  static std::vector<Property::Map> results;
-
-  if(DALI_UNLIKELY(results.empty()))
-  {
-    results.resize(2);
-
-    auto& vertexShaderResult   = results[0];
-    auto& fragmentShaderResult = results[1];
-
-    if(!ParseScriptInfomation(vertexShaderResult, fragmentShaderResult))
-    {
-      // Use default script information if parse failed.
-      vertexShaderResult.Clear();
-      fragmentShaderResult.Clear();
-
-      vertexShaderResult.Insert(std::string(DEBUG_APPLY_VARYINGS_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_APPLY_VARYINGS_CODE_MACRO_VALUE));
-
-      fragmentShaderResult.Insert(std::string(MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY), std::string(DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE));
-      fragmentShaderResult.Insert(std::string(MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY), std::string(DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE));
-      fragmentShaderResult.Insert(std::string(DEBUG_TRIGGER_RED_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
-      fragmentShaderResult.Insert(std::string(DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
-      fragmentShaderResult.Insert(std::string(DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
-      fragmentShaderResult.Insert(std::string(DEBUG_RATIO_RED_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
-      fragmentShaderResult.Insert(std::string(DEBUG_RATIO_GREEN_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
-      fragmentShaderResult.Insert(std::string(DEBUG_RATIO_BLUE_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
-    }
-  }
-
-  return results;
-}
-
-void RedefineMacro(std::string& shaderCode, std::string macro, std::string value)
-{
-  std::string definition = "#define " + macro;
-  std::size_t found      = shaderCode.find(definition);
-  DALI_ASSERT_ALWAYS(found != std::string::npos && "Macro keyword was not exist in shader code!");
-
-  std::size_t insertionPoint = found + definition.length();
-
-  // Automatically insert line-continuation character into value
-  std::regex                 re("\n");
-  std::sregex_token_iterator first{value.begin(), value.end(), re, -1}, last;
-  for(auto i = first; i != last; ++i)
-  {
-    std::string line = std::string(" \\\n") + (*i).str();
-    shaderCode.insert(insertionPoint, line);
-    insertionPoint += line.length();
-  }
-}
-
-} // namespace
-
-namespace ImageVisualShaderDebug
-{
-bool DebugImageVisualShaderEnabled()
-{
-  return DebugImageVisualShaderEnvironmentEnabled();
-}
-
-void ApplyImageVisualShaderDebugScriptCode(std::string& vertexShader, std::string& fragmentShader)
-{
-  const auto& resultMaps = GetScriptInfomation();
-
-  for(std::size_t i = 0u; i < resultMaps[0].Count(); ++i)
-  {
-    auto        key   = resultMaps[0].GetKeyAt(i);
-    const auto& value = resultMaps[0].GetValue(i);
-
-    RedefineMacro(vertexShader, std::move(key.stringKey), value.Get<std::string>());
-  }
-
-  for(std::size_t i = 0u; i < resultMaps[1].Count(); ++i)
-  {
-    auto        key   = resultMaps[1].GetKeyAt(i);
-    const auto& value = resultMaps[1].GetValue(i);
-
-    RedefineMacro(fragmentShader, std::move(key.stringKey), value.Get<std::string>());
-  }
-}
-} // namespace ImageVisualShaderDebug
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-debug.h b/dali-toolkit/internal/visuals/image-visual-shader-debug.h
deleted file mode 100644 (file)
index aff6130..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
-#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
-
-/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace ImageVisualShaderDebug
-{
-/**
- * @brief Check whether we need to use debug option for image visual.
- *
- * @return True if ImageVisualShader relative environment on. False otherwise.
- */
-bool DebugImageVisualShaderEnabled();
-
-/**
- * @brief Apply vertex / fragment shader use debug script.
- *
- * @param[in, out] vertexShader Vertex shader code to apply debug script.
- * @param[in, out] fragmentShader Fragment shader code to apply debug script.
- */
-void ApplyImageVisualShaderDebugScriptCode(std::string& vertexShader, std::string& fragmentShader);
-
-} // namespace ImageVisualShaderDebug
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp
deleted file mode 100644 (file)
index f0e413c..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/rendering/texture-devel.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-debug.h>
-#include <dali-toolkit/internal/visuals/visual-string-constants.h>
-#include <dali/integration-api/debug.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace
-{
-const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
-
-constexpr int              NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMAGE_SHADER - VisualFactoryCache::ShaderType::IMAGE_SHADER;
-constexpr std::string_view Y_FLIP_MASK_TEXTURE       = "uYFlipMaskTexture";
-constexpr float            NOT_FLIP_MASK_TEXTURE     = 0.0f;
-
-constexpr auto SHADER_TYPE_COUNT = 6u;
-
-constexpr std::string_view VertexPredefines[SHADER_TYPE_COUNT]{
-  "",                                     // VisualFactoryCache::IMAGE_SHADER,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
-  "",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
-  "",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
-};
-constexpr std::string_view FragmentPredefines[SHADER_TYPE_COUNT]{
-  "",                                                                              // VisualFactoryCache::IMAGE_SHADER,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n",                                          // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
-  "#define IS_REQUIRED_YUV_TO_RGB\n",                                              // VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_YUV_TO_RGB\n",          // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
-  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
-  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
-};
-constexpr VisualFactoryCache::ShaderType ShaderTypePredefines[SHADER_TYPE_COUNT]{
-  VisualFactoryCache::ShaderType::IMAGE_SHADER,
-  VisualFactoryCache::ShaderType::IMAGE_SHADER_ROUNDED_CORNER,
-  VisualFactoryCache::ShaderType::IMAGE_SHADER_YUV_TO_RGB,
-  VisualFactoryCache::ShaderType::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
-  VisualFactoryCache::ShaderType::IMAGE_SHADER_YUV_AND_RGB,
-  VisualFactoryCache::ShaderType::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
-};
-} // unnamed namespace
-
-ImageVisualShaderFactory::ImageVisualShaderFactory()
-: mFragmentShaderNeedChange(ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED)
-{
-}
-
-ImageVisualShaderFactory::~ImageVisualShaderFactory()
-{
-}
-
-Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, ImageVisualShaderFeatureBuilder& featureBuilder)
-{
-  Shader                         shader;
-  VisualFactoryCache::ShaderType shaderType = featureBuilder.GetShaderType();
-
-  if(featureBuilder.NeedToChangeFragmentShader() == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE &&
-     (mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED ||
-      mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE))
-  {
-    DALI_ASSERT_DEBUG((static_cast<int>(shaderType) >= static_cast<int>(VisualFactoryCache::IMAGE_SHADER)) &&
-                      (static_cast<int>(shaderType) <= static_cast<int>(VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP)) &&
-                      "Do not support native image shader for given feature!!");
-    shaderType = static_cast<VisualFactoryCache::ShaderType>(static_cast<int>(shaderType) + NATIVE_SHADER_TYPE_OFFSET);
-  }
-
-  shader = factoryCache.GetShader(shaderType);
-  if(shader)
-  {
-    return shader;
-  }
-
-  std::string vertexShaderPrefixList;
-  std::string fragmentShaderPrefixList;
-  featureBuilder.GetVertexShaderPrefixList(vertexShaderPrefixList);
-  featureBuilder.GetFragmentShaderPrefixList(fragmentShaderPrefixList);
-
-  if(Dali::Toolkit::Internal::ImageVisualShaderDebug::DebugImageVisualShaderEnabled())
-  {
-    vertexShaderPrefixList += "#define IS_REQUIRED_DEBUG_VISUAL_SHADER\n";
-    fragmentShaderPrefixList += "#define IS_REQUIRED_DEBUG_VISUAL_SHADER\n";
-  }
-
-  std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
-  std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_FRAG.data());
-
-  if(Dali::Toolkit::Internal::ImageVisualShaderDebug::DebugImageVisualShaderEnabled())
-  {
-    Dali::Toolkit::Internal::ImageVisualShaderDebug::ApplyImageVisualShaderDebugScriptCode(vertexShader, fragmentShader);
-  }
-
-  if(featureBuilder.NeedToChangeFragmentShader() == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE)
-  {
-    bool modified = DevelTexture::ApplyNativeFragmentShader(featureBuilder.GetTexture(), fragmentShader);
-    if(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE)
-    {
-      DALI_ASSERT_ALWAYS(modified && "NativeImageTexture need to change fragment shader. But DALI default image shader doesn't changed!");
-    }
-    else if(DALI_UNLIKELY(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED))
-    {
-      mFragmentShaderNeedChange = (modified) ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
-
-      if(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE)
-      {
-        shaderType = static_cast<VisualFactoryCache::ShaderType>(static_cast<int>(shaderType) - NATIVE_SHADER_TYPE_OFFSET);
-        shader     = factoryCache.GetShader(shaderType);
-      }
-    }
-  }
-
-  if(shader)
-  {
-    return shader;
-  }
-
-  shader = factoryCache.GenerateAndSaveShader(shaderType, vertexShader, fragmentShader);
-  shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
-  if(featureBuilder.IsEnabledAlphaMaskingOnRendering())
-  {
-    shader.RegisterProperty(Y_FLIP_MASK_TEXTURE, NOT_FLIP_MASK_TEXTURE);
-  }
-
-  return shader;
-}
-
-std::string_view ImageVisualShaderFactory::GetVertexShaderSource()
-{
-  // static string variable to cache complete vertex shader
-  static std::string gVertexShader;
-  if(gVertexShader.empty())
-  {
-    gVertexShader = Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data();
-  }
-
-  return gVertexShader;
-}
-
-std::string_view ImageVisualShaderFactory::GetFragmentShaderSource()
-{
-  // static string variable to cache complete fragment shader (no atlas)
-  static std::string gFragmentShaderNoAtlas;
-  if(gFragmentShaderNoAtlas.empty())
-  {
-    gFragmentShaderNoAtlas = Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_FRAG.data();
-  }
-  return gFragmentShaderNoAtlas;
-}
-
-void ImageVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
-{
-  std::vector<std::string_view> vertexPrefix;
-  std::vector<std::string_view> fragmentPrefix;
-  std::vector<std::string_view> shaderName;
-  shaders.shaderCount = 0;
-  int shaderCount     = 0;
-  for(uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i)
-  {
-    vertexPrefix.push_back(VertexPredefines[i]);
-    fragmentPrefix.push_back(FragmentPredefines[i]);
-    shaderName.push_back(Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(ShaderTypePredefines[i], VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
-    shaderCount++;
-  }
-
-  shaders.vertexPrefix   = vertexPrefix;
-  shaders.fragmentPrefix = fragmentPrefix;
-  shaders.shaderName     = shaderName;
-  shaders.vertexShader   = SHADER_IMAGE_VISUAL_SHADER_VERT;
-  shaders.fragmentShader = SHADER_IMAGE_VISUAL_SHADER_FRAG;
-  shaders.shaderCount    = shaderCount;
-}
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.h b/dali-toolkit/internal/visuals/image-visual-shader-factory.h
deleted file mode 100644 (file)
index 8b50669..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
-#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
-
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
-#include <string_view>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-
-/**
- * ImageVisualShaderFactory is an object that provides and shares shaders between image visuals
- */
-class ImageVisualShaderFactory
-{
-public:
-  /**
-   * @brief Constructor
-   */
-  ImageVisualShaderFactory();
-
-  /**
-   * @brief Destructor
-   */
-  ~ImageVisualShaderFactory();
-
-  /**
-   * @brief Get the standard image rendering shader.
-   * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
-   * @param[in] featureBuilder Collection of current image shader's features
-   * @return The standard image rendering shader with features.
-   */
-  Shader GetShader(VisualFactoryCache& factoryCache, ImageVisualShaderFeatureBuilder& featureBuilder);
-
-  /**
-   * @brief Request the default vertex shader source.
-   * @return The default vertex shader source.
-   */
-  std::string_view GetVertexShaderSource();
-
-  /**
-   * @brief Request the default fragment shader source.
-   * @return The default fragment shader source.
-   */
-  std::string_view GetFragmentShaderSource();
-
-  /**
-   * @brief Get the default shader source.
-   * @param[in] shaders shaderList for precompile
-   */
-  void GetPreCompiledShader(RawShaderData& shaders);
-
-protected:
-  /**
-   * Undefined copy constructor.
-   */
-  ImageVisualShaderFactory(const ImageVisualShaderFactory&);
-
-  /**
-   * Undefined assignment operator.
-   */
-  ImageVisualShaderFactory& operator=(const ImageVisualShaderFactory& rhs);
-
-private:
-  /**
-   * @brief Cached information whether native image should change fragment shader.
-   * Default it is ChangeFragmentShader::UNDECIDED.
-   * If we have any chance to check native image source apply fragment shader,
-   * this vaule will be changed one of these : ChangeFragmentShader::DONT_CHANGE or ChangeFragmentShader::NEED_CHANGE
-   *
-   * After result cached, this value will not be changed.
-   *
-   * If value is DONT_CHANGE, ImageVisualShaderFactory::GetShader never call ApplyNativeFragmentShader.
-   * Else, ImageVisualShaderFactory::GetShader will call ApplyNativeFragmentShader if native image source texture come.
-   */
-  ImageVisualShaderFeature::ChangeFragmentShader::Type mFragmentShaderNeedChange : 3;
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.cpp b/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.cpp
deleted file mode 100644 (file)
index 6939cd1..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace
-{
-// enum of required list when we select shader
-enum class ImageVisualRequireFlag : uint32_t
-{
-  DEFAULT          = 0,
-  ROUNDED_CORNER   = 1 << 0,
-  BORDERLINE       = 1 << 1,
-  ALPHA_MASKING    = 1 << 2,
-  COLOR_CONVERSION = 1 << 3,
-
-  UNIFIED_YUV_AND_RGB = 1 << 2, // Special enum to trick unified YUV and RGB.
-};
-
-static constexpr auto          SHADER_TYPE_COUNT = 16u;
-VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
-  {
-    VisualFactoryCache::IMAGE_SHADER,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
-    VisualFactoryCache::IMAGE_SHADER_BORDERLINE,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE,
-    VisualFactoryCache::IMAGE_SHADER_MASKING,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
-    VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
-    VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
-    VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_TO_RGB,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_TO_RGB,
-    VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
-    VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_AND_RGB,
-    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB};
-} // unnamed namespace
-
-ImageVisualShaderFeatureBuilder::ImageVisualShaderFeatureBuilder()
-: mTextureAtlas(ImageVisualShaderFeature::TextureAtlas::DISABLED),
-  mDefaultTextureWrapMode(ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY),
-  mRoundedCorner(ImageVisualShaderFeature::RoundedCorner::DISABLED),
-  mBorderline(ImageVisualShaderFeature::Borderline::DISABLED),
-  mAlphaMaskingOnRendering(ImageVisualShaderFeature::AlphaMaskingOnRendering::DISABLED),
-  mColorConversion(ImageVisualShaderFeature::ColorConversion::DONT_NEED),
-  mTexture()
-{
-}
-
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableTextureAtlas(bool enableTextureAtlas)
-{
-  mTextureAtlas = (enableTextureAtlas ? ImageVisualShaderFeature::TextureAtlas::ENABLED : ImageVisualShaderFeature::TextureAtlas::DISABLED);
-  return *this;
-}
-
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode)
-{
-  mDefaultTextureWrapMode = (applyDefaultTextureWrapMode ? ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY : ImageVisualShaderFeature::DefaultTextureWrapMode::DO_NOT_APPLY);
-  return *this;
-}
-
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableRoundedCorner(bool enableRoundedCorner)
-{
-  mRoundedCorner = (enableRoundedCorner ? ImageVisualShaderFeature::RoundedCorner::ENABLED : ImageVisualShaderFeature::RoundedCorner::DISABLED);
-  return *this;
-}
-
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableBorderline(bool enableBorderline)
-{
-  mBorderline = (enableBorderline ? ImageVisualShaderFeature::Borderline::ENABLED : ImageVisualShaderFeature::Borderline::DISABLED);
-  return *this;
-}
-
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::SetTextureForFragmentShaderCheck(const Dali::Texture& texture)
-{
-  mTexture = texture;
-  return *this;
-}
-
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering)
-{
-  mAlphaMaskingOnRendering = (enableAlphaMaskingOnRendering ? ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED : ImageVisualShaderFeature::AlphaMaskingOnRendering::DISABLED);
-  return *this;
-}
-
-ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb)
-{
-  mColorConversion = (enableUnifiedYuvAndRgb ? ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB : (enableYuvToRgb ? ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB : ImageVisualShaderFeature::ColorConversion::DONT_NEED));
-  return *this;
-}
-
-VisualFactoryCache::ShaderType ImageVisualShaderFeatureBuilder::GetShaderType()
-{
-  VisualFactoryCache::ShaderType shaderType = VisualFactoryCache::IMAGE_SHADER;
-  if(mTextureAtlas == ImageVisualShaderFeature::TextureAtlas::ENABLED)
-  {
-    if(mDefaultTextureWrapMode == ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY)
-    {
-      shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP;
-    }
-    else
-    {
-      shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP;
-    }
-  }
-  else
-  {
-    uint32_t shaderTypeFlag = static_cast<uint32_t>(ImageVisualRequireFlag::DEFAULT);
-    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
-    {
-      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ROUNDED_CORNER);
-    }
-    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
-    {
-      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::BORDERLINE);
-    }
-    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
-    {
-      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ALPHA_MASKING);
-    }
-    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB) // Not support gpu masking and color conversion at the same time now
-    {
-      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
-    }
-    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB)
-    {
-      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
-      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::UNIFIED_YUV_AND_RGB);
-    }
-    shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
-  }
-
-  return shaderType;
-}
-
-ImageVisualShaderFeature::ChangeFragmentShader::Type ImageVisualShaderFeatureBuilder::NeedToChangeFragmentShader()
-{
-  return (mTexture && DevelTexture::IsNative(mTexture))
-           ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE
-           : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
-}
-
-void ImageVisualShaderFeatureBuilder::GetVertexShaderPrefixList(std::string& vertexShaderPrefixList)
-{
-  if(mTextureAtlas != ImageVisualShaderFeature::TextureAtlas::ENABLED)
-  {
-    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
-    {
-      vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER\n";
-    }
-    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
-    {
-      vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE\n";
-    }
-    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
-    {
-      vertexShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
-    }
-  }
-}
-
-void ImageVisualShaderFeatureBuilder::GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList)
-{
-  if(mTextureAtlas == ImageVisualShaderFeature::TextureAtlas::ENABLED)
-  {
-    if(mDefaultTextureWrapMode == ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY)
-    {
-      fragmentShaderPrefixList += "#define ATLAS_DEFAULT_WARP\n";
-    }
-    else
-    {
-      fragmentShaderPrefixList += "#define ATLAS_CUSTOM_WARP\n";
-    }
-  }
-  else
-  {
-    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER\n";
-    }
-    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE\n";
-    }
-    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
-    }
-    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_YUV_TO_RGB\n";
-    }
-    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n";
-    }
-  }
-}
-
-Dali::Texture ImageVisualShaderFeatureBuilder::GetTexture()
-{
-  return mTexture;
-}
-
-bool ImageVisualShaderFeatureBuilder::IsEnabledAlphaMaskingOnRendering() const
-{
-  return mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED;
-}
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h b/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h
deleted file mode 100644 (file)
index 0f1eccb..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FEATURE_BUILDER_H
-#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FEATURE_BUILDER_H
-
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/rendering/texture.h>
-#include <dali/devel-api/rendering/texture-devel.h>
-#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-/**
- * ImageVisualShaderFeature contains feature lists what image visual shader need to know.
- */
-namespace ImageVisualShaderFeature
-{
-namespace TextureAtlas
-{
-/**
- * @brief Whether use texture with atlas, or not
- */
-enum Type
-{
-  DISABLED = 0, ///< Image visual doesn't use ATLAS
-  ENABLED       ///< Image visual uses ATLAS
-};
-} // namespace TextureAtlas
-
-namespace DefaultTextureWrapMode
-{
-/**
- * @brief Whether apply to texture wraping in default, or not
- */
-enum Type
-{
-  APPLY = 0,   ///< Image visual applies to wraping texture in default
-  DO_NOT_APPLY ///< Image visual doesn't apply to wraping texture in default
-};
-} // namespace DefaultTextureWrapMode
-
-namespace RoundedCorner
-{
-/**
- * @brief Whether use rounded corner, or not
- */
-enum Type
-{
-  DISABLED = 0, ///< Image visual doesn't use rounded corner
-  ENABLED       ///< Image visual uses rounded corner
-};
-} // namespace RoundedCorner
-
-namespace Borderline
-{
-/**
- * @brief Whether use borderline, or not
- */
-enum Type
-{
-  DISABLED = 0, ///< Image visual doesn't use borderline
-  ENABLED       ///< Image visual uses borderline
-};
-} // namespace Borderline
-
-namespace ChangeFragmentShader
-{
-/**
- * @brief Whether native image change the default fragment shader, or not
- */
-enum Type
-{
-  DONT_CHANGE = 0, ///< Native image doesn't change default fragment shader.
-  NEED_CHANGE,     ///< Native image changes default fragment shader. We need another shader cache.
-  UNDECIDED,       ///< Undecided.
-};
-} // namespace ChangeFragmentShader
-
-namespace AlphaMaskingOnRendering
-{
-/**
- * @brief Whether use runtime alpha masking in shader, or not
- */
-enum Type
-{
-  DISABLED = 0, ///< Image visual doesn't use runtime alpha masking
-  ENABLED       ///< Image visual uses runtime alpha masking
-};
-} // namespace AlphaMaskingOnRendering
-
-namespace ColorConversion
-{
-/**
- * @brief Whether the color format conversion is needed or not
- */
-enum Type
-{
-  DONT_NEED = 0,      ///< Not need to convert
-  YUV_TO_RGB,         ///< Need yuv to rgb conversion
-  UNIFIED_YUV_AND_RGB ///< Need to support both yuv conversion case and normal case.
-};
-} // namespace ColorConversion
-
-} // namespace ImageVisualShaderFeature
-
-/**
- * @brief Collection of current image visual feature. Only use for ImageVisualShaderFactory::GetShader()
- */
-class ImageVisualShaderFeatureBuilder
-{
-public:
-  ImageVisualShaderFeatureBuilder();
-
-  ImageVisualShaderFeatureBuilder& EnableTextureAtlas(bool enableTextureAtlas);
-
-  ImageVisualShaderFeatureBuilder& ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode);
-
-  ImageVisualShaderFeatureBuilder& EnableRoundedCorner(bool enableRoundedCorner);
-
-  ImageVisualShaderFeatureBuilder& EnableBorderline(bool enableBorderline);
-
-  ImageVisualShaderFeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
-
-  ImageVisualShaderFeatureBuilder& EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering);
-
-  ImageVisualShaderFeatureBuilder& EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb = false);
-
-  VisualFactoryCache::ShaderType GetShaderType();
-
-  ImageVisualShaderFeature::ChangeFragmentShader::Type NeedToChangeFragmentShader();
-
-  void GetVertexShaderPrefixList(std::string& vertexShaderPrefixList);
-  void GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList);
-
-  Dali::Texture GetTexture();
-
-  bool IsEnabledAlphaMaskingOnRendering() const;
-
-private:
-  ImageVisualShaderFeature::TextureAtlas::Type            mTextureAtlas : 2;            ///< Whether use texture with atlas, or not. default as TextureAtlas::DISABLED
-  ImageVisualShaderFeature::DefaultTextureWrapMode::Type  mDefaultTextureWrapMode : 2;  ///< Whether apply to texture wraping in default, or not. default as DefaultTextureWrapMode::APPLY
-  ImageVisualShaderFeature::RoundedCorner::Type           mRoundedCorner : 2;           ///< Whether use rounded corner, or not. default as RoundedCorner::DISABLED
-  ImageVisualShaderFeature::Borderline::Type              mBorderline : 2;              ///< Whether use borderline, or not. default as Borderline::DISABLED
-  ImageVisualShaderFeature::AlphaMaskingOnRendering::Type mAlphaMaskingOnRendering : 2; ///< Whether use runtime alpha masking, or not. default as AlphaMaskingOnRendering::DISABLED
-  ImageVisualShaderFeature::ColorConversion::Type         mColorConversion : 2;         ///< Whether the color format conversion is needed or not
-  Dali::Texture                                           mTexture;                     ///< Texture to check whether we need to change fragment shader or not
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
diff --git a/dali-toolkit/internal/visuals/image/image-atlas-manager.cpp b/dali-toolkit/internal/visuals/image/image-atlas-manager.cpp
new file mode 100644 (file)
index 0000000..c1c1970
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h>
+
+// EXTERNAL HEADER
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+
+// INTERNAL HEADERS
+#include <dali-toolkit/internal/image-loader/image-atlas-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+const uint32_t DEFAULT_ATLAS_SIZE(1024u); // this size can fit 8 by 8 images of average size 128*128
+const uint32_t MAX_ITEM_SIZE(512u);
+const uint32_t MAX_ITEM_AREA(MAX_ITEM_SIZE* MAX_ITEM_SIZE);
+} // namespace
+
+ImageAtlasManager::ImageAtlasManager()
+: mBrokenImageUrl("")
+{
+}
+
+ImageAtlasManager::~ImageAtlasManager()
+{
+}
+
+bool ImageAtlasManager::CheckAtlasAvailable(const VisualUrl& url, const ImageDimensions& size) const
+{
+  ImageDimensions dimensions = size;
+  ImageDimensions zero;
+  if(size == zero)
+  {
+    dimensions = Dali::GetClosestImageSize(url.GetUrl());
+  }
+
+  // big image, atlasing is not applied
+  if(static_cast<uint32_t>(dimensions.GetWidth()) * static_cast<uint32_t>(dimensions.GetHeight()) > MAX_ITEM_AREA || dimensions.GetWidth() > DEFAULT_ATLAS_SIZE || dimensions.GetHeight() > DEFAULT_ATLAS_SIZE)
+  {
+    return false;
+  }
+  return true;
+}
+
+TextureSet ImageAtlasManager::Add(Vector4&             textureRect,
+                                  const VisualUrl&     url,
+                                  ImageDimensions&     size,
+                                  FittingMode::Type    fittingMode,
+                                  bool                 orientationCorrection,
+                                  AtlasUploadObserver* atlasUploadObserver)
+{
+  ImageDimensions dimensions = size;
+  ImageDimensions zero;
+  if(size == zero)
+  {
+    dimensions = Dali::GetClosestImageSize(url.GetUrl());
+  }
+
+  // big image, atlasing is not applied
+  if(static_cast<uint32_t>(dimensions.GetWidth()) * static_cast<uint32_t>(dimensions.GetHeight()) > MAX_ITEM_AREA || dimensions.GetWidth() > DEFAULT_ATLAS_SIZE || dimensions.GetHeight() > DEFAULT_ATLAS_SIZE)
+  {
+    return TextureSet();
+  }
+  size = dimensions;
+
+  uint32_t i = 0;
+  for(AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
+  {
+    if(GetImplementation(*iter).Upload(textureRect, url, size, fittingMode, orientationCorrection, atlasUploadObserver))
+    {
+      return mTextureSetList[i];
+    }
+    i++;
+  }
+
+  CreateNewAtlas();
+  GetImplementation(mAtlasList.back()).Upload(textureRect, url, size, fittingMode, orientationCorrection, atlasUploadObserver);
+  return mTextureSetList.back();
+}
+
+TextureSet ImageAtlasManager::Add(Vector4&                  textureRect,
+                                  const EncodedImageBuffer& encodedImageBuffer,
+                                  const ImageDimensions&    size,
+                                  FittingMode::Type         fittingMode,
+                                  bool                      orientationCorrection,
+                                  AtlasUploadObserver*      atlasUploadObserver)
+{
+  // big image, atlasing is not applied
+  if(static_cast<uint32_t>(size.GetWidth()) * static_cast<uint32_t>(size.GetHeight()) > MAX_ITEM_AREA || size.GetWidth() > DEFAULT_ATLAS_SIZE || size.GetHeight() > DEFAULT_ATLAS_SIZE)
+  {
+    return TextureSet();
+  }
+
+  uint32_t i = 0;
+  for(AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
+  {
+    if(GetImplementation(*iter).Upload(textureRect, encodedImageBuffer, size, fittingMode, orientationCorrection, atlasUploadObserver))
+    {
+      return mTextureSetList[i];
+    }
+    i++;
+  }
+
+  CreateNewAtlas();
+  GetImplementation(mAtlasList.back()).Upload(textureRect, encodedImageBuffer, size, fittingMode, orientationCorrection, atlasUploadObserver);
+  return mTextureSetList.back();
+}
+
+TextureSet ImageAtlasManager::Add(Vector4&  textureRect,
+                                  PixelData pixelData)
+{
+  // big buffer, atlasing is not applied
+  if(static_cast<uint32_t>(pixelData.GetWidth()) * static_cast<uint32_t>(pixelData.GetHeight()) > MAX_ITEM_AREA || pixelData.GetWidth() > DEFAULT_ATLAS_SIZE || pixelData.GetHeight() > DEFAULT_ATLAS_SIZE)
+  {
+    return TextureSet();
+  }
+
+  uint32_t i = 0;
+  for(AtlasContainer::iterator iter = mAtlasList.begin(); iter != mAtlasList.end(); ++iter)
+  {
+    if((*iter).Upload(textureRect, pixelData))
+    {
+      return mTextureSetList[i];
+    }
+    i++;
+  }
+
+  CreateNewAtlas();
+  mAtlasList.back().Upload(textureRect, pixelData);
+  return mTextureSetList.back();
+}
+
+void ImageAtlasManager::Remove(TextureSet textureSet, const Vector4& textureRect)
+{
+  uint32_t i = 0;
+  for(TextureSetContainer::iterator iter = mTextureSetList.begin(); iter != mTextureSetList.end(); ++iter)
+  {
+    if((*iter) == textureSet)
+    {
+      mAtlasList[i].Remove(textureRect);
+      return;
+    }
+    i++;
+  }
+}
+
+void ImageAtlasManager::SetBrokenImage(const std::string& brokenImageUrl)
+{
+  if(!brokenImageUrl.empty())
+  {
+    mBrokenImageUrl = brokenImageUrl;
+  }
+}
+
+void ImageAtlasManager::CreateNewAtlas()
+{
+  Toolkit::ImageAtlas newAtlas = Toolkit::ImageAtlas::New(DEFAULT_ATLAS_SIZE, DEFAULT_ATLAS_SIZE);
+  if(!mBrokenImageUrl.empty())
+  {
+    newAtlas.SetBrokenImage(mBrokenImageUrl);
+  }
+  mAtlasList.push_back(newAtlas);
+  TextureSet textureSet = TextureSet::New();
+  textureSet.SetTexture(0u, newAtlas.GetAtlas());
+  mTextureSetList.push_back(textureSet);
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image/image-atlas-manager.h b/dali-toolkit/internal/visuals/image/image-atlas-manager.h
new file mode 100644 (file)
index 0000000..4d71476
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef DALI_TOOLKIT_IMAGE_ATLAS_MANAGER_H
+#define DALI_TOOLKIT_IMAGE_ATLAS_MANAGER_H
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/rendering/texture-set.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+class AtlasUploadObserver;
+
+namespace Internal
+{
+/**
+ * The manager for automatic image atlasing. Owned by VisualFactory
+ */
+class ImageAtlasManager : public RefObject
+{
+public:
+  typedef std::vector<Toolkit::ImageAtlas> AtlasContainer;
+  typedef std::vector<TextureSet>          TextureSetContainer;
+
+public:
+  /**
+   * Construtor
+   *
+   */
+  ImageAtlasManager();
+
+  /**
+   * @brief Check whether the image of url could be Atlas or not.
+   *
+   * @param [in] url The URL of the resource image file to use.
+   * @param [in] size The width and height to fit the loaded image to.
+   * @return True if the image could be Atlas.
+   */
+  bool CheckAtlasAvailable(const VisualUrl& url, const ImageDimensions& size) const;
+
+  /**
+   * @brief Add an image to the atlas.
+   *
+   * @note To make the atlasing efficient, an valid size should be provided.
+   *       If size is not provided, then the image file will be opened to read the actual size for loading.
+   *
+   * SamplingMode::BOX_THEN_LINEAR is used to sampling pixels from the input image while fitting it to desired size.
+   *
+   * @param [out] textureRect The texture area of the resource image in the atlas.
+   * @param [in] url The URL of the resource image file to use.
+   * @param [in, out] size The width and height to fit the loaded image to.
+   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
+   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
+   * @param [in] atlasUploadObserver The object to observe the uploading state inside ImageAtlas.
+   * @return The texture set containing the image.
+   */
+  TextureSet Add(Vector4&             textureRect,
+                 const VisualUrl&     url,
+                 ImageDimensions&     size,
+                 FittingMode::Type    fittingMode           = FittingMode::DEFAULT,
+                 bool                 orientationCorrection = true,
+                 AtlasUploadObserver* atlasUploadObserver   = NULL);
+
+  /**
+   * @brief Add an image to the atlas.
+   *
+   * @note To make the atlasing efficient, an valid size should be provided.
+   *
+   * SamplingMode::BOX_THEN_LINEAR is used to sampling pixels from the input image while fitting it to desired size.
+   *
+   * @param [out] textureRect The texture area of the resource image in the atlas.
+   * @param [in] encodedImageBuffer The encoded buffer of the resource image file to use.
+   * @param [in] size The width and height to fit the loaded image to.
+   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
+   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
+   * @param [in] atlasUploadObserver The object to observe the uploading state inside ImageAtlas.
+   * @return The texture set containing the image.
+   */
+  TextureSet Add(Vector4&                  textureRect,
+                 const EncodedImageBuffer& encodedImageBuffer,
+                 const ImageDimensions&    size,
+                 FittingMode::Type         fittingMode           = FittingMode::DEFAULT,
+                 bool                      orientationCorrection = true,
+                 AtlasUploadObserver*      atlasUploadObserver   = NULL);
+
+  /**
+   * @brief Add a pixel buffer to the atlas
+   *
+   * @param [out] textureRect The texture area of the resource image in the atlas.
+   * @param [in] pixelData The pixel data.
+   * @return The texture set containing the image.
+   */
+  TextureSet Add(Vector4&  textureRect,
+                 PixelData pixelData);
+
+  /**
+   * Remove the image at the given rectangle from the texture set.
+   *
+   * @param [in] textureSet The texture set containing the atlas image.
+   * @param [in] textureRect The texture area to be removed.
+   */
+  void Remove(TextureSet textureSet, const Vector4& textureRect);
+
+  /**
+   * @brief Set the broken image which is used to replace the image if loading fails.
+   *
+   * @param[in] brokenImageUrl The url of the broken image.
+   */
+  void SetBrokenImage(const std::string& brokenImageUrl);
+
+  /**
+   * @brief Get shader
+   */
+  Shader GetShader() const;
+
+private:
+  /**
+   * @brief Create a new atlas.
+   *
+   * This method is called when the newly added image or pixel buffer cannot fit into the current atlas list.
+   */
+  void CreateNewAtlas();
+
+protected:
+  /**
+   * Destructor
+   */
+  ~ImageAtlasManager() override;
+
+  /**
+   * Undefined copy constructor.
+   */
+  ImageAtlasManager(const ImageAtlasManager&);
+
+  /**
+   * Undefined assignment operator.
+   */
+  ImageAtlasManager& operator=(const ImageAtlasManager& rhs);
+
+private:
+  AtlasContainer      mAtlasList;
+  TextureSetContainer mTextureSetList;
+  std::string         mBrokenImageUrl;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_ATLAS_MANAGER_H
diff --git a/dali-toolkit/internal/visuals/image/image-visual-shader-debug.cpp b/dali-toolkit/internal/visuals/image/image-visual-shader-debug.cpp
new file mode 100644 (file)
index 0000000..1440374
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-debug.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
+#include <dali/devel-api/adaptor-framework/style-monitor.h> ///< for load json file.
+#include <dali/public-api/common/vector-wrapper.h>
+
+#include <regex> ///< for redefine shader
+#include <string_view>
+
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
+#include <dali-toolkit/devel-api/builder/json-parser.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+constexpr auto DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV = "DALI_DEBUG_IMAGE_VISUAL_SHADER";
+
+bool DebugImageVisualShaderEnvironmentEnabled()
+{
+  static bool enabled       = false;
+  static bool enabledSetted = false;
+  if(!enabledSetted)
+  {
+    enabledSetted           = true;
+    auto debugEnabledString = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_ENV);
+    enabled                 = debugEnabledString ? std::atoi(debugEnabledString) : false;
+  }
+  return enabled;
+}
+
+constexpr auto DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV = "DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME";
+constexpr auto DEFAULT_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME  = "debug-image-visual-shader-script.json";
+
+const std::string& GetScriptFilename()
+{
+  // Set the full path for the default script file.
+  const static std::string styleDirPath{AssetManager::GetDaliStylePath()};
+  static std::string       mScriptFileName{};
+
+  if(DALI_UNLIKELY(mScriptFileName.empty()))
+  {
+    // Use user's own script if exist.
+    auto environmentScriptFilename = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME_ENV);
+
+    mScriptFileName = environmentScriptFilename ? std::string(environmentScriptFilename) : styleDirPath + std::string(DEFAULT_DEBUG_IMAGE_VISUAL_SHADER_SCRIPT_FILE_NAME);
+
+    DALI_ASSERT_DEBUG(0 != mScriptFileName.length());
+  }
+
+  return mScriptFileName;
+}
+
+bool LoadJsonScript(std::string& stringOut)
+{
+  auto styleMonitor = StyleMonitor::Get();
+
+  // as toolkit is platform agnostic, it cannot load files from filesystem
+  // ask style monitor to load the style sheet
+  if(styleMonitor)
+  {
+    try
+    {
+      return styleMonitor.LoadThemeFile(GetScriptFilename(), stringOut);
+    }
+    catch(const std::exception& e)
+    {
+      DALI_LOG_ERROR("Something system exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
+      DALI_LOG_ERROR("Error message : [%s]\n", e.what());
+    }
+    catch(const Dali::DaliException& e)
+    {
+      DALI_LOG_ERROR("Something Dali exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
+      DALI_LOG_ERROR("Error message : [%s]\n", e.condition);
+    }
+    catch(...)
+    {
+      DALI_LOG_ERROR("Something unkown exception throwed during load script file![%s]\n", GetScriptFilename().c_str());
+    }
+  }
+
+  return false;
+}
+// Json keywords what we will get information from json.
+constexpr std::string_view DEBUG_SCRIPT_VERSION_JSON_KEY = "version";
+
+constexpr std::string_view DEBUG_EXTRA_ATTRIBUTES_JSON_KEY    = "extraAttributes";
+constexpr std::string_view DEBUG_EXTRA_VARYINGS_JSON_KEY      = "extraVaryings";
+constexpr std::string_view DEBUG_EXTRA_UNIFORMS_JSON_KEY      = "extraUniforms";
+constexpr std::string_view DEBUG_APPLY_VARYINGS_CODE_JSON_KEY = "applyVaryingsCode";
+
+constexpr std::string_view MINIMUM_DEBUG_COLOR_RATE_JSON_KEY = "minimumColorRate";
+constexpr std::string_view MAXIMUM_DEBUG_COLOR_RATE_JSON_KEY = "maximumColorRate";
+
+constexpr std::string_view DEBUG_RED_CHANNEL_CODE_JSON_KEY   = "redChannelCodes";
+constexpr std::string_view DEBUG_GREEN_CHANNEL_CODE_JSON_KEY = "greenChannelCodes";
+constexpr std::string_view DEBUG_BLUE_CHANNEL_CODE_JSON_KEY  = "blueChannelCodes";
+constexpr std::string_view DEBUG_TRIGGER_CODE_JSON_KEY       = "triggerCode";
+constexpr std::string_view DEBUG_RATIO_CODE_JSON_KEY         = "ratioCode";
+
+// Macro keywords what we will replace at vertex/fragment shader.
+constexpr std::string_view DEBUG_EXTRA_ATTRIBUTES_MACRO_KEY    = "DEBUG_EXTRA_ATTRIBUTES";
+constexpr std::string_view DEBUG_EXTRA_VARYINGS_MACRO_KEY      = "DEBUG_EXTRA_VARYINGS";
+constexpr std::string_view DEBUG_EXTRA_UNIFORMS_MACRO_KEY      = "DEBUG_EXTRA_UNIFORMS";
+constexpr std::string_view DEBUG_APPLY_VARYINGS_CODE_MACRO_KEY = "DEBUG_APPLY_VARYING_CODE";
+
+constexpr std::string_view MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY = "MINIMUM_DEBUG_COLOR_RATE";
+constexpr std::string_view MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY = "MAXIMUM_DEBUG_COLOR_RATE";
+
+constexpr std::string_view DEBUG_TRIGGER_RED_CODE_MACRO_KEY   = "DEBUG_TRIGGER_RED_CODE";
+constexpr std::string_view DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY = "DEBUG_TRIGGER_GREEN_CODE";
+constexpr std::string_view DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY  = "DEBUG_TRIGGER_BLUE_CODE";
+constexpr std::string_view DEBUG_RATIO_RED_CODE_MACRO_KEY     = "DEBUG_RATIO_RED_CODE";
+constexpr std::string_view DEBUG_RATIO_GREEN_CODE_MACRO_KEY   = "DEBUG_RATIO_GREEN_CODE";
+constexpr std::string_view DEBUG_RATIO_BLUE_CODE_MACRO_KEY    = "DEBUG_RATIO_BLUE_CODE";
+
+// Default macro keywords when we fail to parse script.
+constexpr std::string_view DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE          = "0.0";
+constexpr std::string_view DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE        = "return false;";
+constexpr std::string_view DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE          = "return 0.0;";
+constexpr std::string_view DEFAULT_DEBUG_APPLY_VARYINGS_CODE_MACRO_VALUE = "return;";
+
+constexpr std::string_view EMPTY_STRING                    = "";
+constexpr std::string_view VERTEX_SHADER_ATTRIBUTES_PREFIX = "INPUT";
+constexpr std::string_view VERTEX_SHADER_VARYINGS_PREFIX   = "OUTPUT";
+constexpr std::string_view FRAGMENT_SHADER_VARYINGS_PREFIX = "INPUT";
+constexpr std::string_view UNIFORMS_PREFIX                 = "uniform";
+
+bool ParseScriptInfomation(Property::Map& vertexResult, Property::Map& fragmentResult)
+{
+  std::string stringOut;
+  if(!LoadJsonScript(stringOut))
+  {
+    DALI_LOG_ERROR("Fail to load script file [%s]\n", GetScriptFilename().c_str());
+    return false;
+  }
+
+  Toolkit::JsonParser parser = Toolkit::JsonParser::New();
+
+  if(!parser.Parse(stringOut))
+  {
+    std::ostringstream stream;
+    if(parser.ParseError())
+    {
+      stream << "position: " << parser.GetErrorPosition() << ", line: " << parser.GetErrorLineNumber() << ", column: " << parser.GetErrorColumn() << ", description: " << parser.GetErrorDescription() << ".";
+    }
+    DALI_LOG_ERROR("Fail to parse json script\nError : %s\nJson : %s\n", stream.str().c_str(), stringOut.c_str());
+    return false;
+  }
+
+  const auto* rootNode = parser.GetRoot();
+  if(!rootNode)
+  {
+    DALI_LOG_ERROR("Fail to get root node\n");
+    return false;
+  }
+
+  auto InsertScriptMap = [](Property::Map& result, const TreeNode* node, const std::string_view& jsonKey, const std::string_view& macroKey, const std::string_view& defaultValue, const std::string_view& prefixString) {
+    std::ostringstream oss;
+    oss.clear();
+
+    if(node)
+    {
+      const auto* childNode = node->GetChild(jsonKey);
+
+      if(childNode)
+      {
+        if(childNode->GetType() == TreeNode::FLOAT)
+        {
+          oss << childNode->GetFloat();
+        }
+        else if(childNode->GetType() == TreeNode::STRING)
+        {
+          if(!prefixString.empty())
+          {
+            oss << prefixString << " ";
+          }
+          oss << childNode->GetString();
+        }
+        else if(childNode->GetType() == TreeNode::ARRAY)
+        {
+          // Concat strings with line feed
+          bool isFirst = true;
+          for(auto iter = childNode->CBegin(), endIter = childNode->CEnd(); iter != endIter; ++iter)
+          {
+            if((*iter).second.GetType() == TreeNode::STRING)
+            {
+              if(isFirst)
+              {
+                isFirst = false;
+              }
+              else
+              {
+                oss << "\n";
+              }
+              if(!prefixString.empty())
+              {
+                oss << prefixString << " ";
+              }
+              oss << (*iter).second.GetString();
+            }
+          }
+        }
+      }
+    }
+
+    if(oss.str().empty() && !defaultValue.empty())
+    {
+      oss << defaultValue;
+    }
+
+    if(!oss.str().empty())
+    {
+      result.Insert(std::string(macroKey), oss.str());
+    }
+  };
+
+  auto InsertChannelScriptMap = [&InsertScriptMap](Property::Map& result, const TreeNode* node, const std::string_view& channelJsonKey, const std::string_view& triggerMacroKey, const std::string_view& ratioMacroKey) {
+    const auto* channelNode = node->GetChild(channelJsonKey);
+    InsertScriptMap(result, channelNode, DEBUG_TRIGGER_CODE_JSON_KEY, triggerMacroKey, DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE, EMPTY_STRING);
+    InsertScriptMap(result, channelNode, DEBUG_RATIO_CODE_JSON_KEY, ratioMacroKey, DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE, EMPTY_STRING);
+  };
+
+  // Get attribute value code
+  InsertScriptMap(vertexResult, rootNode, DEBUG_EXTRA_ATTRIBUTES_JSON_KEY, DEBUG_EXTRA_ATTRIBUTES_MACRO_KEY, EMPTY_STRING, VERTEX_SHADER_ATTRIBUTES_PREFIX);
+
+  // Get varying value code
+  InsertScriptMap(vertexResult, rootNode, DEBUG_EXTRA_VARYINGS_JSON_KEY, DEBUG_EXTRA_VARYINGS_MACRO_KEY, EMPTY_STRING, VERTEX_SHADER_VARYINGS_PREFIX);
+  InsertScriptMap(fragmentResult, rootNode, DEBUG_EXTRA_VARYINGS_JSON_KEY, DEBUG_EXTRA_VARYINGS_MACRO_KEY, EMPTY_STRING, FRAGMENT_SHADER_VARYINGS_PREFIX);
+
+  // Get uniform value code
+  InsertScriptMap(vertexResult, rootNode, DEBUG_EXTRA_UNIFORMS_JSON_KEY, DEBUG_EXTRA_UNIFORMS_MACRO_KEY, EMPTY_STRING, UNIFORMS_PREFIX);
+  InsertScriptMap(fragmentResult, rootNode, DEBUG_EXTRA_UNIFORMS_JSON_KEY, DEBUG_EXTRA_UNIFORMS_MACRO_KEY, EMPTY_STRING, UNIFORMS_PREFIX);
+
+  // Get apply varying code
+  InsertScriptMap(vertexResult, rootNode, DEBUG_APPLY_VARYINGS_CODE_JSON_KEY, DEBUG_APPLY_VARYINGS_CODE_MACRO_KEY, DEFAULT_DEBUG_APPLY_VARYINGS_CODE_MACRO_VALUE, EMPTY_STRING);
+
+  // Get color rate
+  InsertScriptMap(fragmentResult, rootNode, MINIMUM_DEBUG_COLOR_RATE_JSON_KEY, MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY, DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE, EMPTY_STRING);
+  InsertScriptMap(fragmentResult, rootNode, MAXIMUM_DEBUG_COLOR_RATE_JSON_KEY, MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY, DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE, EMPTY_STRING);
+
+  // Get each color ChannelCodes
+  InsertChannelScriptMap(fragmentResult, rootNode, DEBUG_RED_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_RED_CODE_MACRO_KEY, DEBUG_RATIO_RED_CODE_MACRO_KEY);
+  InsertChannelScriptMap(fragmentResult, rootNode, DEBUG_GREEN_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY, DEBUG_RATIO_GREEN_CODE_MACRO_KEY);
+  InsertChannelScriptMap(fragmentResult, rootNode, DEBUG_BLUE_CHANNEL_CODE_JSON_KEY, DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY, DEBUG_RATIO_BLUE_CODE_MACRO_KEY);
+
+  return true;
+}
+
+const std::vector<Property::Map>& GetScriptInfomation()
+{
+  static std::vector<Property::Map> results;
+
+  if(DALI_UNLIKELY(results.empty()))
+  {
+    results.resize(2);
+
+    auto& vertexShaderResult   = results[0];
+    auto& fragmentShaderResult = results[1];
+
+    if(!ParseScriptInfomation(vertexShaderResult, fragmentShaderResult))
+    {
+      // Use default script information if parse failed.
+      vertexShaderResult.Clear();
+      fragmentShaderResult.Clear();
+
+      vertexShaderResult.Insert(std::string(DEBUG_APPLY_VARYINGS_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_APPLY_VARYINGS_CODE_MACRO_VALUE));
+
+      fragmentShaderResult.Insert(std::string(MINIMUM_DEBUG_COLOR_RATE_MACRO_KEY), std::string(DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE));
+      fragmentShaderResult.Insert(std::string(MAXIMUM_DEBUG_COLOR_RATE_MACRO_KEY), std::string(DEFAULT_DEBUG_COLOR_RATE_MACRO_VALUE));
+      fragmentShaderResult.Insert(std::string(DEBUG_TRIGGER_RED_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
+      fragmentShaderResult.Insert(std::string(DEBUG_TRIGGER_GREEN_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
+      fragmentShaderResult.Insert(std::string(DEBUG_TRIGGER_BLUE_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_TRIGGER_CODE_MACRO_VALUE));
+      fragmentShaderResult.Insert(std::string(DEBUG_RATIO_RED_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
+      fragmentShaderResult.Insert(std::string(DEBUG_RATIO_GREEN_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
+      fragmentShaderResult.Insert(std::string(DEBUG_RATIO_BLUE_CODE_MACRO_KEY), std::string(DEFAULT_DEBUG_RATIO_CODE_MACRO_VALUE));
+    }
+  }
+
+  return results;
+}
+
+void RedefineMacro(std::string& shaderCode, std::string macro, std::string value)
+{
+  std::string definition = "#define " + macro;
+  std::size_t found      = shaderCode.find(definition);
+  DALI_ASSERT_ALWAYS(found != std::string::npos && "Macro keyword was not exist in shader code!");
+
+  std::size_t insertionPoint = found + definition.length();
+
+  // Automatically insert line-continuation character into value
+  std::regex                 re("\n");
+  std::sregex_token_iterator first{value.begin(), value.end(), re, -1}, last;
+  for(auto i = first; i != last; ++i)
+  {
+    std::string line = std::string(" \\\n") + (*i).str();
+    shaderCode.insert(insertionPoint, line);
+    insertionPoint += line.length();
+  }
+}
+
+} // namespace
+
+namespace ImageVisualShaderDebug
+{
+bool DebugImageVisualShaderEnabled()
+{
+  return DebugImageVisualShaderEnvironmentEnabled();
+}
+
+void ApplyImageVisualShaderDebugScriptCode(std::string& vertexShader, std::string& fragmentShader)
+{
+  const auto& resultMaps = GetScriptInfomation();
+
+  for(std::size_t i = 0u; i < resultMaps[0].Count(); ++i)
+  {
+    auto        key   = resultMaps[0].GetKeyAt(i);
+    const auto& value = resultMaps[0].GetValue(i);
+
+    RedefineMacro(vertexShader, std::move(key.stringKey), value.Get<std::string>());
+  }
+
+  for(std::size_t i = 0u; i < resultMaps[1].Count(); ++i)
+  {
+    auto        key   = resultMaps[1].GetKeyAt(i);
+    const auto& value = resultMaps[1].GetValue(i);
+
+    RedefineMacro(fragmentShader, std::move(key.stringKey), value.Get<std::string>());
+  }
+}
+} // namespace ImageVisualShaderDebug
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image/image-visual-shader-debug.h b/dali-toolkit/internal/visuals/image/image-visual-shader-debug.h
new file mode 100644 (file)
index 0000000..aff6130
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
+#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace ImageVisualShaderDebug
+{
+/**
+ * @brief Check whether we need to use debug option for image visual.
+ *
+ * @return True if ImageVisualShader relative environment on. False otherwise.
+ */
+bool DebugImageVisualShaderEnabled();
+
+/**
+ * @brief Apply vertex / fragment shader use debug script.
+ *
+ * @param[in, out] vertexShader Vertex shader code to apply debug script.
+ * @param[in, out] fragmentShader Fragment shader code to apply debug script.
+ */
+void ApplyImageVisualShaderDebugScriptCode(std::string& vertexShader, std::string& fragmentShader);
+
+} // namespace ImageVisualShaderDebug
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_IMAGE_VISUAL_SHADER_DEBUG_H
diff --git a/dali-toolkit/internal/visuals/image/image-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/image/image-visual-shader-factory.cpp
new file mode 100644 (file)
index 0000000..77ea3c0
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/rendering/texture-devel.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-debug.h>
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
+
+constexpr int              NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMAGE_SHADER - VisualFactoryCache::ShaderType::IMAGE_SHADER;
+constexpr std::string_view Y_FLIP_MASK_TEXTURE       = "uYFlipMaskTexture";
+constexpr float            NOT_FLIP_MASK_TEXTURE     = 0.0f;
+
+constexpr auto SHADER_TYPE_COUNT = 6u;
+
+constexpr std::string_view VertexPredefines[SHADER_TYPE_COUNT]{
+  "",                                     // VisualFactoryCache::IMAGE_SHADER,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+  "",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+  "",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+};
+constexpr std::string_view FragmentPredefines[SHADER_TYPE_COUNT]{
+  "",                                                                              // VisualFactoryCache::IMAGE_SHADER,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n",                                          // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+  "#define IS_REQUIRED_YUV_TO_RGB\n",                                              // VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_YUV_TO_RGB\n",          // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+  "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n",                                     // VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
+  "#define IS_REQUIRED_ROUNDED_CORNER\n#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n", // VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+};
+constexpr VisualFactoryCache::ShaderType ShaderTypePredefines[SHADER_TYPE_COUNT]{
+  VisualFactoryCache::ShaderType::IMAGE_SHADER,
+  VisualFactoryCache::ShaderType::IMAGE_SHADER_ROUNDED_CORNER,
+  VisualFactoryCache::ShaderType::IMAGE_SHADER_YUV_TO_RGB,
+  VisualFactoryCache::ShaderType::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+  VisualFactoryCache::ShaderType::IMAGE_SHADER_YUV_AND_RGB,
+  VisualFactoryCache::ShaderType::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+};
+} // unnamed namespace
+
+ImageVisualShaderFactory::ImageVisualShaderFactory()
+: mFragmentShaderNeedChange(ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED)
+{
+}
+
+ImageVisualShaderFactory::~ImageVisualShaderFactory()
+{
+}
+
+Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, ImageVisualShaderFeatureBuilder& featureBuilder)
+{
+  Shader                         shader;
+  VisualFactoryCache::ShaderType shaderType = featureBuilder.GetShaderType();
+
+  if(featureBuilder.NeedToChangeFragmentShader() == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE &&
+     (mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED ||
+      mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE))
+  {
+    DALI_ASSERT_DEBUG((static_cast<int>(shaderType) >= static_cast<int>(VisualFactoryCache::IMAGE_SHADER)) &&
+                      (static_cast<int>(shaderType) <= static_cast<int>(VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP)) &&
+                      "Do not support native image shader for given feature!!");
+    shaderType = static_cast<VisualFactoryCache::ShaderType>(static_cast<int>(shaderType) + NATIVE_SHADER_TYPE_OFFSET);
+  }
+
+  shader = factoryCache.GetShader(shaderType);
+  if(shader)
+  {
+    return shader;
+  }
+
+  std::string vertexShaderPrefixList;
+  std::string fragmentShaderPrefixList;
+  featureBuilder.GetVertexShaderPrefixList(vertexShaderPrefixList);
+  featureBuilder.GetFragmentShaderPrefixList(fragmentShaderPrefixList);
+
+  if(Dali::Toolkit::Internal::ImageVisualShaderDebug::DebugImageVisualShaderEnabled())
+  {
+    vertexShaderPrefixList += "#define IS_REQUIRED_DEBUG_VISUAL_SHADER\n";
+    fragmentShaderPrefixList += "#define IS_REQUIRED_DEBUG_VISUAL_SHADER\n";
+  }
+
+  std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_VERT.data());
+  std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_FRAG.data());
+
+  if(Dali::Toolkit::Internal::ImageVisualShaderDebug::DebugImageVisualShaderEnabled())
+  {
+    Dali::Toolkit::Internal::ImageVisualShaderDebug::ApplyImageVisualShaderDebugScriptCode(vertexShader, fragmentShader);
+  }
+
+  if(featureBuilder.NeedToChangeFragmentShader() == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE)
+  {
+    bool modified = DevelTexture::ApplyNativeFragmentShader(featureBuilder.GetTexture(), fragmentShader);
+    if(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE)
+    {
+      DALI_ASSERT_ALWAYS(modified && "NativeImageTexture need to change fragment shader. But DALI default image shader doesn't changed!");
+    }
+    else if(DALI_UNLIKELY(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::UNDECIDED))
+    {
+      mFragmentShaderNeedChange = (modified) ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
+
+      if(mFragmentShaderNeedChange == ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE)
+      {
+        shaderType = static_cast<VisualFactoryCache::ShaderType>(static_cast<int>(shaderType) - NATIVE_SHADER_TYPE_OFFSET);
+        shader     = factoryCache.GetShader(shaderType);
+      }
+    }
+  }
+
+  if(shader)
+  {
+    return shader;
+  }
+
+  shader = factoryCache.GenerateAndSaveShader(shaderType, vertexShader, fragmentShader);
+  shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
+  if(featureBuilder.IsEnabledAlphaMaskingOnRendering())
+  {
+    shader.RegisterProperty(Y_FLIP_MASK_TEXTURE, NOT_FLIP_MASK_TEXTURE);
+  }
+
+  return shader;
+}
+
+std::string_view ImageVisualShaderFactory::GetVertexShaderSource()
+{
+  // static string variable to cache complete vertex shader
+  static std::string gVertexShader;
+  if(gVertexShader.empty())
+  {
+    gVertexShader = Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data();
+  }
+
+  return gVertexShader;
+}
+
+std::string_view ImageVisualShaderFactory::GetFragmentShaderSource()
+{
+  // static string variable to cache complete fragment shader (no atlas)
+  static std::string gFragmentShaderNoAtlas;
+  if(gFragmentShaderNoAtlas.empty())
+  {
+    gFragmentShaderNoAtlas = Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_FRAG.data();
+  }
+  return gFragmentShaderNoAtlas;
+}
+
+void ImageVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
+{
+  std::vector<std::string_view> vertexPrefix;
+  std::vector<std::string_view> fragmentPrefix;
+  std::vector<std::string_view> shaderName;
+  shaders.shaderCount = 0;
+  int shaderCount     = 0;
+  for(uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i)
+  {
+    vertexPrefix.push_back(VertexPredefines[i]);
+    fragmentPrefix.push_back(FragmentPredefines[i]);
+    shaderName.push_back(Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(ShaderTypePredefines[i], VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+    shaderCount++;
+  }
+
+  shaders.vertexPrefix   = vertexPrefix;
+  shaders.fragmentPrefix = fragmentPrefix;
+  shaders.shaderName     = shaderName;
+  shaders.vertexShader   = SHADER_IMAGE_VISUAL_SHADER_VERT;
+  shaders.fragmentShader = SHADER_IMAGE_VISUAL_SHADER_FRAG;
+  shaders.shaderCount    = shaderCount;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image/image-visual-shader-factory.h b/dali-toolkit/internal/visuals/image/image-visual-shader-factory.h
new file mode 100644 (file)
index 0000000..21f6ec3
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
+#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/shader-precompiler.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
+#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+#include <string_view>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * ImageVisualShaderFactory is an object that provides and shares shaders between image visuals
+ */
+class ImageVisualShaderFactory
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  ImageVisualShaderFactory();
+
+  /**
+   * @brief Destructor
+   */
+  ~ImageVisualShaderFactory();
+
+  /**
+   * @brief Get the standard image rendering shader.
+   * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] featureBuilder Collection of current image shader's features
+   * @return The standard image rendering shader with features.
+   */
+  Shader GetShader(VisualFactoryCache& factoryCache, ImageVisualShaderFeatureBuilder& featureBuilder);
+
+  /**
+   * @brief Request the default vertex shader source.
+   * @return The default vertex shader source.
+   */
+  std::string_view GetVertexShaderSource();
+
+  /**
+   * @brief Request the default fragment shader source.
+   * @return The default fragment shader source.
+   */
+  std::string_view GetFragmentShaderSource();
+
+  /**
+   * @brief Get the default shader source.
+   * @param[in] shaders shaderList for precompile
+   */
+  void GetPreCompiledShader(RawShaderData& shaders);
+
+protected:
+  /**
+   * Undefined copy constructor.
+   */
+  ImageVisualShaderFactory(const ImageVisualShaderFactory&);
+
+  /**
+   * Undefined assignment operator.
+   */
+  ImageVisualShaderFactory& operator=(const ImageVisualShaderFactory& rhs);
+
+private:
+  /**
+   * @brief Cached information whether native image should change fragment shader.
+   * Default it is ChangeFragmentShader::UNDECIDED.
+   * If we have any chance to check native image source apply fragment shader,
+   * this vaule will be changed one of these : ChangeFragmentShader::DONT_CHANGE or ChangeFragmentShader::NEED_CHANGE
+   *
+   * After result cached, this value will not be changed.
+   *
+   * If value is DONT_CHANGE, ImageVisualShaderFactory::GetShader never call ApplyNativeFragmentShader.
+   * Else, ImageVisualShaderFactory::GetShader will call ApplyNativeFragmentShader if native image source texture come.
+   */
+  ImageVisualShaderFeature::ChangeFragmentShader::Type mFragmentShaderNeedChange : 3;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
diff --git a/dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.cpp b/dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.cpp
new file mode 100644 (file)
index 0000000..7945470
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+// enum of required list when we select shader
+enum class ImageVisualRequireFlag : uint32_t
+{
+  DEFAULT          = 0,
+  ROUNDED_CORNER   = 1 << 0,
+  BORDERLINE       = 1 << 1,
+  ALPHA_MASKING    = 1 << 2,
+  COLOR_CONVERSION = 1 << 3,
+
+  UNIFIED_YUV_AND_RGB = 1 << 2, // Special enum to trick unified YUV and RGB.
+};
+
+static constexpr auto          SHADER_TYPE_COUNT = 16u;
+VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[SHADER_TYPE_COUNT] =
+  {
+    VisualFactoryCache::IMAGE_SHADER,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER,
+    VisualFactoryCache::IMAGE_SHADER_BORDERLINE,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE,
+    VisualFactoryCache::IMAGE_SHADER_MASKING,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_MASKING,
+    VisualFactoryCache::IMAGE_SHADER_BORDERLINE_MASKING,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
+    VisualFactoryCache::IMAGE_SHADER_YUV_TO_RGB,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_TO_RGB,
+    VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_TO_RGB,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_TO_RGB,
+    VisualFactoryCache::IMAGE_SHADER_YUV_AND_RGB,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER_YUV_AND_RGB,
+    VisualFactoryCache::IMAGE_SHADER_BORDERLINE_YUV_AND_RGB,
+    VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE_YUV_AND_RGB};
+} // unnamed namespace
+
+ImageVisualShaderFeatureBuilder::ImageVisualShaderFeatureBuilder()
+: mTextureAtlas(ImageVisualShaderFeature::TextureAtlas::DISABLED),
+  mDefaultTextureWrapMode(ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY),
+  mRoundedCorner(ImageVisualShaderFeature::RoundedCorner::DISABLED),
+  mBorderline(ImageVisualShaderFeature::Borderline::DISABLED),
+  mAlphaMaskingOnRendering(ImageVisualShaderFeature::AlphaMaskingOnRendering::DISABLED),
+  mColorConversion(ImageVisualShaderFeature::ColorConversion::DONT_NEED),
+  mTexture()
+{
+}
+
+ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableTextureAtlas(bool enableTextureAtlas)
+{
+  mTextureAtlas = (enableTextureAtlas ? ImageVisualShaderFeature::TextureAtlas::ENABLED : ImageVisualShaderFeature::TextureAtlas::DISABLED);
+  return *this;
+}
+
+ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode)
+{
+  mDefaultTextureWrapMode = (applyDefaultTextureWrapMode ? ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY : ImageVisualShaderFeature::DefaultTextureWrapMode::DO_NOT_APPLY);
+  return *this;
+}
+
+ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableRoundedCorner(bool enableRoundedCorner)
+{
+  mRoundedCorner = (enableRoundedCorner ? ImageVisualShaderFeature::RoundedCorner::ENABLED : ImageVisualShaderFeature::RoundedCorner::DISABLED);
+  return *this;
+}
+
+ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableBorderline(bool enableBorderline)
+{
+  mBorderline = (enableBorderline ? ImageVisualShaderFeature::Borderline::ENABLED : ImageVisualShaderFeature::Borderline::DISABLED);
+  return *this;
+}
+
+ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::SetTextureForFragmentShaderCheck(const Dali::Texture& texture)
+{
+  mTexture = texture;
+  return *this;
+}
+
+ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering)
+{
+  mAlphaMaskingOnRendering = (enableAlphaMaskingOnRendering ? ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED : ImageVisualShaderFeature::AlphaMaskingOnRendering::DISABLED);
+  return *this;
+}
+
+ImageVisualShaderFeatureBuilder& ImageVisualShaderFeatureBuilder::EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb)
+{
+  mColorConversion = (enableUnifiedYuvAndRgb ? ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB : (enableYuvToRgb ? ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB : ImageVisualShaderFeature::ColorConversion::DONT_NEED));
+  return *this;
+}
+
+VisualFactoryCache::ShaderType ImageVisualShaderFeatureBuilder::GetShaderType()
+{
+  VisualFactoryCache::ShaderType shaderType = VisualFactoryCache::IMAGE_SHADER;
+  if(mTextureAtlas == ImageVisualShaderFeature::TextureAtlas::ENABLED)
+  {
+    if(mDefaultTextureWrapMode == ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY)
+    {
+      shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP;
+    }
+    else
+    {
+      shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP;
+    }
+  }
+  else
+  {
+    uint32_t shaderTypeFlag = static_cast<uint32_t>(ImageVisualRequireFlag::DEFAULT);
+    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
+    {
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ROUNDED_CORNER);
+    }
+    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
+    {
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::BORDERLINE);
+    }
+    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
+    {
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::ALPHA_MASKING);
+    }
+    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB) // Not support gpu masking and color conversion at the same time now
+    {
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
+    }
+    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB)
+    {
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::COLOR_CONVERSION);
+      shaderTypeFlag |= static_cast<uint32_t>(ImageVisualRequireFlag::UNIFIED_YUV_AND_RGB);
+    }
+    shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
+  }
+
+  return shaderType;
+}
+
+ImageVisualShaderFeature::ChangeFragmentShader::Type ImageVisualShaderFeatureBuilder::NeedToChangeFragmentShader()
+{
+  return (mTexture && DevelTexture::IsNative(mTexture))
+           ? ImageVisualShaderFeature::ChangeFragmentShader::NEED_CHANGE
+           : ImageVisualShaderFeature::ChangeFragmentShader::DONT_CHANGE;
+}
+
+void ImageVisualShaderFeatureBuilder::GetVertexShaderPrefixList(std::string& vertexShaderPrefixList)
+{
+  if(mTextureAtlas != ImageVisualShaderFeature::TextureAtlas::ENABLED)
+  {
+    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
+    {
+      vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER\n";
+    }
+    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
+    {
+      vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE\n";
+    }
+    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
+    {
+      vertexShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
+    }
+  }
+}
+
+void ImageVisualShaderFeatureBuilder::GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList)
+{
+  if(mTextureAtlas == ImageVisualShaderFeature::TextureAtlas::ENABLED)
+  {
+    if(mDefaultTextureWrapMode == ImageVisualShaderFeature::DefaultTextureWrapMode::APPLY)
+    {
+      fragmentShaderPrefixList += "#define ATLAS_DEFAULT_WARP\n";
+    }
+    else
+    {
+      fragmentShaderPrefixList += "#define ATLAS_CUSTOM_WARP\n";
+    }
+  }
+  else
+  {
+    if(mRoundedCorner == ImageVisualShaderFeature::RoundedCorner::ENABLED)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER\n";
+    }
+    if(mBorderline == ImageVisualShaderFeature::Borderline::ENABLED)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE\n";
+    }
+    if(mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_ALPHA_MASKING\n";
+    }
+    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::YUV_TO_RGB)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_YUV_TO_RGB\n";
+    }
+    else if(mColorConversion == ImageVisualShaderFeature::ColorConversion::UNIFIED_YUV_AND_RGB)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_UNIFIED_YUV_AND_RGB\n";
+    }
+  }
+}
+
+Dali::Texture ImageVisualShaderFeatureBuilder::GetTexture()
+{
+  return mTexture;
+}
+
+bool ImageVisualShaderFeatureBuilder::IsEnabledAlphaMaskingOnRendering() const
+{
+  return mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h b/dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h
new file mode 100644 (file)
index 0000000..635a06c
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FEATURE_BUILDER_H
+#define DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FEATURE_BUILDER_H
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+#include <dali/devel-api/rendering/texture-devel.h>
+#include <dali/public-api/rendering/texture.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * ImageVisualShaderFeature contains feature lists what image visual shader need to know.
+ */
+namespace ImageVisualShaderFeature
+{
+namespace TextureAtlas
+{
+/**
+ * @brief Whether use texture with atlas, or not
+ */
+enum Type
+{
+  DISABLED = 0, ///< Image visual doesn't use ATLAS
+  ENABLED       ///< Image visual uses ATLAS
+};
+} // namespace TextureAtlas
+
+namespace DefaultTextureWrapMode
+{
+/**
+ * @brief Whether apply to texture wraping in default, or not
+ */
+enum Type
+{
+  APPLY = 0,   ///< Image visual applies to wraping texture in default
+  DO_NOT_APPLY ///< Image visual doesn't apply to wraping texture in default
+};
+} // namespace DefaultTextureWrapMode
+
+namespace RoundedCorner
+{
+/**
+ * @brief Whether use rounded corner, or not
+ */
+enum Type
+{
+  DISABLED = 0, ///< Image visual doesn't use rounded corner
+  ENABLED       ///< Image visual uses rounded corner
+};
+} // namespace RoundedCorner
+
+namespace Borderline
+{
+/**
+ * @brief Whether use borderline, or not
+ */
+enum Type
+{
+  DISABLED = 0, ///< Image visual doesn't use borderline
+  ENABLED       ///< Image visual uses borderline
+};
+} // namespace Borderline
+
+namespace ChangeFragmentShader
+{
+/**
+ * @brief Whether native image change the default fragment shader, or not
+ */
+enum Type
+{
+  DONT_CHANGE = 0, ///< Native image doesn't change default fragment shader.
+  NEED_CHANGE,     ///< Native image changes default fragment shader. We need another shader cache.
+  UNDECIDED,       ///< Undecided.
+};
+} // namespace ChangeFragmentShader
+
+namespace AlphaMaskingOnRendering
+{
+/**
+ * @brief Whether use runtime alpha masking in shader, or not
+ */
+enum Type
+{
+  DISABLED = 0, ///< Image visual doesn't use runtime alpha masking
+  ENABLED       ///< Image visual uses runtime alpha masking
+};
+} // namespace AlphaMaskingOnRendering
+
+namespace ColorConversion
+{
+/**
+ * @brief Whether the color format conversion is needed or not
+ */
+enum Type
+{
+  DONT_NEED = 0,      ///< Not need to convert
+  YUV_TO_RGB,         ///< Need yuv to rgb conversion
+  UNIFIED_YUV_AND_RGB ///< Need to support both yuv conversion case and normal case.
+};
+} // namespace ColorConversion
+
+} // namespace ImageVisualShaderFeature
+
+/**
+ * @brief Collection of current image visual feature. Only use for ImageVisualShaderFactory::GetShader()
+ */
+class ImageVisualShaderFeatureBuilder
+{
+public:
+  ImageVisualShaderFeatureBuilder();
+
+  ImageVisualShaderFeatureBuilder& EnableTextureAtlas(bool enableTextureAtlas);
+
+  ImageVisualShaderFeatureBuilder& ApplyDefaultTextureWrapMode(bool applyDefaultTextureWrapMode);
+
+  ImageVisualShaderFeatureBuilder& EnableRoundedCorner(bool enableRoundedCorner);
+
+  ImageVisualShaderFeatureBuilder& EnableBorderline(bool enableBorderline);
+
+  ImageVisualShaderFeatureBuilder& SetTextureForFragmentShaderCheck(const Dali::Texture& texture);
+
+  ImageVisualShaderFeatureBuilder& EnableAlphaMaskingOnRendering(bool enableAlphaMaskingOnRendering);
+
+  ImageVisualShaderFeatureBuilder& EnableYuvToRgb(bool enableYuvToRgb, bool enableUnifiedYuvAndRgb = false);
+
+  VisualFactoryCache::ShaderType GetShaderType();
+
+  ImageVisualShaderFeature::ChangeFragmentShader::Type NeedToChangeFragmentShader();
+
+  void GetVertexShaderPrefixList(std::string& vertexShaderPrefixList);
+  void GetFragmentShaderPrefixList(std::string& fragmentShaderPrefixList);
+
+  Dali::Texture GetTexture();
+
+  bool IsEnabledAlphaMaskingOnRendering() const;
+
+private:
+  ImageVisualShaderFeature::TextureAtlas::Type            mTextureAtlas : 2;            ///< Whether use texture with atlas, or not. default as TextureAtlas::DISABLED
+  ImageVisualShaderFeature::DefaultTextureWrapMode::Type  mDefaultTextureWrapMode : 2;  ///< Whether apply to texture wraping in default, or not. default as DefaultTextureWrapMode::APPLY
+  ImageVisualShaderFeature::RoundedCorner::Type           mRoundedCorner : 2;           ///< Whether use rounded corner, or not. default as RoundedCorner::DISABLED
+  ImageVisualShaderFeature::Borderline::Type              mBorderline : 2;              ///< Whether use borderline, or not. default as Borderline::DISABLED
+  ImageVisualShaderFeature::AlphaMaskingOnRendering::Type mAlphaMaskingOnRendering : 2; ///< Whether use runtime alpha masking, or not. default as AlphaMaskingOnRendering::DISABLED
+  ImageVisualShaderFeature::ColorConversion::Type         mColorConversion : 2;         ///< Whether the color format conversion is needed or not
+  Dali::Texture                                           mTexture;                     ///< Texture to check whether we need to change fragment shader or not
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_IMAGE_VISUAL_SHADER_FACTORY_H
index 65af749c00ddaa1c9d53e2e9536c0c5a9fde08da..4ebb5e4b9bc315be7ca9a8f4c9a4aa59df622de2 100644 (file)
@@ -34,9 +34,9 @@
 // INTERNAL HEADERS
 #include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.h>
 #include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
diff --git a/dali-toolkit/internal/visuals/npatch-data.cpp b/dali-toolkit/internal/visuals/npatch-data.cpp
deleted file mode 100644 (file)
index 28c3ebd..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/visuals/npatch-data.h>
-
-// INTERNAL HEADERS
-#include <dali-toolkit/internal/visuals/rendering-addon.h>
-
-// EXTERNAL HEADERS
-#include <dali/integration-api/debug.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-NPatchData::NPatchData()
-: mId(INVALID_NPATCH_DATA_ID),
-  mUrl(),
-  mTextureSet(),
-  mHash(0),
-  mCroppedWidth(0),
-  mCroppedHeight(0),
-  mBorder(0, 0, 0, 0),
-  mLoadingState(LoadingState::NOT_STARTED),
-  mRenderingMap{nullptr},
-  mPreMultiplyOnLoad(false),
-  mObserverNotifying(false)
-{
-}
-
-NPatchData::~NPatchData()
-{
-  // If there is an opacity map, it has to be destroyed using addon call
-  if(mRenderingMap)
-  {
-    RenderingAddOn::Get().DestroyNPatch(mRenderingMap);
-  }
-  mObserverList.Clear();
-  mQueuedObservers.Clear();
-}
-
-void NPatchData::SetId(const NPatchDataId id)
-{
-  mId = id;
-}
-
-NPatchData::NPatchDataId NPatchData::GetId() const
-{
-  return mId;
-}
-
-void NPatchData::AddObserver(TextureUploadObserver* textureObserver)
-{
-  if(textureObserver)
-  {
-    if(mObserverNotifying)
-    {
-      // Do not add it into observer list during observer notifying.
-      mQueuedObservers.PushBack(textureObserver);
-    }
-    else
-    {
-      mObserverList.PushBack(textureObserver);
-    }
-    textureObserver->DestructionSignal().Connect(this, &NPatchData::ObserverDestroyed);
-  }
-}
-
-void NPatchData::RemoveObserver(TextureUploadObserver* textureObserver)
-{
-  if(textureObserver)
-  {
-    for(uint32_t index = 0; index < mObserverList.Count(); ++index)
-    {
-      if(textureObserver == mObserverList[index])
-      {
-        textureObserver->DestructionSignal().Disconnect(this, &NPatchData::ObserverDestroyed);
-        mObserverList.Erase(mObserverList.begin() + index);
-        break;
-      }
-    }
-  }
-}
-
-uint32_t NPatchData::GetObserverCount() const
-{
-  return mObserverList.Count();
-}
-
-void NPatchData::SetUrl(const VisualUrl& url)
-{
-  mUrl = url;
-}
-
-VisualUrl NPatchData::GetUrl() const
-{
-  return mUrl;
-}
-
-void NPatchData::SetTextures(const TextureSet textureSet)
-{
-  mTextureSet = textureSet;
-}
-
-TextureSet NPatchData::GetTextures() const
-{
-  return mTextureSet;
-}
-
-void NPatchData::SetStretchPixelsX(const NPatchUtility::StretchRanges stretchPixelsX)
-{
-  mStretchPixelsX = stretchPixelsX;
-}
-
-void NPatchData::SetStretchPixelsY(const NPatchUtility::StretchRanges stretchPixelsY)
-{
-  mStretchPixelsY = stretchPixelsY;
-}
-
-NPatchUtility::StretchRanges NPatchData::GetStretchPixelsX() const
-{
-  return mStretchPixelsX;
-}
-
-NPatchUtility::StretchRanges NPatchData::GetStretchPixelsY() const
-{
-  return mStretchPixelsY;
-}
-
-void NPatchData::SetHash(std::size_t hash)
-{
-  mHash = hash;
-}
-
-std::size_t NPatchData::GetHash() const
-{
-  return mHash;
-}
-
-void NPatchData::SetCroppedWidth(uint32_t croppedWidth)
-{
-  mCroppedWidth = croppedWidth;
-}
-
-void NPatchData::SetCroppedHeight(uint32_t croppedHeight)
-{
-  mCroppedHeight = croppedHeight;
-}
-
-uint32_t NPatchData::GetCroppedWidth() const
-{
-  return mCroppedWidth;
-}
-
-uint32_t NPatchData::GetCroppedHeight() const
-{
-  return mCroppedHeight;
-}
-
-void NPatchData::SetBorder(const Rect<int> border)
-{
-  mBorder = border;
-}
-
-Rect<int> NPatchData::GetBorder() const
-{
-  return mBorder;
-}
-
-void NPatchData::SetPreMultiplyOnLoad(bool preMultiplyOnLoad)
-{
-  mPreMultiplyOnLoad = preMultiplyOnLoad;
-}
-
-bool NPatchData::IsPreMultiplied() const
-{
-  return mPreMultiplyOnLoad;
-}
-
-void NPatchData::SetLoadingState(const LoadingState loadingState)
-{
-  mLoadingState = loadingState;
-}
-
-NPatchData::LoadingState NPatchData::GetLoadingState() const
-{
-  return mLoadingState;
-}
-
-void* NPatchData::GetRenderingMap() const
-{
-  return mRenderingMap;
-}
-
-void NPatchData::SetLoadedNPatchData(Devel::PixelBuffer& pixelBuffer, bool preMultiplied)
-{
-  if(mBorder == Rect<int>(0, 0, 0, 0))
-  {
-    NPatchUtility::ParseBorders(pixelBuffer, mStretchPixelsX, mStretchPixelsY);
-
-    // Crop the image
-    pixelBuffer.Crop(1, 1, pixelBuffer.GetWidth() - 2, pixelBuffer.GetHeight() - 2);
-  }
-  else
-  {
-    mStretchPixelsX.PushBack(Uint16Pair(mBorder.left, ((pixelBuffer.GetWidth() >= static_cast<unsigned int>(mBorder.right)) ? pixelBuffer.GetWidth() - mBorder.right : 0)));
-    mStretchPixelsY.PushBack(Uint16Pair(mBorder.top, ((pixelBuffer.GetHeight() >= static_cast<unsigned int>(mBorder.bottom)) ? pixelBuffer.GetHeight() - mBorder.bottom : 0)));
-  }
-
-  mCroppedWidth  = pixelBuffer.GetWidth();
-  mCroppedHeight = pixelBuffer.GetHeight();
-
-  // Create opacity map
-  mRenderingMap = RenderingAddOn::Get().IsValid() ? RenderingAddOn::Get().BuildNPatch(pixelBuffer, this) : nullptr;
-
-  PixelData pixels = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
-
-  Texture texture = Texture::New(TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight());
-  texture.Upload(pixels);
-
-  mTextureSet = TextureSet::New();
-  mTextureSet.SetTexture(0u, texture);
-
-  mPreMultiplyOnLoad = preMultiplied;
-
-  mLoadingState = LoadingState::LOAD_COMPLETE;
-}
-
-void NPatchData::NotifyObserver(TextureUploadObserver* observer, const bool& loadSuccess)
-{
-  observer->LoadComplete(
-    loadSuccess,
-    TextureUploadObserver::TextureInformation(
-      TextureUploadObserver::ReturnType::TEXTURE,
-      static_cast<TextureManager::TextureId>(mId), ///< Note : until end of NPatchLoader::Load, npatch-visual don't know the id of data.
-      mTextureSet,
-      mUrl.GetUrl(),
-      mPreMultiplyOnLoad));
-}
-
-void NPatchData::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
-{
-  NPatchDataPtr self = this; // Keep reference until this API finished
-
-  if(loadSuccess)
-  {
-    if(mLoadingState != LoadingState::LOAD_COMPLETE)
-    {
-      // If mLoadingState is LOAD_FAILED, just re-set (It can be happened when sync loading is failed, but async loading is succeeded).
-      SetLoadedNPatchData(textureInformation.pixelBuffer, textureInformation.preMultiplied);
-    }
-  }
-  else
-  {
-    if(mLoadingState == LoadingState::LOADING)
-    {
-      mLoadingState = LoadingState::LOAD_FAILED;
-    }
-    // If mLoadingState is already LOAD_COMPLETE, we can use uploaded texture (It can be happened when sync loading is succeeded, but async loading is failed).
-    else if(mLoadingState == LoadingState::LOAD_COMPLETE)
-    {
-      loadSuccess = true;
-    }
-  }
-
-  mObserverNotifying = true;
-
-  // Reverse observer list that we can pop_back the observer.
-  std::reverse(mObserverList.Begin(), mObserverList.End());
-
-  while(mObserverList.Count() > 0u)
-  {
-    TextureUploadObserver* observer = *(mObserverList.End() - 1u);
-    mObserverList.Erase(mObserverList.End() - 1u);
-
-    observer->DestructionSignal().Disconnect(this, &NPatchData::ObserverDestroyed);
-
-    NotifyObserver(observer, loadSuccess);
-  }
-
-  mObserverNotifying = false;
-
-  // Swap observer list what we queued during notify observer.
-  // If mQueuedObserver is not empty, it mean mLoadingState was LOAD_FAILED, and we try to re-load for this data.
-  // (If mLoadingState was LOAD_COMPLETE, NotifyObserver will be called directly. @todo : Should we fix this logic, matched with texture manager?)
-  // So LoadComplete will be called.
-  mObserverList.Swap(mQueuedObservers);
-}
-
-void NPatchData::ObserverDestroyed(TextureUploadObserver* observer)
-{
-  for(auto iter = mObserverList.Begin(); iter != mObserverList.End();)
-  {
-    if(observer == (*iter))
-    {
-      iter = mObserverList.Erase(iter);
-    }
-    else
-    {
-      ++iter;
-    }
-  }
-  if(mObserverNotifying)
-  {
-    for(auto iter = mQueuedObservers.Begin(); iter != mQueuedObservers.End();)
-    {
-      if(observer == (*iter))
-      {
-        iter = mQueuedObservers.Erase(iter);
-      }
-      else
-      {
-        ++iter;
-      }
-    }
-  }
-}
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/npatch-data.h b/dali-toolkit/internal/visuals/npatch-data.h
deleted file mode 100644 (file)
index 99c4d08..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-#ifndef DALI_TOOLKIT_NPATCH_DATA_H
-#define DALI_TOOLKIT_NPATCH_DATA_H
-
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
-#include <dali/public-api/object/ref-object.h>
-#include <dali/public-api/rendering/texture-set.h>
-#include <string>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
-#include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
-#include <dali-toolkit/internal/visuals/visual-url.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-class NPatchData;
-typedef IntrusivePtr<NPatchData> NPatchDataPtr;
-
-class NPatchData : public ConnectionTracker, public Dali::Toolkit::TextureUploadObserver, public Dali::RefObject
-{
-public:
-  typedef int32_t           NPatchDataId;                ///< The NPatchDataId type. This is used as a handle to refer to a particular Npatch Data.
-  static const NPatchDataId INVALID_NPATCH_DATA_ID = -1; ///< Used to represent a null TextureId or error
-
-  /**
-   * @brief Loading State of the NPatch image.
-   */
-  enum class LoadingState
-  {
-    NOT_STARTED = 0, ///< NPatch loading is not started yet.
-    LOADING,         ///< NPatch is on loading.
-    LOAD_COMPLETE,   ///< NPatch loading is completed successfully.
-    LOAD_FAILED      ///< NPatch loading is failed.
-  };
-
-public:
-  /**
-   * Constructor
-   */
-  NPatchData();
-
-  /**
-   * Destructor, non-virtual as not a base class
-   */
-  ~NPatchData();
-
-public:
-  /**
-   * @brief Set cache data id.
-   *
-   * @param [in] id cache data id
-   */
-  void SetId(const NPatchDataId id);
-
-  /**
-   * @brief Retrieve cache data id
-   *
-   * @return cache data id.
-   */
-  NPatchDataId GetId() const;
-
-  /**
-   * @brief Add TextureUploadObserver that uses the image of this cache data.
-   *
-   * @param [in] textureObserver the TextureUploadObserver that uses the image of this cache data.
-   */
-  void AddObserver(TextureUploadObserver* textureObserver);
-
-  /**
-   * @brief Remove TextureUploadObserver.
-   *
-   * @param [in] textureObserver the TextureUploadObserver that will be removed in this cache data.
-   */
-  void RemoveObserver(TextureUploadObserver* textureObserver);
-
-  /**
-   * @brief Retrieve the number of observer.
-   *
-   * @return Return the number of observer.
-   */
-  uint32_t GetObserverCount() const;
-
-  /**
-   * @brief Set NPatch image url.
-   *
-   * @param [in] url NPatch image url
-   */
-  void SetUrl(const VisualUrl& url);
-
-  /**
-   * @brief Retrieve the image url.
-   *
-   * @return Return the image url.
-   */
-  VisualUrl GetUrl() const;
-
-  /**
-   * @brief Set texture set on the cache data
-   *
-   * @param [in] textureSet loaded texture set
-   */
-  void SetTextures(const TextureSet textureSet);
-
-  /**
-   * @brief Retrieve loaded texture set.
-   *
-   * @return Return loaded texture set.
-   */
-  TextureSet GetTextures() const;
-
-  /**
-   * @brief Set X directional stretchPixels
-   *
-   * @param [in] stretchPixelsX stretchPixels for X direction
-   */
-  void SetStretchPixelsX(const NPatchUtility::StretchRanges stretchPixelsX);
-
-  /**
-   * @brief Set Y directional stretchPixels
-   *
-   * @param [in] stretchPixelsY stretchPixels for Y direction
-   */
-  void SetStretchPixelsY(const NPatchUtility::StretchRanges stretchPixelsY);
-
-  /**
-   * @brief Retrieve stretchPixels for X direction.
-   *
-   * @return Return stretchPixels for X direction.
-   */
-  NPatchUtility::StretchRanges GetStretchPixelsX() const;
-
-  /**
-   * @brief Retrieve stretchPixels for Y direction.
-   *
-   * @return Return stretchPixels for Y direction.
-   */
-  NPatchUtility::StretchRanges GetStretchPixelsY() const;
-
-  /**
-   * @brief Set cache data hash.
-   *
-   * @param [in] hash cache hash
-   */
-  void SetHash(std::size_t hash);
-
-  /**
-   * @brief Retrieve hash value of the cache.
-   *
-   * @return Return hash value of the cache.
-   */
-  std::size_t GetHash() const;
-
-  /**
-   * @brief Set croppedWidth of NPatch
-   *
-   * @param [in] croppedWidth croppedWidth of NPatch
-   */
-  void SetCroppedWidth(uint32_t croppedWidth);
-
-  /**
-   * @brief Set croppedHeight of NPatch
-   *
-   * @param [in] croppedHeight croppedHeight of NPatch
-   */
-  void SetCroppedHeight(uint32_t croppedHeight);
-
-  /**
-   * @brief Retrieve croppedWidth of NPatch.
-   *
-   * @return Return croppedWidth of NPatch.
-   */
-  uint32_t GetCroppedWidth() const;
-
-  /**
-   * @brief Retrieve croppedHeight of NPatch.
-   *
-   * @return Return croppedHeight of NPatch.
-   */
-  uint32_t GetCroppedHeight() const;
-
-  /**
-   * @brief Set border of NPatch.
-   *
-   * @param [in] border border of NPatch
-   */
-  void SetBorder(const Rect<int> border);
-
-  /**
-   * @brief Retrieve border of NPatch.
-   *
-   * @return Return border of NPatch.
-   */
-  Rect<int> GetBorder() const;
-
-  /**
-   * @brief Set whether the loaded image is premultiplied or not
-   *
-   * @param [in] preMultiplyOnLoad whether the loaded image is premultiplied or not
-   */
-  void SetPreMultiplyOnLoad(bool preMultiplyOnLoad);
-
-  /**
-   * @brief Retrieve whether the loaded image is premultiplied or not.
-   *
-   * @return Return true if the image is premultiplied alpha.
-   */
-  bool IsPreMultiplied() const;
-
-  /**
-   * @brief Set current loading state.
-   *
-   * @param [in] loadingState current loading state
-   */
-  void SetLoadingState(const LoadingState loadingState);
-
-  /**
-   * @brief Retrieve current loading state.
-   *
-   * @return Return current loading state.
-   */
-  LoadingState GetLoadingState() const;
-
-  /**
-   * @brief Retrieve NPatch rendering data.
-   *
-   * @return Return NPatch rendering data.
-   */
-  void* GetRenderingMap() const;
-
-  /**
-   * @brief Set loaded pixel buffer for the cache data.
-   *
-   * @param [in] pixelBuffer loaded pixel buffer.
-   * @param [in] preMultiplied whether the loaded image is premultiplied or not
-   */
-  void SetLoadedNPatchData(Devel::PixelBuffer& pixelBuffer, bool preMultiplied);
-
-  /**
-   * @brief Send LoadComplete notify with current setuped NPatchData
-   *
-   * @param [in] observer observer who will be got LoadComplete notify
-   * @param [in] loadSuccess whether the image load success or not.
-   */
-  void NotifyObserver(TextureUploadObserver* observer, const bool& loadSuccess);
-
-private:
-  /**
-   * @copydoc TextureUploadObserver::LoadComplete
-   *
-   * To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
-   * This callback is the place to add the renderer as it would be called once the loading is finished.
-   */
-  void LoadComplete(bool loadSuccess, TextureInformation textureInformation) override;
-
-  /**
-   * This is called by the TextureUploadObserver when an observer is destroyed.
-   * We use the callback to know when to remove an observer from our notify list.
-   * @param[in] observer The observer that generated the callback
-   */
-  void ObserverDestroyed(TextureUploadObserver* observer);
-
-private:
-  using ObserverListType = Dali::Vector<TextureUploadObserver*>;
-
-  NPatchDataId     mId;
-  ObserverListType mObserverList;    ///< Container used to store all observer clients of this Texture
-  ObserverListType mQueuedObservers; ///< Container observers when user try to add during notify observers
-
-  VisualUrl                    mUrl;            ///< Url of the N-Patch
-  TextureSet                   mTextureSet;     ///< Texture containing the cropped image
-  NPatchUtility::StretchRanges mStretchPixelsX; ///< X stretch pixels
-  NPatchUtility::StretchRanges mStretchPixelsY; ///< Y stretch pixels
-  std::size_t                  mHash;           ///< Hash code for the Url
-  uint32_t                     mCroppedWidth;   ///< Width of the cropped middle part of N-patch
-  uint32_t                     mCroppedHeight;  ///< Height of the cropped middle part of N-patch
-  Rect<int>                    mBorder;         ///< The size of the border
-  LoadingState                 mLoadingState;   ///< True if the data loading is completed
-  void*                        mRenderingMap;   ///< NPatch rendering data
-
-  bool mPreMultiplyOnLoad : 1; ///< Whether to multiply alpha into color channels on load
-  bool mObserverNotifying : 1; ///< Whether this NPatchData notifying observers or not.
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_NPATCH_DATA_H
diff --git a/dali-toolkit/internal/visuals/npatch-loader.cpp b/dali-toolkit/internal/visuals/npatch-loader.cpp
deleted file mode 100644 (file)
index b293cac..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/visuals/npatch-loader.h>
-
-// INTERNAL HEADERS
-#include <dali-toolkit/internal/visuals/rendering-addon.h>
-
-// EXTERNAL HEADERS
-#include <dali/devel-api/common/hash.h>
-#include <dali/integration-api/adaptor-framework/adaptor.h>
-#include <dali/integration-api/debug.h>
-#include <dali/integration-api/trace.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace
-{
-constexpr auto INVALID_CACHE_INDEX = int32_t{-1}; ///< Invalid Cache index
-constexpr auto UNINITIALIZED_ID    = int32_t{0};  ///< uninitialised id, use to initialize ids
-
-DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false);
-} // Anonymous namespace
-
-NPatchLoader::NPatchLoader()
-: mCurrentNPatchDataId(0),
-  mRemoveProcessorRegistered(false)
-{
-}
-
-NPatchLoader::~NPatchLoader()
-{
-  if(mRemoveProcessorRegistered && Adaptor::IsAvailable())
-  {
-    Adaptor::Get().UnregisterProcessorOnce(*this, true);
-    mRemoveProcessorRegistered = false;
-  }
-}
-
-NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
-{
-  // Skip invalid id generation.
-  if(DALI_UNLIKELY(mCurrentNPatchDataId == NPatchData::INVALID_NPATCH_DATA_ID))
-  {
-    mCurrentNPatchDataId = 0;
-  }
-  return mCurrentNPatchDataId++;
-}
-
-NPatchData::NPatchDataId NPatchLoader::Load(TextureManager& textureManager, TextureUploadObserver* textureObserver, const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad, bool synchronousLoading)
-{
-  NPatchDataPtr data = GetNPatchData(url, border, preMultiplyOnLoad);
-
-  DALI_ASSERT_ALWAYS(data.Get() && "NPatchData creation failed!");
-
-  if(data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
-  {
-    if(!synchronousLoading)
-    {
-      // NotifyObserver already done, so
-      // data will not iterate observer list.
-      // We need to call LoadComplete directly.
-      data->NotifyObserver(textureObserver, true);
-    }
-  }
-  else // if NOT_STARTED or LOADING or LOAD_FAILED, try to reload.
-  {
-    if(!synchronousLoading)
-    {
-      data->AddObserver(textureObserver);
-      // If still LOADING and async, don't need to request reload. Fast return.
-      if(data->GetLoadingState() == NPatchData::LoadingState::LOADING)
-      {
-        return data->GetId();
-      }
-    }
-
-    data->SetLoadingState(NPatchData::LoadingState::LOADING);
-
-    auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
-                                                  : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-
-    Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(url, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, data.Get(), true, preMultiplyOnLoading);
-
-    if(pixelBuffer)
-    {
-      preMultiplyOnLoad = (preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? true : false;
-      data->SetLoadedNPatchData(pixelBuffer, preMultiplyOnLoad);
-    }
-    else if(synchronousLoading)
-    {
-      data->SetLoadingState(NPatchData::LoadingState::LOAD_FAILED);
-    }
-  }
-  return data->GetId();
-}
-
-int32_t NPatchLoader::GetCacheIndexFromId(const NPatchData::NPatchDataId id)
-{
-  const unsigned int size = mCache.size();
-
-  for(unsigned int i = 0; i < size; ++i)
-  {
-    if(mCache[i].mData->GetId() == id)
-    {
-      return i;
-    }
-  }
-
-  return INVALID_CACHE_INDEX;
-}
-
-bool NPatchLoader::GetNPatchData(const NPatchData::NPatchDataId id, NPatchDataPtr& data)
-{
-  int32_t cacheIndex = GetCacheIndexFromId(id);
-  if(cacheIndex != INVALID_CACHE_INDEX)
-  {
-    data = mCache[cacheIndex].mData;
-    return true;
-  }
-  data = nullptr;
-  return false;
-}
-
-void NPatchLoader::RequestRemove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver)
-{
-  // Remove observer first
-  if(textureObserver)
-  {
-    int32_t cacheIndex = GetCacheIndexFromId(id);
-    if(cacheIndex != INVALID_CACHE_INDEX)
-    {
-      NPatchInfo& info(mCache[cacheIndex]);
-
-      info.mData->RemoveObserver(textureObserver);
-    }
-  }
-
-  mRemoveQueue.push_back({id, nullptr});
-
-  if(!mRemoveProcessorRegistered && Adaptor::IsAvailable())
-  {
-    mRemoveProcessorRegistered = true;
-    Adaptor::Get().RegisterProcessorOnce(*this, true);
-  }
-}
-
-void NPatchLoader::Remove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver)
-{
-  int32_t cacheIndex = GetCacheIndexFromId(id);
-  if(cacheIndex == INVALID_CACHE_INDEX)
-  {
-    return;
-  }
-
-  NPatchInfo& info(mCache[cacheIndex]);
-
-  info.mData->RemoveObserver(textureObserver);
-
-  if(--info.mReferenceCount <= 0)
-  {
-    mCache.erase(mCache.begin() + cacheIndex);
-  }
-}
-
-void NPatchLoader::Process(bool postProcessor)
-{
-  DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_NPATCH_LOADER_PROCESS_REMOVE_QUEUE", [&](std::ostringstream& oss) {
-    oss << "[" << mRemoveQueue.size() << "]";
-  });
-
-  mRemoveProcessorRegistered = false;
-
-  for(auto& iter : mRemoveQueue)
-  {
-    Remove(iter.first, iter.second);
-  }
-
-  mRemoveQueue.clear();
-
-  DALI_TRACE_END(gTraceFilter, "DALI_NPATCH_LOADER_PROCESS_REMOVE_QUEUE");
-}
-
-NPatchDataPtr NPatchLoader::GetNPatchData(const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad)
-{
-  std::size_t                              hash  = CalculateHash(url.GetUrl());
-  std::vector<NPatchInfo>::size_type       index = UNINITIALIZED_ID;
-  const std::vector<NPatchInfo>::size_type count = mCache.size();
-
-  NPatchInfo* infoPtr = nullptr;
-
-  for(; index < count; ++index)
-  {
-    if(mCache[index].mData->GetHash() == hash)
-    {
-      // hash match, check url as well in case of hash collision
-      if(mCache[index].mData->GetUrl().GetUrl() == url.GetUrl())
-      {
-        // Use cached data. Need to fast-out return.
-        if(mCache[index].mData->GetBorder() == border)
-        {
-          mCache[index].mReferenceCount++;
-          return mCache[index].mData;
-        }
-        else
-        {
-          if(mCache[index].mData->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
-          {
-            // If we only found LOAD_FAILED case, replace current data. We can reuse texture
-            if(infoPtr == nullptr || infoPtr->mData->GetLoadingState() != NPatchData::LoadingState::LOAD_COMPLETE)
-            {
-              infoPtr = &mCache[index];
-            }
-          }
-          // Still loading pixel buffer. We cannot reuse cached texture yet. Skip checking
-          else if(mCache[index].mData->GetLoadingState() == NPatchData::LoadingState::LOADING)
-          {
-            continue;
-          }
-          // if LOAD_FAILED, reuse this cached NPatchData, and try to load again.
-          else
-          {
-            if(infoPtr == nullptr)
-            {
-              infoPtr = &mCache[index];
-            }
-          }
-        }
-      }
-    }
-  }
-
-  // If this is new image loading, make new cache data
-  if(infoPtr == nullptr)
-  {
-    NPatchInfo info(new NPatchData());
-    info.mData->SetId(GenerateUniqueNPatchDataId());
-    info.mData->SetHash(hash);
-    info.mData->SetUrl(url);
-    info.mData->SetBorder(border);
-    info.mData->SetPreMultiplyOnLoad(preMultiplyOnLoad);
-
-    mCache.emplace_back(std::move(info));
-    infoPtr = &mCache.back();
-  }
-  // Else if LOAD_COMPLETE, Same url but border is different - use the existing texture
-  else if(infoPtr->mData->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
-  {
-    NPatchInfo info(new NPatchData());
-
-    info.mData->SetId(GenerateUniqueNPatchDataId());
-    info.mData->SetHash(hash);
-    info.mData->SetUrl(url);
-    info.mData->SetCroppedWidth(infoPtr->mData->GetCroppedWidth());
-    info.mData->SetCroppedHeight(infoPtr->mData->GetCroppedHeight());
-
-    info.mData->SetTextures(infoPtr->mData->GetTextures());
-
-    NPatchUtility::StretchRanges stretchRangesX;
-    stretchRangesX.PushBack(Uint16Pair(border.left, ((info.mData->GetCroppedWidth() >= static_cast<unsigned int>(border.right)) ? info.mData->GetCroppedHeight() - border.right : 0)));
-
-    NPatchUtility::StretchRanges stretchRangesY;
-    stretchRangesY.PushBack(Uint16Pair(border.top, ((info.mData->GetCroppedWidth() >= static_cast<unsigned int>(border.bottom)) ? info.mData->GetCroppedHeight() - border.bottom : 0)));
-
-    info.mData->SetStretchPixelsX(stretchRangesX);
-    info.mData->SetStretchPixelsY(stretchRangesY);
-    info.mData->SetBorder(border);
-
-    info.mData->SetPreMultiplyOnLoad(infoPtr->mData->IsPreMultiplied());
-
-    info.mData->SetLoadingState(NPatchData::LoadingState::LOAD_COMPLETE);
-
-    mCache.emplace_back(std::move(info));
-    infoPtr = &mCache.back();
-  }
-  // Else, LOAD_FAILED. just increase reference so we can reuse it.
-  else
-  {
-    infoPtr->mReferenceCount++;
-  }
-
-  DALI_ASSERT_ALWAYS(infoPtr && "NPatchInfo creation failed!");
-
-  return infoPtr->mData;
-}
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/npatch-loader.h b/dali-toolkit/internal/visuals/npatch-loader.h
deleted file mode 100644 (file)
index fb66fcc..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-#ifndef DALI_TOOLKIT_NPATCH_LOADER_H
-#define DALI_TOOLKIT_NPATCH_LOADER_H
-
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
-#include <dali/integration-api/processor-interface.h>
-#include <dali/public-api/rendering/texture-set.h>
-#include <string>
-#include <utility> // for std::pair
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
-#include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
-#include <dali-toolkit/internal/visuals/npatch-data.h>
-#include <dali-toolkit/internal/visuals/visual-url.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-/**
- * The manager for loading Npatch textures.
- * It caches them internally for better performance; i.e. to avoid loading and
- * parsing the files over and over.
- *
- * Cache is not cleaned during app lifecycle as N patches take considerably
- * small space and there's not usually a lot of them. Usually N patches are specified in
- * toolkit default style and there is 1-2 per control that are shared across the whole application.
- */
-class NPatchLoader : public Integration::Processor
-{
-public:
-  /**
-   * Constructor
-   */
-  NPatchLoader();
-
-  /**
-   * Destructor, non-virtual as not a base class
-   */
-  ~NPatchLoader();
-
-  /**
-   * @brief Retrieve a texture matching the n-patch url.
-   *
-   * @param [in] textureManager that will be used to loading image
-   * @param [in] textureObserver The NPatchVisual that requested loading.
-   * @param [in] url to retrieve
-   * @param [in] border The border size of the image
-   * @param [in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
-   *                                   image has no alpha channel
-   * @param [in] synchronousLoading True if the image will be loaded in synchronous time.
-   * @return id of the texture.
-   */
-  NPatchData::NPatchDataId Load(TextureManager& textureManager, TextureUploadObserver* textureObserver, const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad, bool synchronousLoading);
-
-  /**
-   * @brief Retrieve N patch data matching to an id
-   * @param [in] id of data
-   * @param [out] data const pointer to the NPatchData
-   * @return true if data matching to id was really found
-   */
-  bool GetNPatchData(const NPatchData::NPatchDataId id, NPatchDataPtr& data);
-
-  /**
-   * @brief Request remove a texture matching id.
-   * Erase the observer from the observer list of cache if we need.
-   *
-   * @param [in] id cache data id
-   * @param [in] textureObserver The NPatchVisual that requested loading.
-   */
-  void RequestRemove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver);
-
-protected: // Implementation of Processor
-  /**
-   * @copydoc Dali::Integration::Processor::Process()
-   */
-  void Process(bool postProcessor) override;
-
-  /**
-   * @copydoc Dali::Integration::Processor::GetProcessorName()
-   */
-  std::string_view GetProcessorName() const override
-  {
-    return "NPatchLoader";
-  }
-
-private:
-  NPatchData::NPatchDataId GenerateUniqueNPatchDataId();
-
-  int32_t GetCacheIndexFromId(const NPatchData::NPatchDataId id);
-
-  /**
-   * @brief Remove a texture matching id.
-   * Erase the observer from the observer list of cache if we need.
-   * This API decrease cached NPatchInfo reference.
-   * If the NPatchInfo reference become 0, the textureSet will be reset.
-   *
-   * @param [in] id cache data id
-   * @param [in] textureObserver The NPatchVisual that requested loading.
-   */
-  void Remove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver);
-
-private:
-  /**
-   * @brief Information of NPatchData
-   * It also hold ownership of NPatchData memory.
-   */
-  struct NPatchInfo
-  {
-    NPatchInfo(NPatchDataPtr data)
-    : mData(data),
-      mReferenceCount(1u)
-    {
-    }
-    ~NPatchInfo()
-    {
-    }
-    NPatchInfo(NPatchInfo&& info) noexcept // move constructor
-    {
-      mData                = std::move(info.mData);
-      mReferenceCount      = info.mReferenceCount;
-      info.mReferenceCount = 0u;
-    }
-    NPatchInfo& operator=(NPatchInfo&& info) noexcept // move operator
-    {
-      mData                = std::move(info.mData);
-      mReferenceCount      = info.mReferenceCount;
-      info.mReferenceCount = 0u;
-      return *this;
-    }
-
-    NPatchInfo()                       = delete;            // Do not use default constructor
-    NPatchInfo(const NPatchInfo& info) = delete;            // Do not use copy constructor
-    NPatchInfo& operator=(const NPatchInfo& info) = delete; // Do not use copy assign
-
-    NPatchDataPtr mData;
-    std::int16_t  mReferenceCount; ///< The number of N-patch visuals that use this data.
-  };
-
-  /**
-   * @brief Get cached NPatchData by inputed url and border. If there is no cached data, create new one.
-   * @note This API increase cached NPatchInfo reference.
-   *
-   * @param [in] url to retrieve
-   * @param [in] border The border size of the image
-   * @param [in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
-   *                                   image has no alpha channel
-   * @return NPatchData pointer that Load function will used.
-   */
-  NPatchDataPtr GetNPatchData(const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad);
-
-protected:
-  /**
-   * Undefined copy constructor.
-   */
-  NPatchLoader(const NPatchLoader&);
-
-  /**
-   * Undefined assignment operator.
-   */
-  NPatchLoader& operator=(const NPatchLoader& rhs);
-
-private:
-  NPatchData::NPatchDataId mCurrentNPatchDataId;
-  std::vector<NPatchInfo>  mCache;
-
-  std::vector<std::pair<NPatchData::NPatchDataId, TextureUploadObserver*>> mRemoveQueue; ///< Queue of textures to remove at PostProcess. It will be cleared after PostProcess.
-
-  bool mRemoveProcessorRegistered : 1; ///< Flag if remove processor registered or not.
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_NPATCH_LOADER_H
diff --git a/dali-toolkit/internal/visuals/npatch/npatch-data.cpp b/dali-toolkit/internal/visuals/npatch/npatch-data.cpp
new file mode 100644 (file)
index 0000000..50c4254
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/npatch/npatch-data.h>
+
+// INTERNAL HEADERS
+#include <dali-toolkit/internal/visuals/rendering-addon.h>
+
+// EXTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+NPatchData::NPatchData()
+: mId(INVALID_NPATCH_DATA_ID),
+  mUrl(),
+  mTextureSet(),
+  mHash(0),
+  mCroppedWidth(0),
+  mCroppedHeight(0),
+  mBorder(0, 0, 0, 0),
+  mLoadingState(LoadingState::NOT_STARTED),
+  mRenderingMap{nullptr},
+  mPreMultiplyOnLoad(false),
+  mObserverNotifying(false)
+{
+}
+
+NPatchData::~NPatchData()
+{
+  // If there is an opacity map, it has to be destroyed using addon call
+  if(mRenderingMap)
+  {
+    RenderingAddOn::Get().DestroyNPatch(mRenderingMap);
+  }
+  mObserverList.Clear();
+  mQueuedObservers.Clear();
+}
+
+void NPatchData::SetId(const NPatchDataId id)
+{
+  mId = id;
+}
+
+NPatchData::NPatchDataId NPatchData::GetId() const
+{
+  return mId;
+}
+
+void NPatchData::AddObserver(TextureUploadObserver* textureObserver)
+{
+  if(textureObserver)
+  {
+    if(mObserverNotifying)
+    {
+      // Do not add it into observer list during observer notifying.
+      mQueuedObservers.PushBack(textureObserver);
+    }
+    else
+    {
+      mObserverList.PushBack(textureObserver);
+    }
+    textureObserver->DestructionSignal().Connect(this, &NPatchData::ObserverDestroyed);
+  }
+}
+
+void NPatchData::RemoveObserver(TextureUploadObserver* textureObserver)
+{
+  if(textureObserver)
+  {
+    for(uint32_t index = 0; index < mObserverList.Count(); ++index)
+    {
+      if(textureObserver == mObserverList[index])
+      {
+        textureObserver->DestructionSignal().Disconnect(this, &NPatchData::ObserverDestroyed);
+        mObserverList.Erase(mObserverList.begin() + index);
+        break;
+      }
+    }
+  }
+}
+
+uint32_t NPatchData::GetObserverCount() const
+{
+  return mObserverList.Count();
+}
+
+void NPatchData::SetUrl(const VisualUrl& url)
+{
+  mUrl = url;
+}
+
+VisualUrl NPatchData::GetUrl() const
+{
+  return mUrl;
+}
+
+void NPatchData::SetTextures(const TextureSet textureSet)
+{
+  mTextureSet = textureSet;
+}
+
+TextureSet NPatchData::GetTextures() const
+{
+  return mTextureSet;
+}
+
+void NPatchData::SetStretchPixelsX(const NPatchUtility::StretchRanges stretchPixelsX)
+{
+  mStretchPixelsX = stretchPixelsX;
+}
+
+void NPatchData::SetStretchPixelsY(const NPatchUtility::StretchRanges stretchPixelsY)
+{
+  mStretchPixelsY = stretchPixelsY;
+}
+
+NPatchUtility::StretchRanges NPatchData::GetStretchPixelsX() const
+{
+  return mStretchPixelsX;
+}
+
+NPatchUtility::StretchRanges NPatchData::GetStretchPixelsY() const
+{
+  return mStretchPixelsY;
+}
+
+void NPatchData::SetHash(std::size_t hash)
+{
+  mHash = hash;
+}
+
+std::size_t NPatchData::GetHash() const
+{
+  return mHash;
+}
+
+void NPatchData::SetCroppedWidth(uint32_t croppedWidth)
+{
+  mCroppedWidth = croppedWidth;
+}
+
+void NPatchData::SetCroppedHeight(uint32_t croppedHeight)
+{
+  mCroppedHeight = croppedHeight;
+}
+
+uint32_t NPatchData::GetCroppedWidth() const
+{
+  return mCroppedWidth;
+}
+
+uint32_t NPatchData::GetCroppedHeight() const
+{
+  return mCroppedHeight;
+}
+
+void NPatchData::SetBorder(const Rect<int> border)
+{
+  mBorder = border;
+}
+
+Rect<int> NPatchData::GetBorder() const
+{
+  return mBorder;
+}
+
+void NPatchData::SetPreMultiplyOnLoad(bool preMultiplyOnLoad)
+{
+  mPreMultiplyOnLoad = preMultiplyOnLoad;
+}
+
+bool NPatchData::IsPreMultiplied() const
+{
+  return mPreMultiplyOnLoad;
+}
+
+void NPatchData::SetLoadingState(const LoadingState loadingState)
+{
+  mLoadingState = loadingState;
+}
+
+NPatchData::LoadingState NPatchData::GetLoadingState() const
+{
+  return mLoadingState;
+}
+
+void* NPatchData::GetRenderingMap() const
+{
+  return mRenderingMap;
+}
+
+void NPatchData::SetLoadedNPatchData(Devel::PixelBuffer& pixelBuffer, bool preMultiplied)
+{
+  if(mBorder == Rect<int>(0, 0, 0, 0))
+  {
+    NPatchUtility::ParseBorders(pixelBuffer, mStretchPixelsX, mStretchPixelsY);
+
+    // Crop the image
+    pixelBuffer.Crop(1, 1, pixelBuffer.GetWidth() - 2, pixelBuffer.GetHeight() - 2);
+  }
+  else
+  {
+    mStretchPixelsX.PushBack(Uint16Pair(mBorder.left, ((pixelBuffer.GetWidth() >= static_cast<unsigned int>(mBorder.right)) ? pixelBuffer.GetWidth() - mBorder.right : 0)));
+    mStretchPixelsY.PushBack(Uint16Pair(mBorder.top, ((pixelBuffer.GetHeight() >= static_cast<unsigned int>(mBorder.bottom)) ? pixelBuffer.GetHeight() - mBorder.bottom : 0)));
+  }
+
+  mCroppedWidth  = pixelBuffer.GetWidth();
+  mCroppedHeight = pixelBuffer.GetHeight();
+
+  // Create opacity map
+  mRenderingMap = RenderingAddOn::Get().IsValid() ? RenderingAddOn::Get().BuildNPatch(pixelBuffer, this) : nullptr;
+
+  PixelData pixels = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+
+  Texture texture = Texture::New(TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight());
+  texture.Upload(pixels);
+
+  mTextureSet = TextureSet::New();
+  mTextureSet.SetTexture(0u, texture);
+
+  mPreMultiplyOnLoad = preMultiplied;
+
+  mLoadingState = LoadingState::LOAD_COMPLETE;
+}
+
+void NPatchData::NotifyObserver(TextureUploadObserver* observer, const bool& loadSuccess)
+{
+  observer->LoadComplete(
+    loadSuccess,
+    TextureUploadObserver::TextureInformation(
+      TextureUploadObserver::ReturnType::TEXTURE,
+      static_cast<TextureManager::TextureId>(mId), ///< Note : until end of NPatchLoader::Load, npatch-visual don't know the id of data.
+      mTextureSet,
+      mUrl.GetUrl(),
+      mPreMultiplyOnLoad));
+}
+
+void NPatchData::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
+{
+  NPatchDataPtr self = this; // Keep reference until this API finished
+
+  if(loadSuccess)
+  {
+    if(mLoadingState != LoadingState::LOAD_COMPLETE)
+    {
+      // If mLoadingState is LOAD_FAILED, just re-set (It can be happened when sync loading is failed, but async loading is succeeded).
+      SetLoadedNPatchData(textureInformation.pixelBuffer, textureInformation.preMultiplied);
+    }
+  }
+  else
+  {
+    if(mLoadingState == LoadingState::LOADING)
+    {
+      mLoadingState = LoadingState::LOAD_FAILED;
+    }
+    // If mLoadingState is already LOAD_COMPLETE, we can use uploaded texture (It can be happened when sync loading is succeeded, but async loading is failed).
+    else if(mLoadingState == LoadingState::LOAD_COMPLETE)
+    {
+      loadSuccess = true;
+    }
+  }
+
+  mObserverNotifying = true;
+
+  // Reverse observer list that we can pop_back the observer.
+  std::reverse(mObserverList.Begin(), mObserverList.End());
+
+  while(mObserverList.Count() > 0u)
+  {
+    TextureUploadObserver* observer = *(mObserverList.End() - 1u);
+    mObserverList.Erase(mObserverList.End() - 1u);
+
+    observer->DestructionSignal().Disconnect(this, &NPatchData::ObserverDestroyed);
+
+    NotifyObserver(observer, loadSuccess);
+  }
+
+  mObserverNotifying = false;
+
+  // Swap observer list what we queued during notify observer.
+  // If mQueuedObserver is not empty, it mean mLoadingState was LOAD_FAILED, and we try to re-load for this data.
+  // (If mLoadingState was LOAD_COMPLETE, NotifyObserver will be called directly. @todo : Should we fix this logic, matched with texture manager?)
+  // So LoadComplete will be called.
+  mObserverList.Swap(mQueuedObservers);
+}
+
+void NPatchData::ObserverDestroyed(TextureUploadObserver* observer)
+{
+  for(auto iter = mObserverList.Begin(); iter != mObserverList.End();)
+  {
+    if(observer == (*iter))
+    {
+      iter = mObserverList.Erase(iter);
+    }
+    else
+    {
+      ++iter;
+    }
+  }
+  if(mObserverNotifying)
+  {
+    for(auto iter = mQueuedObservers.Begin(); iter != mQueuedObservers.End();)
+    {
+      if(observer == (*iter))
+      {
+        iter = mQueuedObservers.Erase(iter);
+      }
+      else
+      {
+        ++iter;
+      }
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/npatch/npatch-data.h b/dali-toolkit/internal/visuals/npatch/npatch-data.h
new file mode 100644 (file)
index 0000000..8f1680a
--- /dev/null
@@ -0,0 +1,311 @@
+#ifndef DALI_TOOLKIT_NPATCH_DATA_H
+#define DALI_TOOLKIT_NPATCH_DATA_H
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/rendering/texture-set.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
+#include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+class NPatchData;
+typedef IntrusivePtr<NPatchData> NPatchDataPtr;
+
+class NPatchData : public ConnectionTracker, public Dali::Toolkit::TextureUploadObserver, public Dali::RefObject
+{
+public:
+  typedef int32_t           NPatchDataId;                ///< The NPatchDataId type. This is used as a handle to refer to a particular Npatch Data.
+  static const NPatchDataId INVALID_NPATCH_DATA_ID = -1; ///< Used to represent a null TextureId or error
+
+  /**
+   * @brief Loading State of the NPatch image.
+   */
+  enum class LoadingState
+  {
+    NOT_STARTED = 0, ///< NPatch loading is not started yet.
+    LOADING,         ///< NPatch is on loading.
+    LOAD_COMPLETE,   ///< NPatch loading is completed successfully.
+    LOAD_FAILED      ///< NPatch loading is failed.
+  };
+
+public:
+  /**
+   * Constructor
+   */
+  NPatchData();
+
+  /**
+   * Destructor, non-virtual as not a base class
+   */
+  ~NPatchData();
+
+public:
+  /**
+   * @brief Set cache data id.
+   *
+   * @param [in] id cache data id
+   */
+  void SetId(const NPatchDataId id);
+
+  /**
+   * @brief Retrieve cache data id
+   *
+   * @return cache data id.
+   */
+  NPatchDataId GetId() const;
+
+  /**
+   * @brief Add TextureUploadObserver that uses the image of this cache data.
+   *
+   * @param [in] textureObserver the TextureUploadObserver that uses the image of this cache data.
+   */
+  void AddObserver(TextureUploadObserver* textureObserver);
+
+  /**
+   * @brief Remove TextureUploadObserver.
+   *
+   * @param [in] textureObserver the TextureUploadObserver that will be removed in this cache data.
+   */
+  void RemoveObserver(TextureUploadObserver* textureObserver);
+
+  /**
+   * @brief Retrieve the number of observer.
+   *
+   * @return Return the number of observer.
+   */
+  uint32_t GetObserverCount() const;
+
+  /**
+   * @brief Set NPatch image url.
+   *
+   * @param [in] url NPatch image url
+   */
+  void SetUrl(const VisualUrl& url);
+
+  /**
+   * @brief Retrieve the image url.
+   *
+   * @return Return the image url.
+   */
+  VisualUrl GetUrl() const;
+
+  /**
+   * @brief Set texture set on the cache data
+   *
+   * @param [in] textureSet loaded texture set
+   */
+  void SetTextures(const TextureSet textureSet);
+
+  /**
+   * @brief Retrieve loaded texture set.
+   *
+   * @return Return loaded texture set.
+   */
+  TextureSet GetTextures() const;
+
+  /**
+   * @brief Set X directional stretchPixels
+   *
+   * @param [in] stretchPixelsX stretchPixels for X direction
+   */
+  void SetStretchPixelsX(const NPatchUtility::StretchRanges stretchPixelsX);
+
+  /**
+   * @brief Set Y directional stretchPixels
+   *
+   * @param [in] stretchPixelsY stretchPixels for Y direction
+   */
+  void SetStretchPixelsY(const NPatchUtility::StretchRanges stretchPixelsY);
+
+  /**
+   * @brief Retrieve stretchPixels for X direction.
+   *
+   * @return Return stretchPixels for X direction.
+   */
+  NPatchUtility::StretchRanges GetStretchPixelsX() const;
+
+  /**
+   * @brief Retrieve stretchPixels for Y direction.
+   *
+   * @return Return stretchPixels for Y direction.
+   */
+  NPatchUtility::StretchRanges GetStretchPixelsY() const;
+
+  /**
+   * @brief Set cache data hash.
+   *
+   * @param [in] hash cache hash
+   */
+  void SetHash(std::size_t hash);
+
+  /**
+   * @brief Retrieve hash value of the cache.
+   *
+   * @return Return hash value of the cache.
+   */
+  std::size_t GetHash() const;
+
+  /**
+   * @brief Set croppedWidth of NPatch
+   *
+   * @param [in] croppedWidth croppedWidth of NPatch
+   */
+  void SetCroppedWidth(uint32_t croppedWidth);
+
+  /**
+   * @brief Set croppedHeight of NPatch
+   *
+   * @param [in] croppedHeight croppedHeight of NPatch
+   */
+  void SetCroppedHeight(uint32_t croppedHeight);
+
+  /**
+   * @brief Retrieve croppedWidth of NPatch.
+   *
+   * @return Return croppedWidth of NPatch.
+   */
+  uint32_t GetCroppedWidth() const;
+
+  /**
+   * @brief Retrieve croppedHeight of NPatch.
+   *
+   * @return Return croppedHeight of NPatch.
+   */
+  uint32_t GetCroppedHeight() const;
+
+  /**
+   * @brief Set border of NPatch.
+   *
+   * @param [in] border border of NPatch
+   */
+  void SetBorder(const Rect<int> border);
+
+  /**
+   * @brief Retrieve border of NPatch.
+   *
+   * @return Return border of NPatch.
+   */
+  Rect<int> GetBorder() const;
+
+  /**
+   * @brief Set whether the loaded image is premultiplied or not
+   *
+   * @param [in] preMultiplyOnLoad whether the loaded image is premultiplied or not
+   */
+  void SetPreMultiplyOnLoad(bool preMultiplyOnLoad);
+
+  /**
+   * @brief Retrieve whether the loaded image is premultiplied or not.
+   *
+   * @return Return true if the image is premultiplied alpha.
+   */
+  bool IsPreMultiplied() const;
+
+  /**
+   * @brief Set current loading state.
+   *
+   * @param [in] loadingState current loading state
+   */
+  void SetLoadingState(const LoadingState loadingState);
+
+  /**
+   * @brief Retrieve current loading state.
+   *
+   * @return Return current loading state.
+   */
+  LoadingState GetLoadingState() const;
+
+  /**
+   * @brief Retrieve NPatch rendering data.
+   *
+   * @return Return NPatch rendering data.
+   */
+  void* GetRenderingMap() const;
+
+  /**
+   * @brief Set loaded pixel buffer for the cache data.
+   *
+   * @param [in] pixelBuffer loaded pixel buffer.
+   * @param [in] preMultiplied whether the loaded image is premultiplied or not
+   */
+  void SetLoadedNPatchData(Devel::PixelBuffer& pixelBuffer, bool preMultiplied);
+
+  /**
+   * @brief Send LoadComplete notify with current setuped NPatchData
+   *
+   * @param [in] observer observer who will be got LoadComplete notify
+   * @param [in] loadSuccess whether the image load success or not.
+   */
+  void NotifyObserver(TextureUploadObserver* observer, const bool& loadSuccess);
+
+private:
+  /**
+   * @copydoc TextureUploadObserver::LoadComplete
+   *
+   * To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
+   * This callback is the place to add the renderer as it would be called once the loading is finished.
+   */
+  void LoadComplete(bool loadSuccess, TextureInformation textureInformation) override;
+
+  /**
+   * This is called by the TextureUploadObserver when an observer is destroyed.
+   * We use the callback to know when to remove an observer from our notify list.
+   * @param[in] observer The observer that generated the callback
+   */
+  void ObserverDestroyed(TextureUploadObserver* observer);
+
+private:
+  using ObserverListType = Dali::Vector<TextureUploadObserver*>;
+
+  NPatchDataId     mId;
+  ObserverListType mObserverList;    ///< Container used to store all observer clients of this Texture
+  ObserverListType mQueuedObservers; ///< Container observers when user try to add during notify observers
+
+  VisualUrl                    mUrl;            ///< Url of the N-Patch
+  TextureSet                   mTextureSet;     ///< Texture containing the cropped image
+  NPatchUtility::StretchRanges mStretchPixelsX; ///< X stretch pixels
+  NPatchUtility::StretchRanges mStretchPixelsY; ///< Y stretch pixels
+  std::size_t                  mHash;           ///< Hash code for the Url
+  uint32_t                     mCroppedWidth;   ///< Width of the cropped middle part of N-patch
+  uint32_t                     mCroppedHeight;  ///< Height of the cropped middle part of N-patch
+  Rect<int>                    mBorder;         ///< The size of the border
+  LoadingState                 mLoadingState;   ///< True if the data loading is completed
+  void*                        mRenderingMap;   ///< NPatch rendering data
+
+  bool mPreMultiplyOnLoad : 1; ///< Whether to multiply alpha into color channels on load
+  bool mObserverNotifying : 1; ///< Whether this NPatchData notifying observers or not.
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_NPATCH_DATA_H
diff --git a/dali-toolkit/internal/visuals/npatch/npatch-loader.cpp b/dali-toolkit/internal/visuals/npatch/npatch-loader.cpp
new file mode 100644 (file)
index 0000000..c99eba2
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/npatch/npatch-loader.h>
+
+// INTERNAL HEADERS
+#include <dali-toolkit/internal/visuals/rendering-addon.h>
+
+// EXTERNAL HEADERS
+#include <dali/devel-api/common/hash.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+constexpr auto INVALID_CACHE_INDEX = int32_t{-1}; ///< Invalid Cache index
+constexpr auto UNINITIALIZED_ID    = int32_t{0};  ///< uninitialised id, use to initialize ids
+
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false);
+} // Anonymous namespace
+
+NPatchLoader::NPatchLoader()
+: mCurrentNPatchDataId(0),
+  mRemoveProcessorRegistered(false)
+{
+}
+
+NPatchLoader::~NPatchLoader()
+{
+  if(mRemoveProcessorRegistered && Adaptor::IsAvailable())
+  {
+    Adaptor::Get().UnregisterProcessorOnce(*this, true);
+    mRemoveProcessorRegistered = false;
+  }
+}
+
+NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
+{
+  // Skip invalid id generation.
+  if(DALI_UNLIKELY(mCurrentNPatchDataId == NPatchData::INVALID_NPATCH_DATA_ID))
+  {
+    mCurrentNPatchDataId = 0;
+  }
+  return mCurrentNPatchDataId++;
+}
+
+NPatchData::NPatchDataId NPatchLoader::Load(TextureManager& textureManager, TextureUploadObserver* textureObserver, const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad, bool synchronousLoading)
+{
+  NPatchDataPtr data = GetNPatchData(url, border, preMultiplyOnLoad);
+
+  DALI_ASSERT_ALWAYS(data.Get() && "NPatchData creation failed!");
+
+  if(data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+  {
+    if(!synchronousLoading)
+    {
+      // NotifyObserver already done, so
+      // data will not iterate observer list.
+      // We need to call LoadComplete directly.
+      data->NotifyObserver(textureObserver, true);
+    }
+  }
+  else // if NOT_STARTED or LOADING or LOAD_FAILED, try to reload.
+  {
+    if(!synchronousLoading)
+    {
+      data->AddObserver(textureObserver);
+      // If still LOADING and async, don't need to request reload. Fast return.
+      if(data->GetLoadingState() == NPatchData::LoadingState::LOADING)
+      {
+        return data->GetId();
+      }
+    }
+
+    data->SetLoadingState(NPatchData::LoadingState::LOADING);
+
+    auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
+                                                  : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+    Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(url, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, data.Get(), true, preMultiplyOnLoading);
+
+    if(pixelBuffer)
+    {
+      preMultiplyOnLoad = (preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? true : false;
+      data->SetLoadedNPatchData(pixelBuffer, preMultiplyOnLoad);
+    }
+    else if(synchronousLoading)
+    {
+      data->SetLoadingState(NPatchData::LoadingState::LOAD_FAILED);
+    }
+  }
+  return data->GetId();
+}
+
+int32_t NPatchLoader::GetCacheIndexFromId(const NPatchData::NPatchDataId id)
+{
+  const unsigned int size = mCache.size();
+
+  for(unsigned int i = 0; i < size; ++i)
+  {
+    if(mCache[i].mData->GetId() == id)
+    {
+      return i;
+    }
+  }
+
+  return INVALID_CACHE_INDEX;
+}
+
+bool NPatchLoader::GetNPatchData(const NPatchData::NPatchDataId id, NPatchDataPtr& data)
+{
+  int32_t cacheIndex = GetCacheIndexFromId(id);
+  if(cacheIndex != INVALID_CACHE_INDEX)
+  {
+    data = mCache[cacheIndex].mData;
+    return true;
+  }
+  data = nullptr;
+  return false;
+}
+
+void NPatchLoader::RequestRemove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver)
+{
+  // Remove observer first
+  if(textureObserver)
+  {
+    int32_t cacheIndex = GetCacheIndexFromId(id);
+    if(cacheIndex != INVALID_CACHE_INDEX)
+    {
+      NPatchInfo& info(mCache[cacheIndex]);
+
+      info.mData->RemoveObserver(textureObserver);
+    }
+  }
+
+  mRemoveQueue.push_back({id, nullptr});
+
+  if(!mRemoveProcessorRegistered && Adaptor::IsAvailable())
+  {
+    mRemoveProcessorRegistered = true;
+    Adaptor::Get().RegisterProcessorOnce(*this, true);
+  }
+}
+
+void NPatchLoader::Remove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver)
+{
+  int32_t cacheIndex = GetCacheIndexFromId(id);
+  if(cacheIndex == INVALID_CACHE_INDEX)
+  {
+    return;
+  }
+
+  NPatchInfo& info(mCache[cacheIndex]);
+
+  info.mData->RemoveObserver(textureObserver);
+
+  if(--info.mReferenceCount <= 0)
+  {
+    mCache.erase(mCache.begin() + cacheIndex);
+  }
+}
+
+void NPatchLoader::Process(bool postProcessor)
+{
+  DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_NPATCH_LOADER_PROCESS_REMOVE_QUEUE", [&](std::ostringstream& oss) {
+    oss << "[" << mRemoveQueue.size() << "]";
+  });
+
+  mRemoveProcessorRegistered = false;
+
+  for(auto& iter : mRemoveQueue)
+  {
+    Remove(iter.first, iter.second);
+  }
+
+  mRemoveQueue.clear();
+
+  DALI_TRACE_END(gTraceFilter, "DALI_NPATCH_LOADER_PROCESS_REMOVE_QUEUE");
+}
+
+NPatchDataPtr NPatchLoader::GetNPatchData(const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad)
+{
+  std::size_t                              hash  = CalculateHash(url.GetUrl());
+  std::vector<NPatchInfo>::size_type       index = UNINITIALIZED_ID;
+  const std::vector<NPatchInfo>::size_type count = mCache.size();
+
+  NPatchInfo* infoPtr = nullptr;
+
+  for(; index < count; ++index)
+  {
+    if(mCache[index].mData->GetHash() == hash)
+    {
+      // hash match, check url as well in case of hash collision
+      if(mCache[index].mData->GetUrl().GetUrl() == url.GetUrl())
+      {
+        // Use cached data. Need to fast-out return.
+        if(mCache[index].mData->GetBorder() == border)
+        {
+          mCache[index].mReferenceCount++;
+          return mCache[index].mData;
+        }
+        else
+        {
+          if(mCache[index].mData->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+          {
+            // If we only found LOAD_FAILED case, replace current data. We can reuse texture
+            if(infoPtr == nullptr || infoPtr->mData->GetLoadingState() != NPatchData::LoadingState::LOAD_COMPLETE)
+            {
+              infoPtr = &mCache[index];
+            }
+          }
+          // Still loading pixel buffer. We cannot reuse cached texture yet. Skip checking
+          else if(mCache[index].mData->GetLoadingState() == NPatchData::LoadingState::LOADING)
+          {
+            continue;
+          }
+          // if LOAD_FAILED, reuse this cached NPatchData, and try to load again.
+          else
+          {
+            if(infoPtr == nullptr)
+            {
+              infoPtr = &mCache[index];
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // If this is new image loading, make new cache data
+  if(infoPtr == nullptr)
+  {
+    NPatchInfo info(new NPatchData());
+    info.mData->SetId(GenerateUniqueNPatchDataId());
+    info.mData->SetHash(hash);
+    info.mData->SetUrl(url);
+    info.mData->SetBorder(border);
+    info.mData->SetPreMultiplyOnLoad(preMultiplyOnLoad);
+
+    mCache.emplace_back(std::move(info));
+    infoPtr = &mCache.back();
+  }
+  // Else if LOAD_COMPLETE, Same url but border is different - use the existing texture
+  else if(infoPtr->mData->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+  {
+    NPatchInfo info(new NPatchData());
+
+    info.mData->SetId(GenerateUniqueNPatchDataId());
+    info.mData->SetHash(hash);
+    info.mData->SetUrl(url);
+    info.mData->SetCroppedWidth(infoPtr->mData->GetCroppedWidth());
+    info.mData->SetCroppedHeight(infoPtr->mData->GetCroppedHeight());
+
+    info.mData->SetTextures(infoPtr->mData->GetTextures());
+
+    NPatchUtility::StretchRanges stretchRangesX;
+    stretchRangesX.PushBack(Uint16Pair(border.left, ((info.mData->GetCroppedWidth() >= static_cast<unsigned int>(border.right)) ? info.mData->GetCroppedHeight() - border.right : 0)));
+
+    NPatchUtility::StretchRanges stretchRangesY;
+    stretchRangesY.PushBack(Uint16Pair(border.top, ((info.mData->GetCroppedWidth() >= static_cast<unsigned int>(border.bottom)) ? info.mData->GetCroppedHeight() - border.bottom : 0)));
+
+    info.mData->SetStretchPixelsX(stretchRangesX);
+    info.mData->SetStretchPixelsY(stretchRangesY);
+    info.mData->SetBorder(border);
+
+    info.mData->SetPreMultiplyOnLoad(infoPtr->mData->IsPreMultiplied());
+
+    info.mData->SetLoadingState(NPatchData::LoadingState::LOAD_COMPLETE);
+
+    mCache.emplace_back(std::move(info));
+    infoPtr = &mCache.back();
+  }
+  // Else, LOAD_FAILED. just increase reference so we can reuse it.
+  else
+  {
+    infoPtr->mReferenceCount++;
+  }
+
+  DALI_ASSERT_ALWAYS(infoPtr && "NPatchInfo creation failed!");
+
+  return infoPtr->mData;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/npatch/npatch-loader.h b/dali-toolkit/internal/visuals/npatch/npatch-loader.h
new file mode 100644 (file)
index 0000000..fd1a4fa
--- /dev/null
@@ -0,0 +1,197 @@
+#ifndef DALI_TOOLKIT_NPATCH_LOADER_H
+#define DALI_TOOLKIT_NPATCH_LOADER_H
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/integration-api/processor-interface.h>
+#include <dali/public-api/rendering/texture-set.h>
+#include <string>
+#include <utility> // for std::pair
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
+#include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/npatch/npatch-data.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * The manager for loading Npatch textures.
+ * It caches them internally for better performance; i.e. to avoid loading and
+ * parsing the files over and over.
+ *
+ * Cache is not cleaned during app lifecycle as N patches take considerably
+ * small space and there's not usually a lot of them. Usually N patches are specified in
+ * toolkit default style and there is 1-2 per control that are shared across the whole application.
+ */
+class NPatchLoader : public Integration::Processor
+{
+public:
+  /**
+   * Constructor
+   */
+  NPatchLoader();
+
+  /**
+   * Destructor, non-virtual as not a base class
+   */
+  ~NPatchLoader();
+
+  /**
+   * @brief Retrieve a texture matching the n-patch url.
+   *
+   * @param [in] textureManager that will be used to loading image
+   * @param [in] textureObserver The NPatchVisual that requested loading.
+   * @param [in] url to retrieve
+   * @param [in] border The border size of the image
+   * @param [in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
+   *                                   image has no alpha channel
+   * @param [in] synchronousLoading True if the image will be loaded in synchronous time.
+   * @return id of the texture.
+   */
+  NPatchData::NPatchDataId Load(TextureManager& textureManager, TextureUploadObserver* textureObserver, const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad, bool synchronousLoading);
+
+  /**
+   * @brief Retrieve N patch data matching to an id
+   * @param [in] id of data
+   * @param [out] data const pointer to the NPatchData
+   * @return true if data matching to id was really found
+   */
+  bool GetNPatchData(const NPatchData::NPatchDataId id, NPatchDataPtr& data);
+
+  /**
+   * @brief Request remove a texture matching id.
+   * Erase the observer from the observer list of cache if we need.
+   *
+   * @param [in] id cache data id
+   * @param [in] textureObserver The NPatchVisual that requested loading.
+   */
+  void RequestRemove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver);
+
+protected: // Implementation of Processor
+  /**
+   * @copydoc Dali::Integration::Processor::Process()
+   */
+  void Process(bool postProcessor) override;
+
+  /**
+   * @copydoc Dali::Integration::Processor::GetProcessorName()
+   */
+  std::string_view GetProcessorName() const override
+  {
+    return "NPatchLoader";
+  }
+
+private:
+  NPatchData::NPatchDataId GenerateUniqueNPatchDataId();
+
+  int32_t GetCacheIndexFromId(const NPatchData::NPatchDataId id);
+
+  /**
+   * @brief Remove a texture matching id.
+   * Erase the observer from the observer list of cache if we need.
+   * This API decrease cached NPatchInfo reference.
+   * If the NPatchInfo reference become 0, the textureSet will be reset.
+   *
+   * @param [in] id cache data id
+   * @param [in] textureObserver The NPatchVisual that requested loading.
+   */
+  void Remove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver);
+
+private:
+  /**
+   * @brief Information of NPatchData
+   * It also hold ownership of NPatchData memory.
+   */
+  struct NPatchInfo
+  {
+    NPatchInfo(NPatchDataPtr data)
+    : mData(data),
+      mReferenceCount(1u)
+    {
+    }
+    ~NPatchInfo()
+    {
+    }
+    NPatchInfo(NPatchInfo&& info) noexcept // move constructor
+    {
+      mData                = std::move(info.mData);
+      mReferenceCount      = info.mReferenceCount;
+      info.mReferenceCount = 0u;
+    }
+    NPatchInfo& operator=(NPatchInfo&& info) noexcept // move operator
+    {
+      mData                = std::move(info.mData);
+      mReferenceCount      = info.mReferenceCount;
+      info.mReferenceCount = 0u;
+      return *this;
+    }
+
+    NPatchInfo()                       = delete;            // Do not use default constructor
+    NPatchInfo(const NPatchInfo& info) = delete;            // Do not use copy constructor
+    NPatchInfo& operator=(const NPatchInfo& info) = delete; // Do not use copy assign
+
+    NPatchDataPtr mData;
+    std::int16_t  mReferenceCount; ///< The number of N-patch visuals that use this data.
+  };
+
+  /**
+   * @brief Get cached NPatchData by inputed url and border. If there is no cached data, create new one.
+   * @note This API increase cached NPatchInfo reference.
+   *
+   * @param [in] url to retrieve
+   * @param [in] border The border size of the image
+   * @param [in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
+   *                                   image has no alpha channel
+   * @return NPatchData pointer that Load function will used.
+   */
+  NPatchDataPtr GetNPatchData(const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad);
+
+protected:
+  /**
+   * Undefined copy constructor.
+   */
+  NPatchLoader(const NPatchLoader&);
+
+  /**
+   * Undefined assignment operator.
+   */
+  NPatchLoader& operator=(const NPatchLoader& rhs);
+
+private:
+  NPatchData::NPatchDataId mCurrentNPatchDataId;
+  std::vector<NPatchInfo>  mCache;
+
+  std::vector<std::pair<NPatchData::NPatchDataId, TextureUploadObserver*>> mRemoveQueue; ///< Queue of textures to remove at PostProcess. It will be cleared after PostProcess.
+
+  bool mRemoveProcessorRegistered : 1; ///< Flag if remove processor registered or not.
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_NPATCH_LOADER_H
index dba0a1673b8691dd4987fb01e6ec49b2a9b325d4..f6cbe2fb79a484429ef6dab36d08678958b90a1b 100644 (file)
 #include <dali-toolkit/devel-api/utility/npatch-helper.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
-#include <dali-toolkit/internal/visuals/npatch-loader.h>
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
+#include <dali-toolkit/internal/visuals/npatch/npatch-loader.h>
 #include <dali-toolkit/internal/visuals/rendering-addon.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
index 773e69bdd5eaafa3ae168a74640342fa98ae21bf..85ff47939ca709f56d76e19a9457831d51079aac 100644 (file)
@@ -19,9 +19,9 @@
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h>
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-feature-builder.h>
 #include <dali-toolkit/internal/visuals/svg/svg-task.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
diff --git a/dali-toolkit/internal/visuals/text-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/text-visual-shader-factory.cpp
deleted file mode 100644 (file)
index 365de2f..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/visuals/text-visual-shader-factory.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
-#include <dali-toolkit/internal/visuals/visual-string-constants.h>
-#include <dali/integration-api/debug.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace
-{
-// enum of required list when we select shader
-enum class TextVisualRequireFlag : uint32_t
-{
-  DEFAULT     = 0,
-  STYLES      = 1 << 0,
-  OVERLAY     = 1 << 1,
-  EMOJI       = 1 << 2,
-  MULTI_COLOR = 1 << 3,
-};
-
-const VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[] =
-  {
-    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT,
-    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE,
-    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY,
-    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
-    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_EMOJI,
-    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_EMOJI,
-    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY_AND_EMOJI,
-    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY_AND_EMOJI,
-    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT,
-    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE,
-    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_OVERLAY,
-    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
-};
-
-static constexpr auto      SHADER_TYPE_COUNT = 1u;
-constexpr std::string_view VertexPredefines[SHADER_TYPE_COUNT]{
-  "", // VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT
-};
-constexpr std::string_view FragmentPredefines[SHADER_TYPE_COUNT]{
-  "", // VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT
-};
-constexpr VisualFactoryCache::ShaderType ShaderTypePredefines[SHADER_TYPE_COUNT]{
-  VisualFactoryCache::ShaderType::TEXT_SHADER_SINGLE_COLOR_TEXT,
-};
-
-} // unnamed namespace
-
-namespace TextVisualShaderFeature
-{
-FeatureBuilder& FeatureBuilder::EnableMultiColor(bool enableMultiColor)
-{
-  mTextMultiColor = enableMultiColor ? TextMultiColor::MULTI_COLOR_TEXT : TextMultiColor::SINGLE_COLOR_TEXT;
-  return *this;
-}
-FeatureBuilder& FeatureBuilder::EnableEmoji(bool enableEmoji)
-{
-  mTextEmoji = enableEmoji ? TextEmoji::HAS_EMOJI : TextEmoji::NO_EMOJI;
-  return *this;
-}
-FeatureBuilder& FeatureBuilder::EnableStyle(bool enableStyle)
-{
-  mTextStyle = enableStyle ? TextStyle::HAS_STYLES : TextStyle::NO_STYLES;
-  return *this;
-}
-FeatureBuilder& FeatureBuilder::EnableOverlay(bool enableOverlay)
-{
-  mTextOverlay = enableOverlay ? TextOverlay::HAS_OVERLAY : TextOverlay::NO_OVERLAY;
-  return *this;
-}
-} // namespace TextVisualShaderFeature
-
-TextVisualShaderFactory::TextVisualShaderFactory()
-{
-}
-
-TextVisualShaderFactory::~TextVisualShaderFactory()
-{
-}
-
-Shader TextVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder)
-{
-  Shader                         shader;
-  uint32_t                       shaderTypeFlag = static_cast<uint32_t>(TextVisualRequireFlag::DEFAULT);
-  VisualFactoryCache::ShaderType shaderType     = VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT;
-
-  const auto& multiColor = featureBuilder.mTextMultiColor;
-  const auto& emoji      = featureBuilder.mTextEmoji;
-  const auto& style      = featureBuilder.mTextStyle;
-  const auto& overlay    = featureBuilder.mTextOverlay;
-
-  if(style == TextVisualShaderFeature::TextStyle::HAS_STYLES)
-  {
-    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::STYLES);
-  }
-  if(overlay == TextVisualShaderFeature::TextOverlay::HAS_OVERLAY)
-  {
-    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::OVERLAY);
-  }
-  // multi color can also render emoji. If multi color text, dont consider emoji
-  if(multiColor != TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT && emoji == TextVisualShaderFeature::TextEmoji::HAS_EMOJI)
-  {
-    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::EMOJI);
-  }
-  if(multiColor == TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT)
-  {
-    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::MULTI_COLOR);
-  }
-
-  shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
-  shader     = factoryCache.GetShader(shaderType);
-
-  if(!shader)
-  {
-    std::string vertexShaderPrefixList;
-    std::string fragmentShaderPrefixList;
-
-    if(style == TextVisualShaderFeature::TextStyle::HAS_STYLES)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_STYLE\n";
-    }
-    if(overlay == TextVisualShaderFeature::TextOverlay::HAS_OVERLAY)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_OVERLAY\n";
-    }
-    // multi color can also render emoji. If multi color text, dont consider emoji
-    if(multiColor != TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT && emoji == TextVisualShaderFeature::TextEmoji::HAS_EMOJI)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_EMOJI\n";
-    }
-    if(multiColor == TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT)
-    {
-      fragmentShaderPrefixList += "#define IS_REQUIRED_MULTI_COLOR\n";
-    }
-
-    std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_TEXT_VISUAL_SHADER_VERT.data());
-    std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_TEXT_VISUAL_SHADER_FRAG.data());
-
-    shader = factoryCache.GenerateAndSaveShader(shaderType, vertexShader, fragmentShader);
-  }
-  return shader;
-}
-
-void TextVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
-{
-  std::vector<std::string_view> vertexPrefix;
-  std::vector<std::string_view> fragmentPrefix;
-  std::vector<std::string_view> shaderName;
-  int                           shaderCount = 0;
-  for(uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i)
-  {
-    vertexPrefix.push_back(VertexPredefines[i]);
-    fragmentPrefix.push_back(FragmentPredefines[i]);
-    shaderName.push_back(Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(ShaderTypePredefines[i], VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
-    shaderCount++;
-  }
-
-  shaders.vertexPrefix   = vertexPrefix;
-  shaders.fragmentPrefix = fragmentPrefix;
-  shaders.shaderName     = shaderName;
-  shaders.vertexShader   = SHADER_TEXT_VISUAL_SHADER_VERT;
-  shaders.fragmentShader = SHADER_TEXT_VISUAL_SHADER_FRAG;
-  shaders.shaderCount    = shaderCount;
-}
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/text-visual-shader-factory.h b/dali-toolkit/internal/visuals/text-visual-shader-factory.h
deleted file mode 100644 (file)
index ba4f606..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
-#define DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
-#include <string_view>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-/**
- * TextVisualShaderFeature contains feature lists what text visual shader need to know.
- */
-namespace TextVisualShaderFeature
-{
-namespace TextMultiColor
-{
-/**
- * @brief Whether text contains single color or not.
- */
-enum Type
-{
-  SINGLE_COLOR_TEXT = 0, ///< The text contains single color only.
-  MULTI_COLOR_TEXT       ///< The text contains multiple colors.
-};
-} // namespace TextMultiColor
-
-namespace TextEmoji
-{
-/**
- * @brief Whether text contains emoji or not.
- */
-enum Type
-{
-  NO_EMOJI = 0, ///< The text contains no emoji.
-  HAS_EMOJI     ///< The text contains emoji.
-};
-} // namespace TextEmoji
-
-namespace TextStyle
-{
-/**
- * @brief Whether text contains styles (like shadow or background color) or not.
- */
-enum Type
-{
-  NO_STYLES = 0, ///< The text contains contains no styles.
-  HAS_STYLES     ///< The text contains contains styles.
-};
-} // namespace TextStyle
-
-namespace TextOverlay
-{
-/**
- * @brief Whether text contains overlay styles (like markdown) or not.
- */
-enum Type
-{
-  NO_OVERLAY = 0, ///< The text contains contains no overlay.
-  HAS_OVERLAY     ///< The text contains contains overlay.
-};
-} // namespace TextOverlay
-
-/**
- * @brief Collection of current text visual feature.
- */
-struct FeatureBuilder
-{
-  FeatureBuilder()
-  : mTextMultiColor(TextMultiColor::SINGLE_COLOR_TEXT),
-    mTextEmoji(TextEmoji::NO_EMOJI),
-    mTextStyle(TextStyle::NO_STYLES),
-    mTextOverlay(TextOverlay::NO_OVERLAY)
-  {
-  }
-
-  FeatureBuilder& EnableMultiColor(bool enableMultiColor);
-  FeatureBuilder& EnableEmoji(bool enableEmoji);
-  FeatureBuilder& EnableStyle(bool enableStyle);
-  FeatureBuilder& EnableOverlay(bool enableOverlay);
-
-  bool IsEnabledMultiColor() const
-  {
-    return mTextMultiColor == TextMultiColor::MULTI_COLOR_TEXT;
-  }
-  bool IsEnabledEmoji() const
-  {
-    return mTextEmoji == TextEmoji::HAS_EMOJI;
-  }
-  bool IsEnabledStyle() const
-  {
-    return mTextStyle == TextStyle::HAS_STYLES;
-  }
-  bool IsEnabledOverlay() const
-  {
-    return mTextOverlay == TextOverlay::HAS_OVERLAY;
-  }
-
-  TextMultiColor::Type mTextMultiColor : 2; ///< Whether text has multiple color, or not. default as TextMultiColor::SINGLE_COLOR_TEXT
-  TextEmoji::Type      mTextEmoji : 2;      ///< Whether text has emoji, or not. default as TextEmoji::NO_EMOJI
-  TextStyle::Type      mTextStyle : 2;      ///< Whether text has style, or not. default as TextStyle::NO_STYLES
-  TextOverlay::Type    mTextOverlay : 2;    ///< Whether text has overlay style, or not. default as TextOverlay::NO_OVERLAY
-};
-
-} // namespace TextVisualShaderFeature
-
-/**
- * TextVisualShaderFactory is an object that provides and shares shaders for text visuals
- */
-class TextVisualShaderFactory
-{
-public:
-  /**
-   * @brief Constructor
-   */
-  TextVisualShaderFactory();
-
-  /**
-   * @brief Destructor
-   */
-  ~TextVisualShaderFactory();
-
-  /**
-   * @brief Get the standard text rendering shader.
-   * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
-   * @param[in] featureBuilder Collection of current text shader's features
-   * @return The standard text rendering shader with features.
-   */
-  Shader GetShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder);
-
-  /**
-   * @brief Get the default shader source.
-   * @param[in] shaders shaderList for precompile
-   */
-  void GetPreCompiledShader(RawShaderData& shaders);
-
-protected:
-  /**
-   * Undefined copy constructor.
-   */
-  TextVisualShaderFactory(const TextVisualShaderFactory&);
-
-  /**
-   * Undefined assignment operator.
-   */
-  TextVisualShaderFactory& operator=(const TextVisualShaderFactory& rhs);
-
-private:
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
diff --git a/dali-toolkit/internal/visuals/text/text-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/text/text-visual-shader-factory.cpp
new file mode 100644 (file)
index 0000000..693c39e
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/text/text-visual-shader-factory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+// enum of required list when we select shader
+enum class TextVisualRequireFlag : uint32_t
+{
+  DEFAULT     = 0,
+  STYLES      = 1 << 0,
+  OVERLAY     = 1 << 1,
+  EMOJI       = 1 << 2,
+  MULTI_COLOR = 1 << 3,
+};
+
+const VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[] =
+  {
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_EMOJI,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_EMOJI,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY_AND_EMOJI,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY_AND_EMOJI,
+    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT,
+    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE,
+    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_OVERLAY,
+    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
+};
+
+static constexpr auto      SHADER_TYPE_COUNT = 1u;
+constexpr std::string_view VertexPredefines[SHADER_TYPE_COUNT]{
+  "", // VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT
+};
+constexpr std::string_view FragmentPredefines[SHADER_TYPE_COUNT]{
+  "", // VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT
+};
+constexpr VisualFactoryCache::ShaderType ShaderTypePredefines[SHADER_TYPE_COUNT]{
+  VisualFactoryCache::ShaderType::TEXT_SHADER_SINGLE_COLOR_TEXT,
+};
+
+} // unnamed namespace
+
+namespace TextVisualShaderFeature
+{
+FeatureBuilder& FeatureBuilder::EnableMultiColor(bool enableMultiColor)
+{
+  mTextMultiColor = enableMultiColor ? TextMultiColor::MULTI_COLOR_TEXT : TextMultiColor::SINGLE_COLOR_TEXT;
+  return *this;
+}
+FeatureBuilder& FeatureBuilder::EnableEmoji(bool enableEmoji)
+{
+  mTextEmoji = enableEmoji ? TextEmoji::HAS_EMOJI : TextEmoji::NO_EMOJI;
+  return *this;
+}
+FeatureBuilder& FeatureBuilder::EnableStyle(bool enableStyle)
+{
+  mTextStyle = enableStyle ? TextStyle::HAS_STYLES : TextStyle::NO_STYLES;
+  return *this;
+}
+FeatureBuilder& FeatureBuilder::EnableOverlay(bool enableOverlay)
+{
+  mTextOverlay = enableOverlay ? TextOverlay::HAS_OVERLAY : TextOverlay::NO_OVERLAY;
+  return *this;
+}
+} // namespace TextVisualShaderFeature
+
+TextVisualShaderFactory::TextVisualShaderFactory()
+{
+}
+
+TextVisualShaderFactory::~TextVisualShaderFactory()
+{
+}
+
+Shader TextVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder)
+{
+  Shader                         shader;
+  uint32_t                       shaderTypeFlag = static_cast<uint32_t>(TextVisualRequireFlag::DEFAULT);
+  VisualFactoryCache::ShaderType shaderType     = VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT;
+
+  const auto& multiColor = featureBuilder.mTextMultiColor;
+  const auto& emoji      = featureBuilder.mTextEmoji;
+  const auto& style      = featureBuilder.mTextStyle;
+  const auto& overlay    = featureBuilder.mTextOverlay;
+
+  if(style == TextVisualShaderFeature::TextStyle::HAS_STYLES)
+  {
+    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::STYLES);
+  }
+  if(overlay == TextVisualShaderFeature::TextOverlay::HAS_OVERLAY)
+  {
+    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::OVERLAY);
+  }
+  // multi color can also render emoji. If multi color text, dont consider emoji
+  if(multiColor != TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT && emoji == TextVisualShaderFeature::TextEmoji::HAS_EMOJI)
+  {
+    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::EMOJI);
+  }
+  if(multiColor == TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT)
+  {
+    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::MULTI_COLOR);
+  }
+
+  shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
+  shader     = factoryCache.GetShader(shaderType);
+
+  if(!shader)
+  {
+    std::string vertexShaderPrefixList;
+    std::string fragmentShaderPrefixList;
+
+    if(style == TextVisualShaderFeature::TextStyle::HAS_STYLES)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_STYLE\n";
+    }
+    if(overlay == TextVisualShaderFeature::TextOverlay::HAS_OVERLAY)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_OVERLAY\n";
+    }
+    // multi color can also render emoji. If multi color text, dont consider emoji
+    if(multiColor != TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT && emoji == TextVisualShaderFeature::TextEmoji::HAS_EMOJI)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_EMOJI\n";
+    }
+    if(multiColor == TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_MULTI_COLOR\n";
+    }
+
+    std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_TEXT_VISUAL_SHADER_VERT.data());
+    std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_TEXT_VISUAL_SHADER_FRAG.data());
+
+    shader = factoryCache.GenerateAndSaveShader(shaderType, vertexShader, fragmentShader);
+  }
+  return shader;
+}
+
+void TextVisualShaderFactory::GetPreCompiledShader(RawShaderData& shaders)
+{
+  std::vector<std::string_view> vertexPrefix;
+  std::vector<std::string_view> fragmentPrefix;
+  std::vector<std::string_view> shaderName;
+  int                           shaderCount = 0;
+  for(uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i)
+  {
+    vertexPrefix.push_back(VertexPredefines[i]);
+    fragmentPrefix.push_back(FragmentPredefines[i]);
+    shaderName.push_back(Scripting::GetLinearEnumerationName<VisualFactoryCache::ShaderType>(ShaderTypePredefines[i], VISUAL_SHADER_TYPE_TABLE, VISUAL_SHADER_TYPE_TABLE_COUNT));
+    shaderCount++;
+  }
+
+  shaders.vertexPrefix   = vertexPrefix;
+  shaders.fragmentPrefix = fragmentPrefix;
+  shaders.shaderName     = shaderName;
+  shaders.vertexShader   = SHADER_TEXT_VISUAL_SHADER_VERT;
+  shaders.fragmentShader = SHADER_TEXT_VISUAL_SHADER_FRAG;
+  shaders.shaderCount    = shaderCount;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/text/text-visual-shader-factory.h b/dali-toolkit/internal/visuals/text/text-visual-shader-factory.h
new file mode 100644 (file)
index 0000000..237edc7
--- /dev/null
@@ -0,0 +1,179 @@
+#ifndef DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
+#define DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/shader-precompiler.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+#include <string_view>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * TextVisualShaderFeature contains feature lists what text visual shader need to know.
+ */
+namespace TextVisualShaderFeature
+{
+namespace TextMultiColor
+{
+/**
+ * @brief Whether text contains single color or not.
+ */
+enum Type
+{
+  SINGLE_COLOR_TEXT = 0, ///< The text contains single color only.
+  MULTI_COLOR_TEXT       ///< The text contains multiple colors.
+};
+} // namespace TextMultiColor
+
+namespace TextEmoji
+{
+/**
+ * @brief Whether text contains emoji or not.
+ */
+enum Type
+{
+  NO_EMOJI = 0, ///< The text contains no emoji.
+  HAS_EMOJI     ///< The text contains emoji.
+};
+} // namespace TextEmoji
+
+namespace TextStyle
+{
+/**
+ * @brief Whether text contains styles (like shadow or background color) or not.
+ */
+enum Type
+{
+  NO_STYLES = 0, ///< The text contains contains no styles.
+  HAS_STYLES     ///< The text contains contains styles.
+};
+} // namespace TextStyle
+
+namespace TextOverlay
+{
+/**
+ * @brief Whether text contains overlay styles (like markdown) or not.
+ */
+enum Type
+{
+  NO_OVERLAY = 0, ///< The text contains contains no overlay.
+  HAS_OVERLAY     ///< The text contains contains overlay.
+};
+} // namespace TextOverlay
+
+/**
+ * @brief Collection of current text visual feature.
+ */
+struct FeatureBuilder
+{
+  FeatureBuilder()
+  : mTextMultiColor(TextMultiColor::SINGLE_COLOR_TEXT),
+    mTextEmoji(TextEmoji::NO_EMOJI),
+    mTextStyle(TextStyle::NO_STYLES),
+    mTextOverlay(TextOverlay::NO_OVERLAY)
+  {
+  }
+
+  FeatureBuilder& EnableMultiColor(bool enableMultiColor);
+  FeatureBuilder& EnableEmoji(bool enableEmoji);
+  FeatureBuilder& EnableStyle(bool enableStyle);
+  FeatureBuilder& EnableOverlay(bool enableOverlay);
+
+  bool IsEnabledMultiColor() const
+  {
+    return mTextMultiColor == TextMultiColor::MULTI_COLOR_TEXT;
+  }
+  bool IsEnabledEmoji() const
+  {
+    return mTextEmoji == TextEmoji::HAS_EMOJI;
+  }
+  bool IsEnabledStyle() const
+  {
+    return mTextStyle == TextStyle::HAS_STYLES;
+  }
+  bool IsEnabledOverlay() const
+  {
+    return mTextOverlay == TextOverlay::HAS_OVERLAY;
+  }
+
+  TextMultiColor::Type mTextMultiColor : 2; ///< Whether text has multiple color, or not. default as TextMultiColor::SINGLE_COLOR_TEXT
+  TextEmoji::Type      mTextEmoji : 2;      ///< Whether text has emoji, or not. default as TextEmoji::NO_EMOJI
+  TextStyle::Type      mTextStyle : 2;      ///< Whether text has style, or not. default as TextStyle::NO_STYLES
+  TextOverlay::Type    mTextOverlay : 2;    ///< Whether text has overlay style, or not. default as TextOverlay::NO_OVERLAY
+};
+
+} // namespace TextVisualShaderFeature
+
+/**
+ * TextVisualShaderFactory is an object that provides and shares shaders for text visuals
+ */
+class TextVisualShaderFactory
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  TextVisualShaderFactory();
+
+  /**
+   * @brief Destructor
+   */
+  ~TextVisualShaderFactory();
+
+  /**
+   * @brief Get the standard text rendering shader.
+   * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] featureBuilder Collection of current text shader's features
+   * @return The standard text rendering shader with features.
+   */
+  Shader GetShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder);
+
+  /**
+   * @brief Get the default shader source.
+   * @param[in] shaders shaderList for precompile
+   */
+  void GetPreCompiledShader(RawShaderData& shaders);
+
+protected:
+  /**
+   * Undefined copy constructor.
+   */
+  TextVisualShaderFactory(const TextVisualShaderFactory&);
+
+  /**
+   * Undefined assignment operator.
+   */
+  TextVisualShaderFactory& operator=(const TextVisualShaderFactory& rhs);
+
+private:
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
index ec51c0065ee94457c3fa0ea2f027ac82611fcf6c..55296d6a3707a83e92347744ef09f8dd03edc9c1 100644 (file)
@@ -36,7 +36,7 @@
 #include <dali-toolkit/internal/text/text-effects-style.h>
 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
@@ -279,7 +279,7 @@ void TextVisual::OnInitialize()
   mImpl->mRenderer = VisualRenderer::New(geometry, shader);
   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
   mTextRequireRenderPropertyIndex = mImpl->mRenderer.RegisterUniqueProperty("requireRender", mTextRequireRender);
-  mHasMultipleTextColorsIndex = mImpl->mRenderer.RegisterUniqueProperty("uHasMultipleTextColors", static_cast<float>(false));
+  mHasMultipleTextColorsIndex     = mImpl->mRenderer.RegisterUniqueProperty("uHasMultipleTextColors", static_cast<float>(false));
 }
 
 void TextVisual::DoSetProperties(const Property::Map& propertyMap)
@@ -507,7 +507,7 @@ void TextVisual::UpdateRenderer()
   const bool isWidthRelative  = fabsf(mImpl->mTransform.mOffsetSizeMode.z) < Math::MACHINE_EPSILON_1000;
   const bool isHeightRelative = fabsf(mImpl->mTransform.mOffsetSizeMode.w) < Math::MACHINE_EPSILON_1000;
 
-  const float controlWidth = mImpl->mControlSize.width;
+  const float controlWidth  = mImpl->mControlSize.width;
   const float controlHeight = mImpl->mControlSize.height;
 
   // Round the size and offset to avoid pixel alignement issues.
@@ -573,28 +573,28 @@ void TextVisual::UpdateRenderer()
         shadowEnabled = true;
       }
 
-      const bool outlineEnabled               = (mController->GetTextModel()->GetOutlineWidth() > Math::MACHINE_EPSILON_1);
-      const bool backgroundEnabled            = mController->GetTextModel()->IsBackgroundEnabled();
-      const bool markupOrSpannedText          = mController->IsMarkupProcessorEnabled() || mController->GetTextModel()->IsSpannedTextPlaced();
-      const bool markupUnderlineEnabled       = markupOrSpannedText && mController->GetTextModel()->IsMarkupUnderlineSet();
-      const bool markupStrikethroughEnabled   = markupOrSpannedText && mController->GetTextModel()->IsMarkupStrikethroughSet();
-      const bool underlineEnabled             = mController->GetTextModel()->IsUnderlineEnabled() || markupUnderlineEnabled;
-      const bool strikethroughEnabled         = mController->GetTextModel()->IsStrikethroughEnabled() || markupStrikethroughEnabled;
-      const bool backgroundMarkupSet          = mController->GetTextModel()->IsMarkupBackgroundColorSet();
-      const bool cutoutEnabled                = mController->IsTextCutout();
-      const bool backgroundWithCutoutEnabled  = mController->GetTextModel()->IsBackgroundWithCutoutEnabled();
-      const bool styleEnabled                 = (shadowEnabled || outlineEnabled || backgroundEnabled || markupOrSpannedText || backgroundMarkupSet || cutoutEnabled || backgroundWithCutoutEnabled);
-      const bool isOverlayStyle               = underlineEnabled || strikethroughEnabled;
+      const bool outlineEnabled              = (mController->GetTextModel()->GetOutlineWidth() > Math::MACHINE_EPSILON_1);
+      const bool backgroundEnabled           = mController->GetTextModel()->IsBackgroundEnabled();
+      const bool markupOrSpannedText         = mController->IsMarkupProcessorEnabled() || mController->GetTextModel()->IsSpannedTextPlaced();
+      const bool markupUnderlineEnabled      = markupOrSpannedText && mController->GetTextModel()->IsMarkupUnderlineSet();
+      const bool markupStrikethroughEnabled  = markupOrSpannedText && mController->GetTextModel()->IsMarkupStrikethroughSet();
+      const bool underlineEnabled            = mController->GetTextModel()->IsUnderlineEnabled() || markupUnderlineEnabled;
+      const bool strikethroughEnabled        = mController->GetTextModel()->IsStrikethroughEnabled() || markupStrikethroughEnabled;
+      const bool backgroundMarkupSet         = mController->GetTextModel()->IsMarkupBackgroundColorSet();
+      const bool cutoutEnabled               = mController->IsTextCutout();
+      const bool backgroundWithCutoutEnabled = mController->GetTextModel()->IsBackgroundWithCutoutEnabled();
+      const bool styleEnabled                = (shadowEnabled || outlineEnabled || backgroundEnabled || markupOrSpannedText || backgroundMarkupSet || cutoutEnabled || backgroundWithCutoutEnabled);
+      const bool isOverlayStyle              = underlineEnabled || strikethroughEnabled;
 
       // if background with cutout is enabled, This text visual must render the entire control size.
 
       if(cutoutEnabled)
       {
-        relayoutSize = Vector2(controlWidth, controlHeight);
-        mImpl->mTransform.mSize.width = controlWidth;
+        relayoutSize                   = Vector2(controlWidth, controlHeight);
+        mImpl->mTransform.mSize.width  = controlWidth;
         mImpl->mTransform.mSize.height = controlHeight;
-        mImpl->mTransform.mOffset.x = 0;
-        mImpl->mTransform.mOffset.y = 0;
+        mImpl->mTransform.mOffset.x    = 0;
+        mImpl->mTransform.mOffset.y    = 0;
       }
 
       AddRenderer(control, relayoutSize, hasMultipleTextColors, containsColorGlyph, styleEnabled, isOverlayStyle);
@@ -832,20 +832,20 @@ TextureSet TextVisual::GetTextTexture(const Vector2& size)
   Pixel::Format textPixelFormat = (mTextShaderFeatureCache.IsEnabledEmoji() || mTextShaderFeatureCache.IsEnabledMultiColor() || cutoutEnabled) ? Pixel::RGBA8888 : Pixel::L8;
 
   // Check the text direction
-  Toolkit::DevelText::TextDirection::Type textDirection = mController->GetTextDirection();
-  uint32_t textureSetIndex = 0u;
+  Toolkit::DevelText::TextDirection::Type textDirection   = mController->GetTextDirection();
+  uint32_t                                textureSetIndex = 0u;
   // Create a texture for the text without any styles
 
   Devel::PixelBuffer cutoutData;
-  float cutoutAlpha = mController->GetTextModel()->GetDefaultColor().a;
+  float              cutoutAlpha = mController->GetTextModel()->GetDefaultColor().a;
   if(cutoutEnabled)
   {
     cutoutData = mTypesetter->RenderWithPixelBuffer(size, textDirection, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat);
 
     // Make transparent buffer.
     // If the cutout is enabled, a separate texture is not used for the text.
-    Devel::PixelBuffer buffer = mTypesetter->CreateFullBackgroundBuffer(1, 1, Vector4(0.f, 0.f ,0.f ,0.f));
-    PixelData data = Devel::PixelBuffer::Convert(buffer);
+    Devel::PixelBuffer buffer = mTypesetter->CreateFullBackgroundBuffer(1, 1, Vector4(0.f, 0.f, 0.f, 0.f));
+    PixelData          data   = Devel::PixelBuffer::Convert(buffer);
     AddTexture(textureSet, data, sampler, textureSetIndex);
     ++textureSetIndex;
   }
@@ -856,7 +856,6 @@ TextureSet TextVisual::GetTextTexture(const Vector2& size)
     ++textureSetIndex;
   }
 
-
   if(mTextShaderFeatureCache.IsEnabledStyle())
   {
     // Create RGBA texture for all the text styles that render in the background (without the text itself)
index 0d5e5f863887839b242426b7e1a368f255dcaa84..b404b0c9f52054015e4e9892aa3d113b2e11cbb7 100644 (file)
@@ -27,7 +27,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
-#include <dali-toolkit/internal/visuals/text-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/text/text-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 
 namespace Dali
index e8b5dbfd1bc86dafe0a77c79c8973ea0fbcae5b7..afc37846cc12098d1de5e977a4d7230c64e16144 100644 (file)
@@ -31,7 +31,7 @@
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/image/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 
index 1b3f098a6fd1f235f8725c03be226b29efc9c41f..8a9f1334117c196e1d42c5413b0c506095a1b4d4 100644 (file)
@@ -18,8 +18,6 @@
  */
 
 // EXTERNAL INCLUDES
-#include <dali/devel-api/common/owner-container.h>
-#include <dali/integration-api/adaptor-framework/shader-precompiler.h>
 #include <dali/public-api/math/uint-16-pair.h>
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/rendering/geometry.h>
@@ -27,7 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
-#include <dali-toolkit/internal/visuals/npatch-loader.h>
+#include <dali-toolkit/internal/visuals/npatch/npatch-loader.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 
 namespace Dali
index b060d423eb6f4de14184a7149f232978f3846c94..1b0a44e3b65c8608f871aa1336eca5b8076e8921 100644 (file)
 #include <dali-toolkit/internal/visuals/border/border-visual.h>
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
 #include <dali-toolkit/internal/visuals/gradient/gradient-visual.h>
-#include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/image/image-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/image/image-visual.h>
 #include <dali-toolkit/internal/visuals/mesh/mesh-visual.h>
 #include <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
 #include <dali-toolkit/internal/visuals/primitive/primitive-visual.h>
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
-#include <dali-toolkit/internal/visuals/text-visual-shader-factory.h>
+#include <dali-toolkit/internal/visuals/text/text-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/text/text-visual.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>