21class ConvexRearranger {
25 virtual ~ConvexRearranger() {}
27 virtual size_t ContourLength()
const = 0;
29 virtual Point GetPoint(
size_t i)
const = 0;
31 void RearrangeIntoTriangleStrip(
Point* output) {
32 size_t index_count = 0;
34 output[index_count++] = GetPoint(0);
37 size_t contour_length = ContourLength();
38 size_t b = contour_length - 1;
40 output[index_count++] = GetPoint(a);
41 output[index_count++] = GetPoint(b);
46 output[index_count++] = GetPoint(b);
51 ConvexRearranger(
const ConvexRearranger&) =
delete;
52 ConvexRearranger& operator=(
const ConvexRearranger&) =
delete;
60class UnevenQuadrantsRearranger :
public ConvexRearranger {
62 UnevenQuadrantsRearranger(
Point* cache,
size_t segment_capacity)
63 : cache_(cache), segment_capacity_(segment_capacity) {}
65 Point* QuadCache(
size_t i) {
return cache_ + segment_capacity_ *
i; }
67 const Point* QuadCache(
size_t i)
const {
68 return cache_ + segment_capacity_ *
i;
71 size_t& QuadSize(
size_t i) {
return lengths_[
i]; }
73 size_t ContourLength()
const override {
74 return lengths_[0] + lengths_[1] + lengths_[2] + lengths_[3] - 4;
77 Point GetPoint(
size_t i)
const override {
83 size_t high = lengths_[0] - 1;
85 return QuadCache(0)[
i];
87 high += lengths_[1] - 1;
89 return QuadCache(1)[
high -
i];
92 high += lengths_[2] - 1;
94 return QuadCache(2)[
i -
low];
96 high += lengths_[3] - 1;
98 return QuadCache(3)[
high -
i];
107 size_t segment_capacity_;
117class MirroredQuadrantRearranger :
public ConvexRearranger {
119 MirroredQuadrantRearranger(
Point center,
Point* cache)
120 : center_(
center), cache_(cache) {}
122 size_t& QuadSize() {
return l_; }
124 size_t ContourLength()
const override {
return l_ * 4 - 4; }
126 Point GetPoint(
size_t i)
const override {
132 size_t high = l_ - 1;
134 return cache_[
i] + center_;
138 return cache_[
high -
i] *
Point{1, -1} + center_;
143 return cache_[
i -
low] *
Point{-1, -1} + center_;
147 return cache_[
high -
i] *
Point{-1, 1} + center_;
162constexpr Matrix kFlip = Matrix(
163 0.0f, 1.0f, 0.0f, 0.0f,
164 1.0f, 0.0f, 0.0f, 0.0f,
165 0.0f, 0.0f, 1.0f, 0.0f,
166 0.0f, 0.0f, 0.0f, 1.0f);
173constexpr Scalar kMaxQuadrantSteps = 40;
190 constexpr Scalar pointsPerPixel = 1.0;
191 size_t pointsByDimension =
192 static_cast<size_t>(std::ceil(minDimension * pointsPerPixel));
193 Scalar angleByDimension = fullAngle / pointsByDimension;
195 return std::min(kMinAngleStep, angleByDimension);
209size_t DrawSuperellipsoidArc(
Point* output,
215 Point* next = output;
216 Scalar angle = reverse ? max_theta : 0.0f;
219 CalculateStep(a - a * pow(abs(cosf(max_theta)), 2 / n), max_theta);
221 while ((angle <
end) != reverse) {
222 Scalar x = a * pow(abs(sinf(angle)), 2 / n);
223 Scalar y = a * pow(abs(cosf(angle)), 2 / n);
227 return next - output;
241size_t DrawCircularArc(
Point* output,
260 Point* next = output;
261 Scalar angle = reverse ? max_angle : 0.0f;
263 (reverse ? -1 : 1) * CalculateStep(std::abs(
start.y -
end.y), max_angle);
264 Scalar end_angle = reverse ? 0.0f : max_angle;
266 while ((angle < end_angle) != reverse) {
270 return next - output;
286size_t DrawOctantSquareLikeSquircle(
Point* output,
287 const RoundSuperellipseParam::Octant& param,
288 bool reverse_and_flip,
289 const Matrix& external_transform) {
291 if (reverse_and_flip) {
294 if (param.se_n < 2) {
320 Point* next = output;
321 if (!reverse_and_flip) {
324 DrawSuperellipsoidArc(next, param.se_a, param.se_n, param.se_max_theta,
327 next += DrawCircularArc(
328 next, param.circle_start - param.circle_center,
329 param.circle_max_angle.radians, reverse_and_flip,
333 next += DrawCircularArc(
334 next, param.circle_start - param.circle_center,
335 param.circle_max_angle.radians, reverse_and_flip,
339 DrawSuperellipsoidArc(next, param.se_a, param.se_n, param.se_max_theta,
344 return next - output;
350static size_t DrawQuadrant(
Point* output,
351 const RoundSuperellipseParam::Quadrant& param) {
352 Point* next = output;
355 next += DrawOctantSquareLikeSquircle(next, param.top,
358 next += DrawOctantSquareLikeSquircle(next, param.right,
361 return next - output;
368 : bounds_(bounds.GetPositive()), radii_(radii.Scaled(bounds_)) {}
388 static_assert(kMaxQuadSize > 2 * kMaxQuadrantSteps);
390 ConvexRearranger* rearranger;
391 std::variant<std::monostate, MirroredQuadrantRearranger,
392 UnevenQuadrantsRearranger>
397 if (param.all_corners_same) {
398 rearranger_holder.emplace<MirroredQuadrantRearranger>(bounds_.
GetCenter(),
400 auto& t = std::get<MirroredQuadrantRearranger>(rearranger_holder);
404 param.top_right.offset =
Point();
405 t.QuadSize() = DrawQuadrant(cache, param.top_right);
407 rearranger_holder.emplace<UnevenQuadrantsRearranger>(cache, kMaxQuadSize);
408 auto& t = std::get<UnevenQuadrantsRearranger>(rearranger_holder);
411 t.QuadSize(0) = DrawQuadrant(t.QuadCache(0), param.top_right);
412 t.QuadSize(1) = DrawQuadrant(t.QuadCache(1), param.bottom_right);
413 t.QuadSize(2) = DrawQuadrant(t.QuadCache(2), param.bottom_left);
414 t.QuadSize(3) = DrawQuadrant(t.QuadCache(3), param.top_left);
417 size_t contour_length = rearranger->ContourLength();
419 nullptr,
sizeof(
Point) * contour_length,
alignof(
Point));
421 reinterpret_cast<Point*
>(vertex_buffer.GetBuffer()->OnGetContents() +
422 vertex_buffer.GetRange().offset);
423 rearranger->RearrangeIntoTriangleStrip(vertex_data);
424 vertex_buffer.GetBuffer()->Flush(vertex_buffer.GetRange());
426 return GeometryResult{
430 .vertex_buffer = vertex_buffer,
431 .vertex_count = contour_length,
438std::optional<Rect> RoundSuperellipseGeometry::GetCoverage(
444 const IRect& rect)
const {
445 if (!
transform.IsTranslationScaleOnly()) {
456 bounds_.
GetTop() + top_inset * kGapFactor,
457 bounds_.
GetRight() - right_inset * kGapFactor,
458 bounds_.
GetBottom() - bottom_inset * kGapFactor);
470 round_superellipse_source_(round_superellipse) {}
473 return round_superellipse_source_;
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
Tessellator & GetTessellator() const
Matrix GetShaderTransform(const RenderPass &pass) const
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
Render passes encode render commands directed as one specific render target into an underlying comman...
A Geometry class that generates fillable vertices (with or without texture coordinates) directly from...
~RoundSuperellipseGeometry() override
bool IsAxisAlignedRect() const override
RoundSuperellipseGeometry(const Rect &bounds, const RoundingRadii &radii)
bool CoversArea(const Matrix &transform, const IRect &rect) const override
Determines if this geometry, transformed by the given transform, will completely cover all of the pix...
An abstract Geometry base class that produces fillable vertices representing the stroked outline from...
StrokeRoundSuperellipseGeometry(const RoundSuperellipse &round_superellipse, const StrokeParameters ¶meters)
const PathSource & GetSource() const override
std::vector< Point > & GetStrokePointCache()
Retrieve a pre-allocated arena of kPointArenaSize points.
@ kNone
Does not use the index buffer.
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
static constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
static RoundSuperellipseParam MakeBoundsRadii(const Rect &bounds, const RoundingRadii &radii)
static constexpr Scalar kGapFactor
A structure to store all of the parameters related to stroking a path or basic geometry object.
constexpr auto GetBottom() const
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
constexpr auto GetTop() const
constexpr bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
constexpr auto GetLeft() const
constexpr auto GetRight() const
constexpr Point GetCenter() const
Get the center point as a |Point|.
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)