Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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
6
7#include <algorithm>
8
10#include "third_party/googletest/googletest/include/gtest/gtest.h"
11
12namespace impeller {
13namespace testing {
14
15namespace {
16float lookup(Scalar x) {
17 return std::clamp(x, /*lo=*/0.f, /*hi=*/1.f);
18}
19
20// This mirrors the function in line.frag.
21float 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
38 Scalar width = 5.0f;
39 auto geometry = std::make_unique<LineGeometry>(
40 /*p0=*/Point{0, 0}, //
41 /*p1=*/Point{100, 100}, //
43 .width = width,
44 .cap = Cap::kSquare,
45 });
46 std::unique_ptr<LineContents> contents =
47 LineContents::Make(std::move(geometry), Color(1.f, 0.f, 0.f, 1.f));
48 EXPECT_TRUE(contents);
49 Entity entity;
50 std::optional<Rect> coverage = contents->GetCoverage(entity);
51 EXPECT_TRUE(coverage.has_value());
52 if (coverage.has_value()) {
53 Scalar lip = sqrt((width * width) / 2.f);
54 EXPECT_EQ(*coverage,
55 Rect::MakeXYWH(-lip, -lip, 100 + 2 * lip, 100 + 2 * lip));
56 }
57}
58
59TEST(LineContents, CalculatePerVertex) {
60 LineVertexShader::PerVertexData per_vertex[4];
61 auto geometry = std::make_unique<LineGeometry>(
62 /*p0=*/Point{100, 100}, //
63 /*p1=*/Point{200, 100}, //
65 .width = 5.f,
66 .cap = Cap::kButt,
67 });
69
71 LineContents::CalculatePerVertex(per_vertex, geometry.get(), transform);
72 Scalar offset =
73 (LineContents::kSampleRadius * 2.0 + geometry->GetWidth()) / 2.f;
74 ASSERT_TRUE(status.ok());
75 EXPECT_EQ(status.value().width, 5.f);
76 EXPECT_EQ(status.value().radius, LineContents::kSampleRadius);
77 EXPECT_POINT_NEAR(per_vertex[0].position,
78 Point(100 - LineContents::kSampleRadius, 100 + offset));
79 EXPECT_POINT_NEAR(per_vertex[1].position,
80 Point(200 + LineContents::kSampleRadius, 100 + offset));
81 EXPECT_POINT_NEAR(per_vertex[2].position,
82 Point(100 - LineContents::kSampleRadius, 100 - offset));
83 EXPECT_POINT_NEAR(per_vertex[3].position,
84 Point(200 + LineContents::kSampleRadius, 100 - offset));
85
86 for (int i = 1; i < 4; ++i) {
87 EXPECT_VECTOR3_NEAR(per_vertex[0].e0, per_vertex[i].e0) << i;
88 EXPECT_VECTOR3_NEAR(per_vertex[0].e1, per_vertex[i].e1) << i;
89 EXPECT_VECTOR3_NEAR(per_vertex[0].e2, per_vertex[i].e2) << i;
90 EXPECT_VECTOR3_NEAR(per_vertex[0].e3, per_vertex[i].e3) << i;
91 }
92
93 EXPECT_EQ(CalculateLine(per_vertex[0], Point(0, 0)), 0.f);
94 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 + offset)), 0.f,
96 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 + offset * 0.5)),
97 0.5f, kEhCloseEnough);
98 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100)), 1.f,
100}
101
102TEST(LineContents, CreateCurveData) {
103 std::vector<uint8_t> data = LineContents::CreateCurveData(/*width=*/31,
104 /*radius=*/1,
105 /*scale=*/1);
106 EXPECT_EQ(data.size(), 32u);
107 EXPECT_NEAR(data[0] / 255.f, 0.f, kEhCloseEnough);
108 EXPECT_NEAR(data[1] / 255.f, 0.5f, 0.02);
109 EXPECT_NEAR(data[2] / 255.f, 1.f, kEhCloseEnough);
110 EXPECT_NEAR(data[3] / 255.f, 1.f, kEhCloseEnough);
111}
112
113TEST(LineContents, CreateCurveDataScaled) {
114 std::vector<uint8_t> data = LineContents::CreateCurveData(/*width=*/15.5,
115 /*radius=*/1,
116 /*scale=*/2);
117 EXPECT_EQ(data.size(), 32u);
118 EXPECT_NEAR(data[0] / 255.f, 0.f, kEhCloseEnough);
119 EXPECT_NEAR(data[1] / 255.f, 0.5f, 0.02);
120 EXPECT_NEAR(data[2] / 255.f, 1.f, kEhCloseEnough);
121 EXPECT_NEAR(data[3] / 255.f, 1.f, kEhCloseEnough);
122}
123
124TEST(LineContents, CreateCurveDataHairline) {
125 std::vector<uint8_t> data = LineContents::CreateCurveData(/*width=*/0.0,
126 /*radius=*/1.0,
127 /*scale=*/1.0);
128 EXPECT_EQ(data.size(), 32u);
129 EXPECT_NEAR(data[data.size() - 1] / 255.f, 1.f, kEhCloseEnough);
130}
131
132TEST(LineContents, CreateCurveDataVeryThin) {
133 std::vector<uint8_t> data = LineContents::CreateCurveData(/*width=*/0.01,
134 /*radius=*/1.0,
135 /*scale=*/1.0);
136 EXPECT_EQ(data.size(), 32u);
137 EXPECT_NEAR(data[data.size() - 1] / 255.f, 1.f, kEhCloseEnough);
138}
139
140// This scales the line to be less than 1 pixel.
141TEST(LineContents, CalculatePerVertexLimit) {
142 LineVertexShader::PerVertexData per_vertex[4];
143 Scalar scale = 0.05;
144 auto geometry = std::make_unique<LineGeometry>(
145 /*p0=*/Point{100, 100}, //
146 /*p1=*/Point{200, 100}, //
148 .width = 10.f,
149 .cap = Cap::kButt,
150 });
151 Matrix transform = Matrix::MakeTranslation({100, 100, 1.0}) *
152 Matrix::MakeScale({scale, scale, 1.0}) *
153 Matrix::MakeTranslation({-100, -100, 1.0});
154
156 LineContents::CalculatePerVertex(per_vertex, geometry.get(), transform);
157
158 Scalar one_radius_size = std::max(LineContents::kSampleRadius / scale,
160 Scalar one_px_size = 1.f / scale;
161 Scalar offset = one_px_size / 2.f + one_radius_size;
162 ASSERT_TRUE(status.ok());
163 EXPECT_NEAR(status.value().width, 20.f, kEhCloseEnough);
164 EXPECT_NEAR(status.value().radius, one_px_size * LineContents::kSampleRadius,
166 EXPECT_POINT_NEAR(per_vertex[0].position,
167 Point(100 - one_radius_size, 100 + offset));
168 EXPECT_POINT_NEAR(per_vertex[1].position,
169 Point(200 + one_radius_size, 100 + offset));
170 EXPECT_POINT_NEAR(per_vertex[2].position,
171 Point(100 - one_radius_size, 100 - offset));
172 EXPECT_POINT_NEAR(per_vertex[3].position,
173 Point(200 + one_radius_size, 100 - offset));
174
175 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100)), 1.f,
177 // EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 +
178 // one_px_size)), 1.f,
179 // kEhCloseEnough);
180}
181
182} // namespace testing
183} // namespace impeller
const T & value() const
Definition status_or.h:77
bool ok() const
Definition status_or.h:75
std::optional< Rect > GetCoverage() const
Definition entity.cc:66
static std::unique_ptr< LineContents > Make(std::unique_ptr< LineGeometry > geometry, Color color)
static std::vector< uint8_t > CreateCurveData(Scalar width, Scalar radius, Scalar scale)
static const Scalar kSampleRadius
static fml::StatusOr< EffectiveLineParameters > CalculatePerVertex(LineVertexShader::PerVertexData *per_vertex, const LineGeometry *geometry, const Matrix &entity_transform)
int32_t x
auto & d
Definition main.cc:28
#define EXPECT_VECTOR3_NEAR(a, b)
#define EXPECT_POINT_NEAR(a, b)
Vector3 e0
Vector3 e3
Vector3 e2
Vector3 e1
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 data
Definition switch_defs.h:36
static constexpr DlScalar kEhCloseEnough
float Scalar
Definition scalar.h:19
int32_t width
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
A structure to store all of the parameters related to stroking a path or basic geometry object.
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136