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