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