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