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