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