| Flutter Impeller |

rect_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/rect_geometry.h"
6
7 namespace impeller {
8
9 FillRectGeometry::FillRectGeometry(Rect rect) : rect_(rect) {}
10
11 FillRectGeometry::~FillRectGeometry() = default;
12
13 GeometryResult FillRectGeometry::GetPositionBuffer(
14 const ContentContext& renderer,
15 const Entity& entity,
16 RenderPass& pass) const {
17 auto& host_buffer = renderer.GetTransientsBuffer();
18 return GeometryResult{
19 .type = PrimitiveType::kTriangleStrip,
20 .vertex_buffer =
21 {
22 .vertex_buffer = host_buffer.Emplace(
23 rect_.GetPoints().data(), 8 * sizeof(float), alignof(float)),
24 .vertex_count = 4,
25 .index_type = IndexType::kNone,
26 },
27 .transform = entity.GetShaderTransform(pass),
28 };
29 }
30
31 std::optional<Rect> FillRectGeometry::GetCoverage(
32 const Matrix& transform) const {
33 return rect_.TransformBounds(transform);
34 }
35
36 bool FillRectGeometry::CoversArea(const Matrix& transform,
37 const Rect& rect) const {
38 if (!transform.IsTranslationScaleOnly()) {
39 return false;
40 }
41 Rect coverage = rect_.TransformBounds(transform);
42 return coverage.Contains(rect);
43 }
44
45 bool FillRectGeometry::IsAxisAlignedRect() const {
46 return true;
47 }
48
49 StrokeRectGeometry::StrokeRectGeometry(const Rect& rect,
50 const StrokeParameters& stroke)
51 : rect_(rect),
52 stroke_width_(stroke.width),
53 stroke_join_(AdjustStrokeJoin(stroke)) {}
54
55 StrokeRectGeometry::~StrokeRectGeometry() = default;
56
57 GeometryResult StrokeRectGeometry::GetPositionBuffer(
58 const ContentContext& renderer,
59 const Entity& entity,
60 RenderPass& pass) const {
61 if (stroke_width_ < 0.0) {
62 return {};
63 }
64 Scalar max_basis = entity.GetTransform().GetMaxBasisLengthXY();
65 if (max_basis == 0) {
66 return {};
67 }
68
69 Scalar min_size = kMinStrokeSize / max_basis;
70 Scalar half_stroke_width = std::max(stroke_width_, min_size) * 0.5f;
71
72 auto& host_buffer = renderer.GetTransientsBuffer();
73 const Rect& rect = rect_;
74
75 switch (stroke_join_) {
76 case Join::kRound: {
77 Tessellator::Trigs trigs =
78 renderer.GetTessellator().GetTrigsForDeviceRadius(half_stroke_width *
79 max_basis);
80
81 FML_DCHECK(trigs.size() >= 2u);
82
83 // We use all but the first entry in trigs for each corner.
84 auto vertex_count = trigs.size() - 1;
85 // Every other point has a center vertex added.
86 vertex_count = vertex_count + (vertex_count >> 1);
87 // The loop also adds 3 points of its own.
88 vertex_count += 3;
89 // We do that for each of the 4 corners.
90 vertex_count = vertex_count * 4;
91 // We then add 2 more points at the end to close the last edge.
92 vertex_count += 2;
93
94 return GeometryResult{
95 .type = PrimitiveType::kTriangleStrip,
96 .vertex_buffer =
97 {
98 .vertex_buffer = host_buffer.Emplace(
99 vertex_count * sizeof(Point), alignof(Point),
100 [hsw = half_stroke_width, &rect, vertex_count,
101 &trigs](uint8_t* buffer) {
102 auto vertices = reinterpret_cast<Point*>(buffer);
103 [[maybe_unused]]
104 auto vertices_end = vertices + vertex_count;
105
106 vertices =
107 AppendRoundCornerJoin(vertices, rect.GetLeftTop(),
108 Vector2(-hsw, 0), trigs);
109 vertices =
110 AppendRoundCornerJoin(vertices, rect.GetRightTop(),
111 Vector2(0, -hsw), trigs);
112 vertices = AppendRoundCornerJoin(
113 vertices, rect.GetRightBottom(), Vector2(hsw, 0),
114 trigs);
115 vertices = AppendRoundCornerJoin(
116 vertices, rect.GetLeftBottom(), Vector2(0, hsw),
117 trigs);
118
119 // Repeat the first 2 points from the first corner to
120 // close the last edge.
121 *vertices++ = rect.GetLeftTop() - Vector2(hsw, 0);
122 *vertices++ = rect.GetLeftTop() + Vector2(hsw, 0);
123
124 // Make sure our estimate is always up to date.
125 FML_DCHECK(vertices == vertices_end);
126 }),
127 .vertex_count = vertex_count,
128 .index_type = IndexType::kNone,
129 },
130 .transform = entity.GetShaderTransform(pass),
131 };
132 }
133
134 case Join::kBevel: {
135 return GeometryResult{
136 .type = PrimitiveType::kTriangleStrip,
137 .vertex_buffer =
138 {
139 .vertex_buffer = host_buffer.Emplace(
140 17 * sizeof(Point), alignof(Point),
141 [hsw = half_stroke_width, &rect](uint8_t* buffer) {
142 Scalar left = rect.GetLeft();
143 Scalar top = rect.GetTop();
144 Scalar right = rect.GetRight();
145 Scalar bottom = rect.GetBottom();
146 auto vertices = reinterpret_cast<Point*>(buffer);
147 vertices[0] = Point(left, top - hsw);
148 vertices[1] = Point(left, top + hsw);
149 vertices[2] = Point(right, top - hsw);
150 vertices[3] = Point(right, top + hsw);
151 vertices[4] = Point(right + hsw, top);
152 vertices[5] = Point(right - hsw, top);
153 vertices[6] = Point(right + hsw, bottom);
154 vertices[7] = Point(right - hsw, bottom);
155 vertices[8] = Point(right, bottom + hsw);
156 vertices[9] = Point(right, bottom - hsw);
157 vertices[10] = Point(left, bottom + hsw);
158 vertices[11] = Point(left, bottom - hsw);
159 vertices[12] = Point(left - hsw, bottom);
160 vertices[13] = Point(left + hsw, bottom);
161 vertices[14] = Point(left - hsw, top);
162 vertices[15] = Point(left + hsw, top);
163 vertices[16] = Point(left, top - hsw);
164 }),
165 .vertex_count = 17u,
166 .index_type = IndexType::kNone,
167 },
168 .transform = entity.GetShaderTransform(pass),
169 };
170 }
171
172 case Join::kMiter: {
173 return GeometryResult{
174 .type = PrimitiveType::kTriangleStrip,
175 .vertex_buffer =
176 {
177 .vertex_buffer = host_buffer.Emplace(
178 10 * sizeof(Point), alignof(Point),
179 [hsw = half_stroke_width, &rect](uint8_t* buffer) {
180 Scalar left = rect.GetLeft();
181 Scalar top = rect.GetTop();
182 Scalar right = rect.GetRight();
183 Scalar bottom = rect.GetBottom();
184 auto vertices = reinterpret_cast<Point*>(buffer);
185 vertices[0] = Point(left - hsw, top - hsw);
186 vertices[1] = Point(left + hsw, top + hsw);
187 vertices[2] = Point(right + hsw, top - hsw);
188 vertices[3] = Point(right - hsw, top + hsw);
189 vertices[4] = Point(right + hsw, bottom + hsw);
190 vertices[5] = Point(right - hsw, bottom - hsw);
191 vertices[6] = Point(left - hsw, bottom + hsw);
192 vertices[7] = Point(left + hsw, bottom - hsw);
193 vertices[8] = Point(left - hsw, top - hsw);
194 vertices[9] = Point(left + hsw, top + hsw);
195 }),
196 .vertex_count = 10u,
197 .index_type = IndexType::kNone,
198 },
199 .transform = entity.GetShaderTransform(pass),
200 };
201 }
202 }
203 }
204
205 std::optional<Rect> StrokeRectGeometry::GetCoverage(
206 const Matrix& transform) const {
207 return rect_.TransformBounds(transform);
208 }
209
210 Join StrokeRectGeometry::AdjustStrokeJoin(const StrokeParameters& stroke) {
211 return (stroke.join == Join::kMiter && stroke.miter_limit < kSqrt2)
212 ? Join::kBevel
213 : stroke.join;
214 }
215
216 Point* StrokeRectGeometry::AppendRoundCornerJoin(
217 Point* buffer,
218 Point corner,
219 Vector2 offset,
220 const Tessellator::Trigs& trigs) {
221 // Close the edge box set up by the end of the last corner and
222 // set up the first wedge of this corner.
223 *buffer++ = corner + offset;
224 *buffer++ = corner - offset;
225 bool do_center = false;
226 auto trig = trigs.begin();
227 auto end = trigs.end();
228 while (++trig < end) {
229 if (do_center) {
230 *buffer++ = corner;
231 }
232 do_center = !do_center;
233 *buffer++ = corner + *trig * offset;
234 }
235 // Together with the last point pushed by the loop we set up to
236 // initiate the edge box connecting to the next corner.
237 *buffer++ = corner - end[-1] * offset;
238 return buffer;
239 }
240
241 } // namespace impeller
impeller::ContentContext
Definition: content_context.h:138
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:297
impeller::ContentContext::GetTessellator
Tessellator & GetTessellator() const
Definition: content_context.cc:935
impeller::Entity
Definition: entity.h:26
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Definition: entity.cc:48
impeller::Entity::GetTransform
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:44
impeller::FillRectGeometry::FillRectGeometry
FillRectGeometry(Rect rect)
Definition: rect_geometry.cc:9
impeller::FillRectGeometry::GetCoverage
std::optional< Rect > GetCoverage(const Matrix &transform) const override
Definition: rect_geometry.cc:31
impeller::FillRectGeometry::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: rect_geometry.cc:36
impeller::FillRectGeometry::IsAxisAlignedRect
bool IsAxisAlignedRect() const override
Definition: rect_geometry.cc:45
impeller::FillRectGeometry::GetPositionBuffer
GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: rect_geometry.cc:13
impeller::FillRectGeometry::~FillRectGeometry
~FillRectGeometry() override
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
impeller::StrokeRectGeometry::GetCoverage
std::optional< Rect > GetCoverage(const Matrix &transform) const override
Definition: rect_geometry.cc:205
impeller::StrokeRectGeometry::StrokeRectGeometry
StrokeRectGeometry(const Rect &rect, const StrokeParameters &stroke)
Definition: rect_geometry.cc:49
impeller::StrokeRectGeometry::~StrokeRectGeometry
~StrokeRectGeometry() override
impeller::StrokeRectGeometry::GetPositionBuffer
GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: rect_geometry.cc:57
impeller::Tessellator::Trigs
Definition: tessellator.h:48
impeller::Tessellator::Trigs::size
size_t size() const
Definition: tessellator.h:53
impeller::Tessellator::GetTrigsForDeviceRadius
Trigs GetTrigsForDeviceRadius(Scalar pixel_radius)
Definition: tessellator.cc:310
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
impeller
Definition: allocation.cc:12
impeller::Join
Join
An enum that describes ways to join two segments of a path.
Definition: stroke_parameters.h:20
impeller::Join::kRound
@ kRound
impeller::Join::kMiter
@ kMiter
impeller::Join::kBevel
@ kBevel
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::Vector2
Point Vector2
Definition: point.h:331
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::kSqrt2
constexpr float kSqrt2
Definition: constants.h:47
impeller::kMinStrokeSize
static constexpr Scalar kMinStrokeSize
Definition: geometry.h:19
rect_geometry.h
impeller::GeometryResult
Definition: geometry.h:21
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:37
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Matrix::GetMaxBasisLengthXY
Scalar GetMaxBasisLengthXY() const
Return the maximum scale applied specifically to either the X axis or Y axis unit vectors (the bases)...
Definition: matrix.h:328
impeller::StrokeParameters
A structure to store all of the parameters related to stroking a path or basic geometry object.
Definition: stroke_parameters.h:28
impeller::StrokeParameters::join
Join join
Definition: stroke_parameters.h:31
impeller::StrokeParameters::miter_limit
Scalar miter_limit
Definition: stroke_parameters.h:32
impeller::TPoint< Scalar >
impeller::TRect< Scalar >
impeller::TRect::GetBottom
constexpr auto GetBottom() const
Definition: rect.h:361
impeller::TRect::TransformBounds
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition: rect.h:476
impeller::TRect::GetTop
constexpr auto GetTop() const
Definition: rect.h:357
impeller::TRect::Contains
constexpr bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
Definition: rect.h:235
impeller::TRect::GetPoints
constexpr std::array< TPoint< T >, 4 > GetPoints() const
Get the points that represent the 4 corners of this rectangle in a Z order that is compatible with tr...
Definition: rect.h:418
impeller::TRect::GetLeft
constexpr auto GetLeft() const
Definition: rect.h:355
impeller::TRect::GetRight
constexpr auto GetRight() const
Definition: rect.h:359
impeller::TRect::GetLeftBottom
constexpr TPoint< T > GetLeftBottom() const
Definition: rect.h:371
impeller::TRect::GetRightTop
constexpr TPoint< T > GetRightTop() const
Definition: rect.h:367
impeller::TRect::GetRightBottom
constexpr TPoint< T > GetRightBottom() const
Definition: rect.h:375
impeller::TRect::GetLeftTop
constexpr TPoint< T > GetLeftTop() const
Definition: rect.h:363
end
const size_t end
Definition: tessellator_libtess.cc:63