Reduce Render::Renderer size
[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)
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     }
275   }
276
277   if(dimension & Dimension::HEIGHT)
278   {
279     if(originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED)
280     {
281       preferredSize.height = targetSize.height;
282     }
283     else if(originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED)
284     {
285       targetSize.height = preferredSize.height;
286     }
287   }
288 }
289
290 bool ActorSizer::Relayouter::GetRelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependency)
291 {
292   // Check each possible dimension and see if it is dependent on the input one
293   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
294   {
295     if(dimension & (1 << i))
296     {
297       return resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && dimensionDependencies[i] == dependency;
298     }
299   }
300
301   return false;
302 }
303
304 void ActorSizer::Relayouter::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
305 {
306   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
307   {
308     if(dimension & (1 << i))
309     {
310       dimensionDependencies[i] = dependency;
311     }
312   }
313 }
314
315 Dimension::Type ActorSizer::Relayouter::GetDimensionDependency(Dimension::Type dimension) const
316 {
317   // If more than one dimension is requested, just return the first one found
318   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
319   {
320     if((dimension & (1 << i)))
321     {
322       return dimensionDependencies[i];
323     }
324   }
325
326   return Dimension::ALL_DIMENSIONS; // Default
327 }
328
329 void ActorSizer::Relayouter::SetLayoutDirty(bool dirty, Dimension::Type dimension)
330 {
331   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
332   {
333     if(dimension & (1 << i))
334     {
335       dimensionDirty[i] = dirty;
336     }
337   }
338 }
339
340 bool ActorSizer::Relayouter::IsLayoutDirty(Dimension::Type dimension) const
341 {
342   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
343   {
344     if((dimension & (1 << i)) && dimensionDirty[i])
345     {
346       return true;
347     }
348   }
349
350   return false;
351 }
352
353 void ActorSizer::Relayouter::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
354 {
355   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
356   {
357     if(dimension & (1 << i))
358     {
359       negotiatedDimensions[i] = negotiatedDimension;
360     }
361   }
362 }
363
364 float ActorSizer::Relayouter::GetNegotiatedDimension(Dimension::Type dimension)
365 {
366   // If more than one dimension is requested, just return the first one found
367   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
368   {
369     if((dimension & (1 << i)))
370     {
371       return negotiatedDimensions[i];
372     }
373   }
374
375   return 0.0f; // Default
376 }
377
378 void ActorSizer::Relayouter::SetPadding(const Vector2& padding, Dimension::Type dimension)
379 {
380   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
381   {
382     if(dimension & (1 << i))
383     {
384       dimensionPadding[i] = padding;
385     }
386   }
387 }
388
389 Vector2 ActorSizer::Relayouter::GetPadding(Dimension::Type dimension)
390 {
391   // If more than one dimension is requested, just return the first one found
392   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
393   {
394     if((dimension & (1 << i)))
395     {
396       return dimensionPadding[i];
397     }
398   }
399
400   return DEFAULT_DIMENSION_PADDING;
401 }
402
403 void ActorSizer::Relayouter::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
404 {
405   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
406   {
407     if(dimension & (1 << i))
408     {
409       dimensionNegotiated[i] = negotiated;
410     }
411   }
412 }
413
414 bool ActorSizer::Relayouter::IsLayoutNegotiated(Dimension::Type dimension) const
415 {
416   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
417   {
418     if((dimension & (1 << i)) && dimensionNegotiated[i])
419     {
420       return true;
421     }
422   }
423   return false;
424 }
425
426 } // namespace Internal
427
428 } // namespace Dali