no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / gfx / 2d / Point.h
blob9000cb4e9a616c1a539bf979da32d0cab56d59ab
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"
19 #include "mozilla/gfx/NumericTools.h"
21 #include <cmath>
22 #include <type_traits>
24 namespace mozilla {
26 template <typename>
27 struct IsPixel;
29 template <>
30 struct IsPixel<gfx::UnknownUnits> : std::true_type {};
32 namespace gfx {
34 /// Use this for parameters of functions to allow implicit conversions to
35 /// integer types but not floating point types.
36 /// We use this wrapper to prevent IntSize and IntPoint's constructors to
37 /// take foating point values as parameters, and not require their constructors
38 /// to have implementations for each permutation of integer types.
39 template <typename T>
40 struct IntParam {
41 constexpr MOZ_IMPLICIT IntParam(char val) : value(val) {}
42 constexpr MOZ_IMPLICIT IntParam(unsigned char val) : value(val) {}
43 constexpr MOZ_IMPLICIT IntParam(short val) : value(val) {}
44 constexpr MOZ_IMPLICIT IntParam(unsigned short val) : value(val) {}
45 constexpr MOZ_IMPLICIT IntParam(int val) : value(val) {}
46 constexpr MOZ_IMPLICIT IntParam(unsigned int val) : value(val) {}
47 constexpr MOZ_IMPLICIT IntParam(long val) : value(val) {}
48 constexpr MOZ_IMPLICIT IntParam(unsigned long val) : value(val) {}
49 constexpr MOZ_IMPLICIT IntParam(long long val) : value(val) {}
50 constexpr MOZ_IMPLICIT IntParam(unsigned long long val) : value(val) {}
51 template <typename Unit>
52 constexpr MOZ_IMPLICIT IntParam(IntCoordTyped<Unit> val) : value(val) {}
54 // Disable the evil ones!
55 MOZ_IMPLICIT IntParam(float val) = delete;
56 MOZ_IMPLICIT IntParam(double val) = delete;
58 T value;
61 template <class Units, class>
62 struct PointTyped;
63 template <class Units, class>
64 struct SizeTyped;
66 template <class Units>
67 struct MOZ_EMPTY_BASES IntPointTyped
68 : public BasePoint<int32_t, IntPointTyped<Units>, IntCoordTyped<Units> >,
69 public Units {
70 static_assert(IsPixel<Units>::value,
71 "'Units' must be a coordinate system tag");
73 typedef IntParam<int32_t> ToInt;
74 typedef IntCoordTyped<Units> Coord;
75 typedef BasePoint<int32_t, IntPointTyped<Units>, IntCoordTyped<Units> > Super;
77 constexpr IntPointTyped() : Super() {
78 static_assert(sizeof(IntPointTyped) == sizeof(int32_t) * 2,
79 "Would be unfortunate otherwise!");
81 constexpr IntPointTyped(ToInt aX, ToInt aY)
82 : Super(Coord(aX.value), Coord(aY.value)) {}
84 static IntPointTyped Round(float aX, float aY) {
85 return IntPointTyped(int32_t(floorf(aX + 0.5f)),
86 int32_t(floorf(aY + 0.5f)));
89 static IntPointTyped Ceil(float aX, float aY) {
90 return IntPointTyped(int32_t(ceilf(aX)), int32_t(ceilf(aY)));
93 static IntPointTyped Floor(float aX, float aY) {
94 return IntPointTyped(int32_t(floorf(aX)), int32_t(floorf(aY)));
97 static IntPointTyped Truncate(float aX, float aY) {
98 return IntPointTyped(int32_t(aX), int32_t(aY));
101 static IntPointTyped Round(const PointTyped<Units, float>& aPoint);
102 static IntPointTyped Ceil(const PointTyped<Units, float>& aPoint);
103 static IntPointTyped Floor(const PointTyped<Units, float>& aPoint);
104 static IntPointTyped Truncate(const PointTyped<Units, float>& aPoint);
106 // XXX When all of the code is ported, the following functions to convert to
107 // and from unknown types should be removed.
109 static IntPointTyped FromUnknownPoint(
110 const IntPointTyped<UnknownUnits>& aPoint) {
111 return IntPointTyped<Units>(aPoint.x, aPoint.y);
114 IntPointTyped<UnknownUnits> ToUnknownPoint() const {
115 return IntPointTyped<UnknownUnits>(this->x, this->y);
118 IntPointTyped RoundedToMultiple(int32_t aMultiplier) const {
119 return {RoundToMultiple(this->x, aMultiplier),
120 RoundToMultiple(this->y, aMultiplier)};
123 typedef IntPointTyped<UnknownUnits> IntPoint;
125 template <class Units, class F = Float>
126 struct MOZ_EMPTY_BASES PointTyped
127 : public BasePoint<F, PointTyped<Units, F>, CoordTyped<Units, F> >,
128 public Units {
129 static_assert(IsPixel<Units>::value,
130 "'Units' must be a coordinate system tag");
132 typedef CoordTyped<Units, F> Coord;
133 typedef BasePoint<F, PointTyped<Units, F>, CoordTyped<Units, F> > Super;
135 constexpr PointTyped() : Super() {
136 static_assert(sizeof(PointTyped) == sizeof(F) * 2,
137 "Would be unfortunate otherwise!");
139 constexpr PointTyped(F aX, F aY) : Super(Coord(aX), Coord(aY)) {}
140 // The mixed-type constructors (Float, Coord) and (Coord, Float) are needed to
141 // avoid ambiguities because Coord is implicitly convertible to Float.
142 constexpr PointTyped(F aX, Coord aY) : Super(Coord(aX), aY) {}
143 constexpr PointTyped(Coord aX, F aY) : Super(aX, Coord(aY)) {}
144 constexpr PointTyped(Coord aX, Coord aY) : Super(aX.value, aY.value) {}
145 constexpr MOZ_IMPLICIT PointTyped(const IntPointTyped<Units>& point)
146 : Super(F(point.x), F(point.y)) {}
148 bool WithinEpsilonOf(const PointTyped<Units, F>& aPoint, F aEpsilon) const {
149 return fabs(aPoint.x - this->x) < aEpsilon &&
150 fabs(aPoint.y - this->y) < aEpsilon;
153 // XXX When all of the code is ported, the following functions to convert to
154 // and from unknown types should be removed.
156 static PointTyped<Units, F> FromUnknownPoint(
157 const PointTyped<UnknownUnits, F>& aPoint) {
158 return PointTyped<Units, F>(aPoint.x, aPoint.y);
161 PointTyped<UnknownUnits, F> ToUnknownPoint() const {
162 return PointTyped<UnknownUnits, F>(this->x, this->y);
165 typedef PointTyped<UnknownUnits> Point;
166 typedef PointTyped<UnknownUnits, double> PointDouble;
168 template <class Units>
169 IntPointTyped<Units> RoundedToInt(const PointTyped<Units>& aPoint) {
170 return IntPointTyped<Units>::Round(aPoint.x, aPoint.y);
173 template <class Units>
174 IntPointTyped<Units> TruncatedToInt(const PointTyped<Units>& aPoint) {
175 return IntPointTyped<Units>::Truncate(aPoint.x, aPoint.y);
178 template <class Units, class F = Float>
179 struct Point3DTyped : public BasePoint3D<F, Point3DTyped<Units, F> > {
180 static_assert(IsPixel<Units>::value,
181 "'Units' must be a coordinate system tag");
183 typedef BasePoint3D<F, Point3DTyped<Units, F> > Super;
185 Point3DTyped() : Super() {
186 static_assert(sizeof(Point3DTyped) == sizeof(F) * 3,
187 "Would be unfortunate otherwise!");
189 Point3DTyped(F aX, F aY, F aZ) : Super(aX, aY, aZ) {}
191 // XXX When all of the code is ported, the following functions to convert to
192 // and from unknown types should be removed.
194 static Point3DTyped<Units, F> FromUnknownPoint(
195 const Point3DTyped<UnknownUnits, F>& aPoint) {
196 return Point3DTyped<Units, F>(aPoint.x, aPoint.y, aPoint.z);
199 Point3DTyped<UnknownUnits, F> ToUnknownPoint() const {
200 return Point3DTyped<UnknownUnits, F>(this->x, this->y, this->z);
203 typedef Point3DTyped<UnknownUnits> Point3D;
204 typedef Point3DTyped<UnknownUnits, double> PointDouble3D;
206 template <typename Units>
207 IntPointTyped<Units> IntPointTyped<Units>::Round(
208 const PointTyped<Units, float>& aPoint) {
209 return IntPointTyped::Round(aPoint.x, aPoint.y);
212 template <typename Units>
213 IntPointTyped<Units> IntPointTyped<Units>::Ceil(
214 const PointTyped<Units, float>& aPoint) {
215 return IntPointTyped::Ceil(aPoint.x, aPoint.y);
218 template <typename Units>
219 IntPointTyped<Units> IntPointTyped<Units>::Floor(
220 const PointTyped<Units, float>& aPoint) {
221 return IntPointTyped::Floor(aPoint.x, aPoint.y);
224 template <typename Units>
225 IntPointTyped<Units> IntPointTyped<Units>::Truncate(
226 const PointTyped<Units, float>& aPoint) {
227 return IntPointTyped::Truncate(aPoint.x, aPoint.y);
230 template <class Units, class F = Float>
231 struct Point4DTyped : public BasePoint4D<F, Point4DTyped<Units, F> > {
232 static_assert(IsPixel<Units>::value,
233 "'Units' must be a coordinate system tag");
235 typedef BasePoint4D<F, Point4DTyped<Units, F> > Super;
237 Point4DTyped() : Super() {
238 static_assert(sizeof(Point4DTyped) == sizeof(F) * 4,
239 "Would be unfortunate otherwise!");
241 Point4DTyped(F aX, F aY, F aZ, F aW) : Super(aX, aY, aZ, aW) {}
243 explicit Point4DTyped(const Point3DTyped<Units, F>& aPoint)
244 : Super(aPoint.x, aPoint.y, aPoint.z, 1) {}
246 // XXX When all of the code is ported, the following functions to convert to
247 // and from unknown types should be removed.
249 static Point4DTyped<Units, F> FromUnknownPoint(
250 const Point4DTyped<UnknownUnits, F>& aPoint) {
251 return Point4DTyped<Units, F>(aPoint.x, aPoint.y, aPoint.z, aPoint.w);
254 Point4DTyped<UnknownUnits, F> ToUnknownPoint() const {
255 return Point4DTyped<UnknownUnits, F>(this->x, this->y, this->z, this->w);
258 PointTyped<Units, F> As2DPoint() const {
259 return PointTyped<Units, F>(this->x / this->w, this->y / this->w);
262 Point3DTyped<Units, F> As3DPoint() const {
263 return Point3DTyped<Units, F>(this->x / this->w, this->y / this->w,
264 this->z / this->w);
267 typedef Point4DTyped<UnknownUnits> Point4D;
268 typedef Point4DTyped<UnknownUnits, double> PointDouble4D;
270 template <class Units>
271 struct MOZ_EMPTY_BASES IntSizeTyped
272 : public BaseSize<int32_t, IntSizeTyped<Units>, IntCoordTyped<Units> >,
273 public Units {
274 static_assert(IsPixel<Units>::value,
275 "'Units' must be a coordinate system tag");
277 typedef IntCoordTyped<Units> Coord;
278 typedef BaseSize<int32_t, IntSizeTyped<Units>, Coord> Super;
280 constexpr IntSizeTyped() : Super() {
281 static_assert(sizeof(IntSizeTyped) == sizeof(int32_t) * 2,
282 "Would be unfortunate otherwise!");
284 constexpr IntSizeTyped(Coord aWidth, Coord aHeight)
285 : Super(aWidth.value, aHeight.value) {}
287 static IntSizeTyped Round(float aWidth, float aHeight) {
288 return IntSizeTyped(int32_t(floorf(aWidth + 0.5)),
289 int32_t(floorf(aHeight + 0.5)));
292 static IntSizeTyped Truncate(float aWidth, float aHeight) {
293 return IntSizeTyped(int32_t(aWidth), int32_t(aHeight));
296 static IntSizeTyped Ceil(float aWidth, float aHeight) {
297 return IntSizeTyped(int32_t(ceil(aWidth)), int32_t(ceil(aHeight)));
300 static IntSizeTyped Floor(float aWidth, float aHeight) {
301 return IntSizeTyped(int32_t(floorf(aWidth)), int32_t(floorf(aHeight)));
304 static IntSizeTyped Round(const SizeTyped<Units, float>& aSize);
305 static IntSizeTyped Ceil(const SizeTyped<Units, float>& aSize);
306 static IntSizeTyped Floor(const SizeTyped<Units, float>& aSize);
307 static IntSizeTyped Truncate(const SizeTyped<Units, float>& aSize);
309 IntSizeTyped TruncatedToMultiple(int32_t aMultiplier) const {
310 if (aMultiplier == 1) {
311 return *this;
313 return {RoundDownToMultiple(this->width, aMultiplier),
314 RoundDownToMultiple(this->height, aMultiplier)};
317 IntSizeTyped CeiledToMultiple(int32_t aMultiplier) const {
318 if (aMultiplier == 1) {
319 return *this;
321 return {RoundUpToMultiple(this->width, aMultiplier),
322 RoundUpToMultiple(this->height, aMultiplier)};
325 // XXX When all of the code is ported, the following functions to convert to
326 // and from unknown types should be removed.
328 static IntSizeTyped FromUnknownSize(const IntSizeTyped<UnknownUnits>& aSize) {
329 return IntSizeTyped(aSize.width, aSize.height);
332 IntSizeTyped<UnknownUnits> ToUnknownSize() const {
333 return IntSizeTyped<UnknownUnits>(this->width, this->height);
336 typedef IntSizeTyped<UnknownUnits> IntSize;
337 typedef Maybe<IntSize> MaybeIntSize;
339 template <class Units, class F = Float>
340 struct MOZ_EMPTY_BASES SizeTyped
341 : public BaseSize<F, SizeTyped<Units, F>, CoordTyped<Units, F> >,
342 public Units {
343 static_assert(IsPixel<Units>::value,
344 "'Units' must be a coordinate system tag");
346 typedef CoordTyped<Units, F> Coord;
347 typedef BaseSize<F, SizeTyped<Units, F>, Coord> Super;
349 constexpr SizeTyped() : Super() {
350 static_assert(sizeof(SizeTyped) == sizeof(F) * 2,
351 "Would be unfortunate otherwise!");
353 constexpr SizeTyped(Coord aWidth, Coord aHeight) : Super(aWidth, aHeight) {}
354 explicit SizeTyped(const IntSizeTyped<Units>& size)
355 : Super(F(size.width), F(size.height)) {}
357 // XXX When all of the code is ported, the following functions to convert to
358 // and from unknown types should be removed.
360 static SizeTyped<Units, F> FromUnknownSize(
361 const SizeTyped<UnknownUnits, F>& aSize) {
362 return SizeTyped<Units, F>(aSize.width, aSize.height);
365 SizeTyped<UnknownUnits, F> ToUnknownSize() const {
366 return SizeTyped<UnknownUnits, F>(this->width, this->height);
369 typedef SizeTyped<UnknownUnits> Size;
370 typedef SizeTyped<UnknownUnits, double> SizeDouble;
372 template <class Units>
373 IntSizeTyped<Units> RoundedToInt(const SizeTyped<Units>& aSize) {
374 return IntSizeTyped<Units>(int32_t(floorf(aSize.width + 0.5f)),
375 int32_t(floorf(aSize.height + 0.5f)));
378 template <typename Units>
379 IntSizeTyped<Units> IntSizeTyped<Units>::Round(
380 const SizeTyped<Units, float>& aSize) {
381 return IntSizeTyped::Round(aSize.width, aSize.height);
384 template <typename Units>
385 IntSizeTyped<Units> IntSizeTyped<Units>::Ceil(
386 const SizeTyped<Units, float>& aSize) {
387 return IntSizeTyped::Ceil(aSize.width, aSize.height);
390 template <typename Units>
391 IntSizeTyped<Units> IntSizeTyped<Units>::Floor(
392 const SizeTyped<Units, float>& aSize) {
393 return IntSizeTyped::Floor(aSize.width, aSize.height);
396 template <typename Units>
397 IntSizeTyped<Units> IntSizeTyped<Units>::Truncate(
398 const SizeTyped<Units, float>& aSize) {
399 return IntSizeTyped::Truncate(aSize.width, aSize.height);
402 } // namespace gfx
403 } // namespace mozilla
405 #endif /* MOZILLA_GFX_POINT_H_ */