Home | History | Annotate | Download | only in rendering
      1 /*
      2  * This file is part of the render object implementation for KHTML.
      3  *
      4  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      5  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      6  * Copyright (C) 2003 Apple Computer, Inc.
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  *
     23  */
     24 
     25 #include "config.h"
     26 #include "core/rendering/RenderDeprecatedFlexibleBox.h"
     27 
     28 #include "core/page/UseCounter.h"
     29 #include "core/platform/graphics/Font.h"
     30 #include "core/rendering/LayoutRepainter.h"
     31 #include "core/rendering/RenderLayer.h"
     32 #include "core/rendering/RenderView.h"
     33 #include "wtf/StdLibExtras.h"
     34 #include "wtf/unicode/CharacterNames.h"
     35 
     36 using namespace std;
     37 
     38 namespace WebCore {
     39 
     40 class FlexBoxIterator {
     41 public:
     42     FlexBoxIterator(RenderDeprecatedFlexibleBox* parent)
     43         : m_box(parent)
     44         , m_largestOrdinal(1)
     45     {
     46         if (m_box->style()->boxOrient() == HORIZONTAL && !m_box->style()->isLeftToRightDirection())
     47             m_forward = m_box->style()->boxDirection() != BNORMAL;
     48         else
     49             m_forward = m_box->style()->boxDirection() == BNORMAL;
     50         if (!m_forward) {
     51             // No choice, since we're going backwards, we have to find out the highest ordinal up front.
     52             RenderBox* child = m_box->firstChildBox();
     53             while (child) {
     54                 if (child->style()->boxOrdinalGroup() > m_largestOrdinal)
     55                     m_largestOrdinal = child->style()->boxOrdinalGroup();
     56                 child = child->nextSiblingBox();
     57             }
     58         }
     59 
     60         reset();
     61     }
     62 
     63     void reset()
     64     {
     65         m_currentChild = 0;
     66         m_ordinalIteration = -1;
     67     }
     68 
     69     RenderBox* first()
     70     {
     71         reset();
     72         return next();
     73     }
     74 
     75     RenderBox* next()
     76     {
     77         do {
     78             if (!m_currentChild) {
     79                 ++m_ordinalIteration;
     80 
     81                 if (!m_ordinalIteration)
     82                     m_currentOrdinal = m_forward ? 1 : m_largestOrdinal;
     83                 else {
     84                     if (m_ordinalIteration >= m_ordinalValues.size() + 1)
     85                         return 0;
     86 
     87                     // Only copy+sort the values once per layout even if the iterator is reset.
     88                     if (static_cast<size_t>(m_ordinalValues.size()) != m_sortedOrdinalValues.size()) {
     89                         copyToVector(m_ordinalValues, m_sortedOrdinalValues);
     90                         sort(m_sortedOrdinalValues.begin(), m_sortedOrdinalValues.end());
     91                     }
     92                     m_currentOrdinal = m_forward ? m_sortedOrdinalValues[m_ordinalIteration - 1] : m_sortedOrdinalValues[m_sortedOrdinalValues.size() - m_ordinalIteration];
     93                 }
     94 
     95                 m_currentChild = m_forward ? m_box->firstChildBox() : m_box->lastChildBox();
     96             } else
     97                 m_currentChild = m_forward ? m_currentChild->nextSiblingBox() : m_currentChild->previousSiblingBox();
     98 
     99             if (m_currentChild && notFirstOrdinalValue())
    100                 m_ordinalValues.add(m_currentChild->style()->boxOrdinalGroup());
    101         } while (!m_currentChild || (!m_currentChild->isAnonymous()
    102                  && m_currentChild->style()->boxOrdinalGroup() != m_currentOrdinal));
    103         return m_currentChild;
    104     }
    105 
    106 private:
    107     bool notFirstOrdinalValue()
    108     {
    109         unsigned int firstOrdinalValue = m_forward ? 1 : m_largestOrdinal;
    110         return m_currentOrdinal == firstOrdinalValue && m_currentChild->style()->boxOrdinalGroup() != firstOrdinalValue;
    111     }
    112 
    113     RenderDeprecatedFlexibleBox* m_box;
    114     RenderBox* m_currentChild;
    115     bool m_forward;
    116     unsigned int m_currentOrdinal;
    117     unsigned int m_largestOrdinal;
    118     HashSet<unsigned int> m_ordinalValues;
    119     Vector<unsigned int> m_sortedOrdinalValues;
    120     int m_ordinalIteration;
    121 };
    122 
    123 RenderDeprecatedFlexibleBox::RenderDeprecatedFlexibleBox(Element* element)
    124     : RenderBlock(element)
    125 {
    126     setChildrenInline(false); // All of our children must be block-level
    127     m_stretchingChildren = false;
    128     if (!isAnonymous()) {
    129         const KURL& url = document()->url();
    130         if (url.protocolIs("chrome"))
    131             UseCounter::count(document(), UseCounter::DeprecatedFlexboxChrome);
    132         else if (url.protocolIs("chrome-extension"))
    133             UseCounter::count(document(), UseCounter::DeprecatedFlexboxChromeExtension);
    134         else
    135             UseCounter::count(document(), UseCounter::DeprecatedFlexboxWebContent);
    136     }
    137 }
    138 
    139 RenderDeprecatedFlexibleBox::~RenderDeprecatedFlexibleBox()
    140 {
    141 }
    142 
    143 RenderDeprecatedFlexibleBox* RenderDeprecatedFlexibleBox::createAnonymous(Document* document)
    144 {
    145     RenderDeprecatedFlexibleBox* renderer = new RenderDeprecatedFlexibleBox(0);
    146     renderer->setDocumentForAnonymous(document);
    147     return renderer;
    148 }
    149 
    150 static LayoutUnit marginWidthForChild(RenderBox* child)
    151 {
    152     // A margin basically has three types: fixed, percentage, and auto (variable).
    153     // Auto and percentage margins simply become 0 when computing min/max width.
    154     // Fixed margins can be added in as is.
    155     Length marginLeft = child->style()->marginLeft();
    156     Length marginRight = child->style()->marginRight();
    157     LayoutUnit margin = 0;
    158     if (marginLeft.isFixed())
    159         margin += marginLeft.value();
    160     if (marginRight.isFixed())
    161         margin += marginRight.value();
    162     return margin;
    163 }
    164 
    165 static bool childDoesNotAffectWidthOrFlexing(RenderObject* child)
    166 {
    167     // Positioned children and collapsed children don't affect the min/max width.
    168     return child->isOutOfFlowPositioned() || child->style()->visibility() == COLLAPSE;
    169 }
    170 
    171 static LayoutUnit contentWidthForChild(RenderBox* child)
    172 {
    173     if (child->hasOverrideWidth())
    174         return child->overrideLogicalContentWidth();
    175     return child->logicalWidth() - child->borderAndPaddingLogicalWidth();
    176 }
    177 
    178 static LayoutUnit contentHeightForChild(RenderBox* child)
    179 {
    180     if (child->hasOverrideHeight())
    181         return child->overrideLogicalContentHeight();
    182     return child->logicalHeight() - child->borderAndPaddingLogicalHeight();
    183 }
    184 
    185 void RenderDeprecatedFlexibleBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
    186 {
    187     RenderStyle* oldStyle = style();
    188     if (oldStyle && !oldStyle->lineClamp().isNone() && newStyle->lineClamp().isNone())
    189         clearLineClamp();
    190 
    191     RenderBlock::styleWillChange(diff, newStyle);
    192 }
    193 
    194 void RenderDeprecatedFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
    195 {
    196     if (hasMultipleLines() || isVertical()) {
    197         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    198             if (childDoesNotAffectWidthOrFlexing(child))
    199                 continue;
    200 
    201             LayoutUnit margin = marginWidthForChild(child);
    202             LayoutUnit width = child->minPreferredLogicalWidth() + margin;
    203             minLogicalWidth = max(width, minLogicalWidth);
    204 
    205             width = child->maxPreferredLogicalWidth() + margin;
    206             maxLogicalWidth = max(width, maxLogicalWidth);
    207         }
    208     } else {
    209         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    210             if (childDoesNotAffectWidthOrFlexing(child))
    211                 continue;
    212 
    213             LayoutUnit margin = marginWidthForChild(child);
    214             minLogicalWidth += child->minPreferredLogicalWidth() + margin;
    215             maxLogicalWidth += child->maxPreferredLogicalWidth() + margin;
    216         }
    217     }
    218 
    219     maxLogicalWidth = max(minLogicalWidth, maxLogicalWidth);
    220 
    221     LayoutUnit scrollbarWidth = instrinsicScrollbarLogicalWidth();
    222     maxLogicalWidth += scrollbarWidth;
    223     minLogicalWidth += scrollbarWidth;
    224 }
    225 
    226 void RenderDeprecatedFlexibleBox::computePreferredLogicalWidths()
    227 {
    228     ASSERT(preferredLogicalWidthsDirty());
    229 
    230     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
    231     if (style()->width().isFixed() && style()->width().value() > 0)
    232         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
    233     else
    234         computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
    235 
    236     if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
    237         m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
    238         m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
    239     }
    240 
    241     if (style()->maxWidth().isFixed()) {
    242         m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
    243         m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
    244     }
    245 
    246     LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
    247     m_minPreferredLogicalWidth += borderAndPadding;
    248     m_maxPreferredLogicalWidth += borderAndPadding;
    249 
    250     setPreferredLogicalWidthsDirty(false);
    251 }
    252 
    253 void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
    254 {
    255     ASSERT(needsLayout());
    256 
    257     if (!relayoutChildren && simplifiedLayout())
    258         return;
    259 
    260     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
    261     LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
    262 
    263     // Regions changing widths can force us to relayout our children.
    264     RenderFlowThread* flowThread = flowThreadContainingBlock();
    265     if (logicalWidthChangedInRegions(flowThread))
    266         relayoutChildren = true;
    267     if (updateRegionsAndShapesLogicalSize(flowThread))
    268         relayoutChildren = true;
    269 
    270     LayoutSize previousSize = size();
    271 
    272     updateLogicalWidth();
    273     updateLogicalHeight();
    274 
    275     if (previousSize != size()
    276         || (parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
    277         && parent()->style()->boxAlign() == BSTRETCH))
    278         relayoutChildren = true;
    279 
    280     setHeight(0);
    281 
    282     m_stretchingChildren = false;
    283 
    284     initMaxMarginValues();
    285 
    286     if (isHorizontal())
    287         layoutHorizontalBox(relayoutChildren);
    288     else
    289         layoutVerticalBox(relayoutChildren);
    290 
    291     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
    292     updateLogicalHeight();
    293 
    294     if (previousSize.height() != height())
    295         relayoutChildren = true;
    296 
    297     layoutPositionedObjects(relayoutChildren || isRoot());
    298 
    299     computeRegionRangeForBlock(flowThread);
    300 
    301     if (!isFloatingOrOutOfFlowPositioned() && height() == 0) {
    302         // We are a block with no border and padding and a computed height
    303         // of 0.  The CSS spec states that zero-height blocks collapse their margins
    304         // together.
    305         // When blocks are self-collapsing, we just use the top margin values and set the
    306         // bottom margin max values to 0.  This way we don't factor in the values
    307         // twice when we collapse with our previous vertically adjacent and
    308         // following vertically adjacent blocks.
    309         LayoutUnit pos = maxPositiveMarginBefore();
    310         LayoutUnit neg = maxNegativeMarginBefore();
    311         if (maxPositiveMarginAfter() > pos)
    312             pos = maxPositiveMarginAfter();
    313         if (maxNegativeMarginAfter() > neg)
    314             neg = maxNegativeMarginAfter();
    315         setMaxMarginBeforeValues(pos, neg);
    316         setMaxMarginAfterValues(0, 0);
    317     }
    318 
    319     computeOverflow(oldClientAfterEdge);
    320 
    321     statePusher.pop();
    322 
    323     updateLayerTransform();
    324 
    325     if (view()->layoutState()->pageLogicalHeight())
    326         setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
    327 
    328     // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
    329     // we overflow or not.
    330     if (hasOverflowClip())
    331         layer()->updateScrollInfoAfterLayout();
    332 
    333     // Repaint with our new bounds if they are different from our old bounds.
    334     repainter.repaintAfterLayout();
    335 
    336     clearNeedsLayout();
    337 }
    338 
    339 // The first walk over our kids is to find out if we have any flexible children.
    340 static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChildren, unsigned int& highestFlexGroup, unsigned int& lowestFlexGroup, bool& haveFlex)
    341 {
    342     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    343         // Check to see if this child flexes.
    344         if (!childDoesNotAffectWidthOrFlexing(child) && child->style()->boxFlex() > 0.0f) {
    345             // We always have to lay out flexible objects again, since the flex distribution
    346             // may have changed, and we need to reallocate space.
    347             child->clearOverrideSize();
    348             if (!relayoutChildren)
    349                 child->setChildNeedsLayout(MarkOnlyThis);
    350             haveFlex = true;
    351             unsigned int flexGroup = child->style()->boxFlexGroup();
    352             if (lowestFlexGroup == 0)
    353                 lowestFlexGroup = flexGroup;
    354             if (flexGroup < lowestFlexGroup)
    355                 lowestFlexGroup = flexGroup;
    356             if (flexGroup > highestFlexGroup)
    357                 highestFlexGroup = flexGroup;
    358         }
    359     }
    360 }
    361 
    362 void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
    363 {
    364     LayoutUnit toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
    365     LayoutUnit yPos = borderTop() + paddingTop();
    366     LayoutUnit xPos = borderLeft() + paddingLeft();
    367     bool heightSpecified = false;
    368     LayoutUnit oldHeight = 0;
    369 
    370     LayoutUnit remainingSpace = 0;
    371 
    372 
    373     FlexBoxIterator iterator(this);
    374     unsigned int highestFlexGroup = 0;
    375     unsigned int lowestFlexGroup = 0;
    376     bool haveFlex = false, flexingChildren = false;
    377     gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
    378 
    379     RenderBlock::startDelayUpdateScrollInfo();
    380 
    381     // We do 2 passes.  The first pass is simply to lay everyone out at
    382     // their preferred widths.  The second pass handles flexing the children.
    383     do {
    384         // Reset our height.
    385         setHeight(yPos);
    386 
    387         xPos = borderLeft() + paddingLeft();
    388 
    389         // Our first pass is done without flexing.  We simply lay the children
    390         // out within the box.  We have to do a layout first in order to determine
    391         // our box's intrinsic height.
    392         LayoutUnit maxAscent = 0, maxDescent = 0;
    393         for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    394             // make sure we relayout children if we need it.
    395             if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
    396                 child->setChildNeedsLayout(MarkOnlyThis);
    397 
    398             if (child->isOutOfFlowPositioned())
    399                 continue;
    400 
    401             // Compute the child's vertical margins.
    402             child->computeAndSetBlockDirectionMargins(this);
    403 
    404             if (!child->needsLayout())
    405                 child->markForPaginationRelayoutIfNeeded();
    406 
    407             // Now do the layout.
    408             child->layoutIfNeeded();
    409 
    410             // Update our height and overflow height.
    411             if (style()->boxAlign() == BBASELINE) {
    412                 LayoutUnit ascent = child->firstLineBoxBaseline();
    413                 if (ascent == -1)
    414                     ascent = child->height() + child->marginBottom();
    415                 ascent += child->marginTop();
    416                 LayoutUnit descent = (child->height() + child->marginHeight()) - ascent;
    417 
    418                 // Update our maximum ascent.
    419                 maxAscent = max(maxAscent, ascent);
    420 
    421                 // Update our maximum descent.
    422                 maxDescent = max(maxDescent, descent);
    423 
    424                 // Now update our height.
    425                 setHeight(max(yPos + maxAscent + maxDescent, height()));
    426             }
    427             else
    428                 setHeight(max(height(), yPos + child->height() + child->marginHeight()));
    429         }
    430 
    431         if (!iterator.first() && hasLineIfEmpty())
    432             setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
    433 
    434         setHeight(height() + toAdd);
    435 
    436         oldHeight = height();
    437         updateLogicalHeight();
    438 
    439         relayoutChildren = false;
    440         if (oldHeight != height())
    441             heightSpecified = true;
    442 
    443         // Now that our height is actually known, we can place our boxes.
    444         m_stretchingChildren = (style()->boxAlign() == BSTRETCH);
    445         for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    446             if (child->isOutOfFlowPositioned()) {
    447                 child->containingBlock()->insertPositionedObject(child);
    448                 RenderLayer* childLayer = child->layer();
    449                 childLayer->setStaticInlinePosition(xPos); // FIXME: Not right for regions.
    450                 if (childLayer->staticBlockPosition() != yPos) {
    451                     childLayer->setStaticBlockPosition(yPos);
    452                     if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
    453                         child->setChildNeedsLayout(MarkOnlyThis);
    454                 }
    455                 continue;
    456             }
    457 
    458             if (child->style()->visibility() == COLLAPSE) {
    459                 // visibility: collapsed children do not participate in our positioning.
    460                 // But we need to lay them down.
    461                 child->layoutIfNeeded();
    462                 continue;
    463             }
    464 
    465 
    466             // We need to see if this child's height has changed, since we make block elements
    467             // fill the height of a containing box by default.
    468             // Now do a layout.
    469             LayoutUnit oldChildHeight = child->height();
    470             child->updateLogicalHeight();
    471             if (oldChildHeight != child->height())
    472                 child->setChildNeedsLayout(MarkOnlyThis);
    473 
    474             if (!child->needsLayout())
    475                 child->markForPaginationRelayoutIfNeeded();
    476 
    477             child->layoutIfNeeded();
    478 
    479             // We can place the child now, using our value of box-align.
    480             xPos += child->marginLeft();
    481             LayoutUnit childY = yPos;
    482             switch (style()->boxAlign()) {
    483                 case BCENTER:
    484                     childY += child->marginTop() + max<LayoutUnit>(0, (contentHeight() - (child->height() + child->marginHeight())) / 2);
    485                     break;
    486                 case BBASELINE: {
    487                     LayoutUnit ascent = child->firstLineBoxBaseline();
    488                     if (ascent == -1)
    489                         ascent = child->height() + child->marginBottom();
    490                     ascent += child->marginTop();
    491                     childY += child->marginTop() + (maxAscent - ascent);
    492                     break;
    493                 }
    494                 case BEND:
    495                     childY += contentHeight() - child->marginBottom() - child->height();
    496                     break;
    497                 default: // BSTART
    498                     childY += child->marginTop();
    499                     break;
    500             }
    501 
    502             placeChild(child, LayoutPoint(xPos, childY));
    503 
    504             xPos += child->width() + child->marginRight();
    505         }
    506 
    507         remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos;
    508 
    509         m_stretchingChildren = false;
    510         if (flexingChildren)
    511             haveFlex = false; // We're done.
    512         else if (haveFlex) {
    513             // We have some flexible objects.  See if we need to grow/shrink them at all.
    514             if (!remainingSpace)
    515                 break;
    516 
    517             // Allocate the remaining space among the flexible objects.  If we are trying to
    518             // grow, then we go from the lowest flex group to the highest flex group.  For shrinking,
    519             // we go from the highest flex group to the lowest group.
    520             bool expanding = remainingSpace > 0;
    521             unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
    522             unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
    523             for (unsigned int i = start; i <= end && remainingSpace; i++) {
    524                 // Always start off by assuming the group can get all the remaining space.
    525                 LayoutUnit groupRemainingSpace = remainingSpace;
    526                 do {
    527                     // Flexing consists of multiple passes, since we have to change ratios every time an object hits its max/min-width
    528                     // For a given pass, we always start off by computing the totalFlex of all objects that can grow/shrink at all, and
    529                     // computing the allowed growth before an object hits its min/max width (and thus
    530                     // forces a totalFlex recomputation).
    531                     LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace;
    532                     float totalFlex = 0.0f;
    533                     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    534                         if (allowedChildFlex(child, expanding, i))
    535                             totalFlex += child->style()->boxFlex();
    536                     }
    537                     LayoutUnit spaceAvailableThisPass = groupRemainingSpace;
    538                     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    539                         LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i);
    540                         if (allowedFlex) {
    541                             LayoutUnit projectedFlex = (allowedFlex == LayoutUnit::max()) ? allowedFlex : LayoutUnit(allowedFlex * (totalFlex / child->style()->boxFlex()));
    542                             spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
    543                         }
    544                     }
    545 
    546                     // The flex groups may not have any flexible objects this time around.
    547                     if (!spaceAvailableThisPass || totalFlex == 0.0f) {
    548                         // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group.
    549                         groupRemainingSpace = 0;
    550                         continue;
    551                     }
    552 
    553                     // Now distribute the space to objects.
    554                     for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) {
    555                         if (child->style()->visibility() == COLLAPSE)
    556                             continue;
    557 
    558                         if (allowedChildFlex(child, expanding, i)) {
    559                             LayoutUnit spaceAdd = LayoutUnit(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex));
    560                             if (spaceAdd) {
    561                                 child->setOverrideLogicalContentWidth(contentWidthForChild(child) + spaceAdd);
    562                                 flexingChildren = true;
    563                                 relayoutChildren = true;
    564                             }
    565 
    566                             spaceAvailableThisPass -= spaceAdd;
    567                             remainingSpace -= spaceAdd;
    568                             groupRemainingSpace -= spaceAdd;
    569 
    570                             totalFlex -= child->style()->boxFlex();
    571                         }
    572                     }
    573                     if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
    574                         // This is not advancing, avoid getting stuck by distributing the remaining pixels.
    575                         LayoutUnit spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
    576                         for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) {
    577                             if (allowedChildFlex(child, expanding, i)) {
    578                                 child->setOverrideLogicalContentWidth(contentWidthForChild(child) + spaceAdd);
    579                                 flexingChildren = true;
    580                                 relayoutChildren = true;
    581                                 remainingSpace -= spaceAdd;
    582                                 groupRemainingSpace -= spaceAdd;
    583                             }
    584                         }
    585                     }
    586                 } while (absoluteValue(groupRemainingSpace) >= 1);
    587             }
    588 
    589             // We didn't find any children that could grow.
    590             if (haveFlex && !flexingChildren)
    591                 haveFlex = false;
    592         }
    593     } while (haveFlex);
    594 
    595     RenderBlock::finishDelayUpdateScrollInfo();
    596 
    597     if (remainingSpace > 0 && ((style()->isLeftToRightDirection() && style()->boxPack() != Start)
    598         || (!style()->isLeftToRightDirection() && style()->boxPack() != End))) {
    599         // Children must be repositioned.
    600         LayoutUnit offset = 0;
    601         if (style()->boxPack() == Justify) {
    602             // Determine the total number of children.
    603             int totalChildren = 0;
    604             for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    605                 if (childDoesNotAffectWidthOrFlexing(child))
    606                     continue;
    607                 ++totalChildren;
    608             }
    609 
    610             // Iterate over the children and space them out according to the
    611             // justification level.
    612             if (totalChildren > 1) {
    613                 --totalChildren;
    614                 bool firstChild = true;
    615                 for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    616                     if (childDoesNotAffectWidthOrFlexing(child))
    617                         continue;
    618 
    619                     if (firstChild) {
    620                         firstChild = false;
    621                         continue;
    622                     }
    623 
    624                     offset += remainingSpace/totalChildren;
    625                     remainingSpace -= (remainingSpace/totalChildren);
    626                     --totalChildren;
    627 
    628                     placeChild(child, child->location() + LayoutSize(offset, 0));
    629                 }
    630             }
    631         } else {
    632             if (style()->boxPack() == Center)
    633                 offset += remainingSpace / 2;
    634             else // END for LTR, START for RTL
    635                 offset += remainingSpace;
    636             for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    637                 if (childDoesNotAffectWidthOrFlexing(child))
    638                     continue;
    639 
    640                 placeChild(child, child->location() + LayoutSize(offset, 0));
    641             }
    642         }
    643     }
    644 
    645     // So that the computeLogicalHeight in layoutBlock() knows to relayout positioned objects because of
    646     // a height change, we revert our height back to the intrinsic height before returning.
    647     if (heightSpecified)
    648         setHeight(oldHeight);
    649 }
    650 
    651 void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
    652 {
    653     LayoutUnit yPos = borderTop() + paddingTop();
    654     LayoutUnit toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
    655     bool heightSpecified = false;
    656     LayoutUnit oldHeight = 0;
    657 
    658     LayoutUnit remainingSpace = 0;
    659 
    660     FlexBoxIterator iterator(this);
    661     unsigned int highestFlexGroup = 0;
    662     unsigned int lowestFlexGroup = 0;
    663     bool haveFlex = false, flexingChildren = false;
    664     gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
    665 
    666     // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of
    667     // mainstream block layout); this is not really part of the XUL box model.
    668     bool haveLineClamp = !style()->lineClamp().isNone();
    669     if (haveLineClamp)
    670         applyLineClamp(iterator, relayoutChildren);
    671 
    672     RenderBlock::startDelayUpdateScrollInfo();
    673 
    674     // We do 2 passes.  The first pass is simply to lay everyone out at
    675     // their preferred widths.  The second pass handles flexing the children.
    676     // Our first pass is done without flexing.  We simply lay the children
    677     // out within the box.
    678     do {
    679         setHeight(borderTop() + paddingTop());
    680         LayoutUnit minHeight = height() + toAdd;
    681 
    682         for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    683             // Make sure we relayout children if we need it.
    684             if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))))
    685                 child->setChildNeedsLayout(MarkOnlyThis);
    686 
    687             if (child->isOutOfFlowPositioned()) {
    688                 child->containingBlock()->insertPositionedObject(child);
    689                 RenderLayer* childLayer = child->layer();
    690                 childLayer->setStaticInlinePosition(borderStart() + paddingStart()); // FIXME: Not right for regions.
    691                 if (childLayer->staticBlockPosition() != height()) {
    692                     childLayer->setStaticBlockPosition(height());
    693                     if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
    694                         child->setChildNeedsLayout(MarkOnlyThis);
    695                 }
    696                 continue;
    697             }
    698 
    699             if (child->style()->visibility() == COLLAPSE) {
    700                 // visibility: collapsed children do not participate in our positioning.
    701                 // But we need to lay them down.
    702                 child->layoutIfNeeded();
    703                 continue;
    704             }
    705 
    706             // Compute the child's vertical margins.
    707             child->computeAndSetBlockDirectionMargins(this);
    708 
    709             // Add in the child's marginTop to our height.
    710             setHeight(height() + child->marginTop());
    711 
    712             if (!child->needsLayout())
    713                 child->markForPaginationRelayoutIfNeeded();
    714 
    715             // Now do a layout.
    716             child->layoutIfNeeded();
    717 
    718             // We can place the child now, using our value of box-align.
    719             LayoutUnit childX = borderLeft() + paddingLeft();
    720             switch (style()->boxAlign()) {
    721                 case BCENTER:
    722                 case BBASELINE: // Baseline just maps to center for vertical boxes
    723                     childX += child->marginLeft() + max<LayoutUnit>(0, (contentWidth() - (child->width() + child->marginWidth())) / 2);
    724                     break;
    725                 case BEND:
    726                     if (!style()->isLeftToRightDirection())
    727                         childX += child->marginLeft();
    728                     else
    729                         childX += contentWidth() - child->marginRight() - child->width();
    730                     break;
    731                 default: // BSTART/BSTRETCH
    732                     if (style()->isLeftToRightDirection())
    733                         childX += child->marginLeft();
    734                     else
    735                         childX += contentWidth() - child->marginRight() - child->width();
    736                     break;
    737             }
    738 
    739             // Place the child.
    740             placeChild(child, LayoutPoint(childX, height()));
    741             setHeight(height() + child->height() + child->marginBottom());
    742         }
    743 
    744         yPos = height();
    745 
    746         if (!iterator.first() && hasLineIfEmpty())
    747             setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
    748 
    749         setHeight(height() + toAdd);
    750 
    751         // Negative margins can cause our height to shrink below our minimal height (border/padding).
    752         // If this happens, ensure that the computed height is increased to the minimal height.
    753         if (height() < minHeight)
    754             setHeight(minHeight);
    755 
    756         // Now we have to calc our height, so we know how much space we have remaining.
    757         oldHeight = height();
    758         updateLogicalHeight();
    759         if (oldHeight != height())
    760             heightSpecified = true;
    761 
    762         remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos;
    763 
    764         if (flexingChildren)
    765             haveFlex = false; // We're done.
    766         else if (haveFlex) {
    767             // We have some flexible objects.  See if we need to grow/shrink them at all.
    768             if (!remainingSpace)
    769                 break;
    770 
    771             // Allocate the remaining space among the flexible objects.  If we are trying to
    772             // grow, then we go from the lowest flex group to the highest flex group.  For shrinking,
    773             // we go from the highest flex group to the lowest group.
    774             bool expanding = remainingSpace > 0;
    775             unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
    776             unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
    777             for (unsigned int i = start; i <= end && remainingSpace; i++) {
    778                 // Always start off by assuming the group can get all the remaining space.
    779                 LayoutUnit groupRemainingSpace = remainingSpace;
    780                 do {
    781                     // Flexing consists of multiple passes, since we have to change ratios every time an object hits its max/min-width
    782                     // For a given pass, we always start off by computing the totalFlex of all objects that can grow/shrink at all, and
    783                     // computing the allowed growth before an object hits its min/max width (and thus
    784                     // forces a totalFlex recomputation).
    785                     LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace;
    786                     float totalFlex = 0.0f;
    787                     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    788                         if (allowedChildFlex(child, expanding, i))
    789                             totalFlex += child->style()->boxFlex();
    790                     }
    791                     LayoutUnit spaceAvailableThisPass = groupRemainingSpace;
    792                     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    793                         LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i);
    794                         if (allowedFlex) {
    795                             LayoutUnit projectedFlex = (allowedFlex == LayoutUnit::max()) ? allowedFlex : static_cast<LayoutUnit>(allowedFlex * (totalFlex / child->style()->boxFlex()));
    796                             spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
    797                         }
    798                     }
    799 
    800                     // The flex groups may not have any flexible objects this time around.
    801                     if (!spaceAvailableThisPass || totalFlex == 0.0f) {
    802                         // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group.
    803                         groupRemainingSpace = 0;
    804                         continue;
    805                     }
    806 
    807                     // Now distribute the space to objects.
    808                     for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) {
    809                         if (allowedChildFlex(child, expanding, i)) {
    810                             LayoutUnit spaceAdd = static_cast<LayoutUnit>(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex));
    811                             if (spaceAdd) {
    812                                 child->setOverrideLogicalContentHeight(contentHeightForChild(child) + spaceAdd);
    813                                 flexingChildren = true;
    814                                 relayoutChildren = true;
    815                             }
    816 
    817                             spaceAvailableThisPass -= spaceAdd;
    818                             remainingSpace -= spaceAdd;
    819                             groupRemainingSpace -= spaceAdd;
    820 
    821                             totalFlex -= child->style()->boxFlex();
    822                         }
    823                     }
    824                     if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
    825                         // This is not advancing, avoid getting stuck by distributing the remaining pixels.
    826                         LayoutUnit spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
    827                         for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) {
    828                             if (allowedChildFlex(child, expanding, i)) {
    829                                 child->setOverrideLogicalContentHeight(contentHeightForChild(child) + spaceAdd);
    830                                 flexingChildren = true;
    831                                 relayoutChildren = true;
    832                                 remainingSpace -= spaceAdd;
    833                                 groupRemainingSpace -= spaceAdd;
    834                             }
    835                         }
    836                     }
    837                 } while (absoluteValue(groupRemainingSpace) >= 1);
    838             }
    839 
    840             // We didn't find any children that could grow.
    841             if (haveFlex && !flexingChildren)
    842                 haveFlex = false;
    843         }
    844     } while (haveFlex);
    845 
    846     RenderBlock::finishDelayUpdateScrollInfo();
    847 
    848     if (style()->boxPack() != Start && remainingSpace > 0) {
    849         // Children must be repositioned.
    850         LayoutUnit offset = 0;
    851         if (style()->boxPack() == Justify) {
    852             // Determine the total number of children.
    853             int totalChildren = 0;
    854             for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    855                 if (childDoesNotAffectWidthOrFlexing(child))
    856                     continue;
    857 
    858                 ++totalChildren;
    859             }
    860 
    861             // Iterate over the children and space them out according to the
    862             // justification level.
    863             if (totalChildren > 1) {
    864                 --totalChildren;
    865                 bool firstChild = true;
    866                 for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    867                     if (childDoesNotAffectWidthOrFlexing(child))
    868                         continue;
    869 
    870                     if (firstChild) {
    871                         firstChild = false;
    872                         continue;
    873                     }
    874 
    875                     offset += remainingSpace/totalChildren;
    876                     remainingSpace -= (remainingSpace/totalChildren);
    877                     --totalChildren;
    878                     placeChild(child, child->location() + LayoutSize(0, offset));
    879                 }
    880             }
    881         } else {
    882             if (style()->boxPack() == Center)
    883                 offset += remainingSpace / 2;
    884             else // END
    885                 offset += remainingSpace;
    886             for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    887                 if (childDoesNotAffectWidthOrFlexing(child))
    888                     continue;
    889                 placeChild(child, child->location() + LayoutSize(0, offset));
    890             }
    891         }
    892     }
    893 
    894     // So that the computeLogicalHeight in layoutBlock() knows to relayout positioned objects because of
    895     // a height change, we revert our height back to the intrinsic height before returning.
    896     if (heightSpecified)
    897         setHeight(oldHeight);
    898 }
    899 
    900 void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutChildren)
    901 {
    902     UseCounter::count(document(), UseCounter::LineClamp);
    903 
    904     int maxLineCount = 0;
    905     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    906         if (childDoesNotAffectWidthOrFlexing(child))
    907             continue;
    908 
    909         child->clearOverrideSize();
    910         if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))
    911             || (child->style()->height().isAuto() && child->isBlockFlow())) {
    912             child->setChildNeedsLayout(MarkOnlyThis);
    913 
    914             // Dirty all the positioned objects.
    915             if (child->isRenderBlock()) {
    916                 toRenderBlock(child)->markPositionedObjectsForLayout();
    917                 toRenderBlock(child)->clearTruncation();
    918             }
    919         }
    920         child->layoutIfNeeded();
    921         if (child->style()->height().isAuto() && child->isBlockFlow())
    922             maxLineCount = max(maxLineCount, toRenderBlock(child)->lineCount());
    923     }
    924 
    925     // Get the number of lines and then alter all block flow children with auto height to use the
    926     // specified height. We always try to leave room for at least one line.
    927     LineClampValue lineClamp = style()->lineClamp();
    928     int numVisibleLines = lineClamp.isPercentage() ? max(1, (maxLineCount + 1) * lineClamp.value() / 100) : lineClamp.value();
    929     if (numVisibleLines >= maxLineCount)
    930         return;
    931 
    932     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
    933         if (childDoesNotAffectWidthOrFlexing(child) || !child->style()->height().isAuto() || !child->isBlockFlow())
    934             continue;
    935 
    936         RenderBlock* blockChild = toRenderBlock(child);
    937         int lineCount = blockChild->lineCount();
    938         if (lineCount <= numVisibleLines)
    939             continue;
    940 
    941         LayoutUnit newHeight = blockChild->heightForLineCount(numVisibleLines);
    942         if (newHeight == child->height())
    943             continue;
    944 
    945         child->setOverrideLogicalContentHeight(newHeight - child->borderAndPaddingHeight());
    946         child->forceChildLayout();
    947 
    948         // FIXME: For now don't support RTL.
    949         if (style()->direction() != LTR)
    950             continue;
    951 
    952         // Get the last line
    953         RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount - 1);
    954         if (!lastLine)
    955             continue;
    956 
    957         RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines - 1);
    958         if (!lastVisibleLine)
    959             continue;
    960 
    961         const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' };
    962         DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace, 2));
    963         DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
    964         const Font& font = style(numVisibleLines == 1)->font();
    965 
    966         // Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too
    967         LayoutUnit totalWidth;
    968         InlineBox* anchorBox = lastLine->lastChild();
    969         if (anchorBox && anchorBox->renderer()->style()->isLink())
    970             totalWidth = anchorBox->logicalWidth() + font.width(constructTextRun(this, font, ellipsisAndSpace, 2, style()));
    971         else {
    972             anchorBox = 0;
    973             totalWidth = font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style()));
    974         }
    975 
    976         // See if this width can be accommodated on the last visible line
    977         RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer());
    978         RenderBlock* srcBlock = toRenderBlock(lastLine->renderer());
    979 
    980         // FIXME: Directions of src/destBlock could be different from our direction and from one another.
    981         if (!srcBlock->style()->isLeftToRightDirection())
    982             continue;
    983 
    984         bool leftToRight = destBlock->style()->isLeftToRightDirection();
    985         if (!leftToRight)
    986             continue;
    987 
    988         LayoutUnit blockRightEdge = destBlock->logicalRightOffsetForLine(lastVisibleLine->y(), false);
    989         if (!lastVisibleLine->lineCanAccommodateEllipsis(leftToRight, blockRightEdge, lastVisibleLine->x() + lastVisibleLine->logicalWidth(), totalWidth))
    990             continue;
    991 
    992         // Let the truncation code kick in.
    993         // FIXME: the text alignment should be recomputed after the width changes due to truncation.
    994         LayoutUnit blockLeftEdge = destBlock->logicalLeftOffsetForLine(lastVisibleLine->y(), false);
    995         lastVisibleLine->placeEllipsis(anchorBox ? ellipsisAndSpaceStr : ellipsisStr, leftToRight, blockLeftEdge, blockRightEdge, totalWidth, anchorBox);
    996         destBlock->setHasMarkupTruncation(true);
    997     }
    998 }
    999 
   1000 void RenderDeprecatedFlexibleBox::clearLineClamp()
   1001 {
   1002     FlexBoxIterator iterator(this);
   1003     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
   1004         if (childDoesNotAffectWidthOrFlexing(child))
   1005             continue;
   1006 
   1007         child->clearOverrideSize();
   1008         if ((child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))
   1009             || (child->style()->height().isAuto() && child->isBlockFlow())) {
   1010             child->setChildNeedsLayout();
   1011 
   1012             if (child->isRenderBlock()) {
   1013                 toRenderBlock(child)->markPositionedObjectsForLayout();
   1014                 toRenderBlock(child)->clearTruncation();
   1015             }
   1016         }
   1017     }
   1018 }
   1019 
   1020 void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint& location)
   1021 {
   1022     LayoutRect oldRect = child->frameRect();
   1023 
   1024     // Place the child.
   1025     child->setLocation(location);
   1026 
   1027     // If the child moved, we have to repaint it as well as any floating/positioned
   1028     // descendants.  An exception is if we need a layout.  In this case, we know we're going to
   1029     // repaint ourselves (and the child) anyway.
   1030     if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
   1031         child->repaintDuringLayoutIfMoved(oldRect);
   1032 }
   1033 
   1034 LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsigned int group)
   1035 {
   1036     if (childDoesNotAffectWidthOrFlexing(child) || child->style()->boxFlex() == 0.0f || child->style()->boxFlexGroup() != group)
   1037         return 0;
   1038 
   1039     if (expanding) {
   1040         if (isHorizontal()) {
   1041             // FIXME: For now just handle fixed values.
   1042             LayoutUnit maxWidth = LayoutUnit::max();
   1043             LayoutUnit width = contentWidthForChild(child);
   1044             if (!child->style()->maxWidth().isUndefined() && child->style()->maxWidth().isFixed())
   1045                 maxWidth = child->style()->maxWidth().value();
   1046             else if (child->style()->maxWidth().type() == Intrinsic)
   1047                 maxWidth = child->maxPreferredLogicalWidth();
   1048             else if (child->style()->maxWidth().type() == MinIntrinsic)
   1049                 maxWidth = child->minPreferredLogicalWidth();
   1050             if (maxWidth == LayoutUnit::max())
   1051                 return maxWidth;
   1052             return max<LayoutUnit>(0, maxWidth - width);
   1053         } else {
   1054             // FIXME: For now just handle fixed values.
   1055             LayoutUnit maxHeight = LayoutUnit::max();
   1056             LayoutUnit height = contentHeightForChild(child);
   1057             if (!child->style()->maxHeight().isUndefined() && child->style()->maxHeight().isFixed())
   1058                 maxHeight = child->style()->maxHeight().value();
   1059             if (maxHeight == LayoutUnit::max())
   1060                 return maxHeight;
   1061             return max<LayoutUnit>(0, maxHeight - height);
   1062         }
   1063     }
   1064 
   1065     // FIXME: For now just handle fixed values.
   1066     if (isHorizontal()) {
   1067         LayoutUnit minWidth = child->minPreferredLogicalWidth();
   1068         LayoutUnit width = contentWidthForChild(child);
   1069         if (child->style()->minWidth().isFixed())
   1070             minWidth = child->style()->minWidth().value();
   1071         else if (child->style()->minWidth().type() == Intrinsic)
   1072             minWidth = child->maxPreferredLogicalWidth();
   1073         else if (child->style()->minWidth().type() == MinIntrinsic)
   1074             minWidth = child->minPreferredLogicalWidth();
   1075         else if (child->style()->minWidth().type() == Auto)
   1076             minWidth = 0;
   1077 
   1078         LayoutUnit allowedShrinkage = min<LayoutUnit>(0, minWidth - width);
   1079         return allowedShrinkage;
   1080     } else {
   1081         Length minHeight = child->style()->minHeight();
   1082         if (minHeight.isFixed() || minHeight.isAuto()) {
   1083             LayoutUnit minHeight = child->style()->minHeight().value();
   1084             LayoutUnit height = contentHeightForChild(child);
   1085             LayoutUnit allowedShrinkage = min<LayoutUnit>(0, minHeight - height);
   1086             return allowedShrinkage;
   1087         }
   1088     }
   1089 
   1090     return 0;
   1091 }
   1092 
   1093 const char* RenderDeprecatedFlexibleBox::renderName() const
   1094 {
   1095     if (isFloating())
   1096         return "RenderDeprecatedFlexibleBox (floating)";
   1097     if (isOutOfFlowPositioned())
   1098         return "RenderDeprecatedFlexibleBox (positioned)";
   1099     // FIXME: Temporary hack while the new generated content system is being implemented.
   1100     if (isPseudoElement())
   1101         return "RenderDeprecatedFlexibleBox (generated)";
   1102     if (isAnonymous())
   1103         return "RenderDeprecatedFlexibleBox (generated)";
   1104     if (isRelPositioned())
   1105         return "RenderDeprecatedFlexibleBox (relative positioned)";
   1106     return "RenderDeprecatedFlexibleBox";
   1107 }
   1108 
   1109 } // namespace WebCore
   1110