From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- layout/base/MotionPathUtils.h | 264 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 layout/base/MotionPathUtils.h (limited to 'layout/base/MotionPathUtils.h') diff --git a/layout/base/MotionPathUtils.h b/layout/base/MotionPathUtils.h new file mode 100644 index 0000000000..cf4d820016 --- /dev/null +++ b/layout/base/MotionPathUtils.h @@ -0,0 +1,264 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_MotionPathUtils_h +#define mozilla_MotionPathUtils_h + +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/gfx/Rect.h" +#include "mozilla/Maybe.h" +#include "mozilla/ServoStyleConsts.h" +#include "Units.h" + +class nsIFrame; + +namespace nsStyleTransformMatrix { +class TransformReferenceBox; +} + +namespace mozilla { + +namespace layers { +class MotionPathData; +class PathCommand; +} // namespace layers + +struct ResolvedMotionPathData { + gfx::Point mTranslate; + float mRotate; + // The delta value between transform-origin and offset-anchor. + gfx::Point mShift; +}; + +// The collected information for offset-path. We preprocess the value of +// offset-path and use this data for resolving motion path. +struct OffsetPathData { + enum class Type : uint8_t { + None, + Shape, + Ray, + }; + + struct ShapeData { + RefPtr mGfxPath; + // The current position of this transfromed box in the coordinate system of + // its containing block. + nsPoint mCurrentPosition; + // True if it is a closed loop; false if it is a unclosed interval. + // https://drafts.fxtf.org/motion/#path-distance + bool mIsClosedLoop; + }; + + struct RayData { + const StyleRayFunction* mRay; + // The coord box of the containing block. + nsRect mCoordBox; + // The current position of this transfromed box in the coordinate system of + // its containing block. + nsPoint mCurrentPosition; + // The reference length for computing ray(contain). + CSSCoord mContainReferenceLength; + }; + + Type mType; + union { + ShapeData mShape; + RayData mRay; + }; + + static OffsetPathData None() { return OffsetPathData(); } + static OffsetPathData Shape(already_AddRefed&& aGfxPath, + nsPoint&& aCurrentPosition, bool aIsClosedPath) { + return OffsetPathData(std::move(aGfxPath), std::move(aCurrentPosition), + aIsClosedPath); + } + static OffsetPathData Ray(const StyleRayFunction& aRay, nsRect&& aCoordBox, + nsPoint&& aPosition, + CSSCoord&& aContainReferenceLength) { + return OffsetPathData(&aRay, std::move(aCoordBox), std::move(aPosition), + std::move(aContainReferenceLength)); + } + static OffsetPathData Ray(const StyleRayFunction& aRay, + const nsRect& aCoordBox, const nsPoint& aPosition, + const CSSCoord& aContainReferenceLength) { + return OffsetPathData(&aRay, aCoordBox, aPosition, aContainReferenceLength); + } + + bool IsNone() const { return mType == Type::None; } + bool IsShape() const { return mType == Type::Shape; } + bool IsRay() const { return mType == Type::Ray; } + + const ShapeData& AsShape() const { + MOZ_ASSERT(IsShape()); + return mShape; + } + + const RayData& AsRay() const { + MOZ_ASSERT(IsRay()); + return mRay; + } + + ~OffsetPathData() { + switch (mType) { + case Type::Shape: + mShape.~ShapeData(); + break; + case Type::Ray: + mRay.~RayData(); + break; + default: + break; + } + } + + OffsetPathData(const OffsetPathData& aOther) : mType(aOther.mType) { + switch (mType) { + case Type::Shape: + mShape = aOther.mShape; + break; + case Type::Ray: + mRay = aOther.mRay; + break; + default: + break; + } + } + + OffsetPathData(OffsetPathData&& aOther) : mType(aOther.mType) { + switch (mType) { + case Type::Shape: + mShape = std::move(aOther.mShape); + break; + case Type::Ray: + mRay = std::move(aOther.mRay); + break; + default: + break; + } + } + + private: + OffsetPathData() : mType(Type::None) {} + OffsetPathData(already_AddRefed&& aPath, + nsPoint&& aCurrentPosition, bool aIsClosed) + : mType(Type::Shape), + mShape{std::move(aPath), std::move(aCurrentPosition), aIsClosed} {} + OffsetPathData(const StyleRayFunction* aRay, nsRect&& aCoordBox, + nsPoint&& aPosition, CSSCoord&& aContainReferenceLength) + : mType(Type::Ray), + mRay{aRay, std::move(aCoordBox), std::move(aPosition), + std::move(aContainReferenceLength)} {} + OffsetPathData(const StyleRayFunction* aRay, const nsRect& aCoordBox, + const nsPoint& aPosition, + const CSSCoord& aContainReferenceLength) + : mType(Type::Ray), + mRay{aRay, aCoordBox, aPosition, aContainReferenceLength} {} + OffsetPathData& operator=(const OffsetPathData&) = delete; + OffsetPathData& operator=(OffsetPathData&&) = delete; +}; + +// MotionPathUtils is a namespace class containing utility functions related to +// processing motion path in the [motion-1]. +// https://drafts.fxtf.org/motion-1/ +class MotionPathUtils final { + using TransformReferenceBox = nsStyleTransformMatrix::TransformReferenceBox; + + public: + /** + * SVG frames (unlike other frames) have a reference box that can be (and + * typically is) offset from the TopLeft() of the frame. + * + * In motion path, we have to make sure the object is aligned with offset-path + * when using content area, so we should tweak the anchor point by a given + * offset. + */ + static CSSPoint ComputeAnchorPointAdjustment(const nsIFrame& aFrame); + + /** + * In CSS context, this returns the the box being referenced from the element + * that establishes the containing block for this element. + * In SVG context, we always use view-box. + * https://drafts.fxtf.org/motion-1/#valdef-offset-path-coord-box + */ + static const nsIFrame* GetOffsetPathReferenceBox(const nsIFrame* aFrame, + nsRect& aOutputRect); + + /** + * Return the width or the height of the element’s border box, whichever is + * larger. This is for computing the ray() with "contain" keyword. + */ + static CSSCoord GetRayContainReferenceSize(nsIFrame* aFrame); + + /** + * Get the resolved radius for inset(0 round X), where X is the parameter of + * |aRadius|. + * This returns an empty array if we cannot compute the radii; otherwise, it + * returns an array with 8 elements. + */ + static nsTArray ComputeBorderRadii( + const StyleBorderRadius& aBorderRadius, const nsRect& aCoordBox); + + /** + * Generate the motion path transform result. This function may be called on + * the compositor thread. + */ + static Maybe ResolveMotionPath( + const OffsetPathData& aPath, const LengthPercentage& aDistance, + const StyleOffsetRotate& aRotate, const StylePositionOrAuto& aAnchor, + const StyleOffsetPosition& aPosition, const CSSPoint& aTransformOrigin, + TransformReferenceBox&, const CSSPoint& aAnchorPointAdjustment); + + /** + * Generate the motion path transform result with |nsIFrame|. This is only + * called in the main thread. + */ + static Maybe ResolveMotionPath( + const nsIFrame* aFrame, TransformReferenceBox&); + + /** + * Generate the motion path transfrom result with styles and + * layers::MotionPathData. + * This is only called by the compositor. + */ + static Maybe ResolveMotionPath( + const StyleOffsetPath* aPath, const StyleLengthPercentage* aDistance, + const StyleOffsetRotate* aRotate, const StylePositionOrAuto* aAnchor, + const StyleOffsetPosition* aPosition, + const Maybe& aMotionPathData, + TransformReferenceBox&, gfx::Path* aCachedMotionPath); + + /** + * Build a gfx::Path from the svg path data. We should give it a path builder. + * If |aPathBuilder| is nullptr, we return null path. + * This can be used on the main thread or on the compositor thread. + */ + static already_AddRefed BuildSVGPath( + const StyleSVGPathData& aPath, gfx::PathBuilder* aPathBuilder); + + /** + * Build a gfx::Path from the computed basic shape. + */ + static already_AddRefed BuildPath(const StyleBasicShape&, + const StyleOffsetPosition&, + const nsRect& aCoordBox, + const nsPoint& aCurrentPosition, + gfx::PathBuilder*); + + /** + * Get a path builder for motion path on the main thread. + */ + static already_AddRefed GetPathBuilder(); + + /** + * Get a path builder for compositor. + */ + static already_AddRefed GetCompositorPathBuilder(); +}; + +} // namespace mozilla + +#endif // mozilla_MotionPathUtils_h -- cgit v1.2.3