[dali_2.2.19] Merge branch 'devel/master' 35/290435/1
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 24 Mar 2023 10:55:37 +0000 (10:55 +0000)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 24 Mar 2023 10:55:37 +0000 (10:55 +0000)
Change-Id: Id1e95c37bd576e143712a7e0ca615f9042082bb3

42 files changed:
automated-tests/src/dali-scene3d-internal/utc-Dali-DliLoaderImpl.cpp
automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Accessible.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp
dali-scene3d/internal/common/environment-map-load-task.cpp
dali-scene3d/internal/common/environment-map-load-task.h
dali-scene3d/internal/common/image-based-light-observer.h
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/model/model-impl.h
dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp
dali-scene3d/internal/controls/scene-view/scene-view-impl.h
dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag
dali-scene3d/internal/loader/gltf2-asset.cpp
dali-scene3d/internal/loader/gltf2-util.cpp
dali-scene3d/internal/loader/json-util.cpp
dali-scene3d/public-api/controls/model/model.cpp
dali-scene3d/public-api/controls/model/model.h
dali-scene3d/public-api/controls/scene-view/scene-view.h
dali-scene3d/public-api/loader/alpha-function-helper.cpp
dali-scene3d/public-api/loader/environment-definition.cpp
dali-scene3d/public-api/loader/environment-definition.h
dali-scene3d/public-api/loader/environment-map-data.h
dali-scene3d/public-api/loader/environment-map-loader.cpp
dali-scene3d/public-api/loader/ktx-loader.cpp
dali-scene3d/public-api/loader/material-definition.cpp
dali-scene3d/public-api/loader/node-definition.cpp
dali-scene3d/public-api/loader/node-definition.h
dali-scene3d/public-api/loader/parse-renderer-state.cpp
dali-scene3d/public-api/loader/scene-definition.cpp
dali-scene3d/public-api/loader/shader-definition-factory.cpp
dali-toolkit/devel-api/controls/control-accessible.cpp
dali-toolkit/internal/styling/style-manager-impl.cpp
dali-toolkit/internal/text/controller/text-controller-relayouter.cpp
dali-toolkit/internal/text/multi-language-support-impl.cpp
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 0610deb..e23616e 100644 (file)
@@ -182,6 +182,7 @@ int UtcDaliDliLoaderLoadSceneAssertions(void)
 
 int UtcDaliDliLoaderLoadSceneExercise(void)
 {
+  TestApplication app;
   Context ctx;
 
   auto path = ctx.pathProvider(ResourceType::Mesh) + "exercise.dli";
@@ -219,8 +220,6 @@ int UtcDaliDliLoaderLoadSceneExercise(void)
 
   Customization::Choices choices;
 
-  TestApplication app;
-
   Actor root = Actor::New();
   SetActorCentered(root);
   for(auto iRoot : scene.GetRoots())
index b305a41..03d2f97 100644 (file)
@@ -631,6 +631,7 @@ int UtcDaliGltfLoaderMRendererTest(void)
 
 int UtcDaliGltfLoaderAnimationLoadingTest(void)
 {
+  TestApplication app;
   Context ctx;
 
   auto& resources = ctx.resources;
@@ -652,8 +653,6 @@ int UtcDaliGltfLoaderAnimationLoadingTest(void)
 
   Customization::Choices choices;
 
-  TestApplication app;
-
   Actor root = Actor::New();
   SetActorCentered(root);
   for(auto iRoot : roots)
index 60e1892..f76c4a0 100644 (file)
@@ -114,7 +114,7 @@ int UtcDaliAccessibilityCheckShowingState(void)
   q = Dali::Accessibility::Accessible::Get(buttonB);
   DALI_TEST_CHECK(q);
   states = q->GetStates();
-  DALI_TEST_EQUALS((int) states[Dali::Accessibility::State::SHOWING], (int) false, TEST_LOCATION);
+  DALI_TEST_EQUALS((int) states[Dali::Accessibility::State::SHOWING], (int) true, TEST_LOCATION);
 
   q = Dali::Accessibility::Accessible::Get(buttonC);
   DALI_TEST_CHECK(q);
index 04d193c..319ec67 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
@@ -1214,7 +1214,7 @@ Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(con
       source.resize(graphicsShader->mCreateInfo.sourceSize);
       memcpy(&source[0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
 
-      if(!std::equal(source.begin(), source.end(), cacheEntry.shaders[shader.pipelineStage].begin()))
+      if(!std::equal(source.begin(), source.end(), cacheEntry.shaders[shader.pipelineStage].begin(), cacheEntry.shaders[shader.pipelineStage].end()))
       {
         found = false;
         break;
index 5466495..57a438e 100644 (file)
@@ -202,7 +202,7 @@ public:
   {
     return true;
   }
-  void CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool softwareItailc, bool softwareBold, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth)
+  void CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool softwareItailc, bool softwareBold, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth)
   {
   }
   PixelData CreateBitmap(FontId fontId, GlyphIndex glyphIndex, int outlineWidth)
@@ -406,11 +406,11 @@ FontClient::FontClient(const FontClient& handle)
 {
 }
 
-FontClient::GlyphBufferData::GlyphBufferData()
+GlyphBufferData::GlyphBufferData()
 {
 }
 
-FontClient::GlyphBufferData::~GlyphBufferData()
+GlyphBufferData::~GlyphBufferData()
 {
 }
 
@@ -520,7 +520,7 @@ bool FontClient::GetGlyphMetrics(GlyphInfo* array, uint32_t size, GlyphType type
   return GetImplementation(*this).GetGlyphMetrics(array, size, horizontal);
 }
 
-void FontClient::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool softwareItailc, bool softwareBold, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth)
+void FontClient::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool softwareItailc, bool softwareBold, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth)
 {
   GetImplementation(*this).CreateBitmap(fontId, glyphIndex, softwareItailc, softwareBold, data, outlineWidth);
 }
index 5ff0d51..6b5f5fb 100644 (file)
@@ -61,6 +61,11 @@ Dali::Texture EnvironmentMapLoadTask::GetLoadedTexture()
   return (HasSucceeded()) ? mEnvironmentMapData.GetTexture() : Texture();
 }
 
+uint32_t EnvironmentMapLoadTask::GetMipmapLevels()
+{
+  return (HasSucceeded()) ? mEnvironmentMapData.GetMipmapLevels() : 1u;
+}
+
 } // namespace Internal
 
 } // namespace Scene3D
index 446665c..0bb134f 100644 (file)
@@ -77,6 +77,12 @@ public:
    */
   Dali::Texture GetLoadedTexture();
 
+  /**
+   * Retrieves Mipmap levels of loaded Ibl texture
+   * @return mipmap levels of loaded Ibl texture
+   */
+  uint32_t GetMipmapLevels();
+
 private:
   // Undefined
   EnvironmentMapLoadTask(const EnvironmentMapLoadTask& task) = delete;
index 16bcf32..f9f1e06 100644 (file)
@@ -47,8 +47,9 @@ public:
    * @param[in] diffuseTexture cube map texture that can be used as a diffuse IBL source.
    * @param[in] specularTexture cube map texture that can be used as a specular IBL source.
    * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.
+   * @param[in] specularMipmapLevels mipmap levels of specular texture
    */
-  virtual void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) = 0;
+  virtual void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels) = 0;
 
   /**
    * @brief Notifies Scale Factor of Image Based Light is changed by parent SceneView.
index 5aa4a5f..27e8bc8 100644 (file)
@@ -180,6 +180,8 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr
   mModelPivot(AnchorPoint::CENTER),
   mSceneIblScaleFactor(1.0f),
   mIblScaleFactor(1.0f),
+  mSceneSpecularMipmapLevels(1u),
+  mSpecularMipmapLevels(1u),
   mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE),
   mModelChildrenFocusable(DEFAULT_MODEL_CHILDREN_FOCUSABLE),
   mModelResourceReady(false),
@@ -330,18 +332,6 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s
   NotifyResourceReady();
 }
 
-void Model::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
-{
-  // If input texture is wrong, Model is rendered with SceneView's IBL.
-  if(mDiffuseTexture != diffuseTexture || mSpecularTexture != specularTexture)
-  {
-    mDiffuseTexture  = diffuseTexture;
-    mSpecularTexture = specularTexture;
-    mIblScaleFactor  = scaleFactor;
-    UpdateImageBasedLightTexture();
-  }
-}
-
 void Model::SetImageBasedLightScaleFactor(float scaleFactor)
 {
   mIblScaleFactor = scaleFactor;
@@ -566,15 +556,17 @@ void Model::CollectRenderableActor(Actor actor)
 
 void Model::UpdateImageBasedLightTexture()
 {
-  Dali::Texture currentDiffuseTexture  = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
-  Dali::Texture currentSpecularTexture = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
-  float         currentIblScaleFactor  = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
+  Dali::Texture currentDiffuseTexture          = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
+  Dali::Texture currentSpecularTexture         = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
+  float         currentIblScaleFactor          = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
+  uint32_t      currentIblSpecularMipmapLevels = (mDiffuseTexture && mSpecularTexture) ? mSpecularMipmapLevels : mSceneSpecularMipmapLevels;
 
   if(!currentDiffuseTexture || !currentSpecularTexture)
   {
-    currentDiffuseTexture  = mDefaultDiffuseTexture;
-    currentSpecularTexture = mDefaultSpecularTexture;
-    currentIblScaleFactor  = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
+    currentDiffuseTexture          = mDefaultDiffuseTexture;
+    currentSpecularTexture         = mDefaultSpecularTexture;
+    currentIblScaleFactor          = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
+    currentIblSpecularMipmapLevels = 1u;
   }
 
   for(auto&& actor : mRenderableActors)
@@ -626,6 +618,7 @@ void Model::UpdateImageBasedLightTexture()
       }
     }
     renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
+    renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), static_cast<float>(currentIblSpecularMipmapLevels));
   }
 }
 
@@ -687,13 +680,14 @@ void Model::ApplyCameraTransform(Dali::CameraActor camera) const
   camera.SetProperty(Actor::Property::SCALE, resultScale);
 }
 
-void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
+void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels)
 {
   if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
   {
-    mSceneDiffuseTexture  = diffuseTexture;
-    mSceneSpecularTexture = specularTexture;
-    mSceneIblScaleFactor  = scaleFactor;
+    mSceneDiffuseTexture       = diffuseTexture;
+    mSceneSpecularTexture      = specularTexture;
+    mSceneIblScaleFactor       = scaleFactor;
+    mSceneSpecularMipmapLevels = specularMipmapLevels;
     // If Model IBL is not set, use SceneView's IBL.
     if(!mDiffuseTexture || !mSpecularTexture)
     {
@@ -767,7 +761,8 @@ void Model::OnIblDiffuseLoadComplete()
 
 void Model::OnIblSpecularLoadComplete()
 {
-  mSpecularTexture = mIblSpecularLoadTask->GetLoadedTexture();
+  mSpecularTexture      = mIblSpecularLoadTask->GetLoadedTexture();
+  mSpecularMipmapLevels = mIblSpecularLoadTask->GetMipmapLevels();
   ResetResourceTask(mIblSpecularLoadTask);
   mIblSpecularResourceReady = true;
   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
index 939de84..e5e36d9 100644 (file)
@@ -87,11 +87,6 @@ public:
   void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor);
 
   /**
-   * @copydoc Model::SetImageBasedLightTexture()
-   */
-  void SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor);
-
-  /**
    * @copydoc Model::SetImageBasedLightScaleFactor()
    */
   void SetImageBasedLightScaleFactor(float scaleFactor);
@@ -224,7 +219,7 @@ public: // Overrides ImageBasedLightObserver Methods.
   /**
    * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightTexture()
    */
-  void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) override;
+  void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels) override;
 
   /**
    * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightScaleFactor()
@@ -310,6 +305,8 @@ private:
   Vector3       mModelPivot;
   float         mSceneIblScaleFactor;
   float         mIblScaleFactor;
+  uint32_t      mSceneSpecularMipmapLevels;
+  uint32_t      mSpecularMipmapLevels;
   bool          mModelChildrenSensitive;
   bool          mModelChildrenFocusable;
   bool          mModelResourceReady;
index a4158e1..946eb98 100644 (file)
@@ -277,7 +277,7 @@ void SceneView::RegisterSceneItem(Scene3D::Internal::ImageBasedLightObserver* it
 {
   if(item)
   {
-    item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
+    item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
     mItems.push_back(item);
   }
 }
@@ -353,6 +353,7 @@ void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const st
     mDiffuseTexture.Reset();
     mSpecularTexture.Reset();
 
+    mSpecularMipmapLevels = 1u;
     NotifyImageBasedLightTextureChange();
   }
   else
@@ -826,6 +827,7 @@ void SceneView::OnIblDiffuseLoadComplete()
 void SceneView::OnIblSpecularLoadComplete()
 {
   mSpecularTexture          = mIblSpecularLoadTask->GetLoadedTexture();
+  mSpecularMipmapLevels     = mIblSpecularLoadTask->GetMipmapLevels();
   mIblSpecularResourceReady = true;
   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
   {
@@ -849,7 +851,7 @@ void SceneView::NotifyImageBasedLightTextureChange()
   {
     if(item)
     {
-      item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
+      item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
     }
   }
 }
index 8b175fe..d9377ff 100644 (file)
@@ -323,6 +323,7 @@ private:
   Dali::Texture               mDiffuseTexture;
   Dali::Texture               mSpecularTexture;
   float                       mIblScaleFactor{1.0f};
+  uint32_t                    mSpecularMipmapLevels{1u};
   bool                        mUseFrameBuffer{false};
   bool                        mSkyboxResourceReady{true};
   bool                        mIblDiffuseResourceReady{true};
index c0ef6de..edfb1d8 100644 (file)
@@ -58,10 +58,10 @@ uniform sampler2D sOcclusion;
 uniform float uOcclusionStrength;
 #endif
 
-#ifdef EMISSIVE
+#ifdef EMISSIVE_TEXTURE
 uniform sampler2D sEmissive;
-uniform vec3 uEmissiveFactor;
 #endif
+uniform vec3 uEmissiveFactor;
 
 uniform float uSpecularFactor;
 uniform vec3  uSpecularColorFactor;
@@ -78,6 +78,7 @@ uniform samplerCube sDiffuseEnvSampler;
 uniform samplerCube sSpecularEnvSampler;
 uniform float uIblIntensity;
 uniform vec3 uYDirection;
+uniform float uMaxLOD;
 
 // For Alpha Mode.
 uniform lowp float uOpaque;
@@ -194,7 +195,9 @@ void main()
   vec3 FssEss = specularWeight * (k_S * brdf.x + brdf.y);
 
   // Specular Light
-  lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection * uYDirection).rgb);
+  // uMaxLOD that means mipmap level of specular texture is used for bluring of reflection of specular following roughness.
+  float lod = perceptualRoughness * (uMaxLOD - 1.0);
+  lowp vec3 specularLight = linear(textureLod(sSpecularEnvSampler, reflection * uYDirection, lod).rgb);
   lowp vec3 specular = specularLight * FssEss;
 
   // Diffuse Light
@@ -213,10 +216,12 @@ void main()
   color = mix(color, color * ao, uOcclusionStrength);
 #endif // OCCLUSION
 
-#ifdef EMISSIVE
+#ifdef EMISSIVE_TEXTURE
   lowp vec3 emissive = linear(texture(sEmissive, vUV).rgb) * uEmissiveFactor;
+#else
+  lowp vec3 emissive = uEmissiveFactor;
+#endif // EMISSIVE_TEXTURE
   color += emissive;
-#endif // EMISSIVE
 
   FragColor = vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a) * uColor;
 }
index a747405..a6ac398 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2022 Samsung Electronics Co., Ltd.
+* 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.
@@ -39,53 +39,73 @@ constexpr uint32_t ACCESSOR_TYPE_ELEMENT_COUNT[]{
   16,
   static_cast<uint32_t>(-1)};
 
-const std::map<std::string_view, AccessorType::Type> ACCESSOR_TYPES{
-  ENUM_STRING_MAPPING(AccessorType, SCALAR),
-  ENUM_STRING_MAPPING(AccessorType, VEC2),
-  ENUM_STRING_MAPPING(AccessorType, VEC3),
-  ENUM_STRING_MAPPING(AccessorType, VEC4),
-  ENUM_STRING_MAPPING(AccessorType, MAT2),
-  ENUM_STRING_MAPPING(AccessorType, MAT3),
-  ENUM_STRING_MAPPING(AccessorType, MAT4),
-};
-
-const std::map<std::string_view, AlphaMode::Type> ALPHA_MODE_TYPES{
-  ENUM_STRING_MAPPING(AlphaMode::Type, OPAQUE),
-  ENUM_STRING_MAPPING(AlphaMode::Type, MASK),
-  ENUM_STRING_MAPPING(AlphaMode::Type, BLEND),
-};
-
-const std::map<std::string_view, Attribute::Type> ATTRIBUTE_TYPES{
-  ENUM_STRING_MAPPING(Attribute::Type, POSITION),
-  ENUM_STRING_MAPPING(Attribute::Type, NORMAL),
-  ENUM_STRING_MAPPING(Attribute::Type, TANGENT),
-  ENUM_STRING_MAPPING(Attribute::Type, TEXCOORD_0),
-  ENUM_STRING_MAPPING(Attribute::Type, TEXCOORD_1),
-  ENUM_STRING_MAPPING(Attribute::Type, COLOR_0),
-  ENUM_STRING_MAPPING(Attribute::Type, JOINTS_0),
-  ENUM_STRING_MAPPING(Attribute::Type, WEIGHTS_0),
-};
-
-const std::map<std::string_view, Animation::Sampler::Interpolation::Type> ANIMATION_SAMPLER_INTERPOLATION{
-  ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, STEP),
-  ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, LINEAR),
-  ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, CUBICSPLINE),
-};
-
-const std::map<std::string_view, Animation::Channel::Target::Type> ANIMATION_CHANNEL_TARGET_PATH_TYPES{
-  ENUM_STRING_MAPPING(Animation::Channel::Target::Type, TRANSLATION),
-  ENUM_STRING_MAPPING(Animation::Channel::Target::Type, ROTATION),
-  ENUM_STRING_MAPPING(Animation::Channel::Target::Type, SCALE),
-  ENUM_STRING_MAPPING(Animation::Channel::Target::Type, WEIGHTS),
-};
+const std::map<std::string_view, AccessorType::Type>& GetAccessorTypes()
+{
+  static const std::map<std::string_view, AccessorType::Type> ACCESSOR_TYPES{
+    ENUM_STRING_MAPPING(AccessorType, SCALAR),
+    ENUM_STRING_MAPPING(AccessorType, VEC2),
+    ENUM_STRING_MAPPING(AccessorType, VEC3),
+    ENUM_STRING_MAPPING(AccessorType, VEC4),
+    ENUM_STRING_MAPPING(AccessorType, MAT2),
+    ENUM_STRING_MAPPING(AccessorType, MAT3),
+    ENUM_STRING_MAPPING(AccessorType, MAT4),
+  };
+  return ACCESSOR_TYPES;
+}
+
+const std::map<std::string_view, AlphaMode::Type>& GetAlphaModeTypes()
+{
+  static const std::map<std::string_view, AlphaMode::Type> ALPHA_MODE_TYPES{
+    ENUM_STRING_MAPPING(AlphaMode::Type, OPAQUE),
+    ENUM_STRING_MAPPING(AlphaMode::Type, MASK),
+    ENUM_STRING_MAPPING(AlphaMode::Type, BLEND),
+  };
+  return ALPHA_MODE_TYPES;
+}
+
+const std::map<std::string_view, Attribute::Type>& GetAttributeTypes()
+{
+  static const std::map<std::string_view, Attribute::Type> ATTRIBUTE_TYPES{
+    ENUM_STRING_MAPPING(Attribute::Type, POSITION),
+    ENUM_STRING_MAPPING(Attribute::Type, NORMAL),
+    ENUM_STRING_MAPPING(Attribute::Type, TANGENT),
+    ENUM_STRING_MAPPING(Attribute::Type, TEXCOORD_0),
+    ENUM_STRING_MAPPING(Attribute::Type, TEXCOORD_1),
+    ENUM_STRING_MAPPING(Attribute::Type, COLOR_0),
+    ENUM_STRING_MAPPING(Attribute::Type, JOINTS_0),
+    ENUM_STRING_MAPPING(Attribute::Type, WEIGHTS_0),
+  };
+  return ATTRIBUTE_TYPES;
+}
+
+const std::map<std::string_view, Animation::Sampler::Interpolation::Type>& GetAnimationSamplerInterpolation()
+{
+  static const std::map<std::string_view, Animation::Sampler::Interpolation::Type> ANIMATION_SAMPLER_INTERPOLATION{
+    ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, STEP),
+    ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, LINEAR),
+    ENUM_STRING_MAPPING(Animation::Sampler::Interpolation::Type, CUBICSPLINE),
+  };
+  return ANIMATION_SAMPLER_INTERPOLATION;
+}
+
+const std::map<std::string_view, Animation::Channel::Target::Type>& GetAnimationChannelTargetPathTypes()
+{
+  static const std::map<std::string_view, Animation::Channel::Target::Type> ANIMATION_CHANNEL_TARGET_PATH_TYPES{
+    ENUM_STRING_MAPPING(Animation::Channel::Target::Type, TRANSLATION),
+    ENUM_STRING_MAPPING(Animation::Channel::Target::Type, ROTATION),
+    ENUM_STRING_MAPPING(Animation::Channel::Target::Type, SCALE),
+    ENUM_STRING_MAPPING(Animation::Channel::Target::Type, WEIGHTS),
+  };
+  return ANIMATION_CHANNEL_TARGET_PATH_TYPES;
+}
 
 } // namespace
 
-ENUM_TYPE_FROM_STRING(AccessorType, ACCESSOR_TYPES)
-ENUM_TYPE_FROM_STRING(AlphaMode, ALPHA_MODE_TYPES)
-ENUM_TYPE_FROM_STRING(Attribute, ATTRIBUTE_TYPES)
-ENUM_TYPE_FROM_STRING(Animation::Sampler::Interpolation, ANIMATION_SAMPLER_INTERPOLATION)
-ENUM_TYPE_FROM_STRING(Animation::Channel::Target, ANIMATION_CHANNEL_TARGET_PATH_TYPES)
+ENUM_TYPE_FROM_STRING(AccessorType, GetAccessorTypes())
+ENUM_TYPE_FROM_STRING(AlphaMode, GetAlphaModeTypes())
+ENUM_TYPE_FROM_STRING(Attribute, GetAttributeTypes())
+ENUM_TYPE_FROM_STRING(Animation::Sampler::Interpolation, GetAnimationSamplerInterpolation())
+ENUM_TYPE_FROM_STRING(Animation::Channel::Target, GetAnimationChannelTargetPathTypes())
 
 bool Component::IsUnsigned(Type t)
 {
index 6f70d28..670af82 100644 (file)
@@ -80,32 +80,54 @@ void ApplyAccessorMinMax(const gltf2::Accessor& accessor, float* values)
   MeshDefinition::Blob::ApplyMinMax(accessor.mMin, accessor.mMax, accessor.mCount, values);
 }
 
-const auto BUFFER_READER = std::move(json::Reader<gltf2::Buffer>()
+const json::Reader<gltf2::Buffer>& GetBufferReader()
+{
+  static const auto BUFFER_READER = std::move(json::Reader<gltf2::Buffer>()
                                        .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::Buffer::mByteLength))
                                        .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Buffer::mUri)));
+  return BUFFER_READER;
+}
 
-const auto BUFFER_VIEW_READER = std::move(json::Reader<gltf2::BufferView>()
+const json::Reader<gltf2::BufferView>& GetBufferViewReader()
+{
+  static const auto BUFFER_VIEW_READER = std::move(json::Reader<gltf2::BufferView>()
                                             .Register(*json::MakeProperty("buffer", gltf2::RefReader<gltf2::Document>::Read<gltf2::Buffer, &gltf2::Document::mBuffers>, &gltf2::BufferView::mBuffer))
                                             .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteOffset))
                                             .Register(*json::MakeProperty("byteLength", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteLength))
                                             .Register(*json::MakeProperty("byteStride", json::Read::Number<uint32_t>, &gltf2::BufferView::mByteStride))
                                             .Register(*json::MakeProperty("target", json::Read::Number<uint32_t>, &gltf2::BufferView::mTarget)));
+  return BUFFER_VIEW_READER;
+}
 
-const auto BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::BufferViewClient>()
+const json::Reader<gltf2::BufferViewClient>& GetBufferViewClientReader()
+{
+  static const auto BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::BufferViewClient>()
                                                    .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::BufferViewClient::mBufferView))
                                                    .Register(*json::MakeProperty("byteOffset", json::Read::Number<uint32_t>, &gltf2::BufferViewClient::mByteOffset)));
+  return BUFFER_VIEW_CLIENT_READER;
+}
 
-const auto COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::ComponentTypedBufferViewClient>()
+const json::Reader<gltf2::ComponentTypedBufferViewClient>& GetComponentTypedBufferViewClientReader()
+{
+  static const auto COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER = std::move(json::Reader<gltf2::ComponentTypedBufferViewClient>()
                                                                    .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, gltf2::Ref<gltf2::BufferView>>("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::ComponentTypedBufferViewClient::mBufferView))
                                                                    .Register(*new json::Property<gltf2::ComponentTypedBufferViewClient, uint32_t>("byteOffset", json::Read::Number<uint32_t>, &gltf2::ComponentTypedBufferViewClient::mByteOffset))
                                                                    .Register(*json::MakeProperty("componentType", json::Read::Enum<gltf2::Component::Type>, &gltf2::ComponentTypedBufferViewClient::mComponentType)));
+  return COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER;
+}
 
-const auto ACCESSOR_SPARSE_READER = std::move(json::Reader<gltf2::Accessor::Sparse>()
+const json::Reader<gltf2::Accessor::Sparse>& GetAccessorSparseReader()
+{
+  static const auto ACCESSOR_SPARSE_READER = std::move(json::Reader<gltf2::Accessor::Sparse>()
                                                 .Register(*json::MakeProperty("count", json::Read::Number<uint32_t>, &gltf2::Accessor::Sparse::mCount))
                                                 .Register(*json::MakeProperty("indices", json::ObjectReader<gltf2::ComponentTypedBufferViewClient>::Read, &gltf2::Accessor::Sparse::mIndices))
                                                 .Register(*json::MakeProperty("values", json::ObjectReader<gltf2::BufferViewClient>::Read, &gltf2::Accessor::Sparse::mValues)));
+  return ACCESSOR_SPARSE_READER;
+}
 
-const auto ACCESSOR_READER = std::move(json::Reader<gltf2::Accessor>()
+const json::Reader<gltf2::Accessor>& GetAccessorReader()
+{
+  static const auto ACCESSOR_READER = std::move(json::Reader<gltf2::Accessor>()
                                          .Register(*new json::Property<gltf2::Accessor, gltf2::Ref<gltf2::BufferView>>("bufferView",
                                                                                                                        gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>,
                                                                                                                        &gltf2::Accessor::mBufferView))
@@ -122,50 +144,86 @@ const auto ACCESSOR_READER = std::move(json::Reader<gltf2::Accessor>()
                                          .Register(*json::MakeProperty("min", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMin))
                                          .Register(*json::MakeProperty("max", json::Read::Array<float, json::Read::Number>, &gltf2::Accessor::mMax))
                                          .Register(*new json::Property<gltf2::Accessor, gltf2::Accessor::Sparse>("sparse", json::ObjectReader<gltf2::Accessor::Sparse>::Read, &gltf2::Accessor::SetSparse)));
+  return ACCESSOR_READER;
+}
 
-const auto IMAGE_READER = std::move(json::Reader<gltf2::Image>()
+const json::Reader<gltf2::Image>& GetImageReader()
+{
+  static const auto IMAGE_READER = std::move(json::Reader<gltf2::Image>()
                                       .Register(*new json::Property<gltf2::Image, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
                                       .Register(*json::MakeProperty("uri", json::Read::StringView, &gltf2::Image::mUri))
                                       .Register(*json::MakeProperty("mimeType", json::Read::StringView, &gltf2::Image::mMimeType))
                                       .Register(*json::MakeProperty("bufferView", gltf2::RefReader<gltf2::Document>::Read<gltf2::BufferView, &gltf2::Document::mBufferViews>, &gltf2::Image::mBufferView)));
+  return IMAGE_READER;
+}
 
-const auto SAMPLER_READER = std::move(json::Reader<gltf2::Sampler>()
+const json::Reader<gltf2::Sampler>& GetSamplerReader()
+{
+  static const auto SAMPLER_READER = std::move(json::Reader<gltf2::Sampler>()
                                         .Register(*json::MakeProperty("minFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMinFilter))
                                         .Register(*json::MakeProperty("magFilter", json::Read::Enum<gltf2::Filter::Type>, &gltf2::Sampler::mMagFilter))
                                         .Register(*json::MakeProperty("wrapS", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapS))
                                         .Register(*json::MakeProperty("wrapT", json::Read::Enum<gltf2::Wrap::Type>, &gltf2::Sampler::mWrapT)));
+  return SAMPLER_READER;
+}
 
-const auto TEXURE_READER = std::move(json::Reader<gltf2::Texture>()
+const json::Reader<gltf2::Texture>& GetTextureReader()
+{
+  static const auto TEXURE_READER = std::move(json::Reader<gltf2::Texture>()
                                        .Register(*json::MakeProperty("source", gltf2::RefReader<gltf2::Document>::Read<gltf2::Image, &gltf2::Document::mImages>, &gltf2::Texture::mSource))
                                        .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Document>::Read<gltf2::Sampler, &gltf2::Document::mSamplers>, &gltf2::Texture::mSampler)));
+  return TEXURE_READER;
+}
 
-const auto TEXURE_INFO_READER = std::move(json::Reader<gltf2::TextureInfo>()
+const json::Reader<gltf2::TextureInfo>& GetTextureInfoReader()
+{
+  static const auto TEXURE_INFO_READER = std::move(json::Reader<gltf2::TextureInfo>()
                                             .Register(*json::MakeProperty("index", gltf2::RefReader<gltf2::Document>::Read<gltf2::Texture, &gltf2::Document::mTextures>, &gltf2::TextureInfo::mTexture))
                                             .Register(*json::MakeProperty("texCoord", json::Read::Number<uint32_t>, &gltf2::TextureInfo::mTexCoord))
                                             .Register(*json::MakeProperty("scale", json::Read::Number<float>, &gltf2::TextureInfo::mScale))
                                             .Register(*json::MakeProperty("strength", json::Read::Number<float>, &gltf2::TextureInfo::mStrength)));
+  return TEXURE_INFO_READER;
+}
 
-const auto MATERIAL_PBR_READER = std::move(json::Reader<gltf2::Material::Pbr>()
+const json::Reader<gltf2::Material::Pbr>& GetMaterialPbrReader()
+{
+  static const auto MATERIAL_PBR_READER = std::move(json::Reader<gltf2::Material::Pbr>()
                                              .Register(*json::MakeProperty("baseColorFactor", gltf2::ReadDaliVector<Vector4>, &gltf2::Material::Pbr::mBaseColorFactor))
                                              .Register(*json::MakeProperty("baseColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mBaseColorTexture))
                                              .Register(*json::MakeProperty("metallicFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mMetallicFactor))
                                              .Register(*json::MakeProperty("roughnessFactor", json::Read::Number<float>, &gltf2::Material::Pbr::mRoughnessFactor))
                                              .Register(*json::MakeProperty("metallicRoughnessTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::Pbr::mMetallicRoughnessTexture)));
+  return MATERIAL_PBR_READER;
+}
 
-const auto MATERIAL_SPECULAR_READER = std::move(json::Reader<gltf2::MaterialSpecular>()
+const json::Reader<gltf2::MaterialSpecular>& GetMaterialSpecularReader()
+{
+  static const auto MATERIAL_SPECULAR_READER = std::move(json::Reader<gltf2::MaterialSpecular>()
                                                   .Register(*json::MakeProperty("specularFactor", json::Read::Number<float>, &gltf2::MaterialSpecular::mSpecularFactor))
                                                   .Register(*json::MakeProperty("specularTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularTexture))
                                                   .Register(*json::MakeProperty("specularColorFactor", gltf2::ReadDaliVector<Vector3>, &gltf2::MaterialSpecular::mSpecularColorFactor))
                                                   .Register(*json::MakeProperty("specularColorTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::MaterialSpecular::mSpecularColorTexture)));
+  return MATERIAL_SPECULAR_READER;
+}
 
-const auto MATERIAL_IOR_READER = std::move(json::Reader<gltf2::MaterialIor>()
+const json::Reader<gltf2::MaterialIor>& GetMaterialIorReader()
+{
+  static const auto MATERIAL_IOR_READER = std::move(json::Reader<gltf2::MaterialIor>()
                                              .Register(*json::MakeProperty("ior", json::Read::Number<float>, &gltf2::MaterialIor::mIor)));
+  return MATERIAL_IOR_READER;
+}
 
-const auto MATERIAL_EXTENSION_READER = std::move(json::Reader<gltf2::MaterialExtensions>()
+const json::Reader<gltf2::MaterialExtensions>& GetMaterialExtensionsReader()
+{
+  static const auto MATERIAL_EXTENSION_READER = std::move(json::Reader<gltf2::MaterialExtensions>()
                                                    .Register(*json::MakeProperty("KHR_materials_ior", json::ObjectReader<gltf2::MaterialIor>::Read, &gltf2::MaterialExtensions::mMaterialIor))
                                                    .Register(*json::MakeProperty("KHR_materials_specular", json::ObjectReader<gltf2::MaterialSpecular>::Read, &gltf2::MaterialExtensions::mMaterialSpecular)));
+  return MATERIAL_EXTENSION_READER;
+}
 
-const auto MATERIAL_READER = std::move(json::Reader<gltf2::Material>()
+const json::Reader<gltf2::Material>& GetMaterialReader()
+{
+  static const auto MATERIAL_READER = std::move(json::Reader<gltf2::Material>()
                                          .Register(*new json::Property<gltf2::Material, std::string_view>("name", json::Read::StringView, &gltf2::Material::mName))
                                          .Register(*json::MakeProperty("pbrMetallicRoughness", json::ObjectReader<gltf2::Material::Pbr>::Read, &gltf2::Material::mPbrMetallicRoughness))
                                          .Register(*json::MakeProperty("normalTexture", json::ObjectReader<gltf2::TextureInfo>::Read, &gltf2::Material::mNormalTexture))
@@ -176,6 +234,8 @@ const auto MATERIAL_READER = std::move(json::Reader<gltf2::Material>()
                                          .Register(*json::MakeProperty("alphaCutoff", json::Read::Number<float>, &gltf2::Material::mAlphaCutoff))
                                          .Register(*json::MakeProperty("doubleSided", json::Read::Boolean, &gltf2::Material::mDoubleSided))
                                          .Register(*json::MakeProperty("extensions", json::ObjectReader<gltf2::MaterialExtensions>::Read, &gltf2::Material::mMaterialExtensions)));
+  return MATERIAL_READER;
+}
 
 std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>> ReadMeshPrimitiveAttributes(const json_value_s& j)
 {
@@ -209,21 +269,31 @@ std::vector<std::map<gltf2::Attribute::Type, gltf2::Ref<gltf2::Accessor>>> ReadM
   return result;
 }
 
-const auto MESH_PRIMITIVE_READER = std::move(json::Reader<gltf2::Mesh::Primitive>()
+const json::Reader<gltf2::Mesh::Primitive>& GetMeshPrimitiveReader()
+{
+  static const auto MESH_PRIMITIVE_READER = std::move(json::Reader<gltf2::Mesh::Primitive>()
                                                .Register(*json::MakeProperty("attributes", ReadMeshPrimitiveAttributes, &gltf2::Mesh::Primitive::mAttributes))
                                                .Register(*json::MakeProperty("indices", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Mesh::Primitive::mIndices))
                                                .Register(*json::MakeProperty("material", gltf2::RefReader<gltf2::Document>::Read<gltf2::Material, &gltf2::Document::mMaterials>, &gltf2::Mesh::Primitive::mMaterial))
                                                .Register(*json::MakeProperty("mode", json::Read::Enum<gltf2::Mesh::Primitive::Mode>, &gltf2::Mesh::Primitive::mMode))
                                                .Register(*json::MakeProperty("targets", ReadMeshPrimitiveTargets, &gltf2::Mesh::Primitive::mTargets)));
+  return MESH_PRIMITIVE_READER;
+}
 
-const auto MESH_READER = std::move(json::Reader<gltf2::Mesh>()
+const json::Reader<gltf2::Mesh>& GetMeshReader()
+{
+  static const auto MESH_READER = std::move(json::Reader<gltf2::Mesh>()
                                      .Register(*new json::Property<gltf2::Mesh, std::string_view>("name", json::Read::StringView, &gltf2::Mesh::mName))
                                      .Register(*json::MakeProperty("primitives",
                                                                    json::Read::Array<gltf2::Mesh::Primitive, json::ObjectReader<gltf2::Mesh::Primitive>::Read>,
                                                                    &gltf2::Mesh::mPrimitives))
                                      .Register(*json::MakeProperty("weights", json::Read::Array<float, json::Read::Number>, &gltf2::Mesh::mWeights)));
+  return MESH_READER;
+}
 
-const auto SKIN_READER = std::move(json::Reader<gltf2::Skin>()
+const json::Reader<gltf2::Skin>& GetSkinReader()
+{
+  static const auto SKIN_READER = std::move(json::Reader<gltf2::Skin>()
                                      .Register(*new json::Property<gltf2::Skin, std::string_view>("name", json::Read::StringView, &gltf2::Skin::mName))
                                      .Register(*json::MakeProperty("inverseBindMatrices",
                                                                    gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>,
@@ -234,26 +304,42 @@ const auto SKIN_READER = std::move(json::Reader<gltf2::Skin>()
                                      .Register(*json::MakeProperty("joints",
                                                                    json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
                                                                    &gltf2::Skin::mJoints)));
+  return SKIN_READER;
+}
 
-const auto CAMERA_PERSPECTIVE_READER = std::move(json::Reader<gltf2::Camera::Perspective>()
+const json::Reader<gltf2::Camera::Perspective>& GetCameraPerspectiveReader()
+{
+  static const auto CAMERA_PERSPECTIVE_READER = std::move(json::Reader<gltf2::Camera::Perspective>()
                                                    .Register(*json::MakeProperty("aspectRatio", json::Read::Number<float>, &gltf2::Camera::Perspective::mAspectRatio))
                                                    .Register(*json::MakeProperty("yfov", json::Read::Number<float>, &gltf2::Camera::Perspective::mYFov))
                                                    .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Perspective::mZFar))
                                                    .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Perspective::mZNear))); // TODO: infinite perspective projection, where znear is omitted
+  return CAMERA_PERSPECTIVE_READER;
+}
 
-const auto CAMERA_ORTHOGRAPHIC_READER = std::move(json::Reader<gltf2::Camera::Orthographic>()
+const json::Reader<gltf2::Camera::Orthographic>& GetCameraOrthographicReader()
+{
+  static const auto CAMERA_ORTHOGRAPHIC_READER = std::move(json::Reader<gltf2::Camera::Orthographic>()
                                                     .Register(*json::MakeProperty("xmag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mXMag))
                                                     .Register(*json::MakeProperty("ymag", json::Read::Number<float>, &gltf2::Camera::Orthographic::mYMag))
                                                     .Register(*json::MakeProperty("zfar", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZFar))
                                                     .Register(*json::MakeProperty("znear", json::Read::Number<float>, &gltf2::Camera::Orthographic::mZNear)));
+  return CAMERA_ORTHOGRAPHIC_READER;
+}
 
-const auto CAMERA_READER = std::move(json::Reader<gltf2::Camera>()
+const json::Reader<gltf2::Camera>& GetCameraReader()
+{
+  static const auto CAMERA_READER = std::move(json::Reader<gltf2::Camera>()
                                        .Register(*new json::Property<gltf2::Camera, std::string_view>("name", json::Read::StringView, &gltf2::Camera::mName))
                                        .Register(*json::MakeProperty("type", json::Read::StringView, &gltf2::Camera::mType))
                                        .Register(*json::MakeProperty("perspective", json::ObjectReader<gltf2::Camera::Perspective>::Read, &gltf2::Camera::mPerspective))
                                        .Register(*json::MakeProperty("orthographic", json::ObjectReader<gltf2::Camera::Orthographic>::Read, &gltf2::Camera::mOrthographic)));
+  return CAMERA_READER;
+}
 
-const auto NODE_READER = std::move(json::Reader<gltf2::Node>()
+const json::Reader<gltf2::Node>& GetNodeReader()
+{
+  static const auto NODE_READER = std::move(json::Reader<gltf2::Node>()
                                      .Register(*new json::Property<gltf2::Node, std::string_view>("name", json::Read::StringView, &gltf2::Node::mName))
                                      .Register(*json::MakeProperty("translation", gltf2::ReadDaliVector<Vector3>, &gltf2::Node::mTranslation))
                                      .Register(*json::MakeProperty("rotation", gltf2::ReadQuaternion, &gltf2::Node::mRotation))
@@ -263,21 +349,37 @@ const auto NODE_READER = std::move(json::Reader<gltf2::Node>()
                                      .Register(*json::MakeProperty("children", json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>, &gltf2::Node::mChildren))
                                      .Register(*json::MakeProperty("mesh", gltf2::RefReader<gltf2::Document>::Read<gltf2::Mesh, &gltf2::Document::mMeshes>, &gltf2::Node::mMesh))
                                      .Register(*json::MakeProperty("skin", gltf2::RefReader<gltf2::Document>::Read<gltf2::Skin, &gltf2::Document::mSkins>, &gltf2::Node::mSkin)));
+  return NODE_READER;
+}
 
-const auto ANIMATION_SAMPLER_READER = std::move(json::Reader<gltf2::Animation::Sampler>()
+const json::Reader<gltf2::Animation::Sampler>& GetAnimationSamplerReader()
+{
+  static const auto ANIMATION_SAMPLER_READER = std::move(json::Reader<gltf2::Animation::Sampler>()
                                                   .Register(*json::MakeProperty("input", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mInput))
                                                   .Register(*json::MakeProperty("output", gltf2::RefReader<gltf2::Document>::Read<gltf2::Accessor, &gltf2::Document::mAccessors>, &gltf2::Animation::Sampler::mOutput))
                                                   .Register(*json::MakeProperty("interpolation", gltf2::ReadStringEnum<gltf2::Animation::Sampler::Interpolation>, &gltf2::Animation::Sampler::mInterpolation)));
+  return ANIMATION_SAMPLER_READER;
+}
 
-const auto ANIMATION_TARGET_READER = std::move(json::Reader<gltf2::Animation::Channel::Target>()
+const json::Reader<gltf2::Animation::Channel::Target>& GetAnimationChannelTargetReader()
+{
+  static const auto ANIMATION_TARGET_READER = std::move(json::Reader<gltf2::Animation::Channel::Target>()
                                                  .Register(*json::MakeProperty("node", gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>, &gltf2::Animation::Channel::Target::mNode))
                                                  .Register(*json::MakeProperty("path", gltf2::ReadStringEnum<gltf2::Animation::Channel::Target>, &gltf2::Animation::Channel::Target::mPath)));
+  return ANIMATION_TARGET_READER;
+}
 
-const auto ANIMATION_CHANNEL_READER = std::move(json::Reader<gltf2::Animation::Channel>()
+const json::Reader<gltf2::Animation::Channel>& GetAnimationChannelReader()
+{
+  static const auto ANIMATION_CHANNEL_READER = std::move(json::Reader<gltf2::Animation::Channel>()
                                                   .Register(*json::MakeProperty("target", json::ObjectReader<gltf2::Animation::Channel::Target>::Read, &gltf2::Animation::Channel::mTarget))
                                                   .Register(*json::MakeProperty("sampler", gltf2::RefReader<gltf2::Animation>::Read<gltf2::Animation::Sampler, &gltf2::Animation::mSamplers>, &gltf2::Animation::Channel::mSampler)));
+  return ANIMATION_CHANNEL_READER;
+}
 
-const auto ANIMATION_READER = std::move(json::Reader<gltf2::Animation>()
+const json::Reader<gltf2::Animation>& GetAnimationReader()
+{
+  static const auto ANIMATION_READER = std::move(json::Reader<gltf2::Animation>()
                                           .Register(*new json::Property<gltf2::Animation, std::string_view>("name", json::Read::StringView, &gltf2::Animation::mName))
                                           .Register(*json::MakeProperty("samplers",
                                                                         json::Read::Array<gltf2::Animation::Sampler, json::ObjectReader<gltf2::Animation::Sampler>::Read>,
@@ -285,14 +387,22 @@ const auto ANIMATION_READER = std::move(json::Reader<gltf2::Animation>()
                                           .Register(*json::MakeProperty("channels",
                                                                         json::Read::Array<gltf2::Animation::Channel, json::ObjectReader<gltf2::Animation::Channel>::Read>,
                                                                         &gltf2::Animation::mChannels)));
+  return ANIMATION_READER;
+}
 
-const auto SCENE_READER = std::move(json::Reader<gltf2::Scene>()
+const json::Reader<gltf2::Scene>& GetSceneReader()
+{
+  static const auto SCENE_READER = std::move(json::Reader<gltf2::Scene>()
                                       .Register(*new json::Property<gltf2::Scene, std::string_view>("name", json::Read::StringView, &gltf2::Scene::mName))
                                       .Register(*json::MakeProperty("nodes",
                                                                     json::Read::Array<gltf2::Ref<gltf2::Node>, gltf2::RefReader<gltf2::Document>::Read<gltf2::Node, &gltf2::Document::mNodes>>,
                                                                     &gltf2::Scene::mNodes)));
+  return SCENE_READER;
+}
 
-const auto DOCUMENT_READER = std::move(json::Reader<gltf2::Document>()
+const json::Reader<gltf2::Document>& GetDocumentReader()
+{
+  static const auto DOCUMENT_READER = std::move(json::Reader<gltf2::Document>()
                                          .Register(*json::MakeProperty("buffers",
                                                                        json::Read::Array<gltf2::Buffer, json::ObjectReader<gltf2::Buffer>::Read>,
                                                                        &gltf2::Document::mBuffers))
@@ -333,6 +443,8 @@ const auto DOCUMENT_READER = std::move(json::Reader<gltf2::Document>()
                                                                        json::Read::Array<gltf2::Scene, json::ObjectReader<gltf2::Scene>::Read>,
                                                                        &gltf2::Document::mScenes))
                                          .Register(*json::MakeProperty("scene", gltf2::RefReader<gltf2::Document>::Read<gltf2::Scene, &gltf2::Document::mScenes>, &gltf2::Document::mScene)));
+  return DOCUMENT_READER;
+}
 
 void ConvertBuffer(const gltf2::Buffer& buffer, decltype(ResourceBundle::mBuffers)& outBuffers, const std::string& resourcePath)
 {
@@ -420,10 +532,15 @@ TextureDefinition ConvertTextureInfo(const gltf2::TextureInfo& textureInfo, Conv
   }
 }
 
+void AddTextureStage(uint32_t semantic, MaterialDefinition& materialDefinition, gltf2::TextureInfo textureInfo, const Dali::Scene3D::Loader::ImageMetadata& metaData, ConversionContext& context)
+{
+  materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(textureInfo, context, metaData)});
+  materialDefinition.mFlags |= semantic;
+}
+
 void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<std::string, ImageMetadata>& imageMetaData, decltype(ResourceBundle::mMaterials)& outMaterials, ConversionContext& context)
 {
-  auto getTextureMetaData = [](const std::unordered_map<std::string, ImageMetadata>& metaData, const gltf2::TextureInfo& info)
-  {
+  auto getTextureMetaData = [](const std::unordered_map<std::string, ImageMetadata>& metaData, const gltf2::TextureInfo& info) {
     if(!info.mTexture->mSource->mUri.empty())
     {
       if(auto search = metaData.find(info.mTexture->mSource->mUri.data()); search != metaData.end())
@@ -453,10 +570,7 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
   materialDefinition.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!material.mNormalTexture + !!material.mOcclusionTexture + !!material.mEmissiveTexture);
   if(pbr.mBaseColorTexture)
   {
-    const auto semantic = MaterialDefinition::ALBEDO;
-    materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mBaseColorTexture, context, getTextureMetaData(imageMetaData, pbr.mBaseColorTexture))});
-    // TODO: and there had better be one
-    materialDefinition.mFlags |= semantic;
+    AddTextureStage(MaterialDefinition::ALBEDO, materialDefinition, pbr.mBaseColorTexture, getTextureMetaData(imageMetaData, pbr.mBaseColorTexture), context);
   }
   else
   {
@@ -468,11 +582,11 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
 
   if(pbr.mMetallicRoughnessTexture)
   {
-    const auto semantic = MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
-                          MaterialDefinition::GLTF_CHANNELS;
-    materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(pbr.mMetallicRoughnessTexture, context, getTextureMetaData(imageMetaData, pbr.mMetallicRoughnessTexture))});
-    // TODO: and there had better be one
-    materialDefinition.mFlags |= semantic;
+    AddTextureStage(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+                    materialDefinition,
+                    pbr.mMetallicRoughnessTexture,
+                    getTextureMetaData(imageMetaData, pbr.mMetallicRoughnessTexture),
+                    context);
   }
   else
   {
@@ -482,10 +596,7 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
   materialDefinition.mNormalScale = material.mNormalTexture.mScale;
   if(material.mNormalTexture)
   {
-    const auto semantic = MaterialDefinition::NORMAL;
-    materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mNormalTexture, context, getTextureMetaData(imageMetaData, material.mNormalTexture))});
-    // TODO: and there had better be one
-    materialDefinition.mFlags |= semantic;
+    AddTextureStage(MaterialDefinition::NORMAL, materialDefinition, material.mNormalTexture, getTextureMetaData(imageMetaData, material.mNormalTexture), context);
   }
   else
   {
@@ -494,20 +605,14 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
 
   if(material.mOcclusionTexture)
   {
-    const auto semantic = MaterialDefinition::OCCLUSION;
-    materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mOcclusionTexture, context, getTextureMetaData(imageMetaData, material.mOcclusionTexture))});
-    // TODO: and there had better be one
-    materialDefinition.mFlags |= semantic;
+    AddTextureStage(MaterialDefinition::OCCLUSION, materialDefinition, material.mOcclusionTexture, getTextureMetaData(imageMetaData, material.mOcclusionTexture), context);
     materialDefinition.mOcclusionStrength = material.mOcclusionTexture.mStrength;
   }
 
+  materialDefinition.mEmissiveFactor = material.mEmissiveFactor;
   if(material.mEmissiveTexture)
   {
-    const auto semantic = MaterialDefinition::EMISSIVE;
-    materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mEmissiveTexture, context, getTextureMetaData(imageMetaData, material.mEmissiveTexture))});
-    // TODO: and there had better be one
-    materialDefinition.mFlags |= semantic;
-    materialDefinition.mEmissiveFactor = material.mEmissiveFactor;
+    AddTextureStage(MaterialDefinition::EMISSIVE, materialDefinition, material.mEmissiveTexture, getTextureMetaData(imageMetaData, material.mEmissiveTexture), context);
   }
 
   if(!Dali::Equals(material.mMaterialExtensions.mMaterialIor.mIor, gltf2::UNDEFINED_FLOAT_VALUE))
@@ -520,16 +625,12 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
 
   if(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture)
   {
-    const auto semantic = MaterialDefinition::SPECULAR;
-    materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture, context, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture))});
-    materialDefinition.mFlags |= semantic;
+    AddTextureStage(MaterialDefinition::SPECULAR, materialDefinition, material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture), context);
   }
 
   if(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture)
   {
-    const auto semantic = MaterialDefinition::SPECULAR_COLOR;
-    materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture, context, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture))});
-    materialDefinition.mFlags |= semantic;
+    AddTextureStage(MaterialDefinition::SPECULAR_COLOR, materialDefinition, material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture, getTextureMetaData(imageMetaData, material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture), context);
   }
 
   materialDefinition.mDoubleSided = material.mDoubleSided;
@@ -781,8 +882,7 @@ void ConvertNode(gltf2::Node const& node, const Index gltfIndex, Index parentInd
   auto& resources = output.mResources;
 
   const auto index    = scene.GetNodeCount();
-  auto       weakNode = scene.AddNode([&]()
-                                {
+  auto       weakNode = scene.AddNode([&]() {
     std::unique_ptr<NodeDefinition> nodeDefinition{new NodeDefinition()};
 
     nodeDefinition->mParentIdx = parentIndex;
@@ -1007,6 +1107,21 @@ float LoadBlendShapeKeyFrames(ConversionContext& context, const gltf2::Animation
   return duration;
 }
 
+template<typename T>
+float LoadAnimation(AnimationDefinition& animationDefinition, Index nodeIndex, Index propertyIndex, const std::string& propertyName, const gltf2::Animation::Channel& channel, ConversionContext& context)
+{
+  AnimatedProperty& animatedProperty = animationDefinition.mProperties[propertyIndex];
+
+  animatedProperty.mNodeIndex    = nodeIndex;
+  animatedProperty.mPropertyName = propertyName;
+
+  animatedProperty.mKeyFrames  = KeyFrames::New();
+  float duration               = LoadKeyFrames<T>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
+  animatedProperty.mTimePeriod = {0.f, duration};
+
+  return duration;
+}
+
 void ConvertAnimations(const gltf2::Document& document, ConversionContext& context)
 {
   auto& output = context.mOutput;
@@ -1015,11 +1130,11 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
 
   for(const auto& animation : document.mAnimations)
   {
-    AnimationDefinition animationDef;
+    AnimationDefinition animationDefinition;
 
     if(!animation.mName.empty())
     {
-      animationDef.mName = animation.mName;
+      animationDefinition.mName = animation.mName;
     }
 
     uint32_t numberOfProperties = 0u;
@@ -1034,7 +1149,7 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
         numberOfProperties++;
       }
     }
-    animationDef.mProperties.resize(numberOfProperties);
+    animationDefinition.mProperties.resize(numberOfProperties);
 
     Index propertyIndex = 0u;
     for(const auto& channel : animation.mChannels)
@@ -1046,46 +1161,22 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
       {
         case gltf2::Animation::Channel::Target::TRANSLATION:
         {
-          AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
-
-          animatedProperty.mNodeIndex    = nodeIndex;
-          animatedProperty.mPropertyName = POSITION_PROPERTY;
-
-          animatedProperty.mKeyFrames = KeyFrames::New();
-          duration                    = LoadKeyFrames<Vector3>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
-
-          animatedProperty.mTimePeriod = {0.f, duration};
+          duration = LoadAnimation<Vector3>(animationDefinition, nodeIndex, propertyIndex, POSITION_PROPERTY.data(), channel, context);
           break;
         }
         case gltf2::Animation::Channel::Target::ROTATION:
         {
-          AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
-
-          animatedProperty.mNodeIndex    = nodeIndex;
-          animatedProperty.mPropertyName = ORIENTATION_PROPERTY;
-
-          animatedProperty.mKeyFrames = KeyFrames::New();
-          duration                    = LoadKeyFrames<Quaternion>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
-
-          animatedProperty.mTimePeriod = {0.f, duration};
+          duration = LoadAnimation<Quaternion>(animationDefinition, nodeIndex, propertyIndex, ORIENTATION_PROPERTY.data(), channel, context);
           break;
         }
         case gltf2::Animation::Channel::Target::SCALE:
         {
-          AnimatedProperty& animatedProperty = animationDef.mProperties[propertyIndex];
-
-          animatedProperty.mNodeIndex    = nodeIndex;
-          animatedProperty.mPropertyName = SCALE_PROPERTY;
-
-          animatedProperty.mKeyFrames = KeyFrames::New();
-          duration                    = LoadKeyFrames<Vector3>(context, channel, animatedProperty.mKeyFrames, channel.mTarget.mPath);
-
-          animatedProperty.mTimePeriod = {0.f, duration};
+          duration = LoadAnimation<Vector3>(animationDefinition, nodeIndex, propertyIndex, SCALE_PROPERTY.data(), channel, context);
           break;
         }
         case gltf2::Animation::Channel::Target::WEIGHTS:
         {
-          duration = LoadBlendShapeKeyFrames(context, channel, nodeIndex, propertyIndex, animationDef.mProperties);
+          duration = LoadBlendShapeKeyFrames(context, channel, nodeIndex, propertyIndex, animationDefinition.mProperties);
 
           break;
         }
@@ -1096,12 +1187,12 @@ void ConvertAnimations(const gltf2::Document& document, ConversionContext& conte
         }
       }
 
-      animationDef.mDuration = std::max(duration, animationDef.mDuration);
+      animationDefinition.mDuration = std::max(duration, animationDefinition.mDuration);
 
       ++propertyIndex;
     }
 
-    output.mAnimationDefinitions.push_back(std::move(animationDef));
+    output.mAnimationDefinitions.push_back(std::move(animationDefinition));
   }
 }
 
@@ -1205,33 +1296,33 @@ void ProduceShaders(ShaderDefinitionFactory& shaderFactory, Dali::Scene3D::Loade
 
 void SetObjectReaders()
 {
-  json::SetObjectReader(BUFFER_READER);
-  json::SetObjectReader(BUFFER_VIEW_READER);
-  json::SetObjectReader(BUFFER_VIEW_CLIENT_READER);
-  json::SetObjectReader(COMPONENT_TYPED_BUFFER_VIEW_CLIENT_READER);
-  json::SetObjectReader(ACCESSOR_SPARSE_READER);
-  json::SetObjectReader(ACCESSOR_READER);
-  json::SetObjectReader(IMAGE_READER);
-  json::SetObjectReader(SAMPLER_READER);
-  json::SetObjectReader(TEXURE_READER);
-  json::SetObjectReader(TEXURE_INFO_READER);
-  json::SetObjectReader(MATERIAL_PBR_READER);
-  json::SetObjectReader(MATERIAL_SPECULAR_READER);
-  json::SetObjectReader(MATERIAL_IOR_READER);
-  json::SetObjectReader(MATERIAL_EXTENSION_READER);
-  json::SetObjectReader(MATERIAL_READER);
-  json::SetObjectReader(MESH_PRIMITIVE_READER);
-  json::SetObjectReader(MESH_READER);
-  json::SetObjectReader(SKIN_READER);
-  json::SetObjectReader(CAMERA_PERSPECTIVE_READER);
-  json::SetObjectReader(CAMERA_ORTHOGRAPHIC_READER);
-  json::SetObjectReader(CAMERA_READER);
-  json::SetObjectReader(NODE_READER);
-  json::SetObjectReader(ANIMATION_SAMPLER_READER);
-  json::SetObjectReader(ANIMATION_TARGET_READER);
-  json::SetObjectReader(ANIMATION_CHANNEL_READER);
-  json::SetObjectReader(ANIMATION_READER);
-  json::SetObjectReader(SCENE_READER);
+  json::SetObjectReader(GetBufferReader());
+  json::SetObjectReader(GetBufferViewReader());
+  json::SetObjectReader(GetBufferViewClientReader());
+  json::SetObjectReader(GetComponentTypedBufferViewClientReader());
+  json::SetObjectReader(GetAccessorSparseReader());
+  json::SetObjectReader(GetAccessorReader());
+  json::SetObjectReader(GetImageReader());
+  json::SetObjectReader(GetSamplerReader());
+  json::SetObjectReader(GetTextureReader());
+  json::SetObjectReader(GetTextureInfoReader());
+  json::SetObjectReader(GetMaterialPbrReader());
+  json::SetObjectReader(GetMaterialSpecularReader());
+  json::SetObjectReader(GetMaterialIorReader());
+  json::SetObjectReader(GetMaterialExtensionsReader());
+  json::SetObjectReader(GetMaterialReader());
+  json::SetObjectReader(GetMeshPrimitiveReader());
+  json::SetObjectReader(GetMeshReader());
+  json::SetObjectReader(GetSkinReader());
+  json::SetObjectReader(GetCameraPerspectiveReader());
+  json::SetObjectReader(GetCameraOrthographicReader());
+  json::SetObjectReader(GetCameraReader());
+  json::SetObjectReader(GetNodeReader());
+  json::SetObjectReader(GetAnimationSamplerReader());
+  json::SetObjectReader(GetAnimationChannelTargetReader());
+  json::SetObjectReader(GetAnimationChannelReader());
+  json::SetObjectReader(GetAnimationReader());
+  json::SetObjectReader(GetSceneReader());
 }
 
 void SetDefaultEnvironmentMap(const gltf2::Document& document, ConversionContext& context)
@@ -1265,7 +1356,7 @@ const std::string_view GetRendererModelIdentification()
 
 void ReadDocument(const json_object_s& jsonObject, gltf2::Document& document)
 {
-  DOCUMENT_READER.Read(jsonObject, document);
+  GetDocumentReader().Read(jsonObject, document);
 }
 
 void ReadDocumentFromParsedData(const json_object_s& jsonObject, gltf2::Document& document)
index ec6e95f..88cfad7 100644 (file)
@@ -121,43 +121,47 @@ bool ReadQuadHelper(const TreeNode* tn, const std::array<T*, 4>& quad)
   return true;
 }
 
-const std::map<std::string, Property::Value (*)(const TreeNode*)> kTypeIds{
-  // NONE
-  {"boolean", [](const TreeNode* tn) {
-     return ReadPrimitiveHelper<bool>(tn, ReadBool);
-   }},
-  {"float", [](const TreeNode* tn) {
-     return ReadPrimitiveHelper<float>(tn, ReadFloat);
-   }},
-  {"integer", [](const TreeNode* tn) {
-     return ReadPrimitiveHelper<int>(tn, ReadInt);
-   }},
-  {"vector2", ReadVectorHelper<Vector2>},
-  {"vector3", ReadVectorHelper<Vector3>},
-  {"vector4", ReadVectorHelper<Vector4>},
-  {"matrix3", ReadVectorHelper<Matrix3>},
-  {"matrix", ReadVectorHelper<Matrix>},
-  {"rectangle", [](const TreeNode* tn) {
-     Rect<int> value;
-     if(ReadQuadHelper<int>(tn, {&value.x, &value.y, &value.width, &value.height}))
-     {
-       return Property::Value(value);
-     }
-     return Property::Value();
-   }},
-  {"rotation", ReadRotationHelper},
-  // STRING - not particularly animatable
-  // ARRAY - not particularly animatable
-  // MAP - not particularly animatable
-  {"extents", [](const TreeNode* tn) {
-     Extents value;
-     if(ReadQuadHelper<uint16_t>(tn, {&value.start, &value.end, &value.top, &value.bottom}))
-     {
-       return Property::Value(value);
-     }
-     return Property::Value();
-   }},
-};
+const std::map<std::string_view, Property::Value (*)(const TreeNode*)>& GetTypeIds()
+{
+  static const std::map<std::string_view, Property::Value (*)(const TreeNode*)> kTypeIds{
+    // NONE
+    {"boolean", [](const TreeNode* tn) {
+       return ReadPrimitiveHelper<bool>(tn, ReadBool);
+     }},
+    {"float", [](const TreeNode* tn) {
+       return ReadPrimitiveHelper<float>(tn, ReadFloat);
+     }},
+    {"integer", [](const TreeNode* tn) {
+       return ReadPrimitiveHelper<int>(tn, ReadInt);
+     }},
+    {"vector2", ReadVectorHelper<Vector2>},
+    {"vector3", ReadVectorHelper<Vector3>},
+    {"vector4", ReadVectorHelper<Vector4>},
+    {"matrix3", ReadVectorHelper<Matrix3>},
+    {"matrix", ReadVectorHelper<Matrix>},
+    {"rectangle", [](const TreeNode* tn) {
+       Rect<int> value;
+       if(ReadQuadHelper<int>(tn, {&value.x, &value.y, &value.width, &value.height}))
+       {
+         return Property::Value(value);
+       }
+       return Property::Value();
+     }},
+    {"rotation", ReadRotationHelper},
+    // STRING - not particularly animatable
+    // ARRAY - not particularly animatable
+    // MAP - not particularly animatable
+    {"extents", [](const TreeNode* tn) {
+       Extents value;
+       if(ReadQuadHelper<uint16_t>(tn, {&value.start, &value.end, &value.top, &value.bottom}))
+       {
+         return Property::Value(value);
+       }
+       return Property::Value();
+     }},
+  };
+  return kTypeIds;
+}
 
 Property::Value (*const kArrayPropertyProcessors[])(const TreeNode*){
   ReadVectorHelper<Matrix>,
@@ -469,8 +473,8 @@ Property::Value ReadPropertyValue(const Toolkit::TreeNode& tn)
     auto jsonType = tn.GetChild("type");
     if(jsonType && jsonType->GetType() == TreeNode::STRING)
     {
-      auto iFind = kTypeIds.find(jsonType->GetString());
-      if(iFind != kTypeIds.end())
+      auto iFind = GetTypeIds().find(jsonType->GetString());
+      if(iFind != GetTypeIds().end())
       {
         propValue = iFind->second(tn.GetChild("value"));
       }
index fa792f9..6f01a44 100644 (file)
@@ -92,11 +92,6 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s
   GetImpl(*this).SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor);
 }
 
-void Model::SetImageBasedLightTexture(Texture diffuseTexture, Texture specularTexture, float scaleFactor)
-{
-  GetImpl(*this).SetImageBasedLightTexture(diffuseTexture, specularTexture, scaleFactor);
-}
-
 void Model::SetImageBasedLightScaleFactor(float scaleFactor)
 {
   GetImpl(*this).SetImageBasedLightScaleFactor(scaleFactor);
index da3f7a6..39e7723 100644 (file)
@@ -212,22 +212,10 @@ public:
   void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor = 1.0f);
 
   /**
-   * @brief Sets Image Based Light Texture.
-   *
-   * @SINCE_2_1.41
-   * @param[in] diffuseTexture cube map texture that can be used as a diffuse IBL source.
-   * @param[in] specularTexture cube map texture that can be used as a specular IBL source.
-   * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.
-   *
-   * @note Both of diffuse texture and specular texture should be available. If not, nothing applied.
-   */
-  void SetImageBasedLightTexture(Texture diffuseTexture, Texture specularTexture, float scaleFactor = 1.0f);
-
-  /**
    * @brief Sets Scale Factor of Image Based Light Source.
    *
    * @SINCE_2_1.41
-   * @note If SetImageBasedLightSource() or SetImageBasedLightTexture() method is called after this method, scaleFactor is overrided.
+   * @note If SetImageBasedLightSource() method is called after this method, scaleFactor is overrided.
    *
    * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f].
    */
index f64715d..3866879 100644 (file)
@@ -278,7 +278,7 @@ public:
    * @brief Sets Scale Factor of Image Based Light Source.
    *
    * @SINCE_2_1.41
-   * @note If SetImageBasedLightSource() or SetImageBasedLightTexture() method is called after this method, scaleFactor is overriden.
+   * @note If SetImageBasedLightSource() method is called after this method, scaleFactor is overriden.
    * @note Default value is 1.0f.
    *
    * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f].
index 2aecc50..9c82704 100644 (file)
@@ -29,22 +29,26 @@ namespace
 #define DALI_ALPHA_FUNCTION_ENTRY(x) { #x, AlphaFunction::x }
 // clang-format on
 
-std::unordered_map<std::string, AlphaFunction> sFunctions{
-  DALI_ALPHA_FUNCTION_ENTRY(DEFAULT),
-  DALI_ALPHA_FUNCTION_ENTRY(LINEAR),
-  DALI_ALPHA_FUNCTION_ENTRY(REVERSE),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_SQUARE),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_SQUARE),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_IN),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_OUT),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_SINE),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_SINE),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_OUT_SINE),
-  DALI_ALPHA_FUNCTION_ENTRY(BOUNCE),
-  DALI_ALPHA_FUNCTION_ENTRY(SIN),
-  DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_BACK),
-};
+std::unordered_map<std::string, AlphaFunction>& GetFunctions()
+{
+  static std::unordered_map<std::string, AlphaFunction> sFunctions{
+    DALI_ALPHA_FUNCTION_ENTRY(DEFAULT),
+    DALI_ALPHA_FUNCTION_ENTRY(LINEAR),
+    DALI_ALPHA_FUNCTION_ENTRY(REVERSE),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_SQUARE),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_SQUARE),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_IN),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_OUT),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_SINE),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_SINE),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_IN_OUT_SINE),
+    DALI_ALPHA_FUNCTION_ENTRY(BOUNCE),
+    DALI_ALPHA_FUNCTION_ENTRY(SIN),
+    DALI_ALPHA_FUNCTION_ENTRY(EASE_OUT_BACK),
+  };
+  return sFunctions;
+}
 
 #undef DALI_ALPHA_FUNCTION_ENTRY
 
@@ -52,8 +56,8 @@ std::unordered_map<std::string, AlphaFunction> sFunctions{
 
 AlphaFunction GetAlphaFunction(const std::string& name, bool* found)
 {
-  auto iFind   = sFunctions.find(name);
-  bool success = iFind != sFunctions.end();
+  auto iFind   = GetFunctions().find(name);
+  bool success = iFind != GetFunctions().end();
   if(found)
   {
     *found = success;
@@ -63,7 +67,7 @@ AlphaFunction GetAlphaFunction(const std::string& name, bool* found)
 
 void RegisterAlphaFunction(const std::string& name, AlphaFunction alphaFn)
 {
-  DALI_ASSERT_ALWAYS(sFunctions.insert({name, alphaFn}).second &&
+  DALI_ASSERT_ALWAYS(GetFunctions().insert({name, alphaFn}).second &&
                      "Function with given key already exists.");
 }
 
index 16ec2df..5f4605e 100644 (file)
@@ -91,7 +91,8 @@ EnvironmentDefinition::Textures EnvironmentDefinition::Load(RawData&& raw) const
   // This texture should have 6 faces and 6 mipmaps
   if(!raw.mSpecular.mPixelData.empty())
   {
-    textures.mSpecular = raw.mSpecular.GetTexture();
+    textures.mSpecular             = raw.mSpecular.GetTexture();
+    textures.mSpecularMipmapLevels = raw.mSpecular.GetMipmapLevels();
   }
 
   if(raw.mBrdf)
index 3c4ceee..577a31f 100644 (file)
@@ -36,9 +36,10 @@ struct DALI_SCENE3D_API EnvironmentDefinition
 {
   struct Textures
   {
-    Texture mDiffuse;  // irradiance
-    Texture mSpecular; // radiance
-    Texture mBrdf;     // pre-computed brdf
+    Texture  mDiffuse;  // irradiance
+    Texture  mSpecular; // radiance
+    Texture  mBrdf;     // pre-computed brdf
+    uint32_t mSpecularMipmapLevels{1u};
 
     bool IsLoaded() const
     {
index 2feac5b..6d53cbc 100644 (file)
@@ -65,6 +65,16 @@ public:
     return mEnvironmentMapType;
   }
 
+  void SetMipmapLevels(uint32_t mipmapLevels)
+  {
+    mMipmapLevels = mipmapLevels;
+  }
+
+  uint32_t GetMipmapLevels()
+  {
+    return mMipmapLevels;
+  }
+
 public:
   std::vector<std::vector<PixelData> > mPixelData;
 
@@ -72,6 +82,7 @@ private:
   Dali::Texture                     mEnvironmentMapTexture;
   Dali::Shader                      mEnvironmentMapShader;
   Dali::Scene3D::EnvironmentMapType mEnvironmentMapType{Dali::Scene3D::EnvironmentMapType::AUTO};
+  uint32_t                          mMipmapLevels{1u};
 };
 
 } // namespace Dali::Scene3D::Loader
index 7abff75..306d3b2 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/image-loading.h>
 #include <string.h>
+#include <cmath>
 #include <filesystem>
 
 // INTERNAL INCLUDES
@@ -168,6 +169,8 @@ bool LoadEnvironmentMapData(const std::string& environmentMapUrl, Scene3D::Loade
       {
         environmentMapData.mPixelData[i][0] = GetCubeFace(pixelBuffer, i, cubeType, faceWidth, faceHeight);
       }
+      uint32_t mipmap = static_cast<uint32_t>(1 + std::floor(std::log2(std::max(environmentMapData.mPixelData[0][0].GetWidth(), environmentMapData.mPixelData[0][0].GetHeight()))));
+      environmentMapData.SetMipmapLevels(mipmap);
       environmentMapData.SetEnvironmentMapType(Scene3D::EnvironmentMapType::CUBEMAP);
     }
     else
@@ -193,7 +196,9 @@ bool LoadEnvironmentMap(const std::string& environmentMapUrl, EnvironmentMapData
   std::string           extension = modelPath.extension();
   std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
 
-  return (extension == KTX_EXTENSION) ? Dali::Scene3D::Loader::LoadKtxData(environmentMapUrl, environmentMapData) : LoadEnvironmentMapData(environmentMapUrl, environmentMapData);
+  bool successed = (extension == KTX_EXTENSION) ? Dali::Scene3D::Loader::LoadKtxData(environmentMapUrl, environmentMapData) : LoadEnvironmentMapData(environmentMapUrl, environmentMapData);
+
+  return successed;
 }
 
 } // namespace Loader
index 2261ff8..66e15e2 100644 (file)
@@ -214,6 +214,7 @@ bool LoadKtxData(const std::string& path, EnvironmentMapData& environmentMapData
   header.numberOfArrayElements = std::max(header.numberOfArrayElements, 1u);
   header.pixelDepth            = std::max(header.pixelDepth, 1u);
   header.pixelHeight           = std::max(header.pixelHeight, 1u);
+  environmentMapData.SetMipmapLevels(header.numberOfMipmapLevels);
 
   environmentMapData.mPixelData.resize(header.numberOfFaces);
   for(uint32_t face = 0u; face < header.numberOfFaces; ++face)
index ac6b73a..f69ff72 100644 (file)
@@ -65,7 +65,11 @@ constexpr WrapMode::Type WRAP_MODES_TO_DALI[]{
   WrapMode::CLAMP_TO_EDGE,
   WrapMode::MIRRORED_REPEAT};
 
-const SamplerFlags::Type SINGLE_VALUE_SAMPLER = SamplerFlags::Encode(FilterMode::NEAREST, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE);
+const SamplerFlags::Type GetSingleValueSampler()
+{
+  static const SamplerFlags::Type SINGLE_VALUE_SAMPLER = SamplerFlags::Encode(FilterMode::NEAREST, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE);
+  return SINGLE_VALUE_SAMPLER;
+}
 
 static constexpr std::string_view EMBEDDED_DATA_PREFIX               = "data:";
 static constexpr std::string_view EMBEDDED_DATA_IMAGE_MEDIA_TYPE     = "image/";
@@ -206,7 +210,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath)
     {
       const auto bufferSize = 4;
       uint8_t*   buffer     = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff, 0xff}; // normal of (0, 0, 1), roughness of 1
-      raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+      raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
     }
   }
   else
@@ -240,7 +244,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath)
       buffer[0] = static_cast<uint8_t>(mColor.r * 255.f);
       buffer[1] = static_cast<uint8_t>(mColor.g * 255.f);
       buffer[2] = static_cast<uint8_t>(mColor.b * 255.f);
-      raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, format, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+      raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, format, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
     }
 
     // If we have transparency, or an image based albedo map, we will have to continue with separate metallicRoughness + normal.
@@ -256,7 +260,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath)
       // glTF2 uses B & G, so we might as well just set all components to 1.0.
       const auto bufferSize = 4;
       uint8_t*   buffer     = new uint8_t[bufferSize]{0xff, 0xff, 0xff, 0xff};
-      raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+      raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
     }
 
     if(checkStage(NORMAL))
@@ -270,13 +274,13 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath)
       {
         const auto bufferSize = 3;
         uint8_t*   buffer     = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff}; // normal of (0, 0, 1)
-        raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+        raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
       }
       else // single-value normal-roughness
       {
         const auto bufferSize = 4;
         uint8_t*   buffer     = new uint8_t[bufferSize]{0x7f, 0x7f, 0xff, 0xff}; // normal of (0, 0, 1), roughness of 1.0
-        raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), SINGLE_VALUE_SAMPLER});
+        raw.mTextures.push_back({PixelData::New(buffer, bufferSize, 1, 1, Pixel::RGBA8888, PixelData::DELETE_ARRAY), GetSingleValueSampler()});
       }
     }
   }
index f110150..d2baa33 100644 (file)
@@ -28,6 +28,7 @@ namespace
 {
 constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
 constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
+constexpr std::string_view IBL_MAXLOD("uMaxLOD");
 } // namespace
 
 namespace Scene3D
@@ -118,6 +119,11 @@ std::string_view NodeDefinition::GetIblYDirectionUniformName()
   return IBL_Y_DIRECTION;
 }
 
+std::string_view NodeDefinition::GetIblMaxLodUniformName()
+{
+  return IBL_MAXLOD;
+}
+
 bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
 {
   if(mRenderables.empty())
@@ -237,14 +243,11 @@ void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::Creat
   actor.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
   actor.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
   actor.RegisterProperty("uNormalScale", matDef.mNormalScale);
+  actor.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
   if(matDef.mFlags & MaterialDefinition::OCCLUSION)
   {
     renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
   }
-  if(matDef.mFlags & MaterialDefinition::EMISSIVE)
-  {
-    renderer.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
-  }
 
   Index envIdx = matDef.mEnvironmentIdx;
   renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
@@ -260,7 +263,9 @@ void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::Creat
 
   renderer.SetTextures(textures);
 
+  uint32_t specularMipmap = resources.mEnvironmentMaps[envIdx].second.mSpecularMipmapLevels;
   actor.SetProperty(Actor::Property::COLOR, mColor);
+  actor.RegisterProperty(IBL_MAXLOD.data(), static_cast<float>(specularMipmap));
 }
 
 void ArcRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
index 7474a5f..f73d39b 100644 (file)
@@ -249,6 +249,13 @@ public: // METHODS
    */
   static std::string_view GetIblYDirectionUniformName();
 
+  /**
+   * @brief Retrieves ibl MaxLod uniform name.
+   * This uniform name can be used to set max lod of ibl in shader.
+   * @return std::string_view of the Max Lod uniform name.
+   */
+  static std::string_view GetIblMaxLodUniformName();
+
 public: // DATA
   static const char* ORIGINAL_MATRIX_PROPERTY_NAME;
 
index 30b4d44..63b7d58 100644 (file)
@@ -28,112 +28,129 @@ namespace RendererState
 {
 namespace
 {
-std::map<std::string_view, Type> COMPARISONS{
-#define DECL_COMPARISON(x) {#x, Comparison::x}
-  DECL_COMPARISON(NEVER),
-  DECL_COMPARISON(ALWAYS),
-  DECL_COMPARISON(LESS),
-  DECL_COMPARISON(GREATER),
-  DECL_COMPARISON(EQUAL),
-  DECL_COMPARISON(NOT_EQUAL),
-  DECL_COMPARISON(LESS_EQUAL),
-  DECL_COMPARISON(GREATER_EQUAL),
-#undef DECL_COMPARISON
-};
+const std::map<std::string_view, Type>& GetComparisons()
+{
+  static const std::map<std::string_view, Type> COMPARISONS{
+  #define DECL_COMPARISON(x) {#x, Comparison::x}
+    DECL_COMPARISON(NEVER),
+    DECL_COMPARISON(ALWAYS),
+    DECL_COMPARISON(LESS),
+    DECL_COMPARISON(GREATER),
+    DECL_COMPARISON(EQUAL),
+    DECL_COMPARISON(NOT_EQUAL),
+    DECL_COMPARISON(LESS_EQUAL),
+    DECL_COMPARISON(GREATER_EQUAL),
+  #undef DECL_COMPARISON
+  };
+  return COMPARISONS;
+}
 
 Type InterpretComparison(const std::string_view& str)
 {
   Type value = 0x0;
-  auto iFind = COMPARISONS.find(str);
-  if(iFind != COMPARISONS.end())
+  auto iFind = GetComparisons().find(str);
+  if(iFind != GetComparisons().end())
   {
     value = iFind->second;
   }
   return value;
 }
 
-std::map<std::string_view, Type> BLEND_FACTORS{
-#define DECL_BLEND_FACTOR(x) {#x, Dali::Scene3D::Loader::BlendFactor::x}
-  DECL_BLEND_FACTOR(ZERO),
-  DECL_BLEND_FACTOR(ONE),
-  DECL_BLEND_FACTOR(SRC_COLOR),
-  DECL_BLEND_FACTOR(ONE_MINUS_SRC_COLOR),
-  DECL_BLEND_FACTOR(SRC_ALPHA),
-  DECL_BLEND_FACTOR(ONE_MINUS_SRC_ALPHA),
-  DECL_BLEND_FACTOR(DST_ALPHA),
-  DECL_BLEND_FACTOR(ONE_MINUS_DST_ALPHA),
-  DECL_BLEND_FACTOR(DST_COLOR),
-  DECL_BLEND_FACTOR(ONE_MINUS_DST_COLOR),
-  DECL_BLEND_FACTOR(SRC_ALPHA_SATURATE),
-  DECL_BLEND_FACTOR(CONSTANT_COLOR),
-  DECL_BLEND_FACTOR(ONE_MINUS_CONSTANT_COLOR),
-  DECL_BLEND_FACTOR(CONSTANT_ALPHA),
-  DECL_BLEND_FACTOR(ONE_MINUS_CONSTANT_ALPHA),
-#undef DECL_BLEND_FACTOR
-};
+const std::map<std::string_view, Type>& GetBlendFactors()
+{
+  static const std::map<std::string_view, Type> BLEND_FACTORS{
+  #define DECL_BLEND_FACTOR(x) {#x, Dali::Scene3D::Loader::BlendFactor::x}
+    DECL_BLEND_FACTOR(ZERO),
+    DECL_BLEND_FACTOR(ONE),
+    DECL_BLEND_FACTOR(SRC_COLOR),
+    DECL_BLEND_FACTOR(ONE_MINUS_SRC_COLOR),
+    DECL_BLEND_FACTOR(SRC_ALPHA),
+    DECL_BLEND_FACTOR(ONE_MINUS_SRC_ALPHA),
+    DECL_BLEND_FACTOR(DST_ALPHA),
+    DECL_BLEND_FACTOR(ONE_MINUS_DST_ALPHA),
+    DECL_BLEND_FACTOR(DST_COLOR),
+    DECL_BLEND_FACTOR(ONE_MINUS_DST_COLOR),
+    DECL_BLEND_FACTOR(SRC_ALPHA_SATURATE),
+    DECL_BLEND_FACTOR(CONSTANT_COLOR),
+    DECL_BLEND_FACTOR(ONE_MINUS_CONSTANT_COLOR),
+    DECL_BLEND_FACTOR(CONSTANT_ALPHA),
+    DECL_BLEND_FACTOR(ONE_MINUS_CONSTANT_ALPHA),
+  #undef DECL_BLEND_FACTOR
+  };
+  return BLEND_FACTORS;
+}
 
 Type InterpretBlendFactor(const std::string_view& str, uint8_t item)
 {
   Type value = 0x0;
-  auto iFind = BLEND_FACTORS.find(str);
-  if(iFind != BLEND_FACTORS.end())
+  auto iFind = GetBlendFactors().find(str);
+  if(iFind != GetBlendFactors().end())
   {
     value = iFind->second << (BLEND_FACTOR_BASE_SHIFT + BLEND_FACTOR_ITEM_BITS * item);
   }
   return value;
 }
 
-std::map<std::string_view, Type> BUFFER_MODES{
-#define DECL_BUFFER_MODE(x) {#x, BufferMode::x}
-  DECL_BUFFER_MODE(NONE),
-  DECL_BUFFER_MODE(AUTO),
-  DECL_BUFFER_MODE(COLOR),
-  DECL_BUFFER_MODE(STENCIL),
-  DECL_BUFFER_MODE(COLOR_STENCIL),
-};
+const std::map<std::string_view, Type>& GetBufferModes()
+{
+  static const std::map<std::string_view, Type> BUFFER_MODES{
+  #define DECL_BUFFER_MODE(x) {#x, BufferMode::x}
+    DECL_BUFFER_MODE(NONE),
+    DECL_BUFFER_MODE(AUTO),
+    DECL_BUFFER_MODE(COLOR),
+    DECL_BUFFER_MODE(STENCIL),
+    DECL_BUFFER_MODE(COLOR_STENCIL),
+  #undef DECL_BUFFER_MODE
+  };
+  return BUFFER_MODES;
+}
 
 Type InterpretBufferMode(const std::string_view& str)
 {
   Type value = 0x0;
-  auto iFind = BUFFER_MODES.find(str);
-  if(iFind != BUFFER_MODES.end())
+  auto iFind = GetBufferModes().find(str);
+  if(iFind != GetBufferModes().end())
   {
     value = iFind->second << BUFFER_MODE_SHIFT;
   }
   return value;
 }
 
-std::map<std::string_view, Type (*)(const std::string_view&)> RENDERER_STATE_PROCESSORS{
-  {"DEPTH_WRITE", [](const std::string_view&) -> Type { return DEPTH_WRITE; }},
-  {"DEPTH_TEST", [](const std::string_view&) -> Type { return DEPTH_TEST; }},
-  {"CULL_FRONT", [](const std::string_view&) -> Type { return CULL_FRONT; }},
-  {"CULL_BACK", [](const std::string_view&) -> Type { return CULL_BACK; }},
-  {"ALPHA_BLEND", [](const std::string_view&) -> Type { return ALPHA_BLEND; }},
-  {"DEPTH_FUNC", [](const std::string_view& arg) -> Type {
-     Type value = (arg[0] == ':') ? (InterpretComparison(std::string_view(arg.data() + 1, arg.size() - 1)) << DEPTH_FUNCTION_SHIFT) : 0x0;
-     return value;
-   }},
-  {"BLEND_SRC_RGB", [](const std::string_view& arg) -> Type {
-     Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 0) : 0x0;
-     return value;
-   }},
-  {"BLEND_DST_RGB", [](const std::string_view& arg) -> Type {
-     Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 1) : 0x0;
-     return value;
-   }},
-  {"BLEND_SRC_ALPHA", [](const std::string_view& arg) -> Type {
-     Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 2) : 0x0;
-     return value;
-   }},
-  {"BLEND_DST_ALPHA", [](const std::string_view& arg) -> Type {
-     Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 3) : 0x0;
-     return value;
-   }},
-  {"BUFFER_MODE", [](const std::string_view& arg) -> Type {
-     Type value = (arg[0] == ':') ? InterpretBufferMode(std::string_view(arg.data() + 1, arg.size() - 1)) : 0x0;
-     return value;
-   }},
-};
+const std::map<std::string_view, Type (*)(const std::string_view&)>& GetRendererStateProcessors()
+{
+  static const std::map<std::string_view, Type (*)(const std::string_view&)> RENDERER_STATE_PROCESSORS{
+    {"DEPTH_WRITE", [](const std::string_view&) -> Type { return DEPTH_WRITE; }},
+    {"DEPTH_TEST", [](const std::string_view&) -> Type { return DEPTH_TEST; }},
+    {"CULL_FRONT", [](const std::string_view&) -> Type { return CULL_FRONT; }},
+    {"CULL_BACK", [](const std::string_view&) -> Type { return CULL_BACK; }},
+    {"ALPHA_BLEND", [](const std::string_view&) -> Type { return ALPHA_BLEND; }},
+    {"DEPTH_FUNC", [](const std::string_view& arg) -> Type {
+       Type value = (arg[0] == ':') ? (InterpretComparison(std::string_view(arg.data() + 1, arg.size() - 1)) << DEPTH_FUNCTION_SHIFT) : 0x0;
+       return value;
+     }},
+    {"BLEND_SRC_RGB", [](const std::string_view& arg) -> Type {
+       Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 0) : 0x0;
+       return value;
+     }},
+    {"BLEND_DST_RGB", [](const std::string_view& arg) -> Type {
+       Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 1) : 0x0;
+       return value;
+     }},
+    {"BLEND_SRC_ALPHA", [](const std::string_view& arg) -> Type {
+       Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 2) : 0x0;
+       return value;
+     }},
+    {"BLEND_DST_ALPHA", [](const std::string_view& arg) -> Type {
+       Type value = (arg[0] == ':') ? InterpretBlendFactor(std::string_view(arg.data() + 1, arg.size() - 1), 3) : 0x0;
+       return value;
+     }},
+    {"BUFFER_MODE", [](const std::string_view& arg) -> Type {
+       Type value = (arg[0] == ':') ? InterpretBufferMode(std::string_view(arg.data() + 1, arg.size() - 1)) : 0x0;
+       return value;
+     }},
+  };
+  return RENDERER_STATE_PROCESSORS;
+}
 
 } // namespace
 
@@ -150,8 +167,8 @@ Type Parse(const char* string, size_t length, StringCallback onError)
   {
     auto iNextToken = std::find(string, iEnd, '|');
     auto iColon     = std::find(string, iNextToken, ':');
-    auto i          = RENDERER_STATE_PROCESSORS.find(std::string_view(string, iColon - string));
-    if(i != RENDERER_STATE_PROCESSORS.end() && size_t(std::distance(string, iNextToken)) >= i->first.size())
+    auto i          = GetRendererStateProcessors().find(std::string_view(string, iColon - string));
+    if(i != GetRendererStateProcessors().end() && size_t(std::distance(string, iNextToken)) >= i->first.size())
     {
       value |= i->second(std::string_view(string + i->first.size(), iNextToken - iColon));
     }
index f8377c3..4c9fc70 100644 (file)
@@ -45,48 +45,52 @@ namespace
 {
 const char* JOINT_MATRIX{"jointMatrix"};
 
-const std::map<Property::Type, Constraint (*)(Actor&, Property::Index)> sConstraintFactory = {
-  {Property::Type::BOOLEAN,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<bool>(a, i, [](bool& current, const PropertyInputContainer& inputs) {
-       current = inputs[0]->GetBoolean();
-     });
-   }},
-  {Property::Type::INTEGER,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<int>(a, i, [](int& current, const PropertyInputContainer& inputs) {
-       current = inputs[0]->GetInteger();
-     });
-   }},
-  {Property::Type::FLOAT,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<float>(a, i, EqualToConstraint());
-   }},
-  {Property::Type::VECTOR2,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<Vector2>(a, i, EqualToConstraint());
-   }},
-  {Property::Type::VECTOR3,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<Vector3>(a, i, EqualToConstraint());
-   }},
-  {Property::Type::VECTOR4,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<Vector4>(a, i, EqualToConstraint());
-   }},
-  {Property::Type::MATRIX,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<Matrix>(a, i, EqualToConstraint());
-   }},
-  {Property::Type::MATRIX3,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<Matrix3>(a, i, EqualToConstraint());
-   }},
-  {Property::Type::ROTATION,
-   [](Actor& a, Property::Index i) {
-     return Constraint::New<Quaternion>(a, i, EqualToConstraint());
-   }},
-};
+const std::map<Property::Type, Constraint (*)(Actor&, Property::Index)>& GetConstraintFactory()
+{
+  static const std::map<Property::Type, Constraint (*)(Actor&, Property::Index)> sConstraintFactory = {
+    {Property::Type::BOOLEAN,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<bool>(a, i, [](bool& current, const PropertyInputContainer& inputs) {
+         current = inputs[0]->GetBoolean();
+       });
+     }},
+    {Property::Type::INTEGER,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<int>(a, i, [](int& current, const PropertyInputContainer& inputs) {
+         current = inputs[0]->GetInteger();
+       });
+     }},
+    {Property::Type::FLOAT,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<float>(a, i, EqualToConstraint());
+     }},
+    {Property::Type::VECTOR2,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<Vector2>(a, i, EqualToConstraint());
+     }},
+    {Property::Type::VECTOR3,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<Vector3>(a, i, EqualToConstraint());
+     }},
+    {Property::Type::VECTOR4,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<Vector4>(a, i, EqualToConstraint());
+     }},
+    {Property::Type::MATRIX,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<Matrix>(a, i, EqualToConstraint());
+     }},
+    {Property::Type::MATRIX3,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<Matrix3>(a, i, EqualToConstraint());
+     }},
+    {Property::Type::ROTATION,
+     [](Actor& a, Property::Index i) {
+       return Constraint::New<Quaternion>(a, i, EqualToConstraint());
+     }},
+  };
+  return sConstraintFactory;
+}
 
 struct ResourceReflector : IResourceReflector
 {
@@ -777,8 +781,8 @@ void SceneDefinition::ApplyConstraints(Actor&                           root,
     if(iTarget != Property::INVALID_INDEX)
     {
       auto propertyType = cr.mTarget.GetPropertyType(iTarget);
-      auto iFind        = sConstraintFactory.find(propertyType);
-      if(iFind == sConstraintFactory.end())
+      auto iFind        = GetConstraintFactory().find(propertyType);
+      if(iFind == GetConstraintFactory().end())
       {
         onError(FormatString("node '%s': Property '%s' has unsupported type '%s'; ignored.",
                              sourceName,
index 5db7ab0..a473af1 100644 (file)
@@ -291,7 +291,7 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera
 
     if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
     {
-      shaderDef.mDefines.push_back("EMISSIVE");
+      shaderDef.mDefines.push_back("EMISSIVE_TEXTURE");
     }
 
     if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
@@ -363,7 +363,6 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera
       }
     }
 
-    shaderDef.mUniforms["uMaxLOD"]     = 6.f;
     shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
 
     Index result    = resources.mShaders.size();
index 719657d..5ac6317 100644 (file)
@@ -195,7 +195,6 @@ bool ControlAccessible::IsShowing()
     return true;
   }
 
-  auto childExtent = child->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
   while(parent)
   {
     auto control = Dali::Toolkit::Control::DownCast(parent->Self());
@@ -203,12 +202,6 @@ bool ControlAccessible::IsShowing()
     {
       return false;
     }
-    auto clipMode     = control.GetProperty(Actor::Property::CLIPPING_MODE).Get<bool>();
-    auto parentExtent = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
-    if((clipMode != ClippingMode::DISABLED) && !parentExtent.Intersects(childExtent))
-    {
-      return false;
-    }
     parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
   }
 
index e6ad82f..8cd7ba5 100644 (file)
@@ -118,7 +118,6 @@ StyleManager::StyleManager()
   if(mStyleMonitor)
   {
     mStyleMonitor.StyleChangeSignal().Connect(this, &StyleManager::StyleMonitorChange);
-    mDefaultFontSize = mStyleMonitor.GetDefaultFontSize();
   }
 
   // Set the full path for the default style theme.
@@ -471,6 +470,11 @@ void StyleManager::ApplyStyle(Toolkit::Builder builder, Toolkit::Control control
     builder.ApplyStyle(styleName, control);
   }
 
+  if(mDefaultFontSize == -1 && mStyleMonitor.EnsureFontClientCreated())
+  {
+    mDefaultFontSize = mStyleMonitor.GetDefaultFontSize();
+  }
+
   if(mDefaultFontSize >= 0)
   {
     // Apply the style for logical font size
index 572d830..2f6745b 100644 (file)
@@ -242,7 +242,7 @@ bool Controller::Relayouter::CheckForTextFit(Controller& controller, float point
   textUpdateInfo.Clear();
   textUpdateInfo.mClearAll = true;
 
-  if(textSize.width >= layoutSize.width || textSize.height >= layoutSize.height)
+  if(textSize.width > layoutSize.width || textSize.height > layoutSize.height)
   {
     return false;
   }
index 2ba2793..79de1e1 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/devel-api/common/singleton-service.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
 #include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/emoji-helper.h>
@@ -37,6 +38,8 @@ namespace
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_MULTI_LANGUAGE_SUPPORT");
 #endif
 
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_FONT_PERFORMANCE_MARKER, false);
+
 const Dali::Toolkit::Text::Character UTF32_A = 0x0041;
 } // namespace
 
@@ -423,6 +426,8 @@ void MultilanguageSupport::ValidateFonts(const Vector<Character>&
     return;
   }
 
+  DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_FONTS_VALIDATE");
+
   // Find the first index where to insert the font run.
   FontRunIndex fontIndex = 0u;
   if(0u != startIndex)
index 3dddd7c..a4e9358 100644 (file)
@@ -205,7 +205,7 @@ struct AtlasRenderer::Impl
       if(!isOutline || (isOutline && !isColorGlyph))
       {
         // Retrieve the emoji's bitmap.
-        TextAbstraction::FontClient::GlyphBufferData glyphBufferData;
+        TextAbstraction::GlyphBufferData glyphBufferData;
         glyphBufferData.width  = isColorGlyph ? glyph.width : 0; // Desired width and height.
         glyphBufferData.height = isColorGlyph ? glyph.height : 0;
 
@@ -218,12 +218,12 @@ struct AtlasRenderer::Impl
 
         uint32_t glyphBufferSize = glyphBufferData.width * glyphBufferData.height * Pixel::GetBytesPerPixel(glyphBufferData.format);
         // If glyph buffer data don't have ownership, Or if we need to decompress, create new memory and replace ownership.
-        if(!glyphBufferData.isBufferOwned || glyphBufferData.compressionType != TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION)
+        if(!glyphBufferData.isBufferOwned || glyphBufferData.compressionType != TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION)
         {
           uint8_t* newBuffer = (uint8_t*)malloc(glyphBufferSize);
           if(DALI_LIKELY(newBuffer != nullptr))
           {
-            TextAbstraction::FontClient::GlyphBufferData::Decompress(glyphBufferData, newBuffer);
+            TextAbstraction::GlyphBufferData::Decompress(glyphBufferData, newBuffer);
             if(glyphBufferData.isBufferOwned)
             {
               // Release previous buffer
@@ -231,7 +231,7 @@ struct AtlasRenderer::Impl
             }
             glyphBufferData.isBufferOwned   = true;
             glyphBufferData.buffer          = newBuffer;
-            glyphBufferData.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+            glyphBufferData.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
           }
         }
 
index da8f65f..2176b47 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
@@ -60,18 +60,78 @@ inline uint8_t MultiplyAndNormalizeColor(const uint8_t x, const uint8_t y) noexc
   return ((xy << 15) + (xy << 7) + xy) >> 23;
 }
 
+/// Helper macro define for glyph typesetter. It will reduce some duplicated code line.
+// clang-format off
+/**
+ * @brief Prepare decode glyph bitmap data. It must be call END_GLYPH_BITMAP end of same scope.
+ */
+#define BEGIN_GLYPH_BITMAP(data)                                                                                                               \
+{                                                                                                                                              \
+  uint32_t   glyphOffet               = 0u;                                                                                                    \
+  const bool useLocalScanline         = data.glyphBitmap.compressionType != TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION; \
+  uint8_t* __restrict__ glyphScanline = useLocalScanline ? (uint8_t*)malloc(data.glyphBitmap.width * glyphPixelSize) : data.glyphBitmap.buffer;
+
+/**
+ * @brief Macro to skip useless line fast.
+ */
+#define SKIP_GLYPH_SCANLINE(skipLine)                                                                  \
+if(useLocalScanline)                                                                                   \
+{                                                                                                      \
+  for(int32_t lineIndex = 0; lineIndex < skipLine; ++lineIndex)                                        \
+  {                                                                                                    \
+    TextAbstraction::GlyphBufferData::DecompressScanline(data.glyphBitmap, glyphScanline, glyphOffet); \
+  }                                                                                                    \
+}                                                                                                      \
+else                                                                                                   \
+{                                                                                                      \
+  glyphScanline += skipLine * static_cast<int32_t>(data.glyphBitmap.width * glyphPixelSize);           \
+}
+
+/**
+ * @brief Prepare scanline of glyph bitmap data per each lines. It must be call END_GLYPH_SCANLINE_DECODE end of same scope.
+ */
+#define BEGIN_GLYPH_SCANLINE_DECODE(data)                                                              \
+{                                                                                                      \
+  if(useLocalScanline)                                                                                 \
+  {                                                                                                    \
+    TextAbstraction::GlyphBufferData::DecompressScanline(data.glyphBitmap, glyphScanline, glyphOffet); \
+  }
+
+/**
+ * @brief Finalize scanline of glyph bitmap data per each lines.
+ */
+#define END_GLYPH_SCANLINE_DECODE(data)                       \
+  if(!useLocalScanline)                                       \
+  {                                                           \
+    glyphScanline += data.glyphBitmap.width * glyphPixelSize; \
+  }                                                           \
+} // For ensure that we call BEGIN_GLYPH_SCANLINE_DECODE before
+
+/**
+ * @brief Finalize decode glyph bitmap data.
+ */
+#define END_GLYPH_BITMAP() \
+  if(useLocalScanline)     \
+  {                        \
+    free(glyphScanline);   \
+  }                        \
+} // For ensure that we call BEGIN_GLYPH_BITMAP before
+
+// clang-format on
+/// Helper macro define end.
+
 /**
  * @brief Data struct used to set the buffer of the glyph's bitmap into the final bitmap's buffer.
  */
 struct GlyphData
 {
-  Devel::PixelBuffer                           bitmapBuffer;     ///< The buffer of the whole bitmap. The format is RGBA8888.
-  Vector2*                                     position;         ///< The position of the glyph.
-  TextAbstraction::FontClient::GlyphBufferData glyphBitmap;      ///< The glyph's bitmap.
-  uint32_t                                     width;            ///< The bitmap's width.
-  uint32_t                                     height;           ///< The bitmap's height.
-  int32_t                                      horizontalOffset; ///< The horizontal offset to be added to the 'x' glyph's position.
-  int32_t                                      verticalOffset;   ///< The vertical offset to be added to the 'y' glyph's position.
+  Devel::PixelBuffer               bitmapBuffer;     ///< The buffer of the whole bitmap. The format is RGBA8888.
+  Vector2*                         position;         ///< The position of the glyph.
+  TextAbstraction::GlyphBufferData glyphBitmap;      ///< The glyph's bitmap.
+  uint32_t                         width;            ///< The bitmap's width.
+  uint32_t                         height;           ///< The bitmap's height.
+  int32_t                          horizontalOffset; ///< The horizontal offset to be added to the 'x' glyph's position.
+  int32_t                          verticalOffset;   ///< The vertical offset to be added to the 'y' glyph's position.
 };
 
 /**
@@ -137,13 +197,6 @@ void TypesetGlyph(GlyphData& __restrict__ data,
 
     const bool swapChannelsBR = Pixel::BGRA8888 == data.glyphBitmap.format;
 
-    // Offset byte value of glyph bitmap.
-    uint32_t glyphOffet = 0u;
-
-    // Allocate scanline memory for glyph bitmap if we need.
-    const bool useLocalScanline         = data.glyphBitmap.compressionType != TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
-    uint8_t* __restrict__ glyphScanline = useLocalScanline ? (uint8_t*)malloc(data.glyphBitmap.width * glyphPixelSize) : data.glyphBitmap.buffer;
-
     // Precalculate input color's packed result.
     uint32_t packedInputColor                    = 0u;
     uint8_t* __restrict__ packedInputColorBuffer = reinterpret_cast<uint8_t*>(&packedInputColor);
@@ -153,28 +206,18 @@ void TypesetGlyph(GlyphData& __restrict__ data,
     *(packedInputColorBuffer + 1u) = static_cast<uint8_t>(color->g * 255);
     *(packedInputColorBuffer)      = static_cast<uint8_t>(color->r * 255);
 
+    // Prepare glyph bitmap
+    BEGIN_GLYPH_BITMAP(data);
+
     // Skip basic line of glyph.
-    if(useLocalScanline)
-    {
-      for(int32_t lineIndex = 0; lineIndex < lineIndexRangeMin; ++lineIndex)
-      {
-        TextAbstraction::FontClient::GlyphBufferData::DecompressScanline(data.glyphBitmap, glyphScanline, glyphOffet);
-      }
-    }
-    else
-    {
-      glyphScanline += lineIndexRangeMin * static_cast<int32_t>(data.glyphBitmap.width * glyphPixelSize);
-    }
+    SKIP_GLYPH_SCANLINE(lineIndexRangeMin);
 
     // Traverse the pixels of the glyph line per line.
     if(isColorGlyph)
     {
       for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex)
       {
-        if(useLocalScanline)
-        {
-          TextAbstraction::FontClient::GlyphBufferData::DecompressScanline(data.glyphBitmap, glyphScanline, glyphOffet);
-        }
+        BEGIN_GLYPH_SCANLINE_DECODE(data);
 
         for(int32_t index = indexRangeMin; index < indexRangeMax; ++index)
         {
@@ -219,20 +262,15 @@ void TypesetGlyph(GlyphData& __restrict__ data,
         }
 
         bitmapBuffer += data.width;
-        if(!useLocalScanline)
-        {
-          glyphScanline += data.glyphBitmap.width * glyphPixelSize;
-        }
+
+        END_GLYPH_SCANLINE_DECODE(data);
       }
     }
     else
     {
       for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex)
       {
-        if(useLocalScanline)
-        {
-          TextAbstraction::FontClient::GlyphBufferData::DecompressScanline(data.glyphBitmap, glyphScanline, glyphOffet);
-        }
+        BEGIN_GLYPH_SCANLINE_DECODE(data);
 
         for(int32_t index = indexRangeMin; index < indexRangeMax; ++index)
         {
@@ -279,17 +317,12 @@ void TypesetGlyph(GlyphData& __restrict__ data,
         }
 
         bitmapBuffer += data.width;
-        if(!useLocalScanline)
-        {
-          glyphScanline += data.glyphBitmap.width * glyphPixelSize;
-        }
+
+        END_GLYPH_SCANLINE_DECODE(data);
       }
     }
 
-    if(useLocalScanline)
-    {
-      free(glyphScanline);
-    }
+    END_GLYPH_BITMAP();
   }
   else // Pixel::L8
   {
@@ -297,37 +330,19 @@ void TypesetGlyph(GlyphData& __restrict__ data,
     if(!isColorGlyph)
     {
       uint8_t* __restrict__ bitmapBuffer = data.bitmapBuffer.GetBuffer();
-
-      // Offset byte value of glyph bitmap.
-      uint32_t glyphOffet = 0u;
-
-      // Allocate scanline memory for glyph bitmap if we need.
-      const bool useLocalScanline         = data.glyphBitmap.compressionType != TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
-      uint8_t* __restrict__ glyphScanline = useLocalScanline ? (uint8_t*)malloc(data.glyphBitmap.width * glyphPixelSize) : data.glyphBitmap.buffer;
-
       // Skip basic line.
       bitmapBuffer += (lineIndexRangeMin + yOffset) * static_cast<int32_t>(data.width);
 
+      // Prepare glyph bitmap
+      BEGIN_GLYPH_BITMAP(data);
+
       // Skip basic line of glyph.
-      if(useLocalScanline)
-      {
-        for(int32_t lineIndex = 0; lineIndex < lineIndexRangeMin; ++lineIndex)
-        {
-          TextAbstraction::FontClient::GlyphBufferData::DecompressScanline(data.glyphBitmap, glyphScanline, glyphOffet);
-        }
-      }
-      else
-      {
-        glyphScanline += lineIndexRangeMin * static_cast<int32_t>(data.glyphBitmap.width * glyphPixelSize);
-      }
+      SKIP_GLYPH_SCANLINE(lineIndexRangeMin);
 
       // Traverse the pixels of the glyph line per line.
       for(int32_t lineIndex = lineIndexRangeMin; lineIndex < lineIndexRangeMax; ++lineIndex)
       {
-        if(useLocalScanline)
-        {
-          TextAbstraction::FontClient::GlyphBufferData::DecompressScanline(data.glyphBitmap, glyphScanline, glyphOffet);
-        }
+        BEGIN_GLYPH_SCANLINE_DECODE(data);
 
         for(int32_t index = indexRangeMin; index < indexRangeMax; ++index)
         {
@@ -351,16 +366,11 @@ void TypesetGlyph(GlyphData& __restrict__ data,
         }
 
         bitmapBuffer += data.width;
-        if(!useLocalScanline)
-        {
-          glyphScanline += data.glyphBitmap.width * glyphPixelSize;
-        }
-      }
 
-      if(useLocalScanline)
-      {
-        free(glyphScanline);
+        END_GLYPH_SCANLINE_DECODE(data);
       }
+
+      END_GLYPH_BITMAP();
     }
   }
 }
index 334d922..469a318 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
@@ -549,6 +549,12 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
             {
               Length numberOfSecondHalfGlyphs = numberOfLaidOutGlyphs - firstMiddleIndexOfElidedGlyphs + 1u;
 
+              // Make sure that out-of-boundary does not occur.
+              if(secondMiddleIndexOfElidedGlyphs + numberOfSecondHalfGlyphs > numberOfGlyphs)
+              {
+                numberOfSecondHalfGlyphs = numberOfGlyphs - secondMiddleIndexOfElidedGlyphs;
+              }
+
               //Copy elided glyphs after the ellipsis glyph.
               memcpy(glyphs + firstMiddleIndexOfElidedGlyphs + 1u, glyphs + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo));
               memcpy(glyphPositions + firstMiddleIndexOfElidedGlyphs + 1u, glyphPositions + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2));
index 733141a..265c2fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
@@ -81,6 +81,17 @@ SvgVisual::SvgVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory&
 
 SvgVisual::~SvgVisual()
 {
+  if(Stage::IsInstalled())
+  {
+    if(mLoadingTask)
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask(mLoadingTask);
+    }
+    if(mRasterizingTask)
+    {
+      Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+    }
+  }
 }
 
 void SvgVisual::OnInitialize()
@@ -98,6 +109,7 @@ void SvgVisual::OnInitialize()
   if(IsSynchronousLoadingRequired() && mImageUrl.IsLocalResource())
   {
     mLoadingTask->Process();
+    mLoadingTask.Reset(); // We don't need it now
   }
   else
   {
@@ -219,10 +231,16 @@ void SvgVisual::DoSetOnScene(Actor& actor)
 void SvgVisual::DoSetOffScene(Actor& actor)
 {
   // Remove loading & rasterizing task
-  Dali::AsyncTaskManager::Get().RemoveTask(mLoadingTask);
-  Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
-  mLoadingTask.Reset();
-  mRasterizingTask.Reset();
+  if(mLoadingTask)
+  {
+    Dali::AsyncTaskManager::Get().RemoveTask(mLoadingTask);
+    mLoadingTask.Reset();
+  }
+  if(mRasterizingTask)
+  {
+    Dali::AsyncTaskManager::Get().RemoveTask(mRasterizingTask);
+    mRasterizingTask.Reset();
+  }
 
   actor.RemoveRenderer(mImpl->mRenderer);
   mPlacementActor.Reset();
@@ -301,6 +319,7 @@ void SvgVisual::AddRasterizationTask(const Vector2& size)
     {
       mRasterizingTask->Process();
       ApplyRasterizedImage(mRasterizingTask);
+      mRasterizingTask.Reset(); // We don't need it now
     }
     else
     {
index 9596e0c..eda8a57 100644 (file)
@@ -20,7 +20,6 @@
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/image-loading.h>
-#include <dali/devel-api/images/pixel-data-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 #include <dali/devel-api/rendering/texture-devel.h>
 #include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
index dcb4f91..8217be8 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 18;
+const unsigned int TOOLKIT_MICRO_VERSION = 19;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 863d8c8..a05a7ad 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.2.18
+Version:    2.2.19
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT