Bug 1634272 - Don't use DocumentChannel for about:newtab r=mattwoodrow
[gecko.git] / gfx / 2d / Point.h
blobfbe77d023bbe85b018fea4bd12ac7f2264818596
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_POINT_H_
8 #define MOZILLA_GFX_POINT_H_
10 #include "mozilla/Attributes.h"
11 #include "Types.h"
12 #include "Coord.h"
13 #include "BaseCoord.h"
14 #include "BasePoint.h"
15 #include "BasePoint3D.h"
16 #include "BasePoint4D.h"
17 #include "BaseSize.h"
18 #include "mozilla/Maybe.h"
20 #include <cmath>
21 #include <type_traits>
23 namespace mozilla {
25 template <typename>
26 struct IsPixel;
28 namespace gfx {
30 // This should only be used by the typedefs below.
31 struct UnknownUnits {};
33 } // namespace gfx
35 template <>
36 struct IsPixel<gfx::UnknownUnits> : std::true_type {};
38 namespace gfx {
40 /// Use this for parameters of functions to allow implicit conversions to
41 /// integer types but not floating point types.
42 /// We use this wrapper to prevent IntSize and IntPoint's constructors to
43 /// take foating point values as parameters, and not require their constructors
44 /// to have implementations for each permutation of integer types.
45 template <typename T>
46 struct IntParam {
47 constexpr MOZ_IMPLICIT IntParam(char val) : value(val) {}
48 constexpr MOZ_IMPLICIT IntParam(unsigned char val) : value(val) {}
49 constexpr MOZ_IMPLICIT IntParam(short val) : value(val) {}
50 constexpr MOZ_IMPLICIT IntParam(unsigned short val) : value(val) {}
51 constexpr MOZ_IMPLICIT IntParam(int val) : value(val) {}
52 constexpr MOZ_IMPLICIT IntParam(unsigned int val) : value(val) {}
53 constexpr MOZ_IMPLICIT IntParam(long val) : value(val) {}
54 constexpr MOZ_IMPLICIT IntParam(unsigned long val) : value(val) {}
55 constexpr MOZ_IMPLICIT IntParam(long long val) : value(val) {}
56 constexpr MOZ_IMPLICIT IntParam(unsigned long long val) : value(val) {}
57 template <typename Unit>
58 constexpr MOZ_IMPLICIT IntParam(IntCoordTyped<Unit> val) : value(val) {}
60 // Disable the evil ones!
61 MOZ_IMPLICIT IntParam(float val) = delete;
62 MOZ_IMPLICIT IntParam(double val) = delete;
64 T value;
67 template <class units, class>
68 struct PointTyped;
69 template <class units, class>
70 struct SizeTyped;
72 template <class units>
73 struct IntPointTyped
74 : public BasePoint<int32_t, IntPointTyped<units>, IntCoordTyped<units> >,
75 public units {
76 static_assert(IsPixel<units>::value,
77 "'units' must be a coordinate system tag");
79 typedef IntParam<int32_t> ToInt;
80 typedef IntCoordTyped<units> Coord;
81 typedef BasePoint<int32_t, IntPointTyped<units>, IntCoordTyped<units> > Super;
83 constexpr IntPointTyped() : Super() {}
84 constexpr IntPointTyped(ToInt aX, ToInt aY)
85 : Super(Coord(aX.value), Coord(aY.value)) {}
87 static IntPointTyped<units> Round(float aX, float aY) {
88 return IntPointTyped(int32_t(floorf(aX + 0.5)), int32_t(floorf(aY + 0.5)));
91 static IntPointTyped<units> Ceil(float aX, float aY) {
92 return IntPointTyped(int32_t(ceil(aX)), int32_t(ceil(aY)));
95 static IntPointTyped<units> Floor(float aX, float aY) {
96 return IntPointTyped(int32_t(floorf(aX)), int32_t(floorf(aY)));
99 static IntPointTyped<units> Truncate(float aX, float aY) {
100 return IntPointTyped(int32_t(aX), int32_t(aY));
103 static IntPointTyped<units> Round(const PointTyped<units, float>& aPoint);
104 static IntPointTyped<units> Ceil(const PointTyped<units, float>& aPoint);
105 static IntPointTyped<units> Floor(const PointTyped<units, float>& aPoint);
106 static IntPointTyped<units> Truncate(const PointTyped<units, float>& aPoint);
108 // XXX When all of the code is ported, the following functions to convert to
109 // and from unknown types should be removed.
111 static IntPointTyped<units> FromUnknownPoint(
112 const IntPointTyped<UnknownUnits>& aPoint) {
113 return IntPointTyped<units>(aPoint.x, aPoint.y);
116 IntPointTyped<UnknownUnits> ToUnknownPoint() const {
117 return IntPointTyped<UnknownUnits>(this->x, this->y);
120 typedef IntPointTyped<UnknownUnits> IntPoint;
122 template <class units, class F = Float>
123 struct PointTyped
124 : public BasePoint<F, PointTyped<units, F>, CoordTyped<units, F> >,
125 public units {
126 static_assert(IsPixel<units>::value,
127 "'units' must be a coordinate system tag");
129 typedef CoordTyped<units, F> Coord;
130 typedef BasePoint<F, PointTyped<units, F>, CoordTyped<units, F> > Super;
132 constexpr PointTyped() : Super() {}
133 constexpr PointTyped(F aX, F aY) : Super(Coord(aX), Coord(aY)) {}
134 // The mixed-type constructors (Float, Coord) and (Coord, Float) are needed to
135 // avoid ambiguities because Coord is implicitly convertible to Float.
136 constexpr PointTyped(F aX, Coord aY) : Super(Coord(aX), aY) {}
137 constexpr PointTyped(Coord aX, F aY) : Super(aX, Coord(aY)) {}
138 constexpr PointTyped(Coord aX, Coord aY) : Super(aX.value, aY.value) {}
139 constexpr MOZ_IMPLICIT PointTyped(const IntPointTyped<units>& point)
140 : Super(F(point.x), F(point.y)) {}
142 bool WithinEpsilonOf(const PointTyped<units, F>& aPoint, F aEpsilon) const {
143 return fabs(aPoint.x - this->x) < aEpsilon &&
144 fabs(aPoint.y - this->y) < aEpsilon;
147 // XXX When all of the code is ported, the following functions to convert to
148 // and from unknown types should be removed.
150 static PointTyped<units, F> FromUnknownPoint(
151 const PointTyped<UnknownUnits, F>& aPoint) {
152 return PointTyped<units, F>(aPoint.x, aPoint.y);
155 PointTyped<UnknownUnits, F> ToUnknownPoint() const {
156 return PointTyped<UnknownUnits, F>(this->x, this->y);
159 typedef PointTyped<UnknownUnits> Point;
160 typedef PointTyped<UnknownUnits, double> PointDouble;
162 template <class units>
163 IntPointTyped<units> RoundedToInt(const PointTyped<units>& aPoint) {
164 return IntPointTyped<units>::Round(aPoint.x, aPoint.y);
167 template <class units>
168 IntPointTyped<units> TruncatedToInt(const PointTyped<units>& aPoint) {
169 return IntPointTyped<units>::Truncate(aPoint.x, aPoint.y);
172 template <class units, class F = Float>
173 struct Point3DTyped : public BasePoint3D<F, Point3DTyped<units, F> > {
174 static_assert(IsPixel<units>::value,
175 "'units' must be a coordinate system tag");
177 typedef BasePoint3D<F, Point3DTyped<units, F> > Super;
179 Point3DTyped() : Super() {}
180 Point3DTyped(F aX, F aY, F aZ) : Super(aX, aY, aZ) {}
182 // XXX When all of the code is ported, the following functions to convert to
183 // and from unknown types should be removed.
185 static Point3DTyped<units, F> FromUnknownPoint(
186 const Point3DTyped<UnknownUnits, F>& aPoint) {
187 return Point3DTyped<units, F>(aPoint.x, aPoint.y, aPoint.z);
190 Point3DTyped<UnknownUnits, F> ToUnknownPoint() const {
191 return Point3DTyped<UnknownUnits, F>(this->x, this->y, this->z);
194 typedef Point3DTyped<UnknownUnits> Point3D;
195 typedef Point3DTyped<UnknownUnits, double> PointDouble3D;
197 template <typename units>
198 IntPointTyped<units> IntPointTyped<units>::Round(
199 const PointTyped<units, float>& aPoint) {
200 return IntPointTyped::Round(aPoint.x, aPoint.y);
203 template <typename units>
204 IntPointTyped<units> IntPointTyped<units>::Ceil(
205 const PointTyped<units, float>& aPoint) {
206 return IntPointTyped::Ceil(aPoint.x, aPoint.y);
209 template <typename units>
210 IntPointTyped<units> IntPointTyped<units>::Floor(
211 const PointTyped<units, float>& aPoint) {
212 return IntPointTyped::Floor(aPoint.x, aPoint.y);
215 template <typename units>
216 IntPointTyped<units> IntPointTyped<units>::Truncate(
217 const PointTyped<units, float>& aPoint) {
218 return IntPointTyped::Truncate(aPoint.x, aPoint.y);
221 template <class units, class F = Float>
222 struct Point4DTyped : public BasePoint4D<F, Point4DTyped<units, F> > {
223 static_assert(IsPixel<units>::value,
224 "'units' must be a coordinate system tag");
226 typedef BasePoint4D<F, Point4DTyped<units, F> > Super;
228 Point4DTyped() : Super() {}
229 Point4DTyped(F aX, F aY, F aZ, F aW) : Super(aX, aY, aZ, aW) {}
231 explicit Point4DTyped(const Point3DTyped<units, F>& aPoint)
232 : Super(aPoint.x, aPoint.y, aPoint.z, 1) {}
234 // XXX When all of the code is ported, the following functions to convert to
235 // and from unknown types should be removed.
237 static Point4DTyped<units, F> FromUnknownPoint(
238 const Point4DTyped<UnknownUnits, F>& aPoint) {
239 return Point4DTyped<units, F>(aPoint.x, aPoint.y, aPoint.z, aPoint.w);
242 Point4DTyped<UnknownUnits, F> ToUnknownPoint() const {
243 return Point4DTyped<UnknownUnits, F>(this->x, this->y, this->z, this->w);
246 PointTyped<units, F> As2DPoint() const {
247 return PointTyped<units, F>(this->x / this->w, this->y / this->w);
250 Point3DTyped<units, F> As3DPoint() const {
251 return Point3DTyped<units, F>(this->x / this->w, this->y / this->w,
252 this->z / this->w);
255 typedef Point4DTyped<UnknownUnits> Point4D;
256 typedef Point4DTyped<UnknownUnits, double> PointDouble4D;
258 template <class units>
259 struct IntSizeTyped : public BaseSize<int32_t, IntSizeTyped<units> >,
260 public units {
261 static_assert(IsPixel<units>::value,
262 "'units' must be a coordinate system tag");
264 typedef IntParam<int32_t> ToInt;
265 typedef BaseSize<int32_t, IntSizeTyped<units> > Super;
267 constexpr IntSizeTyped() : Super() {}
268 constexpr IntSizeTyped(ToInt aWidth, ToInt aHeight)
269 : Super(aWidth.value, aHeight.value) {}
271 static IntSizeTyped<units> Round(float aWidth, float aHeight) {
272 return IntSizeTyped(int32_t(floorf(aWidth + 0.5)),
273 int32_t(floorf(aHeight + 0.5)));
276 static IntSizeTyped<units> Truncate(float aWidth, float aHeight) {
277 return IntSizeTyped(int32_t(aWidth), int32_t(aHeight));
280 static IntSizeTyped<units> Ceil(float aWidth, float aHeight) {
281 return IntSizeTyped(int32_t(ceil(aWidth)), int32_t(ceil(aHeight)));
284 static IntSizeTyped<units> Floor(float aWidth, float aHeight) {
285 return IntSizeTyped(int32_t(floorf(aWidth)), int32_t(floorf(aHeight)));
288 static IntSizeTyped<units> Round(const SizeTyped<units, float>& aSize);
289 static IntSizeTyped<units> Ceil(const SizeTyped<units, float>& aSize);
290 static IntSizeTyped<units> Floor(const SizeTyped<units, float>& aSize);
291 static IntSizeTyped<units> Truncate(const SizeTyped<units, float>& aSize);
293 // XXX When all of the code is ported, the following functions to convert to
294 // and from unknown types should be removed.
296 static IntSizeTyped<units> FromUnknownSize(
297 const IntSizeTyped<UnknownUnits>& aSize) {
298 return IntSizeTyped<units>(aSize.width, aSize.height);
301 IntSizeTyped<UnknownUnits> ToUnknownSize() const {
302 return IntSizeTyped<UnknownUnits>(this->width, this->height);
305 typedef IntSizeTyped<UnknownUnits> IntSize;
306 typedef Maybe<IntSize> MaybeIntSize;
308 template <class units, class F = Float>
309 struct SizeTyped : public BaseSize<F, SizeTyped<units, F> >, public units {
310 static_assert(IsPixel<units>::value,
311 "'units' must be a coordinate system tag");
313 typedef BaseSize<F, SizeTyped<units, F> > Super;
315 constexpr SizeTyped() : Super() {}
316 constexpr SizeTyped(F aWidth, F aHeight) : Super(aWidth, aHeight) {}
317 explicit SizeTyped(const IntSizeTyped<units>& size)
318 : Super(F(size.width), F(size.height)) {}
320 // XXX When all of the code is ported, the following functions to convert to
321 // and from unknown types should be removed.
323 static SizeTyped<units, F> FromUnknownSize(
324 const SizeTyped<UnknownUnits, F>& aSize) {
325 return SizeTyped<units, F>(aSize.width, aSize.height);
328 SizeTyped<UnknownUnits, F> ToUnknownSize() const {
329 return SizeTyped<UnknownUnits, F>(this->width, this->height);
332 typedef SizeTyped<UnknownUnits> Size;
333 typedef SizeTyped<UnknownUnits, double> SizeDouble;
335 template <class units>
336 IntSizeTyped<units> RoundedToInt(const SizeTyped<units>& aSize) {
337 return IntSizeTyped<units>(int32_t(floorf(aSize.width + 0.5f)),
338 int32_t(floorf(aSize.height + 0.5f)));
341 template <typename units>
342 IntSizeTyped<units> IntSizeTyped<units>::Round(
343 const SizeTyped<units, float>& aSize) {
344 return IntSizeTyped::Round(aSize.width, aSize.height);
347 template <typename units>
348 IntSizeTyped<units> IntSizeTyped<units>::Ceil(
349 const SizeTyped<units, float>& aSize) {
350 return IntSizeTyped::Ceil(aSize.width, aSize.height);
353 template <typename units>
354 IntSizeTyped<units> IntSizeTyped<units>::Floor(
355 const SizeTyped<units, float>& aSize) {
356 return IntSizeTyped::Floor(aSize.width, aSize.height);
359 template <typename units>
360 IntSizeTyped<units> IntSizeTyped<units>::Truncate(
361 const SizeTyped<units, float>& aSize) {
362 return IntSizeTyped::Truncate(aSize.width, aSize.height);
365 } // namespace gfx
366 } // namespace mozilla
368 #endif /* MOZILLA_GFX_POINT_H_ */