浏览代码

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.
MacDue 3 年之前
父节点
当前提交
0e7aa1e98c

+ 33 - 22
Userland/Libraries/LibWeb/Painting/BorderPainting.cpp

@@ -11,30 +11,41 @@
 
 
 namespace Web::Painting {
 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)
 {
 {
-    auto width_length = CSS::Length::make_px(rect.width());
-    auto height_length = CSS::Length::make_px(rect.height());
-
-    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 bottom_left_radius_px {};
+    BorderRadiusData bottom_right_radius_px {};
+    BorderRadiusData top_left_radius_px {};
+    BorderRadiusData top_right_radius_px {};
 
 
-    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)
-    };
+    auto width_length = CSS::Length::make_px(rect.width());
+    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);
+
+    // 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
     // Scale overlapping curves according to https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
     auto f = 1.0f;
     auto f = 1.0f;

+ 6 - 1
Userland/Libraries/LibWeb/Painting/BorderPainting.h

@@ -23,7 +23,12 @@ struct BorderRadiiData {
     BorderRadiusData bottom_left;
     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 {
 enum class BorderEdge {
     Top,
     Top,

+ 1 - 1
Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp

@@ -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 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);
             Painting::paint_all_borders(context, bordered_rect, border_radii_data, borders_data);
 
 

+ 4 - 3
Userland/Libraries/LibWeb/Painting/PaintableBox.cpp

@@ -178,7 +178,7 @@ void PaintableBox::paint_border(PaintContext& context) const
         .bottom = computed_values().border_bottom(),
         .bottom = computed_values().border_bottom(),
         .left = computed_values().border_left(),
         .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
 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);
     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(),
     return Painting::normalized_border_radii_data(layout_box(), absolute_border_box_rect(),
         computed_values().border_top_left_radius(),
         computed_values().border_top_left_radius(),
         computed_values().border_top_right_radius(),
         computed_values().border_top_right_radius(),
         computed_values().border_bottom_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
 void PaintableBox::before_children_paint(PaintContext& context, PaintPhase) const

+ 1 - 1
Userland/Libraries/LibWeb/Painting/PaintableBox.h

@@ -130,7 +130,7 @@ protected:
     virtual Gfx::FloatRect compute_absolute_rect() const;
     virtual Gfx::FloatRect compute_absolute_rect() const;
 
 
 private:
 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;
     OwnPtr<Painting::StackingContext> m_stacking_context;