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_PAINTING_TRANSFORMCLIPNODE_H
8 #define MOZILLA_PAINTING_TRANSFORMCLIPNODE_H
10 #include "mozilla/gfx/MatrixFwd.h"
11 #include "mozilla/gfx/Rect.h"
12 #include "mozilla/Maybe.h"
13 #include "nsISupports.h"
14 #include "nsRegionFwd.h"
19 * TransformClipNode stores a transformation matrix and a post-transform
21 * They can be used to transform and clip a display item inside a flattened
22 * nsDisplayTransform to the coordinate space of that nsDisplayTransform.
24 class TransformClipNode
{
25 NS_INLINE_DECL_REFCOUNTING(TransformClipNode
);
28 TransformClipNode(const RefPtr
<TransformClipNode
>& aParent
,
29 const gfx::Matrix4x4Flagged
& aTransform
,
30 const Maybe
<gfx::IntRect
>& aClip
)
31 : mParent(aParent
), mTransform(aTransform
), mClip(aClip
) {
32 MOZ_COUNT_CTOR(TransformClipNode
);
36 * Returns the parent node, or nullptr if this is the root node.
38 const RefPtr
<TransformClipNode
>& Parent() const { return mParent
; }
41 * Transforms and clips |aRect| up to the root transform node.
42 * |aRect| is expected to be in app units.
44 nsRect
TransformRect(const nsRect
& aRect
, const int32_t aA2D
) const {
45 if (aRect
.IsEmpty()) {
49 gfx::Rect
result(NSAppUnitsToFloatPixels(aRect
.x
, aA2D
),
50 NSAppUnitsToFloatPixels(aRect
.y
, aA2D
),
51 NSAppUnitsToFloatPixels(aRect
.width
, aA2D
),
52 NSAppUnitsToFloatPixels(aRect
.height
, aA2D
));
53 TransformRect(result
);
54 return nsRect(NSFloatPixelsToAppUnits(result
.x
, aA2D
),
55 NSFloatPixelsToAppUnits(result
.y
, aA2D
),
56 NSFloatPixelsToAppUnits(result
.width
, aA2D
),
57 NSFloatPixelsToAppUnits(result
.height
, aA2D
));
61 * Transforms and clips |aRect| up to the root transform node.
62 * |aRect| is expected to be in integer pixels.
64 gfx::IntRect
TransformRect(const gfx::IntRect
& aRect
) const {
65 if (aRect
.IsEmpty()) {
69 gfx::Rect
result(IntRectToRect(aRect
));
70 TransformRect(result
);
71 return RoundedToInt(result
);
75 * Transforms and clips |aRegion| up to the root transform node.
76 * |aRegion| is expected be in integer pixels.
78 nsIntRegion
TransformRegion(const nsIntRegion
& aRegion
) {
79 if (aRegion
.IsEmpty()) {
83 nsIntRegion result
= aRegion
;
85 const TransformClipNode
* node
= this;
87 const gfx::Matrix4x4Flagged
& transform
= node
->Transform();
88 result
= result
.Transform(transform
.GetMatrix());
91 const gfx::IntRect clipRect
= *node
->Clip();
92 result
.AndWith(clipRect
);
95 node
= node
->Parent();
103 * Returns the post-transform clip, if there is one.
105 const Maybe
<gfx::IntRect
>& Clip() const { return mClip
; }
108 * Returns the matrix that transforms the item bounds to the coordinate space
109 * of the flattened nsDisplayTransform.
111 const gfx::Matrix4x4Flagged
& Transform() const { return mTransform
; }
113 void TransformRect(gfx::Rect
& aRect
) const {
114 const TransformClipNode
* node
= this;
116 const gfx::Matrix4x4Flagged
& transform
= node
->Transform();
117 gfx::Rect maxBounds
= gfx::Rect::MaxIntRect();
120 maxBounds
= IntRectToRect(*node
->Clip());
123 aRect
= transform
.TransformAndClipBounds(aRect
, maxBounds
);
124 node
= node
->Parent();
129 MOZ_COUNTED_DTOR(TransformClipNode
)
131 const RefPtr
<TransformClipNode
> mParent
;
132 const gfx::Matrix4x4Flagged mTransform
;
133 const Maybe
<gfx::IntRect
> mClip
;
136 } // namespace mozilla
138 #endif /* MOZILLA_PAINTING_TRANSFORMCLIPNODE_H */