| Flutter Impeller |

line_geometry.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/geometry/line_geometry.h"
6
7 namespace impeller {
8
9 LineGeometry::LineGeometry(Point p0, Point p1, Scalar width, Cap cap)
10 : p0_(p0), p1_(p1), width_(width), cap_(cap) {
11 FML_DCHECK(width >= 0);
12 }
13
14 Scalar LineGeometry::ComputePixelHalfWidth(const Matrix& transform,
15 Scalar width) {
16 auto determinant = transform.GetDeterminant();
17 if (determinant == 0) {
18 return 0.0f;
19 }
20
21 Scalar min_size = 1.0f / sqrt(std::abs(determinant));
22 return std::max(width, min_size) * 0.5f;
23 }
24
25 Vector2 LineGeometry::ComputeAlongVector(const Matrix& transform,
26 bool allow_zero_length) const {
27 Scalar stroke_half_width = ComputePixelHalfWidth(transform, width_);
28 if (stroke_half_width < kEhCloseEnough) {
29 return {};
30 }
31
32 auto along = p1_ - p0_;
33 Scalar length = along.GetLength();
34 if (length < kEhCloseEnough) {
35 if (!allow_zero_length) {
36 // We won't enclose any pixels unless the endpoints are extended
37 return {};
38 }
39 return {stroke_half_width, 0};
40 } else {
41 return along * stroke_half_width / length;
42 }
43 }
44
45 bool LineGeometry::ComputeCorners(Point corners[4],
46 const Matrix& transform,
47 bool extend_endpoints) const {
48 auto along = ComputeAlongVector(transform, extend_endpoints);
49 if (along.IsZero()) {
50 return false;
51 }
52
53 auto across = Vector2(along.y, -along.x);
54 corners[0] = p0_ - across;
55 corners[1] = p1_ - across;
56 corners[2] = p0_ + across;
57 corners[3] = p1_ + across;
58 if (extend_endpoints) {
59 corners[0] -= along;
60 corners[1] += along;
61 corners[2] -= along;
62 corners[3] += along;
63 }
64 return true;
65 }
66
67 GeometryResult LineGeometry::GetPositionBuffer(const ContentContext& renderer,
68 const Entity& entity,
69 RenderPass& pass) const {
70 using VT = SolidFillVertexShader::PerVertexData;
71
72 auto& transform = entity.GetTransform();
73 auto radius = ComputePixelHalfWidth(transform, width_);
74
75 if (cap_ == Cap::kRound) {
76 std::shared_ptr<Tessellator> tessellator = renderer.GetTessellator();
77 auto generator = tessellator->RoundCapLine(transform, p0_, p1_, radius);
78 return ComputePositionGeometry(generator, entity, pass);
79 }
80
81 Point corners[4];
82 if (!ComputeCorners(corners, transform, cap_ == Cap::kSquare)) {
83 return kEmptyResult;
84 }
85
86 auto& host_buffer = pass.GetTransientsBuffer();
87
88 size_t count = 4;
89 BufferView vertex_buffer = host_buffer.Emplace(
90 count * sizeof(VT), alignof(VT), [&corners](uint8_t* buffer) {
91 auto vertices = reinterpret_cast<VT*>(buffer);
92 for (auto& corner : corners) {
93 *vertices++ = {
94 .position = corner,
95 };
96 }
97 });
98
99 return GeometryResult{
100 .type = PrimitiveType::kTriangleStrip,
101 .vertex_buffer =
102 {
103 .vertex_buffer = vertex_buffer,
104 .vertex_count = count,
105 .index_type = IndexType::kNone,
106 },
107 .transform = pass.GetOrthographicTransform() * entity.GetTransform(),
108 .prevent_overdraw = false,
109 };
110 }
111
112 // |Geometry|
113 GeometryResult LineGeometry::GetPositionUVBuffer(Rect texture_coverage,
114 Matrix effect_transform,
115 const ContentContext& renderer,
116 const Entity& entity,
117 RenderPass& pass) const {
118 auto& host_buffer = pass.GetTransientsBuffer();
119 using VT = TextureFillVertexShader::PerVertexData;
120
121 auto& transform = entity.GetTransform();
122 auto radius = ComputePixelHalfWidth(transform, width_);
123
124 auto uv_transform =
125 texture_coverage.GetNormalizingTransform() * effect_transform;
126
127 if (cap_ == Cap::kRound) {
128 std::shared_ptr<Tessellator> tessellator = renderer.GetTessellator();
129 auto generator = tessellator->RoundCapLine(transform, p0_, p1_, radius);
130 return ComputePositionUVGeometry(generator, uv_transform, entity, pass);
131 }
132
133 Point corners[4];
134 if (!ComputeCorners(corners, transform, cap_ == Cap::kSquare)) {
135 return kEmptyResult;
136 }
137
138 size_t count = 4;
139 BufferView vertex_buffer =
140 host_buffer.Emplace(count * sizeof(VT), alignof(VT),
141 [&uv_transform, &corners](uint8_t* buffer) {
142 auto vertices = reinterpret_cast<VT*>(buffer);
143 for (auto& corner : corners) {
144 *vertices++ = {
145 .position = corner,
146 .texture_coords = uv_transform * corner,
147 };
148 }
149 });
150
151 return GeometryResult{
152 .type = PrimitiveType::kTriangleStrip,
153 .vertex_buffer =
154 {
155 .vertex_buffer = vertex_buffer,
156 .vertex_count = count,
157 .index_type = IndexType::kNone,
158 },
159 .transform = pass.GetOrthographicTransform() * entity.GetTransform(),
160 .prevent_overdraw = false,
161 };
162 }
163
164 GeometryVertexType LineGeometry::GetVertexType() const {
165 return GeometryVertexType::kPosition;
166 }
167
168 std::optional<Rect> LineGeometry::GetCoverage(const Matrix& transform) const {
169 Point corners[4];
170 if (!ComputeCorners(corners, transform, cap_ != Cap::kButt)) {
171 return {};
172 }
173
174 for (int i = 0; i < 4; i++) {
175 corners[i] = transform * corners[i];
176 }
177 return Rect::MakePointBounds(std::begin(corners), std::end(corners));
178 }
179
180 bool LineGeometry::CoversArea(const Matrix& transform, const Rect& rect) const {
181 if (!transform.IsTranslationScaleOnly() || !IsAxisAlignedRect()) {
182 return false;
183 }
184 auto coverage = GetCoverage(transform);
185 return coverage.has_value() ? coverage->Contains(rect) : false;
186 }
187
188 bool LineGeometry::IsAxisAlignedRect() const {
189 return cap_ != Cap::kRound && (p0_.x == p1_.x || p0_.y == p1_.y);
190 }
191
192 } // namespace impeller
impeller::Cap::kRound
@ kRound
impeller::Cap::kSquare
@ kSquare
impeller::TPoint::y
Type y
Definition: point.h:26
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::Vector2
Point Vector2
Definition: point.h:312
impeller::Matrix::GetDeterminant
Scalar GetDeterminant() const
Definition: matrix.cc:162
impeller::LineGeometry::LineGeometry
LineGeometry(Point p0, Point p1, Scalar width, Cap cap)
Definition: line_geometry.cc:9
impeller::Cap::kButt
@ kButt
impeller::GeometryVertexType
GeometryVertexType
Definition: geometry.h:34
impeller::TRect< Scalar >::MakePointBounds
constexpr static std::optional< TRect > MakePointBounds(const U &value)
Definition: rect.h:49
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:21
impeller::LineGeometry::CoversArea
bool CoversArea(const Matrix &transform, const Rect &rect) const override
Determines if this geometry, transformed by the given transform, will completely cover all surface ar...
Definition: line_geometry.cc:180
impeller::Matrix::IsTranslationScaleOnly
constexpr bool IsTranslationScaleOnly() const
Returns true if the matrix has a scale-only basis and is non-projective. Note that an identity matrix...
Definition: matrix.h:360
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::Geometry::ComputePositionGeometry
static GeometryResult ComputePositionGeometry(const Tessellator::VertexGenerator &generator, const Entity &entity, RenderPass &pass)
Definition: geometry.cc:23
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:488
impeller::LineGeometry::IsAxisAlignedRect
bool IsAxisAlignedRect() const override
Definition: line_geometry.cc:188
impeller::LineGeometry::ComputePixelHalfWidth
static Scalar ComputePixelHalfWidth(const Matrix &transform, Scalar width)
Definition: line_geometry.cc:14
impeller::TPoint::x
Type x
Definition: point.h:25
impeller::kEmptyResult
static const GeometryResult kEmptyResult
Definition: geometry.h:27
impeller::TPoint< Scalar >
line_geometry.h
impeller
Definition: aiks_context.cc:10
impeller::Geometry::ComputePositionUVGeometry
static GeometryResult ComputePositionUVGeometry(const Tessellator::VertexGenerator &generator, const Matrix &uv_transform, const Entity &entity, RenderPass &pass)
Definition: geometry.cc:55
impeller::kPosition
@ kPosition
Definition: geometry.h:35
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Cap
Cap
Definition: path.h:18