1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:18:11 +00:00

LibWeb: Add flag to normalize border radii to width only

This is needed to avoid issues (such as overlapping curves) for outline
border radii, which do not currently support elliptical corners.
This commit is contained in:
MacDue 2022-06-12 15:21:32 +01:00 committed by Linus Groh
parent 28c78b45ca
commit 0e7aa1e98c
5 changed files with 44 additions and 27 deletions

View file

@ -11,30 +11,41 @@
namespace Web::Painting {
BorderRadiiData normalized_border_radii_data(Layout::Node const& node, Gfx::FloatRect const& rect, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius)
BorderRadiiData normalized_border_radii_data(Layout::Node const& node, Gfx::FloatRect const& rect, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius, RelativeToWidthOnly relative_to_width_only)
{
BorderRadiusData bottom_left_radius_px {};
BorderRadiusData bottom_right_radius_px {};
BorderRadiusData top_left_radius_px {};
BorderRadiusData top_right_radius_px {};
auto width_length = CSS::Length::make_px(rect.width());
auto height_length = CSS::Length::make_px(rect.height());
bottom_left_radius_px.horizontal_radius = bottom_left_radius.horizontal_radius.resolved(node, width_length).to_px(node);
bottom_right_radius_px.horizontal_radius = bottom_right_radius.horizontal_radius.resolved(node, width_length).to_px(node);
top_left_radius_px.horizontal_radius = top_left_radius.horizontal_radius.resolved(node, width_length).to_px(node);
top_right_radius_px.horizontal_radius = top_right_radius.horizontal_radius.resolved(node, width_length).to_px(node);
BorderRadiusData bottom_left_radius_px {
bottom_left_radius.horizontal_radius.resolved(node, width_length).to_px(node),
bottom_left_radius.vertical_radius.resolved(node, height_length).to_px(node)
};
BorderRadiusData bottom_right_radius_px {
bottom_right_radius.horizontal_radius.resolved(node, width_length).to_px(node),
bottom_right_radius.vertical_radius.resolved(node, height_length).to_px(node)
};
BorderRadiusData top_left_radius_px {
top_left_radius.horizontal_radius.resolved(node, width_length).to_px(node),
top_left_radius.vertical_radius.resolved(node, height_length).to_px(node)
};
BorderRadiusData top_right_radius_px {
top_right_radius.horizontal_radius.resolved(node, width_length).to_px(node),
top_right_radius.vertical_radius.resolved(node, height_length).to_px(node)
};
// FIXME: Remove `relative_to_width_only = Yes' flag, this only exists to
// avoid overlapping curves for (outline) borders, which do not yet
// support elliptical corners.
switch (relative_to_width_only) {
case RelativeToWidthOnly::No: {
// Normal correct rendering:
auto height_length = CSS::Length::make_px(rect.height());
bottom_left_radius_px.vertical_radius = bottom_left_radius.vertical_radius.resolved(node, height_length).to_px(node);
bottom_right_radius_px.vertical_radius = bottom_right_radius.vertical_radius.resolved(node, height_length).to_px(node);
top_left_radius_px.vertical_radius = top_left_radius.vertical_radius.resolved(node, height_length).to_px(node);
top_right_radius_px.vertical_radius = top_right_radius.vertical_radius.resolved(node, height_length).to_px(node);
break;
}
case RelativeToWidthOnly::Yes:
bottom_left_radius_px.vertical_radius = bottom_left_radius_px.horizontal_radius;
bottom_right_radius_px.vertical_radius = bottom_right_radius_px.horizontal_radius;
top_left_radius_px.vertical_radius = top_left_radius_px.horizontal_radius;
top_right_radius_px.vertical_radius = top_right_radius_px.horizontal_radius;
break;
default:
VERIFY_NOT_REACHED();
}
// Scale overlapping curves according to https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
auto f = 1.0f;

View file

@ -23,7 +23,12 @@ struct BorderRadiiData {
BorderRadiusData bottom_left;
};
BorderRadiiData normalized_border_radii_data(Layout::Node const&, Gfx::FloatRect const&, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius);
enum class RelativeToWidthOnly {
Yes,
No
};
BorderRadiiData normalized_border_radii_data(Layout::Node const&, Gfx::FloatRect const&, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius, RelativeToWidthOnly relative_to_width_only = RelativeToWidthOnly::No);
enum class BorderEdge {
Top,

View file

@ -106,7 +106,7 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c
}
auto bordered_rect = absolute_fragment_rect.inflated(borders_data.top.width, borders_data.right.width, borders_data.bottom.width, borders_data.left.width);
auto border_radii_data = Painting::normalized_border_radii_data(layout_node(), bordered_rect, top_left_border_radius, top_right_border_radius, bottom_right_border_radius, bottom_left_border_radius);
auto border_radii_data = Painting::normalized_border_radii_data(layout_node(), bordered_rect, top_left_border_radius, top_right_border_radius, bottom_right_border_radius, bottom_left_border_radius, Painting::RelativeToWidthOnly::Yes);
Painting::paint_all_borders(context, bordered_rect, border_radii_data, borders_data);

View file

@ -178,7 +178,7 @@ void PaintableBox::paint_border(PaintContext& context) const
.bottom = computed_values().border_bottom(),
.left = computed_values().border_left(),
};
paint_all_borders(context, absolute_border_box_rect(), normalized_border_radii_data(), borders_data);
paint_all_borders(context, absolute_border_box_rect(), normalized_border_radii_data(Painting::RelativeToWidthOnly::Yes), borders_data);
}
void PaintableBox::paint_background(PaintContext& context) const
@ -233,13 +233,14 @@ void PaintableBox::paint_box_shadow(PaintContext& context) const
Painting::paint_box_shadow(context, enclosing_int_rect(absolute_border_box_rect()), resolved_box_shadow_data);
}
BorderRadiiData PaintableBox::normalized_border_radii_data() const
BorderRadiiData PaintableBox::normalized_border_radii_data(Painting::RelativeToWidthOnly relative_to_width_only) const
{
return Painting::normalized_border_radii_data(layout_box(), absolute_border_box_rect(),
computed_values().border_top_left_radius(),
computed_values().border_top_right_radius(),
computed_values().border_bottom_right_radius(),
computed_values().border_bottom_left_radius());
computed_values().border_bottom_left_radius(),
relative_to_width_only);
}
void PaintableBox::before_children_paint(PaintContext& context, PaintPhase) const

View file

@ -130,7 +130,7 @@ protected:
virtual Gfx::FloatRect compute_absolute_rect() const;
private:
Painting::BorderRadiiData normalized_border_radii_data() const;
Painting::BorderRadiiData normalized_border_radii_data(Painting::RelativeToWidthOnly relative_to_width_only = Painting::RelativeToWidthOnly::No) const;
OwnPtr<Painting::StackingContext> m_stacking_context;