blob: 89088c86e8e3ffa06d68af5be2a64ccbaa6cdf54 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/entity/geometry/fill_path_geometry.h"
#include "fml/logging.h"
#include "impeller/core/formats.h"
#include "impeller/core/vertex_buffer.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/geometry/geometry.h"
namespace impeller {
FillPathGeometry::FillPathGeometry(const Path& path,
std::optional<Rect> inner_rect)
: path_(path), inner_rect_(inner_rect) {}
GeometryResult FillPathGeometry::GetPositionBuffer(
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
auto& host_buffer = renderer.GetTransientsBuffer();
const auto& bounding_box = path_.GetBoundingBox();
if (bounding_box.has_value() && bounding_box->IsEmpty()) {
return GeometryResult{
.type = PrimitiveType::kTriangle,
.vertex_buffer =
VertexBuffer{
.vertex_buffer = {},
.vertex_count = 0,
.index_type = IndexType::k16bit,
},
.transform = pass.GetOrthographicTransform() * entity.GetTransform(),
};
}
VertexBuffer vertex_buffer = renderer.GetTessellator()->TessellateConvex(
path_, host_buffer, entity.GetTransform().GetMaxBasisLength());
return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer = vertex_buffer,
.transform = entity.GetShaderTransform(pass),
.mode = GetResultMode(),
};
}
// |Geometry|
GeometryResult FillPathGeometry::GetPositionUVBuffer(
Rect texture_coverage,
Matrix effect_transform,
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
const auto& bounding_box = path_.GetBoundingBox();
if (bounding_box.has_value() && bounding_box->IsEmpty()) {
return GeometryResult{
.type = PrimitiveType::kTriangle,
.vertex_buffer =
VertexBuffer{
.vertex_buffer = {},
.vertex_count = 0,
.index_type = IndexType::k16bit,
},
.transform = pass.GetOrthographicTransform() * entity.GetTransform(),
};
}
auto uv_transform =
texture_coverage.GetNormalizingTransform() * effect_transform;
VertexBuffer vertex_buffer = renderer.GetTessellator()->TessellateConvex(
path_, renderer.GetTransientsBuffer(),
entity.GetTransform().GetMaxBasisLength(), uv_transform);
return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer = vertex_buffer,
.transform = entity.GetShaderTransform(pass),
.mode = GetResultMode(),
};
}
GeometryResult::Mode FillPathGeometry::GetResultMode() const {
const auto& bounding_box = path_.GetBoundingBox();
if (path_.IsConvex() ||
(bounding_box.has_value() && bounding_box->IsEmpty())) {
return GeometryResult::Mode::kNormal;
}
switch (path_.GetFillType()) {
case FillType::kNonZero:
return GeometryResult::Mode::kNonZero;
case FillType::kOdd:
return GeometryResult::Mode::kEvenOdd;
}
FML_UNREACHABLE();
}
GeometryVertexType FillPathGeometry::GetVertexType() const {
return GeometryVertexType::kPosition;
}
std::optional<Rect> FillPathGeometry::GetCoverage(
const Matrix& transform) const {
return path_.GetTransformedBoundingBox(transform);
}
bool FillPathGeometry::CoversArea(const Matrix& transform,
const Rect& rect) const {
if (!inner_rect_.has_value()) {
return false;
}
if (!transform.IsTranslationScaleOnly()) {
return false;
}
Rect coverage = inner_rect_->TransformBounds(transform);
return coverage.Contains(rect);
}
} // namespace impeller