1/* 2 * Copyright (c) 2012, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#ifndef LayoutUnit_h 32#define LayoutUnit_h 33 34#include "wtf/Assertions.h" 35#include "wtf/MathExtras.h" 36#include "wtf/SaturatedArithmetic.h" 37#include <limits.h> 38#include <limits> 39#include <stdlib.h> 40 41namespace blink { 42 43#if !ERROR_DISABLED 44 45#define REPORT_OVERFLOW(doesOverflow) ((void)0) 46 47#else 48 49#define REPORT_OVERFLOW(doesOverflow) do \ 50 if (!(doesOverflow)) { \ 51 WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "!(%s)", #doesOverflow); \ 52 } \ 53while (0) 54 55#endif 56 57static const int kLayoutUnitFractionalBits = 6; 58static const int kFixedPointDenominator = 1 << kLayoutUnitFractionalBits; 59 60const int intMaxForLayoutUnit = INT_MAX / kFixedPointDenominator; 61const int intMinForLayoutUnit = INT_MIN / kFixedPointDenominator; 62 63class LayoutUnit { 64public: 65 LayoutUnit() : m_value(0) { } 66 LayoutUnit(int value) { setValue(value); } 67 LayoutUnit(unsigned short value) { setValue(value); } 68 LayoutUnit(unsigned value) { setValue(value); } 69 LayoutUnit(unsigned long value) { m_value = clampTo<int>(value * kFixedPointDenominator); } 70 LayoutUnit(unsigned long long value) { m_value = clampTo<int>(value * kFixedPointDenominator); } 71 LayoutUnit(float value) { m_value = clampTo<int>(value * kFixedPointDenominator); } 72 LayoutUnit(double value) { m_value = clampTo<int>(value * kFixedPointDenominator); } 73 74 static LayoutUnit fromFloatCeil(float value) 75 { 76 LayoutUnit v; 77 v.m_value = clampToInteger(ceilf(value * kFixedPointDenominator)); 78 return v; 79 } 80 81 static LayoutUnit fromFloatFloor(float value) 82 { 83 LayoutUnit v; 84 v.m_value = clampToInteger(floorf(value * kFixedPointDenominator)); 85 return v; 86 } 87 88 static LayoutUnit fromFloatRound(float value) 89 { 90 if (value >= 0) 91 return clamp(value + epsilon() / 2.0f); 92 return clamp(value - epsilon() / 2.0f); 93 } 94 95 int toInt() const { return m_value / kFixedPointDenominator; } 96 float toFloat() const { return static_cast<float>(m_value) / kFixedPointDenominator; } 97 double toDouble() const { return static_cast<double>(m_value) / kFixedPointDenominator; } 98 float ceilToFloat() const 99 { 100 float floatValue = toFloat(); 101 if (static_cast<int>(floatValue * kFixedPointDenominator) == m_value) 102 return floatValue; 103 if (floatValue > 0) 104 return nextafterf(floatValue, std::numeric_limits<float>::max()); 105 return nextafterf(floatValue, std::numeric_limits<float>::min()); 106 } 107 unsigned toUnsigned() const { REPORT_OVERFLOW(m_value >= 0); return toInt(); } 108 109 operator int() const { return toInt(); } 110 operator unsigned() const { return toUnsigned(); } 111 operator double() const { return toDouble(); } 112 operator bool() const { return m_value; } 113 114 LayoutUnit operator++(int) 115 { 116 m_value += kFixedPointDenominator; 117 return *this; 118 } 119 120 inline int rawValue() const { return m_value; } 121 inline void setRawValue(int value) { m_value = value; } 122 void setRawValue(long long value) 123 { 124 REPORT_OVERFLOW(value > std::numeric_limits<int>::min() && value < std::numeric_limits<int>::max()); 125 m_value = static_cast<int>(value); 126 } 127 128 LayoutUnit abs() const 129 { 130 LayoutUnit returnValue; 131 returnValue.setRawValue(::abs(m_value)); 132 return returnValue; 133 } 134#if OS(MACOSX) 135 int wtf_ceil() const 136#else 137 int ceil() const 138#endif 139 { 140 if (UNLIKELY(m_value >= INT_MAX - kFixedPointDenominator + 1)) 141 return intMaxForLayoutUnit; 142 143 if (m_value >= 0) 144 return (m_value + kFixedPointDenominator - 1) / kFixedPointDenominator; 145 return toInt(); 146 } 147 ALWAYS_INLINE int round() const 148 { 149 return saturatedAddition(rawValue(), kFixedPointDenominator / 2) >> kLayoutUnitFractionalBits; 150 } 151 152 int floor() const 153 { 154 if (UNLIKELY(m_value <= INT_MIN + kFixedPointDenominator - 1)) 155 return intMinForLayoutUnit; 156 157 return m_value >> kLayoutUnitFractionalBits; 158 } 159 160 LayoutUnit fraction() const 161 { 162 // Add the fraction to the size (as opposed to the full location) to avoid overflows. 163 // Compute fraction using the mod operator to preserve the sign of the value as it may affect rounding. 164 LayoutUnit fraction; 165 fraction.setRawValue(rawValue() % kFixedPointDenominator); 166 return fraction; 167 } 168 169 bool mightBeSaturated() const 170 { 171 return rawValue() == std::numeric_limits<int>::max() 172 || rawValue() == std::numeric_limits<int>::min(); 173 } 174 175 static float epsilon() { return 1.0f / kFixedPointDenominator; } 176 177 static const LayoutUnit max() 178 { 179 LayoutUnit m; 180 m.m_value = std::numeric_limits<int>::max(); 181 return m; 182 } 183 static const LayoutUnit min() 184 { 185 LayoutUnit m; 186 m.m_value = std::numeric_limits<int>::min(); 187 return m; 188 } 189 190 // Versions of max/min that are slightly smaller/larger than max/min() to allow for roinding without overflowing. 191 static const LayoutUnit nearlyMax() 192 { 193 LayoutUnit m; 194 m.m_value = std::numeric_limits<int>::max() - kFixedPointDenominator / 2; 195 return m; 196 } 197 static const LayoutUnit nearlyMin() 198 { 199 LayoutUnit m; 200 m.m_value = std::numeric_limits<int>::min() + kFixedPointDenominator / 2; 201 return m; 202 } 203 204 static LayoutUnit clamp(double value) 205 { 206 return clampTo<LayoutUnit>(value, LayoutUnit::min(), LayoutUnit::max()); 207 } 208 209private: 210 static bool isInBounds(int value) 211 { 212 return ::abs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator; 213 } 214 static bool isInBounds(unsigned value) 215 { 216 return value <= static_cast<unsigned>(std::numeric_limits<int>::max()) / kFixedPointDenominator; 217 } 218 static bool isInBounds(double value) 219 { 220 return ::fabs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator; 221 } 222 223 ALWAYS_INLINE void setValue(int value) 224 { 225 m_value = saturatedSet(value, kLayoutUnitFractionalBits); 226 } 227 228 inline void setValue(unsigned value) 229 { 230 m_value = saturatedSet(value, kLayoutUnitFractionalBits); 231 } 232 233 int m_value; 234}; 235 236inline bool operator<=(const LayoutUnit& a, const LayoutUnit& b) 237{ 238 return a.rawValue() <= b.rawValue(); 239} 240 241inline bool operator<=(const LayoutUnit& a, float b) 242{ 243 return a.toFloat() <= b; 244} 245 246inline bool operator<=(const LayoutUnit& a, int b) 247{ 248 return a <= LayoutUnit(b); 249} 250 251inline bool operator<=(const float a, const LayoutUnit& b) 252{ 253 return a <= b.toFloat(); 254} 255 256inline bool operator<=(const int a, const LayoutUnit& b) 257{ 258 return LayoutUnit(a) <= b; 259} 260 261inline bool operator>=(const LayoutUnit& a, const LayoutUnit& b) 262{ 263 return a.rawValue() >= b.rawValue(); 264} 265 266inline bool operator>=(const LayoutUnit& a, int b) 267{ 268 return a >= LayoutUnit(b); 269} 270 271inline bool operator>=(const float a, const LayoutUnit& b) 272{ 273 return a >= b.toFloat(); 274} 275 276inline bool operator>=(const LayoutUnit& a, float b) 277{ 278 return a.toFloat() >= b; 279} 280 281inline bool operator>=(const int a, const LayoutUnit& b) 282{ 283 return LayoutUnit(a) >= b; 284} 285 286inline bool operator<(const LayoutUnit& a, const LayoutUnit& b) 287{ 288 return a.rawValue() < b.rawValue(); 289} 290 291inline bool operator<(const LayoutUnit& a, int b) 292{ 293 return a < LayoutUnit(b); 294} 295 296inline bool operator<(const LayoutUnit& a, float b) 297{ 298 return a.toFloat() < b; 299} 300 301inline bool operator<(const LayoutUnit& a, double b) 302{ 303 return a.toDouble() < b; 304} 305 306inline bool operator<(const int a, const LayoutUnit& b) 307{ 308 return LayoutUnit(a) < b; 309} 310 311inline bool operator<(const float a, const LayoutUnit& b) 312{ 313 return a < b.toFloat(); 314} 315 316inline bool operator>(const LayoutUnit& a, const LayoutUnit& b) 317{ 318 return a.rawValue() > b.rawValue(); 319} 320 321inline bool operator>(const LayoutUnit& a, double b) 322{ 323 return a.toDouble() > b; 324} 325 326inline bool operator>(const LayoutUnit& a, float b) 327{ 328 return a.toFloat() > b; 329} 330 331inline bool operator>(const LayoutUnit& a, int b) 332{ 333 return a > LayoutUnit(b); 334} 335 336inline bool operator>(const int a, const LayoutUnit& b) 337{ 338 return LayoutUnit(a) > b; 339} 340 341inline bool operator>(const float a, const LayoutUnit& b) 342{ 343 return a > b.toFloat(); 344} 345 346inline bool operator>(const double a, const LayoutUnit& b) 347{ 348 return a > b.toDouble(); 349} 350 351inline bool operator!=(const LayoutUnit& a, const LayoutUnit& b) 352{ 353 return a.rawValue() != b.rawValue(); 354} 355 356inline bool operator!=(const LayoutUnit& a, float b) 357{ 358 return a != LayoutUnit(b); 359} 360 361inline bool operator!=(const int a, const LayoutUnit& b) 362{ 363 return LayoutUnit(a) != b; 364} 365 366inline bool operator!=(const LayoutUnit& a, int b) 367{ 368 return a != LayoutUnit(b); 369} 370 371inline bool operator==(const LayoutUnit& a, const LayoutUnit& b) 372{ 373 return a.rawValue() == b.rawValue(); 374} 375 376inline bool operator==(const LayoutUnit& a, int b) 377{ 378 return a == LayoutUnit(b); 379} 380 381inline bool operator==(const int a, const LayoutUnit& b) 382{ 383 return LayoutUnit(a) == b; 384} 385 386inline bool operator==(const LayoutUnit& a, float b) 387{ 388 return a.toFloat() == b; 389} 390 391inline bool operator==(const float a, const LayoutUnit& b) 392{ 393 return a == b.toFloat(); 394} 395 396// For multiplication that's prone to overflow, this bounds it to LayoutUnit::max() and ::min() 397inline LayoutUnit boundedMultiply(const LayoutUnit& a, const LayoutUnit& b) 398{ 399 int64_t result = static_cast<int64_t>(a.rawValue()) * static_cast<int64_t>(b.rawValue()) / kFixedPointDenominator; 400 int32_t high = static_cast<int32_t>(result >> 32); 401 int32_t low = static_cast<int32_t>(result); 402 uint32_t saturated = (static_cast<uint32_t>(a.rawValue() ^ b.rawValue()) >> 31) + std::numeric_limits<int>::max(); 403 // If the higher 32 bits does not match the lower 32 with sign extension the operation overflowed. 404 if (high != low >> 31) 405 result = saturated; 406 407 LayoutUnit returnVal; 408 returnVal.setRawValue(static_cast<int>(result)); 409 return returnVal; 410} 411 412inline LayoutUnit operator*(const LayoutUnit& a, const LayoutUnit& b) 413{ 414 return boundedMultiply(a, b); 415} 416 417inline double operator*(const LayoutUnit& a, double b) 418{ 419 return a.toDouble() * b; 420} 421 422inline float operator*(const LayoutUnit& a, float b) 423{ 424 return a.toFloat() * b; 425} 426 427inline LayoutUnit operator*(const LayoutUnit& a, int b) 428{ 429 return a * LayoutUnit(b); 430} 431 432inline LayoutUnit operator*(const LayoutUnit& a, unsigned short b) 433{ 434 return a * LayoutUnit(b); 435} 436 437inline LayoutUnit operator*(const LayoutUnit& a, unsigned b) 438{ 439 return a * LayoutUnit(b); 440} 441 442inline LayoutUnit operator*(const LayoutUnit& a, unsigned long b) 443{ 444 return a * LayoutUnit(b); 445} 446 447inline LayoutUnit operator*(const LayoutUnit& a, unsigned long long b) 448{ 449 return a * LayoutUnit(b); 450} 451 452inline LayoutUnit operator*(unsigned short a, const LayoutUnit& b) 453{ 454 return LayoutUnit(a) * b; 455} 456 457inline LayoutUnit operator*(unsigned a, const LayoutUnit& b) 458{ 459 return LayoutUnit(a) * b; 460} 461 462inline LayoutUnit operator*(unsigned long a, const LayoutUnit& b) 463{ 464 return LayoutUnit(a) * b; 465} 466 467inline LayoutUnit operator*(unsigned long long a, const LayoutUnit& b) 468{ 469 return LayoutUnit(a) * b; 470} 471 472inline LayoutUnit operator*(const int a, const LayoutUnit& b) 473{ 474 return LayoutUnit(a) * b; 475} 476 477inline float operator*(const float a, const LayoutUnit& b) 478{ 479 return a * b.toFloat(); 480} 481 482inline double operator*(const double a, const LayoutUnit& b) 483{ 484 return a * b.toDouble(); 485} 486 487inline LayoutUnit operator/(const LayoutUnit& a, const LayoutUnit& b) 488{ 489 LayoutUnit returnVal; 490 long long rawVal = static_cast<long long>(kFixedPointDenominator) * a.rawValue() / b.rawValue(); 491 returnVal.setRawValue(clampTo<int>(rawVal)); 492 return returnVal; 493} 494 495inline float operator/(const LayoutUnit& a, float b) 496{ 497 return a.toFloat() / b; 498} 499 500inline double operator/(const LayoutUnit& a, double b) 501{ 502 return a.toDouble() / b; 503} 504 505inline LayoutUnit operator/(const LayoutUnit& a, int b) 506{ 507 return a / LayoutUnit(b); 508} 509 510inline LayoutUnit operator/(const LayoutUnit& a, unsigned short b) 511{ 512 return a / LayoutUnit(b); 513} 514 515inline LayoutUnit operator/(const LayoutUnit& a, unsigned b) 516{ 517 return a / LayoutUnit(b); 518} 519 520inline LayoutUnit operator/(const LayoutUnit& a, unsigned long b) 521{ 522 return a / LayoutUnit(b); 523} 524 525inline LayoutUnit operator/(const LayoutUnit& a, unsigned long long b) 526{ 527 return a / LayoutUnit(b); 528} 529 530inline float operator/(const float a, const LayoutUnit& b) 531{ 532 return a / b.toFloat(); 533} 534 535inline double operator/(const double a, const LayoutUnit& b) 536{ 537 return a / b.toDouble(); 538} 539 540inline LayoutUnit operator/(const int a, const LayoutUnit& b) 541{ 542 return LayoutUnit(a) / b; 543} 544 545inline LayoutUnit operator/(unsigned short a, const LayoutUnit& b) 546{ 547 return LayoutUnit(a) / b; 548} 549 550inline LayoutUnit operator/(unsigned a, const LayoutUnit& b) 551{ 552 return LayoutUnit(a) / b; 553} 554 555inline LayoutUnit operator/(unsigned long a, const LayoutUnit& b) 556{ 557 return LayoutUnit(a) / b; 558} 559 560inline LayoutUnit operator/(unsigned long long a, const LayoutUnit& b) 561{ 562 return LayoutUnit(a) / b; 563} 564 565ALWAYS_INLINE LayoutUnit operator+(const LayoutUnit& a, const LayoutUnit& b) 566{ 567 LayoutUnit returnVal; 568 returnVal.setRawValue(saturatedAddition(a.rawValue(), b.rawValue())); 569 return returnVal; 570} 571 572inline LayoutUnit operator+(const LayoutUnit& a, int b) 573{ 574 return a + LayoutUnit(b); 575} 576 577inline float operator+(const LayoutUnit& a, float b) 578{ 579 return a.toFloat() + b; 580} 581 582inline double operator+(const LayoutUnit& a, double b) 583{ 584 return a.toDouble() + b; 585} 586 587inline LayoutUnit operator+(const int a, const LayoutUnit& b) 588{ 589 return LayoutUnit(a) + b; 590} 591 592inline float operator+(const float a, const LayoutUnit& b) 593{ 594 return a + b.toFloat(); 595} 596 597inline double operator+(const double a, const LayoutUnit& b) 598{ 599 return a + b.toDouble(); 600} 601 602ALWAYS_INLINE LayoutUnit operator-(const LayoutUnit& a, const LayoutUnit& b) 603{ 604 LayoutUnit returnVal; 605 returnVal.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue())); 606 return returnVal; 607} 608 609inline LayoutUnit operator-(const LayoutUnit& a, int b) 610{ 611 return a - LayoutUnit(b); 612} 613 614inline LayoutUnit operator-(const LayoutUnit& a, unsigned b) 615{ 616 return a - LayoutUnit(b); 617} 618 619inline float operator-(const LayoutUnit& a, float b) 620{ 621 return a.toFloat() - b; 622} 623 624inline LayoutUnit operator-(const int a, const LayoutUnit& b) 625{ 626 return LayoutUnit(a) - b; 627} 628 629inline float operator-(const float a, const LayoutUnit& b) 630{ 631 return a - b.toFloat(); 632} 633 634inline LayoutUnit operator-(const LayoutUnit& a) 635{ 636 LayoutUnit returnVal; 637 returnVal.setRawValue(-a.rawValue()); 638 return returnVal; 639} 640 641// For returning the remainder after a division with integer results. 642inline LayoutUnit intMod(const LayoutUnit& a, const LayoutUnit& b) 643{ 644 // This calculates the modulo so that: a = static_cast<int>(a / b) * b + intMod(a, b). 645 LayoutUnit returnVal; 646 returnVal.setRawValue(a.rawValue() % b.rawValue()); 647 return returnVal; 648} 649 650inline LayoutUnit operator%(const LayoutUnit& a, const LayoutUnit& b) 651{ 652 // This calculates the modulo so that: a = (a / b) * b + a % b. 653 LayoutUnit returnVal; 654 long long rawVal = (static_cast<long long>(kFixedPointDenominator) * a.rawValue()) % b.rawValue(); 655 returnVal.setRawValue(rawVal / kFixedPointDenominator); 656 return returnVal; 657} 658 659inline LayoutUnit operator%(const LayoutUnit& a, int b) 660{ 661 return a % LayoutUnit(b); 662} 663 664inline LayoutUnit operator%(int a, const LayoutUnit& b) 665{ 666 return LayoutUnit(a) % b; 667} 668 669inline LayoutUnit& operator+=(LayoutUnit& a, const LayoutUnit& b) 670{ 671 a.setRawValue(saturatedAddition(a.rawValue(), b.rawValue())); 672 return a; 673} 674 675inline LayoutUnit& operator+=(LayoutUnit& a, int b) 676{ 677 a = a + b; 678 return a; 679} 680 681inline LayoutUnit& operator+=(LayoutUnit& a, float b) 682{ 683 a = a + b; 684 return a; 685} 686 687inline float& operator+=(float& a, const LayoutUnit& b) 688{ 689 a = a + b; 690 return a; 691} 692 693inline LayoutUnit& operator-=(LayoutUnit& a, int b) 694{ 695 a = a - b; 696 return a; 697} 698 699inline LayoutUnit& operator-=(LayoutUnit& a, const LayoutUnit& b) 700{ 701 a.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue())); 702 return a; 703} 704 705inline LayoutUnit& operator-=(LayoutUnit& a, float b) 706{ 707 a = a - b; 708 return a; 709} 710 711inline float& operator-=(float& a, const LayoutUnit& b) 712{ 713 a = a - b; 714 return a; 715} 716 717inline LayoutUnit& operator*=(LayoutUnit& a, const LayoutUnit& b) 718{ 719 a = a * b; 720 return a; 721} 722// operator*=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int). 723 724inline LayoutUnit& operator*=(LayoutUnit& a, float b) 725{ 726 a = a * b; 727 return a; 728} 729 730inline float& operator*=(float& a, const LayoutUnit& b) 731{ 732 a = a * b; 733 return a; 734} 735 736inline LayoutUnit& operator/=(LayoutUnit& a, const LayoutUnit& b) 737{ 738 a = a / b; 739 return a; 740} 741// operator/=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int). 742 743inline LayoutUnit& operator/=(LayoutUnit& a, float b) 744{ 745 a = a / b; 746 return a; 747} 748 749inline float& operator/=(float& a, const LayoutUnit& b) 750{ 751 a = a / b; 752 return a; 753} 754 755inline int snapSizeToPixel(LayoutUnit size, LayoutUnit location) 756{ 757 LayoutUnit fraction = location.fraction(); 758 return (fraction + size).round() - fraction.round(); 759} 760 761inline int roundToInt(LayoutUnit value) 762{ 763 return value.round(); 764} 765 766inline int floorToInt(LayoutUnit value) 767{ 768 return value.floor(); 769} 770 771inline LayoutUnit absoluteValue(const LayoutUnit& value) 772{ 773 return value.abs(); 774} 775 776inline LayoutUnit layoutMod(const LayoutUnit& numerator, const LayoutUnit& denominator) 777{ 778 return numerator % denominator; 779} 780 781inline bool isIntegerValue(const LayoutUnit value) 782{ 783 return value.toInt() == value; 784} 785 786inline LayoutUnit clampToLayoutUnit(LayoutUnit value, LayoutUnit min, LayoutUnit max) 787{ 788 if (value >= max) 789 return max; 790 if (value <= min) 791 return min; 792 return value; 793} 794 795} // namespace blink 796 797#endif // LayoutUnit_h 798