Changeset 112229 in webkit


Ignore:
Timestamp:
Mar 27, 2012 2:24:46 AM (12 years ago)
Author:
Nikolas Zimmermann
Message:

<img style='width: 100%' src='foo.svg'> gets pixellated when stretched
https://bugs.webkit.org/show_bug.cgi?id=81631

Reviewed by Antti Koivisto.

Source/WebCore:

Final cleanup of RenderReplaced after the intrinsic size negotiation patch series from some weeks/months ago.
Stop tracking whether a RenderReplaced has an intrinsic size or not with an extra-bool, instead assume each
RenderReplaced derived class has an intrinsic size. If not, the class should override
computeIntrinsicRatioInformation() for any custom logic - currently only done by RenderImage.

Remove all logic depending on m_hasIntrinsicSize from computeReplacedLogicalWidth/Height, which was used
to support different sizing models depending on if the replaced element is a RenderImage or a RenderPart.
Unify all of this in computeIntrinsicRatioInformation right in RenderReplaced. This allows to remove
a hack from RenderImage::computeReplacedLogicalWidth(), which forced the synchroniziation of the intrinsicSize()
before calling the base classes RenderReplaced::computeReplacedLogicalWidth().
Now RenderImage just overrides the layout() method, calls RenderReplaced::layout() and then sets the container
size of the image resources to [contentWidth(), contentHeight()] - reflecting the actual result of the layout.
Furthermore this now allows us to unify CachedImage::imageSizeForRenderer() again for both SVG and non-SVG images.

Propagating the right container size to the image resource fixes the actual bug, that the SVGImage got pixellated.
Adding new tests covering percentage width or height set on an <img> embedding an external SVG, no more pixelation.

Tests: svg/as-image/img-relative-height-expected.html

svg/as-image/img-relative-height.html
svg/as-image/img-relative-width-expected.html
svg/as-image/img-relative-width.html

  • loader/cache/CachedImage.cpp:

(WebCore::CachedImage::imageSizeForRenderer):

  • rendering/RenderEmbeddedObject.cpp:

(WebCore::RenderEmbeddedObject::RenderEmbeddedObject):

  • rendering/RenderImage.cpp:

(WebCore::RenderImage::layout):
(WebCore::RenderImage::computeIntrinsicRatioInformation):

  • rendering/RenderImage.h:

(RenderImage):

  • rendering/RenderReplaced.cpp:

(WebCore::RenderReplaced::RenderReplaced):
(WebCore::rendererHasAspectRatio):
(WebCore):
(WebCore::RenderReplaced::computeIntrinsicRatioInformationForRenderBox):
(WebCore::RenderReplaced::computeIntrinsicRatioInformation):
(WebCore::RenderReplaced::computeReplacedLogicalWidth):
(WebCore::RenderReplaced::computeReplacedLogicalHeight):

  • rendering/RenderReplaced.h:

(WebCore::RenderReplaced::intrinsicSize):
(RenderReplaced):
(WebCore::RenderReplaced::setIntrinsicSize):

  • svg/graphics/SVGImage.cpp:

(WebCore::SVGImage::setContainerSize):

  • svg/graphics/SVGImage.h:

(WebCore::SVGImage::usesContainerSize):

LayoutTests:

Add new tests covering setting only one of width/height to a percentage when embedding SVGs into <img>s.

  • platform/chromium/test_expectations.txt: Update expectations.
  • platform/mac/fast/repaint/block-layout-inline-children-replaced-expected.txt: Update changed result - slight rounding difference.
  • platform/mac/fast/table/quote-text-around-iframe-expected.png: Update changed result, now the default intrinsic size respects scaling.
  • platform/mac/fast/table/quote-text-around-iframe-expected.txt: Ditto.
  • svg/as-image/img-relative-height-expected.html: Added.
  • svg/as-image/img-relative-height.html: Added.
  • svg/as-image/img-relative-width-expected.html: Added.
  • svg/as-image/img-relative-width.html: Added.
  • svg/as-image/resources/island.svg: Added.
  • svg/as-image/svg-non-integer-scaled-image-expected.png:
  • svg/as-image/svg-non-integer-scaled-image-expected.txt:
Location:
trunk
Files:
5 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r112228 r112229  
     12012-03-27  Nikolas Zimmermann  <nzimmermann@rim.com>
     2
     3        <img style='width: 100%' src='foo.svg'> gets pixellated when stretched
     4        https://bugs.webkit.org/show_bug.cgi?id=81631
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Add new tests covering setting only one of width/height to a percentage when embedding SVGs into <img>s.
     9
     10        * platform/chromium/test_expectations.txt: Update expectations.
     11        * platform/mac/fast/repaint/block-layout-inline-children-replaced-expected.txt: Update changed result - slight rounding difference.
     12        * platform/mac/fast/table/quote-text-around-iframe-expected.png: Update changed result, now the default intrinsic size respects scaling.
     13        * platform/mac/fast/table/quote-text-around-iframe-expected.txt: Ditto.
     14        * svg/as-image/img-relative-height-expected.html: Added.
     15        * svg/as-image/img-relative-height.html: Added.
     16        * svg/as-image/img-relative-width-expected.html: Added.
     17        * svg/as-image/img-relative-width.html: Added.
     18        * svg/as-image/resources/island.svg: Added.
     19        * svg/as-image/svg-non-integer-scaled-image-expected.png:
     20        * svg/as-image/svg-non-integer-scaled-image-expected.txt:
     21
    1222012-03-27  Philippe Normand  <pnormand@igalia.com>
    223
  • trunk/LayoutTests/platform/chromium/test_expectations.txt

    r112212 r112229  
    36533653
    36543654BUGWK73494 : svg/text/non-bmp-positioning-lists.svg = IMAGE+TEXT IMAGE
    3655 BUGWK73494 : svg/as-image/svg-non-integer-scaled-image.html = IMAGE PASS
     3655// BUGWK73494 : svg/as-image/svg-non-integer-scaled-image.html = IMAGE PASS
    36563656
    36573657BUGWK73872 LINUX : svg/custom/linking-uri-01-b.svg = PASS TIMEOUT
     
    41324132
    41334133// Needs rebaseline due to a progression
    4134 BUGWK43022 WIN : tables/mozilla_expected_failures/bugs/bug85016.html = IMAGE
    4135 BUGWK43022 MAC : tables/mozilla_expected_failures/bugs/bug85016.html = IMAGE+TEXT
     4134// BUGWK43022 WIN : tables/mozilla_expected_failures/bugs/bug85016.html = IMAGE
     4135// BUGWK43022 MAC : tables/mozilla_expected_failures/bugs/bug85016.html = IMAGE+TEXT
    41364136
    41374137// flaky tests
     
    42064206// New test, flaky since added in r110965.
    42074207BUGWK82097 : editing/selection/move-by-word-visually-crash-test-5.html = PASS TIMEOUT
     4208
     4209// Just needs a rebaseline. The iframe size is now 600x300, before it was 300x150 - as we properly zoom the default intrinsic size now.
     4210BUGWK81631 : fast/table/quote-text-around-iframe.html = IMAGE IMAGE+TEXT PASS
     4211// Size should be 100 now, instead of 101 - if so, only needs a rebaseline.
     4212BUGWK81631 : svg/as-image/svg-non-integer-scaled-image.html  = IMAGE IMAGE+TEXT PASS
     4213// Size changed from 93 to 92 due rounding, just needs a rebaseline.
     4214BUGWK81631 : fast/repaint/block-layout-inline-children-replaced.html = IMAGE IMAGE+TEXT PASS
     4215// Just needs a rebaseline, no visible changes.
     4216BUGWK81631 : fast/writing-mode/block-level-images.html = IMAGE IMAGE+TEXT PASS
     4217// Slight change in image size due to rounding - just needs a rebaseline.
     4218BUGWK81631 : tables/mozilla_expected_failures/bugs/bug85016.html = IMAGE IMAGE+TEXT PASS
    42084219
    42094220// Temporary: generate platform specific IETestCenter results, then
  • trunk/LayoutTests/platform/mac/fast/repaint/block-layout-inline-children-replaced-expected.txt

    r98852 r112229  
    1212      RenderBlock {DIV} at (0,34) size 800x152
    1313        RenderBlock {DIV} at (0,0) size 402x152 [border: (1px solid #DDDDDD)]
    14           RenderImage {IMG} at (155,1) size 93x100
     14          RenderImage {IMG} at (155,1) size 92x100
  • trunk/LayoutTests/platform/mac/fast/table/quote-text-around-iframe-expected.txt

    r95671 r112229  
    11layer at (0,0) size 800x600
    22  RenderView at (0,0) size 800x600
    3 layer at (0,0) size 800x198
    4   RenderBlock {HTML} at (0,0) size 800x198
    5     RenderBody {BODY} at (16,16) size 768x166
    6       RenderTable at (0,0) size 394x166
    7         RenderTableSection (anonymous) at (0,0) size 394x166
    8           RenderTableRow {Q} at (0,0) size 394x166
    9             RenderTableCell (anonymous) at (0,0) size 394x166 [r=0 c=0 rs=1 cs=1]
     3layer at (0,0) size 800x348
     4  RenderBlock {HTML} at (0,0) size 800x348
     5    RenderBody {BODY} at (16,16) size 768x316
     6      RenderTable at (0,0) size 694x316
     7        RenderTableSection (anonymous) at (0,0) size 694x316
     8          RenderTableRow {Q} at (0,0) size 694x316
     9            RenderTableCell (anonymous) at (0,0) size 694x316 [r=0 c=0 rs=1 cs=1]
    1010              RenderInline (generated) at (0,0) size 13x37
    11                 RenderQuote at (0,129) size 13x37
    12                   text run at (0,129) width 13: "\""
    13               RenderText {#text} at (13,129) size 31x37
    14                 text run at (13,129) width 31: " A"
    15               RenderPartObject {IFRAME} at (44,0) size 308x158 [border: (4px inset #000000)]
    16                 layer at (0,0) size 300x150
    17                   RenderView at (0,0) size 300x150
    18                 layer at (0,0) size 300x150
    19                   RenderBlock {HTML} at (0,0) size 300x150
    20                     RenderBody {BODY} at (8,8) size 284x134
    21               RenderText {#text} at (352,129) size 29x37
    22                 text run at (352,129) width 29: "B "
     11                RenderQuote at (0,279) size 13x37
     12                  text run at (0,279) width 13: "\""
     13              RenderText {#text} at (13,279) size 31x37
     14                text run at (13,279) width 31: " A"
     15              RenderPartObject {IFRAME} at (44,0) size 608x308 [border: (4px inset #000000)]
     16                layer at (0,0) size 600x300
     17                  RenderView at (0,0) size 600x300
     18                layer at (0,0) size 600x300
     19                  RenderBlock {HTML} at (0,0) size 600x300
     20                    RenderBody {BODY} at (8,8) size 584x284
     21              RenderText {#text} at (652,279) size 29x37
     22                text run at (652,279) width 29: "B "
    2323              RenderInline (generated) at (0,0) size 13x37
    24                 RenderQuote at (381,129) size 13x37
    25                   text run at (381,129) width 13: "\""
     24                RenderQuote at (681,279) size 13x37
     25                  text run at (681,279) width 13: "\""
  • trunk/LayoutTests/svg/as-image/svg-non-integer-scaled-image-expected.txt

    r100778 r112229  
    44  RenderBlock {HTML} at (0,0) size 800x600
    55    RenderBody {BODY} at (0,0) size 800x600
    6       RenderImage {IMG} at (0,0) size 100x101
     6      RenderImage {IMG} at (0,0) size 100x100
    77      RenderText {#text} at (0,0) size 0x0
  • trunk/Source/WebCore/ChangeLog

    r112225 r112229  
     12012-03-27  Nikolas Zimmermann  <nzimmermann@rim.com>
     2
     3        <img style='width: 100%' src='foo.svg'> gets pixellated when stretched
     4        https://bugs.webkit.org/show_bug.cgi?id=81631
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Final cleanup of RenderReplaced after the intrinsic size negotiation patch series from some weeks/months ago.
     9        Stop tracking whether a RenderReplaced has an intrinsic size or not with an extra-bool, instead assume each
     10        RenderReplaced derived class has an intrinsic size. If not, the class should override
     11        computeIntrinsicRatioInformation() for any custom logic - currently only done by RenderImage.
     12
     13        Remove all logic depending on m_hasIntrinsicSize from computeReplacedLogicalWidth/Height, which was used
     14        to support different sizing models depending on if the replaced element is a RenderImage or a RenderPart.
     15        Unify all of this in computeIntrinsicRatioInformation right in RenderReplaced. This allows to remove
     16        a hack from RenderImage::computeReplacedLogicalWidth(), which forced the synchroniziation of the intrinsicSize()
     17        before calling the base classes RenderReplaced::computeReplacedLogicalWidth().
     18        Now RenderImage just overrides the layout() method, calls RenderReplaced::layout() and then sets the container
     19        size of the image resources to [contentWidth(), contentHeight()] - reflecting the actual result of the layout.
     20        Furthermore this now allows us to unify CachedImage::imageSizeForRenderer() again for both SVG and non-SVG images.
     21
     22        Propagating the right container size to the image resource fixes the actual bug, that the SVGImage got pixellated.
     23        Adding new tests covering percentage width or height set on an <img> embedding an external SVG, no more pixelation.
     24
     25        Tests: svg/as-image/img-relative-height-expected.html
     26               svg/as-image/img-relative-height.html
     27               svg/as-image/img-relative-width-expected.html
     28               svg/as-image/img-relative-width.html
     29
     30        * loader/cache/CachedImage.cpp:
     31        (WebCore::CachedImage::imageSizeForRenderer):
     32        * rendering/RenderEmbeddedObject.cpp:
     33        (WebCore::RenderEmbeddedObject::RenderEmbeddedObject):
     34        * rendering/RenderImage.cpp:
     35        (WebCore::RenderImage::layout):
     36        (WebCore::RenderImage::computeIntrinsicRatioInformation):
     37        * rendering/RenderImage.h:
     38        (RenderImage):
     39        * rendering/RenderReplaced.cpp:
     40        (WebCore::RenderReplaced::RenderReplaced):
     41        (WebCore::rendererHasAspectRatio):
     42        (WebCore):
     43        (WebCore::RenderReplaced::computeIntrinsicRatioInformationForRenderBox):
     44        (WebCore::RenderReplaced::computeIntrinsicRatioInformation):
     45        (WebCore::RenderReplaced::computeReplacedLogicalWidth):
     46        (WebCore::RenderReplaced::computeReplacedLogicalHeight):
     47        * rendering/RenderReplaced.h:
     48        (WebCore::RenderReplaced::intrinsicSize):
     49        (RenderReplaced):
     50        (WebCore::RenderReplaced::setIntrinsicSize):
     51        * svg/graphics/SVGImage.cpp:
     52        (WebCore::SVGImage::setContainerSize):
     53        * svg/graphics/SVGImage.h:
     54        (WebCore::SVGImage::usesContainerSize):
     55
    1562012-03-27  Ilya Tikhonovsky  <loislo@chromium.org>
    257
  • trunk/Source/WebCore/loader/cache/CachedImage.cpp

    r112201 r112229  
    241241    if (!m_image)
    242242        return IntSize();
     243
     244    IntSize imageSize = m_image->size();
     245
    243246#if ENABLE(SVG)
    244247    if (m_image->isSVGImage()) {
    245         // SVGImages already includes the zooming in its intrinsic size.
    246248        SVGImageCache::SizeAndZoom sizeAndZoom = m_svgImageCache->requestedSizeAndZoom(renderer);
    247         if (sizeAndZoom.size.isEmpty())
    248             return m_image->size();
    249         if (sizeAndZoom.zoom == 1)
    250             return sizeAndZoom.size;
    251         if (multiplier == 1) {
    252             // Consumer wants unscaled coordinates.
    253             sizeAndZoom.size.setWidth(sizeAndZoom.size.width() / sizeAndZoom.zoom);
    254             sizeAndZoom.size.setHeight(sizeAndZoom.size.height() / sizeAndZoom.zoom);
    255             return sizeAndZoom.size;
     249        if (!sizeAndZoom.size.isEmpty()) {
     250            imageSize.setWidth(sizeAndZoom.size.width() / sizeAndZoom.zoom);
     251            imageSize.setHeight(sizeAndZoom.size.height() / sizeAndZoom.zoom);
    256252        }
    257         return sizeAndZoom.size;
    258253    }
    259254#else
     
    262257
    263258    if (multiplier == 1.0f)
    264         return m_image->size();
     259        return imageSize;
    265260       
    266261    // Don't let images that have a width/height >= 1 shrink below 1 when zoomed.
    267     bool hasWidth = m_image->size().width() > 0;
    268     bool hasHeight = m_image->size().height() > 0;
    269     int width = m_image->size().width() * (m_image->hasRelativeWidth() ? 1.0f : multiplier);
    270     int height = m_image->size().height() * (m_image->hasRelativeHeight() ? 1.0f : multiplier);
     262    bool hasWidth = imageSize.width() > 0;
     263    bool hasHeight = imageSize.height() > 0;
     264    int width = imageSize.width() * (m_image->hasRelativeWidth() ? 1.0f : multiplier);
     265    int height = imageSize.height() * (m_image->hasRelativeHeight() ? 1.0f : multiplier);
    271266    if (hasWidth)
    272267        width = max(1, width);
  • trunk/Source/WebCore/rendering/RenderEmbeddedObject.cpp

    r109273 r112229  
    5454#include "TextRun.h"
    5555
    56 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
    57 #include "HTMLVideoElement.h"
    58 #endif
    59 
    6056namespace WebCore {
    6157
     
    8480{
    8581    view()->frameView()->setIsVisuallyNonEmpty();
    86 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
    87     if (element->hasTagName(videoTag) || element->hasTagName(audioTag))
    88         setHasIntrinsicSize();
    89 #endif
    9082}
    9183
  • trunk/Source/WebCore/rendering/RenderImage.cpp

    r111515 r112229  
    77 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
    88 * Copyright (C) 2010 Google Inc. All rights reserved.
     9 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
    910 *
    1011 * This library is free software; you can redistribute it and/or
     
    504505}
    505506
    506 LayoutUnit RenderImage::computeReplacedLogicalWidth(bool includeMaxWidth) const
    507 {
    508     // If we've got an explicit width/height assigned, propagate it to the image resource.
    509     if (style()->logicalWidth().isSpecified() && style()->logicalHeight().isSpecified()) {
    510         LayoutUnit width = RenderReplaced::computeReplacedLogicalWidth(includeMaxWidth);
    511         m_imageResource->setContainerSizeForRenderer(IntSize(width, computeReplacedLogicalHeight()));
    512         return width;
    513     }
    514 
    515     IntSize containerSize;
    516     if (m_imageResource->imageHasRelativeWidth() || m_imageResource->imageHasRelativeHeight()) {
    517         // Propagate the containing block size to the image resource, otherwhise we can't compute our own intrinsic size, if it's relative.
     507void RenderImage::layout()
     508{
     509    RenderReplaced::layout();
     510
     511    // Propagate container size to image resource.
     512    IntSize containerSize(contentWidth(), contentHeight());
     513    if (!containerSize.isEmpty())
     514        m_imageResource->setContainerSizeForRenderer(containerSize);
     515}
     516
     517void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
     518{
     519    RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
     520
     521    // Our intrinsicSize is empty if we're rendering generated images with relative width/height. Figure out the right intrinsic size to use.
     522    if (intrinsicSize.isEmpty() && (m_imageResource->imageHasRelativeWidth() || m_imageResource->imageHasRelativeHeight())) {
    518523        RenderObject* containingBlock = isPositioned() ? container() : this->containingBlock();
    519524        if (containingBlock->isBox()) {
    520525            RenderBox* box = toRenderBox(containingBlock);
    521             containerSize = IntSize(box->availableWidth(), box->availableHeight()); // Already contains zooming information.
    522         }
    523     } else {
    524         // Propagate the current zoomed image size to the image resource, otherwhise the image size will remain the same on-screen.
    525         CachedImage* cachedImage = m_imageResource->cachedImage();
    526         if (cachedImage && cachedImage->image()) {
    527             containerSize = cachedImage->image()->size();
    528             // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
    529             containerSize.setWidth(roundToInt(containerSize.width() * style()->effectiveZoom()));
    530             containerSize.setHeight(roundToInt(containerSize.height() * style()->effectiveZoom()));
    531         }
    532     }
    533 
    534     if (!containerSize.isEmpty()) {
    535         m_imageResource->setContainerSizeForRenderer(containerSize);
    536         const_cast<RenderImage*>(this)->updateIntrinsicSizeIfNeeded(containerSize, false);
    537     }
    538 
    539     return RenderReplaced::computeReplacedLogicalWidth(includeMaxWidth);
    540 }
    541 
    542 void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
    543 {
    544     // Assure this method is never used for SVGImages.
    545     ASSERT(!embeddedContentBox());
    546     isPercentageIntrinsicSize = false;
    547     CachedImage* cachedImage = m_imageResource ? m_imageResource->cachedImage() : 0;
    548     if (!cachedImage || !cachedImage->image())
    549         return;
    550     intrinsicSize = cachedImage->image()->size();
    551     intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
     526            intrinsicSize.setWidth(box->availableLogicalWidth());
     527            intrinsicSize.setHeight(box->availableLogicalHeight());
     528        }
     529    }
     530    // Don't compute an intrinsic ratio to preserve historical WebKit behavior if we're painting alt text and/or a broken image.
     531    if (m_imageResource && m_imageResource->errorOccurred()) {
     532        intrinsicRatio = 1;
     533        return;
     534    }
    552535}
    553536
  • trunk/Source/WebCore/rendering/RenderImage.h

    r111515 r112229  
    6969    virtual void paintIntoRect(GraphicsContext*, const LayoutRect&);
    7070    virtual void paint(PaintInfo&, const LayoutPoint&);
     71    virtual void layout();
    7172
    7273    virtual void intrinsicSizeChanged()
     
    9091    virtual void notifyFinished(CachedResource*);
    9192    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
    92 
    93     virtual LayoutUnit computeReplacedLogicalWidth(bool includeMaxWidth = true) const;
    9493
    9594    IntSize imageSizeForError(CachedImage*) const;
  • trunk/Source/WebCore/rendering/RenderReplaced.cpp

    r112198 r112229  
    33 * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
    44 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
     5 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
    56 *
    67 * This library is free software; you can redistribute it and/or
     
    4445    : RenderBox(node)
    4546    , m_intrinsicSize(cDefaultWidth, cDefaultHeight)
    46     , m_hasIntrinsicSize(false)
    4747{
    4848    setReplaced(true);
     
    5252    : RenderBox(node)
    5353    , m_intrinsicSize(intrinsicSize)
    54     , m_hasIntrinsicSize(true)
    5554{
    5655    setReplaced(true);
     
    203202}
    204203
    205 int RenderReplaced::computeIntrinsicLogicalWidth(RenderBox* contentRenderer, bool includeMaxWidth) const
    206 {
    207     if (m_hasIntrinsicSize)
    208         return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
    209     ASSERT(contentRenderer);
    210     ASSERT(contentRenderer->style());
    211     return contentRenderer->computeReplacedLogicalWidthRespectingMinMaxWidth(contentRenderer->computeReplacedLogicalWidthUsing(contentRenderer->style()->logicalWidth()), includeMaxWidth);
    212 }
    213 
    214 int RenderReplaced::computeIntrinsicLogicalHeight(RenderBox* contentRenderer) const
    215 {
    216     if (m_hasIntrinsicSize)
    217         return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
    218     ASSERT(contentRenderer);
    219     ASSERT(contentRenderer->style());
    220     return contentRenderer->computeReplacedLogicalHeightRespectingMinMaxHeight(contentRenderer->computeReplacedLogicalHeightUsing(contentRenderer->style()->logicalHeight()));
    221 }
    222 
    223204static inline RenderBlock* firstContainingBlockWithLogicalWidth(const RenderReplaced* replaced)
    224205{
     
    283264}
    284265
     266static inline bool rendererHasAspectRatio(const RenderObject* renderer)
     267{
     268    ASSERT(renderer);
     269    return renderer->isImage() || renderer->isCanvas() || renderer->isVideo();
     270}
     271
     272void RenderReplaced::computeIntrinsicRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
     273{
     274    if (contentRenderer) {
     275        contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
     276        if (intrinsicRatio)
     277            ASSERT(!isPercentageIntrinsicSize);
     278
     279        // Handle zoom & vertical writing modes here, as the embedded document doesn't know about them.
     280        if (!isPercentageIntrinsicSize)
     281            intrinsicSize.scale(style()->effectiveZoom());
     282
     283        if (intrinsicRatio && !isHorizontalWritingMode())
     284            intrinsicRatio = 1 / intrinsicRatio;
     285
     286        if (rendererHasAspectRatio(this) && isPercentageIntrinsicSize)
     287            intrinsicRatio = 1;
     288        return;
     289    }
     290
     291    // This code path can't yield percentage intrinsic sizes, assert that.
     292    computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
     293    ASSERT(!isPercentageIntrinsicSize);
     294}
     295
     296void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
     297{
     298    // If there's an embeddedContentBox() of a remote, referenced document available, this code-path should never be used.
     299    ASSERT(!embeddedContentBox());
     300    isPercentageIntrinsicSize = false;
     301    intrinsicSize = FloatSize(intrinsicLogicalWidth(), intrinsicLogicalHeight());
     302
     303    // Figure out if we need to compute an intrinsic ratio.
     304    if (intrinsicSize.isEmpty() || !rendererHasAspectRatio(this))
     305        return;
     306
     307    intrinsicRatio = intrinsicSize.width() / intrinsicSize.height();
     308    if (style()->logicalWidth().isAuto() && style()->logicalHeight().isAuto()) {
     309        // We can't multiply or divide by 'intrinsicRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which
     310        // can only be fixed once subpixel precision is available for things like intrinsicWidth/Height - which include zoom!
     311        intrinsicSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicLogicalWidth() / intrinsicLogicalHeight());
     312        intrinsicSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicLogicalHeight() / intrinsicLogicalWidth());
     313    }
     314}
     315
    285316LayoutUnit RenderReplaced::computeReplacedLogicalWidth(bool includeMaxWidth) const
    286317{
     
    294325    double intrinsicRatio = 0;
    295326    FloatSize intrinsicSize;
    296     if (contentRenderer)
    297         contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
    298     else
    299         computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
    300 
    301     if (intrinsicRatio && !isHorizontalWritingMode())
    302         intrinsicRatio = 1 / intrinsicRatio;
    303 
     327    computeIntrinsicRatioInformationForRenderBox(contentRenderer, intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
     328
     329    // FIXME: Remove unnecessary round/roundToInt calls from this method when layout is off ints: webkit.org/b/63656
    304330    if (style()->logicalWidth().isAuto()) {
    305331        bool heightIsAuto = style()->logicalHeight().isAuto();
    306         bool hasIntrinsicWidth = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.width() > 0);
     332        bool hasIntrinsicWidth = !isPercentageIntrinsicSize && intrinsicSize.width() > 0;
    307333
    308334        // 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'.
    309         if (heightIsAuto && hasIntrinsicWidth) {
    310             if (m_hasIntrinsicSize)
    311                 return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
    312             return static_cast<LayoutUnit>(intrinsicSize.width() * style()->effectiveZoom());
    313         }
    314 
    315         bool hasIntrinsicHeight = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.height() > 0);
     335        if (heightIsAuto && hasIntrinsicWidth)
     336            return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(intrinsicSize.width()), includeMaxWidth);
     337
     338        bool hasIntrinsicHeight = !isPercentageIntrinsicSize && intrinsicSize.height() > 0;
    316339        if (intrinsicRatio || isPercentageIntrinsicSize) {
    317340            // 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;
     
    320343            if (intrinsicRatio && ((heightIsAuto && !hasIntrinsicWidth && hasIntrinsicHeight) || !heightIsAuto)) {
    321344                LayoutUnit logicalHeight = computeReplacedLogicalHeightUsing(style()->logicalHeight());
    322                 return computeReplacedLogicalWidthRespectingMinMaxWidth(static_cast<LayoutUnit>(ceil(logicalHeight * intrinsicRatio)));
     345                return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(round(logicalHeight * intrinsicRatio)));
    323346            }
    324347
     
    340363                logicalWidth = max(0, logicalWidth - (marginStart + marginEnd + (width() - clientWidth())));
    341364                if (isPercentageIntrinsicSize)
    342                     // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
    343                     logicalWidth = static_cast<LayoutUnit>(round(logicalWidth * intrinsicSize.width() / 100));
    344                 return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth);
     365                    logicalWidth = roundToInt(logicalWidth * intrinsicSize.width() / 100);
     366                return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth, includeMaxWidth);
    345367            }
    346368        }
    347369
    348370        // 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'.
    349         if (hasIntrinsicWidth) {
    350             if (isPercentageIntrinsicSize || m_hasIntrinsicSize)
    351                 return computeReplacedLogicalWidthRespectingMinMaxWidth(calcAspectRatioLogicalWidth(), includeMaxWidth);
    352             return static_cast<LayoutUnit>(intrinsicSize.width() * style()->effectiveZoom());
    353         }
     371        if (hasIntrinsicWidth)
     372            return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(intrinsicSize.width()), includeMaxWidth);
    354373
    355374        // 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
    356375        // 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.
    357         return computeReplacedLogicalWidthRespectingMinMaxWidth(cDefaultWidth, includeMaxWidth);
     376        // Note: We fall through and instead return intrinsicLogicalWidth() here - to preserve existing WebKit behavior, which might or might not be correct, or desired.
     377        // Changing this to return cDefaultWidth, will affect lots of test results. Eg. some tests assume that a blank <img> tag (which implies width/height=auto)
     378        // has no intrinsic size, which is wrong per CSS 2.1, but matches our behavior since a long time.
    358379    }
    359380
     
    373394    double intrinsicRatio = 0;
    374395    FloatSize intrinsicSize;
    375     if (contentRenderer)
    376         contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
    377     else
    378         computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
    379 
    380     if (intrinsicRatio && !isHorizontalWritingMode())
    381         intrinsicRatio = 1 / intrinsicRatio;
    382 
     396    computeIntrinsicRatioInformationForRenderBox(contentRenderer, intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
     397
     398    // FIXME: Remove unnecessary round/roundToInt calls from this method when layout is off ints: webkit.org/b/63656
    383399    bool widthIsAuto = style()->logicalWidth().isAuto();
    384     bool hasIntrinsicHeight = m_hasIntrinsicSize || (!isPercentageIntrinsicSize && intrinsicSize.height() > 0);
     400    bool hasIntrinsicHeight = !isPercentageIntrinsicSize && intrinsicSize.height() > 0;
    385401
    386402    // 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'.
    387     if (widthIsAuto && hasIntrinsicHeight) {
    388         if (m_hasIntrinsicSize)
    389             return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
    390         return static_cast<LayoutUnit>(intrinsicSize.height() * style()->effectiveZoom());
    391     }
     403    if (widthIsAuto && hasIntrinsicHeight)
     404        return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(intrinsicSize.height()));
    392405
    393406    // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic ratio then the used value of 'height' is:
    394407    // (used width) / (intrinsic ratio)
    395     if (intrinsicRatio && !isPercentageIntrinsicSize) {
    396         // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
    397         return computeReplacedLogicalHeightRespectingMinMaxHeight(round(availableLogicalWidth() / intrinsicRatio));
    398     }
     408    if (intrinsicRatio)
     409        return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(round(availableLogicalWidth() / intrinsicRatio)));
    399410
    400411    // 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'.
    401     if (hasIntrinsicHeight) {
    402         if (m_hasIntrinsicSize)
    403             return computeReplacedLogicalHeightRespectingMinMaxHeight(calcAspectRatioLogicalHeight());
    404         return static_cast<LayoutUnit>(intrinsicSize.height() * style()->effectiveZoom());
    405     }
     412    if (hasIntrinsicHeight)
     413        return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(intrinsicSize.height()));
    406414
    407415    // 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
    408416    // 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.
    409     return computeReplacedLogicalHeightRespectingMinMaxHeight(cDefaultHeight);
    410 }
    411 
    412 int RenderReplaced::calcAspectRatioLogicalWidth() const
    413 {
    414     int intrinsicWidth = intrinsicLogicalWidth();
    415     int intrinsicHeight = intrinsicLogicalHeight();
    416     if (!intrinsicHeight)
    417         return 0;
    418     return RenderBox::computeReplacedLogicalHeight() * intrinsicWidth / intrinsicHeight;
    419 }
    420 
    421 int RenderReplaced::calcAspectRatioLogicalHeight() const
    422 {
    423     int intrinsicWidth = intrinsicLogicalWidth();
    424     int intrinsicHeight = intrinsicLogicalHeight();
    425     if (!intrinsicWidth)
    426         return 0;
    427     return RenderBox::computeReplacedLogicalWidth() * intrinsicHeight / intrinsicWidth;
     417    return computeReplacedLogicalHeightRespectingMinMaxHeight(intrinsicLogicalHeight());
    428418}
    429419
     
    538528}
    539529
    540 IntSize RenderReplaced::intrinsicSize() const
    541 {
    542     return m_intrinsicSize;
    543 }
    544 
    545 void RenderReplaced::setIntrinsicSize(const IntSize& size)
    546 {
    547     ASSERT(m_hasIntrinsicSize);
    548     m_intrinsicSize = size;
    549 }
    550 
    551530LayoutRect RenderReplaced::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const
    552531{
  • trunk/Source/WebCore/rendering/RenderReplaced.h

    r112166 r112229  
    4444    virtual void layout();
    4545
    46     virtual IntSize intrinsicSize() const;
     46    virtual IntSize intrinsicSize() const { return m_intrinsicSize; }
     47    virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
    4748
    4849    virtual int minimumReplacedHeight() const { return 0; }
     
    5455    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
    5556
    56     void setIntrinsicSize(const IntSize&);
     57    void setIntrinsicSize(const IntSize& intrinsicSize) { m_intrinsicSize = intrinsicSize; }
    5758    virtual void intrinsicSizeChanged();
    58     void setHasIntrinsicSize() { m_hasIntrinsicSize = true; }
    5959
    6060    virtual void paint(PaintInfo&, const LayoutPoint&);
     
    6464private:
    6565    virtual RenderBox* embeddedContentBox() const { return 0; }
    66     int computeIntrinsicLogicalWidth(RenderBox* contentRenderer, bool includeMaxWidth) const;
    67     int computeIntrinsicLogicalHeight(RenderBox* contentRenderer) const;
    68 
    6966    virtual const char* renderName() const { return "RenderReplaced"; }
    7067
     
    7269
    7370    virtual void computePreferredLogicalWidths();
    74 
    75     int calcAspectRatioLogicalWidth() const;
    76     int calcAspectRatioLogicalHeight() const;
    77 
    7871    virtual void paintReplaced(PaintInfo&, const LayoutPoint&) { }
    7972
     
    8578
    8679    virtual LayoutRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
     80    void computeIntrinsicRatioInformationForRenderBox(RenderBox*, FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
    8781
    8882    IntSize m_intrinsicSize;
    89     bool m_hasIntrinsicSize;
    9083};
    9184
  • trunk/Source/WebCore/svg/graphics/SVGImage.cpp

    r111637 r112229  
    103103void SVGImage::setContainerSize(const IntSize&)
    104104{
     105    // SVGImageCache already intercepted this call, as it stores & caches the desired container sizes & zoom levels.
    105106    ASSERT_NOT_REACHED();
    106 }
    107 
    108 bool SVGImage::usesContainerSize() const
    109 {
    110     if (!m_page)
    111         return false;
    112     Frame* frame = m_page->mainFrame();
    113     SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement();
    114     if (!rootElement)
    115         return false;
    116     if (RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()))
    117         return !renderer->containerSize().isEmpty();
    118     return false;
    119107}
    120108
  • trunk/Source/WebCore/svg/graphics/SVGImage.h

    r111637 r112229  
    7070
    7171    virtual void setContainerSize(const IntSize&);
    72     virtual bool usesContainerSize() const;
     72    virtual bool usesContainerSize() const { return true; }
    7373    virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor = 1);
    7474
Note: See TracChangeset for help on using the changeset viewer.