1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h"
10 static void copyMarginProperties(ComputedStyle
& placeholderStyle
, const ComputedStyle
& spannerStyle
)
12 // We really only need the block direction margins, but there are no setters for that in
13 // ComputedStyle. Just copy all margin sides. The inline ones don't matter anyway.
14 placeholderStyle
.setMarginLeft(spannerStyle
.marginLeft());
15 placeholderStyle
.setMarginRight(spannerStyle
.marginRight());
16 placeholderStyle
.setMarginTop(spannerStyle
.marginTop());
17 placeholderStyle
.setMarginBottom(spannerStyle
.marginBottom());
20 LayoutMultiColumnSpannerPlaceholder
* LayoutMultiColumnSpannerPlaceholder::createAnonymous(const ComputedStyle
& parentStyle
, LayoutBox
& layoutObjectInFlowThread
)
22 LayoutMultiColumnSpannerPlaceholder
* newSpanner
= new LayoutMultiColumnSpannerPlaceholder(&layoutObjectInFlowThread
);
23 Document
& document
= layoutObjectInFlowThread
.document();
24 newSpanner
->setDocumentForAnonymous(&document
);
25 RefPtr
<ComputedStyle
> newStyle
= ComputedStyle::createAnonymousStyleWithDisplay(parentStyle
, BLOCK
);
26 copyMarginProperties(*newStyle
, layoutObjectInFlowThread
.styleRef());
27 newSpanner
->setStyle(newStyle
);
31 LayoutMultiColumnSpannerPlaceholder::LayoutMultiColumnSpannerPlaceholder(LayoutBox
* layoutObjectInFlowThread
)
33 , m_layoutObjectInFlowThread(layoutObjectInFlowThread
)
37 void LayoutMultiColumnSpannerPlaceholder::layoutObjectInFlowThreadStyleDidChange(const ComputedStyle
* oldStyle
)
39 LayoutBox
* objectInFlowThread
= m_layoutObjectInFlowThread
;
40 if (flowThread()->removeSpannerPlaceholderIfNoLongerValid(objectInFlowThread
)) {
41 // No longer a valid spanner, due to style changes. |this| is now dead.
42 if (objectInFlowThread
->style()->hasOutOfFlowPosition() && !oldStyle
->hasOutOfFlowPosition()) {
43 // We went from being a spanner to being out-of-flow positioned. When an object becomes
44 // out-of-flow positioned, we need to lay out its parent, since that's where the
45 // now-out-of-flow object gets added to the right containing block for out-of-flow
46 // positioned objects. Since neither a spanner nor an out-of-flow object is guaranteed
47 // to have this parent in its containing block chain, we need to mark it here, or we
48 // risk that the object isn't laid out.
49 objectInFlowThread
->parent()->setNeedsLayout(LayoutInvalidationReason::ColumnsChanged
);
53 updateMarginProperties();
56 void LayoutMultiColumnSpannerPlaceholder::updateMarginProperties()
58 RefPtr
<ComputedStyle
> newStyle
= ComputedStyle::clone(styleRef());
59 copyMarginProperties(*newStyle
, m_layoutObjectInFlowThread
->styleRef());
63 void LayoutMultiColumnSpannerPlaceholder::willBeRemovedFromTree()
65 if (m_layoutObjectInFlowThread
) {
66 LayoutBox
* exSpanner
= m_layoutObjectInFlowThread
;
67 m_layoutObjectInFlowThread
->clearSpannerPlaceholder();
68 // Even if the placeholder is going away, the object in the flow thread might live on. Since
69 // it's not a spanner anymore, it needs to be relaid out.
70 exSpanner
->setNeedsLayoutAndPrefWidthsRecalc(LayoutInvalidationReason::ColumnsChanged
);
72 LayoutBox::willBeRemovedFromTree();
75 bool LayoutMultiColumnSpannerPlaceholder::needsPreferredWidthsRecalculation() const
77 return m_layoutObjectInFlowThread
->needsPreferredWidthsRecalculation();
80 LayoutUnit
LayoutMultiColumnSpannerPlaceholder::minPreferredLogicalWidth() const
82 return m_layoutObjectInFlowThread
->minPreferredLogicalWidth();
85 LayoutUnit
LayoutMultiColumnSpannerPlaceholder::maxPreferredLogicalWidth() const
87 return m_layoutObjectInFlowThread
->maxPreferredLogicalWidth();
90 void LayoutMultiColumnSpannerPlaceholder::layout()
92 ASSERT(needsLayout());
94 // Lay out the actual column-span:all element.
95 m_layoutObjectInFlowThread
->layoutIfNeeded();
97 // The spanner has now been laid out, so its height is known. Time to update the placeholder's
98 // height as well, so that we take up the correct amount of space in the multicol container.
99 updateLogicalHeight();
101 // Take the overflow from the spanner, so that it gets
102 // propagated to the multicol container and beyond.
104 addVisualOverflow(m_layoutObjectInFlowThread
->visualOverflowRect());
105 addLayoutOverflow(m_layoutObjectInFlowThread
->layoutOverflowRect());
110 void LayoutMultiColumnSpannerPlaceholder::computeLogicalHeight(LayoutUnit
, LayoutUnit logicalTop
, LogicalExtentComputedValues
& computedValues
) const
112 computedValues
.m_extent
= m_layoutObjectInFlowThread
->logicalHeight();
113 computedValues
.m_position
= logicalTop
;
114 computedValues
.m_margins
.m_before
= marginBefore();
115 computedValues
.m_margins
.m_after
= marginAfter();
118 void LayoutMultiColumnSpannerPlaceholder::invalidateTreeIfNeeded(PaintInvalidationState
& paintInvalidationState
)
120 PaintInvalidationState
newPaintInvalidationState(paintInvalidationState
, *this, paintInvalidationState
.paintInvalidationContainer());
121 m_layoutObjectInFlowThread
->invalidateTreeIfNeeded(newPaintInvalidationState
);
122 LayoutBox::invalidateTreeIfNeeded(paintInvalidationState
);
125 void LayoutMultiColumnSpannerPlaceholder::paint(const PaintInfo
& paintInfo
, const LayoutPoint
& paintOffset
)
127 if (!m_layoutObjectInFlowThread
->hasSelfPaintingLayer())
128 m_layoutObjectInFlowThread
->paint(paintInfo
, paintOffset
);
131 bool LayoutMultiColumnSpannerPlaceholder::nodeAtPoint(HitTestResult
& result
, const HitTestLocation
& locationInContainer
, const LayoutPoint
& accumulatedOffset
, HitTestAction action
)
133 return !m_layoutObjectInFlowThread
->hasSelfPaintingLayer() && m_layoutObjectInFlowThread
->nodeAtPoint(result
, locationInContainer
, accumulatedOffset
, action
);