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"
12 void PathBuilderCapture::MoveTo(const Point
& aPoint
) {
14 op
.mType
= PathOp::OP_MOVETO
;
16 mPathOps
.push_back(op
);
17 mCurrentPoint
= aPoint
;
21 void PathBuilderCapture::LineTo(const Point
& aPoint
) {
23 op
.mType
= PathOp::OP_LINETO
;
25 mPathOps
.push_back(op
);
26 mCurrentPoint
= aPoint
;
29 void PathBuilderCapture::BezierTo(const Point
& aCP1
, const Point
& aCP2
,
32 op
.mType
= PathOp::OP_BEZIERTO
;
36 mPathOps
.push_back(op
);
40 void PathBuilderCapture::QuadraticBezierTo(const Point
& aCP1
,
43 op
.mType
= PathOp::OP_QUADRATICBEZIERTO
;
46 mPathOps
.push_back(op
);
50 void PathBuilderCapture::Arc(const Point
& aCenter
, float aRadius
,
51 float aStartAngle
, float aEndAngle
,
52 bool aAntiClockwise
) {
54 op
.mType
= PathOp::OP_ARC
;
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() {
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
++) {
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
) {
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
) {
112 newPathOp
.mType
= PathOp::OP_LINETO
;
113 newPathOp
.mP1
= mTransform
->TransformPoint(aPoint
);
114 mVector
->push_back(newPathOp
);
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
);
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()) {
146 return mRealizedPath
->ContainsPoint(aPoint
, aTransform
);
149 bool PathCapture::StrokeContainsPoint(const StrokeOptions
& aStrokeOptions
,
151 const Matrix
& aTransform
) const {
152 if (!EnsureRealizedPath()) {
155 return mRealizedPath
->StrokeContainsPoint(aStrokeOptions
, aPoint
, aTransform
);
158 Rect
PathCapture::GetBounds(const Matrix
& aTransform
) const {
159 if (!EnsureRealizedPath()) {
162 return mRealizedPath
->GetBounds(aTransform
);
165 Rect
PathCapture::GetStrokedBounds(const StrokeOptions
& aStrokeOptions
,
166 const Matrix
& aTransform
) const {
167 if (!EnsureRealizedPath()) {
170 return mRealizedPath
->GetStrokedBounds(aStrokeOptions
, aTransform
);
173 void PathCapture::StreamToSink(PathSink
* aSink
) const {
174 for (const PathOp
& op
: mPathOps
) {
176 case PathOp::OP_MOVETO
:
177 aSink
->MoveTo(op
.mP1
);
179 case PathOp::OP_LINETO
:
180 aSink
->LineTo(op
.mP1
);
182 case PathOp::OP_BEZIERTO
:
183 aSink
->BezierTo(op
.mP1
, op
.mP2
, op
.mP3
);
185 case PathOp::OP_QUADRATICBEZIERTO
:
186 aSink
->QuadraticBezierTo(op
.mP1
, op
.mP2
);
189 aSink
->Arc(op
.mP1
, op
.mRadius
, op
.mStartAngle
, op
.mEndAngle
,
192 case PathOp::OP_CLOSE
:
199 bool PathCapture::EnsureRealizedPath() const {
200 RefPtr
<PathBuilder
> builder
= mDT
->CreatePathBuilder(mFillRule
);
204 StreamToSink(builder
);
205 mRealizedPath
= builder
->Finish();
209 Path
* PathCapture::GetRealizedPath() const {
210 if (!EnsureRealizedPath()) {
214 return mRealizedPath
.get();
218 } // namespace mozilla