Merge "Use Mipmap level to sample specular texture" into devel/master
authorEunki Hong <eunkiki.hong@samsung.com>
Thu, 23 Mar 2023 07:04:25 +0000 (07:04 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 23 Mar 2023 07:04:25 +0000 (07:04 +0000)
20 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Accessible.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-abstraction.cpp
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/loader/alpha-function-helper.cpp
dali-scene3d/public-api/loader/material-definition.cpp
dali-scene3d/public-api/loader/node-definition.cpp
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/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/text/text-visual.cpp

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 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 1579866..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;
@@ -216,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 b01c8ba..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,7 +532,7 @@ 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)
+void AddTextureStage(uint32_t semantic, MaterialDefinition& materialDefinition, gltf2::TextureInfo textureInfo, const Dali::Scene3D::Loader::ImageMetadatametaData, ConversionContext& context)
 {
   materialDefinition.mTextureStages.push_back({semantic, ConvertTextureInfo(textureInfo, context, metaData)});
   materialDefinition.mFlags |= semantic;
@@ -428,8 +540,7 @@ void AddTextureStage(uint32_t semantic, MaterialDefinition& materialDefinition,
 
 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())
@@ -498,10 +609,10 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
     materialDefinition.mOcclusionStrength = material.mOcclusionTexture.mStrength;
   }
 
+  materialDefinition.mEmissiveFactor = material.mEmissiveFactor;
   if(material.mEmissiveTexture)
   {
     AddTextureStage(MaterialDefinition::EMISSIVE, materialDefinition, material.mEmissiveTexture, getTextureMetaData(imageMetaData, material.mEmissiveTexture), context);
-    materialDefinition.mEmissiveFactor = material.mEmissiveFactor;
   }
 
   if(!Dali::Equals(material.mMaterialExtensions.mMaterialIor.mIor, gltf2::UNDEFINED_FLOAT_VALUE))
@@ -771,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;
@@ -1186,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)
@@ -1246,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 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 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 833d489..d2baa33 100644 (file)
@@ -243,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);
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 6a0bf8a..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))
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 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>