Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
compute all quadrants
  • Loading branch information
walley892 committed May 12, 2026
commit 51862408ceaa97455347fa256fc664b26320907a
116 changes: 2 additions & 114 deletions engine/src/flutter/impeller/display_list/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1044,126 +1044,14 @@ void Canvas::DrawRoundSuperellipse(const RoundSuperellipse& round_superellipse,

if (renderer_.GetContext()->GetFlags().use_sdfs &&
!paint.mask_blur_descriptor.has_value()) {
auto split_proc = [](Scalar left, Scalar right, Scalar ratio_left,
Scalar ratio_right) -> Scalar {
if (ratio_left == 0 && ratio_right == 0) {
return (left + right) / 2;
}
return (left * ratio_right + right * ratio_left) /
(ratio_left + ratio_right);
};

auto round_superellipse_params = RoundSuperellipseParam::MakeBoundsRadii(
round_superellipse.GetBounds(), round_superellipse.GetRadii());

RoundSuperellipseParam::Quadrant tr = round_superellipse_params.top_right;
RoundSuperellipseParam::Quadrant br =
round_superellipse_params.all_corners_same
? tr
: round_superellipse_params.bottom_right;
RoundSuperellipseParam::Quadrant bl =
round_superellipse_params.all_corners_same
? tr
: round_superellipse_params.bottom_left;
RoundSuperellipseParam::Quadrant tl =
round_superellipse_params.all_corners_same
? tr
: round_superellipse_params.top_left;

Rect bounds = round_superellipse.GetBounds();
Point center = bounds.GetCenter();
RoundingRadii radii = round_superellipse.GetRadii();

Scalar top_split = split_proc(bounds.GetLeft(), bounds.GetRight(),
radii.top_left.width, radii.top_right.width) -
center.x;
Scalar bottom_split =
split_proc(bounds.GetLeft(), bounds.GetRight(), radii.bottom_left.width,
radii.bottom_right.width) -
center.x;
Scalar left_split =
split_proc(bounds.GetTop(), bounds.GetBottom(), radii.top_left.height,
radii.bottom_left.height) -
center.y;
Scalar right_split =
split_proc(bounds.GetTop(), bounds.GetBottom(), radii.top_right.height,
radii.bottom_right.height) -
center.y;

Point tr_center_relative = tr.offset - center;
Point br_center_relative = br.offset - center;
Point bl_center_relative = bl.offset - center;
Point tl_center_relative = tl.offset - center;

Vector4 superellipse_degrees_top(tr.top.se_n, br.top.se_n, bl.top.se_n,
tl.top.se_n);
Vector4 superellipse_degrees_right(tr.right.se_n, br.right.se_n,
bl.right.se_n, tl.right.se_n);
Vector4 superellipse_semi_axes_top(tr.top.se_a, br.top.se_a, bl.top.se_a,
tl.top.se_a);
Vector4 superellipse_semi_axes_right(tr.right.se_a, br.right.se_a,
bl.right.se_a, tl.right.se_a);
Vector4 angle_spans_top(tr.top.circle_max_angle.radians,
br.top.circle_max_angle.radians,
bl.top.circle_max_angle.radians,
tl.top.circle_max_angle.radians);
Vector4 angle_spans_right(tr.right.circle_max_angle.radians,
br.right.circle_max_angle.radians,
bl.right.circle_max_angle.radians,
tl.right.circle_max_angle.radians);
Vector4 octant_offsets_c(tr.top.se_a - tr.right.se_a,
br.top.se_a - br.right.se_a,
bl.top.se_a - bl.right.se_a,
tl.top.se_a - tl.right.se_a);
Vector4 radii_width(tr.top.circle_radius, br.top.circle_radius,
bl.top.circle_radius, tl.top.circle_radius);
Vector4 radii_height(tr.right.circle_radius, br.right.circle_radius,
bl.right.circle_radius, tl.right.circle_radius);
Vector4 circle_centers_top_x(tr.top.circle_center.x, br.top.circle_center.x,
bl.top.circle_center.x,
tl.top.circle_center.x);
Vector4 circle_centers_top_y(tr.top.circle_center.y, br.top.circle_center.y,
bl.top.circle_center.y,
tl.top.circle_center.y);
Vector4 circle_centers_right_x(
tr.right.circle_center.x, br.right.circle_center.x,
bl.right.circle_center.x, tl.right.circle_center.x);
Vector4 circle_centers_right_y(
tr.right.circle_center.y, br.right.circle_center.y,
bl.right.circle_center.y, tl.right.circle_center.y);
Vector4 superellipse_scales_x(
tr.signed_scale.Abs().x, br.signed_scale.Abs().x,
bl.signed_scale.Abs().x, tl.signed_scale.Abs().x);
Vector4 superellipse_scales_y(
tr.signed_scale.Abs().y, br.signed_scale.Abs().y,
bl.signed_scale.Abs().y, tl.signed_scale.Abs().y);
Vector4 quadrant_centers_x(tr_center_relative.x, br_center_relative.x,
bl_center_relative.x, tl_center_relative.x);
Vector4 quadrant_centers_y(tr_center_relative.y, br_center_relative.y,
bl_center_relative.y, tl_center_relative.y);
Vector4 quadrant_splits(top_split, bottom_split, left_split, right_split);

auto params = UberSDFParameters::MakeRoundedSuperellipse(
/*color=*/paint.color,
/*bounds=*/bounds,
/*superellipse_degrees_top=*/superellipse_degrees_top,
/*superellipse_degrees_right=*/superellipse_degrees_right,
/*superellipse_semi_axes_top=*/superellipse_semi_axes_top,
/*superellipse_semi_axes_right=*/superellipse_semi_axes_right,
/*angle_spans_top=*/angle_spans_top,
/*angle_spans_right=*/angle_spans_right,
/*octant_offsets_c=*/octant_offsets_c,
/*radii_width=*/radii_width,
/*radii_height=*/radii_height,
/*circle_centers_top_x=*/circle_centers_top_x,
/*circle_centers_top_y=*/circle_centers_top_y,
/*circle_centers_right_x=*/circle_centers_right_x,
/*circle_centers_right_y=*/circle_centers_right_y,
/*superellipse_scales_x=*/superellipse_scales_x,
/*superellipse_scales_y=*/superellipse_scales_y,
/*quadrant_centers_x=*/quadrant_centers_x,
/*quadrant_centers_y=*/quadrant_centers_y,
/*quadrant_splits=*/quadrant_splits,
/*bounds=*/round_superellipse.GetBounds(),
/*round_superellipse_params=*/round_superellipse_params,
/*stroke=*/paint.GetStroke());

AddRenderSDFEntityToCurrentPass(paint, params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,6 @@ bool UberSDFContents::Render(const ContentContext& renderer,
params_.color.WithAlpha(params_.color.alpha * GetOpacityFactor());
frag_info.center = params_.center;
frag_info.size = params_.size;
frag_info.radii =
Vector4(params_.radii.bottom_right.width, params_.radii.top_right.width,
params_.radii.bottom_left.width, params_.radii.top_left.width);
frag_info.radii_right =
Vector4(params_.radii.bottom_right.height, params_.radii.top_right.height,
params_.radii.bottom_left.height, params_.radii.top_left.height);
frag_info.stroked = params_.stroke ? 1.0f : 0.0f;
frag_info.stroke_width = params_.stroke ? params_.stroke->width : 0.0f;
frag_info.stroke_join =
Expand Down
99 changes: 54 additions & 45 deletions engine/src/flutter/impeller/entity/contents/uber_sdf_parameters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,61 +63,70 @@ UberSDFParameters UberSDFParameters::MakeRoundedRect(
const RoundingRadii& radii,
std::optional<StrokeParameters> stroke) {
Point size = Point(rect.GetSize() * 0.5f);
return UberSDFParameters{.type = Type::kRoundedRect,
.color = color,
.center = rect.GetCenter(),
.size = size,
.stroke = stroke,
.radii = radii};
return UberSDFParameters{
.type = Type::kRoundedRect,
.color = color,
.center = rect.GetCenter(),
.size = size,
.stroke = stroke,
.radii_width = Vector4(radii.bottom_right.width, radii.top_right.width,
radii.bottom_left.width, radii.top_left.width)};
Comment thread
walley892 marked this conversation as resolved.
Outdated
}

UberSDFParameters UberSDFParameters::MakeRoundedSuperellipse(
Color color,
Rect rect,
Vector4 superellipse_degrees_top,
Vector4 superellipse_degrees_right,
Vector4 superellipse_semi_axes_top,
Vector4 superellipse_semi_axes_right,
Vector4 angle_spans_top,
Vector4 angle_spans_right,
Vector4 octant_offsets_c,
Vector4 radii_width,
Vector4 radii_height,
Vector4 circle_centers_top_x,
Vector4 circle_centers_top_y,
Vector4 circle_centers_right_x,
Vector4 circle_centers_right_y,
Vector4 superellipse_scales_x,
Vector4 superellipse_scales_y,
Vector4 quadrant_centers_x,
Vector4 quadrant_centers_y,
Vector4 quadrant_splits,
const Rect& bounds,
const RoundSuperellipseParam& round_superellipse_params,
std::optional<StrokeParameters> stroke) {
Point size = Point(rect.GetSize() * 0.5f);
Point center = bounds.GetCenter();

RoundSuperellipseParam::Quadrant top_right = round_superellipse_params.top_right;
RoundSuperellipseParam::Quadrant bottom_right =
round_superellipse_params.all_corners_same
? top_right
: round_superellipse_params.bottom_right;
RoundSuperellipseParam::Quadrant bottom_left =
round_superellipse_params.all_corners_same
? top_right
: round_superellipse_params.bottom_left;
RoundSuperellipseParam::Quadrant top_left =
round_superellipse_params.all_corners_same
? top_right
: round_superellipse_params.top_left;

Point top_right_center_relative = top_right.offset - center;
Point bottom_right_center_relative = bottom_right.offset - center;
Point bottom_left_center_relative = bottom_left.offset - center;
Point top_left_center_relative = top_left.offset - center;

Point size = Point(bounds.GetSize() * 0.5f);
return UberSDFParameters{
.type = Type::kRoundedSuperellipse,
.color = color,
.center = rect.GetCenter(),
.center = center,
.size = size,
.stroke = stroke,
.superellipse_degrees_top = superellipse_degrees_top,
.superellipse_degrees_right = superellipse_degrees_right,
.superellipse_semi_axes_top = superellipse_semi_axes_top,
.superellipse_semi_axes_right = superellipse_semi_axes_right,
.angle_spans_top = angle_spans_top,
.angle_spans_right = angle_spans_right,
.octant_offsets_c = octant_offsets_c,
.radii_width = radii_width,
.radii_height = radii_height,
.circle_centers_top_x = circle_centers_top_x,
.circle_centers_top_y = circle_centers_top_y,
.circle_centers_right_x = circle_centers_right_x,
.circle_centers_right_y = circle_centers_right_y,
.superellipse_scales_x = superellipse_scales_x,
.superellipse_scales_y = superellipse_scales_y,
.quadrant_centers_x = quadrant_centers_x,
.quadrant_centers_y = quadrant_centers_y,
.quadrant_splits = quadrant_splits};
.superellipse_degrees_top = Vector4(top_right.top.se_n, bottom_right.top.se_n, bottom_left.top.se_n, top_left.top.se_n),
.superellipse_degrees_right = Vector4(top_right.right.se_n, bottom_right.right.se_n, bottom_left.right.se_n, top_left.right.se_n),
.superellipse_semi_axes_top = Vector4(top_right.top.se_a, bottom_right.top.se_a, bottom_left.top.se_a, top_left.top.se_a),
.superellipse_semi_axes_right = Vector4(top_right.right.se_a, bottom_right.right.se_a, bottom_left.right.se_a, top_left.right.se_a),
.angle_spans_top = Vector4(top_right.top.circle_max_angle.radians, bottom_right.top.circle_max_angle.radians, bottom_left.top.circle_max_angle.radians, top_left.top.circle_max_angle.radians),
.angle_spans_right = Vector4(top_right.right.circle_max_angle.radians, bottom_right.right.circle_max_angle.radians, bottom_left.right.circle_max_angle.radians, top_left.right.circle_max_angle.radians),
.octant_offsets_c = Vector4(top_right.top.se_a - top_right.right.se_a, bottom_right.top.se_a - bottom_right.right.se_a, bottom_left.top.se_a - bottom_left.right.se_a, top_left.top.se_a - top_left.right.se_a),
.radii_width = Vector4(top_right.top.circle_radius, bottom_right.top.circle_radius, bottom_left.top.circle_radius, top_left.top.circle_radius),
.radii_height = Vector4(top_right.right.circle_radius, bottom_right.right.circle_radius, bottom_left.right.circle_radius, top_left.right.circle_radius),
.circle_centers_top_x = Vector4(top_right.top.circle_center.x, bottom_right.top.circle_center.x, bottom_left.top.circle_center.x, top_left.top.circle_center.x),
.circle_centers_top_y = Vector4(top_right.top.circle_center.y, bottom_right.top.circle_center.y, bottom_left.top.circle_center.y, top_left.top.circle_center.y),
.circle_centers_right_x = Vector4(top_right.right.circle_center.x, bottom_right.right.circle_center.x, bottom_left.right.circle_center.x, top_left.right.circle_center.x),
.circle_centers_right_y = Vector4(top_right.right.circle_center.y, bottom_right.right.circle_center.y, bottom_left.right.circle_center.y, top_left.right.circle_center.y),
.superellipse_scales_x = Vector4(top_right.signed_scale.Abs().x, bottom_right.signed_scale.Abs().x, bottom_left.signed_scale.Abs().x, top_left.signed_scale.Abs().x),
.superellipse_scales_y = Vector4(top_right.signed_scale.Abs().y, bottom_right.signed_scale.Abs().y, bottom_left.signed_scale.Abs().y, top_left.signed_scale.Abs().y),
.quadrant_centers_x = Vector4(top_right_center_relative.x, bottom_right_center_relative.x, bottom_left_center_relative.x, top_left_center_relative.x),
.quadrant_centers_y = Vector4(top_right_center_relative.y, bottom_right_center_relative.y, bottom_left_center_relative.y, top_left_center_relative.y),
.quadrant_splits = Vector4(round_superellipse_params.top_split - center.x,
round_superellipse_params.bottom_split - center.x,
round_superellipse_params.left_split - center.y,
round_superellipse_params.right_split - center.y)};
}

} // namespace impeller
25 changes: 3 additions & 22 deletions engine/src/flutter/impeller/entity/contents/uber_sdf_parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "impeller/geometry/point.h"
#include "impeller/geometry/rect.h"
#include "impeller/geometry/round_rect.h"
#include "impeller/geometry/round_superellipse_param.h"
#include "impeller/geometry/stroke_parameters.h"
#include "impeller/geometry/vector.h"

Expand Down Expand Up @@ -57,25 +58,8 @@ struct UberSDFParameters {
/// Creates UberSDFParameters for an asymmetric round superellipse.
static UberSDFParameters MakeRoundedSuperellipse(
Color color,
Rect bounds,
Vector4 superellipse_degrees_top,
Vector4 superellipse_degrees_right,
Vector4 superellipse_semi_axes_top,
Vector4 superellipse_semi_axes_right,
Vector4 angle_spans_top,
Vector4 angle_spans_right,
Vector4 octant_offsets_c,
Vector4 radii_width,
Vector4 radii_height,
Vector4 circle_centers_top_x,
Vector4 circle_centers_top_y,
Vector4 circle_centers_right_x,
Vector4 circle_centers_right_y,
Vector4 superellipse_scales_x,
Vector4 superellipse_scales_y,
Vector4 quadrant_centers_x,
Vector4 quadrant_centers_y,
Vector4 quadrant_splits,
const Rect& bounds,
const RoundSuperellipseParam& round_superellipse_params,
std::optional<StrokeParameters> stroke);

/// The type of shape to render.
Expand All @@ -95,9 +79,6 @@ struct UberSDFParameters {
/// The stroke parameters. If std::nullopt, the shape is filled.
std::optional<StrokeParameters> stroke;

/// The corner radii for a rounded shapes.
RoundingRadii radii;

Vector4 superellipse_degrees_top;
Vector4 superellipse_degrees_right;
Vector4 superellipse_semi_axes_top;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ TEST(UberSDFParametersTest, MakeRoundedRect) {
EXPECT_EQ(params.color, Color::Red());
EXPECT_EQ(params.center, Point(60, 70));
EXPECT_EQ(params.size, Point(50, 50));
EXPECT_EQ(params.radii.top_left.width, 1.0f);
EXPECT_EQ(params.radii.top_right.width, 2.0f);
EXPECT_EQ(params.radii.bottom_left.width, 3.0f);
EXPECT_EQ(params.radii.bottom_right.width, 4.0f);
EXPECT_EQ(params.radii_width.w, 1.0f);
EXPECT_EQ(params.radii_width.y, 2.0f);
EXPECT_EQ(params.radii_width.z, 3.0f);
EXPECT_EQ(params.radii_width.x, 4.0f);
Comment thread
walley892 marked this conversation as resolved.
Outdated
EXPECT_FALSE(params.stroke.has_value());
}

Expand Down
Loading