diff --git a/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp b/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp index 7629c51961..a19917acb6 100644 --- a/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp @@ -64,8 +64,71 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const context.painter().draw_text(enclosing_rect, alt, Gfx::TextAlignment::Center, computed_values().color(), Gfx::TextElision::Right); } else if (auto bitmap = layout_box().image_provider().current_image_bitmap(image_rect.size().to_type())) { ScopedCornerRadiusClip corner_clip { context, context.painter(), image_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; - auto scaling_mode = to_gfx_scaling_mode(computed_values().image_rendering(), bitmap->rect(), image_rect.to_type()); - context.painter().draw_scaled_bitmap(image_rect.to_type(), *bitmap, bitmap->rect(), 1.f, scaling_mode); + auto image_int_rect = image_rect.to_type(); + auto bitmap_rect = bitmap->rect(); + auto scaling_mode = to_gfx_scaling_mode(computed_values().image_rendering(), bitmap_rect, image_int_rect); + auto& dom_element = verify_cast(*dom_node()); + auto object_fit = dom_element.computed_css_values()->object_fit(); + auto bitmap_aspect_ratio = bitmap_rect.height() / bitmap_rect.width(); + auto image_aspect_ratio = (float)image_rect.height().value() / image_rect.width().value(); + + auto scale_x = 0.0f; + auto scale_y = 0.0f; + Gfx::IntRect bitmap_intersect = bitmap_rect; + + auto object_fit_value = CSS::InitialValues::object_fit(); + + if (object_fit.has_value()) + object_fit_value = object_fit.value(); + + switch (object_fit_value) { + case CSS::ObjectFit::Fill: + scale_x = (float)image_int_rect.width() / bitmap_rect.width(); + scale_y = (float)image_int_rect.height() / bitmap_rect.height(); + bitmap_intersect = bitmap_rect; + break; + case CSS::ObjectFit::Contain: + if (bitmap_aspect_ratio >= image_aspect_ratio) { + scale_x = (float)image_int_rect.height() / bitmap_rect.height(); + scale_y = scale_x; + } else { + scale_x = (float)image_int_rect.width() / bitmap_rect.width(); + scale_y = scale_x; + } + break; + case CSS::ObjectFit::Cover: + if (bitmap_aspect_ratio >= image_aspect_ratio) { + scale_x = (float)image_int_rect.width() / bitmap_rect.width(); + scale_y = scale_x; + bitmap_intersect.set_height(bitmap_rect.width() * image_aspect_ratio); + } else { + scale_x = (float)image_int_rect.height() / bitmap_rect.height(); + scale_y = scale_x; + bitmap_intersect.set_width(bitmap_rect.height() / image_aspect_ratio); + } + break; + case CSS::ObjectFit::ScaleDown: + // FIXME: Implement + case CSS::ObjectFit::None: + scale_x = 1; + scale_y = 1; + bitmap_intersect.set_size(image_int_rect.size()); + } + + bitmap_intersect.set_x((bitmap_rect.width() - bitmap_intersect.width()) / 2); + bitmap_intersect.set_y((bitmap_rect.height() - bitmap_intersect.height()) / 2); + + auto offset_x = (image_int_rect.width() - bitmap_rect.width() * scale_x) / 2; + auto offset_y = (image_int_rect.height() - bitmap_rect.height() * scale_y) / 2; + + Gfx::IntRect draw_rect = { + image_int_rect.x() + offset_x, + image_int_rect.y() + offset_y, + bitmap_rect.width() * scale_x, + bitmap_rect.height() * scale_y + }; + + context.painter().draw_scaled_bitmap(draw_rect.intersected(image_int_rect), *bitmap, bitmap_rect.intersected(bitmap_intersect), 1.f, scaling_mode); } } }