• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_NG_PROPERTIES_SIZE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_NG_PROPERTIES_SIZE_H
18 
19 #include <cstdint>
20 #include <iomanip>
21 #include <optional>
22 #include <sstream>
23 #include <string>
24 
25 #include "base/geometry/axis.h"
26 #include "base/utils/utils.h"
27 
28 namespace OHOS::Ace::NG {
29 template<typename T>
30 class SizeT {
31 public:
32     SizeT() = default;
33     ~SizeT() = default;
SizeT(T width,T height)34     SizeT(T width, T height) : width_(width), height_(height) {}
35 
Reset()36     void Reset()
37     {
38         width_ = 0;
39         height_ = 0;
40     }
41 
Width()42     T Width() const
43     {
44         return width_;
45     }
46 
Height()47     T Height() const
48     {
49         return height_;
50     }
51 
MainSize(Axis axis)52     T MainSize(Axis axis) const
53     {
54         return axis == Axis::HORIZONTAL ? width_ : height_;
55     }
56 
CrossSize(Axis axis)57     T CrossSize(Axis axis) const
58     {
59         return axis == Axis::HORIZONTAL ? height_ : width_;
60     }
61 
SetWidth(T width)62     void SetWidth(T width)
63     {
64         width_ = width;
65     }
66 
SetHeight(T height)67     void SetHeight(T height)
68     {
69         height_ = height;
70     }
71 
SetMainSize(T mainSize,Axis axis)72     void SetMainSize(T mainSize, Axis axis)
73     {
74         axis == Axis::HORIZONTAL ? width_ = mainSize : height_ = mainSize;
75     }
76 
SetCrossSize(T crossSize,Axis axis)77     void SetCrossSize(T crossSize, Axis axis)
78     {
79         axis == Axis::HORIZONTAL ? height_ = crossSize : width_ = crossSize;
80     }
81 
SetSizeT(const SizeT & SizeT)82     void SetSizeT(const SizeT& SizeT)
83     {
84         width_ = SizeT.Width();
85         height_ = SizeT.Height();
86     }
87 
AddHeight(T height)88     SizeT& AddHeight(T height)
89     {
90         height_ += height;
91         return *this;
92     }
93 
AddWidth(T value)94     SizeT& AddWidth(T value)
95     {
96         width_ += value;
97         return *this;
98     }
99 
MinusHeight(T height)100     SizeT& MinusHeight(T height)
101     {
102         height_ -= height;
103         return *this;
104     }
105 
MinusWidth(T width)106     SizeT& MinusWidth(T width)
107     {
108         width_ -= width;
109         return *this;
110     }
111 
MinusPadding(const std::optional<T> & left,const std::optional<T> & right,const std::optional<T> & top,const std::optional<T> & bottom)112     void MinusPadding(const std::optional<T>& left, const std::optional<T>& right, const std::optional<T>& top,
113         const std::optional<T>& bottom)
114     {
115         T tempWidth = width_ - left.value_or(0) - right.value_or(0);
116         if (NonNegative(tempWidth)) {
117             width_ = tempWidth;
118         }
119         T tempHeight = height_ - top.value_or(0) - bottom.value_or(0);
120         if (NonNegative(tempHeight)) {
121             height_ = tempHeight;
122         }
123     }
124 
AddPadding(const std::optional<T> & left,const std::optional<T> & right,const std::optional<T> & top,const std::optional<T> & bottom)125     void AddPadding(const std::optional<T>& left, const std::optional<T>& right, const std::optional<T>& top,
126         const std::optional<T>& bottom)
127     {
128         width_ = width_ + left.value_or(0) + right.value_or(0);
129         height_ = height_ + top.value_or(0) + bottom.value_or(0);
130     }
131 
IsNonNegative()132     bool IsNonNegative() const
133     {
134         return NonNegative(width_) && NonNegative(height_);
135     }
136 
137     // width and height all less than zero.
IsNegative()138     bool IsNegative() const
139     {
140         return Negative(width_) && Negative(height_);
141     }
142 
IsPositive()143     bool IsPositive() const
144     {
145         return Positive(width_) && Positive(height_);
146     }
147 
IsNonPositive()148     bool IsNonPositive() const
149     {
150         return NonPositive(width_) && NonPositive(height_);
151     }
152 
UpdateSizeWithCheck(const SizeT & size)153     bool UpdateSizeWithCheck(const SizeT& size)
154     {
155         bool isModified = false;
156         if (NonNegative(size.width_) && (width_ != size.width_)) {
157             width_ = size.width_;
158             isModified = true;
159         }
160         if (NonNegative(size.height_) && (height_ != size.height_)) {
161             height_ = size.height_;
162             isModified = true;
163         }
164         return isModified;
165     }
166 
UpdateIllegalSizeWithCheck(const SizeT & size)167     void UpdateIllegalSizeWithCheck(const SizeT& size)
168     {
169         if (Negative(width_) && NonNegative(size.width_)) {
170             width_ = size.width_;
171         }
172         if (Negative(height_) && NonNegative(size.height_)) {
173             height_ = size.height_;
174         }
175     }
176 
UpdateSizeWhenLarger(const SizeT & size)177     bool UpdateSizeWhenLarger(const SizeT& size)
178     {
179         bool isModified = false;
180         if (NonNegative(size.width_)) {
181             auto temp = width_ > size.width_ ? width_ : size.width_;
182             if (width_ != temp) {
183                 isModified = true;
184             }
185             width_ = temp;
186         }
187         if (NonNegative(size.height_)) {
188             auto temp = height_ > size.height_ ? height_ : size.height_;
189             if (height_ != temp) {
190                 isModified = true;
191             }
192             height_ = temp;
193         }
194         return isModified;
195     }
196 
UpdateSizeWhenSmaller(const SizeT & size)197     bool UpdateSizeWhenSmaller(const SizeT& size)
198     {
199         bool isModified = false;
200         if (NonNegative(size.width_)) {
201             auto temp = width_ < size.width_ ? width_ : size.width_;
202             if (width_ != temp) {
203                 isModified = true;
204             }
205             width_ = temp;
206         }
207         if (NonNegative(size.height_)) {
208             auto temp = height_ < size.height_ ? height_ : size.height_;
209             if (height_ != temp) {
210                 isModified = true;
211             }
212             height_ = temp;
213         }
214         return isModified;
215     }
216 
UpdateMin(const SizeT & minSize)217     void UpdateMin(const SizeT& minSize)
218     {
219         if (NonNegative(minSize.width_)) {
220             width_ = width_ > minSize.Width() ? width_ : minSize.Width();
221         }
222         if (NonNegative(minSize.height_)) {
223             height_ = height_ > minSize.Height() ? height_ : minSize.Height();
224         }
225     }
226 
UpdateMax(const SizeT & maxSize)227     void UpdateMax(const SizeT& maxSize)
228     {
229         if (NonNegative(maxSize.width_)) {
230             width_ = width_ < maxSize.Width() ? width_ : maxSize.Width();
231         }
232         if (NonNegative(maxSize.height_)) {
233             height_ = height_ < maxSize.Height() ? height_ : maxSize.Height();
234         }
235     }
236 
237     void Constrain(const SizeT& minSize, const SizeT& maxSize, bool version10OrLarger = false)
238     {
239         if (version10OrLarger) {
240             UpdateMax(maxSize);
241             UpdateMin(minSize);
242             return;
243         }
244         UpdateMin(minSize);
245         UpdateMax(maxSize);
246     }
247 
248     SizeT operator*(double value) const
249     {
250         return SizeT(width_ * value, height_ * value);
251     }
252 
253     bool operator==(const SizeT& size) const
254     {
255         return NearEqual(width_, size.width_) && NearEqual(height_, size.height_);
256     }
257 
258     bool operator!=(const SizeT& size) const
259     {
260         return !operator==(size);
261     }
262 
263     SizeT operator+(const SizeT& size) const
264     {
265         return SizeT(width_ + size.Width(), height_ + size.Height());
266     }
267 
268     SizeT& operator+=(const SizeT& size)
269     {
270         width_ += size.Width();
271         height_ += size.Height();
272         return *this;
273     }
274 
275     SizeT operator-(const SizeT& size) const
276     {
277         return SizeT(width_ - size.Width(), height_ - size.Height());
278     }
279 
280     SizeT& operator-=(const SizeT& size)
281     {
282         width_ -= size.Width();
283         height_ -= size.Height();
284         return *this;
285     }
286 
DivideScale(float scale)287     void DivideScale(float scale)
288     {
289         if (NearZero(scale)) {
290             return;
291         }
292         width_ /= scale;
293         height_ /= scale;
294     }
295 
ApplyScale(double scale)296     void ApplyScale(double scale)
297     {
298         width_ *= scale;
299         height_ *= scale;
300     }
301 
302     /*
303      * Please make sure that two SizeTs are both valid.
304      * You can use IsValid() to see if a SizeT is valid.
305      */
306     bool operator>(const SizeT& SizeT) const
307     {
308         if (IsNonNegative() && SizeT.IsNonNegative()) {
309             return GreatOrEqual(width_, SizeT.width_) && GreatOrEqual(height_, SizeT.height_);
310         }
311         return false;
312     }
313 
314     /*
315      * Please make sure that two SizeTs are both valid.
316      * You can use IsValid() to see if a SizeT is valid.
317      */
318     bool operator<(const SizeT& SizeT) const
319     {
320         if (IsNonNegative() && SizeT.IsNonNegative()) {
321             return LessOrEqual(width_, SizeT.width_) && LessOrEqual(height_, SizeT.height_);
322         }
323         return false;
324     }
325 
CalcRatio()326     double CalcRatio() const
327     {
328         return static_cast<double>(width_) / static_cast<double>(height_);
329     }
330 
ToString()331     std::string ToString() const
332     {
333         static const int32_t precision = 2;
334         std::stringstream ss;
335         ss << "[" << std::fixed << std::setprecision(precision);
336         ss << width_;
337         ss << " x ";
338         ss << height_;
339         ss << "]";
340         std::string output = ss.str();
341         return output;
342     }
343 
344 private:
345     T width_ { 0 };
346     T height_ { 0 };
347 };
348 
349 using SizeF = SizeT<float>;
350 
351 template<typename T>
352 class OptionalSize {
353 public:
354     OptionalSize() = default;
355     ~OptionalSize() = default;
OptionalSize(const std::optional<T> & width,const std::optional<T> & height)356     OptionalSize(const std::optional<T>& width, const std::optional<T>& height) : width_(width), height_(height) {}
OptionalSize(const T & width,const T & height)357     OptionalSize(const T& width, const T& height) : width_(width), height_(height) {}
OptionalSize(const SizeT<T> & size)358     explicit OptionalSize(const SizeT<T>& size) : width_(size.Width()), height_(size.Height()) {}
359 
Reset()360     void Reset()
361     {
362         width_.reset();
363         height_.reset();
364     }
365 
Width()366     const std::optional<T>& Width() const
367     {
368         return width_;
369     }
370 
Height()371     const std::optional<T>& Height() const
372     {
373         return height_;
374     }
375 
MainSize(Axis axis)376     const std::optional<T>& MainSize(Axis axis) const
377     {
378         return axis == Axis::HORIZONTAL ? width_ : height_;
379     }
380 
CrossSize(Axis axis)381     const std::optional<T>& CrossSize(Axis axis) const
382     {
383         return axis == Axis::HORIZONTAL ? height_ : width_;
384     }
385 
SetWidth(T width)386     void SetWidth(T width)
387     {
388         width_ = width;
389     }
390 
SetHeight(T height)391     void SetHeight(T height)
392     {
393         height_ = height;
394     }
395 
SetMainSize(T mainSize,Axis axis)396     void SetMainSize(T mainSize, Axis axis)
397     {
398         axis == Axis::HORIZONTAL ? width_ = mainSize : height_ = mainSize;
399     }
400 
SetCrossSize(T crossSize,Axis axis)401     void SetCrossSize(T crossSize, Axis axis)
402     {
403         axis == Axis::HORIZONTAL ? height_ = crossSize : width_ = crossSize;
404     }
405 
SetWidth(const std::optional<T> & width)406     void SetWidth(const std::optional<T>& width)
407     {
408         width_ = width;
409     }
410 
SetHeight(const std::optional<T> & height)411     void SetHeight(const std::optional<T>& height)
412     {
413         height_ = height;
414     }
415 
SetSize(const SizeT<T> & sizeF)416     void SetSize(const SizeT<T>& sizeF)
417     {
418         width_ = sizeF.Width();
419         height_ = sizeF.Height();
420     }
421 
SetOptionalSize(const OptionalSize & size)422     void SetOptionalSize(const OptionalSize& size)
423     {
424         width_ = size.Width();
425         height_ = size.Height();
426     }
427 
AddHeight(float height)428     OptionalSize& AddHeight(float height)
429     {
430         height_ = height_.value_or(0) + height;
431         return *this;
432     }
433 
AddWidth(float width)434     OptionalSize& AddWidth(float width)
435     {
436         width_ = width_.value_or(0) + width;
437         return *this;
438     }
439 
MinusHeight(float height)440     OptionalSize& MinusHeight(float height)
441     {
442         height_ = height_.value_or(0) - height;
443         return *this;
444     }
445 
MinusWidth(float width)446     OptionalSize& MinusWidth(float width)
447     {
448         width_ = width_.value_or(0) - width;
449         return *this;
450     }
451 
MinusPadding(const std::optional<T> & left,const std::optional<T> & right,const std::optional<T> & top,const std::optional<T> & bottom)452     void MinusPadding(const std::optional<T>& left, const std::optional<T>& right, const std::optional<T>& top,
453         const std::optional<T>& bottom)
454     {
455         if (width_) {
456             T tempWidth = width_.value() - left.value_or(0) - right.value_or(0);
457             width_ = NonNegative(tempWidth) ? tempWidth : 0;
458         }
459         if (height_) {
460             T tempHeight = height_.value() - top.value_or(0) - bottom.value_or(0);
461             height_ = NonNegative(tempHeight) ? tempHeight : 0;
462         }
463     }
464 
AddPadding(const std::optional<T> & left,const std::optional<T> & right,const std::optional<T> & top,const std::optional<T> & bottom)465     void AddPadding(const std::optional<T>& left, const std::optional<T>& right, const std::optional<T>& top,
466         const std::optional<T>& bottom)
467     {
468         if (width_) {
469             width_ = width_.value() + left.value_or(0) + right.value_or(0);
470         }
471         if (height_) {
472             height_ = height_.value() + top.value_or(0) + bottom.value_or(0);
473         }
474     }
475 
IsValid()476     bool IsValid() const
477     {
478         return width_ && height_;
479     }
480 
AtLeastOneValid()481     bool AtLeastOneValid() const
482     {
483         return width_ || height_;
484     }
485 
IsNull()486     bool IsNull() const
487     {
488         return !width_ && !height_;
489     }
490 
IsNonNegative()491     bool IsNonNegative() const
492     {
493         return NonNegative(width_.value_or(-1)) && NonNegative(height_.value_or(-1));
494     }
495 
496     // width and height all less than zero.
IsNegative()497     bool IsNegative() const
498     {
499         return Negative(width_.value_or(-1)) && Negative(height_.value_or(-1));
500     }
501 
IsPositive()502     bool IsPositive() const
503     {
504         return Positive(width_.value_or(-1)) && Positive(height_.value_or(-1));
505     }
506 
IsNonPositive()507     bool IsNonPositive() const
508     {
509         return NonPositive(width_.value_or(-1)) && NonPositive(height_.value_or(-1));
510     }
511 
UpdateSizeWithCheck(const OptionalSize & size)512     bool UpdateSizeWithCheck(const OptionalSize& size)
513     {
514         bool isModified = false;
515         if (size.width_ && (width_ != size.width_)) {
516             width_ = size.width_;
517             isModified = true;
518         }
519         if (size.height_ && (height_ != size.height_)) {
520             height_ = size.height_;
521             isModified = true;
522         }
523         return isModified;
524     }
525 
UpdateSizeWithCheck(const SizeT<T> & size)526     bool UpdateSizeWithCheck(const SizeT<T>& size)
527     {
528         bool isModified = false;
529         if (NonNegative(size.Width()) && (width_ != size.Width())) {
530             width_ = size.Width();
531             isModified = true;
532         }
533         if (NonNegative(size.Height()) && (height_ != size.Height())) {
534             height_ = size.Height();
535             isModified = true;
536         }
537         return isModified;
538     }
539 
UpdateIllegalSizeWithCheck(const OptionalSize & size)540     bool UpdateIllegalSizeWithCheck(const OptionalSize& size)
541     {
542         bool isModified = false;
543         if (!width_ && size.Width()) {
544             width_ = size.Width();
545             isModified = true;
546         }
547         if (!height_ && size.Height()) {
548             height_ = size.Height();
549             isModified = true;
550         }
551         return isModified;
552     }
553 
UpdateIllegalSizeWithCheck(const SizeT<T> & size)554     bool UpdateIllegalSizeWithCheck(const SizeT<T>& size)
555     {
556         bool isModified = false;
557         if (!width_.has_value() && NonNegative(size.Width())) {
558             width_ = size.Width();
559             isModified = true;
560         }
561         if (!height_.has_value() && NonNegative(size.Height())) {
562             height_ = size.Height();
563             isModified = true;
564         }
565         return isModified;
566     }
567 
UpdateSizeWhenLarger(const SizeT<T> & size)568     bool UpdateSizeWhenLarger(const SizeT<T>& size)
569     {
570         bool isModified = false;
571         if (NonNegative(size.Width()) && width_) {
572             auto temp = width_.value_or(0) > size.Width() ? width_ : size.Width();
573             if (width_ != temp) {
574                 isModified = true;
575             }
576             width_ = temp;
577         }
578         if (NonNegative(size.Height()) && height_) {
579             auto temp = height_.value_or(0) > size.Height() ? height_ : size.Height();
580             if (height_ != temp) {
581                 isModified = true;
582             }
583             height_ = temp;
584         }
585         return isModified;
586     }
587 
UpdateSizeWhenSmaller(const SizeT<T> & size)588     bool UpdateSizeWhenSmaller(const SizeT<T>& size)
589     {
590         bool isModified = false;
591         if (NonNegative(size.Width())) {
592             auto temp = width_.value_or(0) < size.Width() ? width_ : size.Width();
593             if (width_ != temp) {
594                 isModified = true;
595             }
596             width_ = temp;
597         }
598         if (NonNegative(size.Height())) {
599             auto temp = height_.value_or(0) < size.Height() ? height_ : size.Height();
600             if (height_ != temp) {
601                 isModified = true;
602             }
603             height_ = temp;
604         }
605         return isModified;
606     }
607 
UpdateMin(const SizeT<T> & minSize)608     void UpdateMin(const SizeT<T>& minSize)
609     {
610         if (NonNegative(minSize.Width()) && width_) {
611             width_ = width_.value_or(0) > minSize.Width() ? width_ : minSize.Width();
612         }
613         if (NonNegative(minSize.Height()) && height_) {
614             height_ = height_.value_or(0) > minSize.Height() ? height_ : minSize.Height();
615         }
616     }
617 
UpdateMax(const SizeT<T> & maxSize)618     void UpdateMax(const SizeT<T>& maxSize)
619     {
620         if (NonNegative(maxSize.Width()) && width_) {
621             width_ = width_.value_or(0) < maxSize.Width() ? width_ : maxSize.Width();
622         }
623         if (NonNegative(maxSize.Height()) && height_) {
624             height_ = height_.value_or(0) < maxSize.Height() ? Height() : maxSize.Height();
625         }
626     }
627 
628     void Constrain(const SizeT<T>& minSize, const SizeT<T>& maxSize, bool version10OrLarger = false)
629     {
630         if (version10OrLarger) {
631             UpdateMax(maxSize);
632             UpdateMin(minSize);
633             return;
634         }
635         UpdateMin(minSize);
636         UpdateMax(maxSize);
637     }
638 
639     void ConstrainFloat(const SizeT<T>& minSize, const SizeT<T>& maxSize, bool isWidth, bool version10OrLarger = false)
640     {
641         if (isWidth) {
642             if (version10OrLarger) {
643                 if (NonNegative(maxSize.Width()) && width_) {
644                     width_ = width_.value_or(0) < maxSize.Width() ? width_ : maxSize.Width();
645                 }
646                 if (NonNegative(minSize.Width()) && width_) {
647                     width_ = width_.value_or(0) > minSize.Width() ? width_ : minSize.Width();
648                 }
649                 return;
650             }
651             if (NonNegative(minSize.Width()) && width_) {
652                 width_ = width_.value_or(0) > minSize.Width() ? width_ : minSize.Width();
653             }
654 
655             if (NonNegative(maxSize.Width()) && width_) {
656                 width_ = width_.value_or(0) < maxSize.Width() ? width_ : maxSize.Width();
657             }
658             return;
659         }
660         if (version10OrLarger) {
661             if (NonNegative(maxSize.Height()) && height_) {
662                 height_ = height_.value_or(0) < maxSize.Height() ? Height() : maxSize.Height();
663             }
664             if (NonNegative(minSize.Height()) && height_) {
665                 height_ = height_.value_or(0) > minSize.Height() ? height_ : minSize.Height();
666             }
667             return;
668         }
669         if (NonNegative(minSize.Height()) && height_) {
670             height_ = height_.value_or(0) > minSize.Height() ? height_ : minSize.Height();
671         }
672         if (NonNegative(maxSize.Height()) && height_) {
673             height_ = height_.value_or(0) < maxSize.Height() ? Height() : maxSize.Height();
674         }
675     }
676 
677     OptionalSize operator*(double value) const
678     {
679         return OptionalSize(width_ ? *width_.value() * value : width_, height_ ? height_.value() * value : height_);
680     }
681 
682     bool operator==(const OptionalSize& size) const
683     {
684         if (width_.has_value() ^ size.width_.has_value()) {
685             return false;
686         }
687         if (!NearEqual(width_.value_or(0), size.width_.value_or(0))) {
688             return false;
689         }
690         if (height_.has_value() ^ size.height_.has_value()) {
691             return false;
692         }
693         if (!NearEqual(height_.value_or(0), size.height_.value_or(0))) {
694             return false;
695         }
696         return true;
697     }
698 
699     bool operator!=(const OptionalSize& size) const
700     {
701         return !operator==(size);
702     }
703 
704     OptionalSize operator+(const OptionalSize& size) const
705     {
706         std::optional<T> width;
707         if (width_) {
708             width = width_.value() + size.width_.value_or(0);
709         }
710         std::optional<T> height;
711         if (height_) {
712             height = height_.value() + size.height_.value_or(0);
713         }
714         return OptionalSize(width, height);
715     }
716 
717     OptionalSize& operator+=(const OptionalSize& size)
718     {
719         if (width_) {
720             width_ = width_.value() + size.width_.value_or(0);
721         }
722         if (height_) {
723             height_ = height_.value() + size.height_.value_or(0);
724         }
725         return *this;
726     }
727 
728     OptionalSize operator-(const OptionalSize& size) const
729     {
730         std::optional<T> width;
731         if (width_) {
732             width = width_.value() - size.width_.value_or(0);
733         }
734         std::optional<T> height;
735         if (height_) {
736             height = height_.value() - size.height_.value_or(0);
737         }
738         return OptionalSize(width, height);
739     }
740 
741     OptionalSize& operator-=(const OptionalSize& size)
742     {
743         if (width_) {
744             width_ = width_.value() - size.width_.value_or(0);
745         }
746         if (height_) {
747             height_ = height_.value() - size.height_.value_or(0);
748         }
749         return *this;
750     }
751 
ApplyScale(double scale)752     void ApplyScale(double scale)
753     {
754         width_ = width_ ? width_.value() * scale : width_;
755         height_ = height_ ? height_.value() * scale : height_;
756     }
757 
758     bool operator>(const SizeT<T>& size) const
759     {
760         if (IsNonNegative() && size.IsNonNegative()) {
761             return GreatOrEqual(width_.value_or(0), size.Width()) && GreatOrEqual(height_.value_or(0), size.Height());
762         }
763         return false;
764     }
765 
766     bool operator<(const SizeT<T>& size) const
767     {
768         if (IsNonNegative() && size.IsNonNegative()) {
769             return LessOrEqual(width_.value_or(0), size.Width()) && LessOrEqual(height_.value_or(0), size.Height());
770         }
771         return false;
772     }
773 
CalcRatio()774     double CalcRatio() const
775     {
776         if (NearZero(height_.value_or(0))) {
777             return 0.0;
778         }
779         return static_cast<double>(width_.value_or(0)) / static_cast<double>(height_.value());
780     }
781 
ConvertToSizeT()782     SizeT<T> ConvertToSizeT() const
783     {
784         return { width_.value_or(-1), height_.value_or(-1) };
785     }
786 
ToString()787     std::string ToString() const
788     {
789         static const int32_t precision = 2;
790         std::stringstream ss;
791         ss << "[" << std::fixed << std::setprecision(precision);
792         if (width_) {
793             ss << width_.value();
794         } else {
795             ss << "NA";
796         }
797         ss << " x ";
798         if (height_) {
799             ss << height_.value();
800         } else {
801             ss << "NA";
802         }
803         ss << "]";
804         std::string output = ss.str();
805         return output;
806     }
807 
808 private:
809     std::optional<T> width_;
810     std::optional<T> height_;
811 };
812 
813 using OptionalSizeF = OptionalSize<float>;
814 
815 } // namespace OHOS::Ace::NG
816 
817 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_NG_PROPERTIES_SIZE_H
818