зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
e468b1ba27
Коммит
47c82792d1
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче