Add post processor
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / visual-base-data-impl.cpp
1 /*
2  * Copyright (c) 2021 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   // clang-format on
77
78   Vector2 result(&pointToVector2[point * 2]);
79   if(direction == Direction::RIGHT_TO_LEFT)
80   {
81     result.x = 1.0f - result.x;
82   }
83
84   return result;
85 }
86
87 bool GetPolicyFromValue(const Property::Value& value, Vector2& policy)
88 {
89   bool success = false;
90   if(value.Get(policy))
91   {
92     success = true;
93   }
94   else
95   {
96     const Property::Array* array = value.GetArray();
97     if(array && array->Size() == 2)
98     {
99       Toolkit::Visual::Transform::Policy::Type xPolicy = static_cast<Toolkit::Visual::Transform::Policy::Type>(-1); // Assign an invalid value so definitely changes
100       Toolkit::Visual::Transform::Policy::Type yPolicy = static_cast<Toolkit::Visual::Transform::Policy::Type>(-1); // Assign an invalid value so definitely changes
101
102       if(Scripting::GetEnumerationProperty<Toolkit::Visual::Transform::Policy::Type>(array->GetElementAt(0), POLICY_TABLE, POLICY_TABLE_COUNT, xPolicy) &&
103          Scripting::GetEnumerationProperty<Toolkit::Visual::Transform::Policy::Type>(array->GetElementAt(1), POLICY_TABLE, POLICY_TABLE_COUNT, yPolicy))
104       {
105         policy.x = xPolicy;
106         policy.y = yPolicy;
107         success  = true;
108       }
109     }
110   }
111   return success;
112 }
113
114 } // unnamed namespace
115
116 Internal::Visual::Base::Impl::Impl(FittingMode fittingMode, Toolkit::Visual::Type type)
117 : mCustomShader(NULL),
118   mEventObserver(NULL),
119   mTransform(),
120   mMixColor(Color::WHITE),
121   mControlSize(Vector2::ZERO),
122   mCornerRadius(Vector4::ZERO),
123   mCornerRadiusPolicy(1.0f),
124   mDepthIndex(0.0f),
125   mMixColorIndex(Property::INVALID_INDEX),
126   mCornerRadiusIndex(Property::INVALID_INDEX),
127   mFittingMode(fittingMode),
128   mFlags(0),
129   mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
130   mType(type),
131   mNeedCornerRadius(false)
132 {
133 }
134
135 Internal::Visual::Base::Impl::~Impl()
136 {
137   delete mCustomShader;
138 }
139
140 Internal::Visual::Base::Impl::CustomShader::CustomShader(const Property::Map& map)
141 : mGridSize(1, 1),
142   mHints(Shader::Hint::NONE)
143 {
144   SetPropertyMap(map);
145 }
146
147 void Internal::Visual::Base::Impl::CustomShader::SetPropertyMap(const Property::Map& shaderMap)
148 {
149   mVertexShader.clear();
150   mFragmentShader.clear();
151   mGridSize = ImageDimensions(1, 1);
152   mHints    = Shader::Hint::NONE;
153
154   Property::Value* vertexShaderValue = shaderMap.Find(Toolkit::Visual::Shader::Property::VERTEX_SHADER, CUSTOM_VERTEX_SHADER);
155   if(vertexShaderValue)
156   {
157     if(!GetStringFromProperty(*vertexShaderValue, mVertexShader))
158     {
159       DALI_LOG_ERROR("'%s' parameter does not correctly specify a string\n", CUSTOM_VERTEX_SHADER);
160     }
161   }
162
163   Property::Value* fragmentShaderValue = shaderMap.Find(Toolkit::Visual::Shader::Property::FRAGMENT_SHADER, CUSTOM_FRAGMENT_SHADER);
164   if(fragmentShaderValue)
165   {
166     if(!GetStringFromProperty(*fragmentShaderValue, mFragmentShader))
167     {
168       DALI_LOG_ERROR("'%s' parameter does not correctly specify a string\n", CUSTOM_FRAGMENT_SHADER);
169     }
170   }
171
172   Property::Value* subdivideXValue = shaderMap.Find(Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_X, CUSTOM_SUBDIVIDE_GRID_X);
173   if(subdivideXValue)
174   {
175     int subdivideX;
176     if(!subdivideXValue->Get(subdivideX) || subdivideX < 1)
177     {
178       DALI_LOG_ERROR("'%s' parameter does not correctly specify a value greater than 1\n", CUSTOM_SUBDIVIDE_GRID_X);
179     }
180     else
181     {
182       mGridSize = ImageDimensions(subdivideX, mGridSize.GetY());
183     }
184   }
185
186   Property::Value* subdivideYValue = shaderMap.Find(Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_Y, CUSTOM_SUBDIVIDE_GRID_Y);
187   if(subdivideYValue)
188   {
189     int subdivideY;
190     if(!subdivideYValue->Get(subdivideY) || subdivideY < 1)
191     {
192       DALI_LOG_ERROR("'%s' parameter does not correctly specify a value greater than 1\n", CUSTOM_SUBDIVIDE_GRID_Y);
193     }
194     else
195     {
196       mGridSize = ImageDimensions(mGridSize.GetX(), subdivideY);
197     }
198   }
199
200   Property::Value* hintsValue = shaderMap.Find(Toolkit::Visual::Shader::Property::HINTS, CUSTOM_SHADER_HINTS);
201   if(hintsValue)
202   {
203     if(!Scripting::GetBitmaskEnumerationProperty(*hintsValue, SHADER_HINT_TABLE, SHADER_HINT_TABLE_COUNT, mHints))
204     {
205       DALI_LOG_ERROR("'%s' parameter does not correctly specify a hint or an array of hint strings\n", CUSTOM_SHADER_HINTS);
206     }
207   }
208 }
209
210 void Internal::Visual::Base::Impl::CustomShader::CreatePropertyMap(Property::Map& map) const
211 {
212   if(!mVertexShader.empty() || !mFragmentShader.empty())
213   {
214     Property::Map customShader;
215     if(!mVertexShader.empty())
216     {
217       customShader.Insert(Toolkit::Visual::Shader::Property::VERTEX_SHADER, mVertexShader);
218     }
219     if(!mFragmentShader.empty())
220     {
221       customShader.Insert(Toolkit::Visual::Shader::Property::FRAGMENT_SHADER, mFragmentShader);
222     }
223
224     if(mGridSize.GetWidth() != 1)
225     {
226       customShader.Insert(Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_X, mGridSize.GetWidth());
227     }
228     if(mGridSize.GetHeight() != 1)
229     {
230       customShader.Insert(Toolkit::Visual::Shader::Property::SUBDIVIDE_GRID_Y, mGridSize.GetHeight());
231     }
232
233     if(mHints != Dali::Shader::Hint::NONE)
234     {
235       customShader.Insert(Toolkit::Visual::Shader::Property::HINTS, static_cast<int>(mHints));
236     }
237
238     map.Insert(Toolkit::Visual::Property::SHADER, customShader);
239   }
240 }
241
242 Internal::Visual::Base::Impl::Transform::Transform()
243 : mOffset(0.0f, 0.0f),
244   mSize(1.0f, 1.0f),
245   mExtraSize(0.0f, 0.0f),
246   mOffsetSizeMode(0.0f, 0.0f, 0.0f, 0.0f),
247   mOrigin(Toolkit::Align::TOP_BEGIN),
248   mAnchorPoint(Toolkit::Align::TOP_BEGIN),
249   mOffsetIndex(Property::INVALID_INDEX),
250   mSizeIndex(Property::INVALID_INDEX)
251 {
252 }
253
254 void Internal::Visual::Base::Impl::Transform::SetPropertyMap(const Property::Map& map)
255 {
256   // Set default values
257   mOffset         = Vector2(0.0f, 0.0f);
258   mSize           = Vector2(1.0f, 1.0f);
259   mExtraSize      = Vector2(0.0f, 0.0f);
260   mOffsetSizeMode = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
261   mOrigin         = Toolkit::Align::TOP_BEGIN;
262   mAnchorPoint    = Toolkit::Align::TOP_BEGIN;
263
264   UpdatePropertyMap(map);
265 }
266
267 void Internal::Visual::Base::Impl::Transform::UpdatePropertyMap(const Property::Map& map)
268 {
269   for(Property::Map::SizeType i(0); i < map.Count(); ++i)
270   {
271     KeyValuePair keyValue = map.GetKeyValue(i);
272     if(keyValue.first.type == Property::Key::INDEX)
273     {
274       switch(keyValue.first.indexKey)
275       {
276         case Toolkit::Visual::Transform::Property::OFFSET:
277         {
278           keyValue.second.Get(mOffset);
279           break;
280         }
281         case Toolkit::Visual::Transform::Property::SIZE:
282         {
283           keyValue.second.Get(mSize);
284           break;
285         }
286         case Toolkit::Visual::Transform::Property::ORIGIN:
287         {
288           Scripting::GetEnumerationProperty<Toolkit::Align::Type>(keyValue.second, ALIGN_TABLE, ALIGN_TABLE_COUNT, mOrigin);
289           break;
290         }
291         case Toolkit::Visual::Transform::Property::ANCHOR_POINT:
292         {
293           Scripting::GetEnumerationProperty<Toolkit::Align::Type>(keyValue.second, ALIGN_TABLE, ALIGN_TABLE_COUNT, mAnchorPoint);
294           break;
295         }
296         case Toolkit::Visual::Transform::Property::OFFSET_POLICY:
297         {
298           Vector2 policy;
299           if(GetPolicyFromValue(keyValue.second, policy))
300           {
301             mOffsetSizeMode.x = policy.x;
302             mOffsetSizeMode.y = policy.y;
303           }
304           break;
305         }
306         case Toolkit::Visual::Transform::Property::SIZE_POLICY:
307         {
308           Vector2 policy;
309           if(GetPolicyFromValue(keyValue.second, policy))
310           {
311             mOffsetSizeMode.z = policy.x;
312             mOffsetSizeMode.w = policy.y;
313           }
314           break;
315         }
316         case Toolkit::DevelVisual::Transform::Property::EXTRA_SIZE:
317         {
318           keyValue.second.Get(mExtraSize);
319           break;
320         }
321       }
322     }
323     else // Key type is STRING
324     {
325       if(keyValue.first == "offset")
326       {
327         keyValue.second.Get(mOffset);
328       }
329       else if(keyValue.first == "size")
330       {
331         keyValue.second.Get(mSize);
332       }
333       else if(keyValue.first == "origin")
334       {
335         Scripting::GetEnumerationProperty<Toolkit::Align::Type>(keyValue.second, ALIGN_TABLE, ALIGN_TABLE_COUNT, mOrigin);
336       }
337       else if(keyValue.first == "anchorPoint")
338       {
339         Scripting::GetEnumerationProperty<Toolkit::Align::Type>(keyValue.second, ALIGN_TABLE, ALIGN_TABLE_COUNT, mAnchorPoint);
340       }
341       else if(keyValue.first == "offsetPolicy")
342       {
343         Vector2 policy;
344         if(GetPolicyFromValue(keyValue.second, policy))
345         {
346           mOffsetSizeMode.x = policy.x;
347           mOffsetSizeMode.y = policy.y;
348         }
349       }
350       else if(keyValue.first == "sizePolicy")
351       {
352         Vector2 policy;
353         if(GetPolicyFromValue(keyValue.second, policy))
354         {
355           mOffsetSizeMode.z = policy.x;
356           mOffsetSizeMode.w = policy.y;
357         }
358       }
359       else if(keyValue.first == "extraSize")
360       {
361         keyValue.second.Get(mExtraSize);
362       }
363     }
364   }
365 }
366
367 void Internal::Visual::Base::Impl::Transform::GetPropertyMap(Property::Map& map) const
368 {
369   map.Clear();
370   map.Add(Toolkit::Visual::Transform::Property::OFFSET, mOffset)
371     .Add(Toolkit::Visual::Transform::Property::SIZE, mSize)
372     .Add(Toolkit::Visual::Transform::Property::ORIGIN, mOrigin)
373     .Add(Toolkit::Visual::Transform::Property::ANCHOR_POINT, mAnchorPoint)
374     .Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2(mOffsetSizeMode.x, mOffsetSizeMode.y))
375     .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2(mOffsetSizeMode.z, mOffsetSizeMode.w))
376     .Add(Toolkit::DevelVisual::Transform::Property::EXTRA_SIZE, mExtraSize);
377 }
378
379 void Internal::Visual::Base::Impl::Transform::RegisterUniforms(Dali::Renderer renderer, Toolkit::Direction::Type direction)
380 {
381   mSizeIndex   = renderer.RegisterProperty(SIZE, mSize);
382   mOffsetIndex = renderer.RegisterProperty(OFFSET, direction == Toolkit::Direction::LEFT_TO_RIGHT ? mOffset : mOffset * Vector2(-1.0f, 1.0f));
383   renderer.RegisterProperty(OFFSET_SIZE_MODE, mOffsetSizeMode);
384   renderer.RegisterProperty(ORIGIN, PointToVector2(mOrigin, direction) - Vector2(0.5, 0.5));
385   renderer.RegisterProperty(ANCHOR_POINT, Vector2(0.5, 0.5) - PointToVector2(mAnchorPoint, direction));
386   renderer.RegisterProperty(EXTRA_SIZE, mExtraSize);
387 }
388
389 Vector2 Internal::Visual::Base::Impl::Transform::GetVisualSize(const Vector2& controlSize)
390 {
391   return Vector2(Lerp(mOffsetSizeMode.z, mSize.x * controlSize.x, mSize.x),
392                  Lerp(mOffsetSizeMode.w, mSize.y * controlSize.y, mSize.y)) +
393          mExtraSize;
394 }
395
396 } // namespace Internal
397
398 } // namespace Toolkit
399
400 } // namespace Dali