21 class 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;
60 class 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_;
117 class 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_;
162 constexpr 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);
173 constexpr
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);
209 size_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;
241 size_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;
286 size_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;
350 static 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,
438 std::optional<Rect> RoundSuperellipseGeometry::GetCoverage(
444 const Rect& 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 & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
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 CoversArea(const Matrix &transform, const Rect &rect) const override
Determines if this geometry, transformed by the given transform, will completely cover all surface ar...
bool IsAxisAlignedRect() const override
RoundSuperellipseGeometry(const Rect &bounds, const RoundingRadii &radii)
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|.
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)