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 
7 
8 namespace impeller {
9 
11  : p0_(p0), p1_(p1), width_(width), cap_(cap) {
12  FML_DCHECK(width >= 0);
13 }
14 
15 LineGeometry::~LineGeometry() = default;
16 
18  Scalar width) {
19  Scalar max_basis = transform.GetMaxBasisLengthXY();
20  if (max_basis == 0) {
21  return {};
22  }
23 
24  Scalar min_size = kMinStrokeSize / max_basis;
25  return std::max(width, min_size) * 0.5f;
26 }
27 
28 Vector2 LineGeometry::ComputeAlongVector(const Matrix& transform,
29  bool allow_zero_length) const {
30  Scalar stroke_half_width = ComputePixelHalfWidth(transform, width_);
31  if (stroke_half_width < kEhCloseEnough) {
32  return {};
33  }
34 
35  auto along = p1_ - p0_;
36  Scalar length = along.GetLength();
37  if (length < kEhCloseEnough) {
38  if (!allow_zero_length) {
39  // We won't enclose any pixels unless the endpoints are extended
40  return {};
41  }
42  return {stroke_half_width, 0};
43  } else {
44  return along * stroke_half_width / length;
45  }
46 }
47 
48 bool LineGeometry::ComputeCorners(Point corners[4],
49  const Matrix& transform,
50  bool extend_endpoints) const {
51  auto along = ComputeAlongVector(transform, extend_endpoints);
52  if (along.IsZero()) {
53  return false;
54  }
55 
56  auto across = Vector2(along.y, -along.x);
57  corners[0] = p0_ - across;
58  corners[1] = p1_ - across;
59  corners[2] = p0_ + across;
60  corners[3] = p1_ + across;
61  if (extend_endpoints) {
62  corners[0] -= along;
63  corners[1] += along;
64  corners[2] -= along;
65  corners[3] += along;
66  }
67  return true;
68 }
69 
71  return Geometry::ComputeStrokeAlphaCoverage(entity, width_);
72 }
73 
74 GeometryResult LineGeometry::GetPositionBuffer(const ContentContext& renderer,
75  const Entity& entity,
76  RenderPass& pass) const {
77  using VT = SolidFillVertexShader::PerVertexData;
78 
79  auto& transform = entity.GetTransform();
80  auto radius = ComputePixelHalfWidth(transform, width_);
81 
82  if (cap_ == Cap::kRound) {
83  auto generator =
84  renderer.GetTessellator().RoundCapLine(transform, p0_, p1_, radius);
85  return ComputePositionGeometry(renderer, generator, entity, pass);
86  }
87 
88  Point corners[4];
89  if (!ComputeCorners(corners, transform, cap_ == Cap::kSquare)) {
90  return kEmptyResult;
91  }
92 
93  auto& host_buffer = renderer.GetTransientsBuffer();
94 
95  size_t count = 4;
96  BufferView vertex_buffer = host_buffer.Emplace(
97  count * sizeof(VT), alignof(VT), [&corners](uint8_t* buffer) {
98  auto vertices = reinterpret_cast<VT*>(buffer);
99  for (auto& corner : corners) {
100  *vertices++ = {
101  .position = corner,
102  };
103  }
104  });
105 
106  return GeometryResult{
108  .vertex_buffer =
109  {
110  .vertex_buffer = vertex_buffer,
111  .vertex_count = count,
112  .index_type = IndexType::kNone,
113  },
114  .transform = entity.GetShaderTransform(pass),
115  };
116 }
117 
118 std::optional<Rect> LineGeometry::GetCoverage(const Matrix& transform) const {
119  Point corners[4];
120  // Note: MSAA boolean doesn't matter for coverage computation.
121  if (!ComputeCorners(corners, transform, cap_ != Cap::kButt)) {
122  return {};
123  }
124 
125  for (int i = 0; i < 4; i++) {
126  corners[i] = transform * corners[i];
127  }
128  return Rect::MakePointBounds(std::begin(corners), std::end(corners));
129 }
130 
131 bool LineGeometry::CoversArea(const Matrix& transform, const Rect& rect) const {
132  if (!transform.IsTranslationScaleOnly() || !IsAxisAlignedRect()) {
133  return false;
134  }
135  auto coverage = GetCoverage(transform);
136  return coverage.has_value() ? coverage->Contains(rect) : false;
137 }
138 
140  return cap_ != Cap::kRound && (p0_.x == p1_.x || p0_.y == p1_.y);
141 }
142 
143 } // namespace impeller
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Tessellator & GetTessellator() const
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:48
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:44
static Scalar ComputeStrokeAlphaCoverage(const Matrix &entity, Scalar stroke_width)
Compute an alpha value to simulate lower coverage of fractional pixel strokes.
Definition: geometry.cc:126
static GeometryResult ComputePositionGeometry(const ContentContext &renderer, const Tessellator::VertexGenerator &generator, const Entity &entity, RenderPass &pass)
Definition: geometry.cc:23
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Definition: host_buffer.h:93
LineGeometry(Point p0, Point p1, Scalar width, Cap cap)
static Scalar ComputePixelHalfWidth(const Matrix &transform, Scalar width)
bool IsAxisAlignedRect() const override
Scalar ComputeAlphaCoverage(const Matrix &transform) const override
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...
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
EllipticalVertexGenerator RoundCapLine(const Matrix &view_transform, const Point &p0, const Point &p1, Scalar radius)
Create a |VertexGenerator| that can produce vertices for a line with round end caps of the given radi...
Definition: tessellator.cc:376
@ kNone
Does not use the index buffer.
Point Vector2
Definition: point.h:331
float Scalar
Definition: scalar.h:18
constexpr float kEhCloseEnough
Definition: constants.h:56
TPoint< Scalar > Point
Definition: point.h:327
Cap
Definition: path.h:19
static const GeometryResult kEmptyResult
Definition: geometry.h:43
static constexpr Scalar kMinStrokeSize
Definition: geometry.h:19
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
constexpr static std::optional< TRect > MakePointBounds(const U &value)
Definition: rect.h:165