Explorar o código

LibWeb: Support rendering background images with 'background-repeat'

Update the painting of background images for both <body> nodes and other
non-initial nodes. Currently, only the following values are supported:
    repeat, repeat-x, repeat-y, no-repeat

This also doesn't support the two-value syntax which allows for setting
horizontal and vertical repetition separately.
Timothy Flynn %!s(int64=4) %!d(string=hai) anos
pai
achega
fa9ba8bce5

+ 13 - 0
Userland/Libraries/LibWeb/DOM/Document.cpp

@@ -362,6 +362,19 @@ RefPtr<Gfx::Bitmap> Document::background_image() const
     return background_image->bitmap();
     return background_image->bitmap();
 }
 }
 
 
+CSS::Repeat Document::background_repeat() const
+{
+    auto* body_element = body();
+    if (!body_element)
+        return CSS::Repeat::Repeat;
+
+    auto* body_layout_node = body_element->layout_node();
+    if (!body_layout_node)
+        return CSS::Repeat::Repeat;
+
+    return body_layout_node->computed_values().background_repeat();
+}
+
 URL Document::complete_url(const String& string) const
 URL Document::complete_url(const String& string) const
 {
 {
     return m_url.complete_url(string);
     return m_url.complete_url(string);

+ 1 - 0
Userland/Libraries/LibWeb/DOM/Document.h

@@ -129,6 +129,7 @@ public:
 
 
     Color background_color(const Gfx::Palette&) const;
     Color background_color(const Gfx::Palette&) const;
     RefPtr<Gfx::Bitmap> background_image() const;
     RefPtr<Gfx::Bitmap> background_image() const;
+    CSS::Repeat background_repeat() const;
 
 
     Color link_color() const;
     Color link_color() const;
     void set_link_color(Color);
     void set_link_color(Color);

+ 17 - 0
Userland/Libraries/LibWeb/Layout/Box.cpp

@@ -49,6 +49,23 @@ void Box::paint(PaintContext& context, PaintPhase phase)
         auto background_rect = enclosing_int_rect(padded_rect);
         auto background_rect = enclosing_int_rect(padded_rect);
         context.painter().fill_rect(background_rect, computed_values().background_color());
         context.painter().fill_rect(background_rect, computed_values().background_color());
         if (background_image() && background_image()->bitmap()) {
         if (background_image() && background_image()->bitmap()) {
+            switch (computed_values().background_repeat()) {
+            case CSS::Repeat::Repeat:
+                // The background rect is already sized to align with 'repeat'.
+                break;
+            case CSS::Repeat::RepeatX:
+                background_rect.set_height(background_image()->bitmap()->height());
+                break;
+            case CSS::Repeat::RepeatY:
+                background_rect.set_width(background_image()->bitmap()->width());
+                break;
+            case CSS::Repeat::NoRepeat:
+            default: // FIXME: Support 'round' and 'square'
+                background_rect.set_width(background_image()->bitmap()->width());
+                background_rect.set_height(background_image()->bitmap()->height());
+                break;
+            }
+
             context.painter().blit_tiled(background_rect, *background_image()->bitmap(), background_image()->bitmap()->rect());
             context.painter().blit_tiled(background_rect, *background_image()->bitmap(), background_image()->bitmap()->rect());
         }
         }
     }
     }

+ 24 - 6
Userland/Libraries/LibWeb/Layout/InitialContainingBlockBox.cpp

@@ -68,12 +68,30 @@ void InitialContainingBlockBox::paint_document_background(PaintContext& context)
     context.painter().translate(-context.viewport_rect().location());
     context.painter().translate(-context.viewport_rect().location());
 
 
     if (auto background_bitmap = document().background_image()) {
     if (auto background_bitmap = document().background_image()) {
-        Gfx::IntRect background_rect {
-            0,
-            0,
-            context.viewport_rect().x() + context.viewport_rect().width(),
-            context.viewport_rect().y() + context.viewport_rect().height()
-        };
+        int painted_image_width = 0;
+        int painted_image_height = 0;
+
+        switch (document().background_repeat()) {
+        case CSS::Repeat::Repeat:
+            painted_image_width = context.viewport_rect().x() + context.viewport_rect().width();
+            painted_image_height = context.viewport_rect().y() + context.viewport_rect().height();
+            break;
+        case CSS::Repeat::RepeatX:
+            painted_image_width = context.viewport_rect().x() + context.viewport_rect().width();
+            painted_image_height = background_bitmap->rect().height();
+            break;
+        case CSS::Repeat::RepeatY:
+            painted_image_width = background_bitmap->rect().width();
+            painted_image_height = context.viewport_rect().y() + context.viewport_rect().height();
+            break;
+        case CSS::Repeat::NoRepeat:
+        default: // FIXME: Support 'round' and 'square'
+            painted_image_width = background_bitmap->rect().width();
+            painted_image_height = background_bitmap->rect().height();
+            break;
+        }
+
+        Gfx::IntRect background_rect { 0, 0, painted_image_width, painted_image_height };
         context.painter().blit_tiled(background_rect, *background_bitmap, background_bitmap->rect());
         context.painter().blit_tiled(background_rect, *background_bitmap, background_bitmap->rect());
     }
     }
 }
 }