| 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 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
70 Scalar LineGeometry::ComputeAlphaCoverage(const Matrix& entity) const {
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{
107 .type = PrimitiveType::kTriangleStrip,
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
139 bool LineGeometry::IsAxisAlignedRect() const {
140 return cap_ != Cap::kRound && (p0_.x == p1_.x || p0_.y == p1_.y);
141 }
142
143 } // namespace impeller
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:48
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:93
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:44
impeller::LineGeometry::ComputeAlphaCoverage
Scalar ComputeAlphaCoverage(const Matrix &transform) const override
Definition: line_geometry.cc:70
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::ContentContext::GetTessellator
Tessellator & GetTessellator() const
Definition: content_context.cc:609
impeller::kMinStrokeSize
static constexpr Scalar kMinStrokeSize
Definition: geometry.h:19
impeller::TRect< Scalar >::MakePointBounds
constexpr static std::optional< TRect > MakePointBounds(const U &value)
Definition: rect.h:165
impeller::Geometry::ComputePositionGeometry
static GeometryResult ComputePositionGeometry(const ContentContext &renderer, const Tessellator::VertexGenerator &generator, const Entity &entity, RenderPass &pass)
Definition: geometry.cc:23
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:131
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
impeller::GeometryResult
Definition: geometry.h:21
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::LineGeometry::IsAxisAlignedRect
bool IsAxisAlignedRect() const override
Definition: line_geometry.cc:139
impeller::LineGeometry::ComputePixelHalfWidth
static Scalar ComputePixelHalfWidth(const Matrix &transform, Scalar width)
Definition: line_geometry.cc:17
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:30
impeller::kEmptyResult
static const GeometryResult kEmptyResult
Definition: geometry.h:43
impeller::Tessellator::RoundCapLine
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
impeller::TPoint< Scalar >
line_geometry.h
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:126
impeller
Definition: allocation.cc:12
impeller::ContentContext
Definition: content_context.h:371
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:866
impeller::Cap
Cap
Definition: path.h:19
impeller::LineGeometry::~LineGeometry
~LineGeometry() override