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 "ValueToString.h" 35#include <limits.h> 36#include <limits> 37#include <math.h> 38#include <stdlib.h> 39#include <wtf/MathExtras.h> 40#include <wtf/SaturatedArithmetic.h> 41 42namespace WebCore { 43 44#ifdef NDEBUG 45 46#define REPORT_OVERFLOW(doesOverflow) ((void)0) 47 48#else 49 50#define REPORT_OVERFLOW(doesOverflow) do \ 51 if (!(doesOverflow)) { \ 52 WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "!(%s)", #doesOverflow); \ 53 } \ 54while (0) 55 56#endif 57 58static const int kFixedPointDenominator = 64; 59 60#if ENABLE(SUBPIXEL_LAYOUT) 61static const int kEffectiveFixedPointDenominator = kFixedPointDenominator; 62#else 63static const int kEffectiveFixedPointDenominator = 1; 64#endif 65const int intMaxForLayoutUnit = INT_MAX / kEffectiveFixedPointDenominator; 66const int intMinForLayoutUnit = INT_MIN / kEffectiveFixedPointDenominator; 67 68class LayoutUnit { 69public: 70 LayoutUnit() : m_value(0) { } 71#if ENABLE(SUBPIXEL_LAYOUT) 72 LayoutUnit(int value) { setValue(value); } 73 LayoutUnit(unsigned short value) { setValue(value); } 74 LayoutUnit(unsigned value) { setValue(value); } 75 LayoutUnit(unsigned long value) 76 { 77#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 78 m_value = clampTo<int>(value * kEffectiveFixedPointDenominator); 79#else 80 REPORT_OVERFLOW(isInBounds(static_cast<unsigned>(value))); 81 m_value = value * kEffectiveFixedPointDenominator; 82#endif 83 } 84 LayoutUnit(unsigned long long value) 85 { 86#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 87 m_value = clampTo<int>(value * kEffectiveFixedPointDenominator); 88#else 89 REPORT_OVERFLOW(isInBounds(static_cast<unsigned>(value))); 90 m_value = static_cast<int>(value * kEffectiveFixedPointDenominator); 91#endif 92 } 93 LayoutUnit(float value) 94 { 95#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 96 m_value = clampTo<float>(value * kEffectiveFixedPointDenominator, static_cast<float>(INT_MIN), static_cast<float>(INT_MAX)); 97#else 98 REPORT_OVERFLOW(isInBounds(value)); 99 m_value = value * kEffectiveFixedPointDenominator; 100#endif 101 } 102 LayoutUnit(double value) 103 { 104#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 105 m_value = clampTo<double>(value * kEffectiveFixedPointDenominator, static_cast<double>(INT_MIN), static_cast<double>(INT_MAX)); 106#else 107 REPORT_OVERFLOW(isInBounds(value)); 108 m_value = value * kEffectiveFixedPointDenominator; 109#endif 110 } 111#else 112 LayoutUnit(int value) { REPORT_OVERFLOW(isInBounds(value)); m_value = value; } 113 LayoutUnit(unsigned short value) { REPORT_OVERFLOW(isInBounds(value)); m_value = value; } 114 LayoutUnit(unsigned value) { REPORT_OVERFLOW(isInBounds(value)); m_value = clampTo<int>(value); } 115 LayoutUnit(unsigned long long value) { REPORT_OVERFLOW(isInBounds(static_cast<unsigned>(value))); m_value = clampTo<int>(value); } 116 LayoutUnit(unsigned long value) { REPORT_OVERFLOW(isInBounds(static_cast<unsigned>(value))); m_value = clampTo<int>(value); } 117 LayoutUnit(float value) { REPORT_OVERFLOW(isInBounds(value)); m_value = clampTo<int>(value); } 118 LayoutUnit(double value) { REPORT_OVERFLOW(isInBounds(value)); m_value = clampTo<int>(value); } 119#endif 120 121 static LayoutUnit fromPixel(int value) 122 { 123 return LayoutUnit(value); 124 } 125 126 static LayoutUnit fromFloatCeil(float value) 127 { 128 LayoutUnit v; 129#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 130 v.m_value = clampToInteger(ceilf(value * kEffectiveFixedPointDenominator)); 131#else 132 REPORT_OVERFLOW(isInBounds(value)); 133 v.m_value = ceilf(value * kEffectiveFixedPointDenominator); 134#endif 135 return v; 136 } 137 138 static LayoutUnit fromFloatFloor(float value) 139 { 140 LayoutUnit v; 141#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 142 v.m_value = clampToInteger(floorf(value * kEffectiveFixedPointDenominator)); 143#else 144 REPORT_OVERFLOW(isInBounds(value)); 145 v.m_value = floorf(value * kEffectiveFixedPointDenominator); 146#endif 147 return v; 148 } 149 150 static LayoutUnit fromFloatRound(float value) 151 { 152#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 153 if (value >= 0) 154 return clamp(value + epsilon() / 2.0f); 155 return clamp(value - epsilon() / 2.0f); 156#else 157 if (value >= 0) { 158 REPORT_OVERFLOW(isInBounds(value + epsilon() / 2.0f)); 159 return LayoutUnit(value + epsilon() / 2.0f); 160 } 161 REPORT_OVERFLOW(isInBounds(value - epsilon() / 2.0f)); 162 return LayoutUnit(value - epsilon() / 2.0f); 163#endif 164 } 165 166#if ENABLE(SUBPIXEL_LAYOUT) 167 int toInt() const { return m_value / kEffectiveFixedPointDenominator; } 168 float toFloat() const { return static_cast<float>(m_value) / kEffectiveFixedPointDenominator; } 169 double toDouble() const { return static_cast<double>(m_value) / kEffectiveFixedPointDenominator; } 170 float ceilToFloat() const 171 { 172 float floatValue = toFloat(); 173 if (static_cast<int>(floatValue * kEffectiveFixedPointDenominator) == m_value) 174 return floatValue; 175 if (floatValue > 0) 176 return nextafterf(floatValue, std::numeric_limits<float>::max()); 177 return nextafterf(floatValue, std::numeric_limits<float>::min()); 178 } 179#else 180 int toInt() const { return m_value; } 181 float toFloat() const { return static_cast<float>(m_value); } 182 double toDouble() const { return static_cast<double>(m_value); } 183 float ceilToFloat() const { return toFloat(); } 184#endif 185 unsigned toUnsigned() const { REPORT_OVERFLOW(m_value >= 0); return toInt(); } 186 187 operator int() const { return toInt(); } 188 operator unsigned() const { return toUnsigned(); } 189 operator float() const { return toFloat(); } 190 operator double() const { return toDouble(); } 191 operator bool() const { return m_value; } 192 193 LayoutUnit& operator++() 194 { 195 m_value += kEffectiveFixedPointDenominator; 196 return *this; 197 } 198 199 inline int rawValue() const { return m_value; } 200 inline void setRawValue(int value) { m_value = value; } 201 void setRawValue(long long value) 202 { 203 REPORT_OVERFLOW(value > std::numeric_limits<int>::min() && value < std::numeric_limits<int>::max()); 204 m_value = static_cast<int>(value); 205 } 206 207 LayoutUnit abs() const 208 { 209 LayoutUnit returnValue; 210 returnValue.setRawValue(::abs(m_value)); 211 return returnValue; 212 } 213#if OS(DARWIN) 214 int wtf_ceil() const 215#else 216 int ceil() const 217#endif 218 { 219#if ENABLE(SUBPIXEL_LAYOUT) 220#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 221 if (UNLIKELY(m_value >= INT_MAX - kEffectiveFixedPointDenominator + 1)) 222 return intMaxForLayoutUnit; 223#endif 224 if (m_value >= 0) 225 return (m_value + kEffectiveFixedPointDenominator - 1) / kEffectiveFixedPointDenominator; 226 return toInt(); 227#else 228 return m_value; 229#endif 230 } 231 int round() const 232 { 233#if ENABLE(SUBPIXEL_LAYOUT) && ENABLE(SATURATED_LAYOUT_ARITHMETIC) 234 if (m_value > 0) 235 return saturatedAddition(rawValue(), kEffectiveFixedPointDenominator / 2) / kEffectiveFixedPointDenominator; 236 return saturatedSubtraction(rawValue(), (kEffectiveFixedPointDenominator / 2) - 1) / kEffectiveFixedPointDenominator; 237#elif ENABLE(SUBPIXEL_LAYOUT) 238 if (m_value > 0) 239 return (m_value + (kEffectiveFixedPointDenominator / 2)) / kEffectiveFixedPointDenominator; 240 return (m_value - ((kEffectiveFixedPointDenominator / 2) - 1)) / kEffectiveFixedPointDenominator; 241#else 242 return m_value; 243#endif 244 } 245 246 int floor() const 247 { 248#if ENABLE(SUBPIXEL_LAYOUT) 249#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 250 if (UNLIKELY(m_value <= INT_MIN + kEffectiveFixedPointDenominator - 1)) 251 return intMinForLayoutUnit; 252#endif 253 if (m_value >= 0) 254 return toInt(); 255 return (m_value - kEffectiveFixedPointDenominator + 1) / kEffectiveFixedPointDenominator; 256#else 257 return m_value; 258#endif 259 } 260 261 LayoutUnit fraction() const 262 { 263 // Add the fraction to the size (as opposed to the full location) to avoid overflows. 264 // Compute fraction using the mod operator to preserve the sign of the value as it may affect rounding. 265 LayoutUnit fraction; 266 fraction.setRawValue(rawValue() % kEffectiveFixedPointDenominator); 267 return fraction; 268 } 269 270#if ENABLE(SUBPIXEL_LAYOUT) 271 bool mightBeSaturated() const 272 { 273 return rawValue() == std::numeric_limits<int>::max() 274 || rawValue() == std::numeric_limits<int>::min(); 275 } 276 277 static float epsilon() { return 1.0f / kEffectiveFixedPointDenominator; } 278#else 279 static int epsilon() { return 0; } 280#endif 281 static const LayoutUnit max() 282 { 283 LayoutUnit m; 284 m.m_value = std::numeric_limits<int>::max(); 285 return m; 286 } 287 static const LayoutUnit min() 288 { 289 LayoutUnit m; 290 m.m_value = std::numeric_limits<int>::min(); 291 return m; 292 } 293 294 // Versions of max/min that are slightly smaller/larger than max/min() to allow for roinding without overflowing. 295 static const LayoutUnit nearlyMax() 296 { 297 LayoutUnit m; 298 m.m_value = std::numeric_limits<int>::max() - kEffectiveFixedPointDenominator / 2; 299 return m; 300 } 301 static const LayoutUnit nearlyMin() 302 { 303 LayoutUnit m; 304 m.m_value = std::numeric_limits<int>::min() + kEffectiveFixedPointDenominator / 2; 305 return m; 306 } 307 308 static LayoutUnit clamp(double value) 309 { 310 return clampTo<LayoutUnit>(value, LayoutUnit::min(), LayoutUnit::max()); 311 } 312 313private: 314 static bool isInBounds(int value) 315 { 316 return ::abs(value) <= std::numeric_limits<int>::max() / kEffectiveFixedPointDenominator; 317 } 318 static bool isInBounds(unsigned value) 319 { 320 return value <= static_cast<unsigned>(std::numeric_limits<int>::max()) / kEffectiveFixedPointDenominator; 321 } 322 static bool isInBounds(double value) 323 { 324 return ::fabs(value) <= std::numeric_limits<int>::max() / kEffectiveFixedPointDenominator; 325 } 326 327 inline void setValue(int value) 328 { 329#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 330 if (value > intMaxForLayoutUnit) 331 m_value = std::numeric_limits<int>::max(); 332 else if (value < intMinForLayoutUnit) 333 m_value = std::numeric_limits<int>::min(); 334 else 335 m_value = value * kEffectiveFixedPointDenominator; 336#else 337 REPORT_OVERFLOW(isInBounds(value)); 338 m_value = value * kEffectiveFixedPointDenominator; 339#endif 340 } 341 inline void setValue(unsigned value) 342 { 343#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 344 if (value >= static_cast<unsigned>(intMaxForLayoutUnit)) 345 m_value = std::numeric_limits<int>::max(); 346 else 347 m_value = value * kEffectiveFixedPointDenominator; 348#else 349 REPORT_OVERFLOW(isInBounds(value)); 350 m_value = value * kEffectiveFixedPointDenominator; 351#endif 352 } 353 354 int m_value; 355}; 356 357inline bool operator<=(const LayoutUnit& a, const LayoutUnit& b) 358{ 359 return a.rawValue() <= b.rawValue(); 360} 361 362inline bool operator<=(const LayoutUnit& a, float b) 363{ 364 return a.toFloat() <= b; 365} 366 367inline bool operator<=(const LayoutUnit& a, int b) 368{ 369 return a <= LayoutUnit(b); 370} 371 372inline bool operator<=(const float a, const LayoutUnit& b) 373{ 374 return a <= b.toFloat(); 375} 376 377inline bool operator<=(const int a, const LayoutUnit& b) 378{ 379 return LayoutUnit(a) <= b; 380} 381 382inline bool operator>=(const LayoutUnit& a, const LayoutUnit& b) 383{ 384 return a.rawValue() >= b.rawValue(); 385} 386 387inline bool operator>=(const LayoutUnit& a, int b) 388{ 389 return a >= LayoutUnit(b); 390} 391 392inline bool operator>=(const float a, const LayoutUnit& b) 393{ 394 return a >= b.toFloat(); 395} 396 397inline bool operator>=(const LayoutUnit& a, float b) 398{ 399 return a.toFloat() >= b; 400} 401 402inline bool operator>=(const int a, const LayoutUnit& b) 403{ 404 return LayoutUnit(a) >= b; 405} 406 407inline bool operator<(const LayoutUnit& a, const LayoutUnit& b) 408{ 409 return a.rawValue() < b.rawValue(); 410} 411 412inline bool operator<(const LayoutUnit& a, int b) 413{ 414 return a < LayoutUnit(b); 415} 416 417inline bool operator<(const LayoutUnit& a, float b) 418{ 419 return a.toFloat() < b; 420} 421 422inline bool operator<(const LayoutUnit& a, double b) 423{ 424 return a.toDouble() < b; 425} 426 427inline bool operator<(const int a, const LayoutUnit& b) 428{ 429 return LayoutUnit(a) < b; 430} 431 432inline bool operator<(const float a, const LayoutUnit& b) 433{ 434 return a < b.toFloat(); 435} 436 437inline bool operator>(const LayoutUnit& a, const LayoutUnit& b) 438{ 439 return a.rawValue() > b.rawValue(); 440} 441 442inline bool operator>(const LayoutUnit& a, double b) 443{ 444 return a.toDouble() > b; 445} 446 447inline bool operator>(const LayoutUnit& a, float b) 448{ 449 return a.toFloat() > b; 450} 451 452inline bool operator>(const LayoutUnit& a, int b) 453{ 454 return a > LayoutUnit(b); 455} 456 457inline bool operator>(const int a, const LayoutUnit& b) 458{ 459 return LayoutUnit(a) > b; 460} 461 462inline bool operator>(const float a, const LayoutUnit& b) 463{ 464 return a > b.toFloat(); 465} 466 467inline bool operator>(const double a, const LayoutUnit& b) 468{ 469 return a > b.toDouble(); 470} 471 472inline bool operator!=(const LayoutUnit& a, const LayoutUnit& b) 473{ 474 return a.rawValue() != b.rawValue(); 475} 476 477inline bool operator!=(const LayoutUnit& a, float b) 478{ 479 return a != LayoutUnit(b); 480} 481 482inline bool operator!=(const int a, const LayoutUnit& b) 483{ 484 return LayoutUnit(a) != b; 485} 486 487inline bool operator!=(const LayoutUnit& a, int b) 488{ 489 return a != LayoutUnit(b); 490} 491 492inline bool operator==(const LayoutUnit& a, const LayoutUnit& b) 493{ 494 return a.rawValue() == b.rawValue(); 495} 496 497inline bool operator==(const LayoutUnit& a, int b) 498{ 499 return a == LayoutUnit(b); 500} 501 502inline bool operator==(const int a, const LayoutUnit& b) 503{ 504 return LayoutUnit(a) == b; 505} 506 507inline bool operator==(const LayoutUnit& a, float b) 508{ 509 return a.toFloat() == b; 510} 511 512inline bool operator==(const float a, const LayoutUnit& b) 513{ 514 return a == b.toFloat(); 515} 516 517// For multiplication that's prone to overflow, this bounds it to LayoutUnit::max() and ::min() 518inline LayoutUnit boundedMultiply(const LayoutUnit& a, const LayoutUnit& b) 519{ 520#if ENABLE(SUBPIXEL_LAYOUT) 521 int64_t result = static_cast<int64_t>(a.rawValue()) * static_cast<int64_t>(b.rawValue()) / kEffectiveFixedPointDenominator; 522 int32_t high = static_cast<int32_t>(result >> 32); 523 int32_t low = static_cast<int32_t>(result); 524 uint32_t saturated = (static_cast<uint32_t>(a.rawValue() ^ b.rawValue()) >> 31) + std::numeric_limits<int>::max(); 525 // If the higher 32 bits does not match the lower 32 with sign extension the operation overflowed. 526 if (high != low >> 31) 527 result = saturated; 528 529 LayoutUnit returnVal; 530 returnVal.setRawValue(static_cast<int>(result)); 531 return returnVal; 532#else 533 // FIXME: Should be bounded even in the non-subpixel case. 534 return a.rawValue() * b.rawValue(); 535#endif 536} 537 538inline LayoutUnit operator*(const LayoutUnit& a, const LayoutUnit& b) 539{ 540#if ENABLE(SUBPIXEL_LAYOUT) && ENABLE(SATURATED_LAYOUT_ARITHMETIC) 541 return boundedMultiply(a, b); 542#elif ENABLE(SUBPIXEL_LAYOUT) 543 LayoutUnit returnVal; 544 long long rawVal = static_cast<long long>(a.rawValue()) * b.rawValue() / kEffectiveFixedPointDenominator; 545 returnVal.setRawValue(rawVal); 546 return returnVal; 547#else 548 return a.rawValue() * b.rawValue(); 549#endif 550} 551 552inline double operator*(const LayoutUnit& a, double b) 553{ 554 return a.toDouble() * b; 555} 556 557inline float operator*(const LayoutUnit& a, float b) 558{ 559 return a.toFloat() * b; 560} 561 562inline LayoutUnit operator*(const LayoutUnit& a, int b) 563{ 564 return a * LayoutUnit(b); 565} 566 567inline LayoutUnit operator*(const LayoutUnit& a, unsigned short b) 568{ 569 return a * LayoutUnit(b); 570} 571 572inline LayoutUnit operator*(const LayoutUnit& a, unsigned b) 573{ 574 return a * LayoutUnit(b); 575} 576 577inline LayoutUnit operator*(const LayoutUnit& a, unsigned long b) 578{ 579 return a * LayoutUnit(b); 580} 581 582inline LayoutUnit operator*(const LayoutUnit& a, unsigned long long b) 583{ 584 return a * LayoutUnit(b); 585} 586 587inline LayoutUnit operator*(unsigned short a, const LayoutUnit& b) 588{ 589 return LayoutUnit(a) * b; 590} 591 592inline LayoutUnit operator*(unsigned a, const LayoutUnit& b) 593{ 594 return LayoutUnit(a) * b; 595} 596 597inline LayoutUnit operator*(unsigned long a, const LayoutUnit& b) 598{ 599 return LayoutUnit(a) * b; 600} 601 602inline LayoutUnit operator*(unsigned long long a, const LayoutUnit& b) 603{ 604 return LayoutUnit(a) * b; 605} 606 607inline LayoutUnit operator*(const int a, const LayoutUnit& b) 608{ 609 return LayoutUnit(a) * b; 610} 611 612inline float operator*(const float a, const LayoutUnit& b) 613{ 614 return a * b.toFloat(); 615} 616 617inline double operator*(const double a, const LayoutUnit& b) 618{ 619 return a * b.toDouble(); 620} 621 622inline LayoutUnit operator/(const LayoutUnit& a, const LayoutUnit& b) 623{ 624#if ENABLE(SUBPIXEL_LAYOUT) 625 LayoutUnit returnVal; 626 long long rawVal = static_cast<long long>(kEffectiveFixedPointDenominator) * a.rawValue() / b.rawValue(); 627#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 628 returnVal.setRawValue(clampTo<int>(rawVal)); 629#else 630 returnVal.setRawValue(rawVal); 631#endif 632 return returnVal; 633#else 634 return a.rawValue() / b.rawValue(); 635#endif 636} 637 638inline float operator/(const LayoutUnit& a, float b) 639{ 640 return a.toFloat() / b; 641} 642 643inline double operator/(const LayoutUnit& a, double b) 644{ 645 return a.toDouble() / b; 646} 647 648inline LayoutUnit operator/(const LayoutUnit& a, int b) 649{ 650 return a / LayoutUnit(b); 651} 652 653inline LayoutUnit operator/(const LayoutUnit& a, unsigned short b) 654{ 655 return a / LayoutUnit(b); 656} 657 658inline LayoutUnit operator/(const LayoutUnit& a, unsigned b) 659{ 660 return a / LayoutUnit(b); 661} 662 663inline LayoutUnit operator/(const LayoutUnit& a, unsigned long b) 664{ 665 return a / LayoutUnit(b); 666} 667 668inline LayoutUnit operator/(const LayoutUnit& a, unsigned long long b) 669{ 670 return a / LayoutUnit(b); 671} 672 673inline float operator/(const float a, const LayoutUnit& b) 674{ 675 return a / b.toFloat(); 676} 677 678inline double operator/(const double a, const LayoutUnit& b) 679{ 680 return a / b.toDouble(); 681} 682 683inline LayoutUnit operator/(const int a, const LayoutUnit& b) 684{ 685 return LayoutUnit(a) / b; 686} 687 688inline LayoutUnit operator/(unsigned short a, const LayoutUnit& b) 689{ 690 return LayoutUnit(a) / b; 691} 692 693inline LayoutUnit operator/(unsigned a, const LayoutUnit& b) 694{ 695 return LayoutUnit(a) / b; 696} 697 698inline LayoutUnit operator/(unsigned long a, const LayoutUnit& b) 699{ 700 return LayoutUnit(a) / b; 701} 702 703inline LayoutUnit operator/(unsigned long long a, const LayoutUnit& b) 704{ 705 return LayoutUnit(a) / b; 706} 707 708inline LayoutUnit operator+(const LayoutUnit& a, const LayoutUnit& b) 709{ 710 LayoutUnit returnVal; 711#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 712 returnVal.setRawValue(saturatedAddition(a.rawValue(), b.rawValue())); 713#else 714 returnVal.setRawValue(a.rawValue() + b.rawValue()); 715#endif 716 return returnVal; 717} 718 719inline LayoutUnit operator+(const LayoutUnit& a, int b) 720{ 721 return a + LayoutUnit(b); 722} 723 724inline float operator+(const LayoutUnit& a, float b) 725{ 726 return a.toFloat() + b; 727} 728 729inline double operator+(const LayoutUnit& a, double b) 730{ 731 return a.toDouble() + b; 732} 733 734inline LayoutUnit operator+(const int a, const LayoutUnit& b) 735{ 736 return LayoutUnit(a) + b; 737} 738 739inline float operator+(const float a, const LayoutUnit& b) 740{ 741 return a + b.toFloat(); 742} 743 744inline double operator+(const double a, const LayoutUnit& b) 745{ 746 return a + b.toDouble(); 747} 748 749inline LayoutUnit operator-(const LayoutUnit& a, const LayoutUnit& b) 750{ 751 LayoutUnit returnVal; 752#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 753 returnVal.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue())); 754#else 755 returnVal.setRawValue(a.rawValue() - b.rawValue()); 756#endif 757 return returnVal; 758} 759 760inline LayoutUnit operator-(const LayoutUnit& a, int b) 761{ 762 return a - LayoutUnit(b); 763} 764 765inline LayoutUnit operator-(const LayoutUnit& a, unsigned b) 766{ 767 return a - LayoutUnit(b); 768} 769 770inline float operator-(const LayoutUnit& a, float b) 771{ 772 return a.toFloat() - b; 773} 774 775inline LayoutUnit operator-(const int a, const LayoutUnit& b) 776{ 777 return LayoutUnit(a) - b; 778} 779 780inline float operator-(const float a, const LayoutUnit& b) 781{ 782 return a - b.toFloat(); 783} 784 785inline LayoutUnit operator-(const LayoutUnit& a) 786{ 787 LayoutUnit returnVal; 788 returnVal.setRawValue(-a.rawValue()); 789 return returnVal; 790} 791 792// For returning the remainder after a division with integer results. 793inline LayoutUnit intMod(const LayoutUnit& a, const LayoutUnit& b) 794{ 795#if ENABLE(SUBPIXEL_LAYOUT) 796 // This calculates the modulo so that: a = static_cast<int>(a / b) * b + intMod(a, b). 797 LayoutUnit returnVal; 798 returnVal.setRawValue(a.rawValue() % b.rawValue()); 799 return returnVal; 800#else 801 return a.rawValue() % b.rawValue(); 802#endif 803} 804 805inline LayoutUnit operator%(const LayoutUnit& a, const LayoutUnit& b) 806{ 807#if ENABLE(SUBPIXEL_LAYOUT) 808 // This calculates the modulo so that: a = (a / b) * b + a % b. 809 LayoutUnit returnVal; 810 long long rawVal = (static_cast<long long>(kEffectiveFixedPointDenominator) * a.rawValue()) % b.rawValue(); 811 returnVal.setRawValue(rawVal / kEffectiveFixedPointDenominator); 812 return returnVal; 813#else 814 return a.rawValue() % b.rawValue(); 815#endif 816} 817 818inline LayoutUnit operator%(const LayoutUnit& a, int b) 819{ 820 return a % LayoutUnit(b); 821} 822 823inline LayoutUnit operator%(int a, const LayoutUnit& b) 824{ 825 return LayoutUnit(a) % b; 826} 827 828inline LayoutUnit& operator+=(LayoutUnit& a, const LayoutUnit& b) 829{ 830#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 831 a.setRawValue(saturatedAddition(a.rawValue(), b.rawValue())); 832#else 833 a = a + b; 834#endif 835 return a; 836} 837 838inline LayoutUnit& operator+=(LayoutUnit& a, int b) 839{ 840 a = a + b; 841 return a; 842} 843 844inline LayoutUnit& operator+=(LayoutUnit& a, float b) 845{ 846 a = a + b; 847 return a; 848} 849 850inline float& operator+=(float& a, const LayoutUnit& b) 851{ 852 a = a + b; 853 return a; 854} 855 856inline LayoutUnit& operator-=(LayoutUnit& a, int b) 857{ 858 a = a - b; 859 return a; 860} 861 862inline LayoutUnit& operator-=(LayoutUnit& a, const LayoutUnit& b) 863{ 864#if ENABLE(SATURATED_LAYOUT_ARITHMETIC) 865 a.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue())); 866#else 867 a = a - b; 868#endif 869 return a; 870} 871 872inline LayoutUnit& operator-=(LayoutUnit& a, float b) 873{ 874 a = a - b; 875 return a; 876} 877 878inline float& operator-=(float& a, const LayoutUnit& b) 879{ 880 a = a - b; 881 return a; 882} 883 884inline LayoutUnit& operator*=(LayoutUnit& a, const LayoutUnit& b) 885{ 886 a = a * b; 887 return a; 888} 889// operator*=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int). 890 891inline LayoutUnit& operator*=(LayoutUnit& a, float b) 892{ 893 a = a * b; 894 return a; 895} 896 897inline float& operator*=(float& a, const LayoutUnit& b) 898{ 899 a = a * b; 900 return a; 901} 902 903inline LayoutUnit& operator/=(LayoutUnit& a, const LayoutUnit& b) 904{ 905 a = a / b; 906 return a; 907} 908// operator/=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int). 909 910inline LayoutUnit& operator/=(LayoutUnit& a, float b) 911{ 912 a = a / b; 913 return a; 914} 915 916inline float& operator/=(float& a, const LayoutUnit& b) 917{ 918 a = a / b; 919 return a; 920} 921 922inline int snapSizeToPixel(LayoutUnit size, LayoutUnit location) 923{ 924 LayoutUnit fraction = location.fraction(); 925 return (fraction + size).round() - fraction.round(); 926} 927 928inline int roundToInt(LayoutUnit value) 929{ 930 return value.round(); 931} 932 933inline int floorToInt(LayoutUnit value) 934{ 935 return value.floor(); 936} 937 938inline float roundToDevicePixel(LayoutUnit value, const float pixelSnappingFactor, bool needsDirectionalRounding = false) 939{ 940 auto roundInternal = [&] (float valueToRound) { return roundf((valueToRound * pixelSnappingFactor) / kEffectiveFixedPointDenominator) / pixelSnappingFactor; }; 941 942 float adjustedValue = value.rawValue() - (needsDirectionalRounding ? LayoutUnit::epsilon() / 2.0f : 0); 943 if (adjustedValue >= 0) 944 return roundInternal(adjustedValue); 945 946 // This adjusts directional rounding on negative halfway values. It produces the same direction for both negative and positive values. 947 // It helps snapping relative negative coordinates to the same position as if they were positive absolute coordinates. 948 float translateOrigin = fabsf(adjustedValue - LayoutUnit::fromPixel(1)); 949 return roundInternal(adjustedValue + (translateOrigin * kEffectiveFixedPointDenominator)) - translateOrigin; 950} 951 952inline float floorToDevicePixel(LayoutUnit value, float pixelSnappingFactor) 953{ 954 return floorf((value.rawValue() * pixelSnappingFactor) / kEffectiveFixedPointDenominator) / pixelSnappingFactor; 955} 956 957inline float ceilToDevicePixel(LayoutUnit value, float pixelSnappingFactor) 958{ 959 return ceilf((value.rawValue() * pixelSnappingFactor) / kEffectiveFixedPointDenominator) / pixelSnappingFactor; 960} 961 962inline float snapSizeToDevicePixel(LayoutUnit size, LayoutUnit location, float pixelSnappingFactor) 963{ 964 LayoutUnit fraction = location.fraction(); 965 return roundToDevicePixel(fraction + size, pixelSnappingFactor) - roundToDevicePixel(fraction, pixelSnappingFactor); 966} 967 968inline LayoutUnit roundedLayoutUnit(float value) 969{ 970#if ENABLE(SUBPIXEL_LAYOUT) 971 return LayoutUnit::fromFloatRound(value); 972#else 973 return static_cast<int>(lroundf(value)); 974#endif 975} 976 977inline LayoutUnit ceiledLayoutUnit(float value) 978{ 979#if ENABLE(SUBPIXEL_LAYOUT) 980 return LayoutUnit::fromFloatCeil(value); 981#else 982 return ceilf(value); 983#endif 984} 985 986inline LayoutUnit absoluteValue(const LayoutUnit& value) 987{ 988 return value.abs(); 989} 990 991inline bool isIntegerValue(const LayoutUnit value) 992{ 993 return value.toInt() == value; 994} 995 996#ifndef NDEBUG 997// This structure is used by PODIntervalTree for debugging. 998template <> 999struct ValueToString<LayoutUnit> { 1000 static String string(const LayoutUnit value) { return String::number(value.toFloat()); } 1001}; 1002#endif 1003 1004} // namespace WebCore 1005 1006#endif // LayoutUnit_h 1007