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 
6 
7 namespace impeller {
8 
10  : p0_(p0), p1_(p1), width_(width), cap_(cap) {
11  FML_DCHECK(width >= 0);
12 }
13 
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(renderer, 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 = renderer.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{
101  .vertex_buffer =
102  {
103  .vertex_buffer = vertex_buffer,
104  .vertex_count = count,
105  .index_type = IndexType::kNone,
106  },
107  .transform = entity.GetShaderTransform(pass),
108  };
109 }
110 
111 // |Geometry|
112 GeometryResult LineGeometry::GetPositionUVBuffer(Rect texture_coverage,
113  Matrix effect_transform,
114  const ContentContext& renderer,
115  const Entity& entity,
116  RenderPass& pass) const {
117  auto& host_buffer = renderer.GetTransientsBuffer();
118  using VT = TextureFillVertexShader::PerVertexData;
119 
120  auto& transform = entity.GetTransform();
121  auto radius = ComputePixelHalfWidth(transform, width_);
122 
123  auto uv_transform =
124  texture_coverage.GetNormalizingTransform() * effect_transform;
125 
126  if (cap_ == Cap::kRound) {
127  std::shared_ptr<Tessellator> tessellator = renderer.GetTessellator();
128  auto generator = tessellator->RoundCapLine(transform, p0_, p1_, radius);
129  return ComputePositionUVGeometry(renderer, generator, uv_transform, entity,
130  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{
153  .vertex_buffer =
154  {
155  .vertex_buffer = vertex_buffer,
156  .vertex_count = count,
157  .index_type = IndexType::kNone,
158  },
159  .transform = entity.GetShaderTransform(pass),
160  };
161 }
162 
163 GeometryVertexType LineGeometry::GetVertexType() const {
165 }
166 
167 std::optional<Rect> LineGeometry::GetCoverage(const Matrix& transform) const {
168  Point corners[4];
169  if (!ComputeCorners(corners, transform, cap_ != Cap::kButt)) {
170  return {};
171  }
172 
173  for (int i = 0; i < 4; i++) {
174  corners[i] = transform * corners[i];
175  }
176  return Rect::MakePointBounds(std::begin(corners), std::end(corners));
177 }
178 
179 bool LineGeometry::CoversArea(const Matrix& transform, const Rect& rect) const {
180  if (!transform.IsTranslationScaleOnly() || !IsAxisAlignedRect()) {
181  return false;
182  }
183  auto coverage = GetCoverage(transform);
184  return coverage.has_value() ? coverage->Contains(rect) : false;
185 }
186 
188  return cap_ != Cap::kRound && (p0_.x == p1_.x || p0_.y == p1_.y);
189 }
190 
191 } // namespace impeller
impeller::Cap::kRound
@ kRound
impeller::Cap::kSquare
@ kSquare
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::Vector2
Point Vector2
Definition: point.h:320
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:49
impeller::TRect< Scalar >::MakePointBounds
constexpr static std::optional< TRect > MakePointBounds(const U &value)
Definition: rect.h:151
impeller::Geometry::ComputePositionGeometry
static GeometryResult ComputePositionGeometry(const ContentContext &renderer, const Tessellator::VertexGenerator &generator, const Entity &entity, RenderPass &pass)
Definition: geometry.cc:25
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:36
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:179
impeller::Geometry::ComputePositionUVGeometry
static GeometryResult ComputePositionUVGeometry(const ContentContext &renderer, const Tessellator::VertexGenerator &generator, const Matrix &uv_transform, const Entity &entity, RenderPass &pass)
Definition: geometry.cc:57
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:363
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:661
impeller::LineGeometry::IsAxisAlignedRect
bool IsAxisAlignedRect() const override
Definition: line_geometry.cc:187
impeller::LineGeometry::ComputePixelHalfWidth
static Scalar ComputePixelHalfWidth(const Matrix &transform, Scalar width)
Definition: line_geometry.cc:14
impeller::TPoint::x
Type x
Definition: point.h:30
impeller::kEmptyResult
static const GeometryResult kEmptyResult
Definition: geometry.h:42
impeller::TPoint< Scalar >
line_geometry.h
impeller
Definition: aiks_blur_unittests.cc:20
impeller::kPosition
@ kPosition
Definition: geometry.h:50
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Cap
Cap
Definition: path.h:17