summaryrefslogtreecommitdiffstats
path: root/gfx/2d/PathSkia.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/2d/PathSkia.cpp
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/2d/PathSkia.cpp')
-rw-r--r--gfx/2d/PathSkia.cpp209
1 files changed, 209 insertions, 0 deletions
diff --git a/gfx/2d/PathSkia.cpp b/gfx/2d/PathSkia.cpp
new file mode 100644
index 0000000000..a25f0c3a20
--- /dev/null
+++ b/gfx/2d/PathSkia.cpp
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PathSkia.h"
+#include <math.h>
+#include "DrawTargetSkia.h"
+#include "Logging.h"
+#include "HelpersSkia.h"
+#include "PathHelpers.h"
+#include "skia/src/core/SkDraw.h"
+
+namespace mozilla::gfx {
+
+PathBuilderSkia::PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath,
+ FillRule aFillRule)
+ : mPath(aPath) {
+ SkMatrix matrix;
+ GfxMatrixToSkiaMatrix(aTransform, matrix);
+ mPath.transform(matrix);
+ SetFillRule(aFillRule);
+}
+
+PathBuilderSkia::PathBuilderSkia(FillRule aFillRule) { SetFillRule(aFillRule); }
+
+void PathBuilderSkia::SetFillRule(FillRule aFillRule) {
+ mFillRule = aFillRule;
+ if (mFillRule == FillRule::FILL_WINDING) {
+ mPath.setFillType(SkPath::kWinding_FillType);
+ } else {
+ mPath.setFillType(SkPath::kEvenOdd_FillType);
+ }
+}
+
+void PathBuilderSkia::MoveTo(const Point& aPoint) {
+ mPath.moveTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
+ mCurrentPoint = aPoint;
+ mBeginPoint = aPoint;
+}
+
+void PathBuilderSkia::LineTo(const Point& aPoint) {
+ if (!mPath.countPoints()) {
+ MoveTo(aPoint);
+ } else {
+ mPath.lineTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
+ }
+ mCurrentPoint = aPoint;
+}
+
+void PathBuilderSkia::BezierTo(const Point& aCP1, const Point& aCP2,
+ const Point& aCP3) {
+ if (!mPath.countPoints()) {
+ MoveTo(aCP1);
+ }
+ mPath.cubicTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
+ SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y),
+ SkFloatToScalar(aCP3.x), SkFloatToScalar(aCP3.y));
+ mCurrentPoint = aCP3;
+}
+
+void PathBuilderSkia::QuadraticBezierTo(const Point& aCP1, const Point& aCP2) {
+ if (!mPath.countPoints()) {
+ MoveTo(aCP1);
+ }
+ mPath.quadTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
+ SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y));
+ mCurrentPoint = aCP2;
+}
+
+void PathBuilderSkia::Close() {
+ mPath.close();
+ mCurrentPoint = mBeginPoint;
+}
+
+void PathBuilderSkia::Arc(const Point& aOrigin, float aRadius,
+ float aStartAngle, float aEndAngle,
+ bool aAntiClockwise) {
+ ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle,
+ aAntiClockwise);
+}
+
+already_AddRefed<Path> PathBuilderSkia::Finish() {
+ RefPtr<Path> path =
+ MakeAndAddRef<PathSkia>(mPath, mFillRule, mCurrentPoint, mBeginPoint);
+ mCurrentPoint = Point(0.0, 0.0);
+ mBeginPoint = Point(0.0, 0.0);
+ return path.forget();
+}
+
+void PathBuilderSkia::AppendPath(const SkPath& aPath) { mPath.addPath(aPath); }
+
+already_AddRefed<PathBuilder> PathSkia::CopyToBuilder(
+ FillRule aFillRule) const {
+ return TransformedCopyToBuilder(Matrix(), aFillRule);
+}
+
+already_AddRefed<PathBuilder> PathSkia::TransformedCopyToBuilder(
+ const Matrix& aTransform, FillRule aFillRule) const {
+ RefPtr<PathBuilderSkia> builder =
+ MakeAndAddRef<PathBuilderSkia>(aTransform, mPath, aFillRule);
+
+ builder->mCurrentPoint = aTransform.TransformPoint(mCurrentPoint);
+ builder->mBeginPoint = aTransform.TransformPoint(mBeginPoint);
+
+ return builder.forget();
+}
+
+static bool SkPathContainsPoint(const SkPath& aPath, const Point& aPoint,
+ const Matrix& aTransform) {
+ Matrix inverse = aTransform;
+ if (!inverse.Invert()) {
+ return false;
+ }
+
+ SkPoint point = PointToSkPoint(inverse.TransformPoint(aPoint));
+ return aPath.contains(point.fX, point.fY);
+}
+
+bool PathSkia::ContainsPoint(const Point& aPoint,
+ const Matrix& aTransform) const {
+ if (!mPath.isFinite()) {
+ return false;
+ }
+
+ return SkPathContainsPoint(mPath, aPoint, aTransform);
+}
+
+bool PathSkia::StrokeContainsPoint(const StrokeOptions& aStrokeOptions,
+ const Point& aPoint,
+ const Matrix& aTransform) const {
+ if (!mPath.isFinite()) {
+ return false;
+ }
+
+ SkPaint paint;
+ if (!StrokeOptionsToPaint(paint, aStrokeOptions)) {
+ return false;
+ }
+
+ SkMatrix skiaMatrix;
+ GfxMatrixToSkiaMatrix(aTransform, skiaMatrix);
+ SkPath strokePath;
+ paint.getFillPath(mPath, &strokePath, nullptr,
+ SkDraw::ComputeResScaleForStroking(skiaMatrix));
+
+ return SkPathContainsPoint(strokePath, aPoint, aTransform);
+}
+
+Rect PathSkia::GetBounds(const Matrix& aTransform) const {
+ if (!mPath.isFinite()) {
+ return Rect();
+ }
+
+ Rect bounds = SkRectToRect(mPath.computeTightBounds());
+ return aTransform.TransformBounds(bounds);
+}
+
+Rect PathSkia::GetStrokedBounds(const StrokeOptions& aStrokeOptions,
+ const Matrix& aTransform) const {
+ if (!mPath.isFinite()) {
+ return Rect();
+ }
+
+ SkPaint paint;
+ if (!StrokeOptionsToPaint(paint, aStrokeOptions)) {
+ return Rect();
+ }
+
+ SkPath result;
+ paint.getFillPath(mPath, &result);
+
+ Rect bounds = SkRectToRect(result.computeTightBounds());
+ return aTransform.TransformBounds(bounds);
+}
+
+void PathSkia::StreamToSink(PathSink* aSink) const {
+ SkPath::RawIter iter(mPath);
+
+ SkPoint points[4];
+ SkPath::Verb currentVerb;
+ while ((currentVerb = iter.next(points)) != SkPath::kDone_Verb) {
+ switch (currentVerb) {
+ case SkPath::kMove_Verb:
+ aSink->MoveTo(SkPointToPoint(points[0]));
+ break;
+ case SkPath::kLine_Verb:
+ aSink->LineTo(SkPointToPoint(points[1]));
+ break;
+ case SkPath::kCubic_Verb:
+ aSink->BezierTo(SkPointToPoint(points[1]), SkPointToPoint(points[2]),
+ SkPointToPoint(points[3]));
+ break;
+ case SkPath::kQuad_Verb:
+ aSink->QuadraticBezierTo(SkPointToPoint(points[1]),
+ SkPointToPoint(points[2]));
+ break;
+ case SkPath::kClose_Verb:
+ aSink->Close();
+ break;
+ default:
+ MOZ_ASSERT(false);
+ // Unexpected verb found in path!
+ }
+ }
+}
+
+} // namespace mozilla::gfx