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/Point.h"
11 #include "mozilla/Maybe.h"
12 #include "mozilla/ServoStyleConsts.h"
17 namespace nsStyleTransformMatrix
{
18 class TransformReferenceBox
;
23 using RayFunction
= StyleRayFunction
<StyleAngle
>;
30 struct ResolvedMotionPathData
{
31 gfx::Point mTranslate
;
33 // The delta value between transform-origin and offset-anchor.
37 struct RayReferenceData
{
38 // The initial position related to the containing block.
39 CSSPoint mInitialPosition
;
40 // The rect of the containing block.
41 CSSRect mContainingBlockRect
;
43 RayReferenceData() = default;
44 explicit RayReferenceData(const nsIFrame
* aFrame
);
46 bool operator==(const RayReferenceData
& aOther
) const {
47 return mInitialPosition
== aOther
.mInitialPosition
&&
48 mContainingBlockRect
== aOther
.mContainingBlockRect
;
52 // The collected information for offset-path. We preprocess the value of
53 // offset-path and use this data for resolving motion path.
54 struct OffsetPathData
{
55 enum class Type
: uint8_t {
62 RefPtr
<gfx::Path
> mGfxPath
;
63 bool mIsClosedIntervals
;
67 const RayFunction
* mRay
;
68 RayReferenceData mData
;
77 static OffsetPathData
None() { return OffsetPathData(); }
78 static OffsetPathData
Path(const StyleSVGPathData
& aPath
,
79 already_AddRefed
<gfx::Path
>&& aGfxPath
) {
80 const auto& path
= aPath
._0
.AsSpan();
81 return OffsetPathData(std::move(aGfxPath
),
82 !path
.empty() && path
.rbegin()->IsClosePath());
84 static OffsetPathData
Ray(const RayFunction
& aRay
,
85 const RayReferenceData
& aData
) {
86 return OffsetPathData(&aRay
, aData
);
88 static OffsetPathData
Ray(const RayFunction
& aRay
, RayReferenceData
&& aData
) {
89 return OffsetPathData(&aRay
, std::move(aData
));
92 bool IsNone() const { return mType
== Type::None
; }
93 bool IsPath() const { return mType
== Type::Path
; }
94 bool IsRay() const { return mType
== Type::Ray
; }
96 const PathData
& AsPath() const {
101 const RayData
& AsRay() const {
119 OffsetPathData(const OffsetPathData
& aOther
) : mType(aOther
.mType
) {
122 mPath
= aOther
.mPath
;
132 OffsetPathData(OffsetPathData
&& aOther
) : mType(aOther
.mType
) {
135 mPath
= std::move(aOther
.mPath
);
138 mRay
= std::move(aOther
.mRay
);
146 OffsetPathData() : mType(Type::None
) {}
147 OffsetPathData(already_AddRefed
<gfx::Path
>&& aPath
, bool aIsClosed
)
148 : mType(Type::Path
), mPath
{std::move(aPath
), aIsClosed
} {}
149 OffsetPathData(const RayFunction
* aRay
, RayReferenceData
&& aRef
)
150 : mType(Type::Ray
), mRay
{aRay
, std::move(aRef
)} {}
151 OffsetPathData(const RayFunction
* aRay
, const RayReferenceData
& aRef
)
152 : mType(Type::Ray
), mRay
{aRay
, aRef
} {}
153 OffsetPathData
& operator=(const OffsetPathData
&) = delete;
154 OffsetPathData
& operator=(OffsetPathData
&&) = delete;
157 // MotionPathUtils is a namespace class containing utility functions related to
158 // processing motion path in the [motion-1].
159 // https://drafts.fxtf.org/motion-1/
160 class MotionPathUtils final
{
161 using TransformReferenceBox
= nsStyleTransformMatrix::TransformReferenceBox
;
164 // SVG frames (unlike other frames) have a reference box that can be (and
165 // typically is) offset from the TopLeft() of the frame.
167 // In motion path, we have to make sure the object is aligned with offset-path
168 // when using content area, so we should tweak the anchor point by a given
170 static CSSPoint
ComputeAnchorPointAdjustment(const nsIFrame
& aFrame
);
173 * Generate the motion path transform result. This function may be called on
174 * the compositor thread.
176 static Maybe
<ResolvedMotionPathData
> ResolveMotionPath(
177 const OffsetPathData
& aPath
, const LengthPercentage
& aDistance
,
178 const StyleOffsetRotate
& aRotate
, const StylePositionOrAuto
& aAnchor
,
179 const CSSPoint
& aTransformOrigin
, TransformReferenceBox
&,
180 const CSSPoint
& aAnchorPointAdjustment
);
183 * Generate the motion path transform result with |nsIFrame|. This is only
184 * called in the main thread.
186 static Maybe
<ResolvedMotionPathData
> ResolveMotionPath(
187 const nsIFrame
* aFrame
, TransformReferenceBox
&);
190 * Generate the motion path transfrom result with styles and
191 * layers::MotionPathData.
192 * This is only called by the compositor.
194 static Maybe
<ResolvedMotionPathData
> ResolveMotionPath(
195 const StyleOffsetPath
* aPath
, const StyleLengthPercentage
* aDistance
,
196 const StyleOffsetRotate
* aRotate
, const StylePositionOrAuto
* aAnchor
,
197 const Maybe
<layers::MotionPathData
>& aMotionPathData
,
198 TransformReferenceBox
&, gfx::Path
* aCachedMotionPath
);
201 * Normalize StyleSVGPathData.
203 * The algorithm of normalization is the same as normalize() in
204 * servo/components/style/values/specified/svg_path.rs
205 * FIXME: Bug 1489392: We don't have to normalize the path here if we accept
206 * the spec issue which would like to normalize svg paths at computed time.
207 * https://github.com/w3c/svgwg/issues/321
209 static StyleSVGPathData
NormalizeSVGPathData(const StyleSVGPathData
& aPath
);
212 * Build a gfx::Path from the computed svg path. We should give it a path
213 * builder. If |aPathBuilder| is nullptr, we return null path.
215 static already_AddRefed
<gfx::Path
> BuildPath(const StyleSVGPathData
& aPath
,
216 gfx::PathBuilder
* aPathBuilder
);
219 * Get a path builder for compositor.
221 static already_AddRefed
<gfx::PathBuilder
> GetCompositorPathBuilder();
224 } // namespace mozilla
226 #endif // mozilla_MotionPathUtils_h