mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:47:45 +00:00
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. :^)
This commit is contained in:
parent
6234e3fcb3
commit
7089681f68
1 changed files with 41 additions and 9 deletions
|
@ -56,43 +56,75 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet
|
||||||
painter.save();
|
painter.save();
|
||||||
painter.add_clip_rect(clip_rect);
|
painter.add_clip_rect(clip_rect);
|
||||||
|
|
||||||
auto painting_rect = border_rect;
|
|
||||||
|
|
||||||
// FIXME: Attachment
|
// FIXME: Attachment
|
||||||
// FIXME: Size
|
// FIXME: Size
|
||||||
int scaled_width = image.width();
|
Gfx::IntRect image_rect { border_rect.x(), border_rect.y(), image.width(), image.height() };
|
||||||
int scaled_height = image.height();
|
|
||||||
|
|
||||||
// FIXME: Origin
|
// FIXME: Origin
|
||||||
// FIXME: Position
|
// FIXME: Position
|
||||||
|
|
||||||
// Repetition
|
// Repetition
|
||||||
|
bool repeat_x = false;
|
||||||
|
bool repeat_y = false;
|
||||||
|
float x_step = 0;
|
||||||
|
float y_step = 0;
|
||||||
|
|
||||||
switch (layer.repeat_x) {
|
switch (layer.repeat_x) {
|
||||||
case CSS::Repeat::Round:
|
case CSS::Repeat::Round:
|
||||||
case CSS::Repeat::Space:
|
case CSS::Repeat::Space:
|
||||||
// FIXME: Support 'round' and 'space'. Fall through to 'repeat' since that most closely resembles these.
|
// FIXME: Support 'round' and 'space'. Fall through to 'repeat' since that most closely resembles these.
|
||||||
case CSS::Repeat::Repeat:
|
case CSS::Repeat::Repeat:
|
||||||
// The background rect is already sized to align with 'repeat'.
|
x_step = image_rect.width();
|
||||||
|
repeat_x = true;
|
||||||
break;
|
break;
|
||||||
case CSS::Repeat::NoRepeat:
|
case CSS::Repeat::NoRepeat:
|
||||||
painting_rect.set_width(min(painting_rect.width(), scaled_width));
|
repeat_x = false;
|
||||||
break;
|
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) {
|
switch (layer.repeat_y) {
|
||||||
case CSS::Repeat::Round:
|
case CSS::Repeat::Round:
|
||||||
case CSS::Repeat::Space:
|
case CSS::Repeat::Space:
|
||||||
// FIXME: Support 'round' and 'space'. Fall through to 'repeat' since that most closely resembles these.
|
// FIXME: Support 'round' and 'space'. Fall through to 'repeat' since that most closely resembles these.
|
||||||
case CSS::Repeat::Repeat:
|
case CSS::Repeat::Repeat:
|
||||||
// The background rect is already sized to align with 'repeat'.
|
y_step = image_rect.height();
|
||||||
|
repeat_y = true;
|
||||||
break;
|
break;
|
||||||
case CSS::Repeat::NoRepeat:
|
case CSS::Repeat::NoRepeat:
|
||||||
painting_rect.set_height(min(painting_rect.height(), scaled_height));
|
repeat_y = false;
|
||||||
break;
|
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
|
// 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();
|
painter.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue