2 * Copyright (c) 2012, Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
34 #include "wtf/Assertions.h"
35 #include "wtf/MathExtras.h"
36 #include "wtf/SaturatedArithmetic.h"
45 #define REPORT_OVERFLOW(doesOverflow) ((void)0)
49 #define REPORT_OVERFLOW(doesOverflow) do \
50 if (!(doesOverflow)) { \
51 WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "!(%s)", #doesOverflow); \
57 static const int kLayoutUnitFractionalBits = 6;
58 static const int kFixedPointDenominator = 1 << kLayoutUnitFractionalBits;
60 const int intMaxForLayoutUnit = INT_MAX / kFixedPointDenominator;
61 const int intMinForLayoutUnit = INT_MIN / kFixedPointDenominator;
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); }
74 static LayoutUnit fromFloatCeil(float value)
77 v.m_value = clampTo<int>(ceilf(value * kFixedPointDenominator));
81 static LayoutUnit fromFloatFloor(float value)
84 v.m_value = clampTo<int>(floorf(value * kFixedPointDenominator));
88 static LayoutUnit fromFloatRound(float value)
91 return clamp(value + epsilon() / 2.0f);
92 return clamp(value - epsilon() / 2.0f);
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
100 float floatValue = toFloat();
101 if (static_cast<int>(floatValue * kFixedPointDenominator) == m_value)
104 return nextafterf(floatValue, std::numeric_limits<float>::max());
105 return nextafterf(floatValue, std::numeric_limits<float>::min());
107 unsigned toUnsigned() const { REPORT_OVERFLOW(m_value >= 0); return toInt(); }
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; }
114 LayoutUnit operator++(int)
116 m_value += kFixedPointDenominator;
120 inline int rawValue() const { return m_value; }
121 inline void setRawValue(int value) { m_value = value; }
122 void setRawValue(long long value)
124 REPORT_OVERFLOW(value > std::numeric_limits<int>::min() && value < std::numeric_limits<int>::max());
125 m_value = static_cast<int>(value);
128 LayoutUnit abs() const
130 LayoutUnit returnValue;
131 returnValue.setRawValue(::abs(m_value));
136 if (UNLIKELY(m_value >= INT_MAX - kFixedPointDenominator + 1))
137 return intMaxForLayoutUnit;
140 return (m_value + kFixedPointDenominator - 1) / kFixedPointDenominator;
143 ALWAYS_INLINE int round() const
145 return saturatedAddition(rawValue(), kFixedPointDenominator / 2) >> kLayoutUnitFractionalBits;
150 if (UNLIKELY(m_value <= INT_MIN + kFixedPointDenominator - 1))
151 return intMinForLayoutUnit;
153 return m_value >> kLayoutUnitFractionalBits;
156 LayoutUnit fraction() const
158 // Add the fraction to the size (as opposed to the full location) to avoid overflows.
159 // Compute fraction using the mod operator to preserve the sign of the value as it may affect rounding.
161 fraction.setRawValue(rawValue() % kFixedPointDenominator);
165 bool mightBeSaturated() const
167 return rawValue() == std::numeric_limits<int>::max()
168 || rawValue() == std::numeric_limits<int>::min();
171 static float epsilon() { return 1.0f / kFixedPointDenominator; }
173 static const LayoutUnit max()
176 m.m_value = std::numeric_limits<int>::max();
179 static const LayoutUnit min()
182 m.m_value = std::numeric_limits<int>::min();
186 // Versions of max/min that are slightly smaller/larger than max/min() to allow for roinding without overflowing.
187 static const LayoutUnit nearlyMax()
190 m.m_value = std::numeric_limits<int>::max() - kFixedPointDenominator / 2;
193 static const LayoutUnit nearlyMin()
196 m.m_value = std::numeric_limits<int>::min() + kFixedPointDenominator / 2;
200 static LayoutUnit clamp(double value)
202 return clampTo<LayoutUnit>(value, LayoutUnit::min(), LayoutUnit::max());
206 static bool isInBounds(int value)
208 return ::abs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator;
210 static bool isInBounds(unsigned value)
212 return value <= static_cast<unsigned>(std::numeric_limits<int>::max()) / kFixedPointDenominator;
214 static bool isInBounds(double value)
216 return ::fabs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator;
219 ALWAYS_INLINE void setValue(int value)
221 m_value = saturatedSet(value, kLayoutUnitFractionalBits);
224 inline void setValue(unsigned value)
226 m_value = saturatedSet(value, kLayoutUnitFractionalBits);
232 inline bool operator<=(const LayoutUnit& a, const LayoutUnit& b)
234 return a.rawValue() <= b.rawValue();
237 inline bool operator<=(const LayoutUnit& a, float b)
239 return a.toFloat() <= b;
242 inline bool operator<=(const LayoutUnit& a, int b)
244 return a <= LayoutUnit(b);
247 inline bool operator<=(const float a, const LayoutUnit& b)
249 return a <= b.toFloat();
252 inline bool operator<=(const int a, const LayoutUnit& b)
254 return LayoutUnit(a) <= b;
257 inline bool operator>=(const LayoutUnit& a, const LayoutUnit& b)
259 return a.rawValue() >= b.rawValue();
262 inline bool operator>=(const LayoutUnit& a, int b)
264 return a >= LayoutUnit(b);
267 inline bool operator>=(const float a, const LayoutUnit& b)
269 return a >= b.toFloat();
272 inline bool operator>=(const LayoutUnit& a, float b)
274 return a.toFloat() >= b;
277 inline bool operator>=(const int a, const LayoutUnit& b)
279 return LayoutUnit(a) >= b;
282 inline bool operator<(const LayoutUnit& a, const LayoutUnit& b)
284 return a.rawValue() < b.rawValue();
287 inline bool operator<(const LayoutUnit& a, int b)
289 return a < LayoutUnit(b);
292 inline bool operator<(const LayoutUnit& a, float b)
294 return a.toFloat() < b;
297 inline bool operator<(const LayoutUnit& a, double b)
299 return a.toDouble() < b;
302 inline bool operator<(const int a, const LayoutUnit& b)
304 return LayoutUnit(a) < b;
307 inline bool operator<(const float a, const LayoutUnit& b)
309 return a < b.toFloat();
312 inline bool operator>(const LayoutUnit& a, const LayoutUnit& b)
314 return a.rawValue() > b.rawValue();
317 inline bool operator>(const LayoutUnit& a, double b)
319 return a.toDouble() > b;
322 inline bool operator>(const LayoutUnit& a, float b)
324 return a.toFloat() > b;
327 inline bool operator>(const LayoutUnit& a, int b)
329 return a > LayoutUnit(b);
332 inline bool operator>(const int a, const LayoutUnit& b)
334 return LayoutUnit(a) > b;
337 inline bool operator>(const float a, const LayoutUnit& b)
339 return a > b.toFloat();
342 inline bool operator>(const double a, const LayoutUnit& b)
344 return a > b.toDouble();
347 inline bool operator!=(const LayoutUnit& a, const LayoutUnit& b)
349 return a.rawValue() != b.rawValue();
352 inline bool operator!=(const LayoutUnit& a, float b)
354 return a != LayoutUnit(b);
357 inline bool operator!=(const int a, const LayoutUnit& b)
359 return LayoutUnit(a) != b;
362 inline bool operator!=(const LayoutUnit& a, int b)
364 return a != LayoutUnit(b);
367 inline bool operator==(const LayoutUnit& a, const LayoutUnit& b)
369 return a.rawValue() == b.rawValue();
372 inline bool operator==(const LayoutUnit& a, int b)
374 return a == LayoutUnit(b);
377 inline bool operator==(const int a, const LayoutUnit& b)
379 return LayoutUnit(a) == b;
382 inline bool operator==(const LayoutUnit& a, float b)
384 return a.toFloat() == b;
387 inline bool operator==(const float a, const LayoutUnit& b)
389 return a == b.toFloat();
392 // For multiplication that's prone to overflow, this bounds it to LayoutUnit::max() and ::min()
393 inline LayoutUnit boundedMultiply(const LayoutUnit& a, const LayoutUnit& b)
395 int64_t result = static_cast<int64_t>(a.rawValue()) * static_cast<int64_t>(b.rawValue()) / kFixedPointDenominator;
396 int32_t high = static_cast<int32_t>(result >> 32);
397 int32_t low = static_cast<int32_t>(result);
398 uint32_t saturated = (static_cast<uint32_t>(a.rawValue() ^ b.rawValue()) >> 31) + std::numeric_limits<int>::max();
399 // If the higher 32 bits does not match the lower 32 with sign extension the operation overflowed.
400 if (high != low >> 31)
403 LayoutUnit returnVal;
404 returnVal.setRawValue(static_cast<int>(result));
408 inline LayoutUnit operator*(const LayoutUnit& a, const LayoutUnit& b)
410 return boundedMultiply(a, b);
413 inline double operator*(const LayoutUnit& a, double b)
415 return a.toDouble() * b;
418 inline float operator*(const LayoutUnit& a, float b)
420 return a.toFloat() * b;
423 inline LayoutUnit operator*(const LayoutUnit& a, int b)
425 return a * LayoutUnit(b);
428 inline LayoutUnit operator*(const LayoutUnit& a, unsigned short b)
430 return a * LayoutUnit(b);
433 inline LayoutUnit operator*(const LayoutUnit& a, unsigned b)
435 return a * LayoutUnit(b);
438 inline LayoutUnit operator*(const LayoutUnit& a, unsigned long b)
440 return a * LayoutUnit(b);
443 inline LayoutUnit operator*(const LayoutUnit& a, unsigned long long b)
445 return a * LayoutUnit(b);
448 inline LayoutUnit operator*(unsigned short a, const LayoutUnit& b)
450 return LayoutUnit(a) * b;
453 inline LayoutUnit operator*(unsigned a, const LayoutUnit& b)
455 return LayoutUnit(a) * b;
458 inline LayoutUnit operator*(unsigned long a, const LayoutUnit& b)
460 return LayoutUnit(a) * b;
463 inline LayoutUnit operator*(unsigned long long a, const LayoutUnit& b)
465 return LayoutUnit(a) * b;
468 inline LayoutUnit operator*(const int a, const LayoutUnit& b)
470 return LayoutUnit(a) * b;
473 inline float operator*(const float a, const LayoutUnit& b)
475 return a * b.toFloat();
478 inline double operator*(const double a, const LayoutUnit& b)
480 return a * b.toDouble();
483 inline LayoutUnit operator/(const LayoutUnit& a, const LayoutUnit& b)
485 LayoutUnit returnVal;
486 long long rawVal = static_cast<long long>(kFixedPointDenominator) * a.rawValue() / b.rawValue();
487 returnVal.setRawValue(clampTo<int>(rawVal));
491 inline float operator/(const LayoutUnit& a, float b)
493 return a.toFloat() / b;
496 inline double operator/(const LayoutUnit& a, double b)
498 return a.toDouble() / b;
501 inline LayoutUnit operator/(const LayoutUnit& a, int b)
503 return a / LayoutUnit(b);
506 inline LayoutUnit operator/(const LayoutUnit& a, unsigned short b)
508 return a / LayoutUnit(b);
511 inline LayoutUnit operator/(const LayoutUnit& a, unsigned b)
513 return a / LayoutUnit(b);
516 inline LayoutUnit operator/(const LayoutUnit& a, unsigned long b)
518 return a / LayoutUnit(b);
521 inline LayoutUnit operator/(const LayoutUnit& a, unsigned long long b)
523 return a / LayoutUnit(b);
526 inline float operator/(const float a, const LayoutUnit& b)
528 return a / b.toFloat();
531 inline double operator/(const double a, const LayoutUnit& b)
533 return a / b.toDouble();
536 inline LayoutUnit operator/(const int a, const LayoutUnit& b)
538 return LayoutUnit(a) / b;
541 inline LayoutUnit operator/(unsigned short a, const LayoutUnit& b)
543 return LayoutUnit(a) / b;
546 inline LayoutUnit operator/(unsigned a, const LayoutUnit& b)
548 return LayoutUnit(a) / b;
551 inline LayoutUnit operator/(unsigned long a, const LayoutUnit& b)
553 return LayoutUnit(a) / b;
556 inline LayoutUnit operator/(unsigned long long a, const LayoutUnit& b)
558 return LayoutUnit(a) / b;
561 ALWAYS_INLINE LayoutUnit operator+(const LayoutUnit& a, const LayoutUnit& b)
563 LayoutUnit returnVal;
564 returnVal.setRawValue(saturatedAddition(a.rawValue(), b.rawValue()));
568 inline LayoutUnit operator+(const LayoutUnit& a, int b)
570 return a + LayoutUnit(b);
573 inline float operator+(const LayoutUnit& a, float b)
575 return a.toFloat() + b;
578 inline double operator+(const LayoutUnit& a, double b)
580 return a.toDouble() + b;
583 inline LayoutUnit operator+(const int a, const LayoutUnit& b)
585 return LayoutUnit(a) + b;
588 inline float operator+(const float a, const LayoutUnit& b)
590 return a + b.toFloat();
593 inline double operator+(const double a, const LayoutUnit& b)
595 return a + b.toDouble();
598 ALWAYS_INLINE LayoutUnit operator-(const LayoutUnit& a, const LayoutUnit& b)
600 LayoutUnit returnVal;
601 returnVal.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue()));
605 inline LayoutUnit operator-(const LayoutUnit& a, int b)
607 return a - LayoutUnit(b);
610 inline LayoutUnit operator-(const LayoutUnit& a, unsigned b)
612 return a - LayoutUnit(b);
615 inline float operator-(const LayoutUnit& a, float b)
617 return a.toFloat() - b;
620 inline double operator-(const LayoutUnit& a, double b)
622 return a.toDouble() - b;
625 inline LayoutUnit operator-(const int a, const LayoutUnit& b)
627 return LayoutUnit(a) - b;
630 inline float operator-(const float a, const LayoutUnit& b)
632 return a - b.toFloat();
635 inline LayoutUnit operator-(const LayoutUnit& a)
637 LayoutUnit returnVal;
638 returnVal.setRawValue(-a.rawValue());
642 // For returning the remainder after a division with integer results.
643 inline LayoutUnit intMod(const LayoutUnit& a, const LayoutUnit& b)
645 // This calculates the modulo so that: a = static_cast<int>(a / b) * b + intMod(a, b).
646 LayoutUnit returnVal;
647 returnVal.setRawValue(a.rawValue() % b.rawValue());
651 inline LayoutUnit operator%(const LayoutUnit& a, const LayoutUnit& b)
653 // This calculates the modulo so that: a = (a / b) * b + a % b.
654 LayoutUnit returnVal;
655 long long rawVal = (static_cast<long long>(kFixedPointDenominator) * a.rawValue()) % b.rawValue();
656 returnVal.setRawValue(rawVal / kFixedPointDenominator);
660 inline LayoutUnit operator%(const LayoutUnit& a, int b)
662 return a % LayoutUnit(b);
665 inline LayoutUnit operator%(int a, const LayoutUnit& b)
667 return LayoutUnit(a) % b;
670 inline LayoutUnit& operator+=(LayoutUnit& a, const LayoutUnit& b)
672 a.setRawValue(saturatedAddition(a.rawValue(), b.rawValue()));
676 inline LayoutUnit& operator+=(LayoutUnit& a, int b)
682 inline LayoutUnit& operator+=(LayoutUnit& a, float b)
688 inline float& operator+=(float& a, const LayoutUnit& b)
694 inline LayoutUnit& operator-=(LayoutUnit& a, int b)
700 inline LayoutUnit& operator-=(LayoutUnit& a, const LayoutUnit& b)
702 a.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue()));
706 inline LayoutUnit& operator-=(LayoutUnit& a, float b)
712 inline float& operator-=(float& a, const LayoutUnit& b)
718 inline LayoutUnit& operator*=(LayoutUnit& a, const LayoutUnit& b)
723 // operator*=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int).
725 inline LayoutUnit& operator*=(LayoutUnit& a, float b)
731 inline float& operator*=(float& a, const LayoutUnit& b)
737 inline LayoutUnit& operator/=(LayoutUnit& a, const LayoutUnit& b)
742 // operator/=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int).
744 inline LayoutUnit& operator/=(LayoutUnit& a, float b)
750 inline float& operator/=(float& a, const LayoutUnit& b)
756 inline int snapSizeToPixel(LayoutUnit size, LayoutUnit location)
758 LayoutUnit fraction = location.fraction();
759 return (fraction + size).round() - fraction.round();
762 inline int roundToInt(LayoutUnit value)
764 return value.round();
767 inline int floorToInt(LayoutUnit value)
769 return value.floor();
772 inline LayoutUnit absoluteValue(const LayoutUnit& value)
777 inline LayoutUnit layoutMod(const LayoutUnit& numerator, const LayoutUnit& denominator)
779 return numerator % denominator;
782 inline bool isIntegerValue(const LayoutUnit value)
784 return value.toInt() == value;
787 inline LayoutUnit clampToLayoutUnit(LayoutUnit value, LayoutUnit min, LayoutUnit max)
798 #endif // LayoutUnit_h