فهرست منبع

LibWeb: Support using border-radius with a background-image

MacDue 3 سال پیش
والد
کامیت
4e8e1492f9
1فایلهای تغییر یافته به همراه39 افزوده شده و 8 حذف شده
  1. 39 8
      Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp

+ 39 - 8
Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp

@@ -10,6 +10,7 @@
 #include <LibWeb/Layout/InitialContainingBlock.h>
 #include <LibWeb/Layout/Node.h>
 #include <LibWeb/Painting/BackgroundPainting.h>
+#include <LibWeb/Painting/BorderRadiusCornerClipper.h>
 #include <LibWeb/Painting/PaintContext.h>
 
 namespace Web::Painting {
@@ -42,18 +43,46 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
     if (background_layers && !background_layers->is_empty())
         color_rect = get_box(background_layers->last().clip);
 
-    Gfx::AntiAliasingPainter aa_painter { painter };
-    aa_painter.fill_rect_with_rounded_corners(color_rect.to_rounded<int>(),
-        background_color, border_radii.top_left.as_corner(), border_radii.top_right.as_corner(), border_radii.bottom_right.as_corner(), border_radii.bottom_left.as_corner());
+    auto layer_is_paintable = [&](auto& layer) {
+        return layer.image && layer.image->bitmap();
+    };
+
+    bool has_paintable_layers = false;
+    if (background_layers) {
+        for (auto& layer : *background_layers) {
+            if (layer_is_paintable(layer)) {
+                has_paintable_layers = true;
+                break;
+            }
+        }
+    }
+
+    Optional<BorderRadiusCornerClipper> corner_radius_clipper {};
 
-    if (!background_layers)
+    if (border_radii.has_any_radius()) {
+        if (!has_paintable_layers) {
+            Gfx::AntiAliasingPainter aa_painter { painter };
+            aa_painter.fill_rect_with_rounded_corners(color_rect.to_rounded<int>(),
+                background_color, border_radii.top_left.as_corner(), border_radii.top_right.as_corner(), border_radii.bottom_right.as_corner(), border_radii.bottom_left.as_corner());
+            return;
+        }
+        auto clipper = BorderRadiusCornerClipper::create(border_rect.to_rounded<int>(), border_radii);
+        if (!clipper.is_error())
+            corner_radius_clipper = clipper.release_value();
+    }
+
+    if (corner_radius_clipper.has_value())
+        corner_radius_clipper->sample_under_corners(painter);
+
+    painter.fill_rect(color_rect.to_rounded<int>(), background_color);
+
+    if (!has_paintable_layers)
         return;
 
     // Note: Background layers are ordered front-to-back, so we paint them in reverse
-    for (int layer_index = background_layers->size() - 1; layer_index >= 0; layer_index--) {
-        auto& layer = background_layers->at(layer_index);
+    for (auto& layer : background_layers->in_reverse()) {
         // TODO: Gradients!
-        if (!layer.image || !layer.image->bitmap())
+        if (!layer_is_paintable(layer))
             continue;
         auto& image = *layer.image->bitmap();
 
@@ -230,7 +259,6 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
             image_rect.set_y(image_rect.y() - y_delta);
         }
 
-        // FIXME: Handle rounded corners
         float initial_image_x = image_rect.x();
         float image_y = image_rect.y();
         while (image_y < clip_rect.bottom()) {
@@ -252,6 +280,9 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
 
         painter.restore();
     }
+
+    if (corner_radius_clipper.has_value())
+        corner_radius_clipper->blit_corner_clipping(painter);
 }
 
 }