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