|
4 | 4 |
|
5 | 5 | #include "flutter/testing/testing.h" |
6 | 6 | #include "impeller/entity/geometry/geometry.h" |
| 7 | +#include "impeller/entity/geometry/stroke_path_geometry.h" |
| 8 | +#include "impeller/geometry/geometry_asserts.h" |
7 | 9 | #include "impeller/geometry/path_builder.h" |
8 | 10 |
|
| 11 | +inline ::testing::AssertionResult SolidVerticesNear( |
| 12 | + std::vector<impeller::SolidFillVertexShader::PerVertexData> a, |
| 13 | + std::vector<impeller::SolidFillVertexShader::PerVertexData> b) { |
| 14 | + if (a.size() != b.size()) { |
| 15 | + return ::testing::AssertionFailure() << "Colors length does not match"; |
| 16 | + } |
| 17 | + for (auto i = 0u; i < b.size(); i++) { |
| 18 | + if (!PointNear(a[i].position, b[i].position)) { |
| 19 | + return ::testing::AssertionFailure() << "Positions are not equal."; |
| 20 | + } |
| 21 | + } |
| 22 | + return ::testing::AssertionSuccess(); |
| 23 | +} |
| 24 | + |
| 25 | +inline ::testing::AssertionResult TextureVerticesNear( |
| 26 | + std::vector<impeller::TextureFillVertexShader::PerVertexData> a, |
| 27 | + std::vector<impeller::TextureFillVertexShader::PerVertexData> b) { |
| 28 | + if (a.size() != b.size()) { |
| 29 | + return ::testing::AssertionFailure() << "Colors length does not match"; |
| 30 | + } |
| 31 | + for (auto i = 0u; i < b.size(); i++) { |
| 32 | + if (!PointNear(a[i].position, b[i].position)) { |
| 33 | + return ::testing::AssertionFailure() << "Positions are not equal."; |
| 34 | + } |
| 35 | + if (!PointNear(a[i].texture_coords, b[i].texture_coords)) { |
| 36 | + return ::testing::AssertionFailure() << "Texture coords are not equal."; |
| 37 | + } |
| 38 | + } |
| 39 | + return ::testing::AssertionSuccess(); |
| 40 | +} |
| 41 | + |
| 42 | +#define EXPECT_SOLID_VERTICES_NEAR(a, b) \ |
| 43 | + EXPECT_PRED2(&::SolidVerticesNear, a, b) |
| 44 | +#define EXPECT_TEXTURE_VERTICES_NEAR(a, b) \ |
| 45 | + EXPECT_PRED2(&::TextureVerticesNear, a, b) |
| 46 | + |
9 | 47 | namespace impeller { |
| 48 | + |
| 49 | +class ImpellerEntityUnitTestAccessor { |
| 50 | + public: |
| 51 | + static std::vector<SolidFillVertexShader::PerVertexData> |
| 52 | + GenerateSolidStrokeVertices(const Path::Polyline& polyline, |
| 53 | + Scalar stroke_width, |
| 54 | + Scalar miter_limit, |
| 55 | + Join stroke_join, |
| 56 | + Cap stroke_cap, |
| 57 | + Scalar scale) { |
| 58 | + return StrokePathGeometry::GenerateSolidStrokeVertices( |
| 59 | + polyline, stroke_width, miter_limit, stroke_join, stroke_cap, scale); |
| 60 | + } |
| 61 | + |
| 62 | + static std::vector<TextureFillVertexShader::PerVertexData> |
| 63 | + GenerateSolidStrokeVerticesUV(const Path::Polyline& polyline, |
| 64 | + Scalar stroke_width, |
| 65 | + Scalar miter_limit, |
| 66 | + Join stroke_join, |
| 67 | + Cap stroke_cap, |
| 68 | + Scalar scale, |
| 69 | + Point texture_origin, |
| 70 | + Size texture_size, |
| 71 | + const Matrix& effect_transform) { |
| 72 | + return StrokePathGeometry::GenerateSolidStrokeVerticesUV( |
| 73 | + polyline, stroke_width, miter_limit, stroke_join, stroke_cap, scale, |
| 74 | + texture_origin, texture_size, effect_transform); |
| 75 | + } |
| 76 | +}; |
| 77 | + |
10 | 78 | namespace testing { |
11 | 79 |
|
12 | 80 | TEST(EntityGeometryTest, RectGeometryCoversArea) { |
@@ -71,5 +139,74 @@ TEST(EntityGeometryTest, RoundRectGeometryCoversArea) { |
71 | 139 | EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 30, 99, 70))); |
72 | 140 | } |
73 | 141 |
|
| 142 | +TEST(EntityGeometryTest, StrokePathGeometryTransformOfLine) { |
| 143 | + auto path = |
| 144 | + PathBuilder().AddLine(Point(100, 100), Point(200, 100)).TakePath(); |
| 145 | + auto points = std::make_unique<std::vector<Point>>(); |
| 146 | + auto polyline = |
| 147 | + path.CreatePolyline(1.0f, std::move(points), |
| 148 | + [&points](Path::Polyline::PointBufferPtr reclaimed) { |
| 149 | + points = std::move(reclaimed); |
| 150 | + }); |
| 151 | + |
| 152 | + auto vertices = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices( |
| 153 | + polyline, 10.0f, 10.0f, Join::kBevel, Cap::kButt, 1.0); |
| 154 | + |
| 155 | + std::vector<SolidFillVertexShader::PerVertexData> expected = { |
| 156 | + {.position = Point(100.0f, 105.0f)}, // |
| 157 | + {.position = Point(100.0f, 95.0f)}, // |
| 158 | + {.position = Point(100.0f, 105.0f)}, // |
| 159 | + {.position = Point(100.0f, 95.0f)}, // |
| 160 | + {.position = Point(200.0f, 105.0f)}, // |
| 161 | + {.position = Point(200.0f, 95.0f)}, // |
| 162 | + {.position = Point(200.0f, 105.0f)}, // |
| 163 | + {.position = Point(200.0f, 95.0f)}, // |
| 164 | + }; |
| 165 | + |
| 166 | + EXPECT_SOLID_VERTICES_NEAR(vertices, expected); |
| 167 | + |
| 168 | + { |
| 169 | + auto uv_vertices = |
| 170 | + ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVerticesUV( |
| 171 | + polyline, 10.0f, 10.0f, Join::kBevel, Cap::kButt, 1.0, // |
| 172 | + Point(50.0f, 40.0f), Size(20.0f, 40.0f), |
| 173 | + Matrix::MakeScale({8.0f, 4.0f, 1.0f})); |
| 174 | + // uvx = ((x * 8) - 50) / 20 |
| 175 | + // uvy = ((y * 4) - 40) / 40 |
| 176 | + auto uv = [](const Point& p) { |
| 177 | + return Point(((p.x * 8.0f) - 50.0f) / 20.0f, |
| 178 | + ((p.y * 4.0f) - 40.0f) / 40.0f); |
| 179 | + }; |
| 180 | + std::vector<TextureFillVertexShader::PerVertexData> uv_expected; |
| 181 | + for (size_t i = 0; i < expected.size(); i++) { |
| 182 | + auto p = expected[i].position; |
| 183 | + uv_expected.push_back({.position = p, .texture_coords = uv(p)}); |
| 184 | + } |
| 185 | + |
| 186 | + EXPECT_TEXTURE_VERTICES_NEAR(uv_vertices, uv_expected); |
| 187 | + } |
| 188 | + |
| 189 | + { |
| 190 | + auto uv_vertices = |
| 191 | + ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVerticesUV( |
| 192 | + polyline, 10.0f, 10.0f, Join::kBevel, Cap::kButt, 1.0, // |
| 193 | + Point(50.0f, 40.0f), Size(20.0f, 40.0f), |
| 194 | + Matrix::MakeTranslation({8.0f, 4.0f})); |
| 195 | + // uvx = ((x + 8) - 50) / 20 |
| 196 | + // uvy = ((y + 4) - 40) / 40 |
| 197 | + auto uv = [](const Point& p) { |
| 198 | + return Point(((p.x + 8.0f) - 50.0f) / 20.0f, |
| 199 | + ((p.y + 4.0f) - 40.0f) / 40.0f); |
| 200 | + }; |
| 201 | + std::vector<TextureFillVertexShader::PerVertexData> uv_expected; |
| 202 | + for (size_t i = 0; i < expected.size(); i++) { |
| 203 | + auto p = expected[i].position; |
| 204 | + uv_expected.push_back({.position = p, .texture_coords = uv(p)}); |
| 205 | + } |
| 206 | + |
| 207 | + EXPECT_TEXTURE_VERTICES_NEAR(uv_vertices, uv_expected); |
| 208 | + } |
| 209 | +} |
| 210 | + |
74 | 211 | } // namespace testing |
75 | 212 | } // namespace impeller |
0 commit comments