Changeset 144258 in webkit


Ignore:
Timestamp:
Feb 27, 2013 7:31:57 PM (11 years ago)
Author:
hmuller@adobe.com
Message:

[CSS Exclusions] Enable shape-inside rectangle support for shape-padding
https://bugs.webkit.org/show_bug.cgi?id=110500

Reviewed by Dirk Schulze.

Source/WebCore:

Added support for CSS shape-padding for shapes defined with shape-inside.

Tests: fast/exclusions/shape-inside/shape-inside-circle-padding.html

fast/exclusions/shape-inside/shape-inside-ellipse-padding.html
fast/exclusions/shape-inside/shape-inside-rectangle-padding.html
fast/exclusions/shape-inside/shape-inside-rounded-rectangle-padding.html

  • rendering/ExclusionRectangle.cpp:

(WebCore::FloatRoundedRect::paddingBounds): Inset the rounded rectangle to reflect the padding parameter.
(WebCore::FloatRoundedRect::marginBounds): Expand the rounded rectangle to reflect the margin parameter.
(WebCore::FloatRoundedRect::cornerInterceptForWidth): Moved this method from ExclusionRectangle to FloatRoundedRect.
(WebCore::ExclusionRectangle::shapePaddingBounds): Lazily compute the bounds of the padding box.
(WebCore::ExclusionRectangle::shapeMarginBounds): Lazily compute the bounds of the margin box.
(WebCore::ExclusionRectangle::getExcludedIntervals): This computuation is now based on the (new) margin box.
(WebCore::ExclusionRectangle::getIncludedIntervals): This computation is now base don the (new) padding box.
(WebCore::ExclusionRectangle::firstIncludedIntervalLogicalTop): This computation is now base don the (new) padding box.

  • rendering/ExclusionRectangle.h:

(FloatRoundedRect): A subclass of FloatRect that includes corner radii specified as CSS shapes do.
(WebCore::FloatRoundedRect::FloatRoundedRect):
(WebCore::FloatRoundedRect::rx):
(WebCore::FloatRoundedRect::ry):
(WebCore::ExclusionRectangle::ExclusionRectangle):

  • rendering/ExclusionShape.cpp:

(WebCore::ExclusionShape::createExclusionShape): Initialize the new shapeMargin and shapePadding properties.

  • rendering/ExclusionShape.h:

(ExclusionShape):
(WebCore::ExclusionShape::shapeMargin): Added a public read-only property for shapeMargin.
(WebCore::ExclusionShape::shapePadding): Added a public read-only property for shapePadding.

  • rendering/ExclusionShapeInfo.cpp:

(WebCore::::computedShape): Pass the values of the CSS shape-margin and shapp-padding properties to createExclusionShape().

LayoutTests:

Added one shape-inside, shape-padding test for each CSS shape type.

  • fast/exclusions/shape-inside/shape-inside-circle-padding-expected.html: Added.
  • fast/exclusions/shape-inside/shape-inside-circle-padding.html: Added.
  • fast/exclusions/shape-inside/shape-inside-ellipse-padding-expected.html: Added.
  • fast/exclusions/shape-inside/shape-inside-ellipse-padding.html: Added.
  • fast/exclusions/shape-inside/shape-inside-rectangle-padding-expected.html: Added.
  • fast/exclusions/shape-inside/shape-inside-rectangle-padding.html: Added.
  • fast/exclusions/shape-inside/shape-inside-rounded-rectangle-padding-expected.html: Added.
  • fast/exclusions/shape-inside/shape-inside-rounded-rectangle-padding.html: Added.
Location:
trunk
Files:
8 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r144256 r144258  
     12013-02-27  Hans Muller  <hmuller@adobe.com>
     2
     3        [CSS Exclusions] Enable shape-inside rectangle support for shape-padding
     4        https://bugs.webkit.org/show_bug.cgi?id=110500
     5
     6        Reviewed by Dirk Schulze.
     7
     8        Added one shape-inside, shape-padding test for each CSS shape type.
     9
     10        * fast/exclusions/shape-inside/shape-inside-circle-padding-expected.html: Added.
     11        * fast/exclusions/shape-inside/shape-inside-circle-padding.html: Added.
     12        * fast/exclusions/shape-inside/shape-inside-ellipse-padding-expected.html: Added.
     13        * fast/exclusions/shape-inside/shape-inside-ellipse-padding.html: Added.
     14        * fast/exclusions/shape-inside/shape-inside-rectangle-padding-expected.html: Added.
     15        * fast/exclusions/shape-inside/shape-inside-rectangle-padding.html: Added.
     16        * fast/exclusions/shape-inside/shape-inside-rounded-rectangle-padding-expected.html: Added.
     17        * fast/exclusions/shape-inside/shape-inside-rounded-rectangle-padding.html: Added.
     18
    1192013-02-27  Stephen Chenney  <schenney@chromium.org>
    220
  • trunk/Source/WebCore/ChangeLog

    r144257 r144258  
     12013-02-27  Hans Muller  <hmuller@adobe.com>
     2
     3        [CSS Exclusions] Enable shape-inside rectangle support for shape-padding
     4        https://bugs.webkit.org/show_bug.cgi?id=110500
     5
     6        Reviewed by Dirk Schulze.
     7
     8        Added support for CSS shape-padding for shapes defined with shape-inside.
     9
     10        Tests: fast/exclusions/shape-inside/shape-inside-circle-padding.html
     11               fast/exclusions/shape-inside/shape-inside-ellipse-padding.html
     12               fast/exclusions/shape-inside/shape-inside-rectangle-padding.html
     13               fast/exclusions/shape-inside/shape-inside-rounded-rectangle-padding.html
     14
     15        * rendering/ExclusionRectangle.cpp:
     16        (WebCore::FloatRoundedRect::paddingBounds): Inset the rounded rectangle to reflect the padding parameter.
     17        (WebCore::FloatRoundedRect::marginBounds): Expand the rounded rectangle to reflect the margin parameter.
     18        (WebCore::FloatRoundedRect::cornerInterceptForWidth): Moved this method from ExclusionRectangle to FloatRoundedRect.
     19        (WebCore::ExclusionRectangle::shapePaddingBounds): Lazily compute the bounds of the padding box.
     20        (WebCore::ExclusionRectangle::shapeMarginBounds): Lazily compute the bounds of the margin box.
     21        (WebCore::ExclusionRectangle::getExcludedIntervals): This computuation is now based on the (new) margin box.
     22        (WebCore::ExclusionRectangle::getIncludedIntervals): This computation is now base don the (new) padding box.
     23        (WebCore::ExclusionRectangle::firstIncludedIntervalLogicalTop): This computation is now base don the (new) padding box.
     24        * rendering/ExclusionRectangle.h:
     25        (FloatRoundedRect): A subclass of FloatRect that includes corner radii specified as CSS shapes do.
     26        (WebCore::FloatRoundedRect::FloatRoundedRect):
     27        (WebCore::FloatRoundedRect::rx):
     28        (WebCore::FloatRoundedRect::ry):
     29        (WebCore::ExclusionRectangle::ExclusionRectangle):
     30        * rendering/ExclusionShape.cpp:
     31        (WebCore::ExclusionShape::createExclusionShape): Initialize the new shapeMargin and shapePadding properties.
     32        * rendering/ExclusionShape.h:
     33        (ExclusionShape):
     34        (WebCore::ExclusionShape::shapeMargin): Added a public read-only property for shapeMargin.
     35        (WebCore::ExclusionShape::shapePadding): Added a public read-only property for shapePadding.
     36        * rendering/ExclusionShapeInfo.cpp:
     37        (WebCore::::computedShape): Pass the values of the CSS shape-margin and shapp-padding properties to createExclusionShape().
     38
    1392013-02-25  Alpha Lam  <hclam@chromium.org>
    240
  • trunk/Source/WebCore/rendering/ExclusionRectangle.cpp

    r138043 r144258  
    4747}
    4848
     49FloatRoundedRect FloatRoundedRect::paddingBounds(float padding) const
     50{
     51    ASSERT(padding >= 0);
     52    if (!padding || isEmpty())
     53        return *this;
     54
     55    float boundsX = x() + std::min(width() / 2, padding);
     56    float boundsY = y() + std::min(height() / 2, padding);
     57    float boundsWidth = std::max(0.0f, width() - padding * 2);
     58    float boundsHeight = std::max(0.0f, height() - padding * 2);
     59    float boundsRadiusX = std::max(0.0f, rx() - padding);
     60    float boundsRadiusY = std::max(0.0f, ry() - padding);
     61    return FloatRoundedRect(FloatRect(boundsX, boundsY, boundsWidth, boundsHeight), FloatSize(boundsRadiusX, boundsRadiusY));
     62}
     63
     64FloatRoundedRect FloatRoundedRect::marginBounds(float margin) const
     65{
     66    ASSERT(margin >= 0);
     67    if (!margin)
     68        return *this;
     69
     70    float boundsX = x() - margin;
     71    float boundsY = y() - margin;
     72    float boundsWidth = width() + margin * 2;
     73    float boundsHeight = height() + margin * 2;
     74    float boundsRadiusX = std::max(rx(), margin);
     75    float boundsRadiusY = std::max(ry(), margin);
     76    return FloatRoundedRect(FloatRect(boundsX, boundsY, boundsWidth, boundsHeight), FloatSize(boundsRadiusX, boundsRadiusY));
     77}
     78
     79FloatPoint FloatRoundedRect::cornerInterceptForWidth(float widthAtIntercept) const
     80{
     81    float xi = (width() - widthAtIntercept) / 2;
     82    float yi = ry() - ellipseYIntercept(rx() - xi, rx(), ry());
     83    return FloatPoint(xi, yi);
     84}
     85
     86FloatRoundedRect ExclusionRectangle::shapePaddingBounds() const
     87{
     88    if (!m_haveInitializedPaddingBounds) {
     89        m_haveInitializedPaddingBounds = true;
     90        m_paddingBounds = m_bounds.paddingBounds(shapePadding());
     91    }
     92    return m_paddingBounds;
     93}
     94
     95FloatRoundedRect ExclusionRectangle::shapeMarginBounds() const
     96{
     97    if (!m_haveInitializedMarginBounds) {
     98        m_haveInitializedMarginBounds = true;
     99        m_marginBounds = m_bounds.marginBounds(shapeMargin());
     100    }
     101    return m_marginBounds;
     102}
     103
    49104void ExclusionRectangle::getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const
    50105{
    51     if (isEmpty())
     106    const FloatRoundedRect& bounds = shapeMarginBounds();
     107    if (bounds.isEmpty())
    52108        return;
    53109
     
    55111    float y2 = y1 + logicalHeight;
    56112
    57     if (y2 < m_y || y1 >= m_y + m_height)
    58         return;
    59 
    60     float x1 = m_x;
    61     float x2 = m_x + m_width;
    62 
    63     if (m_ry > 0) {
    64         if (y2 < m_y + m_ry) {
    65             float yi = y2 - m_y - m_ry;
    66             float xi = ellipseXIntercept(yi, m_rx, m_ry);
    67             x1 = m_x + m_rx - xi;
    68             x2 = m_x + m_width - m_rx + xi;
    69         } else if (y1 > m_y + m_height - m_ry) {
    70             float yi =  y1 - (m_y + m_height - m_ry);
    71             float xi = ellipseXIntercept(yi, m_rx, m_ry);
    72             x1 = m_x + m_rx - xi;
    73             x2 = m_x + m_width - m_rx + xi;
     113    if (y2 < bounds.y() || y1 >= bounds.maxY())
     114        return;
     115
     116    float x1 = bounds.x();
     117    float x2 = bounds.maxX();
     118
     119    if (bounds.ry() > 0) {
     120        if (y2 < bounds.y() + bounds.ry()) {
     121            float yi = y2 - bounds.y() - bounds.ry();
     122            float xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
     123            x1 = bounds.x() + bounds.rx() - xi;
     124            x2 = bounds.maxX() - bounds.rx() + xi;
     125        } else if (y1 > bounds.maxY() - bounds.ry()) {
     126            float yi =  y1 - (bounds.maxY() - bounds.ry());
     127            float xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
     128            x1 = bounds.x() + bounds.rx() - xi;
     129            x2 = bounds.maxX() - bounds.rx() + xi;
    74130        }
    75131    }
     
    80136void ExclusionRectangle::getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const
    81137{
    82     if (isEmpty())
     138    const FloatRoundedRect& bounds = shapePaddingBounds();
     139    if (bounds.isEmpty())
    83140        return;
    84141
     
    86143    float y2 = y1 + logicalHeight;
    87144
    88     if (y1 < m_y || y2 > m_y + m_height)
    89         return;
    90 
    91     float x1 = m_x;
    92     float x2 = m_x + m_width;
    93 
    94     if (m_ry > 0) {
    95         bool y1InterceptsCorner = y1 < m_y + m_ry;
    96         bool y2InterceptsCorner = y2 > m_y + m_height - m_ry;
     145    if (y1 < bounds.y() || y2 > bounds.maxY())
     146        return;
     147
     148    float x1 = bounds.x();
     149    float x2 = bounds.maxX();
     150
     151    if (bounds.ry() > 0) {
     152        bool y1InterceptsCorner = y1 < bounds.y() + bounds.ry();
     153        bool y2InterceptsCorner = y2 > bounds.maxY() - bounds.ry();
    97154        float xi = 0;
    98155
    99156        if (y1InterceptsCorner && y2InterceptsCorner) {
    100             if  (y1 < m_height + 2*m_y - y2) {
    101                 float yi = y1 - m_y - m_ry;
    102                 xi = ellipseXIntercept(yi, m_rx, m_ry);
     157            if  (y1 < bounds.height() + 2 * bounds.y() - y2) {
     158                float yi = y1 - bounds.y() - bounds.ry();
     159                xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
    103160            } else {
    104                 float yi =  y2 - (m_y + m_height - m_ry);
    105                 xi = ellipseXIntercept(yi, m_rx, m_ry);
     161                float yi =  y2 - (bounds.maxY() - bounds.ry());
     162                xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
    106163            }
    107164        } else if (y1InterceptsCorner) {
    108             float yi = y1 - m_y - m_ry;
    109             xi = ellipseXIntercept(yi, m_rx, m_ry);
     165            float yi = y1 - bounds.y() - bounds.ry();
     166            xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
    110167        } else if (y2InterceptsCorner) {
    111             float yi =  y2 - (m_y + m_height - m_ry);
    112             xi = ellipseXIntercept(yi, m_rx, m_ry);
     168            float yi =  y2 - (bounds.maxY() - bounds.ry());
     169            xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
    113170        }
    114171
    115172        if (y1InterceptsCorner || y2InterceptsCorner) {
    116             x1 = m_x + m_rx - xi;
    117             x2 = m_x + m_width - m_rx + xi;
     173            x1 = bounds.x() + bounds.rx() - xi;
     174            x2 = bounds.maxX() - bounds.rx() + xi;
    118175        }
    119176    }
     
    122179}
    123180
    124 FloatPoint ExclusionRectangle::cornerInterceptForWidth(float width) const
    125 {
    126     float xi = (m_width - width) / 2;
    127     float yi = m_ry - ellipseYIntercept(m_rx - xi, m_rx, m_ry);
    128     return FloatPoint(xi, yi);
    129 }
    130 
    131181bool ExclusionRectangle::firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const
    132182{
    133     if (minLogicalIntervalSize.width() > m_width)
     183    const FloatRoundedRect& bounds = shapePaddingBounds();
     184    if (bounds.isEmpty() || minLogicalIntervalSize.width() > bounds.width())
    134185        return false;
    135186
    136     float minY = std::max(m_y, minLogicalIntervalTop);
     187    float minY = std::max(bounds.y(), minLogicalIntervalTop);
    137188    float maxY = minY + minLogicalIntervalSize.height();
    138189
    139     if (maxY > m_y + m_height)
     190    if (maxY > bounds.maxY())
    140191        return false;
    141192
    142     bool intervalOverlapsMinCorner = minY < m_y + m_ry;
    143     bool intervalOverlapsMaxCorner = maxY > m_y + m_height - m_ry;
     193    bool intervalOverlapsMinCorner = minY < bounds.y() + bounds.ry();
     194    bool intervalOverlapsMaxCorner = maxY > bounds.maxY() - bounds.ry();
    144195
    145196    if (!intervalOverlapsMinCorner && !intervalOverlapsMaxCorner) {
     
    148199    }
    149200
    150     float centerY = m_y + m_height / 2;
     201    float centerY = bounds.y() + bounds.height() / 2;
    151202    bool minCornerDefinesX = fabs(centerY - minY) > fabs(centerY - maxY);
    152     bool intervalFitsWithinCorners = minLogicalIntervalSize.width() + 2 * m_rx <= m_width;
    153     FloatPoint cornerIntercept = cornerInterceptForWidth(minLogicalIntervalSize.width());
     203    bool intervalFitsWithinCorners = minLogicalIntervalSize.width() + 2 * bounds.rx() <= bounds.width();
     204    FloatPoint cornerIntercept = bounds.cornerInterceptForWidth(minLogicalIntervalSize.width());
    154205
    155206    if (intervalOverlapsMinCorner && (!intervalOverlapsMaxCorner || minCornerDefinesX)) {
    156         if (intervalFitsWithinCorners || m_y + cornerIntercept.y() < minY) {
     207        if (intervalFitsWithinCorners || bounds.y() + cornerIntercept.y() < minY) {
    157208            result = minY;
    158209            return true;
    159210        }
    160         if (minLogicalIntervalSize.height() < m_height - (2 * cornerIntercept.y())) {
    161             result = m_y + cornerIntercept.y();
     211        if (minLogicalIntervalSize.height() < bounds.height() - (2 * cornerIntercept.y())) {
     212            result = bounds.y() + cornerIntercept.y();
    162213            return true;
    163214        }
     
    165216
    166217    if (intervalOverlapsMaxCorner && (!intervalOverlapsMinCorner || !minCornerDefinesX)) {
    167         if (intervalFitsWithinCorners || minY <=  m_y + m_height - cornerIntercept.y() - minLogicalIntervalSize.height()) {
     218        if (intervalFitsWithinCorners || minY <=  bounds.maxY() - cornerIntercept.y() - minLogicalIntervalSize.height()) {
    168219            result = minY;
    169220            return true;
  • trunk/Source/WebCore/rendering/ExclusionRectangle.h

    r138043 r144258  
    3333#include "ExclusionShape.h"
    3434#include "FloatPoint.h"
     35#include "FloatRect.h"
    3536#include "FloatSize.h"
    3637#include <wtf/Assertions.h>
     
    3940namespace WebCore {
    4041
     42class FloatRoundedRect : public FloatRect {
     43public:
     44    FloatRoundedRect() { }
     45    FloatRoundedRect(const FloatRect& bounds, const FloatSize& radii)
     46        : FloatRect(bounds)
     47        , m_radii(radii)
     48    {
     49    }
     50
     51    float rx() const { return m_radii.width(); }
     52    float ry() const { return m_radii.height(); }
     53    FloatRoundedRect marginBounds(float margin) const;
     54    FloatRoundedRect paddingBounds(float padding) const;
     55    FloatPoint cornerInterceptForWidth(float width) const;
     56
     57private:
     58    FloatSize m_radii;
     59};
     60
    4161class ExclusionRectangle : public ExclusionShape {
    4262public:
    4363    ExclusionRectangle(const FloatRect& bounds, const FloatSize& radii)
    4464        : ExclusionShape()
    45         , m_x(bounds.x())
    46         , m_y(bounds.y())
    47         , m_width(bounds.width())
    48         , m_height(bounds.height())
    49         , m_rx(radii.width())
    50         , m_ry(radii.height())
     65        , m_bounds(bounds, radii)
     66        , m_haveInitializedMarginBounds(false)
     67        , m_haveInitializedPaddingBounds(false)
    5168    {
    5269    }
    5370
    54     virtual FloatRect shapeLogicalBoundingBox() const OVERRIDE { return FloatRect(m_x, m_y, m_width, m_height); }
    55     virtual bool isEmpty() const OVERRIDE { return m_width <= 0 || m_height <= 0; }
     71    virtual FloatRect shapeLogicalBoundingBox() const OVERRIDE { return m_bounds; }
     72    virtual bool isEmpty() const OVERRIDE { return m_bounds.isEmpty(); }
    5673    virtual void getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
    5774    virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
    5875    virtual bool firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float&) const OVERRIDE;
    5976
     77    FloatRoundedRect shapeMarginBounds() const;
     78    FloatRoundedRect shapePaddingBounds() const;
     79
    6080private:
    61     FloatPoint cornerInterceptForWidth(float width) const;
    62 
    63     float m_x;
    64     float m_y;
    65     float m_width;
    66     float m_height;
    67     float m_rx; // corner X radius
    68     float m_ry; // corner Y radius
     81    FloatRoundedRect m_bounds;
     82    mutable FloatRoundedRect m_marginBounds;
     83    mutable FloatRoundedRect m_paddingBounds;
     84    mutable bool m_haveInitializedMarginBounds : 1;
     85    mutable bool m_haveInitializedPaddingBounds : 1;
    6986};
    7087
  • trunk/Source/WebCore/rendering/ExclusionShape.cpp

    r138043 r144258  
    9191}
    9292
    93 PassOwnPtr<ExclusionShape> ExclusionShape::createExclusionShape(const BasicShape* basicShape, float logicalBoxWidth, float logicalBoxHeight, WritingMode writingMode)
     93PassOwnPtr<ExclusionShape> ExclusionShape::createExclusionShape(const BasicShape* basicShape, float logicalBoxWidth, float logicalBoxHeight, WritingMode writingMode, Length margin, Length padding)
    9494{
    9595    ASSERT(basicShape);
     
    176176    exclusionShape->m_logicalBoxHeight = logicalBoxHeight;
    177177    exclusionShape->m_writingMode = writingMode;
     178    exclusionShape->m_margin = floatValueForLength(margin, 0);
     179    exclusionShape->m_padding = floatValueForLength(padding, 0);
    178180
    179181    return exclusionShape.release();
  • trunk/Source/WebCore/rendering/ExclusionShape.h

    r138043 r144258  
    6060class ExclusionShape {
    6161public:
    62     static PassOwnPtr<ExclusionShape> createExclusionShape(const BasicShape*, float logicalBoxWidth, float logicalBoxHeight, WritingMode);
     62    static PassOwnPtr<ExclusionShape> createExclusionShape(const BasicShape*, float logicalBoxWidth, float logicalBoxHeight, WritingMode, Length margin, Length padding);
    6363
    6464    virtual ~ExclusionShape() { }
    6565
     66    float shapeMargin() const { return m_margin; }
     67    float shapePadding() const { return m_padding; }
    6668    virtual FloatRect shapeLogicalBoundingBox() const = 0;
    6769    virtual bool isEmpty() const = 0;
     
    7577    float m_logicalBoxHeight;
    7678    FloatRect m_boundingBox;
     79    float m_margin;
     80    float m_padding;
    7781};
    7882
  • trunk/Source/WebCore/rendering/ExclusionShapeInfo.cpp

    r143766 r144258  
    5151    ASSERT(shape);
    5252
    53     m_shape = ExclusionShape::createExclusionShape(shape, m_shapeLogicalWidth, m_shapeLogicalHeight, m_renderer->style()->writingMode());
     53    m_shape = ExclusionShape::createExclusionShape(shape, m_shapeLogicalWidth, m_shapeLogicalHeight, m_renderer->style()->writingMode(), m_renderer->style()->shapeMargin(), m_renderer->style()->shapePadding());
    5454    ASSERT(m_shape);
    5555    return m_shape.get();
Note: See TracChangeset for help on using the changeset viewer.