Bug 1447839 - Avoid creating internal path for PathRecording unless necessary. r=jrmuizel

Differential Revision: https://phabricator.services.mozilla.com/D172869
This commit is contained in:
Lee Salzman 2023-03-17 19:04:39 +00:00
Родитель e468b1ba27
Коммит 47c82792d1
2 изменённых файлов: 59 добавлений и 35 удалений

Просмотреть файл

@ -150,52 +150,63 @@ size_t PathOps::NumberOfOps() const {
void PathBuilderRecording::MoveTo(const Point& aPoint) {
mPathOps.MoveTo(aPoint);
mPathBuilder->MoveTo(aPoint);
mBeginPoint = aPoint;
mCurrentPoint = aPoint;
}
void PathBuilderRecording::LineTo(const Point& aPoint) {
mPathOps.LineTo(aPoint);
mPathBuilder->LineTo(aPoint);
mCurrentPoint = aPoint;
}
void PathBuilderRecording::BezierTo(const Point& aCP1, const Point& aCP2,
const Point& aCP3) {
mPathOps.BezierTo(aCP1, aCP2, aCP3);
mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
mCurrentPoint = aCP3;
}
void PathBuilderRecording::QuadraticBezierTo(const Point& aCP1,
const Point& aCP2) {
mPathOps.QuadraticBezierTo(aCP1, aCP2);
mPathBuilder->QuadraticBezierTo(aCP1, aCP2);
mCurrentPoint = aCP2;
}
void PathBuilderRecording::Close() {
mPathOps.Close();
mPathBuilder->Close();
mCurrentPoint = mBeginPoint;
}
void PathBuilderRecording::Arc(const Point& aOrigin, float aRadius,
float aStartAngle, float aEndAngle,
bool aAntiClockwise) {
mPathOps.Arc(aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
mPathBuilder->Arc(aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
// This just lets ArcToBezier override the current point without modifying
// path ops or having to instantiate a path.
struct CurrentPointTracker {
PathBuilderRecording* mPathBuilder;
void LineTo(const Point& aPoint) { mPathBuilder->SetCurrentPoint(aPoint); }
void BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3) {
mPathBuilder->SetCurrentPoint(aCP3);
}
} tracker = {this};
ArcToBezier(&tracker, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle,
aAntiClockwise);
}
already_AddRefed<Path> PathBuilderRecording::Finish() {
// We rely on mPathBuilder to track begin and current point, but that stops
// when we call Finish, so we need to store them first.
Point beginPoint = BeginPoint();
Point currentPoint = CurrentPoint();
RefPtr<Path> path = mPathBuilder->Finish();
return MakeAndAddRef<PathRecording>(path, std::move(mPathOps), mFillRule,
currentPoint, beginPoint);
return MakeAndAddRef<PathRecording>(std::move(mPathBuilder),
std::move(mPathOps), mFillRule,
mBeginPoint, mCurrentPoint);
}
PathRecording::PathRecording(Path* aPath, PathOps&& aOps, FillRule aFillRule,
const Point& aCurrentPoint,
PathRecording::PathRecording(RefPtr<PathBuilder>&& aPathBuilder, PathOps&& aOps,
FillRule aFillRule, const Point& aCurrentPoint,
const Point& aBeginPoint)
: mPath(aPath),
: mPathBuilder(std::move(aPathBuilder)),
mPathOps(std::move(aOps)),
mFillRule(aFillRule),
mCurrentPoint(aCurrentPoint),
@ -208,8 +219,23 @@ PathRecording::~PathRecording() {
}
}
void PathRecording::EnsurePath() const {
if (mPath) {
return;
}
MOZ_ASSERT(!!mPathBuilder);
if (!mPathOps.StreamToSink(*mPathBuilder)) {
MOZ_ASSERT(false, "Failed to stream PathOps to PathBuilder");
} else {
mPath = mPathBuilder->Finish();
MOZ_ASSERT(!!mPath, "Failed finishing Path from PathBuilder");
}
mPathBuilder = nullptr;
}
already_AddRefed<PathBuilder> PathRecording::CopyToBuilder(
FillRule aFillRule) const {
EnsurePath();
RefPtr<PathBuilder> pathBuilder = mPath->CopyToBuilder(aFillRule);
RefPtr<PathBuilderRecording> recording =
new PathBuilderRecording(pathBuilder, mPathOps, aFillRule);
@ -220,6 +246,7 @@ already_AddRefed<PathBuilder> PathRecording::CopyToBuilder(
already_AddRefed<PathBuilder> PathRecording::TransformedCopyToBuilder(
const Matrix& aTransform, FillRule aFillRule) const {
EnsurePath();
RefPtr<PathBuilder> pathBuilder =
mPath->TransformedCopyToBuilder(aTransform, aFillRule);
RefPtr<PathBuilderRecording> recording = new PathBuilderRecording(

Просмотреть файл

@ -153,21 +153,6 @@ class PathBuilderRecording final : public PathBuilder {
void Arc(const Point& aOrigin, float aRadius, float aStartAngle,
float aEndAngle, bool aAntiClockwise) final;
/* Point the current subpath is at - or where the next subpath will start
* if there is no active subpath.
*/
Point CurrentPoint() const final { return mPathBuilder->CurrentPoint(); }
Point BeginPoint() const final { return mPathBuilder->BeginPoint(); }
void SetCurrentPoint(const Point& aPoint) final {
mPathBuilder->SetCurrentPoint(aPoint);
}
void SetBeginPoint(const Point& aPoint) final {
mPathBuilder->SetBeginPoint(aPoint);
}
already_AddRefed<Path> Finish() final;
BackendType GetBackendType() const final { return BackendType::RECORDING; }
@ -182,7 +167,7 @@ class PathRecording final : public Path {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathRecording, override)
PathRecording(Path* aPath, PathOps&& aOps, FillRule aFillRule,
PathRecording(RefPtr<PathBuilder>&& aPath, PathOps&& aOps, FillRule aFillRule,
const Point& aCurrentPoint, const Point& aBeginPoint);
~PathRecording();
@ -193,26 +178,35 @@ class PathRecording final : public Path {
const Matrix& aTransform, FillRule aFillRule) const final;
bool ContainsPoint(const Point& aPoint,
const Matrix& aTransform) const final {
EnsurePath();
return mPath->ContainsPoint(aPoint, aTransform);
}
bool StrokeContainsPoint(const StrokeOptions& aStrokeOptions,
const Point& aPoint,
const Matrix& aTransform) const final {
EnsurePath();
return mPath->StrokeContainsPoint(aStrokeOptions, aPoint, aTransform);
}
Rect GetBounds(const Matrix& aTransform = Matrix()) const final {
EnsurePath();
return mPath->GetBounds(aTransform);
}
Rect GetStrokedBounds(const StrokeOptions& aStrokeOptions,
const Matrix& aTransform = Matrix()) const final {
EnsurePath();
return mPath->GetStrokedBounds(aStrokeOptions, aTransform);
}
Maybe<Rect> AsRect() const final { return mPath->AsRect(); }
Maybe<Rect> AsRect() const final {
EnsurePath();
return mPath->AsRect();
}
void StreamToSink(PathSink* aSink) const final { mPath->StreamToSink(aSink); }
void StreamToSink(PathSink* aSink) const final {
mPathOps.StreamToSink(*aSink);
}
FillRule GetFillRule() const final { return mFillRule; }
@ -221,7 +215,10 @@ class PathRecording final : public Path {
friend class DrawTargetRecording;
friend class RecordedPathCreation;
RefPtr<Path> mPath;
void EnsurePath() const;
mutable RefPtr<PathBuilder> mPathBuilder;
mutable RefPtr<Path> mPath;
PathOps mPathOps;
FillRule mFillRule;
Point mCurrentPoint;