10 : p0_(p0), p1_(p1), width_(width), cap_(cap) {
11 FML_DCHECK(width >= 0);
17 if (determinant == 0) {
21 Scalar min_size = 1.0f / sqrt(std::abs(determinant));
22 return std::max(width, min_size) * 0.5f;
25 Vector2 LineGeometry::ComputeAlongVector(
const Matrix& transform,
26 bool allow_zero_length)
const {
32 auto along = p1_ - p0_;
33 Scalar length = along.GetLength();
35 if (!allow_zero_length) {
39 return {stroke_half_width, 0};
41 return along * stroke_half_width / length;
45 bool LineGeometry::ComputeCorners(
Point corners[4],
46 const Matrix& transform,
47 bool extend_endpoints)
const {
48 auto along = ComputeAlongVector(transform, extend_endpoints);
53 auto across =
Vector2(along.y, -along.x);
54 corners[0] = p0_ - across;
55 corners[1] = p1_ - across;
56 corners[2] = p0_ + across;
57 corners[3] = p1_ + across;
58 if (extend_endpoints) {
67 GeometryResult LineGeometry::GetPositionBuffer(
const ContentContext& renderer,
69 RenderPass& pass)
const {
70 using VT = SolidFillVertexShader::PerVertexData;
72 auto& transform = entity.GetTransform();
76 std::shared_ptr<Tessellator> tessellator = renderer.GetTessellator();
77 auto generator = tessellator->RoundCapLine(transform, p0_, p1_, radius);
82 if (!ComputeCorners(corners, transform, cap_ ==
Cap::kSquare)) {
86 auto& host_buffer = renderer.GetTransientsBuffer();
89 BufferView vertex_buffer = host_buffer.Emplace(
90 count *
sizeof(VT),
alignof(VT), [&corners](uint8_t* buffer) {
91 auto vertices =
reinterpret_cast<VT*
>(buffer);
92 for (
auto& corner : corners) {
99 return GeometryResult{
103 .vertex_buffer = vertex_buffer,
104 .vertex_count = count,
107 .transform = entity.GetShaderTransform(pass),
112 GeometryResult LineGeometry::GetPositionUVBuffer(
Rect texture_coverage,
113 Matrix effect_transform,
114 const ContentContext& renderer,
115 const Entity& entity,
116 RenderPass& pass)
const {
117 auto& host_buffer = renderer.GetTransientsBuffer();
118 using VT = TextureFillVertexShader::PerVertexData;
120 auto& transform = entity.GetTransform();
124 texture_coverage.GetNormalizingTransform() * effect_transform;
127 std::shared_ptr<Tessellator> tessellator = renderer.GetTessellator();
128 auto generator = tessellator->RoundCapLine(transform, p0_, p1_, radius);
134 if (!ComputeCorners(corners, transform, cap_ ==
Cap::kSquare)) {
139 BufferView vertex_buffer =
140 host_buffer.Emplace(count *
sizeof(VT),
alignof(VT),
141 [&uv_transform, &corners](uint8_t* buffer) {
142 auto vertices =
reinterpret_cast<VT*
>(buffer);
143 for (
auto& corner : corners) {
146 .texture_coords = uv_transform * corner,
151 return GeometryResult{
155 .vertex_buffer = vertex_buffer,
156 .vertex_count = count,
159 .transform = entity.GetShaderTransform(pass),
167 std::optional<Rect> LineGeometry::GetCoverage(
const Matrix& transform)
const {
169 if (!ComputeCorners(corners, transform, cap_ !=
Cap::kButt)) {
173 for (
int i = 0; i < 4; i++) {
174 corners[i] = transform * corners[i];
183 auto coverage = GetCoverage(transform);
184 return coverage.has_value() ? coverage->Contains(rect) :
false;
188 return cap_ !=
Cap::kRound && (p0_.x == p1_.
x || p0_.y == p1_.
y);