| Flutter Impeller |

line_contents_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/entity/contents/line_contents.h"
6
7 #include <algorithm>
8
9 #include "impeller/geometry/geometry_asserts.h"
10 #include "third_party/googletest/googletest/include/gtest/gtest.h"
11
12 namespace impeller {
13 namespace testing {
14
15 namespace {
16 float lookup(Scalar x) {
17 return std::clamp(x, /*lo=*/0.f, /*hi=*/1.f);
18 }
19
20 // This mirrors the function in line.frag.
21 float CalculateLine(const LineVertexShader::PerVertexData& per_vertex,
22 Point position) {
23 Vector3 pos = Vector3(position.x, position.y, 1.0);
24 Scalar d[4] = {pos.Dot(per_vertex.e0), pos.Dot(per_vertex.e1),
25 pos.Dot(per_vertex.e2), pos.Dot(per_vertex.e3)};
26
27 for (int i = 0; i < 4; ++i) {
28 if (d[i] < 0.f) {
29 return 0.0;
30 }
31 }
32
33 return lookup(std::min(d[0], d[2])) * lookup(std::min(d[1], d[3]));
34 }
35 } // namespace
36
37 TEST(LineContents, Create) {
38 Path path;
39 Scalar width = 5.0f;
40 auto geometry = std::make_unique<LineGeometry>(
41 /*p0=*/Point{0, 0}, //
42 /*p1=*/Point{100, 100}, //
43 /*width=*/width, //
44 /*cap=*/Cap::kSquare);
45 std::unique_ptr<LineContents> contents =
46 LineContents::Make(std::move(geometry), Color(1.f, 0.f, 0.f, 1.f));
47 EXPECT_TRUE(contents);
48 Entity entity;
49 std::optional<Rect> coverage = contents->GetCoverage(entity);
50 EXPECT_TRUE(coverage.has_value());
51 if (coverage.has_value()) {
52 Scalar lip = sqrt((width * width) / 2.f);
53 EXPECT_EQ(*coverage,
54 Rect::MakeXYWH(-lip, -lip, 100 + 2 * lip, 100 + 2 * lip));
55 }
56 }
57
58 TEST(LineContents, CalculatePerVertex) {
59 LineVertexShader::PerVertexData per_vertex[4];
60 auto geometry = std::make_unique<LineGeometry>(
61 /*p0=*/Point{100, 100}, //
62 /*p1=*/Point{200, 100}, //
63 /*width=*/5.f, //
64 /*cap=*/Cap::kButt);
65 Matrix transform;
66
67 fml::StatusOr<LineContents::EffectiveLineParameters> status =
68 LineContents::CalculatePerVertex(per_vertex, geometry.get(), transform);
69 Scalar offset =
70 (LineContents::kSampleRadius * 2.0 + geometry->GetWidth()) / 2.f;
71 ASSERT_TRUE(status.ok());
72 EXPECT_EQ(status.value().width, 5.f);
73 EXPECT_EQ(status.value().radius, LineContents::kSampleRadius);
74 EXPECT_POINT_NEAR(per_vertex[0].position,
75 Point(100 - LineContents::kSampleRadius, 100 + offset));
76 EXPECT_POINT_NEAR(per_vertex[1].position,
77 Point(200 + LineContents::kSampleRadius, 100 + offset));
78 EXPECT_POINT_NEAR(per_vertex[2].position,
79 Point(100 - LineContents::kSampleRadius, 100 - offset));
80 EXPECT_POINT_NEAR(per_vertex[3].position,
81 Point(200 + LineContents::kSampleRadius, 100 - offset));
82
83 for (int i = 1; i < 4; ++i) {
84 EXPECT_VECTOR3_NEAR(per_vertex[0].e0, per_vertex[i].e0) << i;
85 EXPECT_VECTOR3_NEAR(per_vertex[0].e1, per_vertex[i].e1) << i;
86 EXPECT_VECTOR3_NEAR(per_vertex[0].e2, per_vertex[i].e2) << i;
87 EXPECT_VECTOR3_NEAR(per_vertex[0].e3, per_vertex[i].e3) << i;
88 }
89
90 EXPECT_EQ(CalculateLine(per_vertex[0], Point(0, 0)), 0.f);
91 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 + offset)), 0.f,
92 kEhCloseEnough);
93 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 + offset * 0.5)),
94 0.5f, kEhCloseEnough);
95 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100)), 1.f,
96 kEhCloseEnough);
97 }
98
99 TEST(LineContents, CreateCurveData) {
100 std::vector<uint8_t> data = LineContents::CreateCurveData(/*width=*/31,
101 /*radius=*/1,
102 /*scale=*/1);
103 EXPECT_EQ(data.size(), 32u);
104 EXPECT_NEAR(data[0] / 255.f, 0.f, kEhCloseEnough);
105 EXPECT_NEAR(data[1] / 255.f, 0.5f, 0.02);
106 EXPECT_NEAR(data[2] / 255.f, 1.f, kEhCloseEnough);
107 EXPECT_NEAR(data[3] / 255.f, 1.f, kEhCloseEnough);
108 }
109
110 TEST(LineContents, CreateCurveDataScaled) {
111 std::vector<uint8_t> data = LineContents::CreateCurveData(/*width=*/15.5,
112 /*radius=*/1,
113 /*scale=*/2);
114 EXPECT_EQ(data.size(), 32u);
115 EXPECT_NEAR(data[0] / 255.f, 0.f, kEhCloseEnough);
116 EXPECT_NEAR(data[1] / 255.f, 0.5f, 0.02);
117 EXPECT_NEAR(data[2] / 255.f, 1.f, kEhCloseEnough);
118 EXPECT_NEAR(data[3] / 255.f, 1.f, kEhCloseEnough);
119 }
120
121 // This scales the line to be less than 1 pixel.
122 TEST(LineContents, CalculatePerVertexLimit) {
123 LineVertexShader::PerVertexData per_vertex[4];
124 Scalar scale = 0.05;
125 auto geometry = std::make_unique<LineGeometry>(
126 /*p0=*/Point{100, 100}, //
127 /*p1=*/Point{200, 100}, //
128 /*width=*/10.f, //
129 /*cap=*/Cap::kButt);
130 Matrix transform = Matrix::MakeTranslation({100, 100, 1.0}) *
131 Matrix::MakeScale({scale, scale, 1.0}) *
132 Matrix::MakeTranslation({-100, -100, 1.0});
133
134 fml::StatusOr<LineContents::EffectiveLineParameters> status =
135 LineContents::CalculatePerVertex(per_vertex, geometry.get(), transform);
136
137 Scalar one_radius_size = std::max(LineContents::kSampleRadius / scale,
138 LineContents::kSampleRadius);
139 Scalar one_px_size = 1.f / scale;
140 Scalar offset = one_px_size / 2.f + one_radius_size;
141 ASSERT_TRUE(status.ok());
142 EXPECT_NEAR(status.value().width, 20.f, kEhCloseEnough);
143 EXPECT_NEAR(status.value().radius, one_px_size * LineContents::kSampleRadius,
144 kEhCloseEnough);
145 EXPECT_POINT_NEAR(per_vertex[0].position,
146 Point(100 - one_radius_size, 100 + offset));
147 EXPECT_POINT_NEAR(per_vertex[1].position,
148 Point(200 + one_radius_size, 100 + offset));
149 EXPECT_POINT_NEAR(per_vertex[2].position,
150 Point(100 - one_radius_size, 100 - offset));
151 EXPECT_POINT_NEAR(per_vertex[3].position,
152 Point(200 + one_radius_size, 100 - offset));
153
154 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100)), 1.f,
155 kEhCloseEnough);
156 // EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 +
157 // one_px_size)), 1.f,
158 // kEhCloseEnough);
159 }
160
161 } // namespace testing
162 } // namespace impeller
impeller::Entity
Definition: entity.h:20
impeller::Entity::GetCoverage
std::optional< Rect > GetCoverage() const
Definition: entity.cc:64
impeller::LineContents
Definition: line_contents.h:15
impeller::LineContents::Make
static std::unique_ptr< LineContents > Make(std::unique_ptr< LineGeometry > geometry, Color color)
Definition: line_contents.cc:137
impeller::LineContents::CreateCurveData
static std::vector< uint8_t > CreateCurveData(Scalar width, Scalar radius, Scalar scale)
Definition: line_contents.cc:198
impeller::LineContents::kSampleRadius
static const Scalar kSampleRadius
Definition: line_contents.h:17
impeller::LineContents::CalculatePerVertex
static fml::StatusOr< EffectiveLineParameters > CalculatePerVertex(LineVertexShader::PerVertexData *per_vertex, const LineGeometry *geometry, const Matrix &entity_transform)
Definition: line_contents.cc:227
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:54
x
int32_t x
Definition: dl_golden_unittests.cc:458
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
geometry_asserts.h
EXPECT_VECTOR3_NEAR
#define EXPECT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:206
EXPECT_POINT_NEAR
#define EXPECT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:205
e0
Vector3 e0
Definition: line_contents.cc:106
e3
Vector3 e3
Definition: line_contents.cc:109
e2
Vector3 e2
Definition: line_contents.cc:108
e1
Vector3 e1
Definition: line_contents.cc:107
line_contents.h
impeller::interop::Create
ScopedObject< Object > Create(CtorArgs &&... args)
Definition: object.h:161
impeller::testing::TEST
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Definition: allocation_size_unittests.cc:10
impeller
Definition: allocation.cc:12
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:57
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::Cap::kButt
@ kButt
impeller::Cap::kSquare
@ kSquare
scale
const Scalar scale
Definition: stroke_path_geometry.cc:319
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:322
impeller::Color
Definition: color.h:124
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
impeller::TPoint< Scalar >
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67