Title: [123171] trunk
Revision
123171
Author
[email protected]
Date
2012-07-19 20:59:03 -0700 (Thu, 19 Jul 2012)

Log Message

SVG images broken when max-width specified.
https://bugs.webkit.org/show_bug.cgi?id=91474

Source/WebCore: 

SVG images were computing intrinsic dimensions when width and height were auto that did not
respect min-max width/height. Normal images had code that applied these constraints properly.
Looking at the code before the check-in that broke things, these constraints used to be
applied to all images regardless of type via calcAspectRatioLogicalWidth/Height.
        
This patch leaves the new function structure in place but converts the code to be more like
it was prior to the introduction of the regression. Instead of raw intrinsic sizes being
used in the SVG case, now all image types get the intrinsic sizes constrained when doing
width/height computations.

Reviewed by Dan Bernstein.

Test: svg/as-image/svg-intrinsic-size.html

* rendering/RenderReplaced.cpp:
(WebCore::RenderReplaced::computeAspectRatioInformationForRenderBox):
Rename computeIntrinsicRatioInformationForRenderBox to computeAspectRatioInformationForRenderBox.
Also rename the intrinsicSize reference to constrainedSize to reflect the fact that the size
is not necessarily the intrinsic size any longer but instead a size where both axes have been
constrained based off the max-min values of the opposite axes.
        
Move the constraining code out of RenderReplaced::computeIntrinsicRatioInformation into this
function so that the SVG code path appies the constraints as well. The movement of this code
is what fixes the bug.

(WebCore::RenderReplaced::computeIntrinsicRatioInformation):
Changed to remove the code that constrains the returned size, since it is shifting to
computeAspectRatioInformationForRenderBox instead.

(WebCore::RenderReplaced::computeReplacedLogicalWidth):
(WebCore::RenderReplaced::computeReplacedLogicalHeight):
* rendering/RenderReplaced.h:
(RenderReplaced):
Patch the name of the reference passed in to computeReplacedLogicalWidth/Height to be
constrainedSize instead of intrinsicSize, so that it is more obvious that the returned
result is not just the intrinsic size of the image.

LayoutTests: 

Reviewed by Dan Bernstein.

* svg/as-image/svg-intrinsic-size-expected.html: Added.
* svg/as-image/svg-intrinsic-size.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (123170 => 123171)


--- trunk/LayoutTests/ChangeLog	2012-07-20 03:57:56 UTC (rev 123170)
+++ trunk/LayoutTests/ChangeLog	2012-07-20 03:59:03 UTC (rev 123171)
@@ -1,3 +1,13 @@
+2012-07-19  David Hyatt  <[email protected]>
+
+        SVG images broken when max-width specified.
+        https://bugs.webkit.org/show_bug.cgi?id=91474
+
+        Reviewed by Dan Bernstein.
+
+        * svg/as-image/svg-intrinsic-size-expected.html: Added.
+        * svg/as-image/svg-intrinsic-size.html: Added.
+
 2012-07-19  Julien Chaffraix  <[email protected]>
 
         [CSS2.1] Anonymous tables should be inline/block-level based off their parent

Added: trunk/LayoutTests/svg/as-image/svg-intrinsic-size-expected.html (0 => 123171)


--- trunk/LayoutTests/svg/as-image/svg-intrinsic-size-expected.html	                        (rev 0)
+++ trunk/LayoutTests/svg/as-image/svg-intrinsic-size-expected.html	2012-07-20 03:59:03 UTC (rev 123171)
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<div style="position: absolute; top: 10px; left: 10px; width: 200px; height: 400px; outline: 1px solid blue;">
+    <img style="background-color: yellow; width: auto; height: auto; max-width: 100%; max-height: 100%;" src=""
+</div>
+
+<div style="position: absolute; top: 10px; left: 250px; width: 200px; height: 400px; outline: 1px solid blue;">
+    <img id="target" style="background-color: yellow; width: auto; height: auto; max-width: 100%; max-height: 100%;" src=""
+</div>

Added: trunk/LayoutTests/svg/as-image/svg-intrinsic-size.html (0 => 123171)


--- trunk/LayoutTests/svg/as-image/svg-intrinsic-size.html	                        (rev 0)
+++ trunk/LayoutTests/svg/as-image/svg-intrinsic-size.html	2012-07-20 03:59:03 UTC (rev 123171)
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<div style="position: absolute; top: 10px; left: 10px; width: 200px; height: 400px; outline: 1px solid blue;">
+    <img style="background-color: yellow; width: auto; height: auto; max-width: 100%; max-height: 100%;" src="" width='300' height='300' xmlns='http://www.w3.org/2000/svg'><rect x='0' y='0' width='300' height='300'></rect></svg>">
+</div>
+
+<div style="position: absolute; top: 10px; left: 250px; width: 200px; height: 400px; outline: 1px solid blue;">
+    <img id="target" style="background-color: yellow; width: auto; height: auto; max-width: 100%; max-height: 100%;" src=""
+</div>

Modified: trunk/Source/WebCore/ChangeLog (123170 => 123171)


--- trunk/Source/WebCore/ChangeLog	2012-07-20 03:57:56 UTC (rev 123170)
+++ trunk/Source/WebCore/ChangeLog	2012-07-20 03:59:03 UTC (rev 123171)
@@ -1,3 +1,45 @@
+2012-07-19  David Hyatt  <[email protected]>
+
+        SVG images broken when max-width specified.
+        https://bugs.webkit.org/show_bug.cgi?id=91474
+
+        SVG images were computing intrinsic dimensions when width and height were auto that did not
+        respect min-max width/height. Normal images had code that applied these constraints properly.
+        Looking at the code before the check-in that broke things, these constraints used to be
+        applied to all images regardless of type via calcAspectRatioLogicalWidth/Height.
+        
+        This patch leaves the new function structure in place but converts the code to be more like
+        it was prior to the introduction of the regression. Instead of raw intrinsic sizes being
+        used in the SVG case, now all image types get the intrinsic sizes constrained when doing
+        width/height computations.
+
+        Reviewed by Dan Bernstein.
+
+        Test: svg/as-image/svg-intrinsic-size.html
+
+        * rendering/RenderReplaced.cpp:
+        (WebCore::RenderReplaced::computeAspectRatioInformationForRenderBox):
+        Rename computeIntrinsicRatioInformationForRenderBox to computeAspectRatioInformationForRenderBox.
+        Also rename the intrinsicSize reference to constrainedSize to reflect the fact that the size
+        is not necessarily the intrinsic size any longer but instead a size where both axes have been
+        constrained based off the max-min values of the opposite axes.
+        
+        Move the constraining code out of RenderReplaced::computeIntrinsicRatioInformation into this
+        function so that the SVG code path appies the constraints as well. The movement of this code
+        is what fixes the bug.
+
+        (WebCore::RenderReplaced::computeIntrinsicRatioInformation):
+        Changed to remove the code that constrains the returned size, since it is shifting to
+        computeAspectRatioInformationForRenderBox instead.
+
+        (WebCore::RenderReplaced::computeReplacedLogicalWidth):
+        (WebCore::RenderReplaced::computeReplacedLogicalHeight):
+        * rendering/RenderReplaced.h:
+        (RenderReplaced):
+        Patch the name of the reference passed in to computeReplacedLogicalWidth/Height to be
+        constrainedSize instead of intrinsicSize, so that it is more obvious that the returned
+        result is not just the intrinsic size of the image.
+
 2012-07-19  Dmitry Titov  <[email protected]>
 
         Unreviewed, reverting http://trac.webkit.org/changeset/123149.

Modified: trunk/Source/WebCore/rendering/RenderReplaced.cpp (123170 => 123171)


--- trunk/Source/WebCore/rendering/RenderReplaced.cpp	2012-07-20 03:57:56 UTC (rev 123170)
+++ trunk/Source/WebCore/rendering/RenderReplaced.cpp	2012-07-20 03:59:03 UTC (rev 123171)
@@ -269,8 +269,9 @@
     return renderer->isImage() || renderer->isCanvas() || renderer->isVideo();
 }
 
-void RenderReplaced::computeIntrinsicRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& constrainedSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
 {
+    FloatSize intrinsicSize;
     if (contentRenderer) {
         contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
         if (intrinsicRatio)
@@ -285,11 +286,25 @@
 
         if (rendererHasAspectRatio(this) && isPercentageIntrinsicSize)
             intrinsicRatio = 1;
-        return;
+    } else {
+        computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+        if (intrinsicRatio)
+            ASSERT(!isPercentageIntrinsicSize);
     }
-    computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
-    if (intrinsicRatio)
-        ASSERT(!isPercentageIntrinsicSize);
+
+    // Now constrain the intrinsic size along each axis according to minimum and maximum width/heights along the
+    // opposite axis. So for example a maximum width that shrinks our width will result in the height we compute here
+    // having to shrink in order to preserve the aspect ratio. Because we compute these values independently along
+    // each axis, the final returned size may in fact not preserve the aspect ratio.
+    // FIXME: In the long term, it might be better to just return this code more to the way it used to be before this
+    // function was added, since all it has done is make the code more unclear.
+    constrainedSize = intrinsicSize;
+    if (intrinsicRatio && !intrinsicSize.isEmpty() && style()->logicalWidth().isAuto() && style()->logicalHeight().isAuto()) {
+        // We can't multiply or divide by 'intrinsicRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which
+        // can only be fixed once subpixel precision is available for things like intrinsicWidth/Height - which include zoom!
+        constrainedSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicSize.width() / intrinsicSize.height());
+        constrainedSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicSize.width() / intrinsicSize.height());
+    }
 }
 
 void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
@@ -304,12 +319,6 @@
         return;
 
     intrinsicRatio = intrinsicSize.width() / intrinsicSize.height();
-    if (style()->logicalWidth().isAuto() && style()->logicalHeight().isAuto()) {
-        // We can't multiply or divide by 'intrinsicRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which
-        // can only be fixed once subpixel precision is available for things like intrinsicWidth/Height - which include zoom!
-        intrinsicSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicLogicalWidth() / intrinsicLogicalHeight());
-        intrinsicSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicLogicalHeight() / intrinsicLogicalWidth());
-    }
 }
 
 LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) const
@@ -322,19 +331,19 @@
     // 10.3.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
     bool isPercentageIntrinsicSize = false;
     double intrinsicRatio = 0;
-    FloatSize intrinsicSize;
-    computeIntrinsicRatioInformationForRenderBox(contentRenderer, intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+    FloatSize constrainedSize;
+    computeAspectRatioInformationForRenderBox(contentRenderer, constrainedSize, intrinsicRatio, isPercentageIntrinsicSize);
 
     // FIXME: Remove unnecessary round/roundToInt calls from this method when layout is off ints: webkit.org/b/63656
     if (style()->logicalWidth().isAuto()) {
         bool heightIsAuto = style()->logicalHeight().isAuto();
-        bool hasIntrinsicWidth = !isPercentageIntrinsicSize && intrinsicSize.width() > 0;
+        bool hasIntrinsicWidth = !isPercentageIntrinsicSize && constrainedSize.width() > 0;
 
         // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'.
         if (heightIsAuto && hasIntrinsicWidth)
-            return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(intrinsicSize.width()), includeMaxWidth);
+            return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(constrainedSize.width()), includeMaxWidth);
 
-        bool hasIntrinsicHeight = !isPercentageIntrinsicSize && intrinsicSize.height() > 0;
+        bool hasIntrinsicHeight = !isPercentageIntrinsicSize && constrainedSize.height() > 0;
         if (intrinsicRatio || isPercentageIntrinsicSize) {
             // If 'height' and 'width' both have computed values of 'auto' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio;
             // or if 'width' has a computed value of 'auto', 'height' has some other computed value, and the element does have an intrinsic ratio; then the used value
@@ -361,14 +370,14 @@
                 LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), logicalWidth);
                 logicalWidth = max(ZERO_LAYOUT_UNIT, logicalWidth - (marginStart + marginEnd + (width() - clientWidth())));
                 if (isPercentageIntrinsicSize)
-                    logicalWidth = roundToInt(logicalWidth * intrinsicSize.width() / 100);
+                    logicalWidth = roundToInt(logicalWidth * constrainedSize.width() / 100);
                 return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth, includeMaxWidth);
             }
         }
 
         // Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'.
         if (hasIntrinsicWidth)
-            return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(intrinsicSize.width()), includeMaxWidth);
+            return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(constrainedSize.width()), includeMaxWidth);
 
         // Otherwise, if 'width' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'width' becomes 300px. If 300px is too
         // wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead.
@@ -391,16 +400,16 @@
     // 10.6.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
     bool isPercentageIntrinsicSize = false;
     double intrinsicRatio = 0;
-    FloatSize intrinsicSize;
-    computeIntrinsicRatioInformationForRenderBox(contentRenderer, intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+    FloatSize constrainedSize;
+    computeAspectRatioInformationForRenderBox(contentRenderer, constrainedSize, intrinsicRatio, isPercentageIntrinsicSize);
 
     // FIXME: Remove unnecessary round/roundToInt calls from this method when layout is off ints: webkit.org/b/63656
     bool widthIsAuto = style()->logicalWidth().isAuto();
-    bool hasIntrinsicHeight = !isPercentageIntrinsicSize && intrinsicSize.height() > 0;
+    bool hasIntrinsicHeight = !isPercentageIntrinsicSize && constrainedSize.height() > 0;
 
     // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic height, then that intrinsic height is the used value of 'height'.
     if (widthIsAuto && hasIntrinsicHeight)
-        return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(intrinsicSize.height()));
+        return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(constrainedSize.height()));
 
     // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic ratio then the used value of 'height' is:
     // (used width) / (intrinsic ratio)
@@ -409,7 +418,7 @@
 
     // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic height, then that intrinsic height is the used value of 'height'.
     if (hasIntrinsicHeight)
-        return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(intrinsicSize.height()));
+        return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(constrainedSize.height()));
 
     // Otherwise, if 'height' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'height' must be set to the height
     // of the largest rectangle that has a 2:1 ratio, has a height not greater than 150px, and has a width not greater than the device width.

Modified: trunk/Source/WebCore/rendering/RenderReplaced.h (123170 => 123171)


--- trunk/Source/WebCore/rendering/RenderReplaced.h	2012-07-20 03:57:56 UTC (rev 123170)
+++ trunk/Source/WebCore/rendering/RenderReplaced.h	2012-07-20 03:59:03 UTC (rev 123171)
@@ -77,7 +77,7 @@
     virtual bool canBeSelectionLeaf() const { return true; }
 
     virtual LayoutRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
-    void computeIntrinsicRatioInformationForRenderBox(RenderBox*, FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+    void computeAspectRatioInformationForRenderBox(RenderBox*, FloatSize& constrainedSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
 
     IntSize m_intrinsicSize;
 };
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to