Changeset 154858 in webkit


Ignore:
Timestamp:
Aug 29, 2013 5:23:23 PM (11 years ago)
Author:
Simon Fraser
Message:

Implement object-fit CSS property
https://bugs.webkit.org/show_bug.cgi?id=52040

Source/WebCore:

Reviewed by Antti Koivisto, Sam Weinig.

Merge object-fit patch from Blink r156535, which started as a patch
by me.

Since then, the spec has gone to CR. This patch is an
implementation of object-fit as described in
http://www.w3.org/TR/2012/CR-css3-images-20120417/#object-fit

Object-fit is used to maintain the aspect ratio of replaced content
within its content box. All object-fit values but the initial one
('fill') will always ensure that the aspect ratio is retained, in
different ways (fit inside the content box, cover the content box, or
use intrinsic size). Painting is always clipped against the content
box, regardless of the 'overflow' property.

Tests: fast/css/object-fit/object-fit-canvas.html

fast/css/object-fit/object-fit-embed.html
fast/css/object-fit/object-fit-grow-landscape.html
fast/css/object-fit/object-fit-grow-portrait.html
fast/css/object-fit/object-fit-img-svg.html
fast/css/object-fit/object-fit-img-svg2.html
fast/css/object-fit/object-fit-img.html
fast/css/object-fit/object-fit-input-image.html
fast/css/object-fit/object-fit-object.html
fast/css/object-fit/object-fit-shrink.html
fast/css/object-fit/object-fit-video-poster.html
fast/css/parsing-object-fit.html
http/tests/css/object-fit-delayed-img-svg.html
media/video-object-fit-change.html
media/video-object-fit.html

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::ComputedStyleExtractor::propertyValue):

  • css/CSSParser.cpp:

(WebCore::isValidKeywordPropertyAndValue):
(WebCore::isKeywordPropertyID):
(WebCore::CSSParser::parseValue):

  • css/CSSPrimitiveValueMappings.h:

(WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
(WebCore::CSSPrimitiveValue::operator EObjectFit):

  • css/CSSProperty.cpp:

(WebCore::CSSProperty::isInheritedProperty):

  • css/CSSPropertyNames.in:
  • css/CSSValueKeywords.in:
  • css/DeprecatedStyleBuilder.cpp:

(WebCore::DeprecatedStyleBuilder::DeprecatedStyleBuilder):

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::applyProperty):

  • css/html.css:

(video): Set object-fit to 'contain'. This is how VIDEO elements
work, apparently.

  • loader/cache/CachedImage.cpp:

(WebCore::CachedImage::imageSizeForRenderer):

  • loader/cache/CachedImage.h:
  • platform/graphics/LayoutSize.h:

(WebCore::fitLayoutSizeToAspectRatio): New function to grow or shrink
in one dimension to fit to the aspect ratio.

  • rendering/RenderHTMLCanvas.cpp:

(WebCore::RenderHTMLCanvas::paintReplaced): Apply object-fit and
clip if necessary.

  • rendering/RenderImage.cpp:

(WebCore::RenderImage::updateInnerContentRect):
(WebCore::RenderImage::imageDimensionsChanged): Update intrinsic
size properly, and recalculate the inner content rectangle (the
exact area occupied by the replaced content) again if appropriate.
(WebCore::RenderImage::paintReplaced): Apply object-fit and clip
if necessary.
(WebCore::RenderImage::foregroundIsKnownToBeOpaqueInRect):
object-fit may leave parts of the content box empty, in which case
it won't be fully obscured.
(WebCore::RenderImage::layout):

  • rendering/RenderImage.h:
  • rendering/RenderImageResource.cpp:

(WebCore::RenderImageResource::intrinsicSize): Need this to
differentiate between intrinsic and extrinsic size for SVG images.

  • rendering/RenderImageResource.h:
  • rendering/RenderImageResourceStyleImage.h:
  • rendering/RenderReplaced.cpp:

(WebCore::RenderReplaced::replacedContentRect): Return the
rectangle occupied by the replaced content. This will be identical
to the content box if object-fit is 'fill', but will typically be
something else for other values.

  • rendering/RenderReplaced.h:
  • rendering/RenderVideo.cpp:

(WebCore::RenderVideo::videoBox): Not much left to do here, with
the new RenderReplaced::replacedContentRect() method in place.
(WebCore::RenderVideo::paintReplaced): Apply object-fit and clip
if necessary.

  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::changeRequiresRepaint):

  • rendering/style/RenderStyle.h:
  • rendering/style/RenderStyleConstants.h:
  • rendering/style/StyleRareNonInheritedData.cpp:

(WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
(WebCore::StyleRareNonInheritedData::operator==):

  • rendering/style/StyleRareNonInheritedData.h:

LayoutTests:

Reviewed by Antti Koivisto, Sam Weinig.

Tests for object-fit.

  • fast/css/object-fit/object-fit-canvas-expected.html: Added.
  • fast/css/object-fit/object-fit-canvas.html: Added.
  • fast/css/object-fit/object-fit-embed-expected.html: Added.
  • fast/css/object-fit/object-fit-embed.html: Added.
  • fast/css/object-fit/object-fit-grow-landscape-expected.html: Added.
  • fast/css/object-fit/object-fit-grow-landscape.html: Added.
  • fast/css/object-fit/object-fit-grow-portrait-expected.html: Added.
  • fast/css/object-fit/object-fit-grow-portrait.html: Added.
  • fast/css/object-fit/object-fit-img-expected.html: Added.
  • fast/css/object-fit/object-fit-img-svg-expected.html: Added.
  • fast/css/object-fit/object-fit-img-svg.html: Added.
  • fast/css/object-fit/object-fit-img-svg2-expected.html: Added.
  • fast/css/object-fit/object-fit-img-svg2.html: Added.
  • fast/css/object-fit/object-fit-img.html: Added.
  • fast/css/object-fit/object-fit-input-image-expected.html: Added.
  • fast/css/object-fit/object-fit-input-image.html: Added.
  • fast/css/object-fit/object-fit-object-expected.html: Added.
  • fast/css/object-fit/object-fit-object.html: Added.
  • fast/css/object-fit/object-fit-shrink-expected.html: Added.
  • fast/css/object-fit/object-fit-shrink.html: Added.
  • fast/css/object-fit/object-fit-video-poster-expected.html: Added.
  • fast/css/object-fit/object-fit-video-poster.html: Added.
  • fast/css/parsing-object-fit-expected.txt: Added.
  • fast/css/parsing-object-fit.html: Added.
  • fast/css/resources/circle.svg: Added.
  • fast/css/resources/circle2.svg: Added.
  • fast/css/resources/circles-landscape-small.png: Added.
  • fast/css/resources/circles-landscape.png: Added.
  • fast/css/resources/circles-portrait-small.png: Added.
  • fast/css/resources/circles-portrait.png: Added.
  • http/tests/css/object-fit-delayed-img-svg-expected.html: Added.
  • http/tests/css/object-fit-delayed-img-svg.html: Added.
  • media/video-object-fit-change-expected.html: Added.
  • media/video-object-fit-change.html: Added.
  • media/video-object-fit-expected.html: Added.
  • media/video-object-fit.html: Added.
  • platform/mac/TestExpectations:
Location:
trunk
Files:
37 added
33 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r154856 r154858  
     12013-08-26  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Implement object-fit CSS property
     4        https://bugs.webkit.org/show_bug.cgi?id=52040
     5
     6        Reviewed by Antti Koivisto, Sam Weinig.
     7
     8        Tests for object-fit.
     9
     10        * fast/css/object-fit/object-fit-canvas-expected.html: Added.
     11        * fast/css/object-fit/object-fit-canvas.html: Added.
     12        * fast/css/object-fit/object-fit-embed-expected.html: Added.
     13        * fast/css/object-fit/object-fit-embed.html: Added.
     14        * fast/css/object-fit/object-fit-grow-landscape-expected.html: Added.
     15        * fast/css/object-fit/object-fit-grow-landscape.html: Added.
     16        * fast/css/object-fit/object-fit-grow-portrait-expected.html: Added.
     17        * fast/css/object-fit/object-fit-grow-portrait.html: Added.
     18        * fast/css/object-fit/object-fit-img-expected.html: Added.
     19        * fast/css/object-fit/object-fit-img-svg-expected.html: Added.
     20        * fast/css/object-fit/object-fit-img-svg.html: Added.
     21        * fast/css/object-fit/object-fit-img-svg2-expected.html: Added.
     22        * fast/css/object-fit/object-fit-img-svg2.html: Added.
     23        * fast/css/object-fit/object-fit-img.html: Added.
     24        * fast/css/object-fit/object-fit-input-image-expected.html: Added.
     25        * fast/css/object-fit/object-fit-input-image.html: Added.
     26        * fast/css/object-fit/object-fit-object-expected.html: Added.
     27        * fast/css/object-fit/object-fit-object.html: Added.
     28        * fast/css/object-fit/object-fit-shrink-expected.html: Added.
     29        * fast/css/object-fit/object-fit-shrink.html: Added.
     30        * fast/css/object-fit/object-fit-video-poster-expected.html: Added.
     31        * fast/css/object-fit/object-fit-video-poster.html: Added.
     32        * fast/css/parsing-object-fit-expected.txt: Added.
     33        * fast/css/parsing-object-fit.html: Added.
     34        * fast/css/resources/circle.svg: Added.
     35        * fast/css/resources/circle2.svg: Added.
     36        * fast/css/resources/circles-landscape-small.png: Added.
     37        * fast/css/resources/circles-landscape.png: Added.
     38        * fast/css/resources/circles-portrait-small.png: Added.
     39        * fast/css/resources/circles-portrait.png: Added.
     40        * http/tests/css/object-fit-delayed-img-svg-expected.html: Added.
     41        * http/tests/css/object-fit-delayed-img-svg.html: Added.
     42        * media/video-object-fit-change-expected.html: Added.
     43        * media/video-object-fit-change.html: Added.
     44        * media/video-object-fit-expected.html: Added.
     45        * media/video-object-fit.html: Added.
     46        * platform/mac/TestExpectations:
     47
    1482013-08-29  Tim Horton  <timothy_horton@apple.com>
    249
  • trunk/LayoutTests/platform/mac/TestExpectations

    r154829 r154858  
    5252# This test requires ogg codecs
    5353media/media-can-play-ogg.html
     54
     55webkit.org/b/52103 media/video-object-fit-change.html
     56webkit.org/b/52103 media/video-object-fit.html
    5457
    5558# This test requires flac codec
     
    379382# Styled scope element is not yet enabled.
    380383webkit.org/b/49142 fast/css/style-scoped
     384
     385# fails because of antialiasing differences.
     386fast/css/object-fit/object-fit-canvas.html [ Pass ImageOnlyFailure ]
    381387
    382388# CSS Regions tests for region styling and scoped styles
  • trunk/Source/WebCore/ChangeLog

    r154856 r154858  
     12013-08-26  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Implement object-fit CSS property
     4        https://bugs.webkit.org/show_bug.cgi?id=52040
     5
     6        Reviewed by Antti Koivisto, Sam Weinig.
     7       
     8        Merge object-fit patch from Blink r156535, which started as a patch
     9        by me.
     10
     11        Since then, the spec has gone to CR. This patch is an
     12        implementation of object-fit as described in
     13        http://www.w3.org/TR/2012/CR-css3-images-20120417/#object-fit
     14
     15        Object-fit is used to maintain the aspect ratio of replaced content
     16        within its content box. All object-fit values but the initial one
     17        ('fill') will always ensure that the aspect ratio is retained, in
     18        different ways (fit inside the content box, cover the content box, or
     19        use intrinsic size). Painting is always clipped against the content
     20        box, regardless of the 'overflow' property.
     21
     22        Tests: fast/css/object-fit/object-fit-canvas.html
     23               fast/css/object-fit/object-fit-embed.html
     24               fast/css/object-fit/object-fit-grow-landscape.html
     25               fast/css/object-fit/object-fit-grow-portrait.html
     26               fast/css/object-fit/object-fit-img-svg.html
     27               fast/css/object-fit/object-fit-img-svg2.html
     28               fast/css/object-fit/object-fit-img.html
     29               fast/css/object-fit/object-fit-input-image.html
     30               fast/css/object-fit/object-fit-object.html
     31               fast/css/object-fit/object-fit-shrink.html
     32               fast/css/object-fit/object-fit-video-poster.html
     33               fast/css/parsing-object-fit.html
     34               http/tests/css/object-fit-delayed-img-svg.html
     35               media/video-object-fit-change.html
     36               media/video-object-fit.html
     37
     38        * css/CSSComputedStyleDeclaration.cpp:
     39        (WebCore::ComputedStyleExtractor::propertyValue):
     40        * css/CSSParser.cpp:
     41        (WebCore::isValidKeywordPropertyAndValue):
     42        (WebCore::isKeywordPropertyID):
     43        (WebCore::CSSParser::parseValue):
     44        * css/CSSPrimitiveValueMappings.h:
     45        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
     46        (WebCore::CSSPrimitiveValue::operator EObjectFit):
     47        * css/CSSProperty.cpp:
     48        (WebCore::CSSProperty::isInheritedProperty):
     49        * css/CSSPropertyNames.in:
     50        * css/CSSValueKeywords.in:
     51        * css/DeprecatedStyleBuilder.cpp:
     52        (WebCore::DeprecatedStyleBuilder::DeprecatedStyleBuilder):
     53        * css/StyleResolver.cpp:
     54        (WebCore::StyleResolver::applyProperty):
     55        * css/html.css:
     56        (video): Set object-fit to 'contain'. This is how VIDEO elements
     57        work, apparently.
     58        * loader/cache/CachedImage.cpp:
     59        (WebCore::CachedImage::imageSizeForRenderer):
     60        * loader/cache/CachedImage.h:
     61        * platform/graphics/LayoutSize.h:
     62        (WebCore::fitLayoutSizeToAspectRatio): New function to grow or shrink
     63        in one dimension to fit to the aspect ratio.
     64        * rendering/RenderHTMLCanvas.cpp:
     65        (WebCore::RenderHTMLCanvas::paintReplaced): Apply object-fit and
     66        clip if necessary.
     67        * rendering/RenderImage.cpp:
     68        (WebCore::RenderImage::updateInnerContentRect):
     69        (WebCore::RenderImage::imageDimensionsChanged): Update intrinsic
     70        size properly, and recalculate the inner content rectangle (the
     71        exact area occupied by the replaced content) again if appropriate.
     72        (WebCore::RenderImage::paintReplaced): Apply object-fit and clip
     73        if necessary.
     74        (WebCore::RenderImage::foregroundIsKnownToBeOpaqueInRect):
     75        object-fit may leave parts of the content box empty, in which case
     76        it won't be fully obscured.
     77        (WebCore::RenderImage::layout):
     78        * rendering/RenderImage.h:
     79        * rendering/RenderImageResource.cpp:
     80        (WebCore::RenderImageResource::intrinsicSize): Need this to
     81        differentiate between intrinsic and extrinsic size for SVG images.
     82        * rendering/RenderImageResource.h:
     83        * rendering/RenderImageResourceStyleImage.h:
     84        * rendering/RenderReplaced.cpp:
     85        (WebCore::RenderReplaced::replacedContentRect): Return the
     86        rectangle occupied by the replaced content. This will be identical
     87        to the content box if object-fit is 'fill', but will typically be
     88        something else for other values.
     89        * rendering/RenderReplaced.h:
     90        * rendering/RenderVideo.cpp:
     91        (WebCore::RenderVideo::videoBox): Not much left to do here, with
     92        the new RenderReplaced::replacedContentRect() method in place.
     93        (WebCore::RenderVideo::paintReplaced): Apply object-fit and clip
     94        if necessary.
     95        * rendering/style/RenderStyle.cpp:
     96        (WebCore::RenderStyle::changeRequiresRepaint):
     97        * rendering/style/RenderStyle.h:
     98        * rendering/style/RenderStyleConstants.h:
     99        * rendering/style/StyleRareNonInheritedData.cpp:
     100        (WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
     101        (WebCore::StyleRareNonInheritedData::operator==):
     102        * rendering/style/StyleRareNonInheritedData.h:
     103
    11042013-08-29  Tim Horton  <timothy_horton@apple.com>
    2105
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r154541 r154858  
    22422242                return zoomAdjustedPixelValue(0, style.get());
    22432243            return zoomAdjustedPixelValueForLength(style->minWidth(), style.get());
     2244        case CSSPropertyObjectFit:
     2245            return cssValuePool().createValue(style->objectFit());
    22442246        case CSSPropertyOpacity:
    22452247            return cssValuePool().createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
  • trunk/Source/WebCore/css/CSSParser.cpp

    r154766 r154858  
    739739            return true;
    740740        break;
     741    case CSSPropertyObjectFit:
     742        if (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown)
     743            return true;
     744        break;
    741745    case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
    742746        if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
     
    10761080    case CSSPropertyListStylePosition:
    10771081    case CSSPropertyListStyleType:
     1082    case CSSPropertyObjectFit:
    10781083    case CSSPropertyOutlineStyle:
    10791084    case CSSPropertyOverflowWrap:
     
    30323037    case CSSPropertyListStylePosition:
    30333038    case CSSPropertyListStyleType:
     3039    case CSSPropertyObjectFit:
    30343040    case CSSPropertyOutlineStyle:
    30353041    case CSSPropertyOverflowWrap:
  • trunk/Source/WebCore/css/CSSPrimitiveValueMappings.h

    r153401 r154858  
    35683568    ASSERT_NOT_REACHED();
    35693569    return FontDescription::AutoKerning;
     3570}
     3571
     3572template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ObjectFit fit)
     3573    : CSSValue(PrimitiveClass)
     3574{
     3575    m_primitiveUnitType = CSS_VALUE_ID;
     3576    switch (fit) {
     3577    case ObjectFitFill:
     3578        m_value.valueID = CSSValueFill;
     3579        break;
     3580    case ObjectFitContain:
     3581        m_value.valueID = CSSValueContain;
     3582        break;
     3583    case ObjectFitCover:
     3584        m_value.valueID = CSSValueCover;
     3585        break;
     3586    case ObjectFitNone:
     3587        m_value.valueID = CSSValueNone;
     3588        break;
     3589    case ObjectFitScaleDown:
     3590        m_value.valueID = CSSValueScaleDown;
     3591        break;
     3592    }
     3593}
     3594
     3595template<> inline CSSPrimitiveValue::operator ObjectFit() const
     3596{
     3597    ASSERT(isValueID());
     3598
     3599    switch (m_value.valueID) {
     3600    case CSSValueFill:
     3601        return ObjectFitFill;
     3602    case CSSValueContain:
     3603        return ObjectFitContain;
     3604    case CSSValueCover:
     3605        return ObjectFitCover;
     3606    case CSSValueNone:
     3607        return ObjectFitNone;
     3608    case CSSValueScaleDown:
     3609        return ObjectFitScaleDown;
     3610    default:
     3611        ASSERT_NOT_REACHED();
     3612        return ObjectFitFill;
     3613    }
    35703614}
    35713615
  • trunk/Source/WebCore/css/CSSProperty.cpp

    r154338 r154858  
    463463    case CSSPropertyMinHeight:
    464464    case CSSPropertyMinWidth:
     465    case CSSPropertyObjectFit:
    465466    case CSSPropertyOpacity:
    466467    case CSSPropertyOutline:
  • trunk/Source/WebCore/css/CSSPropertyNames.in

    r154338 r154858  
    137137parameters
    138138#endif
     139object-fit
    139140opacity
    140141// Honor -webkit-opacity as a synonym for opacity. This was the only syntax that worked in Safari 1.1,
  • trunk/Source/WebCore/css/CSSValueKeywords.in

    r154203 r154858  
    10101010luminosity
    10111011
     1012// object-fit
     1013// fill
     1014// contain
     1015// cover
     1016// none
     1017scale-down
     1018
    10121019#if defined(ENABLE_CSS_IMAGE_RESOLUTION) && ENABLE_CSS_IMAGE_RESOLUTION
    10131020from-image
  • trunk/Source/WebCore/css/DeprecatedStyleBuilder.cpp

    r154174 r154858  
    21672167    setPropertyHandler(CSSPropertyMinHeight, ApplyPropertyLength<&RenderStyle::minHeight, &RenderStyle::setMinHeight, &RenderStyle::initialMinSize, AutoEnabled, LegacyIntrinsicEnabled, IntrinsicDisabled>::createHandler());
    21682168    setPropertyHandler(CSSPropertyMinWidth, ApplyPropertyLength<&RenderStyle::minWidth, &RenderStyle::setMinWidth, &RenderStyle::initialMinSize, AutoEnabled, LegacyIntrinsicEnabled, IntrinsicEnabled>::createHandler());
     2169    setPropertyHandler(CSSPropertyObjectFit, ApplyPropertyDefault<ObjectFit, &RenderStyle::objectFit, ObjectFit, &RenderStyle::setObjectFit, ObjectFit, &RenderStyle::initialObjectFit>::createHandler());
    21692170    setPropertyHandler(CSSPropertyOpacity, ApplyPropertyDefault<float, &RenderStyle::opacity, float, &RenderStyle::setOpacity, float, &RenderStyle::initialOpacity>::createHandler());
    21702171    setPropertyHandler(CSSPropertyOrphans, ApplyPropertyAuto<short, &RenderStyle::orphans, &RenderStyle::setOrphans, &RenderStyle::hasAutoOrphans, &RenderStyle::setHasAutoOrphans>::createHandler());
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r154835 r154858  
    28132813    case CSSPropertyMinHeight:
    28142814    case CSSPropertyMinWidth:
     2815    case CSSPropertyObjectFit:
    28152816    case CSSPropertyOpacity:
    28162817    case CSSPropertyOrphans:
  • trunk/Source/WebCore/css/html.css

    r154835 r154858  
    147147}
    148148
     149video {
     150    object-fit: contain;
     151}
     152
    149153/* heading elements */
    150154
  • trunk/Source/WebCore/loader/cache/CachedImage.cpp

    r154706 r154858  
    246246}
    247247
    248 LayoutSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float multiplier)
     248LayoutSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float multiplier, SizeType sizeType)
    249249{
    250250    ASSERT(!isPurgeable());
     
    258258        imageSize = static_cast<BitmapImage*>(m_image.get())->sizeRespectingOrientation();
    259259#if ENABLE(SVG)
    260     else if (m_image->isSVGImage()) {
     260    else if (m_image->isSVGImage() && sizeType == UsedSize) {
    261261        imageSize = m_svgImageCache->imageSizeForRenderer(renderer);
    262262    }
  • trunk/Source/WebCore/loader/cache/CachedImage.h

    r151586 r154858  
    6868    virtual void finishLoading(ResourceBuffer*) OVERRIDE;
    6969
     70    enum SizeType {
     71        UsedSize,
     72        IntrinsicSize
     73    };
    7074    // This method takes a zoom multiplier that can be used to increase the natural size of the image by the zoom.
    71     LayoutSize imageSizeForRenderer(const RenderObject*, float multiplier); // returns the size of the complete image.
     75    LayoutSize imageSizeForRenderer(const RenderObject*, float multiplier, SizeType = UsedSize); // returns the size of the complete image.
    7276    void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
    7377
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.h

    r154470 r154858  
    361361    IntRect contentsRect() const { return m_contentsRect; }
    362362    virtual void setContentsRect(const IntRect& r) { m_contentsRect = r; }
    363    
     363
     364    IntRect contentsClippingRect() const { return m_contentsClippingRect; }
     365    virtual void setContentsClippingRect(const IntRect& r) { m_contentsClippingRect = r; }
     366
    364367    // Transitions are identified by a special animation name that cannot clash with a keyframe identifier.
    365368    static String animationNameForTransition(AnimatedPropertyID);
     
    569572
    570573    IntRect m_contentsRect;
     574    IntRect m_contentsClippingRect;
    571575    IntPoint m_contentsTilePhase;
    572576    IntSize m_contentsTileSize;
  • trunk/Source/WebCore/platform/graphics/LayoutRect.cpp

    r152175 r154858  
    114114}
    115115
     116void LayoutRect::scale(float xScale, float yScale)
     117{
     118    m_location.scale(xScale, yScale);
     119    m_size.scale(xScale, yScale);
     120}
     121
    116122LayoutRect unionRect(const Vector<LayoutRect>& rects)
    117123{
  • trunk/Source/WebCore/platform/graphics/LayoutRect.h

    r152175 r154858  
    161161    void inflate(LayoutUnit d) { inflateX(d); inflateY(d); }
    162162    void scale(float s);
     163    void scale(float xScale, float yScale);
    163164
    164165    LayoutRect transposedRect() const { return LayoutRect(m_location.transposedPoint(), m_size.transposedSize()); }
  • trunk/Source/WebCore/platform/graphics/LayoutSize.h

    r152175 r154858  
    3939
    4040class LayoutPoint;
     41
     42enum AspectRatioFit {
     43    AspectRatioFitShrink,
     44    AspectRatioFitGrow
     45};
    4146
    4247class LayoutSize {
     
    115120    operator FloatSize() const { return FloatSize(m_width, m_height); }
    116121
     122    LayoutSize fitToAspectRatio(const LayoutSize& aspectRatio, AspectRatioFit fit) const
     123    {
     124        float heightScale = height().toFloat() / aspectRatio.height().toFloat();
     125        float widthScale = width().toFloat() / aspectRatio.width().toFloat();
     126
     127        if ((widthScale > heightScale) != (fit == AspectRatioFitGrow))
     128            return LayoutSize(height() * aspectRatio.width() / aspectRatio.height(), height());
     129
     130        return LayoutSize(width(), width() * aspectRatio.height() / aspectRatio.width());
     131    }
     132
    117133private:
    118134    LayoutUnit m_width, m_height;
  • trunk/Source/WebCore/rendering/RenderHTMLCanvas.cpp

    r154554 r154858  
    6060void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    6161{
    62     LayoutRect rect = contentBoxRect();
    63     rect.moveBy(paintOffset);
     62    GraphicsContext* context = paintInfo.context;
     63
     64    LayoutRect contentRect = contentBoxRect();
     65    contentRect.moveBy(paintOffset);
     66    LayoutRect paintRect = replacedContentRect(intrinsicSize());
     67    paintRect.moveBy(paintOffset);
     68
     69    // Not allowed to overflow the content box.
     70    bool clip = !contentRect.contains(paintRect);
     71    GraphicsContextStateSaver stateSaver(*paintInfo.context, clip);
     72    if (clip)
     73        paintInfo.context->clip(pixelSnappedIntRect(contentRect));
    6474
    6575    if (Page* page = frame().page()) {
    6676        if (paintInfo.phase == PaintPhaseForeground)
    67             page->addRelevantRepaintedObject(this, rect);
     77            page->addRelevantRepaintedObject(this, intersection(paintRect, contentRect));
    6878    }
    6979
    7080    bool useLowQualityScale = style()->imageRendering() == ImageRenderingCrispEdges || style()->imageRendering() == ImageRenderingOptimizeSpeed;
    71     static_cast<HTMLCanvasElement*>(node())->paint(paintInfo.context, rect, useLowQualityScale);
     81    static_cast<HTMLCanvasElement*>(node())->paint(context, paintRect, useLowQualityScale);
    7282}
    7383
  • trunk/Source/WebCore/rendering/RenderImage.cpp

    r154580 r154858  
    207207}
    208208
     209void RenderImage::updateInnerContentRect()
     210{
     211    // Propagate container size to image resource.
     212    LayoutRect paintRect = replacedContentRect(intrinsicSize());
     213    IntSize containerSize(paintRect.width(), paintRect.height());
     214    if (!containerSize.isEmpty())
     215        m_imageResource->setContainerSizeForRenderer(containerSize);
     216}
     217
    209218void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* rect)
    210219{
     
    215224    if (scale <= 0)
    216225        scale = 1;
    217     bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->imageSize(style()->effectiveZoom() / scale), imageSizeChanged);
     226    bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->intrinsicSize(style()->effectiveZoom() / scale), imageSizeChanged);
    218227#else
    219     bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->imageSize(style()->effectiveZoom()), imageSizeChanged);
     228    bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->intrinsicSize(style()->effectiveZoom()), imageSizeChanged);
    220229#endif
    221230
     
    255264            if (!selfNeedsLayout())
    256265                setNeedsLayout(true);
     266        }
     267
     268        if (everHadLayout() && !selfNeedsLayout()) {
     269            // The inner content rectangle is calculated during layout, but may need an update now
     270            // (unless the box has already been scheduled for layout). In order to calculate it, we
     271            // may need values from the containing block, though, so make sure that we're not too
     272            // early. It may be that layout hasn't even taken place once yet.
     273
     274            // FIXME: we should not have to trigger another call to setContainerSizeForRenderer()
     275            // from here, since it's already being done during layout.
     276            updateInnerContentRect();
    257277        }
    258278    }
     
    395415#endif
    396416
    397         LayoutSize contentSize(cWidth, cHeight);
    398         LayoutPoint contentLocation = paintOffset;
    399         contentLocation.move(leftBorder + leftPad, topBorder + topPad);
    400         paintIntoRect(context, LayoutRect(contentLocation, contentSize));
     417        LayoutRect contentRect = contentBoxRect();
     418        contentRect.moveBy(paintOffset);
     419        LayoutRect paintRect = replacedContentRect(intrinsicSize());
     420        paintRect.moveBy(paintOffset);
     421        bool clip = !contentRect.contains(paintRect);
     422        GraphicsContextStateSaver stateSaver(*context, clip);
     423        if (clip)
     424            context->clip(contentRect);
     425
     426        paintIntoRect(context, paintRect);
    401427       
    402428        if (cachedImage() && page && paintInfo.phase == PaintPhaseForeground) {
    403429            // For now, count images as unpainted if they are still progressively loading. We may want
    404430            // to refine this in the future to account for the portion of the image that has painted.
     431            LayoutRect visibleRect = intersection(paintRect, contentRect);
    405432            if (cachedImage()->isLoading())
    406                 page->addRelevantUnpaintedObject(this, LayoutRect(contentLocation, contentSize));
     433                page->addRelevantUnpaintedObject(this, visibleRect);
    407434            else
    408                 page->addRelevantRepaintedObject(this, LayoutRect(contentLocation, contentSize));
     435                page->addRelevantRepaintedObject(this, visibleRect);
    409436        }
    410437    }
     
    510537    if ((backgroundClip == BorderFillBox || backgroundClip == PaddingFillBox) && style()->hasPadding())
    511538        return false;
     539    // Object-fit may leave parts of the content box empty.
     540    ObjectFit objectFit = style()->objectFit();
     541    if (objectFit != ObjectFitFill && objectFit != ObjectFitCover)
     542        return false;
    512543    // Check for image with alpha.
    513544    return m_imageResource->cachedImage() && m_imageResource->cachedImage()->currentFrameKnownToBeOpaque(this);
     
    575606    StackStats::LayoutCheckPoint layoutCheckPoint;
    576607    RenderReplaced::layout();
    577 
    578     // Propagate container size to image resource.
    579     IntSize containerSize(contentWidth(), contentHeight());
    580     if (!containerSize.isEmpty())
    581         m_imageResource->setContainerSizeForRenderer(containerSize);
     608    updateInnerContentRect();
    582609}
    583610
  • trunk/Source/WebCore/rendering/RenderImage.h

    r153380 r154858  
    102102    void imageDimensionsChanged(bool imageSizeChanged, const IntRect* = 0);
    103103    bool updateIntrinsicSizeIfNeeded(const LayoutSize&, bool imageSizeChanged);
     104    // Update the size of the image to be rendered. Object-fit may cause this to be different from the CSS box's content rect.
     105    void updateInnerContentRect();
    104106
    105107    void paintAreaElementFocusRing(PaintInfo&);
  • trunk/Source/WebCore/rendering/RenderImageResource.cpp

    r148175 r154858  
    132132}
    133133
     134LayoutSize RenderImageResource::intrinsicSize(float multiplier) const
     135{
     136    return m_cachedImage ? m_cachedImage->imageSizeForRenderer(m_renderer, multiplier, CachedImage::IntrinsicSize) : LayoutSize();
     137}
     138
    134139} // namespace WebCore
  • trunk/Source/WebCore/rendering/RenderImageResource.h

    r148175 r154858  
    6464
    6565    virtual LayoutSize imageSize(float multiplier) const;
     66    virtual LayoutSize intrinsicSize(float multiplier) const;
    6667
    6768    virtual WrappedImagePtr imagePtr() const { return m_cachedImage.get(); }
  • trunk/Source/WebCore/rendering/RenderImageResourceStyleImage.h

    r133172 r154858  
    5656
    5757    virtual LayoutSize imageSize(float multiplier) const OVERRIDE { return m_styleImage->imageSize(m_renderer, multiplier); }
     58    virtual LayoutSize intrinsicSize(float multiplier) const OVERRIDE { return m_styleImage->imageSize(m_renderer, multiplier); }
    5859
    5960    virtual WrappedImagePtr imagePtr() const { return m_styleImage->data(); }
  • trunk/Source/WebCore/rendering/RenderObject.h

    r154835 r154858  
    357357    virtual bool isRenderPart() const { return false; }
    358358    virtual bool isRenderRegion() const { return false; }
     359    virtual bool isRenderReplaced() const { return false; }
    359360    virtual bool isRenderView() const { return false; }
    360361    virtual bool isReplica() const { return false; }
  • trunk/Source/WebCore/rendering/RenderReplaced.cpp

    r154580 r154858  
    299299}
    300300
     301LayoutRect RenderReplaced::replacedContentRect(const LayoutSize& intrinsicSize) const
     302{
     303    LayoutRect contentRect = contentBoxRect();
     304    ObjectFit objectFit = style()->objectFit();
     305    if (objectFit == ObjectFitFill)
     306        return contentRect;
     307
     308    if (!intrinsicSize.width() || !intrinsicSize.height())
     309        return contentRect;
     310
     311    LayoutRect finalRect = contentRect;
     312    switch (objectFit) {
     313    case ObjectFitContain:
     314    case ObjectFitScaleDown:
     315    case ObjectFitCover:
     316        finalRect.setSize(finalRect.size().fitToAspectRatio(intrinsicSize, objectFit == ObjectFitCover ? AspectRatioFitGrow : AspectRatioFitShrink));
     317        if (objectFit != ObjectFitScaleDown || finalRect.width() <= intrinsicSize.width())
     318            break;
     319        // fall through
     320    case ObjectFitNone:
     321        finalRect.setSize(intrinsicSize);
     322        break;
     323    case ObjectFitFill:
     324        ASSERT_NOT_REACHED();
     325    }
     326
     327    // FIXME: This is where object-position should be taken into account, but since it's not
     328    // implemented yet, assume the initial value of "50% 50%".
     329    LayoutUnit xOffset = (contentRect.width() - finalRect.width()) / 2;
     330    LayoutUnit yOffset = (contentRect.height() - finalRect.height()) / 2;
     331    finalRect.move(xOffset, yOffset);
     332
     333    return finalRect;
     334}
     335
    301336void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
    302337{
  • trunk/Source/WebCore/rendering/RenderReplaced.h

    r153380 r154858  
    3636    virtual LayoutUnit computeReplacedLogicalHeight() const;
    3737
     38    LayoutRect replacedContentRect(const LayoutSize& intrinsicSize) const;
     39
    3840    bool hasReplacedLogicalWidth() const;
    3941    bool hasReplacedLogicalHeight() const;
    4042
    4143protected:
     44    virtual bool isRenderReplaced() const OVERRIDE FINAL { return true; }
     45
    4246    virtual void willBeDestroyed();
    4347
     
    8690};
    8791
     92inline RenderReplaced* toRenderReplaced(RenderObject* object)
     93{
     94    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderReplaced());
     95    return static_cast<RenderReplaced*>(object);
     96}
     97
     98inline const RenderReplaced* toRenderReplaced(const RenderObject* object)
     99{
     100    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderReplaced());
     101    return static_cast<const RenderReplaced*>(object);
     102}
     103
     104// This will catch anyone doing an unnecessary cast.
     105void toRenderReplaced(const RenderReplaced*);
     106
    88107}
    89108
  • trunk/Source/WebCore/rendering/RenderVideo.cpp

    r154580 r154858  
    152152IntRect RenderVideo::videoBox() const
    153153{
    154     if (m_cachedImageSize.isEmpty() && videoElement()->shouldDisplayPosterImage())
    155         return IntRect();
    156 
    157     LayoutSize elementSize;
     154    LayoutSize intrinsicSize = this->intrinsicSize();
     155
    158156    if (videoElement()->shouldDisplayPosterImage())
    159         elementSize = m_cachedImageSize;
    160     else
    161         elementSize = intrinsicSize();
    162 
    163     IntRect contentRect = pixelSnappedIntRect(contentBoxRect());
    164     if (elementSize.isEmpty() || contentRect.isEmpty())
    165         return IntRect();
    166 
    167     LayoutRect renderBox = contentRect;
    168     LayoutUnit ratio = renderBox.width() * elementSize.height() - renderBox.height() * elementSize.width();
    169     if (ratio > 0) {
    170         LayoutUnit newWidth = renderBox.height() * elementSize.width() / elementSize.height();
    171         // Just fill the whole area if the difference is one pixel or less (in both sides)
    172         if (renderBox.width() - newWidth > 2)
    173             renderBox.setWidth(newWidth);
    174         renderBox.move((contentRect.width() - renderBox.width()) / 2, 0);
    175     } else if (ratio < 0) {
    176         LayoutUnit newHeight = renderBox.width() * elementSize.height() / elementSize.width();
    177         if (renderBox.height() - newHeight > 2)
    178             renderBox.setHeight(newHeight);
    179         renderBox.move(0, (contentRect.height() - renderBox.height()) / 2);
    180     }
    181 
    182     return pixelSnappedIntRect(renderBox);
     157        intrinsicSize = m_cachedImageSize;
     158
     159    return pixelSnappedIntRect(replacedContentRect(intrinsicSize));
    183160}
    184161
     
    212189        page->addRelevantRepaintedObject(this, rect);
    213190
     191    LayoutRect contentRect = contentBoxRect();
     192    contentRect.moveBy(paintOffset);
     193    GraphicsContext* context = paintInfo.context;
     194    bool clip = !contentRect.contains(rect);
     195    GraphicsContextStateSaver stateSaver(*context, clip);
     196    if (clip)
     197        context->clip(contentRect);
     198
    214199    if (displayingPoster)
    215         paintIntoRect(paintInfo.context, rect);
     200        paintIntoRect(context, rect);
    216201    else if (view().frameView().paintBehavior() & PaintBehaviorFlattenCompositingLayers)
    217         mediaPlayer->paintCurrentFrameInContext(paintInfo.context, pixelSnappedIntRect(rect));
     202        mediaPlayer->paintCurrentFrameInContext(context, pixelSnappedIntRect(rect));
    218203    else
    219         mediaPlayer->paint(paintInfo.context, pixelSnappedIntRect(rect));
     204        mediaPlayer->paint(context, pixelSnappedIntRect(rect));
    220205}
    221206
     
    240225void RenderVideo::updatePlayer()
    241226{
     227    if (documentBeingDestroyed())
     228        return;
     229
    242230    updateIntrinsicSize();
    243231
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r154430 r154858  
    702702        || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
    703703        || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
     704        || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
    704705        || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
    705706        return true;
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r153906 r154858  
    864864
    865865    TextOrientation textOrientation() const { return static_cast<TextOrientation>(rareInheritedData->m_textOrientation); }
     866
     867    ObjectFit objectFit() const { return static_cast<ObjectFit>(rareNonInheritedData->m_objectFit); }
    866868   
    867869    // Return true if any transform related property (currently transform, transformStyle3D or perspective)
     
    13711373    bool setTextOrientation(TextOrientation);
    13721374
     1375    void setObjectFit(ObjectFit fit) { SET_VAR(rareNonInheritedData, m_objectFit, fit); }
     1376
    13731377    void setRubyPosition(RubyPosition position) { SET_VAR(rareInheritedData, m_rubyPosition, position); }
    13741378
     
    15921596    static TextCombine initialTextCombine() { return TextCombineNone; }
    15931597    static TextOrientation initialTextOrientation() { return TextOrientationVerticalRight; }
     1598    static ObjectFit initialObjectFit() { return ObjectFitFill; }
    15941599    static EDisplay initialDisplay() { return INLINE; }
    15951600    static EEmptyCell initialEmptyCells() { return SHOW; }
  • trunk/Source/WebCore/rendering/style/RenderStyleConstants.h

    r154174 r154858  
    208208enum EUserSelect {
    209209    SELECT_NONE, SELECT_TEXT, SELECT_ALL
     210};
     211
     212// CSS3 Image Values
     213enum ObjectFit {
     214    ObjectFitFill, ObjectFitContain, ObjectFitCover, ObjectFitNone, ObjectFitScaleDown
    210215};
    211216
  • trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp

    r154435 r154858  
    8888    , m_effectiveBlendMode(RenderStyle::initialBlendMode())
    8989#endif
     90    , m_objectFit(RenderStyle::initialObjectFit())
    9091{
    9192    m_maskBoxImage.setMaskDefaults();
     
    173174    , m_effectiveBlendMode(o.m_effectiveBlendMode)
    174175#endif
     176    , m_objectFit(o.m_objectFit)
    175177{
    176178}
     
    263265        && m_effectiveBlendMode == o.m_effectiveBlendMode
    264266#endif
    265         && m_hasAspectRatio == o.m_hasAspectRatio;
     267        && m_hasAspectRatio == o.m_hasAspectRatio
     268        && m_objectFit == o.m_objectFit;
    266269}
    267270
  • trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h

    r154430 r154858  
    202202#endif
    203203
     204    unsigned m_objectFit : 3; // ObjectFit
     205
    204206private:
    205207    StyleRareNonInheritedData();
Note: See TracChangeset for help on using the changeset viewer.