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