Bug 1890689 accumulate input in LargerReceiverBlockSizeThanDesiredBuffering GTest...
[gecko.git] / gfx / 2d / PathRecording.h
blobf804381cb1b24eaea5a0cc528fca3dc1497197c3
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MOZILLA_GFX_PATHRECORDING_H_
8 #define MOZILLA_GFX_PATHRECORDING_H_
10 #include "2D.h"
11 #include <vector>
12 #include <ostream>
14 #include "PathHelpers.h"
15 #include "RecordingTypes.h"
17 namespace mozilla {
18 namespace gfx {
20 struct Circle {
21 Point origin;
22 float radius;
23 bool closed = false;
26 struct Line {
27 Point origin;
28 Point destination;
31 class PathOps {
32 public:
33 PathOps() = default;
35 template <class S>
36 explicit PathOps(S& aStream);
38 PathOps(const PathOps& aOther) = default;
39 PathOps& operator=(const PathOps&) = delete; // assign using std::move()!
41 PathOps(PathOps&& aOther) = default;
42 PathOps& operator=(PathOps&& aOther) = default;
44 template <class S>
45 void Record(S& aStream) const;
47 bool StreamToSink(PathSink& aPathSink) const;
49 bool CheckedStreamToSink(PathSink& aPathSink) const;
51 PathOps TransformedCopy(const Matrix& aTransform) const;
53 size_t NumberOfOps() const;
55 void MoveTo(const Point& aPoint) { AppendPathOp(OpType::OP_MOVETO, aPoint); }
57 void LineTo(const Point& aPoint) { AppendPathOp(OpType::OP_LINETO, aPoint); }
59 void BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3) {
60 AppendPathOp(OpType::OP_BEZIERTO, ThreePoints{aCP1, aCP2, aCP3});
63 void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) {
64 AppendPathOp(OpType::OP_QUADRATICBEZIERTO, TwoPoints{aCP1, aCP2});
67 void Arc(const Point& aOrigin, float aRadius, float aStartAngle,
68 float aEndAngle, bool aAntiClockwise) {
69 AppendPathOp(OpType::OP_ARC, ArcParams{aOrigin, aRadius, aStartAngle,
70 aEndAngle, aAntiClockwise});
73 void Close() {
74 size_t oldSize = mPathData.size();
75 mPathData.resize(oldSize + sizeof(OpType));
76 *reinterpret_cast<OpType*>(mPathData.data() + oldSize) = OpType::OP_CLOSE;
79 Maybe<Circle> AsCircle() const;
80 Maybe<Line> AsLine() const;
82 bool IsActive() const { return !mPathData.empty(); }
84 bool IsEmpty() const;
86 private:
87 enum class OpType : uint32_t {
88 OP_MOVETO = 0,
89 OP_LINETO,
90 OP_BEZIERTO,
91 OP_QUADRATICBEZIERTO,
92 OP_ARC,
93 OP_CLOSE,
94 OP_INVALID
97 template <typename T>
98 void AppendPathOp(const OpType& aOpType, const T& aOpParams) {
99 size_t oldSize = mPathData.size();
100 mPathData.resize(oldSize + sizeof(OpType) + sizeof(T));
101 memcpy(mPathData.data() + oldSize, &aOpType, sizeof(OpType));
102 oldSize += sizeof(OpType);
103 memcpy(mPathData.data() + oldSize, &aOpParams, sizeof(T));
106 struct TwoPoints {
107 Point p1;
108 Point p2;
111 struct ThreePoints {
112 Point p1;
113 Point p2;
114 Point p3;
117 struct ArcParams {
118 Point origin;
119 float radius;
120 float startAngle;
121 float endAngle;
122 bool antiClockwise;
125 std::vector<uint8_t> mPathData;
128 template <class S>
129 PathOps::PathOps(S& aStream) {
130 ReadVector(aStream, mPathData);
133 template <class S>
134 inline void PathOps::Record(S& aStream) const {
135 WriteVector(aStream, mPathData);
138 class PathRecording;
139 class DrawEventRecorderPrivate;
141 class PathBuilderRecording final : public PathBuilder {
142 public:
143 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderRecording, override)
145 PathBuilderRecording(BackendType aBackend, FillRule aFillRule)
146 : mBackendType(aBackend), mFillRule(aFillRule) {}
148 PathBuilderRecording(BackendType aBackend, PathOps&& aPathOps,
149 FillRule aFillRule)
150 : mBackendType(aBackend),
151 mFillRule(aFillRule),
152 mPathOps(std::move(aPathOps)) {}
154 /* Move the current point in the path, any figure currently being drawn will
155 * be considered closed during fill operations, however when stroking the
156 * closing line segment will not be drawn.
158 void MoveTo(const Point& aPoint) final;
160 /* Add a linesegment to the current figure */
161 void LineTo(const Point& aPoint) final;
163 /* Add a cubic bezier curve to the current figure */
164 void BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3) final;
166 /* Add a quadratic bezier curve to the current figure */
167 void QuadraticBezierTo(const Point& aCP1, const Point& aCP2) final;
169 /* Close the current figure, this will essentially generate a line segment
170 * from the current point to the starting point for the current figure
172 void Close() final;
174 /* Add an arc to the current figure */
175 void Arc(const Point& aOrigin, float aRadius, float aStartAngle,
176 float aEndAngle, bool aAntiClockwise) final;
178 already_AddRefed<Path> Finish() final;
180 BackendType GetBackendType() const final { return BackendType::RECORDING; }
182 bool IsActive() const final { return mPathOps.IsActive(); }
184 private:
185 BackendType mBackendType;
186 FillRule mFillRule;
187 PathOps mPathOps;
190 class PathRecording final : public Path {
191 public:
192 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathRecording, override)
194 PathRecording(BackendType aBackend, PathOps&& aOps, FillRule aFillRule,
195 const Point& aCurrentPoint, const Point& aBeginPoint);
197 ~PathRecording();
199 BackendType GetBackendType() const final { return BackendType::RECORDING; }
200 already_AddRefed<PathBuilder> CopyToBuilder(FillRule aFillRule) const final;
201 already_AddRefed<PathBuilder> TransformedCopyToBuilder(
202 const Matrix& aTransform, FillRule aFillRule) const final;
203 bool ContainsPoint(const Point& aPoint,
204 const Matrix& aTransform) const final {
205 EnsurePath();
206 return mPath->ContainsPoint(aPoint, aTransform);
208 bool StrokeContainsPoint(const StrokeOptions& aStrokeOptions,
209 const Point& aPoint,
210 const Matrix& aTransform) const final {
211 EnsurePath();
212 return mPath->StrokeContainsPoint(aStrokeOptions, aPoint, aTransform);
215 Rect GetBounds(const Matrix& aTransform = Matrix()) const final {
216 EnsurePath();
217 return mPath->GetBounds(aTransform);
220 Rect GetStrokedBounds(const StrokeOptions& aStrokeOptions,
221 const Matrix& aTransform = Matrix()) const final {
222 EnsurePath();
223 return mPath->GetStrokedBounds(aStrokeOptions, aTransform);
226 Maybe<Rect> AsRect() const final {
227 EnsurePath();
228 return mPath->AsRect();
231 Maybe<Circle> AsCircle() const { return mPathOps.AsCircle(); }
232 Maybe<Line> AsLine() const { return mPathOps.AsLine(); }
234 void StreamToSink(PathSink* aSink) const final {
235 mPathOps.StreamToSink(*aSink);
238 FillRule GetFillRule() const final { return mFillRule; }
240 bool IsEmpty() const final { return mPathOps.IsEmpty(); }
242 private:
243 friend class DrawTargetWrapAndRecord;
244 friend class DrawTargetRecording;
245 friend class RecordedPathCreation;
247 void EnsurePath() const;
249 BackendType mBackendType;
250 mutable RefPtr<Path> mPath;
251 PathOps mPathOps;
252 FillRule mFillRule;
253 Point mCurrentPoint;
254 Point mBeginPoint;
256 // Event recorders that have this path in their event stream.
257 std::vector<RefPtr<DrawEventRecorderPrivate>> mStoredRecorders;
260 } // namespace gfx
261 } // namespace mozilla
263 #endif /* MOZILLA_GFX_PATHRECORDING_H_ */