2019-10-31 23:07:28 +03:00
|
|
|
/* -*- 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
|
|
|
|
|
2020-11-23 19:21:38 +03:00
|
|
|
#include "mozilla/gfx/2D.h"
|
2019-10-31 23:07:28 +03:00
|
|
|
#include "mozilla/gfx/Point.h"
|
2020-11-23 19:21:38 +03:00
|
|
|
#include "mozilla/gfx/Rect.h"
|
2019-10-31 23:07:28 +03:00
|
|
|
#include "mozilla/Maybe.h"
|
2019-10-31 23:07:30 +03:00
|
|
|
#include "mozilla/ServoStyleConsts.h"
|
|
|
|
#include "Units.h"
|
2019-10-31 23:07:28 +03:00
|
|
|
|
|
|
|
class nsIFrame;
|
|
|
|
|
2020-02-07 16:34:42 +03:00
|
|
|
namespace nsStyleTransformMatrix {
|
|
|
|
class TransformReferenceBox;
|
|
|
|
}
|
|
|
|
|
2019-10-31 23:07:28 +03:00
|
|
|
namespace mozilla {
|
|
|
|
|
2019-10-31 23:07:30 +03:00
|
|
|
using RayFunction = StyleRayFunction<StyleAngle>;
|
|
|
|
|
2019-10-31 23:07:41 +03:00
|
|
|
namespace layers {
|
2020-01-08 12:02:36 +03:00
|
|
|
class MotionPathData;
|
2019-10-31 23:07:41 +03:00
|
|
|
class PathCommand;
|
|
|
|
} // namespace layers
|
|
|
|
|
2020-01-08 12:02:38 +03:00
|
|
|
struct ResolvedMotionPathData {
|
2019-10-31 23:07:28 +03:00
|
|
|
gfx::Point mTranslate;
|
|
|
|
float mRotate;
|
|
|
|
// The delta value between transform-origin and offset-anchor.
|
|
|
|
gfx::Point mShift;
|
|
|
|
};
|
|
|
|
|
2019-10-31 23:07:30 +03:00
|
|
|
struct RayReferenceData {
|
|
|
|
// The initial position related to the containing block.
|
|
|
|
CSSPoint mInitialPosition;
|
|
|
|
// The rect of the containing block.
|
|
|
|
CSSRect mContainingBlockRect;
|
|
|
|
|
2019-10-31 23:07:41 +03:00
|
|
|
RayReferenceData() = default;
|
2019-10-31 23:07:30 +03:00
|
|
|
explicit RayReferenceData(const nsIFrame* aFrame);
|
2019-10-31 23:07:41 +03:00
|
|
|
|
|
|
|
bool operator==(const RayReferenceData& aOther) const {
|
|
|
|
return mInitialPosition == aOther.mInitialPosition &&
|
|
|
|
mContainingBlockRect == aOther.mContainingBlockRect;
|
|
|
|
}
|
2019-10-31 23:07:30 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
// 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,
|
|
|
|
Path,
|
|
|
|
Ray,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PathData {
|
|
|
|
RefPtr<gfx::Path> mGfxPath;
|
|
|
|
bool mIsClosedIntervals;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct RayData {
|
|
|
|
const RayFunction* mRay;
|
|
|
|
RayReferenceData mData;
|
|
|
|
};
|
|
|
|
|
|
|
|
Type mType;
|
|
|
|
union {
|
|
|
|
PathData mPath;
|
|
|
|
RayData mRay;
|
|
|
|
};
|
|
|
|
|
|
|
|
static OffsetPathData None() { return OffsetPathData(); }
|
2019-10-31 23:07:31 +03:00
|
|
|
static OffsetPathData Path(const StyleSVGPathData& aPath,
|
2019-11-01 00:36:39 +03:00
|
|
|
already_AddRefed<gfx::Path>&& aGfxPath) {
|
|
|
|
const auto& path = aPath._0.AsSpan();
|
|
|
|
return OffsetPathData(std::move(aGfxPath),
|
|
|
|
!path.empty() && path.rbegin()->IsClosePath());
|
|
|
|
}
|
2019-10-31 23:07:30 +03:00
|
|
|
static OffsetPathData Ray(const RayFunction& aRay,
|
|
|
|
const RayReferenceData& aData) {
|
|
|
|
return OffsetPathData(&aRay, aData);
|
|
|
|
}
|
|
|
|
static OffsetPathData Ray(const RayFunction& aRay, RayReferenceData&& aData) {
|
|
|
|
return OffsetPathData(&aRay, std::move(aData));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsNone() const { return mType == Type::None; }
|
|
|
|
bool IsPath() const { return mType == Type::Path; }
|
|
|
|
bool IsRay() const { return mType == Type::Ray; }
|
|
|
|
|
|
|
|
const PathData& AsPath() const {
|
|
|
|
MOZ_ASSERT(IsPath());
|
|
|
|
return mPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
const RayData& AsRay() const {
|
|
|
|
MOZ_ASSERT(IsRay());
|
|
|
|
return mRay;
|
|
|
|
}
|
|
|
|
|
|
|
|
~OffsetPathData() {
|
|
|
|
switch (mType) {
|
|
|
|
case Type::Path:
|
|
|
|
mPath.~PathData();
|
|
|
|
break;
|
|
|
|
case Type::Ray:
|
|
|
|
mRay.~RayData();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OffsetPathData(const OffsetPathData& aOther) : mType(aOther.mType) {
|
|
|
|
switch (mType) {
|
|
|
|
case Type::Path:
|
|
|
|
mPath = aOther.mPath;
|
|
|
|
break;
|
|
|
|
case Type::Ray:
|
|
|
|
mRay = aOther.mRay;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OffsetPathData(OffsetPathData&& aOther) : mType(aOther.mType) {
|
|
|
|
switch (mType) {
|
|
|
|
case Type::Path:
|
|
|
|
mPath = std::move(aOther.mPath);
|
|
|
|
break;
|
|
|
|
case Type::Ray:
|
|
|
|
mRay = std::move(aOther.mRay);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
OffsetPathData() : mType(Type::None) {}
|
2019-11-01 00:36:39 +03:00
|
|
|
OffsetPathData(already_AddRefed<gfx::Path>&& aPath, bool aIsClosed)
|
|
|
|
: mType(Type::Path), mPath{std::move(aPath), aIsClosed} {}
|
2019-10-31 23:07:30 +03:00
|
|
|
OffsetPathData(const RayFunction* aRay, RayReferenceData&& aRef)
|
|
|
|
: mType(Type::Ray), mRay{aRay, std::move(aRef)} {}
|
|
|
|
OffsetPathData(const RayFunction* aRay, const RayReferenceData& aRef)
|
|
|
|
: mType(Type::Ray), mRay{aRay, aRef} {}
|
|
|
|
OffsetPathData& operator=(const OffsetPathData&) = delete;
|
|
|
|
OffsetPathData& operator=(OffsetPathData&&) = delete;
|
|
|
|
};
|
|
|
|
|
2019-10-31 23:07:28 +03:00
|
|
|
// 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 {
|
2020-02-07 16:34:42 +03:00
|
|
|
using TransformReferenceBox = nsStyleTransformMatrix::TransformReferenceBox;
|
|
|
|
|
2019-10-31 23:07:28 +03:00
|
|
|
public:
|
2020-02-07 16:34:42 +03:00
|
|
|
// 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);
|
|
|
|
|
2019-10-31 23:07:28 +03:00
|
|
|
/**
|
2019-10-31 23:07:30 +03:00
|
|
|
* Generate the motion path transform result. This function may be called on
|
|
|
|
* the compositor thread.
|
2020-02-07 16:34:42 +03:00
|
|
|
*/
|
2020-01-08 12:02:38 +03:00
|
|
|
static Maybe<ResolvedMotionPathData> ResolveMotionPath(
|
2019-10-31 23:07:30 +03:00
|
|
|
const OffsetPathData& aPath, const LengthPercentage& aDistance,
|
|
|
|
const StyleOffsetRotate& aRotate, const StylePositionOrAuto& aAnchor,
|
2020-02-07 16:34:42 +03:00
|
|
|
const CSSPoint& aTransformOrigin, TransformReferenceBox&,
|
|
|
|
const CSSPoint& aAnchorPointAdjustment);
|
2019-10-31 23:07:30 +03:00
|
|
|
|
|
|
|
/**
|
2019-10-31 23:07:41 +03:00
|
|
|
* Generate the motion path transform result with |nsIFrame|. This is only
|
|
|
|
* called in the main thread.
|
2020-02-07 16:34:42 +03:00
|
|
|
*/
|
2020-01-08 12:02:38 +03:00
|
|
|
static Maybe<ResolvedMotionPathData> ResolveMotionPath(
|
2020-02-07 16:34:42 +03:00
|
|
|
const nsIFrame* aFrame, TransformReferenceBox&);
|
2019-10-31 23:07:41 +03:00
|
|
|
|
|
|
|
/**
|
2020-01-08 12:02:36 +03:00
|
|
|
* Generate the motion path transfrom result with styles and
|
|
|
|
* layers::MotionPathData.
|
2019-10-31 23:07:41 +03:00
|
|
|
* This is only called by the compositor.
|
|
|
|
*/
|
2020-01-08 12:02:38 +03:00
|
|
|
static Maybe<ResolvedMotionPathData> ResolveMotionPath(
|
2019-10-31 23:07:41 +03:00
|
|
|
const StyleOffsetPath* aPath, const StyleLengthPercentage* aDistance,
|
|
|
|
const StyleOffsetRotate* aRotate, const StylePositionOrAuto* aAnchor,
|
2020-01-08 12:02:36 +03:00
|
|
|
const Maybe<layers::MotionPathData>& aMotionPathData,
|
2020-02-07 16:34:42 +03:00
|
|
|
TransformReferenceBox&, gfx::Path* aCachedMotionPath);
|
2019-10-31 23:07:41 +03:00
|
|
|
|
|
|
|
/**
|
2020-01-22 23:18:35 +03:00
|
|
|
* Normalize StyleSVGPathData.
|
2019-10-31 23:07:41 +03:00
|
|
|
*
|
|
|
|
* The algorithm of normalization is the same as normalize() in
|
|
|
|
* servo/components/style/values/specified/svg_path.rs
|
|
|
|
* FIXME: Bug 1489392: We don't have to normalize the path here if we accept
|
2020-01-22 23:18:35 +03:00
|
|
|
* the spec issue which would like to normalize svg paths at computed time.
|
2019-10-31 23:07:41 +03:00
|
|
|
* https://github.com/w3c/svgwg/issues/321
|
|
|
|
*/
|
2020-01-22 23:18:35 +03:00
|
|
|
static StyleSVGPathData NormalizeSVGPathData(const StyleSVGPathData& aPath);
|
2019-11-01 00:36:39 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Build a gfx::Path from the computed svg path. We should give it a path
|
|
|
|
* builder. If |aPathBuilder| is nullptr, we return null path.
|
|
|
|
* */
|
|
|
|
static already_AddRefed<gfx::Path> BuildPath(const StyleSVGPathData& aPath,
|
|
|
|
gfx::PathBuilder* aPathBuilder);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a path builder for compositor.
|
|
|
|
*/
|
|
|
|
static already_AddRefed<gfx::PathBuilder> GetCompositorPathBuilder();
|
2019-10-31 23:07:28 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // mozilla_MotionPathUtils_h
|