LibWeb: Respect SVG intrinsic sizing during object fitting

Previously we used the `frame_rect` size, this is the same as the
intrinsic size for bitmap images but is `OptionalNone` for SVG which
caused us to always fall back to the `image_rect` and thus not apply
any scaling for SVGs regardless of whether they had intrinsic sizing.
This commit is contained in:
Callum Law 2026-06-12 17:11:37 +12:00 committed by Alexander Kalenik
parent f6f68ece44
commit d3c0cfdc71
6 changed files with 74 additions and 1 deletions

View file

@ -75,7 +75,12 @@ void ImagePaintable::paint(DisplayListRecordingContext& context, PaintPhase phas
// https://drafts.csswg.org/css-images/#the-object-fit
auto object_fit = m_is_svg_image ? CSS::ObjectFit::Contain : computed_values().object_fit();
auto draw_rect = get_replaced_box_painting_area(*this, context, object_fit, bitmap_rect.size());
auto intrinsic_size = m_image_provider.intrinsic_size()
.map([](auto size) { return size.template to_type<int>(); })
.value_or(image_int_rect_device_pixels.size());
auto draw_rect = get_replaced_box_painting_area(*this, context, object_fit, intrinsic_size);
if (!draw_rect.is_empty()) {
auto draw_rect_needs_clip = !image_int_rect_device_pixels.contains(draw_rect);
if (draw_rect_needs_clip) {

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="120" height="72" viewBox="0 0 120 72">
<rect width="120" height="72" fill="#f4f4f4" />
<rect width="60" height="72" fill="#2f80ed" />
<rect x="60" width="60" height="72" fill="#27ae60" />
<circle cx="30" cy="36" r="18" fill="#fff" />
<path d="M75 14h30l-15 44z" fill="#fff" />
<rect x="1" y="1" width="118" height="70" fill="none" stroke="#111" stroke-width="2" />
</svg>

After

Width:  |  Height:  |  Size: 442 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="144" viewBox="0 0 120 72">
<rect width="120" height="72" fill="#f4f4f4" />
<rect width="60" height="72" fill="#2f80ed" />
<rect x="60" width="60" height="72" fill="#27ae60" />
<circle cx="30" cy="36" r="18" fill="#fff" />
<path d="M75 14h30l-15 44z" fill="#fff" />
<rect x="1" y="1" width="118" height="70" fill="none" stroke="#111" stroke-width="2" />
</svg>

After

Width:  |  Height:  |  Size: 443 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 72">
<rect width="120" height="72" fill="#f4f4f4" />
<rect width="60" height="72" fill="#2f80ed" />
<rect x="60" width="60" height="72" fill="#27ae60" />
<circle cx="30" cy="36" r="18" fill="#fff" />
<path d="M75 14h30l-15 44z" fill="#fff" />
<rect x="1" y="1" width="118" height="70" fill="none" stroke="#111" stroke-width="2" />
</svg>

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,44 @@
<!doctype html>
<meta name="fuzzy" content="maxDifference=0-2;totalPixels=0-8828" />
<style>
body {
margin: 0;
}
.grid {
display: grid;
grid-template-columns: repeat(3, max-content);
gap: 4px;
margin-bottom: 4px;
}
img {
display: block;
background: #ddd;
width: 160px;
height: 80px;
border: 1px solid #111;
}
</style>
<div class="grid">
<img style="object-fit: contain" src="../data/out-of-line-svg-object-fitting-120x72.svg" />
<img style="object-fit: fill" src="../data/out-of-line-svg-object-fitting-120x72.svg" />
<img style="object-fit: cover" src="../data/out-of-line-svg-object-fitting-120x72.svg" />
<img style="object-fit: none" src="../data/out-of-line-svg-object-fitting-120x72.svg" />
<img style="object-fit: scale-down" src="../data/out-of-line-svg-object-fitting-120x72.svg" />
</div>
<div class="grid">
<img style="object-fit: contain" src="../data/out-of-line-svg-object-fitting-240x144.svg" />
<img style="object-fit: fill" src="../data/out-of-line-svg-object-fitting-240x144.svg" />
<img style="object-fit: cover" src="../data/out-of-line-svg-object-fitting-240x144.svg" />
<img style="object-fit: none" src="../data/out-of-line-svg-object-fitting-240x144.svg" />
<img style="object-fit: scale-down" src="../data/out-of-line-svg-object-fitting-240x144.svg" />
</div>
<div class="grid">
<img style="object-fit: contain" src="../data/out-of-line-svg-object-fitting-no-intrinsic-size.svg" />
<img style="object-fit: fill" src="../data/out-of-line-svg-object-fitting-no-intrinsic-size.svg" />
<img style="object-fit: cover" src="../data/out-of-line-svg-object-fitting-no-intrinsic-size.svg" />
<img style="object-fit: none" src="../data/out-of-line-svg-object-fitting-no-intrinsic-size.svg" />
<img style="object-fit: scale-down" src="../data/out-of-line-svg-object-fitting-no-intrinsic-size.svg" />
</div>