| 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 #include "impeller/entity/geometry/geometry.h"
7
8 namespace impeller {
9
10 LineGeometry::LineGeometry(Point p0, Point p1, Scalar width, Cap cap)
11 : p0_(p0), p1_(p1), width_(width), cap_(cap) {
12 FML_DCHECK(width >= 0);
13 }
14
15 LineGeometry::~LineGeometry() = default;
16
17 Scalar LineGeometry::ComputePixelHalfWidth(const Matrix& transform,
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
73 Scalar LineGeometry::ComputeAlphaCoverage(const Matrix& entity) const {
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,
94 pass.GetSampleCount() == SampleCount::kCount4)) {
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{
112 .type = PrimitiveType::kTriangleStrip,
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
144 bool LineGeometry::IsAxisAlignedRect() const {
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