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_
12 #include <type_traits>
13 #include "mozilla/Attributes.h"
14 #include "mozilla/FloatingPoint.h"
20 template <class T
, typename EnableT
= void>
24 struct FloatType
<T
, typename
std::enable_if_t
<std::is_integral_v
<T
>>> {
29 struct FloatType
<T
, typename
std::enable_if_t
<std::is_floating_point_v
<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
>;
44 using FloatType_t
= typename FloatType
<T
>::type
;
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
>
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
) {
71 void MoveBy(Coord aDx
, Coord 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
) {
95 return *static_cast<Sub
*>(this);
97 Sub
& operator-=(const Sub
& aPoint
) {
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
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 {
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::clamp(x
, -aMaxAbsValue
, aMaxAbsValue
);
136 y
= std::clamp(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
<< ')';
146 } // namespace mozilla
148 #endif /* MOZILLA_GFX_BASEPOINT_H_ */