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.
33 #include "ValueToString.h"
38 #include <wtf/MathExtras.h>
39 #include <wtf/SaturatedArithmetic.h>
49 #define REPORT_OVERFLOW(doesOverflow) ((void)0)
53 #define REPORT_OVERFLOW(doesOverflow) do \
54 if (!(doesOverflow)) { \
55 WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "!(%s)", #doesOverflow); \
61 static const int kFixedPointDenominator = 64;
62 const int intMaxForLayoutUnit = INT_MAX / kFixedPointDenominator;
63 const int intMinForLayoutUnit = INT_MIN / kFixedPointDenominator;
67 LayoutUnit() : m_value(0) { }
68 LayoutUnit(int value) { setValue(value); }
69 LayoutUnit(unsigned short value) { setValue(value); }
70 LayoutUnit(unsigned value) { setValue(value); }
71 LayoutUnit(unsigned long value)
73 m_value = clampTo<int>(value * kFixedPointDenominator);
75 LayoutUnit(unsigned long long value)
77 m_value = clampTo<int>(value * kFixedPointDenominator);
79 LayoutUnit(float value)
81 m_value = clampToInteger(value * kFixedPointDenominator);
83 LayoutUnit(double value)
85 m_value = clampToInteger(value * kFixedPointDenominator);
88 static LayoutUnit fromPixel(int value)
90 return LayoutUnit(value);
93 static LayoutUnit fromFloatCeil(float value)
96 v.m_value = clampToInteger(ceilf(value * kFixedPointDenominator));
100 static LayoutUnit fromFloatFloor(float value)
103 v.m_value = clampToInteger(floorf(value * kFixedPointDenominator));
107 static LayoutUnit fromFloatRound(float value)
110 return clamp(value + epsilon() / 2.0f);
111 return clamp(value - epsilon() / 2.0f);
114 int toInt() const { return m_value / kFixedPointDenominator; }
115 float toFloat() const { return static_cast<float>(m_value) / kFixedPointDenominator; }
116 double toDouble() const { return static_cast<double>(m_value) / kFixedPointDenominator; }
117 unsigned toUnsigned() const { REPORT_OVERFLOW(m_value >= 0); return toInt(); }
119 operator int() const { return toInt(); }
120 operator float() const { return toFloat(); }
121 operator double() const { return toDouble(); }
122 explicit operator bool() const { return m_value; }
124 LayoutUnit& operator++()
126 m_value += kFixedPointDenominator;
130 inline int rawValue() const { return m_value; }
131 inline void setRawValue(int value) { m_value = value; }
132 void setRawValue(long long value)
134 REPORT_OVERFLOW(value > std::numeric_limits<int>::min() && value < std::numeric_limits<int>::max());
135 m_value = static_cast<int>(value);
138 LayoutUnit abs() const
140 LayoutUnit returnValue;
141 returnValue.setRawValue(::abs(m_value));
146 if (UNLIKELY(m_value >= INT_MAX - kFixedPointDenominator + 1))
147 return intMaxForLayoutUnit;
149 return (m_value + kFixedPointDenominator - 1) / kFixedPointDenominator;
156 return saturatedAddition(rawValue(), kFixedPointDenominator / 2) / kFixedPointDenominator;
157 return saturatedSubtraction(rawValue(), (kFixedPointDenominator / 2) - 1) / kFixedPointDenominator;
162 if (UNLIKELY(m_value <= INT_MIN + kFixedPointDenominator - 1))
163 return intMinForLayoutUnit;
166 return (m_value - kFixedPointDenominator + 1) / kFixedPointDenominator;
169 float ceilToFloat() const
171 float floatValue = toFloat();
172 if (static_cast<int>(floatValue * kFixedPointDenominator) == m_value)
175 return nextafterf(floatValue, std::numeric_limits<float>::max());
176 return nextafterf(floatValue, std::numeric_limits<float>::min());
179 LayoutUnit fraction() const
181 // Add the fraction to the size (as opposed to the full location) to avoid overflows.
182 // Compute fraction using the mod operator to preserve the sign of the value as it may affect rounding.
184 fraction.setRawValue(rawValue() % kFixedPointDenominator);
188 bool mightBeSaturated() const
190 return rawValue() == std::numeric_limits<int>::max()
191 || rawValue() == std::numeric_limits<int>::min();
194 static float epsilon() { return 1.0f / kFixedPointDenominator; }
196 static const LayoutUnit max()
199 m.m_value = std::numeric_limits<int>::max();
202 static const LayoutUnit min()
205 m.m_value = std::numeric_limits<int>::min();
209 // Versions of max/min that are slightly smaller/larger than max/min() to allow for roinding without overflowing.
210 static const LayoutUnit nearlyMax()
213 m.m_value = std::numeric_limits<int>::max() - kFixedPointDenominator / 2;
216 static const LayoutUnit nearlyMin()
219 m.m_value = std::numeric_limits<int>::min() + kFixedPointDenominator / 2;
223 static LayoutUnit clamp(double value)
225 return clampTo<LayoutUnit>(value, LayoutUnit::min(), LayoutUnit::max());
229 static bool isInBounds(int value)
231 return ::abs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator;
233 static bool isInBounds(unsigned value)
235 return value <= static_cast<unsigned>(std::numeric_limits<int>::max()) / kFixedPointDenominator;
237 static bool isInBounds(double value)
239 return ::fabs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator;
242 inline void setValue(int value)
244 if (value > intMaxForLayoutUnit)
245 m_value = std::numeric_limits<int>::max();
246 else if (value < intMinForLayoutUnit)
247 m_value = std::numeric_limits<int>::min();
249 m_value = value * kFixedPointDenominator;
251 inline void setValue(unsigned value)
253 if (value >= static_cast<unsigned>(intMaxForLayoutUnit))
254 m_value = std::numeric_limits<int>::max();
256 m_value = value * kFixedPointDenominator;
262 inline bool operator<=(const LayoutUnit& a, const LayoutUnit& b)
264 return a.rawValue() <= b.rawValue();
267 inline bool operator<=(const LayoutUnit& a, float b)
269 return a.toFloat() <= b;
272 inline bool operator<=(const LayoutUnit& a, int b)
274 return a <= LayoutUnit(b);
277 inline bool operator<=(const float a, const LayoutUnit& b)
279 return a <= b.toFloat();
282 inline bool operator<=(const int a, const LayoutUnit& b)
284 return LayoutUnit(a) <= b;
287 inline bool operator>=(const LayoutUnit& a, const LayoutUnit& b)
289 return a.rawValue() >= b.rawValue();
292 inline bool operator>=(const LayoutUnit& a, int b)
294 return a >= LayoutUnit(b);
297 inline bool operator>=(const float a, const LayoutUnit& b)
299 return a >= b.toFloat();
302 inline bool operator>=(const LayoutUnit& a, float b)
304 return a.toFloat() >= b;
307 inline bool operator>=(const int a, const LayoutUnit& b)
309 return LayoutUnit(a) >= b;
312 inline bool operator<(const LayoutUnit& a, const LayoutUnit& b)
314 return a.rawValue() < b.rawValue();
317 inline bool operator<(const LayoutUnit& a, int b)
319 return a < LayoutUnit(b);
322 inline bool operator<(const LayoutUnit& a, float b)
324 return a.toFloat() < b;
327 inline bool operator<(const LayoutUnit& a, double b)
329 return a.toDouble() < 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 LayoutUnit& a, const LayoutUnit& b)
344 return a.rawValue() > b.rawValue();
347 inline bool operator>(const LayoutUnit& a, double b)
349 return a.toDouble() > b;
352 inline bool operator>(const LayoutUnit& a, float b)
354 return a.toFloat() > b;
357 inline bool operator>(const LayoutUnit& a, int b)
359 return a > LayoutUnit(b);
362 inline bool operator>(const int a, const LayoutUnit& b)
364 return LayoutUnit(a) > b;
367 inline bool operator>(const float a, const LayoutUnit& b)
369 return a > b.toFloat();
372 inline bool operator>(const double a, const LayoutUnit& b)
374 return a > b.toDouble();
377 inline bool operator!=(const LayoutUnit& a, const LayoutUnit& b)
379 return a.rawValue() != b.rawValue();
382 inline bool operator!=(const LayoutUnit& a, float b)
384 return a != LayoutUnit(b);
387 inline bool operator!=(const int a, const LayoutUnit& b)
389 return LayoutUnit(a) != b;
392 inline bool operator!=(const LayoutUnit& a, int b)
394 return a != LayoutUnit(b);
397 inline bool operator==(const LayoutUnit& a, const LayoutUnit& b)
399 return a.rawValue() == b.rawValue();
402 inline bool operator==(const LayoutUnit& a, int b)
404 return a == LayoutUnit(b);
407 inline bool operator==(const int a, const LayoutUnit& b)
409 return LayoutUnit(a) == b;
412 inline bool operator==(const LayoutUnit& a, float b)
414 return a.toFloat() == b;
417 inline bool operator==(const float a, const LayoutUnit& b)
419 return a == b.toFloat();
422 // For multiplication that's prone to overflow, this bounds it to LayoutUnit::max() and ::min()
423 inline LayoutUnit boundedMultiply(const LayoutUnit& a, const LayoutUnit& b)
425 int64_t result = static_cast<int64_t>(a.rawValue()) * static_cast<int64_t>(b.rawValue()) / kFixedPointDenominator;
426 int32_t high = static_cast<int32_t>(result >> 32);
427 int32_t low = static_cast<int32_t>(result);
428 uint32_t saturated = (static_cast<uint32_t>(a.rawValue() ^ b.rawValue()) >> 31) + std::numeric_limits<int>::max();
429 // If the higher 32 bits does not match the lower 32 with sign extension the operation overflowed.
430 if (high != low >> 31)
433 LayoutUnit returnVal;
434 returnVal.setRawValue(static_cast<int>(result));
438 inline LayoutUnit operator*(const LayoutUnit& a, const LayoutUnit& b)
440 return boundedMultiply(a, b);
443 inline double operator*(const LayoutUnit& a, double b)
445 return a.toDouble() * b;
448 inline float operator*(const LayoutUnit& a, float b)
450 return a.toFloat() * b;
453 inline LayoutUnit operator*(const LayoutUnit& a, int b)
455 return a * LayoutUnit(b);
458 inline LayoutUnit operator*(const LayoutUnit& a, unsigned short b)
460 return a * LayoutUnit(b);
463 inline LayoutUnit operator*(const LayoutUnit& a, unsigned b)
465 return a * LayoutUnit(b);
468 inline LayoutUnit operator*(const LayoutUnit& a, unsigned long b)
470 return a * LayoutUnit(b);
473 inline LayoutUnit operator*(const LayoutUnit& a, unsigned long long b)
475 return a * LayoutUnit(b);
478 inline LayoutUnit operator*(unsigned short a, const LayoutUnit& b)
480 return LayoutUnit(a) * b;
483 inline LayoutUnit operator*(unsigned a, const LayoutUnit& b)
485 return LayoutUnit(a) * b;
488 inline LayoutUnit operator*(unsigned long a, const LayoutUnit& b)
490 return LayoutUnit(a) * b;
493 inline LayoutUnit operator*(unsigned long long a, const LayoutUnit& b)
495 return LayoutUnit(a) * b;
498 inline LayoutUnit operator*(const int a, const LayoutUnit& b)
500 return LayoutUnit(a) * b;
503 inline float operator*(const float a, const LayoutUnit& b)
505 return a * b.toFloat();
508 inline double operator*(const double a, const LayoutUnit& b)
510 return a * b.toDouble();
513 inline LayoutUnit operator/(const LayoutUnit& a, const LayoutUnit& b)
515 LayoutUnit returnVal;
516 long long rawVal = static_cast<long long>(kFixedPointDenominator) * a.rawValue() / b.rawValue();
517 returnVal.setRawValue(clampTo<int>(rawVal));
521 inline float operator/(const LayoutUnit& a, float b)
523 return a.toFloat() / b;
526 inline double operator/(const LayoutUnit& a, double b)
528 return a.toDouble() / b;
531 inline LayoutUnit operator/(const LayoutUnit& a, int b)
533 return a / LayoutUnit(b);
536 inline LayoutUnit operator/(const LayoutUnit& a, unsigned short b)
538 return a / LayoutUnit(b);
541 inline LayoutUnit operator/(const LayoutUnit& a, unsigned b)
543 return a / LayoutUnit(b);
546 inline LayoutUnit operator/(const LayoutUnit& a, unsigned long b)
548 return a / LayoutUnit(b);
551 inline LayoutUnit operator/(const LayoutUnit& a, unsigned long long b)
553 return a / LayoutUnit(b);
556 inline float operator/(const float a, const LayoutUnit& b)
558 return a / b.toFloat();
561 inline double operator/(const double a, const LayoutUnit& b)
563 return a / b.toDouble();
566 inline LayoutUnit operator/(const int a, const LayoutUnit& b)
568 return LayoutUnit(a) / b;
571 inline LayoutUnit operator/(unsigned short a, const LayoutUnit& b)
573 return LayoutUnit(a) / b;
576 inline LayoutUnit operator/(unsigned a, const LayoutUnit& b)
578 return LayoutUnit(a) / b;
581 inline LayoutUnit operator/(unsigned long a, const LayoutUnit& b)
583 return LayoutUnit(a) / b;
586 inline LayoutUnit operator/(unsigned long long a, const LayoutUnit& b)
588 return LayoutUnit(a) / b;
591 inline LayoutUnit operator+(const LayoutUnit& a, const LayoutUnit& b)
593 LayoutUnit returnVal;
594 returnVal.setRawValue(saturatedAddition(a.rawValue(), b.rawValue()));
598 inline LayoutUnit operator+(const LayoutUnit& a, int b)
600 return a + LayoutUnit(b);
603 inline float operator+(const LayoutUnit& a, float b)
605 return a.toFloat() + b;
608 inline double operator+(const LayoutUnit& a, double b)
610 return a.toDouble() + b;
613 inline LayoutUnit operator+(const int a, const LayoutUnit& b)
615 return LayoutUnit(a) + b;
618 inline float operator+(const float a, const LayoutUnit& b)
620 return a + b.toFloat();
623 inline double operator+(const double a, const LayoutUnit& b)
625 return a + b.toDouble();
628 inline LayoutUnit operator-(const LayoutUnit& a, const LayoutUnit& b)
630 LayoutUnit returnVal;
631 returnVal.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue()));
635 inline LayoutUnit operator-(const LayoutUnit& a, int b)
637 return a - LayoutUnit(b);
640 inline LayoutUnit operator-(const LayoutUnit& a, unsigned b)
642 return a - LayoutUnit(b);
645 inline float operator-(const LayoutUnit& a, float b)
647 return a.toFloat() - b;
650 inline LayoutUnit operator-(const int a, const LayoutUnit& b)
652 return LayoutUnit(a) - b;
655 inline float operator-(const float a, const LayoutUnit& b)
657 return a - b.toFloat();
660 inline LayoutUnit operator-(const LayoutUnit& a)
662 LayoutUnit returnVal;
663 returnVal.setRawValue(-a.rawValue());
667 // For returning the remainder after a division with integer results.
668 inline LayoutUnit intMod(const LayoutUnit& a, const LayoutUnit& b)
670 // This calculates the modulo so that: a = static_cast<int>(a / b) * b + intMod(a, b).
671 LayoutUnit returnVal;
672 returnVal.setRawValue(a.rawValue() % b.rawValue());
676 inline LayoutUnit operator%(const LayoutUnit& a, const LayoutUnit& b)
678 // This calculates the modulo so that: a = (a / b) * b + a % b.
679 LayoutUnit returnVal;
680 long long rawVal = (static_cast<long long>(kFixedPointDenominator) * a.rawValue()) % b.rawValue();
681 returnVal.setRawValue(rawVal / kFixedPointDenominator);
685 inline LayoutUnit operator%(const LayoutUnit& a, int b)
687 return a % LayoutUnit(b);
690 inline LayoutUnit operator%(int a, const LayoutUnit& b)
692 return LayoutUnit(a) % b;
695 inline LayoutUnit& operator+=(LayoutUnit& a, const LayoutUnit& b)
697 a.setRawValue(saturatedAddition(a.rawValue(), b.rawValue()));
701 inline LayoutUnit& operator+=(LayoutUnit& a, int b)
707 inline LayoutUnit& operator+=(LayoutUnit& a, float b)
713 inline float& operator+=(float& a, const LayoutUnit& b)
719 inline LayoutUnit& operator-=(LayoutUnit& a, int b)
725 inline LayoutUnit& operator-=(LayoutUnit& a, const LayoutUnit& b)
727 a.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue()));
731 inline LayoutUnit& operator-=(LayoutUnit& a, float b)
737 inline float& operator-=(float& a, const LayoutUnit& b)
743 inline LayoutUnit& operator*=(LayoutUnit& a, const LayoutUnit& b)
748 // operator*=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int).
750 inline LayoutUnit& operator*=(LayoutUnit& a, float b)
756 inline float& operator*=(float& a, const LayoutUnit& b)
762 inline LayoutUnit& operator/=(LayoutUnit& a, const LayoutUnit& b)
767 // operator/=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int).
769 inline LayoutUnit& operator/=(LayoutUnit& a, float b)
775 inline float& operator/=(float& a, const LayoutUnit& b)
781 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const LayoutUnit&);
783 inline int roundToInt(LayoutUnit value)
785 return value.round();
788 inline int floorToInt(LayoutUnit value)
790 return value.floor();
793 inline float roundToDevicePixel(LayoutUnit value, float pixelSnappingFactor, bool needsDirectionalRounding = false)
795 double valueToRound = value.toDouble();
796 if (needsDirectionalRounding)
797 valueToRound -= LayoutUnit::epsilon() / (2 * kFixedPointDenominator);
799 if (valueToRound >= 0)
800 return round(valueToRound * pixelSnappingFactor) / pixelSnappingFactor;
802 // This adjusts directional rounding on negative halfway values. It produces the same direction for both negative and positive values.
803 // Instead of rounding negative halfway cases away from zero, we translate them to positive values before rounding.
804 // It helps snapping relative negative coordinates to the same position as if they were positive absolute coordinates.
805 unsigned translateOrigin = -value.rawValue();
806 return (round((valueToRound + translateOrigin) * pixelSnappingFactor) / pixelSnappingFactor) - translateOrigin;
809 inline float floorToDevicePixel(LayoutUnit value, float pixelSnappingFactor)
811 return floorf((value.rawValue() * pixelSnappingFactor) / kFixedPointDenominator) / pixelSnappingFactor;
814 inline float ceilToDevicePixel(LayoutUnit value, float pixelSnappingFactor)
816 return ceilf((value.rawValue() * pixelSnappingFactor) / kFixedPointDenominator) / pixelSnappingFactor;
819 inline LayoutUnit absoluteValue(const LayoutUnit& value)
824 inline bool isIntegerValue(const LayoutUnit value)
826 return value.toInt() == value;
830 // This structure is used by PODIntervalTree for debugging.
832 struct ValueToString<LayoutUnit> {
833 static String string(const LayoutUnit value) { return String::number(value.toFloat()); }
837 } // namespace WebCore