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