[Impeller] Move SeparatedVector2 to impeller/geometry. (#53264)
Follow-up for https://github.com/flutter/engine/pull/53210.
Also rename from `Ray` to `SeparatedVector2`, which is a more accurate name for what it is.
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index d3d4103..24bd093 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -42151,6 +42151,8 @@
ORIGIN: ../../../flutter/impeller/geometry/rect.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/saturated_math.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/scalar.h + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/geometry/separated_vector.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/geometry/separated_vector.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/shear.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/shear.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/sigma.cc + ../../../flutter/LICENSE
@@ -45017,6 +45019,8 @@
FILE: ../../../flutter/impeller/geometry/rect.h
FILE: ../../../flutter/impeller/geometry/saturated_math.h
FILE: ../../../flutter/impeller/geometry/scalar.h
+FILE: ../../../flutter/impeller/geometry/separated_vector.cc
+FILE: ../../../flutter/impeller/geometry/separated_vector.h
FILE: ../../../flutter/impeller/geometry/shear.cc
FILE: ../../../flutter/impeller/geometry/shear.h
FILE: ../../../flutter/impeller/geometry/sigma.cc
diff --git a/impeller/entity/geometry/stroke_path_geometry.cc b/impeller/entity/geometry/stroke_path_geometry.cc
index c4220a2..5956adf 100644
--- a/impeller/entity/geometry/stroke_path_geometry.cc
+++ b/impeller/entity/geometry/stroke_path_geometry.cc
@@ -10,6 +10,7 @@
#include "impeller/geometry/constants.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/geometry/path_component.h"
+#include "impeller/geometry/separated_vector.h"
namespace impeller {
using VS = SolidFillVertexShader;
@@ -163,45 +164,13 @@
}
}
- /// @brief Represents a ray in 2D space.
- ///
- /// This is a simple convenience struct for handling polyline offset
- /// values when generating stroke geometry. For performance reasons,
- /// it's sometimes adventageous to track the direction and magnitude
- /// for offsets separately.
- struct Ray {
- /// The normalized direction of the ray.
- Vector2 direction;
-
- /// The magnitude of the ray.
- Scalar magnitude = 0.0;
-
- /// Returns the vector representation of the ray.
- Vector2 GetVector() const { return direction * magnitude; }
-
- /// Returns the scalar alignment of the two rays.
- ///
- /// Domain: [-1, 1]
- /// A value of 1 indicates the rays are parallel and pointing in the same
- /// direction. A value of -1 indicates the rays are parallel and pointing in
- /// opposite directions. A value of 0 indicates the rays are perpendicular.
- Scalar GetAlignment(const Ray& other) const {
- return direction.Dot(other.direction);
- }
-
- /// Returns the scalar angle between the two rays.
- Radians AngleTo(const Ray& other) const {
- return direction.AngleTo(other.direction);
- }
- };
-
/// Computes offset by calculating the direction from point_i - 1 to point_i
/// if point_i is within `contour_start_point_i` and `contour_end_point_i`;
/// Otherwise, it uses direction from contour.
- Ray ComputeOffset(const size_t point_i,
- const size_t contour_start_point_i,
- const size_t contour_end_point_i,
- const Path::PolylineContour& contour) const {
+ SeparatedVector2 ComputeOffset(const size_t point_i,
+ const size_t contour_start_point_i,
+ const size_t contour_end_point_i,
+ const Path::PolylineContour& contour) const {
Point direction;
if (point_i >= contour_end_point_i) {
direction = contour.end_direction;
@@ -211,8 +180,8 @@
direction = (polyline.GetPoint(point_i) - polyline.GetPoint(point_i - 1))
.Normalize();
}
- return {.direction = Vector2{-direction.y, direction.x},
- .magnitude = stroke_width * 0.5f};
+ return SeparatedVector2(Vector2{-direction.y, direction.x},
+ stroke_width * 0.5f);
}
void AddVerticesForLinearComponent(VertexWriter& vtx_builder,
@@ -338,8 +307,8 @@
const CapProc<VertexWriter>& cap_proc;
const Scalar scale;
- Ray previous_offset;
- Ray offset;
+ SeparatedVector2 previous_offset;
+ SeparatedVector2 offset;
SolidFillVertexShader::PerVertexData vtx;
};
diff --git a/impeller/geometry/BUILD.gn b/impeller/geometry/BUILD.gn
index 7697702..e9bfdad 100644
--- a/impeller/geometry/BUILD.gn
+++ b/impeller/geometry/BUILD.gn
@@ -31,6 +31,8 @@
"rect.h",
"saturated_math.h",
"scalar.h",
+ "separated_vector.cc",
+ "separated_vector.h",
"shear.cc",
"shear.h",
"sigma.cc",
diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc
index 124f74b..697471e 100644
--- a/impeller/geometry/geometry_unittests.cc
+++ b/impeller/geometry/geometry_unittests.cc
@@ -19,6 +19,7 @@
#include "impeller/geometry/point.h"
#include "impeller/geometry/rect.h"
#include "impeller/geometry/scalar.h"
+#include "impeller/geometry/separated_vector.h"
#include "impeller/geometry/size.h"
// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
@@ -1141,6 +1142,56 @@
ASSERT_VECTOR4_NEAR(result, expected);
}
+TEST(GeometryTest, SeparatedVector2NormalizesWithConstructor) {
+ SeparatedVector2 v(Vector2(10, 0));
+ ASSERT_POINT_NEAR(v.direction, Vector2(1, 0));
+ ASSERT_NEAR(v.magnitude, 10, kEhCloseEnough);
+}
+
+TEST(GeometryTest, SeparatedVector2GetVector) {
+ SeparatedVector2 v(Vector2(10, 0));
+ ASSERT_POINT_NEAR(v.GetVector(), Vector2(10, 0));
+}
+
+TEST(GeometryTest, SeparatedVector2GetAlignment) {
+ // Parallel
+ {
+ SeparatedVector2 v(Vector2(10, 0));
+ Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(5, 0)));
+ ASSERT_NEAR(actual, 1, kEhCloseEnough);
+ }
+
+ // Perpendicular
+ {
+ SeparatedVector2 v(Vector2(10, 0));
+ Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, 5)));
+ ASSERT_NEAR(actual, 0, kEhCloseEnough);
+ }
+
+ // Opposite parallel
+ {
+ SeparatedVector2 v(Vector2(0, 10));
+ Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, -5)));
+ ASSERT_NEAR(actual, -1, kEhCloseEnough);
+ }
+}
+
+TEST(GeometryTest, SeparatedVector2AngleTo) {
+ {
+ SeparatedVector2 v(Vector2(10, 0));
+ Radians actual = v.AngleTo(SeparatedVector2(Vector2(5, 0)));
+ Radians expected = Radians{0};
+ ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
+ }
+
+ {
+ SeparatedVector2 v(Vector2(10, 0));
+ Radians actual = v.AngleTo(SeparatedVector2(Vector2(0, -5)));
+ Radians expected = Radians{-kPi / 2};
+ ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
+ }
+}
+
TEST(GeometryTest, CanUseVector3AssignmentOperators) {
{
Vector3 p(1, 2, 4);
diff --git a/impeller/geometry/separated_vector.cc b/impeller/geometry/separated_vector.cc
new file mode 100644
index 0000000..dbf0da6
--- /dev/null
+++ b/impeller/geometry/separated_vector.cc
@@ -0,0 +1,29 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "separated_vector.h"
+
+namespace impeller {
+
+SeparatedVector2::SeparatedVector2() = default;
+
+SeparatedVector2::SeparatedVector2(Vector2 direction, Scalar magnitude)
+ : direction(direction), magnitude(magnitude){};
+
+SeparatedVector2::SeparatedVector2(Vector2 vector)
+ : direction(vector.Normalize()), magnitude(vector.GetLength()){};
+
+Vector2 SeparatedVector2::GetVector() const {
+ return direction * magnitude;
+}
+
+Scalar SeparatedVector2::GetAlignment(const SeparatedVector2& other) const {
+ return direction.Dot(other.direction);
+}
+
+Radians SeparatedVector2::AngleTo(const SeparatedVector2& other) const {
+ return direction.AngleTo(other.direction);
+}
+
+} // namespace impeller
diff --git a/impeller/geometry/separated_vector.h b/impeller/geometry/separated_vector.h
new file mode 100644
index 0000000..304029d
--- /dev/null
+++ b/impeller/geometry/separated_vector.h
@@ -0,0 +1,51 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_IMPELLER_GEOMETRY_SEPARATED_VECTOR_H_
+#define FLUTTER_IMPELLER_GEOMETRY_SEPARATED_VECTOR_H_
+
+#include "impeller/geometry/point.h"
+
+#include "impeller/geometry/scalar.h"
+
+namespace impeller {
+
+/// @brief A Vector2, broken down as a separate magnitude and direction.
+/// Assumes that the direction given is normalized.
+///
+/// This is a simple convenience struct for handling polyline offset
+/// values when generating stroke geometry. For performance reasons,
+/// it's sometimes adventageous to track the direction and magnitude
+/// for offsets separately.
+struct SeparatedVector2 {
+ /// The normalized direction of the vector.
+ Vector2 direction;
+
+ /// The magnitude of the vector.
+ Scalar magnitude = 0.0;
+
+ SeparatedVector2();
+ SeparatedVector2(Vector2 direction, Scalar magnitude);
+ explicit SeparatedVector2(Vector2 vector);
+
+ /// Returns the vector representation of the vector.
+ Vector2 GetVector() const;
+
+ /// Returns the scalar alignment of the two vectors.
+ /// In other words, the dot product of the two normalized vectors.
+ ///
+ /// Range: [-1, 1]
+ /// A value of 1 indicates the directions are parallel and pointing in the
+ /// same direction. A value of -1 indicates the vectors are parallel and
+ /// pointing in opposite directions. A value of 0 indicates the vectors are
+ /// perpendicular.
+ Scalar GetAlignment(const SeparatedVector2& other) const;
+
+ /// Returns the scalar angle between the two rays.
+ Radians AngleTo(const SeparatedVector2& other) const;
+};
+
+#endif // FLUTTER_IMPELLER_GEOMETRY_SEPARATED_VECTOR_H_
+
+} // namespace impeller