Bug 1905044 - Add tabbrowser-reviewers, theme-reviewers, sessionstore-reviewers to...
[gecko.git] / gfx / 2d / BasePoint.h
blobb7b0adbabd77dbbba153c7a6313b878a3af416a3
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MOZILLA_GFX_BASEPOINT_H_
8 #define MOZILLA_GFX_BASEPOINT_H_
10 #include <cmath>
11 #include <ostream>
12 #include <type_traits>
13 #include "mozilla/Attributes.h"
14 #include "mozilla/FloatingPoint.h"
15 #include "Coord.h"
17 namespace mozilla {
18 namespace gfx {
20 template <class T, typename EnableT = void>
21 struct FloatType;
23 template <typename T>
24 struct FloatType<T, typename std::enable_if_t<std::is_integral_v<T>>> {
25 using type = float;
28 template <typename T>
29 struct FloatType<T, typename std::enable_if_t<std::is_floating_point_v<T>>> {
30 using type = T;
33 template <typename Units, typename Rep>
34 struct FloatType<IntCoordTyped<Units, Rep>> {
35 using type = CoordTyped<Units, float>;
38 template <typename Units, typename Rep>
39 struct FloatType<CoordTyped<Units, Rep>> {
40 using type = CoordTyped<Units, Rep>;
43 template <typename T>
44 using FloatType_t = typename FloatType<T>::type;
46 /**
47 * Do not use this class directly. Subclass it, pass that subclass as the
48 * Sub parameter, and only use that subclass. This allows methods to safely
49 * cast 'this' to 'Sub*'.
51 template <class T, class Sub, class Coord = T>
52 struct BasePoint {
53 union {
54 struct {
55 Coord x, y;
57 Coord components[2];
60 // Constructors
61 constexpr BasePoint() : x(0), y(0) {}
62 constexpr BasePoint(Coord aX, Coord aY) : x(aX), y(aY) {}
64 MOZ_ALWAYS_INLINE Coord X() const { return x; }
65 MOZ_ALWAYS_INLINE Coord Y() const { return y; }
67 void MoveTo(Coord aX, Coord aY) {
68 x = aX;
69 y = aY;
71 void MoveBy(Coord aDx, Coord aDy) {
72 x += aDx;
73 y += aDy;
76 // Note that '=' isn't defined so we'll get the
77 // compiler generated default assignment operator
79 bool operator==(const Sub& aPoint) const {
80 return x == aPoint.x && y == aPoint.y;
82 bool operator!=(const Sub& aPoint) const {
83 return x != aPoint.x || y != aPoint.y;
86 Sub operator+(const Sub& aPoint) const {
87 return Sub(x + aPoint.x, y + aPoint.y);
89 Sub operator-(const Sub& aPoint) const {
90 return Sub(x - aPoint.x, y - aPoint.y);
92 Sub& operator+=(const Sub& aPoint) {
93 x += aPoint.x;
94 y += aPoint.y;
95 return *static_cast<Sub*>(this);
97 Sub& operator-=(const Sub& aPoint) {
98 x -= aPoint.x;
99 y -= aPoint.y;
100 return *static_cast<Sub*>(this);
103 Sub operator*(T aScale) const { return Sub(x * aScale, y * aScale); }
104 Sub operator/(T aScale) const { return Sub(x / aScale, y / aScale); }
106 Sub operator-() const { return Sub(-x, -y); }
108 T DotProduct(const Sub& aPoint) const {
109 return x.value * aPoint.x.value + y.value * aPoint.y.value;
112 FloatType_t<Coord> Length() const {
113 return FloatType_t<Coord>(hypot(x.value, y.value));
116 T LengthSquare() const { return x.value * x.value + y.value * y.value; }
118 // Round() is *not* rounding to nearest integer if the values are negative.
119 // They are always rounding as floor(n + 0.5).
120 // See https://bugzilla.mozilla.org/show_bug.cgi?id=410748#c14
121 Sub& Round() {
122 x = Coord(std::floor(T(x) + T(0.5f)));
123 y = Coord(std::floor(T(y) + T(0.5f)));
124 return *static_cast<Sub*>(this);
127 // "Finite" means not inf and not NaN
128 bool IsFinite() const {
129 using FloatType =
130 std::conditional_t<std::is_same_v<T, float>, float, double>;
131 return (std::isfinite(FloatType(x)) && std::isfinite(FloatType(y)));
134 void Clamp(Coord aMaxAbsValue) {
135 x = std::max(std::min(x, aMaxAbsValue), -aMaxAbsValue);
136 y = std::max(std::min(y, aMaxAbsValue), -aMaxAbsValue);
139 friend std::ostream& operator<<(std::ostream& stream,
140 const BasePoint<T, Sub, Coord>& aPoint) {
141 return stream << '(' << aPoint.x << ',' << aPoint.y << ')';
145 } // namespace gfx
146 } // namespace mozilla
148 #endif /* MOZILLA_GFX_BASEPOINT_H_ */