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