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 MOZ_UNIT_TRANSFORMS_H_
8 #define MOZ_UNIT_TRANSFORMS_H_
11 #include "mozilla/gfx/Matrix.h"
15 // Convenience functions for converting an entity from one strongly-typed
16 // coordinate system to another without changing the values it stores (this
17 // can be thought of as a cast).
18 // To use these functions, you must provide a justification for each use!
19 // Feel free to add more justifications to PixelCastJustification, along with
20 // a comment that explains under what circumstances it is appropriate to use.
22 MOZ_BEGIN_ENUM_CLASS(PixelCastJustification
, uint8_t)
23 // For the root layer, Screen Pixel = Parent Layer Pixel.
24 ScreenIsParentLayerForRoot
,
25 // For the root composition size we want to view it as layer pixels in any layer
26 ParentLayerToLayerForRootComposition
,
27 // The Layer coordinate space for one layer is the ParentLayer coordinate
28 // space for its children
30 // The transform that is usually used to convert between two coordinate
31 // systems is not available (for example, because the object that stores it
32 // is being destroyed), so fall back to the identity.
34 MOZ_END_ENUM_CLASS(PixelCastJustification
)
36 template <class TargetUnits
, class SourceUnits
>
37 gfx::SizeTyped
<TargetUnits
> ViewAs(const gfx::SizeTyped
<SourceUnits
>& aSize
, PixelCastJustification
) {
38 return gfx::SizeTyped
<TargetUnits
>(aSize
.width
, aSize
.height
);
40 template <class TargetUnits
, class SourceUnits
>
41 gfx::IntSizeTyped
<TargetUnits
> ViewAs(const gfx::IntSizeTyped
<SourceUnits
>& aSize
, PixelCastJustification
) {
42 return gfx::IntSizeTyped
<TargetUnits
>(aSize
.width
, aSize
.height
);
44 template <class TargetUnits
, class SourceUnits
>
45 gfx::PointTyped
<TargetUnits
> ViewAs(const gfx::PointTyped
<SourceUnits
>& aPoint
, PixelCastJustification
) {
46 return gfx::PointTyped
<TargetUnits
>(aPoint
.x
, aPoint
.y
);
48 template <class NewTargetUnits
, class OldTargetUnits
, class SourceUnits
>
49 gfx::ScaleFactor
<SourceUnits
, NewTargetUnits
> ViewTargetAs(
50 const gfx::ScaleFactor
<SourceUnits
, OldTargetUnits
>& aScaleFactor
,
51 PixelCastJustification
) {
52 return gfx::ScaleFactor
<SourceUnits
, NewTargetUnits
>(aScaleFactor
.scale
);
55 // Convenience functions for casting untyped entities to typed entities.
56 // Using these functions does not require a justification, but once we convert
57 // all code to use strongly typed units they should not be needed any longer.
58 template <class TargetUnits
>
59 gfx::PointTyped
<TargetUnits
> ViewAs(const gfxPoint
& aPoint
) {
60 return gfx::PointTyped
<TargetUnits
>(aPoint
.x
, aPoint
.y
);
62 template <class TargetUnits
>
63 gfx::PointTyped
<TargetUnits
> ViewAs(const gfx::Point
& aPoint
) {
64 return gfx::PointTyped
<TargetUnits
>(aPoint
.x
, aPoint
.y
);
66 template <class TargetUnits
>
67 gfx::RectTyped
<TargetUnits
> ViewAs(const gfx::Rect
& aRect
) {
68 return gfx::RectTyped
<TargetUnits
>(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
);
70 template <class TargetUnits
>
71 gfx::IntSizeTyped
<TargetUnits
> ViewAs(const nsIntSize
& aSize
) {
72 return gfx::IntSizeTyped
<TargetUnits
>(aSize
.width
, aSize
.height
);
74 template <class TargetUnits
>
75 gfx::IntPointTyped
<TargetUnits
> ViewAs(const nsIntPoint
& aPoint
) {
76 return gfx::IntPointTyped
<TargetUnits
>(aPoint
.x
, aPoint
.y
);
78 template <class TargetUnits
>
79 gfx::IntRectTyped
<TargetUnits
> ViewAs(const nsIntRect
& aRect
) {
80 return gfx::IntRectTyped
<TargetUnits
>(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
);
83 // Convenience functions for transforming an entity from one strongly-typed
84 // coordinate system to another using the provided transformation matrix.
85 template <typename TargetUnits
, typename SourceUnits
>
86 static gfx::PointTyped
<TargetUnits
> TransformTo(const gfx::Matrix4x4
& aTransform
,
87 const gfx::PointTyped
<SourceUnits
>& aPoint
)
89 return ViewAs
<TargetUnits
>(aTransform
* aPoint
.ToUnknownPoint());
91 template <typename TargetUnits
, typename SourceUnits
>
92 static gfx::IntPointTyped
<TargetUnits
> TransformTo(const gfx::Matrix4x4
& aTransform
,
93 const gfx::IntPointTyped
<SourceUnits
>& aPoint
)
95 return RoundedToInt(TransformTo
<TargetUnits
>(aTransform
, gfx::PointTyped
<SourceUnits
>(aPoint
)));
97 template <typename TargetUnits
, typename SourceUnits
>
98 static gfx::RectTyped
<TargetUnits
> TransformTo(const gfx::Matrix4x4
& aTransform
,
99 const gfx::RectTyped
<SourceUnits
>& aRect
)
101 return ViewAs
<TargetUnits
>(aTransform
.TransformBounds(aRect
.ToUnknownRect()));
103 template <typename TargetUnits
, typename SourceUnits
>
104 static gfx::IntRectTyped
<TargetUnits
> TransformTo(const gfx::Matrix4x4
& aTransform
,
105 const gfx::IntRectTyped
<SourceUnits
>& aRect
)
107 gfx::Rect
rect(aRect
.ToUnknownRect());
108 return RoundedToInt(ViewAs
<TargetUnits
>(aTransform
.TransformBounds(rect
)));
111 // Transform |aVector|, which is anchored at |aAnchor|, by the given transform
112 // matrix, yielding a point in |TargetUnits|.
113 // The anchor is necessary because with 3D tranforms, the location of the
114 // vector can affect the result of the transform.
115 template <typename TargetUnits
, typename SourceUnits
>
116 static gfx::PointTyped
<TargetUnits
> TransformVector(const gfx::Matrix4x4
& aTransform
,
117 const gfx::PointTyped
<SourceUnits
>& aVector
,
118 const gfx::PointTyped
<SourceUnits
>& aAnchor
) {
119 gfx::PointTyped
<TargetUnits
> transformedStart
= TransformTo
<TargetUnits
>(aTransform
, aAnchor
);
120 gfx::PointTyped
<TargetUnits
> transformedEnd
= TransformTo
<TargetUnits
>(aTransform
, aAnchor
+ aVector
);
121 return transformedEnd
- transformedStart
;