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