Bug 1686668 [wpt PR 27185] - Update wpt metadata, a=testonly
[gecko.git] / gfx / 2d / PathCapture.cpp
blobd45693b535d4e31980ced6373ce0f31d432cb2a6
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 #include "PathCapture.h"
9 namespace mozilla {
10 namespace gfx {
12 void PathBuilderCapture::MoveTo(const Point& aPoint) {
13 PathOp op;
14 op.mType = PathOp::OP_MOVETO;
15 op.mP1 = aPoint;
16 mPathOps.push_back(op);
17 mCurrentPoint = aPoint;
18 mBeginPoint = aPoint;
21 void PathBuilderCapture::LineTo(const Point& aPoint) {
22 PathOp op;
23 op.mType = PathOp::OP_LINETO;
24 op.mP1 = aPoint;
25 mPathOps.push_back(op);
26 mCurrentPoint = aPoint;
29 void PathBuilderCapture::BezierTo(const Point& aCP1, const Point& aCP2,
30 const Point& aCP3) {
31 PathOp op;
32 op.mType = PathOp::OP_BEZIERTO;
33 op.mP1 = aCP1;
34 op.mP2 = aCP2;
35 op.mP3 = aCP3;
36 mPathOps.push_back(op);
37 mCurrentPoint = aCP3;
40 void PathBuilderCapture::QuadraticBezierTo(const Point& aCP1,
41 const Point& aCP2) {
42 PathOp op;
43 op.mType = PathOp::OP_QUADRATICBEZIERTO;
44 op.mP1 = aCP1;
45 op.mP2 = aCP2;
46 mPathOps.push_back(op);
47 mCurrentPoint = aCP2;
50 void PathBuilderCapture::Arc(const Point& aCenter, float aRadius,
51 float aStartAngle, float aEndAngle,
52 bool aAntiClockwise) {
53 PathOp op;
54 op.mType = PathOp::OP_ARC;
55 op.mP1 = aCenter;
56 op.mRadius = aRadius;
57 op.mStartAngle = aStartAngle;
58 op.mEndAngle = aEndAngle;
59 op.mAntiClockwise = aAntiClockwise;
60 mPathOps.push_back(op);
61 mCurrentPoint = Point(aCenter.x + aRadius * cosf(aEndAngle),
62 aCenter.y + aRadius * sinf(aEndAngle));
65 void PathBuilderCapture::Close() {
66 PathOp op;
67 op.mType = PathOp::OP_CLOSE;
68 mPathOps.push_back(op);
69 mCurrentPoint = mBeginPoint;
72 already_AddRefed<Path> PathBuilderCapture::Finish() {
73 Point currentPoint = mCurrentPoint;
74 Point beginPoint = mBeginPoint;
75 mCurrentPoint = Point(0.0, 0.0);
76 mBeginPoint = Point(0.0, 0.0);
77 return MakeAndAddRef<PathCapture>(std::move(mPathOps), mFillRule, mDT,
78 currentPoint, beginPoint);
81 already_AddRefed<PathBuilder> PathCapture::CopyToBuilder(
82 FillRule aFillRule) const {
83 RefPtr<PathBuilderCapture> capture = new PathBuilderCapture(aFillRule, mDT);
84 capture->mPathOps = mPathOps;
85 capture->mCurrentPoint = mCurrentPoint;
86 capture->mBeginPoint = mBeginPoint;
87 return capture.forget();
90 already_AddRefed<PathBuilder> PathCapture::TransformedCopyToBuilder(
91 const Matrix& aTransform, FillRule aFillRule) const {
92 RefPtr<PathBuilderCapture> capture = new PathBuilderCapture(aFillRule, mDT);
93 typedef std::vector<PathOp> pathOpVec;
94 for (pathOpVec::const_iterator iter = mPathOps.begin();
95 iter != mPathOps.end(); iter++) {
96 PathOp newPathOp;
97 newPathOp.mType = iter->mType;
98 if (newPathOp.mType == PathOp::OpType::OP_ARC) {
99 struct ArcTransformer {
100 ArcTransformer(pathOpVec& aVector, const Matrix& aTransform)
101 : mVector(&aVector), mTransform(&aTransform) {}
102 void BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3) {
103 PathOp newPathOp;
104 newPathOp.mType = PathOp::OP_BEZIERTO;
105 newPathOp.mP1 = mTransform->TransformPoint(aCP1);
106 newPathOp.mP2 = mTransform->TransformPoint(aCP2);
107 newPathOp.mP3 = mTransform->TransformPoint(aCP3);
108 mVector->push_back(newPathOp);
110 void LineTo(const Point& aPoint) {
111 PathOp newPathOp;
112 newPathOp.mType = PathOp::OP_LINETO;
113 newPathOp.mP1 = mTransform->TransformPoint(aPoint);
114 mVector->push_back(newPathOp);
116 pathOpVec* mVector;
117 const Matrix* mTransform;
120 ArcTransformer arcTransformer(capture->mPathOps, aTransform);
121 ArcToBezier(&arcTransformer, iter->mP1,
122 Size(iter->mRadius, iter->mRadius), iter->mStartAngle,
123 iter->mEndAngle, iter->mAntiClockwise);
124 } else {
125 if (sPointCount[newPathOp.mType] >= 1) {
126 newPathOp.mP1 = aTransform.TransformPoint(iter->mP1);
128 if (sPointCount[newPathOp.mType] >= 2) {
129 newPathOp.mP2 = aTransform.TransformPoint(iter->mP2);
131 if (sPointCount[newPathOp.mType] >= 3) {
132 newPathOp.mP3 = aTransform.TransformPoint(iter->mP3);
134 capture->mPathOps.push_back(newPathOp);
137 capture->mCurrentPoint = aTransform.TransformPoint(mCurrentPoint);
138 capture->mBeginPoint = aTransform.TransformPoint(mBeginPoint);
139 return capture.forget();
141 bool PathCapture::ContainsPoint(const Point& aPoint,
142 const Matrix& aTransform) const {
143 if (!EnsureRealizedPath()) {
144 return false;
146 return mRealizedPath->ContainsPoint(aPoint, aTransform);
149 bool PathCapture::StrokeContainsPoint(const StrokeOptions& aStrokeOptions,
150 const Point& aPoint,
151 const Matrix& aTransform) const {
152 if (!EnsureRealizedPath()) {
153 return false;
155 return mRealizedPath->StrokeContainsPoint(aStrokeOptions, aPoint, aTransform);
158 Rect PathCapture::GetBounds(const Matrix& aTransform) const {
159 if (!EnsureRealizedPath()) {
160 return Rect();
162 return mRealizedPath->GetBounds(aTransform);
165 Rect PathCapture::GetStrokedBounds(const StrokeOptions& aStrokeOptions,
166 const Matrix& aTransform) const {
167 if (!EnsureRealizedPath()) {
168 return Rect();
170 return mRealizedPath->GetStrokedBounds(aStrokeOptions, aTransform);
173 void PathCapture::StreamToSink(PathSink* aSink) const {
174 for (const PathOp& op : mPathOps) {
175 switch (op.mType) {
176 case PathOp::OP_MOVETO:
177 aSink->MoveTo(op.mP1);
178 break;
179 case PathOp::OP_LINETO:
180 aSink->LineTo(op.mP1);
181 break;
182 case PathOp::OP_BEZIERTO:
183 aSink->BezierTo(op.mP1, op.mP2, op.mP3);
184 break;
185 case PathOp::OP_QUADRATICBEZIERTO:
186 aSink->QuadraticBezierTo(op.mP1, op.mP2);
187 break;
188 case PathOp::OP_ARC:
189 aSink->Arc(op.mP1, op.mRadius, op.mStartAngle, op.mEndAngle,
190 op.mAntiClockwise);
191 break;
192 case PathOp::OP_CLOSE:
193 aSink->Close();
194 break;
199 bool PathCapture::EnsureRealizedPath() const {
200 RefPtr<PathBuilder> builder = mDT->CreatePathBuilder(mFillRule);
201 if (!builder) {
202 return false;
204 StreamToSink(builder);
205 mRealizedPath = builder->Finish();
206 return true;
209 Path* PathCapture::GetRealizedPath() const {
210 if (!EnsureRealizedPath()) {
211 return nullptr;
214 return mRealizedPath.get();
217 } // namespace gfx
218 } // namespace mozilla