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 * Do not use this class directly. Subclass it, pass that subclass as the
21 * Sub parameter, and only use that subclass. This allows methods to safely
22 * cast 'this' to 'Sub*'.
24 template <class T
, class Sub
, class Coord
= T
>
34 constexpr BasePoint() : x(0), y(0) {}
35 constexpr BasePoint(Coord aX
, Coord aY
) : x(aX
), y(aY
) {}
37 MOZ_ALWAYS_INLINE T
X() const { return x
; }
38 MOZ_ALWAYS_INLINE T
Y() const { return y
; }
40 void MoveTo(T aX
, T aY
) {
44 void MoveBy(T aDx
, T aDy
) {
49 // Note that '=' isn't defined so we'll get the
50 // compiler generated default assignment operator
52 bool operator==(const Sub
& aPoint
) const {
53 return x
== aPoint
.x
&& y
== aPoint
.y
;
55 bool operator!=(const Sub
& aPoint
) const {
56 return x
!= aPoint
.x
|| y
!= aPoint
.y
;
59 Sub
operator+(const Sub
& aPoint
) const {
60 return Sub(x
+ aPoint
.x
, y
+ aPoint
.y
);
62 Sub
operator-(const Sub
& aPoint
) const {
63 return Sub(x
- aPoint
.x
, y
- aPoint
.y
);
65 Sub
& operator+=(const Sub
& aPoint
) {
68 return *static_cast<Sub
*>(this);
70 Sub
& operator-=(const Sub
& aPoint
) {
73 return *static_cast<Sub
*>(this);
76 Sub
operator*(T aScale
) const { return Sub(x
* aScale
, y
* aScale
); }
77 Sub
operator/(T aScale
) const { return Sub(x
/ aScale
, y
/ aScale
); }
79 Sub
operator-() const { return Sub(-x
, -y
); }
81 T
DotProduct(const Sub
& aPoint
) const { return x
* aPoint
.x
+ y
* aPoint
.y
; }
83 Coord
Length() const { return hypot(x
, y
); }
85 T
LengthSquare() const { return x
* x
+ y
* y
; }
87 // Round() is *not* rounding to nearest integer if the values are negative.
88 // They are always rounding as floor(n + 0.5).
89 // See https://bugzilla.mozilla.org/show_bug.cgi?id=410748#c14
91 x
= Coord(std::floor(T(x
) + T(0.5f
)));
92 y
= Coord(std::floor(T(y
) + T(0.5f
)));
93 return *static_cast<Sub
*>(this);
96 // "Finite" means not inf and not NaN
97 bool IsFinite() const {
99 std::conditional_t
<std::is_same_v
<T
, float>, float, double>;
100 return (mozilla::IsFinite(FloatType(x
)) && mozilla::IsFinite(FloatType(y
)));
104 void Clamp(T aMaxAbsValue
) {
105 x
= std::max(std::min(x
, aMaxAbsValue
), -aMaxAbsValue
);
106 y
= std::max(std::min(y
, aMaxAbsValue
), -aMaxAbsValue
);
109 friend std::ostream
& operator<<(std::ostream
& stream
,
110 const BasePoint
<T
, Sub
, Coord
>& aPoint
) {
111 return stream
<< '(' << aPoint
.x
<< ',' << aPoint
.y
<< ')';
116 } // namespace mozilla
118 #endif /* MOZILLA_GFX_BASEPOINT_H_ */