Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / core / layout / LayoutFlowThread.cpp
blob63b33d97fe15ea51bc9daa7388659bbdd6a98480
1 /*
2 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials
14 * provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 #include "config.h"
32 #include "core/layout/LayoutFlowThread.h"
34 #include "core/layout/LayoutMultiColumnSet.h"
35 #include "core/layout/LayoutView.h"
37 namespace blink {
39 LayoutFlowThread::LayoutFlowThread()
40 : LayoutBlockFlow(nullptr)
41 , m_columnSetsInvalidated(false)
42 , m_pageLogicalSizeChanged(false)
46 LayoutFlowThread* LayoutFlowThread::locateFlowThreadContainingBlockOf(const LayoutObject& descendant)
48 ASSERT(descendant.isInsideFlowThread());
49 LayoutObject* curr = const_cast<LayoutObject*>(&descendant);
50 while (curr) {
51 if (curr->isSVG() && !curr->isSVGRoot())
52 return nullptr;
53 if (curr->isLayoutFlowThread())
54 return toLayoutFlowThread(curr);
55 LayoutObject* container = curr->container();
56 curr = curr->parent();
57 while (curr != container) {
58 if (curr->isLayoutFlowThread()) {
59 // The nearest ancestor flow thread isn't in our containing block chain. Then we
60 // aren't really part of any flow thread, and we should stop looking. This happens
61 // when there are out-of-flow objects or column spanners.
62 return nullptr;
64 curr = curr->parent();
67 return nullptr;
70 void LayoutFlowThread::removeColumnSetFromThread(LayoutMultiColumnSet* columnSet)
72 ASSERT(columnSet);
73 m_multiColumnSetList.remove(columnSet);
74 invalidateColumnSets();
75 // Clear the interval tree right away, instead of leaving it around with dead objects. Not that
76 // anyone _should_ try to access the interval tree when the column sets are marked as invalid,
77 // but this is actually possible if other parts of the engine has bugs that cause us to not lay
78 // out everything that was marked for layout, so that LayoutObject::assertLaidOut() (and a LOT
79 // of other assertions) fails.
80 m_multiColumnSetIntervalTree.clear();
83 void LayoutFlowThread::invalidateColumnSets()
85 if (m_columnSetsInvalidated) {
86 ASSERT(selfNeedsLayout());
87 return;
90 setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::ColumnsChanged);
92 m_columnSetsInvalidated = true;
95 void LayoutFlowThread::validateColumnSets()
97 m_columnSetsInvalidated = false;
98 updateLogicalWidth(); // Called to get the maximum logical width for the columnSet.
99 generateColumnSetIntervalTree();
102 void LayoutFlowThread::mapRectToPaintInvalidationBacking(const LayoutBoxModelObject* paintInvalidationContainer, LayoutRect& rect, const PaintInvalidationState* paintInvalidationState) const
104 ASSERT(paintInvalidationContainer != this); // A flow thread should never be an invalidation container.
105 // |rect| is a layout rectangle, where the block direction coordinate is flipped for writing
106 // mode. fragmentsBoundingBox(), on the other hand, works on physical rectangles, so we need to
107 // flip the rectangle before and after calling it.
108 flipForWritingMode(rect);
109 rect = fragmentsBoundingBox(rect);
110 flipForWritingMode(rect);
111 LayoutBlockFlow::mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, paintInvalidationState);
114 void LayoutFlowThread::layout()
116 m_pageLogicalSizeChanged = m_columnSetsInvalidated && everHadLayout();
117 LayoutBlockFlow::layout();
118 m_pageLogicalSizeChanged = false;
121 void LayoutFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
123 computedValues.m_position = logicalTop;
124 computedValues.m_extent = 0;
126 for (LayoutMultiColumnSetList::const_iterator iter = m_multiColumnSetList.begin(); iter != m_multiColumnSetList.end(); ++iter) {
127 LayoutMultiColumnSet* columnSet = *iter;
128 computedValues.m_extent += columnSet->logicalHeightInFlowThread();
132 bool LayoutFlowThread::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
134 if (hitTestAction == HitTestBlockBackground)
135 return false;
136 return LayoutBlockFlow::nodeAtPoint(result, locationInContainer, accumulatedOffset, hitTestAction);
139 LayoutUnit LayoutFlowThread::pageLogicalHeightForOffset(LayoutUnit offset)
141 LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offset);
142 if (!columnSet)
143 return LayoutUnit();
145 return columnSet->pageLogicalHeightForOffset(offset);
148 LayoutUnit LayoutFlowThread::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule)
150 LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offset);
151 if (!columnSet)
152 return LayoutUnit();
154 return columnSet->pageRemainingLogicalHeightForOffset(offset, pageBoundaryRule);
157 void LayoutFlowThread::generateColumnSetIntervalTree()
159 // FIXME: Optimize not to clear the interval all the time. This implies manually managing the tree nodes lifecycle.
160 m_multiColumnSetIntervalTree.clear();
161 m_multiColumnSetIntervalTree.initIfNeeded();
162 for (auto columnSet : m_multiColumnSetList)
163 m_multiColumnSetIntervalTree.add(MultiColumnSetIntervalTree::createInterval(columnSet->logicalTopInFlowThread(), columnSet->logicalBottomInFlowThread(), columnSet));
166 void LayoutFlowThread::collectLayerFragments(DeprecatedPaintLayerFragments& layerFragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRectInFlowThread)
168 ASSERT(!m_columnSetsInvalidated);
170 LayoutRect dirtyRectInMulticolContainer(dirtyRectInFlowThread);
171 dirtyRectInMulticolContainer.moveBy(location());
173 for (LayoutMultiColumnSetList::const_iterator iter = m_multiColumnSetList.begin(); iter != m_multiColumnSetList.end(); ++iter) {
174 LayoutMultiColumnSet* columnSet = *iter;
175 columnSet->collectLayerFragments(layerFragments, layerBoundingBox, dirtyRectInMulticolContainer);
179 LayoutRect LayoutFlowThread::fragmentsBoundingBox(const LayoutRect& layerBoundingBox) const
181 ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled() || !m_columnSetsInvalidated);
183 LayoutRect result;
184 for (auto* columnSet : m_multiColumnSetList)
185 result.unite(columnSet->fragmentsBoundingBox(layerBoundingBox));
187 return result;
190 void LayoutFlowThread::MultiColumnSetSearchAdapter::collectIfNeeded(const MultiColumnSetInterval& interval)
192 if (m_result)
193 return;
194 if (interval.low() <= m_offset && interval.high() > m_offset)
195 m_result = interval.data();
198 } // namespace blink