diff options
| author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
| commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
| tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp | |
| parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
| download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz | |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp')
| -rw-r--r-- | Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp | 243 |
1 files changed, 164 insertions, 79 deletions
diff --git a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp index 3323986c9..3106fc9a2 100644 --- a/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp +++ b/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "RenderDeprecatedFlexibleBox.h" +#include "FeatureObserver.h" #include "Font.h" #include "LayoutRepainter.h" #include "RenderLayer.h" @@ -119,17 +120,33 @@ private: int m_ordinalIteration; }; -RenderDeprecatedFlexibleBox::RenderDeprecatedFlexibleBox(Node* node) - : RenderBlock(node) +RenderDeprecatedFlexibleBox::RenderDeprecatedFlexibleBox(Element* element) + : RenderBlock(element) { setChildrenInline(false); // All of our children must be block-level m_stretchingChildren = false; + if (!isAnonymous()) { + const KURL& url = document()->url(); + if (url.protocolIs("chrome")) + FeatureObserver::observe(document(), FeatureObserver::DeprecatedFlexboxChrome); + else if (url.protocolIs("chrome-extension")) + FeatureObserver::observe(document(), FeatureObserver::DeprecatedFlexboxChromeExtension); + else + FeatureObserver::observe(document(), FeatureObserver::DeprecatedFlexboxWebContent); + } } RenderDeprecatedFlexibleBox::~RenderDeprecatedFlexibleBox() { } +RenderDeprecatedFlexibleBox* RenderDeprecatedFlexibleBox::createAnonymous(Document* document) +{ + RenderDeprecatedFlexibleBox* renderer = new (document->renderArena()) RenderDeprecatedFlexibleBox(0); + renderer->setDocumentForAnonymous(document); + return renderer; +} + static LayoutUnit marginWidthForChild(RenderBox* child) { // A margin basically has three types: fixed, percentage, and auto (variable). @@ -174,56 +191,47 @@ void RenderDeprecatedFlexibleBox::styleWillChange(StyleDifference diff, const Re RenderBlock::styleWillChange(diff, newStyle); } -void RenderDeprecatedFlexibleBox::calcHorizontalPrefWidths() +void RenderDeprecatedFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const { - for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { - if (childDoesNotAffectWidthOrFlexing(child)) - continue; - - LayoutUnit margin = marginWidthForChild(child); - m_minPreferredLogicalWidth += child->minPreferredLogicalWidth() + margin; - m_maxPreferredLogicalWidth += child->maxPreferredLogicalWidth() + margin; - } -} + if (hasMultipleLines() || isVertical()) { + for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { + if (childDoesNotAffectWidthOrFlexing(child)) + continue; -void RenderDeprecatedFlexibleBox::calcVerticalPrefWidths() -{ - for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { - if (childDoesNotAffectWidthOrFlexing(child)) - continue; + LayoutUnit margin = marginWidthForChild(child); + LayoutUnit width = child->minPreferredLogicalWidth() + margin; + minLogicalWidth = max(width, minLogicalWidth); - LayoutUnit margin = marginWidthForChild(child); - LayoutUnit width = child->minPreferredLogicalWidth() + margin; - m_minPreferredLogicalWidth = max(width, m_minPreferredLogicalWidth); + width = child->maxPreferredLogicalWidth() + margin; + maxLogicalWidth = max(width, maxLogicalWidth); + } + } else { + for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { + if (childDoesNotAffectWidthOrFlexing(child)) + continue; - width = child->maxPreferredLogicalWidth() + margin; - m_maxPreferredLogicalWidth = max(width, m_maxPreferredLogicalWidth); + LayoutUnit margin = marginWidthForChild(child); + minLogicalWidth += child->minPreferredLogicalWidth() + margin; + maxLogicalWidth += child->maxPreferredLogicalWidth() + margin; + } } + + maxLogicalWidth = max(minLogicalWidth, maxLogicalWidth); + + LayoutUnit scrollbarWidth = instrinsicScrollbarLogicalWidth(); + maxLogicalWidth += scrollbarWidth; + minLogicalWidth += scrollbarWidth; } void RenderDeprecatedFlexibleBox::computePreferredLogicalWidths() { ASSERT(preferredLogicalWidthsDirty()); + m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0; if (style()->width().isFixed() && style()->width().value() > 0) m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value()); - else { - m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0; - - if (hasMultipleLines() || isVertical()) - calcVerticalPrefWidths(); - else - calcHorizontalPrefWidths(); - - m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth); - } - - if (hasOverflowClip() && style()->overflowY() == OSCROLL) { - layer()->setHasVerticalScrollbar(true); - LayoutUnit scrollbarWidth = verticalScrollbarWidth(); - m_maxPreferredLogicalWidth += scrollbarWidth; - m_minPreferredLogicalWidth += scrollbarWidth; - } + else + computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth); if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) { m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value())); @@ -242,6 +250,47 @@ void RenderDeprecatedFlexibleBox::computePreferredLogicalWidths() setPreferredLogicalWidthsDirty(false); } +// Use an inline capacity of 8, since flexbox containers usually have less than 8 children. +typedef Vector<LayoutRect, 8> ChildFrameRects; +typedef Vector<LayoutSize, 8> ChildLayoutDeltas; + +static void appendChildFrameRects(RenderDeprecatedFlexibleBox* box, ChildFrameRects& childFrameRects) +{ + FlexBoxIterator iterator(box); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (!child->isOutOfFlowPositioned()) + childFrameRects.append(child->frameRect()); + } +} + +static void appendChildLayoutDeltas(RenderDeprecatedFlexibleBox* box, ChildLayoutDeltas& childLayoutDeltas) +{ + FlexBoxIterator iterator(box); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (!child->isOutOfFlowPositioned()) + childLayoutDeltas.append(LayoutSize()); + } +} + +static void repaintChildrenDuringLayoutIfMoved(RenderDeprecatedFlexibleBox* box, const ChildFrameRects& oldChildRects) +{ + size_t childIndex = 0; + FlexBoxIterator iterator(box); + for (RenderBox* child = iterator.first(); child; child = iterator.next()) { + if (child->isOutOfFlowPositioned()) + continue; + + // If the child moved, we have to repaint it as well as any floating/positioned + // descendants. An exception is if we need a layout. In this case, we know we're going to + // repaint ourselves (and the child) anyway. + if (!box->selfNeedsLayout() && child->checkForRepaintDuringLayout()) + child->repaintDuringLayoutIfMoved(oldChildRects[childIndex]); + + ++childIndex; + } + ASSERT(childIndex == oldChildRects.size()); +} + void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit) { ASSERT(needsLayout()); @@ -252,20 +301,18 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit) LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode()); - if (inRenderFlowThread()) { - // Regions changing widths can force us to relayout our children. - if (logicalWidthChangedInRegions()) - relayoutChildren = true; - } - updateRegionsAndExclusionsLogicalSize(); + // Regions changing widths can force us to relayout our children. + RenderFlowThread* flowThread = flowThreadContainingBlock(); + if (logicalWidthChangedInRegions(flowThread)) + relayoutChildren = true; + if (updateRegionsAndShapesBeforeChildLayout(flowThread)) + relayoutChildren = true; LayoutSize previousSize = size(); updateLogicalWidth(); updateLogicalHeight(); - m_overflow.clear(); - if (previousSize != size() || (parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL && parent()->style()->boxAlign() == BSTRETCH)) @@ -277,11 +324,23 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit) initMaxMarginValues(); +#if !ASSERT_DISABLED + LayoutSize oldLayoutDelta = view()->layoutDelta(); +#endif + + ChildFrameRects oldChildRects; + appendChildFrameRects(this, oldChildRects); + + dirtyForLayoutFromPercentageHeightDescendants(); + if (isHorizontal()) layoutHorizontalBox(relayoutChildren); else layoutVerticalBox(relayoutChildren); + repaintChildrenDuringLayoutIfMoved(this, oldChildRects); + ASSERT(view()->layoutDeltaMatches(oldLayoutDelta)); + LayoutUnit oldClientAfterEdge = clientLogicalBottom(); updateLogicalHeight(); @@ -290,7 +349,7 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit) layoutPositionedObjects(relayoutChildren || isRoot()); - computeRegionRangeForBlock(); + updateRegionsAndShapesAfterChildLayout(flowThread); if (!isFloatingOrOutOfFlowPositioned() && height() == 0) { // We are a block with no border and padding and a computed height @@ -321,8 +380,7 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit) // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if // we overflow or not. - if (hasOverflowClip()) - layer()->updateScrollInfoAfterLayout(); + updateScrollInfoAfterLayout(); // Repaint with our new bounds if they are different from our old bounds. repainter.repaintAfterLayout(); @@ -353,6 +411,16 @@ static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChild } } +static void layoutChildIfNeededApplyingDelta(RenderBox* child, const LayoutSize& layoutDelta) +{ + if (!child->needsLayout()) + return; + + child->view()->addLayoutDelta(layoutDelta); + child->layoutIfNeeded(); + child->view()->addLayoutDelta(-layoutDelta); +} + void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) { LayoutUnit toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight(); @@ -363,43 +431,52 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) LayoutUnit remainingSpace = 0; - FlexBoxIterator iterator(this); unsigned int highestFlexGroup = 0; unsigned int lowestFlexGroup = 0; - bool haveFlex = false, flexingChildren = false; + bool haveFlex = false, flexingChildren = false; gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex); RenderBlock::startDelayUpdateScrollInfo(); + ChildLayoutDeltas childLayoutDeltas; + appendChildLayoutDeltas(this, childLayoutDeltas); + // We do 2 passes. The first pass is simply to lay everyone out at - // their preferred widths. The second pass handles flexing the children. + // their preferred widths. The subsequent passes handle flexing the children. + // The first pass skips flexible objects completely. do { // Reset our height. setHeight(yPos); xPos = borderLeft() + paddingLeft(); + size_t childIndex = 0; + // Our first pass is done without flexing. We simply lay the children // out within the box. We have to do a layout first in order to determine // our box's intrinsic height. LayoutUnit maxAscent = 0, maxDescent = 0; for (RenderBox* child = iterator.first(); child; child = iterator.next()) { - // make sure we relayout children if we need it. - if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))) + if (relayoutChildren) child->setChildNeedsLayout(true, MarkOnlyThis); if (child->isOutOfFlowPositioned()) continue; - + + LayoutSize& childLayoutDelta = childLayoutDeltas[childIndex++]; + // Compute the child's vertical margins. child->computeAndSetBlockDirectionMargins(this); if (!child->needsLayout()) child->markForPaginationRelayoutIfNeeded(); - + + // Apply the child's current layout delta. + layoutChildIfNeededApplyingDelta(child, childLayoutDelta); + // Now do the layout. - child->layoutIfNeeded(); + layoutChildIfNeededApplyingDelta(child, childLayoutDelta); // Update our height and overflow height. if (style()->boxAlign() == BBASELINE) { @@ -421,6 +498,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) else setHeight(max(height(), yPos + child->height() + child->marginHeight())); } + ASSERT(childIndex == childLayoutDeltas.size()); if (!iterator.first() && hasLineIfEmpty()) setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)); @@ -435,6 +513,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) heightSpecified = true; // Now that our height is actually known, we can place our boxes. + childIndex = 0; m_stretchingChildren = (style()->boxAlign() == BSTRETCH); for (RenderBox* child = iterator.first(); child; child = iterator.next()) { if (child->isOutOfFlowPositioned()) { @@ -449,14 +528,15 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) continue; } + LayoutSize& childLayoutDelta = childLayoutDeltas[childIndex++]; + if (child->style()->visibility() == COLLAPSE) { // visibility: collapsed children do not participate in our positioning. - // But we need to lay them down. - child->layoutIfNeeded(); + // But we need to lay them out. + layoutChildIfNeededApplyingDelta(child, childLayoutDelta); continue; } - // We need to see if this child's height has changed, since we make block elements // fill the height of a containing box by default. // Now do a layout. @@ -468,7 +548,7 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) if (!child->needsLayout()) child->markForPaginationRelayoutIfNeeded(); - child->layoutIfNeeded(); + layoutChildIfNeededApplyingDelta(child, childLayoutDelta); // We can place the child now, using our value of box-align. xPos += child->marginLeft(); @@ -493,10 +573,11 @@ void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren) break; } - placeChild(child, LayoutPoint(xPos, childY)); + placeChild(child, LayoutPoint(xPos, childY), &childLayoutDelta); xPos += child->width() + child->marginRight(); } + ASSERT(childIndex == childLayoutDeltas.size()); remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos; @@ -654,7 +735,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) FlexBoxIterator iterator(this); unsigned int highestFlexGroup = 0; unsigned int lowestFlexGroup = 0; - bool haveFlex = false, flexingChildren = false; + bool haveFlex = false, flexingChildren = false; gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex); // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of @@ -665,6 +746,9 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) RenderBlock::startDelayUpdateScrollInfo(); + ChildLayoutDeltas childLayoutDeltas; + appendChildLayoutDeltas(this, childLayoutDeltas); + // We do 2 passes. The first pass is simply to lay everyone out at // their preferred widths. The second pass handles flexing the children. // Our first pass is done without flexing. We simply lay the children @@ -673,9 +757,10 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) setHeight(borderTop() + paddingTop()); LayoutUnit minHeight = height() + toAdd; + size_t childIndex = 0; for (RenderBox* child = iterator.first(); child; child = iterator.next()) { // Make sure we relayout children if we need it. - if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))) + if (!haveLineClamp && relayoutChildren) child->setChildNeedsLayout(true, MarkOnlyThis); if (child->isOutOfFlowPositioned()) { @@ -690,10 +775,12 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) continue; } + LayoutSize& childLayoutDelta = childLayoutDeltas[childIndex++]; + if (child->style()->visibility() == COLLAPSE) { // visibility: collapsed children do not participate in our positioning. // But we need to lay them down. - child->layoutIfNeeded(); + layoutChildIfNeededApplyingDelta(child, childLayoutDelta); continue; } @@ -707,7 +794,7 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) child->markForPaginationRelayoutIfNeeded(); // Now do a layout. - child->layoutIfNeeded(); + layoutChildIfNeededApplyingDelta(child, childLayoutDelta); // We can place the child now, using our value of box-align. LayoutUnit childX = borderLeft() + paddingLeft(); @@ -731,9 +818,10 @@ void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) } // Place the child. - placeChild(child, LayoutPoint(childX, height())); + placeChild(child, LayoutPoint(childX, height()), &childLayoutDelta); setHeight(height() + child->height() + child->marginBottom()); } + ASSERT(childIndex == childLayoutDeltas.size()); yPos = height(); @@ -1010,18 +1098,12 @@ void RenderDeprecatedFlexibleBox::clearLineClamp() } } -void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint& location) +void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint& location, LayoutSize* childLayoutDelta) { - LayoutRect oldRect = child->frameRect(); - - // Place the child. + // Place the child and track the layout delta so we can apply it if we do another layout. + if (childLayoutDelta) + *childLayoutDelta += LayoutSize(child->x() - location.x(), child->y() - location.y()); child->setLocation(location); - - // If the child moved, we have to repaint it as well as any floating/positioned - // descendants. An exception is if we need a layout. In this case, we know we're going to - // repaint ourselves (and the child) anyway. - if (!selfNeedsLayout() && child->checkForRepaintDuringLayout()) - child->repaintDuringLayoutIfMoved(oldRect); } LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsigned int group) @@ -1083,12 +1165,15 @@ LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool return 0; } -const char *RenderDeprecatedFlexibleBox::renderName() const +const char* RenderDeprecatedFlexibleBox::renderName() const { if (isFloating()) return "RenderDeprecatedFlexibleBox (floating)"; if (isOutOfFlowPositioned()) return "RenderDeprecatedFlexibleBox (positioned)"; + // FIXME: Temporary hack while the new generated content system is being implemented. + if (isPseudoElement()) + return "RenderDeprecatedFlexibleBox (generated)"; if (isAnonymous()) return "RenderDeprecatedFlexibleBox (generated)"; if (isRelPositioned()) |
