Skip to content

Commit 2f7f2a1

Browse files
Ahmad-S792Ahmad Saleem
authored andcommitted
Synthesize preserveAspectRatio='none' for SVGs embedded in <img> without viewBox
https://bugs.webkit.org/show_bug.cgi?id=304669 rdar://167121931 Reviewed by Nikolas Zimmermann. When an SVG is embedded through SVGImage (e.g., in an <img> tag) and has fixed width/height attributes but no explicit viewBox, WebKit synthesizes a viewBox matching the SVG's intrinsic dimensions. However, this alone causes the SVG to preserve its aspect ratio and center within the <img> container, which differs from Chrome and Firefox behavior. Chrome and Firefox stretch the SVG to fill the container dimensions in these cases, matching the behavior of raster images. To align with this behavior and meet author expectations, we now also synthesize preserveAspectRatio='none' when a viewBox is synthesized for an embedded SVG. This allows the SVG content to stretch to fill the <img> container, consistent with other browsers and the expected behavior for replaced elements. * Source/WebCore/svg/SVGSVGElement.cpp: (WebCore::isEmbeddedThroughSVGImage): (WebCore::SVGSVGElement::currentViewBoxRect const): (WebCore::SVGSVGElement::viewBoxToViewTransform const): * LayoutTests/svg/as-image/svg-image-aspect-ration-par-none.html: Added. * LayoutTests/svg/as-image/svg-image-aspect-ration-par-none-expected.html: Added. Canonical link: https://commits.webkit.org/305043@main
1 parent c948de8 commit 2f7f2a1

File tree

3 files changed

+45
-20
lines changed

3 files changed

+45
-20
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<style>
3+
img, svg {
4+
border: 5px solid red;
5+
}
6+
</style>
7+
<body>
8+
<img style="width: 200px; height: 500px;" src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='500'><rect fill='lime' width='200' height='500'/></svg>">
9+
<img style="width: 500px; height: 200px;" src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='500' height='200'><rect fill='lime' width='500' height='200'/></svg>">
10+
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="50">
11+
<rect fill="lime" width="100" height="50"/>
12+
</svg>
13+
</body>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<style>
3+
img, svg {
4+
border: 5px solid red;
5+
}
6+
</style>
7+
<body>
8+
<img style="width: 200px; height: 500px;" src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='50' preserveAspectRatio='xMidYMid meet'><rect fill='lime' width='100' height='50'/></svg>">
9+
<img style="width: 500px; height: 200px;" src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='50' preserveAspectRatio='xMidYMid meet'><rect fill='lime' width='100' height='50'/></svg>">
10+
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="50">
11+
<rect fill="lime" width="100" height="50"/>
12+
</svg>
13+
</body>

Source/WebCore/svg/SVGSVGElement.cpp

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "SVGAngle.h"
4848
#include "SVGDocumentExtensions.h"
4949
#include "SVGElementTypeHelpers.h"
50+
#include "SVGImage.h"
5051
#include "SVGLength.h"
5152
#include "SVGMatrix.h"
5253
#include "SVGNumber.h"
@@ -573,6 +574,11 @@ bool SVGSVGElement::hasTransformRelatedAttributes() const
573574
return (hasAttribute(SVGNames::xAttr) || hasAttribute(SVGNames::yAttr)) || (hasAttribute(SVGNames::viewBoxAttr) && !hasEmptyViewBox());
574575
}
575576

577+
static bool isEmbeddedThroughSVGImage(const SVGSVGElement& element)
578+
{
579+
return element.document().documentElement() == &element && isInSVGImage(&element);
580+
}
581+
576582
FloatRect SVGSVGElement::currentViewBoxRect() const
577583
{
578584
if (m_useCurrentView) {
@@ -585,24 +591,7 @@ FloatRect SVGSVGElement::currentViewBoxRect() const
585591
if (!viewBox.isEmpty())
586592
return viewBox;
587593

588-
auto isEmbeddedThroughSVGImage = [this](const RenderElement* renderer) -> bool {
589-
auto isDocumentElement = document().documentElement() == this;
590-
if (!isDocumentElement)
591-
return false;
592-
593-
if (!renderer)
594-
return false;
595-
596-
if (auto* svgRoot = dynamicDowncast<LegacyRenderSVGRoot>(renderer))
597-
return svgRoot->isEmbeddedThroughSVGImage();
598-
599-
if (auto* svgRoot = dynamicDowncast<RenderSVGRoot>(renderer))
600-
return svgRoot->isEmbeddedThroughSVGImage();
601-
602-
return false;
603-
};
604-
605-
if (!isEmbeddedThroughSVGImage(checkedRenderer().get()))
594+
if (!isEmbeddedThroughSVGImage(*this))
606595
return { };
607596

608597
// If no viewBox is specified but non-relative width/height values, then we
@@ -668,8 +657,18 @@ float SVGSVGElement::intrinsicHeight() const
668657

669658
AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float viewHeight) const
670659
{
671-
if (!m_useCurrentView || !m_viewSpec)
672-
return SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), preserveAspectRatio(), viewWidth, viewHeight);
660+
if (!m_useCurrentView || !m_viewSpec) {
661+
auto currentViewBox = currentViewBoxRect();
662+
// If we synthesized a viewBox (no explicit viewBox but embedded through SVGImage),
663+
// we should also synthesize preserveAspectRatio="none" to allow stretching.
664+
if (viewBox().isEmpty() && !currentViewBox.isEmpty() && isEmbeddedThroughSVGImage(*this)) {
665+
// Create a synthetic preserveAspectRatio with align="none".
666+
auto preserveAspectRatio = SVGPreserveAspectRatioValue(SVGPreserveAspectRatioValue::SVG_PRESERVEASPECTRATIO_NONE, SVGPreserveAspectRatioValue::SVG_MEETORSLICE_MEET);
667+
return SVGFitToViewBox::viewBoxToViewTransform(currentViewBox, preserveAspectRatio, viewWidth, viewHeight);
668+
}
669+
670+
return SVGFitToViewBox::viewBoxToViewTransform(currentViewBox, preserveAspectRatio(), viewWidth, viewHeight);
671+
}
673672

674673
RefPtr viewSpec = m_viewSpec;
675674
AffineTransform transform = SVGFitToViewBox::viewBoxToViewTransform(currentViewBoxRect(), viewSpec->preserveAspectRatio(), viewWidth, viewHeight);

0 commit comments

Comments
 (0)