diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2021-11-15 17:05:06 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-11-17 22:20:01 +0100 |
commit | 7089681f6811a0f81270a665f1ba1849c54d7a01 (patch) | |
tree | 8ef374d61f6ed724578adc1807d430ccf61a2f50 /Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp | |
parent | 6234e3fcb39000ec75524bb00875087acde8aa74 (diff) | |
download | serenity-7089681f6811a0f81270a665f1ba1849c54d7a01.zip |
LibWeb: Manually tile background images
This reimplements image tiling instead of using `Painter::blit_tiled()`,
so that we will be able to handle CSS's more complicated repetition
rules. (Like `background-repeat: space`) Otherwise this does the same as
before. :^)
Diffstat (limited to 'Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp')
-rw-r--r-- | Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp index b67bf39bfb..1708274a1b 100644 --- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -56,43 +56,75 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet painter.save(); painter.add_clip_rect(clip_rect); - auto painting_rect = border_rect; - // FIXME: Attachment // FIXME: Size - int scaled_width = image.width(); - int scaled_height = image.height(); + Gfx::IntRect image_rect { border_rect.x(), border_rect.y(), image.width(), image.height() }; // FIXME: Origin // FIXME: Position // Repetition + bool repeat_x = false; + bool repeat_y = false; + float x_step = 0; + float y_step = 0; + switch (layer.repeat_x) { case CSS::Repeat::Round: case CSS::Repeat::Space: // FIXME: Support 'round' and 'space'. Fall through to 'repeat' since that most closely resembles these. case CSS::Repeat::Repeat: - // The background rect is already sized to align with 'repeat'. + x_step = image_rect.width(); + repeat_x = true; break; case CSS::Repeat::NoRepeat: - painting_rect.set_width(min(painting_rect.width(), scaled_width)); + repeat_x = false; break; } + // Move image_rect to the left-most tile position that is still visible + if (repeat_x && image_rect.x() > clip_rect.x()) { + auto x_delta = floorf(x_step * ceilf((image_rect.x() - clip_rect.x()) / x_step)); + image_rect.set_x(image_rect.x() - x_delta); + } switch (layer.repeat_y) { case CSS::Repeat::Round: case CSS::Repeat::Space: // FIXME: Support 'round' and 'space'. Fall through to 'repeat' since that most closely resembles these. case CSS::Repeat::Repeat: - // The background rect is already sized to align with 'repeat'. + y_step = image_rect.height(); + repeat_y = true; break; case CSS::Repeat::NoRepeat: - painting_rect.set_height(min(painting_rect.height(), scaled_height)); + repeat_y = false; break; } + // Move image_rect to the top-most tile position that is still visible + if (repeat_y && image_rect.y() > clip_rect.y()) { + auto y_delta = floorf(y_step * ceilf((image_rect.y() - clip_rect.y()) / y_step)); + image_rect.set_y(image_rect.y() - y_delta); + } // FIXME: Handle rounded corners - painter.blit_tiled(painting_rect, image, image.rect()); + float initial_image_x = image_rect.x(); + float image_y = image_rect.y(); + while (image_y < clip_rect.bottom()) { + image_rect.set_y(roundf(image_y)); + + float image_x = initial_image_x; + while (image_x < clip_rect.right()) { + image_rect.set_x(roundf(image_x)); + painter.draw_scaled_bitmap(image_rect, image, image.rect(), 1.0f, Gfx::Painter::ScalingMode::BilinearBlend); + if (!repeat_x) + break; + image_x += x_step; + } + + if (!repeat_y) + break; + image_y += y_step; + } + painter.restore(); } } |