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