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