Bug 1735097 - Geolocation: use EpochTimeStamp instead of DOMTimeStamp r=saschanaz...
[gecko.git] / gfx / 2d / PathSkia.cpp
bloba25f0c3a20e54844e2bfac01e82220a531891199
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 "PathSkia.h"
8 #include <math.h>
9 #include "DrawTargetSkia.h"
10 #include "Logging.h"
11 #include "HelpersSkia.h"
12 #include "PathHelpers.h"
13 #include "skia/src/core/SkDraw.h"
15 namespace mozilla::gfx {
17 PathBuilderSkia::PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath,
18 FillRule aFillRule)
19 : mPath(aPath) {
20 SkMatrix matrix;
21 GfxMatrixToSkiaMatrix(aTransform, matrix);
22 mPath.transform(matrix);
23 SetFillRule(aFillRule);
26 PathBuilderSkia::PathBuilderSkia(FillRule aFillRule) { SetFillRule(aFillRule); }
28 void PathBuilderSkia::SetFillRule(FillRule aFillRule) {
29 mFillRule = aFillRule;
30 if (mFillRule == FillRule::FILL_WINDING) {
31 mPath.setFillType(SkPath::kWinding_FillType);
32 } else {
33 mPath.setFillType(SkPath::kEvenOdd_FillType);
37 void PathBuilderSkia::MoveTo(const Point& aPoint) {
38 mPath.moveTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
39 mCurrentPoint = aPoint;
40 mBeginPoint = aPoint;
43 void PathBuilderSkia::LineTo(const Point& aPoint) {
44 if (!mPath.countPoints()) {
45 MoveTo(aPoint);
46 } else {
47 mPath.lineTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
49 mCurrentPoint = aPoint;
52 void PathBuilderSkia::BezierTo(const Point& aCP1, const Point& aCP2,
53 const Point& aCP3) {
54 if (!mPath.countPoints()) {
55 MoveTo(aCP1);
57 mPath.cubicTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
58 SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y),
59 SkFloatToScalar(aCP3.x), SkFloatToScalar(aCP3.y));
60 mCurrentPoint = aCP3;
63 void PathBuilderSkia::QuadraticBezierTo(const Point& aCP1, const Point& aCP2) {
64 if (!mPath.countPoints()) {
65 MoveTo(aCP1);
67 mPath.quadTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
68 SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y));
69 mCurrentPoint = aCP2;
72 void PathBuilderSkia::Close() {
73 mPath.close();
74 mCurrentPoint = mBeginPoint;
77 void PathBuilderSkia::Arc(const Point& aOrigin, float aRadius,
78 float aStartAngle, float aEndAngle,
79 bool aAntiClockwise) {
80 ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle,
81 aAntiClockwise);
84 already_AddRefed<Path> PathBuilderSkia::Finish() {
85 RefPtr<Path> path =
86 MakeAndAddRef<PathSkia>(mPath, mFillRule, mCurrentPoint, mBeginPoint);
87 mCurrentPoint = Point(0.0, 0.0);
88 mBeginPoint = Point(0.0, 0.0);
89 return path.forget();
92 void PathBuilderSkia::AppendPath(const SkPath& aPath) { mPath.addPath(aPath); }
94 already_AddRefed<PathBuilder> PathSkia::CopyToBuilder(
95 FillRule aFillRule) const {
96 return TransformedCopyToBuilder(Matrix(), aFillRule);
99 already_AddRefed<PathBuilder> PathSkia::TransformedCopyToBuilder(
100 const Matrix& aTransform, FillRule aFillRule) const {
101 RefPtr<PathBuilderSkia> builder =
102 MakeAndAddRef<PathBuilderSkia>(aTransform, mPath, aFillRule);
104 builder->mCurrentPoint = aTransform.TransformPoint(mCurrentPoint);
105 builder->mBeginPoint = aTransform.TransformPoint(mBeginPoint);
107 return builder.forget();
110 static bool SkPathContainsPoint(const SkPath& aPath, const Point& aPoint,
111 const Matrix& aTransform) {
112 Matrix inverse = aTransform;
113 if (!inverse.Invert()) {
114 return false;
117 SkPoint point = PointToSkPoint(inverse.TransformPoint(aPoint));
118 return aPath.contains(point.fX, point.fY);
121 bool PathSkia::ContainsPoint(const Point& aPoint,
122 const Matrix& aTransform) const {
123 if (!mPath.isFinite()) {
124 return false;
127 return SkPathContainsPoint(mPath, aPoint, aTransform);
130 bool PathSkia::StrokeContainsPoint(const StrokeOptions& aStrokeOptions,
131 const Point& aPoint,
132 const Matrix& aTransform) const {
133 if (!mPath.isFinite()) {
134 return false;
137 SkPaint paint;
138 if (!StrokeOptionsToPaint(paint, aStrokeOptions)) {
139 return false;
142 SkMatrix skiaMatrix;
143 GfxMatrixToSkiaMatrix(aTransform, skiaMatrix);
144 SkPath strokePath;
145 paint.getFillPath(mPath, &strokePath, nullptr,
146 SkDraw::ComputeResScaleForStroking(skiaMatrix));
148 return SkPathContainsPoint(strokePath, aPoint, aTransform);
151 Rect PathSkia::GetBounds(const Matrix& aTransform) const {
152 if (!mPath.isFinite()) {
153 return Rect();
156 Rect bounds = SkRectToRect(mPath.computeTightBounds());
157 return aTransform.TransformBounds(bounds);
160 Rect PathSkia::GetStrokedBounds(const StrokeOptions& aStrokeOptions,
161 const Matrix& aTransform) const {
162 if (!mPath.isFinite()) {
163 return Rect();
166 SkPaint paint;
167 if (!StrokeOptionsToPaint(paint, aStrokeOptions)) {
168 return Rect();
171 SkPath result;
172 paint.getFillPath(mPath, &result);
174 Rect bounds = SkRectToRect(result.computeTightBounds());
175 return aTransform.TransformBounds(bounds);
178 void PathSkia::StreamToSink(PathSink* aSink) const {
179 SkPath::RawIter iter(mPath);
181 SkPoint points[4];
182 SkPath::Verb currentVerb;
183 while ((currentVerb = iter.next(points)) != SkPath::kDone_Verb) {
184 switch (currentVerb) {
185 case SkPath::kMove_Verb:
186 aSink->MoveTo(SkPointToPoint(points[0]));
187 break;
188 case SkPath::kLine_Verb:
189 aSink->LineTo(SkPointToPoint(points[1]));
190 break;
191 case SkPath::kCubic_Verb:
192 aSink->BezierTo(SkPointToPoint(points[1]), SkPointToPoint(points[2]),
193 SkPointToPoint(points[3]));
194 break;
195 case SkPath::kQuad_Verb:
196 aSink->QuadraticBezierTo(SkPointToPoint(points[1]),
197 SkPointToPoint(points[2]));
198 break;
199 case SkPath::kClose_Verb:
200 aSink->Close();
201 break;
202 default:
203 MOZ_ASSERT(false);
204 // Unexpected verb found in path!
209 } // namespace mozilla::gfx