/* -*- 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_GFX_PATHRECORDING_H_ #define MOZILLA_GFX_PATHRECORDING_H_ #include "2D.h" #include #include #include "PathHelpers.h" #include "RecordingTypes.h" namespace mozilla { namespace gfx { struct Circle { Point origin; float radius; bool closed = false; }; struct Line { Point origin; Point destination; }; class PathOps { public: PathOps() = default; template explicit PathOps(S& aStream); PathOps(const PathOps& aOther) = default; PathOps& operator=(const PathOps&) = delete; // assign using std::move()! PathOps(PathOps&& aOther) = default; PathOps& operator=(PathOps&& aOther) = default; template void Record(S& aStream) const; bool StreamToSink(PathSink& aPathSink) const; bool CheckedStreamToSink(PathSink& aPathSink) const; PathOps TransformedCopy(const Matrix& aTransform) const; size_t NumberOfOps() const; void MoveTo(const Point& aPoint) { AppendPathOp(OpType::OP_MOVETO, aPoint); } void LineTo(const Point& aPoint) { AppendPathOp(OpType::OP_LINETO, aPoint); } void BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3) { AppendPathOp(OpType::OP_BEZIERTO, ThreePoints{aCP1, aCP2, aCP3}); } void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) { AppendPathOp(OpType::OP_QUADRATICBEZIERTO, TwoPoints{aCP1, aCP2}); } void Arc(const Point& aOrigin, float aRadius, float aStartAngle, float aEndAngle, bool aAntiClockwise) { AppendPathOp(OpType::OP_ARC, ArcParams{aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise}); } void Close() { size_t oldSize = mPathData.size(); mPathData.resize(oldSize + sizeof(OpType)); *reinterpret_cast(mPathData.data() + oldSize) = OpType::OP_CLOSE; } Maybe AsCircle() const; Maybe AsLine() const; bool IsActive() const { return !mPathData.empty(); } bool IsEmpty() const; private: enum class OpType : uint32_t { OP_MOVETO = 0, OP_LINETO, OP_BEZIERTO, OP_QUADRATICBEZIERTO, OP_ARC, OP_CLOSE, OP_INVALID }; template void AppendPathOp(const OpType& aOpType, const T& aOpParams) { size_t oldSize = mPathData.size(); mPathData.resize(oldSize + sizeof(OpType) + sizeof(T)); memcpy(mPathData.data() + oldSize, &aOpType, sizeof(OpType)); oldSize += sizeof(OpType); memcpy(mPathData.data() + oldSize, &aOpParams, sizeof(T)); } struct TwoPoints { Point p1; Point p2; }; struct ThreePoints { Point p1; Point p2; Point p3; }; struct ArcParams { Point origin; float radius; float startAngle; float endAngle; bool antiClockwise; }; std::vector mPathData; }; template PathOps::PathOps(S& aStream) { ReadVector(aStream, mPathData); } template inline void PathOps::Record(S& aStream) const { WriteVector(aStream, mPathData); } class PathRecording; class DrawEventRecorderPrivate; class PathBuilderRecording final : public PathBuilder { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderRecording, override) PathBuilderRecording(BackendType aBackend, FillRule aFillRule) : mBackendType(aBackend), mFillRule(aFillRule) {} PathBuilderRecording(BackendType aBackend, PathOps&& aPathOps, FillRule aFillRule) : mBackendType(aBackend), mFillRule(aFillRule), mPathOps(std::move(aPathOps)) {} /* Move the current point in the path, any figure currently being drawn will * be considered closed during fill operations, however when stroking the * closing line segment will not be drawn. */ void MoveTo(const Point& aPoint) final; /* Add a linesegment to the current figure */ void LineTo(const Point& aPoint) final; /* Add a cubic bezier curve to the current figure */ void BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3) final; /* Add a quadratic bezier curve to the current figure */ void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) final; /* Close the current figure, this will essentially generate a line segment * from the current point to the starting point for the current figure */ void Close() final; /* Add an arc to the current figure */ void Arc(const Point& aOrigin, float aRadius, float aStartAngle, float aEndAngle, bool aAntiClockwise) final; already_AddRefed Finish() final; BackendType GetBackendType() const final { return BackendType::RECORDING; } bool IsActive() const final { return mPathOps.IsActive(); } private: BackendType mBackendType; FillRule mFillRule; PathOps mPathOps; }; class PathRecording final : public Path { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathRecording, override) PathRecording(BackendType aBackend, PathOps&& aOps, FillRule aFillRule, const Point& aCurrentPoint, const Point& aBeginPoint); ~PathRecording(); BackendType GetBackendType() const final { return BackendType::RECORDING; } already_AddRefed CopyToBuilder(FillRule aFillRule) const final; already_AddRefed TransformedCopyToBuilder( 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 AsRect() const final { EnsurePath(); return mPath->AsRect(); } Maybe AsCircle() const { return mPathOps.AsCircle(); } Maybe AsLine() const { return mPathOps.AsLine(); } void StreamToSink(PathSink* aSink) const final { mPathOps.StreamToSink(*aSink); } FillRule GetFillRule() const final { return mFillRule; } bool IsEmpty() const final { return mPathOps.IsEmpty(); } private: friend class DrawTargetWrapAndRecord; friend class DrawTargetRecording; friend class RecordedPathCreation; void EnsurePath() const; BackendType mBackendType; mutable RefPtr mPath; PathOps mPathOps; FillRule mFillRule; Point mCurrentPoint; Point mBeginPoint; // Event recorders that have this path in their event stream. std::vector> mStoredRecorders; }; } // namespace gfx } // namespace mozilla #endif /* MOZILLA_GFX_PATHRECORDING_H_ */