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