MotionPathUtils.h (8921B)
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/. */ 6 7 #ifndef mozilla_MotionPathUtils_h 8 #define mozilla_MotionPathUtils_h 9 10 #include "Units.h" 11 #include "mozilla/Maybe.h" 12 #include "mozilla/ServoStyleConsts.h" 13 #include "mozilla/gfx/2D.h" 14 #include "mozilla/gfx/Point.h" 15 #include "mozilla/gfx/Rect.h" 16 17 class nsIFrame; 18 19 namespace nsStyleTransformMatrix { 20 class TransformReferenceBox; 21 } 22 23 namespace mozilla { 24 25 namespace layers { 26 class MotionPathData; 27 class PathCommand; 28 } // namespace layers 29 30 struct ResolvedMotionPathData { 31 gfx::Point mTranslate; 32 float mRotate; 33 // The delta value between transform-origin and offset-anchor. 34 gfx::Point mShift; 35 }; 36 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 { 41 None, 42 Shape, 43 Ray, 44 }; 45 46 struct ShapeData { 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 53 bool mIsClosedLoop; 54 }; 55 56 struct RayData { 57 const StyleRayFunction* mRay; 58 // The coord box of the containing block. 59 nsRect mCoordBox; 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; 65 }; 66 67 Type mType; 68 union { 69 ShapeData mShape; 70 RayData mRay; 71 }; 72 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), 77 aIsClosedPath); 78 } 79 static OffsetPathData Ray(const StyleRayFunction& aRay, nsRect&& aCoordBox, 80 nsPoint&& aPosition, 81 CSSCoord&& aContainReferenceLength) { 82 return OffsetPathData(&aRay, std::move(aCoordBox), std::move(aPosition), 83 std::move(aContainReferenceLength)); 84 } 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); 89 } 90 91 bool IsNone() const { return mType == Type::None; } 92 bool IsShape() const { return mType == Type::Shape; } 93 bool IsRay() const { return mType == Type::Ray; } 94 95 const ShapeData& AsShape() const { 96 MOZ_ASSERT(IsShape()); 97 return mShape; 98 } 99 100 const RayData& AsRay() const { 101 MOZ_ASSERT(IsRay()); 102 return mRay; 103 } 104 105 ~OffsetPathData() { 106 switch (mType) { 107 case Type::Shape: 108 mShape.~ShapeData(); 109 break; 110 case Type::Ray: 111 mRay.~RayData(); 112 break; 113 default: 114 break; 115 } 116 } 117 118 OffsetPathData(const OffsetPathData& aOther) : mType(aOther.mType) { 119 switch (mType) { 120 case Type::Shape: 121 mShape = aOther.mShape; 122 break; 123 case Type::Ray: 124 mRay = aOther.mRay; 125 break; 126 default: 127 break; 128 } 129 } 130 131 OffsetPathData(OffsetPathData&& aOther) : mType(aOther.mType) { 132 switch (mType) { 133 case Type::Shape: 134 mShape = std::move(aOther.mShape); 135 break; 136 case Type::Ray: 137 mRay = std::move(aOther.mRay); 138 break; 139 default: 140 break; 141 } 142 } 143 144 private: 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) 152 : mType(Type::Ray), 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) 158 : mType(Type::Ray), 159 mRay{aRay, aCoordBox, aPosition, aContainReferenceLength} {} 160 OffsetPathData& operator=(const OffsetPathData&) = delete; 161 OffsetPathData& operator=(OffsetPathData&&) = delete; 162 }; 163 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; 169 170 public: 171 /** 172 * SVG frames (unlike other frames) have a reference box that can be (and 173 * typically is) offset from the TopLeft() of the frame. 174 * 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 177 * offset. 178 */ 179 static CSSPoint ComputeAnchorPointAdjustment(const nsIFrame& aFrame); 180 181 /** 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 186 */ 187 static const nsIFrame* GetOffsetPathReferenceBox(const nsIFrame* aFrame, 188 nsRect& aOutputRect); 189 190 /** 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. 193 */ 194 static CSSCoord GetRayContainReferenceSize(nsIFrame* aFrame); 195 196 /** 197 * Get the resolved radius for inset(0 round X), where X is the parameter of 198 * |aRadius|. 199 * This returns an empty array if we cannot compute the radii; otherwise, it 200 * returns an array with 8 elements. 201 */ 202 static nsTArray<nscoord> ComputeBorderRadii( 203 const StyleBorderRadius& aBorderRadius, const nsRect& aCoordBox); 204 205 /** 206 * Generate the motion path transform result. This function may be called on 207 * the compositor thread. 208 */ 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); 214 215 /** 216 * Generate the motion path transform result with |nsIFrame|. This is only 217 * called in the main thread. 218 */ 219 static Maybe<ResolvedMotionPathData> ResolveMotionPath( 220 const nsIFrame* aFrame, TransformReferenceBox&); 221 222 /** 223 * Generate the motion path transfrom result with styles and 224 * layers::MotionPathData. 225 * This is only called by the compositor. 226 */ 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); 233 234 /** 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. 238 */ 239 static already_AddRefed<gfx::Path> BuildSVGPath( 240 const StyleSVGPathData& aPath, gfx::PathBuilder* aPathBuilder); 241 242 /** 243 * Build a gfx::Path from the computed basic shape. 244 */ 245 static already_AddRefed<gfx::Path> BuildPath(const StyleBasicShape&, 246 const StyleOffsetPosition&, 247 const nsRect& aCoordBox, 248 const nsPoint& aCurrentPosition, 249 gfx::PathBuilder*); 250 251 /** 252 * Get a path builder for motion path on the main thread. 253 */ 254 static already_AddRefed<gfx::PathBuilder> GetPathBuilder(); 255 256 /** 257 * Get a path builder for compositor. 258 */ 259 static already_AddRefed<gfx::PathBuilder> GetCompositorPathBuilder(); 260 }; 261 262 } // namespace mozilla 263 264 #endif // mozilla_MotionPathUtils_h