Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "PathSkia.h"
7 : #include <math.h>
8 : #include "DrawTargetSkia.h"
9 : #include "Logging.h"
10 : #include "HelpersSkia.h"
11 : #include "PathHelpers.h"
12 :
13 : namespace mozilla {
14 : namespace gfx {
15 :
16 0 : PathBuilderSkia::PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath, FillRule aFillRule)
17 0 : : mPath(aPath)
18 : {
19 : SkMatrix matrix;
20 0 : GfxMatrixToSkiaMatrix(aTransform, matrix);
21 0 : mPath.transform(matrix);
22 0 : SetFillRule(aFillRule);
23 0 : }
24 :
25 112 : PathBuilderSkia::PathBuilderSkia(FillRule aFillRule)
26 : {
27 112 : SetFillRule(aFillRule);
28 112 : }
29 :
30 : void
31 112 : PathBuilderSkia::SetFillRule(FillRule aFillRule)
32 : {
33 112 : mFillRule = aFillRule;
34 112 : if (mFillRule == FillRule::FILL_WINDING) {
35 92 : mPath.setFillType(SkPath::kWinding_FillType);
36 : } else {
37 20 : mPath.setFillType(SkPath::kEvenOdd_FillType);
38 : }
39 112 : }
40 :
41 : void
42 217 : PathBuilderSkia::MoveTo(const Point &aPoint)
43 : {
44 217 : mPath.moveTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
45 217 : }
46 :
47 : void
48 870 : PathBuilderSkia::LineTo(const Point &aPoint)
49 : {
50 870 : if (!mPath.countPoints()) {
51 0 : MoveTo(aPoint);
52 : } else {
53 870 : mPath.lineTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
54 : }
55 870 : }
56 :
57 : void
58 648 : PathBuilderSkia::BezierTo(const Point &aCP1,
59 : const Point &aCP2,
60 : const Point &aCP3)
61 : {
62 648 : if (!mPath.countPoints()) {
63 0 : MoveTo(aCP1);
64 : }
65 648 : mPath.cubicTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
66 648 : SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y),
67 1296 : SkFloatToScalar(aCP3.x), SkFloatToScalar(aCP3.y));
68 648 : }
69 :
70 : void
71 0 : PathBuilderSkia::QuadraticBezierTo(const Point &aCP1,
72 : const Point &aCP2)
73 : {
74 0 : if (!mPath.countPoints()) {
75 0 : MoveTo(aCP1);
76 : }
77 0 : mPath.quadTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
78 0 : SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y));
79 0 : }
80 :
81 : void
82 216 : PathBuilderSkia::Close()
83 : {
84 216 : mPath.close();
85 216 : }
86 :
87 : void
88 0 : PathBuilderSkia::Arc(const Point &aOrigin, float aRadius, float aStartAngle,
89 : float aEndAngle, bool aAntiClockwise)
90 : {
91 0 : ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle, aAntiClockwise);
92 0 : }
93 :
94 : Point
95 0 : PathBuilderSkia::CurrentPoint() const
96 : {
97 0 : int pointCount = mPath.countPoints();
98 0 : if (!pointCount) {
99 0 : return Point(0, 0);
100 : }
101 0 : SkPoint point = mPath.getPoint(pointCount - 1);
102 0 : return Point(SkScalarToFloat(point.fX), SkScalarToFloat(point.fY));
103 : }
104 :
105 : already_AddRefed<Path>
106 112 : PathBuilderSkia::Finish()
107 : {
108 112 : return MakeAndAddRef<PathSkia>(mPath, mFillRule);
109 : }
110 :
111 : void
112 0 : PathBuilderSkia::AppendPath(const SkPath &aPath)
113 : {
114 0 : mPath.addPath(aPath);
115 0 : }
116 :
117 : already_AddRefed<PathBuilder>
118 0 : PathSkia::CopyToBuilder(FillRule aFillRule) const
119 : {
120 0 : return TransformedCopyToBuilder(Matrix(), aFillRule);
121 : }
122 :
123 : already_AddRefed<PathBuilder>
124 0 : PathSkia::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
125 : {
126 0 : return MakeAndAddRef<PathBuilderSkia>(aTransform, mPath, aFillRule);
127 : }
128 :
129 : static bool
130 0 : SkPathContainsPoint(const SkPath& aPath, const Point& aPoint, const Matrix& aTransform)
131 : {
132 0 : Matrix inverse = aTransform;
133 0 : if (!inverse.Invert()) {
134 0 : return false;
135 : }
136 :
137 0 : SkPoint point = PointToSkPoint(inverse.TransformPoint(aPoint));
138 0 : return aPath.contains(point.fX, point.fY);
139 : }
140 :
141 : bool
142 0 : PathSkia::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
143 : {
144 0 : if (!mPath.isFinite()) {
145 0 : return false;
146 : }
147 :
148 0 : return SkPathContainsPoint(mPath, aPoint, aTransform);
149 : }
150 :
151 : bool
152 0 : PathSkia::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
153 : const Point &aPoint,
154 : const Matrix &aTransform) const
155 : {
156 0 : if (!mPath.isFinite()) {
157 0 : return false;
158 : }
159 :
160 0 : SkPaint paint;
161 0 : if (!StrokeOptionsToPaint(paint, aStrokeOptions)) {
162 0 : return false;
163 : }
164 :
165 0 : SkPath strokePath;
166 0 : paint.getFillPath(mPath, &strokePath);
167 :
168 0 : return SkPathContainsPoint(strokePath, aPoint, aTransform);
169 : }
170 :
171 : Rect
172 98 : PathSkia::GetBounds(const Matrix &aTransform) const
173 : {
174 98 : if (!mPath.isFinite()) {
175 0 : return Rect();
176 : }
177 :
178 98 : Rect bounds = SkRectToRect(mPath.computeTightBounds());
179 98 : return aTransform.TransformBounds(bounds);
180 : }
181 :
182 : Rect
183 0 : PathSkia::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
184 : const Matrix &aTransform) const
185 : {
186 0 : if (!mPath.isFinite()) {
187 0 : return Rect();
188 : }
189 :
190 0 : SkPaint paint;
191 0 : if (!StrokeOptionsToPaint(paint, aStrokeOptions)) {
192 0 : return Rect();
193 : }
194 :
195 0 : SkPath result;
196 0 : paint.getFillPath(mPath, &result);
197 :
198 0 : Rect bounds = SkRectToRect(result.computeTightBounds());
199 0 : return aTransform.TransformBounds(bounds);
200 : }
201 :
202 : void
203 6 : PathSkia::StreamToSink(PathSink *aSink) const
204 : {
205 6 : SkPath::RawIter iter(mPath);
206 :
207 : SkPoint points[4];
208 : SkPath::Verb currentVerb;
209 286 : while ((currentVerb = iter.next(points)) != SkPath::kDone_Verb) {
210 140 : switch (currentVerb) {
211 : case SkPath::kMove_Verb:
212 28 : aSink->MoveTo(SkPointToPoint(points[0]));
213 28 : break;
214 : case SkPath::kLine_Verb:
215 84 : aSink->LineTo(SkPointToPoint(points[1]));
216 84 : break;
217 : case SkPath::kCubic_Verb:
218 0 : aSink->BezierTo(SkPointToPoint(points[1]),
219 0 : SkPointToPoint(points[2]),
220 0 : SkPointToPoint(points[3]));
221 0 : break;
222 : case SkPath::kQuad_Verb:
223 0 : aSink->QuadraticBezierTo(SkPointToPoint(points[1]),
224 0 : SkPointToPoint(points[2]));
225 0 : break;
226 : case SkPath::kClose_Verb:
227 28 : aSink->Close();
228 28 : break;
229 : default:
230 0 : MOZ_ASSERT(false);
231 : // Unexpected verb found in path!
232 : }
233 : }
234 6 : }
235 :
236 : } // namespace gfx
237 : } // namespace mozilla
|