49a14def9a1d9f221bc8c06e3d63f3b5ed5e7b3c
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / visual-base-data-impl.cpp
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/public-api/dali-toolkit-common.h>
23 #include <dali/devel-api/scripting/enum-helper.h>
24 #include <dali/devel-api/scripting/scripting.h>
25 #include <dali/integration-api/debug.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
29 #include <dali-toolkit/internal/helpers/property-helper.h>
30 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
31 #include <dali-toolkit/public-api/visuals/visual-properties.h>
32
33 namespace Dali
34 {
35 namespace Toolkit
36 {
37 namespace Internal
38 {
39 namespace
40 {
41 DALI_ENUM_TO_STRING_TABLE_BEGIN(SHADER_HINT)
42   DALI_ENUM_TO_STRING_WITH_SCOPE(Shader::Hint, NONE)
43   DALI_ENUM_TO_STRING_WITH_SCOPE(Shader::Hint, OUTPUT_IS_TRANSPARENT)
44   DALI_ENUM_TO_STRING_WITH_SCOPE(Shader::Hint, MODIFIES_GEOMETRY)
45 DALI_ENUM_TO_STRING_TABLE_END(SHADER_HINT)
46
47 DALI_ENUM_TO_STRING_TABLE_BEGIN(ALIGN)
48   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, TOP_BEGIN)
49   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, TOP_CENTER)
50   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, TOP_END)
51   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, CENTER_BEGIN)
52   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, CENTER)
53   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, CENTER_END)
54   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, BOTTOM_BEGIN)
55   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, BOTTOM_CENTER)
56   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Align, BOTTOM_END)
57 DALI_ENUM_TO_STRING_TABLE_END(ALIGN)
58
59 DALI_ENUM_TO_STRING_TABLE_BEGIN(POLICY)
60   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Visual::Transform::Policy, RELATIVE)
61   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Visual::Transform::Policy, ABSOLUTE)
62 DALI_ENUM_TO_STRING_TABLE_END(POLICY)
63
64 Dali::Vector2 PointToVector2(Toolkit::Align::Type point, Toolkit::Direction::Type direction)
65 {
66   // clang-format off
67   static const float pointToVector2[] = {0.0f,0.0f,
68                                          0.5f,0.0f,
69                                          1.0f,0.0f,
70                                          0.0f,0.5f,
71                                          0.5f,0.5f,
72                                          1.0f,0.5f,
73                                          0.0f,1.0f,
74                                          0.5f,1.0f,
75                                          1.0f,1.0f};
76
77   // clang-format on
78
79   Vector2 result(&pointToVector2[point * 2]);
80   if(direction == Direction::RIGHT_TO_LEFT)
81   {
82     result.x = 1.0f - result.x;
83   }
84
85   return result;
86 }
87
88 bool GetPolicyFromValue(const Property::Value& value, Vector2& policy)
89 {
90   bool success = false;
91   if(value.Get(policy))
92   {
93     success = true;
94   }
95   else
96   {
97     const Property::Array* array = value.GetArray();
98     if(array && array->Size() == 2)
99     {
100       Toolkit::Visual::Transform::Policy::Type xPolicy = static_cast<Toolkit::Visual::Transform::Policy::Type>(-1); // Assign an invalid value so definitely changes
101       Toolkit::Visual::Transform::Policy::Type yPolicy = static_cast<Toolkit::Visual::Transform::Policy::Type>(-1); // Assign an invalid value so definitely changes
102
103       if(Scripting::GetEnumerationProperty<Toolkit::Visual::Transform::Policy::Type>(array->GetElementAt(0), POLICY_TABLE, POLICY_TABLE_COUNT, xPolicy) &&
104          Scripting::GetEnumerationProperty<Toolkit::Visual::Transform::Policy::Type>(array->GetElementAt(1), POLICY_TABLE, POLICY_TABLE_COUNT, yPolicy))
105       {
106         policy.x = xPolicy;
107         policy.y = yPolicy;
108         success  = true;
109       }
110     }
111   }
112   return success;
113 }
114
115 } // unnamed namespace
116
117 Internal::Visual::Base::Impl::Impl(FittingMode fittingMode, Toolkit::Visual::Type type)
118 : mCustomShader(NULL),
119   mEventObserver(NULL),
120   mTransform(),
121   mMixColor(Color::WHITE),
122   mControlSize(Vector2::ZERO),
123   mBorderlineWidth(0.0f),
124   mBorderlineColor(Color::BLACK),
125   mBorderlineOffset(0.0f),
126   mCornerRadius(Vector4::ZERO),
127   mCornerRadiusPolicy(1.0f),
128   mDepthIndex(0.0f),
129   mFittingMode(fittingMode),
130   mFlags(0),
131   mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
132   mType(type),
133   mAlwaysUsingBorderline(false),
134   mAlwaysUsingCornerRadius(false)
135 {
136 }
137
138 Internal::Visual::Base::Impl::~Impl()
139 {
140   delete mCustomShader;
141 }
142
143 Internal::Visual::Base::Impl::CustomShader::CustomShader(const Property::Map& map)
144 : mGridSize(1, 1),
145   mHints(Shader::Hint::NONE)
146 {
147   SetPropertyMap(map);
148 }
149
150 void Internal::Visual::Base::Impl::CustomShader::SetPropertyMap(const Property::Map& shaderMap)
151 {
152   mVertexShader.clear();
153   mFragmentShader.clear();
154   mGridSize = ImageDimensions(1, 1);
155   mHints    = Shader::Hint::NONE;
156
157   Property::Value* vertexShaderValue = shaderMap.Find(Toolkit::Visual::Shader::Property::VERTEX_SHADER, CUSTOM_VERTEX_SHADER);
158   if(vertexShaderValue)
159   {
160     if(!GetStringFromProperty(*vertexShaderValue, mVertexShader))
161     {
162       DALI_LOG_ERROR("'%s' parameter does not correctly specify a string\n", CUSTOM_VERTEX_SHADER);
163     }
164   }
165
166   Property::Value* fragmentShaderValue = shaderMap.Find(Toolkit::Visual::Shader::Property::FRAGMENT_SHADER, CUSTOM_FRAGMENT_SHADER);
167   if(fragmentShaderValue)
168   {
169     if(!GetStringFromProperty(*fragmentShaderValue, mFragmentShader))
170     {
171       DALI_LOG_ERROR("'%s' parameter does not correctly specify a string\n", CUSTOM_FRAGMENT_SHADER);
172     }
173   }
174
175   Property::Value* subdivideXValue = shaderMap.Find(Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_X, CUSTOM_SUBDIVIDE_GRID_X);
176   if(subdivideXValue)
177   {
178     int subdivideX;
179     if(!subdivideXValue->Get(subdivideX) || subdivideX < 1)
180     {
181       DALI_LOG_ERROR("'%s' parameter does not correctly specify a value greater than 1\n", CUSTOM_SUBDIVIDE_GRID_X);
182     }
183     else
184     {
185       mGridSize = ImageDimensions(subdivideX, mGridSize.GetY());
186     }
187   }
188
189   Property::Value* subdivideYValue = shaderMap.Find(Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_Y, CUSTOM_SUBDIVIDE_GRID_Y);
190   if(subdivideYValue)
191   {
192     int subdivideY;
193     if(!subdivideYValue->Get(subdivideY) || subdivideY < 1)
194     {
195       DALI_LOG_ERROR("'%s' parameter does not correctly specify a value greater than 1\n", CUSTOM_SUBDIVIDE_GRID_Y);
196     }
197     else
198     {
199       mGridSize = ImageDimensions(mGridSize.GetX(), subdivideY);
200     }
201   }
202
203   Property::Value* hintsValue = shaderMap.Find(Toolkit::Visual::Shader::Property::HINTS, CUSTOM_SHADER_HINTS);
204   if(hintsValue)
205   {
206     if(!Scripting::GetBitmaskEnumerationProperty(*hintsValue, SHADER_HINT_TABLE, SHADER_HINT_TABLE_COUNT, mHints))
207     {
208       DALI_LOG_ERROR("'%s' parameter does not correctly specify a hint or an array of hint strings\n", CUSTOM_SHADER_HINTS);
209     }
210   }
211 }
212
213 void Internal::Visual::Base::Impl::CustomShader::CreatePropertyMap(Property::Map& map) const
214 {
215   if(!mVertexShader.empty() || !mFragmentShader.empty())
216   {
217     Property::Map customShader;
218     if(!mVertexShader.empty())
219     {
220       customShader.Insert(Toolkit::Visual::Shader::Property::VERTEX_SHADER, mVertexShader);
221     }
222     if(!mFragmentShader.empty())
223     {
224       customShader.Insert(Toolkit::Visual::Shader::Property::FRAGMENT_SHADER, mFragmentShader);
225     }
226
227     if(mGridSize.GetWidth() != 1)
228     {
229       customShader.Insert(Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_X, mGridSize.GetWidth());
230     }
231     if(mGridSize.GetHeight() != 1)
232     {
233       customShader.Insert(Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_Y, mGridSize.GetHeight());
234     }
235
236     if(mHints != Dali::Shader::Hint::NONE)
237     {
238       customShader.Insert(Toolkit::Visual::Shader::Property::HINTS, static_cast<int>(mHints));
239     }
240
241     map.Insert(Toolkit::Visual::Property::SHADER, customShader);
242   }
243 }
244
245 Internal::Visual::Base::Impl::Transform::Transform()
246 : mOffset(0.0f, 0.0f),
247   mSize(1.0f, 1.0f),
248   mExtraSize(0.0f, 0.0f),
249   mOffsetSizeMode(0.0f, 0.0f, 0.0f, 0.0f),
250   mOrigin(Toolkit::Align::TOP_BEGIN),
251   mAnchorPoint(Toolkit::Align::TOP_BEGIN)
252 {
253 }
254
255 void Internal::Visual::Base::Impl::Transform::SetPropertyMap(const Property::Map& map)
256 {
257   // Set default values
258   mOffset         = Vector2(0.0f, 0.0f);
259   mSize           = Vector2(1.0f, 1.0f);
260   mExtraSize      = Vector2(0.0f, 0.0f);
261   mOffsetSizeMode = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
262   mOrigin         = Toolkit::Align::TOP_BEGIN;
263   mAnchorPoint    = Toolkit::Align::TOP_BEGIN;
264
265   UpdatePropertyMap(map);
266 }
267
268 void Internal::Visual::Base::Impl::Transform::UpdatePropertyMap(const Property::Map& map)
269 {
270   for(Property::Map::SizeType i(0); i < map.Count(); ++i)
271   {
272     KeyValuePair keyValue = map.GetKeyValue(i);
273     switch(Visual::Base::GetIntKey(keyValue.first))
274     {
275       case Toolkit::Visual::Transform::Property::OFFSET:
276       {
277         keyValue.second.Get(mOffset);
278         break;
279       }
280       case Toolkit::Visual::Transform::Property::SIZE:
281       {
282         keyValue.second.Get(mSize);
283         break;
284       }
285       case Toolkit::Visual::Transform::Property::ORIGIN:
286       {
287         Scripting::GetEnumerationProperty<Toolkit::Align::Type>(keyValue.second, ALIGN_TABLE, ALIGN_TABLE_COUNT, mOrigin);
288         break;
289       }
290       case Toolkit::Visual::Transform::Property::ANCHOR_POINT:
291       {
292         Scripting::GetEnumerationProperty<Toolkit::Align::Type>(keyValue.second, ALIGN_TABLE, ALIGN_TABLE_COUNT, mAnchorPoint);
293         break;
294       }
295       case Toolkit::Visual::Transform::Property::OFFSET_POLICY:
296       {
297         Vector2 policy;
298         if(GetPolicyFromValue(keyValue.second, policy))
299         {
300           mOffsetSizeMode.x = policy.x;
301           mOffsetSizeMode.y = policy.y;
302         }
303         break;
304       }
305       case Toolkit::Visual::Transform::Property::SIZE_POLICY:
306       {
307         Vector2 policy;
308         if(GetPolicyFromValue(keyValue.second, policy))
309         {
310           mOffsetSizeMode.z = policy.x;
311           mOffsetSizeMode.w = policy.y;
312         }
313         break;
314       }
315       case Toolkit::DevelVisual::Transform::Property::EXTRA_SIZE:
316       {
317         keyValue.second.Get(mExtraSize);
318         break;
319       }
320     }
321   }
322 }
323
324 void Internal::Visual::Base::Impl::Transform::GetPropertyMap(Property::Map& map) const
325 {
326   map.Clear();
327   map
328     .Add(Toolkit::Visual::Transform::Property::OFFSET, mOffset)
329     .Add(Toolkit::Visual::Transform::Property::SIZE, mSize)
330     .Add(Toolkit::Visual::Transform::Property::ORIGIN, mOrigin)
331     .Add(Toolkit::Visual::Transform::Property::ANCHOR_POINT, mAnchorPoint)
332     .Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2(mOffsetSizeMode.x, mOffsetSizeMode.y))
333     .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2(mOffsetSizeMode.z, mOffsetSizeMode.w))
334     .Add(Toolkit::DevelVisual::Transform::Property::EXTRA_SIZE, mExtraSize);
335 }
336
337 void Internal::Visual::Base::Impl::Transform::SetUniforms(Dali::VisualRenderer renderer, Toolkit::Direction::Type direction)
338 {
339   renderer.SetProperty(VisualRenderer::Property::TRANSFORM_SIZE, mSize);
340   renderer.SetProperty(VisualRenderer::Property::TRANSFORM_OFFSET,
341                        direction == Toolkit::Direction::LEFT_TO_RIGHT ? mOffset : mOffset * Vector2(-1.0f, 1.0f));
342   renderer.SetProperty(VisualRenderer::Property::TRANSFORM_OFFSET_SIZE_MODE, mOffsetSizeMode);
343   renderer.SetProperty(VisualRenderer::Property::TRANSFORM_ORIGIN, PointToVector2(mOrigin, direction) - Vector2(0.5, 0.5));
344   renderer.SetProperty(VisualRenderer::Property::TRANSFORM_ANCHOR_POINT,
345                        Vector2(0.5, 0.5) - PointToVector2(mAnchorPoint, direction));
346   renderer.SetProperty(VisualRenderer::Property::EXTRA_SIZE, mExtraSize);
347 }
348
349 Vector2 Internal::Visual::Base::Impl::Transform::GetVisualSize(const Vector2& controlSize)
350 {
351   return Vector2(Lerp(mOffsetSizeMode.z, mSize.x * controlSize.x, mSize.x),
352                  Lerp(mOffsetSizeMode.w, mSize.y * controlSize.y, mSize.y)) +
353          mExtraSize;
354 }
355
356 } // namespace Internal
357
358 } // namespace Toolkit
359
360 } // namespace Dali