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