[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / load-scene-metadata.cpp
1 /*\r
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  * http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  *\r
16  */\r
17 \r
18 // INTERNAL INCLUDES\r
19 #include <dali-scene3d/internal/loader/gltf2-asset.h>\r
20 #include <dali-scene3d/internal/loader/json-reader.h>\r
21 #include <dali-scene3d/public-api/loader/load-scene-metadata.h>\r
22 #include <dali-scene3d/public-api/loader/utils.h>\r
23 \r
24 namespace js = json;\r
25 namespace gt = gltf2;\r
26 \r
27 namespace Dali::Scene3D::Loader\r
28 {\r
29 namespace\r
30 {\r
31 struct ImageData\r
32 {\r
33   struct SamplingMode\r
34   {\r
35     enum Type\r
36     {\r
37       INVALID          = -1,\r
38       BOX              = Dali::SamplingMode::BOX,\r
39       NEAREST          = Dali::SamplingMode::NEAREST,\r
40       LINEAR           = Dali::SamplingMode::LINEAR,\r
41       BOX_THEN_NEAREST = Dali::SamplingMode::BOX_THEN_NEAREST,\r
42       BOX_THEN_LINEAR  = Dali::SamplingMode::BOX_THEN_LINEAR,\r
43       NO_FILTER        = Dali::SamplingMode::NO_FILTER,\r
44       DONT_CARE        = Dali::SamplingMode::DONT_CARE\r
45     };\r
46 \r
47     static Type FromString(const char* s, size_t len);\r
48   };\r
49 \r
50   std::string mImageUri{};  ///< The URI of the image\r
51   uint16_t    mMinWidth{};  ///< The minimum width of the image\r
52   uint16_t    mMinHeight{}; ///< The mimimum height of the image\r
53 \r
54   ImageData::SamplingMode::Type mSamplingMode{ImageData::SamplingMode::BOX_THEN_LINEAR}; ///< The sampling mode used to resize the image.\r
55 };\r
56 \r
57 const std::map<std::string_view, ImageData::SamplingMode::Type>& GetStringSamplingModeTable()\r
58 {\r
59   static const std::map<std::string_view, ImageData::SamplingMode::Type> SAMPLING_MODE_TYPES{\r
60     ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX),\r
61     ENUM_STRING_MAPPING(ImageData::SamplingMode, NEAREST),\r
62     ENUM_STRING_MAPPING(ImageData::SamplingMode, LINEAR),\r
63     ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX_THEN_NEAREST),\r
64     ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX_THEN_LINEAR),\r
65     ENUM_STRING_MAPPING(ImageData::SamplingMode, NO_FILTER),\r
66     ENUM_STRING_MAPPING(ImageData::SamplingMode, DONT_CARE),\r
67   };\r
68   return SAMPLING_MODE_TYPES;\r
69 }\r
70 \r
71 ENUM_TYPE_FROM_STRING(ImageData::SamplingMode, GetStringSamplingModeTable())\r
72 \r
73 struct MetaData\r
74 {\r
75   std::vector<ImageData> mImageData;\r
76 };\r
77 \r
78 const js::Reader<ImageData>& GetImageMetaDataReader()\r
79 {\r
80   static const auto IMAGE_METADATA_READER = std::move(js::Reader<ImageData>()\r
81                                                          .Register(*js::MakeProperty("uri", js::Read::String, &ImageData::mImageUri))\r
82                                                          .Register(*js::MakeProperty("minWidth", js::Read::Number, &ImageData::mMinWidth))\r
83                                                          .Register(*js::MakeProperty("minHeight", js::Read::Number, &ImageData::mMinHeight))\r
84                                                          .Register(*js::MakeProperty("samplingMode", gt::ReadStringEnum<ImageData::SamplingMode>, &ImageData::mSamplingMode)));\r
85   return IMAGE_METADATA_READER;\r
86 }\r
87 \r
88 const js::Reader<MetaData>& GetMetaDataReader()\r
89 {\r
90   static const auto METADATA_READER = std::move(js::Reader<MetaData>()\r
91                                                    .Register(*js::MakeProperty("images", js::Read::Array<ImageData, js::ObjectReader<ImageData>::Read>, &MetaData::mImageData)));\r
92   return METADATA_READER;\r
93 }\r
94 } // namespace\r
95 \r
96 void LoadSceneMetadata(const std::string& url, SceneMetadata& sceneMetadata)\r
97 {\r
98   bool failed = false;\r
99   auto js     = LoadTextFile(url.c_str(), &failed);\r
100   if(failed)\r
101   {\r
102     return;\r
103   }\r
104 \r
105   json::unique_ptr root(json_parse(js.c_str(), js.size()));\r
106   if(!root)\r
107   {\r
108     throw std::runtime_error("Failed to parse " + url);\r
109   }\r
110   auto& rootObj = js::Cast<json_object_s>(*root);\r
111 \r
112   static bool setObjectReaders = true;\r
113   if(setObjectReaders)\r
114   {\r
115     js::SetObjectReader(GetImageMetaDataReader());\r
116 \r
117     setObjectReaders = false;\r
118   }\r
119 \r
120   MetaData metaData;\r
121   GetMetaDataReader().Read(rootObj, metaData);\r
122 \r
123   sceneMetadata.mImageMetadata.reserve(metaData.mImageData.size() + metaData.mImageData.size());\r
124   for(auto&& data : metaData.mImageData)\r
125   {\r
126     if(data.mSamplingMode == ImageData::SamplingMode::INVALID)\r
127     {\r
128       throw std::runtime_error("Sampling mode type unsupported.");\r
129     }\r
130     else\r
131     {\r
132       sceneMetadata.mImageMetadata.insert({data.mImageUri, ImageMetadata{ImageDimensions(data.mMinWidth, data.mMinHeight), static_cast<Dali::SamplingMode::Type>(data.mSamplingMode)}});\r
133     }\r
134   }\r
135 }\r
136 \r
137 } // namespace Dali::Scene3D::Loader\r