Bumping manifests a=b2g-bump
[gecko.git] / gfx / 2d / PathSkia.cpp
blobefa0c6f56b45f4760c0942c1e1e27fff6307630e
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/. */
6 #include "PathSkia.h"
7 #include <math.h>
8 #include "DrawTargetSkia.h"
9 #include "Logging.h"
10 #include "HelpersSkia.h"
11 #include "PathHelpers.h"
13 namespace mozilla {
14 namespace gfx {
16 PathBuilderSkia::PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath, FillRule aFillRule)
17 : mPath(aPath)
19 SkMatrix matrix;
20 GfxMatrixToSkiaMatrix(aTransform, matrix);
21 mPath.transform(matrix);
22 SetFillRule(aFillRule);
25 PathBuilderSkia::PathBuilderSkia(FillRule aFillRule)
27 SetFillRule(aFillRule);
30 void
31 PathBuilderSkia::SetFillRule(FillRule aFillRule)
33 mFillRule = aFillRule;
34 if (mFillRule == FillRule::FILL_WINDING) {
35 mPath.setFillType(SkPath::kWinding_FillType);
36 } else {
37 mPath.setFillType(SkPath::kEvenOdd_FillType);
41 void
42 PathBuilderSkia::MoveTo(const Point &aPoint)
44 mPath.moveTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
47 void
48 PathBuilderSkia::LineTo(const Point &aPoint)
50 if (!mPath.countPoints()) {
51 MoveTo(aPoint);
52 } else {
53 mPath.lineTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
57 void
58 PathBuilderSkia::BezierTo(const Point &aCP1,
59 const Point &aCP2,
60 const Point &aCP3)
62 if (!mPath.countPoints()) {
63 MoveTo(aCP1);
65 mPath.cubicTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
66 SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y),
67 SkFloatToScalar(aCP3.x), SkFloatToScalar(aCP3.y));
70 void
71 PathBuilderSkia::QuadraticBezierTo(const Point &aCP1,
72 const Point &aCP2)
74 if (!mPath.countPoints()) {
75 MoveTo(aCP1);
77 mPath.quadTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
78 SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y));
81 void
82 PathBuilderSkia::Close()
84 mPath.close();
87 void
88 PathBuilderSkia::Arc(const Point &aOrigin, float aRadius, float aStartAngle,
89 float aEndAngle, bool aAntiClockwise)
91 ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle, aAntiClockwise);
94 Point
95 PathBuilderSkia::CurrentPoint() const
97 int pointCount = mPath.countPoints();
98 if (!pointCount) {
99 return Point(0, 0);
101 SkPoint point = mPath.getPoint(pointCount - 1);
102 return Point(SkScalarToFloat(point.fX), SkScalarToFloat(point.fY));
105 TemporaryRef<Path>
106 PathBuilderSkia::Finish()
108 return new PathSkia(mPath, mFillRule);
111 void
112 PathBuilderSkia::AppendPath(const SkPath &aPath)
114 mPath.addPath(aPath);
117 TemporaryRef<PathBuilder>
118 PathSkia::CopyToBuilder(FillRule aFillRule) const
120 return TransformedCopyToBuilder(Matrix(), aFillRule);
123 TemporaryRef<PathBuilder>
124 PathSkia::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
126 return new PathBuilderSkia(aTransform, mPath, aFillRule);
129 bool
130 PathSkia::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
132 Matrix inverse = aTransform;
133 inverse.Invert();
134 Point transformed = inverse * aPoint;
136 Rect bounds = GetBounds(aTransform);
138 if (aPoint.x < bounds.x || aPoint.y < bounds.y ||
139 aPoint.x > bounds.XMost() || aPoint.y > bounds.YMost()) {
140 return false;
143 SkRegion pointRect;
144 pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1.f)),
145 int32_t(SkFloatToScalar(transformed.y - 1.f)),
146 int32_t(SkFloatToScalar(transformed.x + 1.f)),
147 int32_t(SkFloatToScalar(transformed.y + 1.f)));
149 SkRegion pathRegion;
151 return pathRegion.setPath(mPath, pointRect);
154 bool
155 PathSkia::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
156 const Point &aPoint,
157 const Matrix &aTransform) const
159 Matrix inverse = aTransform;
160 inverse.Invert();
161 Point transformed = inverse * aPoint;
163 SkPaint paint;
164 StrokeOptionsToPaint(paint, aStrokeOptions);
166 SkPath strokePath;
167 paint.getFillPath(mPath, &strokePath);
169 Rect bounds = aTransform.TransformBounds(SkRectToRect(strokePath.getBounds()));
171 if (aPoint.x < bounds.x || aPoint.y < bounds.y ||
172 aPoint.x > bounds.XMost() || aPoint.y > bounds.YMost()) {
173 return false;
176 SkRegion pointRect;
177 pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1.f)),
178 int32_t(SkFloatToScalar(transformed.y - 1.f)),
179 int32_t(SkFloatToScalar(transformed.x + 1.f)),
180 int32_t(SkFloatToScalar(transformed.y + 1.f)));
182 SkRegion pathRegion;
184 return pathRegion.setPath(strokePath, pointRect);
187 Rect
188 PathSkia::GetBounds(const Matrix &aTransform) const
190 Rect bounds = SkRectToRect(mPath.getBounds());
191 return aTransform.TransformBounds(bounds);
194 Rect
195 PathSkia::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
196 const Matrix &aTransform) const
198 SkPaint paint;
199 StrokeOptionsToPaint(paint, aStrokeOptions);
201 SkPath result;
202 paint.getFillPath(mPath, &result);
204 Rect bounds = SkRectToRect(result.getBounds());
205 return aTransform.TransformBounds(bounds);
208 void
209 PathSkia::StreamToSink(PathSink *aSink) const
211 SkPath::RawIter iter(mPath);
213 SkPoint points[4];
214 SkPath::Verb currentVerb;
215 while ((currentVerb = iter.next(points)) != SkPath::kDone_Verb) {
216 switch (currentVerb) {
217 case SkPath::kMove_Verb:
218 aSink->MoveTo(SkPointToPoint(points[0]));
219 break;
220 case SkPath::kLine_Verb:
221 aSink->LineTo(SkPointToPoint(points[1]));
222 break;
223 case SkPath::kCubic_Verb:
224 aSink->BezierTo(SkPointToPoint(points[1]),
225 SkPointToPoint(points[2]),
226 SkPointToPoint(points[3]));
227 break;
228 case SkPath::kQuad_Verb:
229 aSink->QuadraticBezierTo(SkPointToPoint(points[1]),
230 SkPointToPoint(points[2]));
231 break;
232 case SkPath::kClose_Verb:
233 aSink->Close();
234 break;
235 default:
236 MOZ_ASSERT(false);
237 // Unexpected verb found in path!