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_MotionPathUtils_h
8 #define mozilla_MotionPathUtils_h
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/gfx/Point.h"
12 #include "mozilla/gfx/Rect.h"
13 #include "mozilla/Maybe.h"
14 #include "mozilla/ServoStyleConsts.h"
19 namespace nsStyleTransformMatrix
{
20 class TransformReferenceBox
;
30 struct ResolvedMotionPathData
{
31 gfx::Point mTranslate
;
33 // The delta value between transform-origin and offset-anchor.
37 // The collected information for offset-path. We preprocess the value of
38 // offset-path and use this data for resolving motion path.
39 struct OffsetPathData
{
40 enum class Type
: uint8_t {
47 RefPtr
<gfx::Path
> mGfxPath
;
48 // The current position of this transfromed box in the coordinate system of
49 // its containing block.
50 nsPoint mCurrentPosition
;
51 // True if it is a closed loop; false if it is a unclosed interval.
52 // https://drafts.fxtf.org/motion/#path-distance
57 const StyleRayFunction
* mRay
;
58 // The coord box of the containing block.
60 // The current position of this transfromed box in the coordinate system of
61 // its containing block.
62 nsPoint mCurrentPosition
;
63 // The reference length for computing ray(contain).
64 CSSCoord mContainReferenceLength
;
73 static OffsetPathData
None() { return OffsetPathData(); }
74 static OffsetPathData
Shape(already_AddRefed
<gfx::Path
>&& aGfxPath
,
75 nsPoint
&& aCurrentPosition
, bool aIsClosedPath
) {
76 return OffsetPathData(std::move(aGfxPath
), std::move(aCurrentPosition
),
79 static OffsetPathData
Ray(const StyleRayFunction
& aRay
, nsRect
&& aCoordBox
,
81 CSSCoord
&& aContainReferenceLength
) {
82 return OffsetPathData(&aRay
, std::move(aCoordBox
), std::move(aPosition
),
83 std::move(aContainReferenceLength
));
85 static OffsetPathData
Ray(const StyleRayFunction
& aRay
,
86 const nsRect
& aCoordBox
, const nsPoint
& aPosition
,
87 const CSSCoord
& aContainReferenceLength
) {
88 return OffsetPathData(&aRay
, aCoordBox
, aPosition
, aContainReferenceLength
);
91 bool IsNone() const { return mType
== Type::None
; }
92 bool IsShape() const { return mType
== Type::Shape
; }
93 bool IsRay() const { return mType
== Type::Ray
; }
95 const ShapeData
& AsShape() const {
96 MOZ_ASSERT(IsShape());
100 const RayData
& AsRay() const {
118 OffsetPathData(const OffsetPathData
& aOther
) : mType(aOther
.mType
) {
121 mShape
= aOther
.mShape
;
131 OffsetPathData(OffsetPathData
&& aOther
) : mType(aOther
.mType
) {
134 mShape
= std::move(aOther
.mShape
);
137 mRay
= std::move(aOther
.mRay
);
145 OffsetPathData() : mType(Type::None
) {}
146 OffsetPathData(already_AddRefed
<gfx::Path
>&& aPath
,
147 nsPoint
&& aCurrentPosition
, bool aIsClosed
)
148 : mType(Type::Shape
),
149 mShape
{std::move(aPath
), std::move(aCurrentPosition
), aIsClosed
} {}
150 OffsetPathData(const StyleRayFunction
* aRay
, nsRect
&& aCoordBox
,
151 nsPoint
&& aPosition
, CSSCoord
&& aContainReferenceLength
)
153 mRay
{aRay
, std::move(aCoordBox
), std::move(aPosition
),
154 std::move(aContainReferenceLength
)} {}
155 OffsetPathData(const StyleRayFunction
* aRay
, const nsRect
& aCoordBox
,
156 const nsPoint
& aPosition
,
157 const CSSCoord
& aContainReferenceLength
)
159 mRay
{aRay
, aCoordBox
, aPosition
, aContainReferenceLength
} {}
160 OffsetPathData
& operator=(const OffsetPathData
&) = delete;
161 OffsetPathData
& operator=(OffsetPathData
&&) = delete;
164 // MotionPathUtils is a namespace class containing utility functions related to
165 // processing motion path in the [motion-1].
166 // https://drafts.fxtf.org/motion-1/
167 class MotionPathUtils final
{
168 using TransformReferenceBox
= nsStyleTransformMatrix::TransformReferenceBox
;
172 * SVG frames (unlike other frames) have a reference box that can be (and
173 * typically is) offset from the TopLeft() of the frame.
175 * In motion path, we have to make sure the object is aligned with offset-path
176 * when using content area, so we should tweak the anchor point by a given
179 static CSSPoint
ComputeAnchorPointAdjustment(const nsIFrame
& aFrame
);
182 * In CSS context, this returns the the box being referenced from the element
183 * that establishes the containing block for this element.
184 * In SVG context, we always use view-box.
185 * https://drafts.fxtf.org/motion-1/#valdef-offset-path-coord-box
187 static const nsIFrame
* GetOffsetPathReferenceBox(const nsIFrame
* aFrame
,
188 nsRect
& aOutputRect
);
191 * Return the width or the height of the element’s border box, whichever is
192 * larger. This is for computing the ray() with "contain" keyword.
194 static CSSCoord
GetRayContainReferenceSize(nsIFrame
* aFrame
);
197 * Get the resolved radius for inset(0 round X), where X is the parameter of
199 * This returns an empty array if we cannot compute the radii; otherwise, it
200 * returns an array with 8 elements.
202 static nsTArray
<nscoord
> ComputeBorderRadii(
203 const StyleBorderRadius
& aBorderRadius
, const nsRect
& aCoordBox
);
206 * Generate the motion path transform result. This function may be called on
207 * the compositor thread.
209 static Maybe
<ResolvedMotionPathData
> ResolveMotionPath(
210 const OffsetPathData
& aPath
, const LengthPercentage
& aDistance
,
211 const StyleOffsetRotate
& aRotate
, const StylePositionOrAuto
& aAnchor
,
212 const StyleOffsetPosition
& aPosition
, const CSSPoint
& aTransformOrigin
,
213 TransformReferenceBox
&, const CSSPoint
& aAnchorPointAdjustment
);
216 * Generate the motion path transform result with |nsIFrame|. This is only
217 * called in the main thread.
219 static Maybe
<ResolvedMotionPathData
> ResolveMotionPath(
220 const nsIFrame
* aFrame
, TransformReferenceBox
&);
223 * Generate the motion path transfrom result with styles and
224 * layers::MotionPathData.
225 * This is only called by the compositor.
227 static Maybe
<ResolvedMotionPathData
> ResolveMotionPath(
228 const StyleOffsetPath
* aPath
, const StyleLengthPercentage
* aDistance
,
229 const StyleOffsetRotate
* aRotate
, const StylePositionOrAuto
* aAnchor
,
230 const StyleOffsetPosition
* aPosition
,
231 const Maybe
<layers::MotionPathData
>& aMotionPathData
,
232 TransformReferenceBox
&, gfx::Path
* aCachedMotionPath
);
235 * Build a gfx::Path from the svg path data. We should give it a path builder.
236 * If |aPathBuilder| is nullptr, we return null path.
237 * This can be used on the main thread or on the compositor thread.
239 static already_AddRefed
<gfx::Path
> BuildSVGPath(
240 const StyleSVGPathData
& aPath
, gfx::PathBuilder
* aPathBuilder
);
243 * Build a gfx::Path from the computed basic shape.
245 static already_AddRefed
<gfx::Path
> BuildPath(const StyleBasicShape
&,
246 const StyleOffsetPosition
&,
247 const nsRect
& aCoordBox
,
248 const nsPoint
& aCurrentPosition
,
252 * Get a path builder for motion path on the main thread.
254 static already_AddRefed
<gfx::PathBuilder
> GetPathBuilder();
257 * Get a path builder for compositor.
259 static already_AddRefed
<gfx::PathBuilder
> GetCompositorPathBuilder();
262 } // namespace mozilla
264 #endif // mozilla_MotionPathUtils_h