Commit 317042f2 authored by fs@opera.com's avatar fs@opera.com

Use the viewBox when scaling <svg:image>s non-uniformly w/ pAR=none

When referencing an SVG image from <svg:image> with pAR set to 'none', and
said image had no intrinsic size, but a 'viewBox', the use of the intrinsic
size (which would be computed as 300x150) as the container size would
incorrect. The 'viewBox' would resolve against 300x150, so if it defined
a different aspect ratio than that, the image would not appear correctly
scaled.

For pAR=none there're a number of cases to consider:
  1) The referenced image has a 'viewBox'.
  2) The referenced image has intrinsic dimensions.
  3) The referenced image has none of the above.
For cases (1) and (2), we should use the 'viewBox' and intrinsic dimensions
(respectively) to define the container size (~= the image's viewport maps
to the viewport defined by <svg:image>). In case (3) we try to use whatever
is left to use (300x150). (In practice cases (2) and (3) should be
equivalent.)

This also recognizes that the TC
svg/custom/svg-image-par-none-zero-intrinsic-size.html
is incorrect, and modifies it. Gecko seem to agree with this change.

The TC from the bug also made it obvious that there was a repaint bug at
play, which resulted in the updated return value from
RenderSVGImage::updateImageViewport. This is covered by the existing TC
svg/custom/svg-image-par-resize.html, which now seem to issue more correct
repaint rectangles.

BUG=428324

Review URL: https://codereview.chromium.org/713263002

git-svn-id: svn://svn.chromium.org/blink/trunk@185226 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent ef038be4
......@@ -1271,6 +1271,8 @@ crbug.com/418324 http/tests/media/media-source/mediasource-redundant-seek.html [
crbug.com/340522 [ Mac ] fast/forms/calendar-picker/calendar-picker-appearance.html [ Pass ImageOnlyFailure ]
crbug.com/428324 svg/custom/svg-image-par-resize.html [ NeedsRebaseline ]
crbug.com/427606 virtual/gpu/fast/canvas/canvas-shadow-source-in.html [ Pass ImageOnlyFailure ]
crbug.com/419486 [ Mac ] fast/text/atsui-small-caps-punctuation-size.html [ Pass Failure ]
......
<!DOCTYPE html>
<div style="width: 100px; height: 200px; background-color: green"></div>
<!DOCTYPE html>
<svg width="100" height="200" style="background-color: red">
<image width="100" height="200" preserveAspectRatio="none"
xlink:href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' fill='green'/></svg>"/>
</svg>
<!DOCTYPE html>
<div style="width: 100px; height: 200px; background-color: green"></div>
<!DOCTYPE html>
<svg width="100" height="200" style="background-color: red">
<image width="100" height="200" preserveAspectRatio="none"
xlink:href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='50%' height='50%' viewBox='0 0 100 100'><rect width='100' height='100' fill='green'/></svg>"/>
</svg>
<!DOCTYPE html>
<svg width="100" height="100" style="background-color: red">
<svg width="100" height="100" style="background-color: green">
<image width="100" height="100" preserveAspectRatio="none"
xlink:href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='0'><rect width='100' height='100' fill='green'/></svg>"/>
xlink:href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='0'><rect width='100' height='100' fill='red'/></svg>"/>
</svg>
......@@ -61,58 +61,43 @@ void RenderSVGImage::destroy()
RenderSVGModelObject::destroy();
}
bool RenderSVGImage::forceNonUniformScaling(SVGImageElement* image) const
FloatSize RenderSVGImage::computeImageViewportSize(ImageResource& cachedImage) const
{
if (toSVGImageElement(element())->preserveAspectRatio()->currentValue()->align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE)
return m_objectBoundingBox.size();
// Images with preserveAspectRatio=none should force non-uniform
// scaling. This can be achieved by setting the image's container size to
// its intrinsic size. If the image does not have an intrinsic size - or
// the intrinsic size is degenerate - set the container size to the bounds
// as in pAR!=none cases.
// its viewport size (i.e. if a viewBox is available - use that - else use intrinsic size.)
// See: http://www.w3.org/TR/SVG/single-page.html, 7.8 The ‘preserveAspectRatio’ attribute.
if (image->preserveAspectRatio()->currentValue()->align() != SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE)
return false;
ImageResource* cachedImage = m_imageResource->cachedImage();
if (!cachedImage)
return false;
Length intrinsicWidth;
Length intrinsicHeight;
FloatSize intrinsicRatio;
cachedImage->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
if (!intrinsicWidth.isFixed() || !intrinsicHeight.isFixed())
return false;
// If the viewport defined by the referenced image is zero in either
// dimension, then SVGImage will have computed an intrinsic size of 300x150.
if (!floatValueForLength(intrinsicWidth, 0) || !floatValueForLength(intrinsicHeight, 0))
return false;
return true;
cachedImage.computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
return intrinsicRatio;
}
bool RenderSVGImage::updateImageViewport()
{
SVGImageElement* image = toSVGImageElement(element());
FloatRect oldBoundaries = m_objectBoundingBox;
bool updatedViewport = false;
SVGLengthContext lengthContext(image);
m_objectBoundingBox = FloatRect(image->x()->currentValue()->value(lengthContext), image->y()->currentValue()->value(lengthContext), image->width()->currentValue()->value(lengthContext), image->height()->currentValue()->value(lengthContext));
bool boundsChanged = oldBoundaries != m_objectBoundingBox;
IntSize newViewportSize;
if (forceNonUniformScaling(image)) {
LayoutSize intrinsicSize = m_imageResource->intrinsicSize(style()->effectiveZoom());
if (intrinsicSize != m_imageResource->imageSize(style()->effectiveZoom())) {
newViewportSize = roundedIntSize(intrinsicSize);
bool updatedViewport = false;
ImageResource* cachedImage = m_imageResource->cachedImage();
if (cachedImage && cachedImage->usesImageContainerSize()) {
FloatSize imageViewportSize = computeImageViewportSize(*cachedImage);
if (imageViewportSize != m_imageResource->imageSize(style()->effectiveZoom())) {
m_imageResource->setContainerSizeForRenderer(roundedIntSize(imageViewportSize));
updatedViewport = true;
}
} else if (boundsChanged) {
newViewportSize = enclosingIntRect(m_objectBoundingBox).size();
updatedViewport = true;
}
if (updatedViewport)
m_imageResource->setContainerSizeForRenderer(newViewportSize);
m_needsBoundariesUpdate |= boundsChanged;
return updatedViewport;
return updatedViewport || boundsChanged;
}
void RenderSVGImage::layout()
......
......@@ -63,7 +63,7 @@ private:
virtual void layout() override;
virtual void paint(PaintInfo&, const LayoutPoint&) override;
bool forceNonUniformScaling(SVGImageElement*) const;
FloatSize computeImageViewportSize(ImageResource&) const;
virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
......
......@@ -84,6 +84,10 @@ public:
virtual bool usesContainerSize() const { return false; }
virtual bool hasRelativeWidth() const { return false; }
virtual bool hasRelativeHeight() const { return false; }
// Computes (extracts) the intrinsic dimensions and ratio from the Image. The intrinsic ratio
// will be the 'viewport' of the image. (Same as the dimensions for a raster image. For SVG
// images it can be the dimensions defined by the 'viewBox'.)
virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
virtual IntSize size() const = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment