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 "wtf/Assertions.h"
35#include "wtf/MathExtras.h"
36#include "wtf/SaturatedArithmetic.h"
37#include <limits.h>
38#include <limits>
39#include <stdlib.h>
40
41namespace blink {
42
43#if !ERROR_DISABLED
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 kLayoutUnitFractionalBits = 6;
58static const int kFixedPointDenominator = 1 << kLayoutUnitFractionalBits;
59
60const int intMaxForLayoutUnit = INT_MAX / kFixedPointDenominator;
61const int intMinForLayoutUnit = INT_MIN / kFixedPointDenominator;
62
63class LayoutUnit {
64public:
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); }
73
74    static LayoutUnit fromFloatCeil(float value)
75    {
76        LayoutUnit v;
77        v.m_value = clampToInteger(ceilf(value * kFixedPointDenominator));
78        return v;
79    }
80
81    static LayoutUnit fromFloatFloor(float value)
82    {
83        LayoutUnit v;
84        v.m_value = clampToInteger(floorf(value * kFixedPointDenominator));
85        return v;
86    }
87
88    static LayoutUnit fromFloatRound(float value)
89    {
90        if (value >= 0)
91            return clamp(value + epsilon() / 2.0f);
92        return clamp(value - epsilon() / 2.0f);
93    }
94
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
99    {
100        float floatValue = toFloat();
101        if (static_cast<int>(floatValue * kFixedPointDenominator) == m_value)
102            return floatValue;
103        if (floatValue > 0)
104            return nextafterf(floatValue, std::numeric_limits<float>::max());
105        return nextafterf(floatValue, std::numeric_limits<float>::min());
106    }
107    unsigned toUnsigned() const { REPORT_OVERFLOW(m_value >= 0); return toInt(); }
108
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; }
113
114    LayoutUnit operator++(int)
115    {
116        m_value += kFixedPointDenominator;
117        return *this;
118    }
119
120    inline int rawValue() const { return m_value; }
121    inline void setRawValue(int value) { m_value = value; }
122    void setRawValue(long long value)
123    {
124        REPORT_OVERFLOW(value > std::numeric_limits<int>::min() && value < std::numeric_limits<int>::max());
125        m_value = static_cast<int>(value);
126    }
127
128    LayoutUnit abs() const
129    {
130        LayoutUnit returnValue;
131        returnValue.setRawValue(::abs(m_value));
132        return returnValue;
133    }
134#if OS(MACOSX)
135    int wtf_ceil() const
136#else
137    int ceil() const
138#endif
139    {
140        if (UNLIKELY(m_value >= INT_MAX - kFixedPointDenominator + 1))
141            return intMaxForLayoutUnit;
142
143        if (m_value >= 0)
144            return (m_value + kFixedPointDenominator - 1) / kFixedPointDenominator;
145        return toInt();
146    }
147    ALWAYS_INLINE int round() const
148    {
149        return saturatedAddition(rawValue(), kFixedPointDenominator / 2) >> kLayoutUnitFractionalBits;
150    }
151
152    int floor() const
153    {
154        if (UNLIKELY(m_value <= INT_MIN + kFixedPointDenominator - 1))
155            return intMinForLayoutUnit;
156
157        return m_value >> kLayoutUnitFractionalBits;
158    }
159
160    LayoutUnit fraction() const
161    {
162        // Add the fraction to the size (as opposed to the full location) to avoid overflows.
163        // Compute fraction using the mod operator to preserve the sign of the value as it may affect rounding.
164        LayoutUnit fraction;
165        fraction.setRawValue(rawValue() % kFixedPointDenominator);
166        return fraction;
167    }
168
169    bool mightBeSaturated() const
170    {
171        return rawValue() == std::numeric_limits<int>::max()
172            || rawValue() == std::numeric_limits<int>::min();
173    }
174
175    static float epsilon() { return 1.0f / kFixedPointDenominator; }
176
177    static const LayoutUnit max()
178    {
179        LayoutUnit m;
180        m.m_value = std::numeric_limits<int>::max();
181        return m;
182    }
183    static const LayoutUnit min()
184    {
185        LayoutUnit m;
186        m.m_value = std::numeric_limits<int>::min();
187        return m;
188    }
189
190    // Versions of max/min that are slightly smaller/larger than max/min() to allow for roinding without overflowing.
191    static const LayoutUnit nearlyMax()
192    {
193        LayoutUnit m;
194        m.m_value = std::numeric_limits<int>::max() - kFixedPointDenominator / 2;
195        return m;
196    }
197    static const LayoutUnit nearlyMin()
198    {
199        LayoutUnit m;
200        m.m_value = std::numeric_limits<int>::min() + kFixedPointDenominator / 2;
201        return m;
202    }
203
204    static LayoutUnit clamp(double value)
205    {
206        return clampTo<LayoutUnit>(value, LayoutUnit::min(), LayoutUnit::max());
207    }
208
209private:
210    static bool isInBounds(int value)
211    {
212        return ::abs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator;
213    }
214    static bool isInBounds(unsigned value)
215    {
216        return value <= static_cast<unsigned>(std::numeric_limits<int>::max()) / kFixedPointDenominator;
217    }
218    static bool isInBounds(double value)
219    {
220        return ::fabs(value) <= std::numeric_limits<int>::max() / kFixedPointDenominator;
221    }
222
223    ALWAYS_INLINE void setValue(int value)
224    {
225        m_value = saturatedSet(value, kLayoutUnitFractionalBits);
226    }
227
228    inline void setValue(unsigned value)
229    {
230        m_value = saturatedSet(value, kLayoutUnitFractionalBits);
231    }
232
233    int m_value;
234};
235
236inline bool operator<=(const LayoutUnit& a, const LayoutUnit& b)
237{
238    return a.rawValue() <= b.rawValue();
239}
240
241inline bool operator<=(const LayoutUnit& a, float b)
242{
243    return a.toFloat() <= b;
244}
245
246inline bool operator<=(const LayoutUnit& a, int b)
247{
248    return a <= LayoutUnit(b);
249}
250
251inline bool operator<=(const float a, const LayoutUnit& b)
252{
253    return a <= b.toFloat();
254}
255
256inline bool operator<=(const int a, const LayoutUnit& b)
257{
258    return LayoutUnit(a) <= b;
259}
260
261inline bool operator>=(const LayoutUnit& a, const LayoutUnit& b)
262{
263    return a.rawValue() >= b.rawValue();
264}
265
266inline bool operator>=(const LayoutUnit& a, int b)
267{
268    return a >= LayoutUnit(b);
269}
270
271inline bool operator>=(const float a, const LayoutUnit& b)
272{
273    return a >= b.toFloat();
274}
275
276inline bool operator>=(const LayoutUnit& a, float b)
277{
278    return a.toFloat() >= b;
279}
280
281inline bool operator>=(const int a, const LayoutUnit& b)
282{
283    return LayoutUnit(a) >= b;
284}
285
286inline bool operator<(const LayoutUnit& a, const LayoutUnit& b)
287{
288    return a.rawValue() < b.rawValue();
289}
290
291inline bool operator<(const LayoutUnit& a, int b)
292{
293    return a < LayoutUnit(b);
294}
295
296inline bool operator<(const LayoutUnit& a, float b)
297{
298    return a.toFloat() < b;
299}
300
301inline bool operator<(const LayoutUnit& a, double b)
302{
303    return a.toDouble() < b;
304}
305
306inline bool operator<(const int a, const LayoutUnit& b)
307{
308    return LayoutUnit(a) < b;
309}
310
311inline bool operator<(const float a, const LayoutUnit& b)
312{
313    return a < b.toFloat();
314}
315
316inline bool operator>(const LayoutUnit& a, const LayoutUnit& b)
317{
318    return a.rawValue() > b.rawValue();
319}
320
321inline bool operator>(const LayoutUnit& a, double b)
322{
323    return a.toDouble() > b;
324}
325
326inline bool operator>(const LayoutUnit& a, float b)
327{
328    return a.toFloat() > b;
329}
330
331inline bool operator>(const LayoutUnit& a, int b)
332{
333    return a > LayoutUnit(b);
334}
335
336inline bool operator>(const int a, const LayoutUnit& b)
337{
338    return LayoutUnit(a) > b;
339}
340
341inline bool operator>(const float a, const LayoutUnit& b)
342{
343    return a > b.toFloat();
344}
345
346inline bool operator>(const double a, const LayoutUnit& b)
347{
348    return a > b.toDouble();
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 != LayoutUnit(b);
359}
360
361inline bool operator!=(const int a, const LayoutUnit& b)
362{
363    return LayoutUnit(a) != b;
364}
365
366inline bool operator!=(const LayoutUnit& a, int b)
367{
368    return a != LayoutUnit(b);
369}
370
371inline bool operator==(const LayoutUnit& a, const LayoutUnit& b)
372{
373    return a.rawValue() == b.rawValue();
374}
375
376inline bool operator==(const LayoutUnit& a, int b)
377{
378    return a == LayoutUnit(b);
379}
380
381inline bool operator==(const int a, const LayoutUnit& b)
382{
383    return LayoutUnit(a) == b;
384}
385
386inline bool operator==(const LayoutUnit& a, float b)
387{
388    return a.toFloat() == b;
389}
390
391inline bool operator==(const float a, const LayoutUnit& b)
392{
393    return a == b.toFloat();
394}
395
396// For multiplication that's prone to overflow, this bounds it to LayoutUnit::max() and ::min()
397inline LayoutUnit boundedMultiply(const LayoutUnit& a, const LayoutUnit& b)
398{
399    int64_t result = static_cast<int64_t>(a.rawValue()) * static_cast<int64_t>(b.rawValue()) / kFixedPointDenominator;
400    int32_t high = static_cast<int32_t>(result >> 32);
401    int32_t low = static_cast<int32_t>(result);
402    uint32_t saturated = (static_cast<uint32_t>(a.rawValue() ^ b.rawValue()) >> 31) + std::numeric_limits<int>::max();
403    // If the higher 32 bits does not match the lower 32 with sign extension the operation overflowed.
404    if (high != low >> 31)
405        result = saturated;
406
407    LayoutUnit returnVal;
408    returnVal.setRawValue(static_cast<int>(result));
409    return returnVal;
410}
411
412inline LayoutUnit operator*(const LayoutUnit& a, const LayoutUnit& b)
413{
414    return boundedMultiply(a, b);
415}
416
417inline double operator*(const LayoutUnit& a, double b)
418{
419    return a.toDouble() * b;
420}
421
422inline float operator*(const LayoutUnit& a, float b)
423{
424    return a.toFloat() * b;
425}
426
427inline LayoutUnit operator*(const LayoutUnit& a, int b)
428{
429    return a * LayoutUnit(b);
430}
431
432inline LayoutUnit operator*(const LayoutUnit& a, unsigned short b)
433{
434    return a * LayoutUnit(b);
435}
436
437inline LayoutUnit operator*(const LayoutUnit& a, unsigned b)
438{
439    return a * LayoutUnit(b);
440}
441
442inline LayoutUnit operator*(const LayoutUnit& a, unsigned long b)
443{
444    return a * LayoutUnit(b);
445}
446
447inline LayoutUnit operator*(const LayoutUnit& a, unsigned long long b)
448{
449    return a * LayoutUnit(b);
450}
451
452inline LayoutUnit operator*(unsigned short a, const LayoutUnit& b)
453{
454    return LayoutUnit(a) * b;
455}
456
457inline LayoutUnit operator*(unsigned a, const LayoutUnit& b)
458{
459    return LayoutUnit(a) * b;
460}
461
462inline LayoutUnit operator*(unsigned long a, const LayoutUnit& b)
463{
464    return LayoutUnit(a) * b;
465}
466
467inline LayoutUnit operator*(unsigned long long a, const LayoutUnit& b)
468{
469    return LayoutUnit(a) * b;
470}
471
472inline LayoutUnit operator*(const int a, const LayoutUnit& b)
473{
474    return LayoutUnit(a) * b;
475}
476
477inline float operator*(const float a, const LayoutUnit& b)
478{
479    return a * b.toFloat();
480}
481
482inline double operator*(const double a, const LayoutUnit& b)
483{
484    return a * b.toDouble();
485}
486
487inline LayoutUnit operator/(const LayoutUnit& a, const LayoutUnit& b)
488{
489    LayoutUnit returnVal;
490    long long rawVal = static_cast<long long>(kFixedPointDenominator) * a.rawValue() / b.rawValue();
491    returnVal.setRawValue(clampTo<int>(rawVal));
492    return returnVal;
493}
494
495inline float operator/(const LayoutUnit& a, float b)
496{
497    return a.toFloat() / b;
498}
499
500inline double operator/(const LayoutUnit& a, double b)
501{
502    return a.toDouble() / b;
503}
504
505inline LayoutUnit operator/(const LayoutUnit& a, int b)
506{
507    return a / LayoutUnit(b);
508}
509
510inline LayoutUnit operator/(const LayoutUnit& a, unsigned short b)
511{
512    return a / LayoutUnit(b);
513}
514
515inline LayoutUnit operator/(const LayoutUnit& a, unsigned b)
516{
517    return a / LayoutUnit(b);
518}
519
520inline LayoutUnit operator/(const LayoutUnit& a, unsigned long b)
521{
522    return a / LayoutUnit(b);
523}
524
525inline LayoutUnit operator/(const LayoutUnit& a, unsigned long long b)
526{
527    return a / LayoutUnit(b);
528}
529
530inline float operator/(const float a, const LayoutUnit& b)
531{
532    return a / b.toFloat();
533}
534
535inline double operator/(const double a, const LayoutUnit& b)
536{
537    return a / b.toDouble();
538}
539
540inline LayoutUnit operator/(const int a, const LayoutUnit& b)
541{
542    return LayoutUnit(a) / b;
543}
544
545inline LayoutUnit operator/(unsigned short a, const LayoutUnit& b)
546{
547    return LayoutUnit(a) / b;
548}
549
550inline LayoutUnit operator/(unsigned a, const LayoutUnit& b)
551{
552    return LayoutUnit(a) / b;
553}
554
555inline LayoutUnit operator/(unsigned long a, const LayoutUnit& b)
556{
557    return LayoutUnit(a) / b;
558}
559
560inline LayoutUnit operator/(unsigned long long a, const LayoutUnit& b)
561{
562    return LayoutUnit(a) / b;
563}
564
565ALWAYS_INLINE LayoutUnit operator+(const LayoutUnit& a, const LayoutUnit& b)
566{
567    LayoutUnit returnVal;
568    returnVal.setRawValue(saturatedAddition(a.rawValue(), b.rawValue()));
569    return returnVal;
570}
571
572inline LayoutUnit operator+(const LayoutUnit& a, int b)
573{
574    return a + LayoutUnit(b);
575}
576
577inline float operator+(const LayoutUnit& a, float b)
578{
579    return a.toFloat() + b;
580}
581
582inline double operator+(const LayoutUnit& a, double b)
583{
584    return a.toDouble() + b;
585}
586
587inline LayoutUnit operator+(const int a, const LayoutUnit& b)
588{
589    return LayoutUnit(a) + b;
590}
591
592inline float operator+(const float a, const LayoutUnit& b)
593{
594    return a + b.toFloat();
595}
596
597inline double operator+(const double a, const LayoutUnit& b)
598{
599    return a + b.toDouble();
600}
601
602ALWAYS_INLINE LayoutUnit operator-(const LayoutUnit& a, const LayoutUnit& b)
603{
604    LayoutUnit returnVal;
605    returnVal.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue()));
606    return returnVal;
607}
608
609inline LayoutUnit operator-(const LayoutUnit& a, int b)
610{
611    return a - LayoutUnit(b);
612}
613
614inline LayoutUnit operator-(const LayoutUnit& a, unsigned b)
615{
616    return a - LayoutUnit(b);
617}
618
619inline float operator-(const LayoutUnit& a, float b)
620{
621    return a.toFloat() - b;
622}
623
624inline LayoutUnit operator-(const int a, const LayoutUnit& b)
625{
626    return LayoutUnit(a) - b;
627}
628
629inline float operator-(const float a, const LayoutUnit& b)
630{
631    return a - b.toFloat();
632}
633
634inline LayoutUnit operator-(const LayoutUnit& a)
635{
636    LayoutUnit returnVal;
637    returnVal.setRawValue(-a.rawValue());
638    return returnVal;
639}
640
641// For returning the remainder after a division with integer results.
642inline LayoutUnit intMod(const LayoutUnit& a, const LayoutUnit& b)
643{
644    // This calculates the modulo so that: a = static_cast<int>(a / b) * b + intMod(a, b).
645    LayoutUnit returnVal;
646    returnVal.setRawValue(a.rawValue() % b.rawValue());
647    return returnVal;
648}
649
650inline LayoutUnit operator%(const LayoutUnit& a, const LayoutUnit& b)
651{
652    // This calculates the modulo so that: a = (a / b) * b + a % b.
653    LayoutUnit returnVal;
654    long long rawVal = (static_cast<long long>(kFixedPointDenominator) * a.rawValue()) % b.rawValue();
655    returnVal.setRawValue(rawVal / kFixedPointDenominator);
656    return returnVal;
657}
658
659inline LayoutUnit operator%(const LayoutUnit& a, int b)
660{
661    return a % LayoutUnit(b);
662}
663
664inline LayoutUnit operator%(int a, const LayoutUnit& b)
665{
666    return LayoutUnit(a) % b;
667}
668
669inline LayoutUnit& operator+=(LayoutUnit& a, const LayoutUnit& b)
670{
671    a.setRawValue(saturatedAddition(a.rawValue(), b.rawValue()));
672    return a;
673}
674
675inline LayoutUnit& operator+=(LayoutUnit& a, int b)
676{
677    a = a + b;
678    return a;
679}
680
681inline LayoutUnit& operator+=(LayoutUnit& a, float b)
682{
683    a = a + b;
684    return a;
685}
686
687inline float& operator+=(float& a, const LayoutUnit& b)
688{
689    a = a + b;
690    return a;
691}
692
693inline LayoutUnit& operator-=(LayoutUnit& a, int b)
694{
695    a = a - b;
696    return a;
697}
698
699inline LayoutUnit& operator-=(LayoutUnit& a, const LayoutUnit& b)
700{
701    a.setRawValue(saturatedSubtraction(a.rawValue(), b.rawValue()));
702    return a;
703}
704
705inline LayoutUnit& operator-=(LayoutUnit& a, float b)
706{
707    a = a - b;
708    return a;
709}
710
711inline float& operator-=(float& a, const LayoutUnit& b)
712{
713    a = a - b;
714    return a;
715}
716
717inline LayoutUnit& operator*=(LayoutUnit& a, const LayoutUnit& b)
718{
719    a = a * b;
720    return a;
721}
722// operator*=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int).
723
724inline LayoutUnit& operator*=(LayoutUnit& a, float b)
725{
726    a = a * b;
727    return a;
728}
729
730inline float& operator*=(float& a, const LayoutUnit& b)
731{
732    a = a * b;
733    return a;
734}
735
736inline LayoutUnit& operator/=(LayoutUnit& a, const LayoutUnit& b)
737{
738    a = a / b;
739    return a;
740}
741// operator/=(LayoutUnit& a, int b) is supported by the operator above plus LayoutUnit(int).
742
743inline LayoutUnit& operator/=(LayoutUnit& a, float b)
744{
745    a = a / b;
746    return a;
747}
748
749inline float& operator/=(float& a, const LayoutUnit& b)
750{
751    a = a / b;
752    return a;
753}
754
755inline int snapSizeToPixel(LayoutUnit size, LayoutUnit location)
756{
757    LayoutUnit fraction = location.fraction();
758    return (fraction + size).round() - fraction.round();
759}
760
761inline int roundToInt(LayoutUnit value)
762{
763    return value.round();
764}
765
766inline int floorToInt(LayoutUnit value)
767{
768    return value.floor();
769}
770
771inline LayoutUnit absoluteValue(const LayoutUnit& value)
772{
773    return value.abs();
774}
775
776inline LayoutUnit layoutMod(const LayoutUnit& numerator, const LayoutUnit& denominator)
777{
778    return numerator % denominator;
779}
780
781inline bool isIntegerValue(const LayoutUnit value)
782{
783    return value.toInt() == value;
784}
785
786inline LayoutUnit clampToLayoutUnit(LayoutUnit value, LayoutUnit min, LayoutUnit max)
787{
788    if (value >= max)
789        return max;
790    if (value <= min)
791        return min;
792    return value;
793}
794
795} // namespace blink
796
797#endif // LayoutUnit_h
798