Changeset 93651 in webkit


Ignore:
Timestamp:
Aug 23, 2011 4:10:45 PM (13 years ago)
Author:
tony@chromium.org
Message:

Add handling of mix-width and max-width for flexitems
https://bugs.webkit.org/show_bug.cgi?id=66723

Reviewed by David Hyatt.

Source/WebCore:

If we flex past a min/max width value, we need to mark the flexitem as
a fixed width and re-start the flexing algorithm. We use a HashMap to
keep track of fixed width items.

This patch also split out the size computation from the actual layout
to avoid unnecessary layouts caused by restarting the flexing algorithm.

Test: css3/flexbox/003.html

  • rendering/RenderFlexibleBox.cpp:

(WebCore::RenderFlexibleBox::layoutHorizontalBlock):
(WebCore::RenderFlexibleBox::runFreeSpaceAllocationAlgorithm):

  • rendering/RenderFlexibleBox.h:

LayoutTests:

  • css3/flexbox/003-expected.txt: Added.
  • css3/flexbox/003.html: Added.
Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r93650 r93651  
     12011-08-23  Tony Chang  <tony@chromium.org>
     2
     3        Add handling of mix-width and max-width for flexitems
     4        https://bugs.webkit.org/show_bug.cgi?id=66723
     5
     6        Reviewed by David Hyatt.
     7
     8        * css3/flexbox/003-expected.txt: Added.
     9        * css3/flexbox/003.html: Added.
     10
    1112011-08-23  Adam Barth  <abarth@webkit.org>
    212
  • trunk/Source/WebCore/ChangeLog

    r93648 r93651  
     12011-08-23  Tony Chang  <tony@chromium.org>
     2
     3        Add handling of mix-width and max-width for flexitems
     4        https://bugs.webkit.org/show_bug.cgi?id=66723
     5
     6        Reviewed by David Hyatt.
     7
     8        If we flex past a min/max width value, we need to mark the flexitem as
     9        a fixed width and re-start the flexing algorithm.  We use a HashMap to
     10        keep track of fixed width items.
     11
     12        This patch also split out the size computation from the actual layout
     13        to avoid unnecessary layouts caused by restarting the flexing algorithm.
     14
     15        Test: css3/flexbox/003.html
     16
     17        * rendering/RenderFlexibleBox.cpp:
     18        (WebCore::RenderFlexibleBox::layoutHorizontalBlock):
     19        (WebCore::RenderFlexibleBox::runFreeSpaceAllocationAlgorithm):
     20        * rendering/RenderFlexibleBox.h:
     21
    1222011-08-23  Pratik Solanki  <psolanki@apple.com>
    223
  • trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp

    r93547 r93651  
    100100    m_overflow.clear();
    101101
    102     // FIXME: Assume horizontal layout until flex-direction is added.
     102    // FIXME: Assume horizontal layout until flex-flow is added.
    103103    layoutHorizontalBlock(relayoutChildren);
    104104
     
    117117static LayoutUnit preferredFlexItemContentWidth(RenderBox* child)
    118118{
     119    // FIXME: Handle vertical writing modes with horizontal flexing.
    119120    if (child->style()->width().isAuto())
    120121        return child->maxPreferredLogicalWidth() - child->borderLeft() - child->borderRight() - child->verticalScrollbarWidth() - child->paddingLeft() - child->paddingRight();
     
    129130    FlexibleBoxIterator iterator(this);
    130131
    131     computePreferredSize(relayoutChildren, iterator, preferredSize, totalPositiveFlexibility, totalNegativeFlexibility);
     132    computePreferredSizeHorizontal(relayoutChildren, iterator, preferredSize, totalPositiveFlexibility, totalNegativeFlexibility);
    132133    LayoutUnit availableFreeSpace = contentWidth() - preferredSize;
    133134
    134     LayoutUnit xOffset = borderLeft() + paddingLeft();
    135     LayoutUnit yOffset = borderTop() + paddingTop();
    136     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    137         LayoutUnit childPreferredSize = preferredFlexItemContentWidth(child);
    138         // FIXME: Handle max-width and min-width (we should clamp to the max/min value and restart the algorithm).
    139         if (availableFreeSpace > 0 && totalPositiveFlexibility > 0)
    140             childPreferredSize += lroundf(availableFreeSpace * child->style()->flexboxWidthPositiveFlex() / totalPositiveFlexibility);
    141         else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0)
    142             childPreferredSize += lroundf(availableFreeSpace * child->style()->flexboxWidthNegativeFlex() / totalNegativeFlexibility);
    143 
    144         childPreferredSize += child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight();
    145         child->setOverrideSize(LayoutSize(childPreferredSize, 0));
    146         child->setChildNeedsLayout(true);
    147         child->layoutIfNeeded();
    148 
    149         setHeight(std::max(height(), borderTop() + paddingTop() + child->marginTop() + child->height() + child->marginBottom() + paddingBottom() + borderBottom() + horizontalScrollbarHeight()));
    150 
    151         if (child->style()->marginLeft().isAuto())
    152             child->setMarginLeft(availableFreeSpace > 0 ? lroundf(availableFreeSpace / totalPositiveFlexibility) : 0);
    153         if (child->style()->marginRight().isAuto())
    154             child->setMarginRight(availableFreeSpace > 0 ? lroundf(availableFreeSpace / totalPositiveFlexibility) : 0);
    155 
    156         xOffset += child->marginLeft();
    157         child->setLocation(IntPoint(xOffset, yOffset));
    158         xOffset += child->width() + child->marginRight();
     135    InflexibleFlexItemSize inflexibleItems;
     136    while (!runFreeSpaceAllocationAlgorithmHorizontal(availableFreeSpace, totalPositiveFlexibility, totalNegativeFlexibility, inflexibleItems)) {
     137        ASSERT(totalPositiveFlexibility >= 0 && totalNegativeFlexibility >= 0);
     138        ASSERT(inflexibleItems.size() > 0);
    159139    }
    160140
     
    168148}
    169149
    170 void RenderFlexibleBox::computePreferredSize(bool relayoutChildren, FlexibleBoxIterator& iterator, LayoutUnit& preferredSize, float& totalPositiveFlexibility, float& totalNegativeFlexibility)
     150void RenderFlexibleBox::computePreferredSizeHorizontal(bool relayoutChildren, FlexibleBoxIterator& iterator, LayoutUnit& preferredSize, float& totalPositiveFlexibility, float& totalNegativeFlexibility)
    171151{
    172152    preferredSize = 0;
    173153    totalPositiveFlexibility = totalNegativeFlexibility = 0;
    174154
     155    // FIXME: Handle vertical writing modes with horizontal flexing.
    175156    LayoutUnit flexboxAvailableLogicalWidth = availableLogicalWidth();
    176157    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
     
    201182}
    202183
     184// Returns true if we successfully ran the algorithm and sized the flex items.
     185bool RenderFlexibleBox::runFreeSpaceAllocationAlgorithmHorizontal(LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize& inflexibleItems)
     186{
     187    FlexibleBoxIterator iterator(this);
     188
     189    // FIXME: Handle vertical writing modes with horizontal flexing.
     190    LayoutUnit flexboxAvailableLogicalWidth = availableLogicalWidth();
     191    WTF::Vector<LayoutUnit> childSizes;
     192    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
     193        LayoutUnit childPreferredSize;
     194        if (inflexibleItems.contains(child))
     195            childPreferredSize = inflexibleItems.get(child);
     196        else {
     197            childPreferredSize = preferredFlexItemContentWidth(child);
     198            if (availableFreeSpace > 0 && totalPositiveFlexibility > 0) {
     199                childPreferredSize += lroundf(availableFreeSpace * child->style()->flexboxWidthPositiveFlex() / totalPositiveFlexibility);
     200
     201                Length childMaxWidth = child->style()->maxWidth();
     202                if (!childMaxWidth.isUndefined() && childMaxWidth.isSpecified() && childPreferredSize > childMaxWidth.calcValue(flexboxAvailableLogicalWidth)) {
     203                    childPreferredSize = childMaxWidth.calcValue(flexboxAvailableLogicalWidth);
     204                    availableFreeSpace -= childPreferredSize - preferredFlexItemContentWidth(child);
     205                    totalPositiveFlexibility -= child->style()->flexboxWidthPositiveFlex();
     206
     207                    inflexibleItems.set(child, childPreferredSize);
     208                    return false;
     209                }
     210            } else if (availableFreeSpace < 0 && totalNegativeFlexibility > 0) {
     211                childPreferredSize += lroundf(availableFreeSpace * child->style()->flexboxWidthNegativeFlex() / totalNegativeFlexibility);
     212
     213                Length childMinWidth = child->style()->minWidth();
     214                if (!childMinWidth.isUndefined() && childMinWidth.isSpecified() && childPreferredSize < childMinWidth.calcValue(flexboxAvailableLogicalWidth)) {
     215                    childPreferredSize = childMinWidth.calcValue(flexboxAvailableLogicalWidth);
     216                    availableFreeSpace += preferredFlexItemContentWidth(child) - childPreferredSize;
     217                    totalNegativeFlexibility -= child->style()->flexboxWidthNegativeFlex();
     218
     219                    inflexibleItems.set(child, childPreferredSize);
     220                    return false;
     221                }
     222            }
     223        }
     224        childSizes.append(childPreferredSize);
     225    }
     226
     227    // Now that we know the sizes, layout and position the flex items.
     228    LayoutUnit xOffset = borderLeft() + paddingLeft();
     229    LayoutUnit yOffset = borderTop() + paddingTop();
     230    setHeight(0);
     231    size_t i = 0;
     232    for (RenderBox* child = iterator.first(); child; child = iterator.next(), ++i) {
     233        LayoutUnit childPreferredSize = childSizes[i];
     234        childPreferredSize += child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight();
     235        // FIXME: Handle vertical writing modes with horizontal flexing.
     236        child->setOverrideSize(LayoutSize(childPreferredSize, 0));
     237        child->setChildNeedsLayout(true);
     238        child->layoutIfNeeded();
     239
     240        setHeight(std::max(height(), borderTop() + paddingTop() + child->marginTop() + child->height() + child->marginBottom() + paddingBottom() + borderBottom() + horizontalScrollbarHeight()));
     241
     242        if (child->style()->marginLeft().isAuto())
     243            child->setMarginLeft(availableFreeSpace > 0 ? lroundf(availableFreeSpace / totalPositiveFlexibility) : 0);
     244        if (child->style()->marginRight().isAuto())
     245            child->setMarginRight(availableFreeSpace > 0 ? lroundf(availableFreeSpace / totalPositiveFlexibility) : 0);
     246
     247        xOffset += child->marginLeft();
     248        child->setLocation(IntPoint(xOffset, yOffset));
     249        xOffset += child->width() + child->marginRight();
     250    }
     251    return true;
     252}
     253
    203254}
    204255
  • trunk/Source/WebCore/rendering/RenderFlexibleBox.h

    r92628 r93651  
    5151private:
    5252    class FlexibleBoxIterator;
     53    typedef WTF::HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize;
    5354
    5455    void layoutHorizontalBlock(bool relayoutChildren);
    5556
    56     void computePreferredSize(bool relayoutChildren, FlexibleBoxIterator&, LayoutUnit&, float& totalPositiveFlexibility, float& totalNegativeFlexibility);
     57    void computePreferredSizeHorizontal(bool relayoutChildren, FlexibleBoxIterator&, LayoutUnit&, float& totalPositiveFlexibility, float& totalNegativeFlexibility);
     58    bool runFreeSpaceAllocationAlgorithmHorizontal(LayoutUnit& availableFreeSpace, float& totalPositiveFlexibility, float& totalNegativeFlexibility, InflexibleFlexItemSize&);
    5759};
    5860
Note: See TracChangeset for help on using the changeset viewer.