Merge "Reduce Render::Renderer size" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-relayouter.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/internal/event/actors/actor-relayouter.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/actors/actor.h>
24 #include <dali/public-api/math/vector2.h>
25 #include <dali/public-api/math/vector3.h>
26
27 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
29
30 #if defined(DEBUG_ENABLED)
31 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER");
32 #endif
33
34 namespace Dali
35 {
36 namespace Internal
37 {
38 ActorSizer::Relayouter::Relayouter()
39 : sizeModeFactor(DEFAULT_SIZE_MODE_FACTOR),
40   preferredSize(DEFAULT_PREFERRED_SIZE),
41   sizeSetPolicy(DEFAULT_SIZE_SCALE_POLICY),
42   relayoutEnabled(false),
43   insideRelayout(false),
44   relayoutRequested(false)
45 {
46   // Set size negotiation defaults
47   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
48   {
49     resizePolicies[i]        = ResizePolicy::DEFAULT;
50     useAssignedSize[i]       = false;
51     negotiatedDimensions[i]  = 0.0f;
52     dimensionNegotiated[i]   = false;
53     dimensionDirty[i]        = false;
54     dimensionDependencies[i] = Dimension::ALL_DIMENSIONS;
55     dimensionPadding[i]      = DEFAULT_DIMENSION_PADDING;
56     minimumSize[i]           = 0.0f;
57     maximumSize[i]           = FLT_MAX;
58   }
59 }
60
61 ResizePolicy::Type ActorSizer::Relayouter::GetResizePolicy(Dimension::Type dimension) const
62 {
63   // If more than one dimension is requested, just return the first one found
64   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
65   {
66     if((dimension & (1 << i)))
67     {
68       if(useAssignedSize[i])
69       {
70         return ResizePolicy::USE_ASSIGNED_SIZE;
71       }
72       else
73       {
74         return resizePolicies[i];
75       }
76     }
77   }
78
79   return ResizePolicy::DEFAULT;
80 }
81
82 Vector2 ActorSizer::Relayouter::ApplySizeSetPolicy(Internal::Actor& actor, const Vector2& size)
83 {
84   switch(sizeSetPolicy)
85   {
86     case SizeScalePolicy::USE_SIZE_SET:
87     {
88       return size;
89     }
90
91     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
92     {
93       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
94       const Vector3 naturalSize = actor.GetNaturalSize();
95       if(naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f)
96       {
97         const float sizeRatio        = size.width / size.height;
98         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
99
100         if(naturalSizeRatio < sizeRatio)
101         {
102           return Vector2(naturalSizeRatio * size.height, size.height);
103         }
104         else if(naturalSizeRatio > sizeRatio)
105         {
106           return Vector2(size.width, size.width / naturalSizeRatio);
107         }
108         else
109         {
110           return size;
111         }
112       }
113
114       break;
115     }
116
117     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
118     {
119       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
120       const Vector3 naturalSize = actor.GetNaturalSize();
121       if(naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f)
122       {
123         const float sizeRatio        = size.width / size.height;
124         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
125
126         if(naturalSizeRatio < sizeRatio)
127         {
128           return Vector2(size.width, size.width / naturalSizeRatio);
129         }
130         else if(naturalSizeRatio > sizeRatio)
131         {
132           return Vector2(naturalSizeRatio * size.height, size.height);
133         }
134         else
135         {
136           return size;
137         }
138       }
139       break;
140     }
141
142     default:
143     {
144       break;
145     }
146   }
147
148   return size;
149 }
150
151 void ActorSizer::Relayouter::SetUseAssignedSize(bool use, Dimension::Type dimension)
152 {
153   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
154   {
155     if(dimension & (1 << i))
156     {
157       useAssignedSize[i] = use;
158     }
159   }
160 }
161
162 bool ActorSizer::Relayouter::GetUseAssignedSize(Dimension::Type dimension) const
163 {
164   // If more than one dimension is requested, just return the first one found
165   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
166   {
167     if(dimension & (1 << i))
168     {
169       return useAssignedSize[i];
170     }
171   }
172
173   return false;
174 }
175
176 void ActorSizer::Relayouter::SetMinimumSize(float size, Dimension::Type dimension)
177 {
178   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
179   {
180     if(dimension & (1 << i))
181     {
182       minimumSize[i] = size;
183     }
184   }
185 }
186
187 float ActorSizer::Relayouter::GetMinimumSize(Dimension::Type dimension) const
188 {
189   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
190   {
191     if(dimension & (1 << i))
192     {
193       return minimumSize[i];
194     }
195   }
196
197   return 0.0f; // Default
198 }
199
200 void ActorSizer::Relayouter::SetMaximumSize(float size, Dimension::Type dimension)
201 {
202   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
203   {
204     if(dimension & (1 << i))
205     {
206       maximumSize[i] = size;
207     }
208   }
209 }
210
211 float ActorSizer::Relayouter::GetMaximumSize(Dimension::Type dimension) const
212 {
213   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
214   {
215     if(dimension & (1 << i))
216     {
217       return maximumSize[i];
218     }
219   }
220
221   return FLT_MAX; // Default
222 }
223
224 void ActorSizer::Relayouter::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension, Vector3& targetSize, bool& targetSizeDirtyFlag)
225 {
226   ResizePolicy::Type originalWidthPolicy  = GetResizePolicy(Dimension::WIDTH);
227   ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
228
229   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
230   {
231     if(dimension & (1 << i))
232     {
233       if(policy == ResizePolicy::USE_ASSIGNED_SIZE)
234       {
235         useAssignedSize[i] = true;
236       }
237       else
238       {
239         resizePolicies[i]  = policy;
240         useAssignedSize[i] = false;
241       }
242     }
243   }
244
245   if(policy == ResizePolicy::DIMENSION_DEPENDENCY)
246   {
247     if(dimension & Dimension::WIDTH)
248     {
249       SetDimensionDependency(Dimension::WIDTH, Dimension::HEIGHT);
250     }
251
252     if(dimension & Dimension::HEIGHT)
253     {
254       SetDimensionDependency(Dimension::HEIGHT, Dimension::WIDTH);
255     }
256   }
257
258   // If calling SetResizePolicy, assume we want relayout enabled
259   relayoutEnabled = true;
260
261   // If the resize policy is set to be FIXED, the preferred size
262   // should be overrided by the target size. Otherwise the target
263   // size should be overrided by the preferred size.
264
265   if(dimension & Dimension::WIDTH)
266   {
267     if(originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED)
268     {
269       preferredSize.width = targetSize.width;
270     }
271     else if(originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED)
272     {
273       targetSize.width = preferredSize.width;
274       targetSizeDirtyFlag = true;
275     }
276   }
277
278   if(dimension & Dimension::HEIGHT)
279   {
280     if(originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED)
281     {
282       preferredSize.height = targetSize.height;
283     }
284     else if(originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED)
285     {
286       targetSize.height = preferredSize.height;
287       targetSizeDirtyFlag = true;
288     }
289   }
290 }
291
292 bool ActorSizer::Relayouter::GetRelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependency)
293 {
294   // Check each possible dimension and see if it is dependent on the input one
295   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
296   {
297     if(dimension & (1 << i))
298     {
299       return resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && dimensionDependencies[i] == dependency;
300     }
301   }
302
303   return false;
304 }
305
306 void ActorSizer::Relayouter::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
307 {
308   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
309   {
310     if(dimension & (1 << i))
311     {
312       dimensionDependencies[i] = dependency;
313     }
314   }
315 }
316
317 Dimension::Type ActorSizer::Relayouter::GetDimensionDependency(Dimension::Type dimension) const
318 {
319   // If more than one dimension is requested, just return the first one found
320   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
321   {
322     if((dimension & (1 << i)))
323     {
324       return dimensionDependencies[i];
325     }
326   }
327
328   return Dimension::ALL_DIMENSIONS; // Default
329 }
330
331 void ActorSizer::Relayouter::SetLayoutDirty(bool dirty, Dimension::Type dimension)
332 {
333   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
334   {
335     if(dimension & (1 << i))
336     {
337       dimensionDirty[i] = dirty;
338     }
339   }
340 }
341
342 bool ActorSizer::Relayouter::IsLayoutDirty(Dimension::Type dimension) const
343 {
344   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
345   {
346     if((dimension & (1 << i)) && dimensionDirty[i])
347     {
348       return true;
349     }
350   }
351
352   return false;
353 }
354
355 void ActorSizer::Relayouter::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
356 {
357   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
358   {
359     if(dimension & (1 << i))
360     {
361       negotiatedDimensions[i] = negotiatedDimension;
362     }
363   }
364 }
365
366 float ActorSizer::Relayouter::GetNegotiatedDimension(Dimension::Type dimension)
367 {
368   // If more than one dimension is requested, just return the first one found
369   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
370   {
371     if((dimension & (1 << i)))
372     {
373       return negotiatedDimensions[i];
374     }
375   }
376
377   return 0.0f; // Default
378 }
379
380 void ActorSizer::Relayouter::SetPadding(const Vector2& padding, Dimension::Type dimension)
381 {
382   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
383   {
384     if(dimension & (1 << i))
385     {
386       dimensionPadding[i] = padding;
387     }
388   }
389 }
390
391 Vector2 ActorSizer::Relayouter::GetPadding(Dimension::Type dimension)
392 {
393   // If more than one dimension is requested, just return the first one found
394   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
395   {
396     if((dimension & (1 << i)))
397     {
398       return dimensionPadding[i];
399     }
400   }
401
402   return DEFAULT_DIMENSION_PADDING;
403 }
404
405 void ActorSizer::Relayouter::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
406 {
407   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
408   {
409     if(dimension & (1 << i))
410     {
411       dimensionNegotiated[i] = negotiated;
412     }
413   }
414 }
415
416 bool ActorSizer::Relayouter::IsLayoutNegotiated(Dimension::Type dimension) const
417 {
418   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
419   {
420     if((dimension & (1 << i)) && dimensionNegotiated[i])
421     {
422       return true;
423     }
424   }
425   return false;
426 }
427
428 } // namespace Internal
429
430 } // namespace Dali