9#include "gtest/gtest.h"
23 std::vector<impeller::Point> a,
24 std::vector<impeller::Point> b) {
25 if (a.size() != b.size()) {
26 return ::testing::AssertionFailure() <<
"Colors length does not match";
28 for (
auto i = 0u;
i < b.size();
i++) {
30 return ::testing::AssertionFailure() <<
"Positions are not equal.";
33 return ::testing::AssertionSuccess();
37 std::vector<impeller::TextureFillVertexShader::PerVertexData> a,
38 std::vector<impeller::TextureFillVertexShader::PerVertexData> b) {
39 if (a.size() != b.size()) {
40 return ::testing::AssertionFailure() <<
"Colors length does not match";
42 for (
auto i = 0u;
i < b.size();
i++) {
44 return ::testing::AssertionFailure() <<
"Positions are not equal.";
46 if (!
PointNear(a[
i].texture_coords, b[
i].texture_coords)) {
47 return ::testing::AssertionFailure() <<
"Texture coords are not equal.";
50 return ::testing::AssertionSuccess();
53#define EXPECT_SOLID_VERTICES_NEAR(a, b) \
54 EXPECT_PRED2(&::SolidVerticesNear, a, b)
55#define EXPECT_TEXTURE_VERTICES_NEAR(a, b) \
56 EXPECT_PRED2(&::TextureVerticesNear, a, b)
69 return StrokePathGeometry::GenerateSolidStrokeVertices(
70 tessellator, path, stroke, scale);
76TEST(EntityGeometryTest, RectGeometryCoversArea) {
79 ASSERT_FALSE(geometry->CoversArea({},
IRect::MakeLTRB(-1, 0, 100, 100)));
81 ASSERT_TRUE(geometry->CoversArea({},
IRect()));
84TEST(EntityGeometryTest, UberSDFGeometryPaddingIsAdjustedByInverseMaxBasis) {
91 EXPECT_TRUE(coverage.has_value());
92 if (coverage.has_value()) {
102 EXPECT_TRUE(coverage.has_value());
103 if (coverage.has_value()) {
104 EXPECT_EQ(coverage.value(),
Rect::MakeLTRB(-0.5, -0.5, 100.5, 100.5)
114 EXPECT_TRUE(coverage.has_value());
115 if (coverage.has_value()) {
116 EXPECT_EQ(coverage.value(),
Rect::MakeLTRB(-2.0, -2.0, 102.0, 102.0)
122TEST(EntityGeometryTest, FillPathGeometryCoversArea) {
128 ASSERT_TRUE(geometry->CoversArea({},
IRect::MakeLTRB(0, 0, 100, 100)));
129 ASSERT_FALSE(geometry->CoversArea({},
IRect::MakeLTRB(-1, 0, 100, 100)));
130 ASSERT_TRUE(geometry->CoversArea({},
IRect::MakeLTRB(1, 1, 100, 100)));
131 ASSERT_TRUE(geometry->CoversArea({},
IRect()));
134TEST(EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect) {
139 ASSERT_FALSE(geometry->CoversArea({},
IRect::MakeLTRB(0, 0, 100, 100)));
140 ASSERT_FALSE(geometry->CoversArea({},
IRect::MakeLTRB(-1, 0, 100, 100)));
141 ASSERT_FALSE(geometry->CoversArea({},
IRect::MakeLTRB(1, 1, 100, 100)));
142 ASSERT_FALSE(geometry->CoversArea({},
IRect()));
145TEST(EntityGeometryTest, FillArcGeometryCoverage) {
153 for (
int sweep = 360; sweep <= 720; sweep += 30) {
155 "start: " + std::to_string(
start) +
" + " + std::to_string(sweep);
158 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
159 <<
"start: " <<
start <<
", sweep: " << sweep;
162 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
163 <<
"start: " <<
start <<
", sweep: " << -sweep;
166 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
167 <<
"start: " <<
start <<
", sweep: " << -sweep <<
", with center";
175 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
176 <<
"start: " <<
start <<
" without center";
179 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
180 <<
"start: " <<
start <<
" with center";
187 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
188 <<
"start: " <<
start <<
" without center";
191 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
192 <<
"start: " <<
start <<
" with center";
206 <<
"start: " <<
start - 45;
217 <<
"start: " <<
start + 45;
228 <<
"start: " <<
start + 135;
239 <<
"start: " <<
start + 225;
254 <<
"start: " <<
start - 45;
265 <<
"start: " <<
start + 45;
276 <<
"start: " <<
start + 135;
287 <<
"start: " <<
start + 225;
294 ASSERT_TRUE(oval_bounds.TransformBounds(transform45).Contains(oval_bounds));
296 EXPECT_TRUE(geometry->GetCoverage(transform45)
298 .Contains(oval_bounds));
303 ASSERT_TRUE(oval_bounds.TransformBounds(transform45).Contains(oval_bounds));
305 EXPECT_TRUE(geometry->GetCoverage(transform45)
307 .Contains(oval_bounds));
311TEST(EntityGeometryTest, StrokeArcGeometryCoverage) {
331 for (
int sweep = 360; sweep <= 720; sweep += 30) {
333 "start: " + std::to_string(
start) +
" + " + std::to_string(sweep);
336 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
337 <<
"start: " <<
start <<
", sweep: " << sweep;
340 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
341 <<
"start: " <<
start <<
", sweep: " << -sweep;
343 Degrees(-sweep), square_params);
344 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
345 <<
"start: " <<
start <<
", sweep: " << -sweep <<
", square caps";
353 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
354 <<
"start: " <<
start <<
", butt caps";
357 EXPECT_EQ(geometry->GetCoverage({}), squared_bounds)
358 <<
"start: " <<
start <<
", square caps";
365 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
366 <<
"start: " <<
start <<
" without center";
369 EXPECT_EQ(geometry->GetCoverage({}), squared_bounds)
370 <<
"start: " <<
start <<
" with center";
384 <<
"start: " <<
start - 45;
395 <<
"start: " <<
start + 45;
406 <<
"start: " <<
start + 135;
417 <<
"start: " <<
start + 225;
433 <<
"start: " <<
start - 45;
444 <<
"start: " <<
start + 45;
455 <<
"start: " <<
start + 135;
466 <<
"start: " <<
start + 225;
474 oval_bounds.TransformBounds(transform45).Contains(expanded_bounds));
476 EXPECT_TRUE(geometry->GetCoverage(transform45)
478 .Contains(expanded_bounds));
484 oval_bounds.TransformBounds(transform45).Contains(expanded_bounds));
486 EXPECT_TRUE(geometry->GetCoverage(transform45)
488 .Contains(squared_bounds));
494 oval_bounds.TransformBounds(transform45).Contains(expanded_bounds));
496 EXPECT_TRUE(geometry->GetCoverage(transform45)
498 .Contains(expanded_bounds));
504 oval_bounds.TransformBounds(transform45).Contains(expanded_bounds));
506 EXPECT_TRUE(geometry->GetCoverage(transform45)
508 .Contains(squared_bounds));
512TEST(EntityGeometryTest, FillRoundRectGeometryCoversArea) {
517 .top_right =
Size(2, 12),
518 .bottom_left =
Size(3, 13),
519 .bottom_right =
Size(4, 14),
525 EXPECT_FALSE(geom.CoversArea({},
IRect::MakeLTRB(102, 100, 196, 200)));
527 EXPECT_FALSE(geom.CoversArea({},
IRect::MakeLTRB(103, 100, 197, 200)));
528 EXPECT_FALSE(geom.CoversArea({},
IRect::MakeLTRB(103, 100, 196, 201)));
533 EXPECT_FALSE(geom.CoversArea({},
IRect::MakeLTRB(100, 111, 200, 186)));
534 EXPECT_FALSE(geom.CoversArea({},
IRect::MakeLTRB(100, 112, 201, 186)));
535 EXPECT_FALSE(geom.CoversArea({},
IRect::MakeLTRB(100, 112, 200, 187)));
538TEST(EntityGeometryTest, LineGeometryCoverage) {
541 {10, 10}, {20, 10}, {.width = 2, .cap =
Cap::kButt});
542 EXPECT_EQ(geometry->GetCoverage({}),
Rect::MakeLTRB(10, 9, 20, 11));
549 EXPECT_EQ(geometry->GetCoverage({}),
Rect::MakeLTRB(9, 9, 21, 11));
555 {10, 10}, {10, 20}, {.width = 2, .cap =
Cap::kButt});
556 EXPECT_EQ(geometry->GetCoverage({}),
Rect::MakeLTRB(9, 10, 11, 20));
563 EXPECT_EQ(geometry->GetCoverage({}),
Rect::MakeLTRB(9, 9, 11, 21));
568TEST(EntityGeometryTest, RoundRectGeometryCoversArea) {
571 EXPECT_FALSE(geometry->CoversArea({},
IRect::MakeLTRB(15, 15, 85, 85)));
572 EXPECT_TRUE(geometry->CoversArea({},
IRect::MakeLTRB(20, 20, 80, 80)));
577TEST(EntityGeometryTest, GeometryResultHasReasonableDefaults) {
584TEST(EntityGeometryTest, AlphaCoverageStrokePaths) {
587 ->ComputeAlphaCoverage(matrix),
590 ->ComputeAlphaCoverage(matrix),
593 ->ComputeAlphaCoverage(matrix),
596 ->ComputeAlphaCoverage(matrix),
599 ->ComputeAlphaCoverage(matrix),
602 ->ComputeAlphaCoverage(matrix),
605 ->ComputeAlphaCoverage(matrix),
609TEST(EntityGeometryTest, SimpleTwoLineStrokeVerticesButtCap) {
611 path_builder.
MoveTo({20, 20});
612 path_builder.
LineTo({30, 20});
613 path_builder.
MoveTo({120, 20});
614 path_builder.
LineTo({130, 20});
627 std::vector<Point> expected = {
647 EXPECT_EQ(
points, expected);
650TEST(EntityGeometryTest, SimpleTwoLineStrokeVerticesRoundCap) {
652 path_builder.
MoveTo({20, 20});
653 path_builder.
LineTo({30, 20});
654 path_builder.
MoveTo({120, 20});
655 path_builder.
LineTo({130, 20});
668 size_t count =
points.size();
669 ASSERT_TRUE((count & 0x1) == 0x0);
677 ASSERT_EQ(
points.size(), 40u);
683 auto offset = [](
int step,
bool left,
bool backwards) ->
Point {
687 Point center = backwards ? -along : along;
688 return left ? center + across : center - across;
693 EXPECT_EQ(
points[1],
Point(20, 20) + offset(1,
true,
true));
694 EXPECT_EQ(
points[2],
Point(20, 20) + offset(1,
false,
true));
695 EXPECT_EQ(
points[3],
Point(20, 20) + offset(2,
true,
true));
696 EXPECT_EQ(
points[4],
Point(20, 20) + offset(2,
false,
true));
697 EXPECT_EQ(
points[5],
Point(20, 20) + offset(3,
true,
true));
698 EXPECT_EQ(
points[6],
Point(20, 20) + offset(3,
false,
true));
703 EXPECT_EQ(
points[11],
Point(30, 20) + offset(3,
true,
false));
704 EXPECT_EQ(
points[12],
Point(30, 20) + offset(3,
false,
false));
705 EXPECT_EQ(
points[13],
Point(30, 20) + offset(2,
true,
false));
706 EXPECT_EQ(
points[14],
Point(30, 20) + offset(2,
false,
false));
707 EXPECT_EQ(
points[15],
Point(30, 20) + offset(1,
true,
false));
708 EXPECT_EQ(
points[16],
Point(30, 20) + offset(1,
false,
false));
719 EXPECT_EQ(
points[23],
Point(120, 20) + offset(1,
true,
true));
720 EXPECT_EQ(
points[24],
Point(120, 20) + offset(1,
false,
true));
721 EXPECT_EQ(
points[25],
Point(120, 20) + offset(2,
true,
true));
722 EXPECT_EQ(
points[26],
Point(120, 20) + offset(2,
false,
true));
723 EXPECT_EQ(
points[27],
Point(120, 20) + offset(3,
true,
true));
724 EXPECT_EQ(
points[28],
Point(120, 20) + offset(3,
false,
true));
729 EXPECT_EQ(
points[33],
Point(130, 20) + offset(3,
true,
false));
730 EXPECT_EQ(
points[34],
Point(130, 20) + offset(3,
false,
false));
731 EXPECT_EQ(
points[35],
Point(130, 20) + offset(2,
true,
false));
732 EXPECT_EQ(
points[36],
Point(130, 20) + offset(2,
false,
false));
733 EXPECT_EQ(
points[37],
Point(130, 20) + offset(1,
true,
false));
734 EXPECT_EQ(
points[38],
Point(130, 20) + offset(1,
false,
false));
738TEST(EntityGeometryTest, SimpleTwoLineStrokeVerticesSquareCap) {
740 path_builder.
MoveTo({20, 20});
741 path_builder.
LineTo({30, 20});
742 path_builder.
MoveTo({120, 20});
743 path_builder.
LineTo({130, 20});
757 std::vector<Point> expected = {
786 EXPECT_EQ(
points, expected);
789TEST(EntityGeometryTest, TwoLineSegmentsRightTurnStrokeVerticesBevelJoin) {
791 path_builder.
MoveTo({20, 20});
792 path_builder.
LineTo({30, 20});
793 path_builder.
LineTo({30, 30});
806 std::vector<Point> expected = {
820 EXPECT_EQ(
points, expected);
823TEST(EntityGeometryTest, TwoLineSegmentsLeftTurnStrokeVerticesBevelJoin) {
825 path_builder.
MoveTo({20, 20});
826 path_builder.
LineTo({30, 20});
827 path_builder.
LineTo({30, 10});
840 std::vector<Point> expected = {
854 EXPECT_EQ(
points, expected);
857TEST(EntityGeometryTest, TwoLineSegmentsRightTurnStrokeVerticesMiterJoin) {
859 path_builder.
MoveTo({20, 20});
860 path_builder.
LineTo({30, 20});
861 path_builder.
LineTo({30, 30});
874 std::vector<Point> expected = {
891 EXPECT_EQ(
points, expected);
894TEST(EntityGeometryTest, TwoLineSegmentsLeftTurnStrokeVerticesMiterJoin) {
896 path_builder.
MoveTo({20, 20});
897 path_builder.
LineTo({30, 20});
898 path_builder.
LineTo({30, 10});
911 std::vector<Point> expected = {
928 EXPECT_EQ(
points, expected);
931TEST(EntityGeometryTest, TinyQuadGeneratesCaps) {
933 path_builder.
MoveTo({20, 20});
947 std::vector<Point> expected = {
965 EXPECT_EQ(
points, expected);
968TEST(EntityGeometryTest, TinyConicGeneratesCaps) {
970 path_builder.
MoveTo({20, 20});
971 path_builder.
ConicCurveTo({20.125, 20}, {20.250, 20}, 0.6);
984 std::vector<Point> expected = {
1002 EXPECT_EQ(
points, expected);
1005TEST(EntityGeometryTest, TinyCubicGeneratesCaps) {
1007 path_builder.
MoveTo({20, 20});
1008 path_builder.
CubicCurveTo({20.0625, 20}, {20.125, 20}, {20.250, 20});
1017 .miter_limit = 4.0f,
1021 std::vector<Point> expected = {
1039 EXPECT_EQ(
points, expected);
1042TEST(EntityGeometryTest, TwoLineSegmentsMiterLimit) {
1044 for (
int degrees = 10; degrees < 180; degrees += 10) {
1052 if (pixel_delta.GetDistance(
Point(1, 0)) *
width < 1.0f) {
1061 Degrees between(180 - degrees);
1068 path_builder.
LineTo(
Point(30, 20) + pixel_delta * 10.0f);
1079 .miter_limit = limit * 0.99f,
1082 EXPECT_EQ(points1.size(), 8u)
1083 <<
"degrees: " << degrees <<
", width: " <<
width <<
", "
1094 .miter_limit = limit * 1.01f,
1097 EXPECT_EQ(points2.size(), 9u)
1098 <<
"degrees: " << degrees <<
", width: " <<
width;
1099 EXPECT_LE(points2[4].GetDistance({30, 20}),
width * limit * 1.05f)
1100 <<
"degrees: " << degrees <<
", width: " <<
width <<
", "
1106TEST(EntityGeometryTest, TwoLineSegments180DegreeJoins) {
1121 .miter_limit = 4.0f,
1125 EXPECT_EQ(points_bevel.size(), 8u);
1134 .miter_limit = 400.0f,
1138 EXPECT_EQ(points_miter.size(), 8u);
1147 .miter_limit = 4.0f,
1151 EXPECT_EQ(points_round.size(), 19u);
1154TEST(EntityGeometryTest, TightQuadratic180DegreeJoins) {
1162 auto points_bevel_reference =
1169 .miter_limit = 4.0f,
1173 EXPECT_EQ(points_bevel_reference.size(), 74u);
1188 .miter_limit = 4.0f,
1192 EXPECT_GT(points_bevel.size(), points_bevel_reference.size());
1201 .miter_limit = 400.0f,
1205 EXPECT_GT(points_miter.size(), points_bevel_reference.size());
1214 .miter_limit = 4.0f,
1218 EXPECT_GT(points_round.size(), points_bevel_reference.size());
1221TEST(EntityGeometryTest, TightConic180DegreeJoins) {
1229 auto points_bevel_reference =
1236 .miter_limit = 4.0f,
1240 EXPECT_EQ(points_bevel_reference.size(), 78u);
1255 .miter_limit = 4.0f,
1259 EXPECT_GT(points_bevel.size(), points_bevel_reference.size());
1268 .miter_limit = 400.0f,
1272 EXPECT_GT(points_miter.size(), points_bevel_reference.size());
1281 .miter_limit = 4.0f,
1285 EXPECT_GT(points_round.size(), points_bevel_reference.size());
1288TEST(EntityGeometryTest, TightCubic180DegreeJoins) {
1297 auto points_reference =
1304 .miter_limit = 4.0f,
1308 EXPECT_EQ(points_reference.size(), 76u);
1323 .miter_limit = 4.0f,
1327 EXPECT_GT(points_bevel.size(), points_reference.size());
1336 .miter_limit = 400.0f,
1340 EXPECT_GT(points_miter.size(), points_reference.size());
1349 .miter_limit = 4.0f,
1353 EXPECT_GT(points_round.size(), points_reference.size());
1356TEST(EntityGeometryTest, RotatedFilledCircleGeometryCoverage) {
1360 ASSERT_EQ(geometry->GetCoverage({}).value_or(
Rect()), circle_bounds);
1366 EXPECT_TRUE(geometry->GetCoverage(transform45).has_value());
1367 Rect bounds = geometry->GetCoverage(transform45).value_or(
Rect());
1368 EXPECT_TRUE(bounds.Contains(circle_bounds))
1369 <<
"geometry bounds: " << bounds << std::endl
1370 <<
" circle bounds: " << circle_bounds;
1373TEST(EntityGeometryTest, RotatedStrokedCircleGeometryCoverage) {
1377 ASSERT_EQ(geometry->GetCoverage({}).value_or(
Rect()), circle_bounds);
1383 EXPECT_TRUE(geometry->GetCoverage(transform45).has_value());
1384 Rect bounds = geometry->GetCoverage(transform45).value_or(
Rect());
1385 EXPECT_TRUE(bounds.Contains(circle_bounds))
1386 <<
"geometry bounds: " << bounds << std::endl
1387 <<
" circle bounds: " << circle_bounds;
DlPathBuilder & LineTo(DlPoint p2)
Draw a line from the current point to the indicated point p2.
DlPathBuilder & MoveTo(DlPoint p2)
Start a new contour that will originate at the indicated point p2.
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
DlPathBuilder & ConicCurveTo(DlPoint cp, DlPoint p2, DlScalar weight)
Draw a conic curve (a rational quadratic bezier curve) from the current point to the indicated point ...
DlPathBuilder & AddRect(const DlRect &rect)
Append a closed rectangular contour to the path.
DlPathBuilder & QuadraticCurveTo(DlPoint cp, DlPoint p2)
Draw a quadratic bezier curve from the current point to the indicated point p2, using the indicated p...
DlPathBuilder & CubicCurveTo(DlPoint cp1, DlPoint cp2, DlPoint p2)
Draw a cubic bezier curve from the current point to the indicated point p2, using the indicated point...
A Geometry class that produces fillable vertices from any |RoundRect| object regardless of radii unif...
static std::unique_ptr< Geometry > MakeFillPath(const flutter::DlPath &path, std::optional< Rect > inner_rect=std::nullopt)
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
static std::unique_ptr< Geometry > MakeFilledArc(const Rect &oval_bounds, Degrees start, Degrees sweep, bool include_center)
static std::unique_ptr< Geometry > MakeStrokePath(const flutter::DlPath &path, const StrokeParameters &stroke={})
static std::unique_ptr< Geometry > MakeCircle(const Point ¢er, Scalar radius)
static std::unique_ptr< Geometry > MakeRoundRect(const Rect &rect, const Size &radii)
static std::unique_ptr< Geometry > MakeLine(const Point &p0, const Point &p1, const StrokeParameters &stroke)
static std::unique_ptr< Geometry > MakeStrokedCircle(const Point ¢er, Scalar radius, Scalar stroke_width)
static std::unique_ptr< Geometry > MakeStrokedArc(const Rect &oval_bounds, Degrees start, Degrees sweep, const StrokeParameters &stroke)
static std::vector< Point > GenerateSolidStrokeVertices(const PathSource &path, const StrokeParameters &stroke, Scalar scale)
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Geometry for rendering shapes using the UberSDF shader.
std::optional< Rect > GetCoverage(const Matrix &transform) const override
The coverage rectangle of this geometry, transformed by the transform argument.
inline ::testing::AssertionResult PointNear(impeller::Point a, impeller::Point b)
#define EXPECT_RECT_NEAR(a, b)
inline ::testing::AssertionResult SolidVerticesNear(std::vector< impeller::Point > a, std::vector< impeller::Point > b)
inline ::testing::AssertionResult TextureVerticesNear(std::vector< impeller::TextureFillVertexShader::PerVertexData > a, std::vector< impeller::TextureFillVertexShader::PerVertexData > b)
TEST(FrameTimingsRecorderTest, RecordVsync)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
constexpr float kSqrt2Over2
static constexpr Color Red()
@ kNormal
The geometry has no overlapping triangles.
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
static RoundRect MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
A structure to store all of the parameters related to stroking a path or basic geometry object.
constexpr TRect TransformAndClipBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle, clipped against the near clippin...
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
static UberSDFParameters MakeRect(Color color, const Rect &rect, std::optional< StrokeParameters > stroke)
Creates UberSDFParameters for a rectangle.
std::vector< Point > points