OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2012 Apple Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * 1. Redistributions of source code must retain the above copyright | |
8 * notice, this list of conditions and the following disclaimer. | |
9 * 2. Redistributions in binary form must reproduce the above copyright | |
10 * notice, this list of conditions and the following disclaimer in the | |
11 * documentation and/or other materials provided with the distribution. | |
12 * | |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 #include "config.h" | |
27 #include "core/rendering/RenderMultiColumnBlock.h" | |
28 | |
29 #include "core/rendering/RenderMultiColumnFlowThread.h" | |
30 #include "core/rendering/RenderMultiColumnSet.h" | |
31 #include "core/rendering/RenderView.h" | |
32 | |
33 using namespace std; | |
34 | |
35 namespace WebCore { | |
36 | |
37 RenderMultiColumnBlock::RenderMultiColumnBlock(Element* element) | |
38 : RenderBlockFlow(element) | |
39 , m_flowThread(0) | |
40 , m_columnCount(1) | |
41 , m_columnWidth(0) | |
42 , m_columnHeightAvailable(0) | |
43 , m_inBalancingPass(false) | |
44 , m_needsRebalancing(false) | |
45 { | |
46 } | |
47 | |
48 void RenderMultiColumnBlock::styleDidChange(StyleDifference diff, const RenderSt
yle* oldStyle) | |
49 { | |
50 RenderBlockFlow::styleDidChange(diff, oldStyle); | |
51 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBo
x()) | |
52 child->setStyle(RenderStyle::createAnonymousStyleWithDisplay(style(), BL
OCK)); | |
53 } | |
54 | |
55 void RenderMultiColumnBlock::computeColumnCountAndWidth() | |
56 { | |
57 // Calculate our column width and column count. | |
58 // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibli
ng4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744 | |
59 m_columnCount = 1; | |
60 m_columnWidth = contentLogicalWidth(); | |
61 | |
62 ASSERT(!style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth()); | |
63 | |
64 LayoutUnit availWidth = m_columnWidth; | |
65 LayoutUnit colGap = columnGap(); | |
66 LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(style()->columnWidth()))
; | |
67 int colCount = max<int>(1, style()->columnCount()); | |
68 | |
69 if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) { | |
70 m_columnCount = colCount; | |
71 m_columnWidth = max<LayoutUnit>(0, (availWidth - ((m_columnCount - 1) *
colGap)) / m_columnCount); | |
72 } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount())
{ | |
73 m_columnCount = max<LayoutUnit>(1, (availWidth + colGap) / (colWidth + c
olGap)); | |
74 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap; | |
75 } else { | |
76 m_columnCount = max<LayoutUnit>(min<LayoutUnit>(colCount, (availWidth +
colGap) / (colWidth + colGap)), 1); | |
77 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap; | |
78 } | |
79 } | |
80 | |
81 bool RenderMultiColumnBlock::updateLogicalWidthAndColumnWidth() | |
82 { | |
83 bool relayoutChildren = RenderBlockFlow::updateLogicalWidthAndColumnWidth(); | |
84 LayoutUnit oldColumnWidth = m_columnWidth; | |
85 computeColumnCountAndWidth(); | |
86 if (m_columnWidth != oldColumnWidth) | |
87 relayoutChildren = true; | |
88 return relayoutChildren; | |
89 } | |
90 | |
91 void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& /
*pageLogicalHeight*/, bool& /*pageLogicalHeightChanged*/, bool& /*hasSpecifiedPa
geLogicalHeight*/) | |
92 { | |
93 // We don't actually update any of the variables. We just subclassed to adju
st our column height. | |
94 updateLogicalHeight(); | |
95 m_columnHeightAvailable = max<LayoutUnit>(contentLogicalHeight(), 0); | |
96 setLogicalHeight(0); | |
97 } | |
98 | |
99 bool RenderMultiColumnBlock::shouldRelayoutMultiColumnBlock() | |
100 { | |
101 if (!m_needsRebalancing) | |
102 return false; | |
103 | |
104 // Column heights may change here because of balancing. We may have to do mu
ltiple layout | |
105 // passes, depending on how the contents is fitted to the changed column hei
ghts. In most | |
106 // cases, laying out again twice or even just once will suffice. Sometimes w
e need more | |
107 // passes than that, though, but the number of retries should not exceed the
number of | |
108 // columns, unless we have a bug. | |
109 bool needsRelayout = false; | |
110 for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->n
extSiblingBox()) { | |
111 if (childBox != m_flowThread && childBox->isRenderMultiColumnSet()) { | |
112 RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(childBox)
; | |
113 if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) { | |
114 multicolSet->setChildNeedsLayout(MarkOnlyThis); | |
115 needsRelayout = true; | |
116 } | |
117 } | |
118 } | |
119 | |
120 if (needsRelayout) | |
121 m_flowThread->setChildNeedsLayout(MarkOnlyThis); | |
122 | |
123 m_inBalancingPass = needsRelayout; | |
124 return needsRelayout; | |
125 } | |
126 | |
127 void RenderMultiColumnBlock::addChild(RenderObject* newChild, RenderObject* befo
reChild) | |
128 { | |
129 if (!m_flowThread) { | |
130 m_flowThread = RenderMultiColumnFlowThread::createAnonymous(&document())
; | |
131 m_flowThread->setStyle(RenderStyle::createAnonymousStyleWithDisplay(styl
e(), BLOCK)); | |
132 RenderBlockFlow::addChild(m_flowThread); | |
133 } | |
134 m_flowThread->addChild(newChild, beforeChild); | |
135 } | |
136 | |
137 RenderObject* RenderMultiColumnBlock::layoutSpecialExcludedChild(bool relayoutCh
ildren, SubtreeLayoutScope& layoutScope) | |
138 { | |
139 if (!m_flowThread) | |
140 return 0; | |
141 | |
142 // Update the dimensions of our regions before we lay out the flow thread. | |
143 // FIXME: Eventually this is going to get way more complicated, and we will
be destroying regions | |
144 // instead of trying to keep them around. | |
145 bool shouldInvalidateRegions = false; | |
146 for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->n
extSiblingBox()) { | |
147 if (childBox == m_flowThread) | |
148 continue; | |
149 | |
150 if (relayoutChildren || childBox->needsLayout()) { | |
151 if (!m_inBalancingPass && childBox->isRenderMultiColumnSet()) | |
152 toRenderMultiColumnSet(childBox)->prepareForLayout(); | |
153 shouldInvalidateRegions = true; | |
154 } | |
155 } | |
156 | |
157 if (shouldInvalidateRegions) | |
158 m_flowThread->invalidateRegions(); | |
159 | |
160 if (relayoutChildren) | |
161 layoutScope.setChildNeedsLayout(m_flowThread); | |
162 | |
163 if (requiresBalancing()) { | |
164 // At the end of multicol layout, relayoutForPagination() is called unco
nditionally, but if | |
165 // no children are to be laid out (e.g. fixed width with layout already
being up-to-date), | |
166 // we want to prevent it from doing any work, so that the column balanci
ng machinery doesn't | |
167 // kick in and trigger additional unnecessary layout passes. Actually, i
t's not just a good | |
168 // idea in general to not waste time on balancing content that hasn't be
en re-laid out; we | |
169 // are actually required to guarantee this. The calculation of implicit
breaks needs to be | |
170 // preceded by a proper layout pass, since it's layout that sets up cont
ent runs, and the | |
171 // runs get deleted right after every pass. | |
172 m_needsRebalancing = shouldInvalidateRegions || m_flowThread->needsLayou
t(); | |
173 } | |
174 | |
175 setLogicalTopForChild(m_flowThread, borderBefore() + paddingBefore()); | |
176 m_flowThread->layoutIfNeeded(); | |
177 determineLogicalLeftPositionForChild(m_flowThread); | |
178 | |
179 return m_flowThread; | |
180 } | |
181 | |
182 const char* RenderMultiColumnBlock::renderName() const | |
183 { | |
184 if (isFloating()) | |
185 return "RenderMultiColumnBlock (floating)"; | |
186 if (isOutOfFlowPositioned()) | |
187 return "RenderMultiColumnBlock (positioned)"; | |
188 if (isAnonymousBlock()) | |
189 return "RenderMultiColumnBlock (anonymous)"; | |
190 // FIXME: Temporary hack while the new generated content system is being imp
lemented. | |
191 if (isPseudoElement()) | |
192 return "RenderMultiColumnBlock (generated)"; | |
193 if (isAnonymous()) | |
194 return "RenderMultiColumnBlock (generated)"; | |
195 if (isRelPositioned()) | |
196 return "RenderMultiColumnBlock (relative positioned)"; | |
197 return "RenderMultiColumnBlock"; | |
198 } | |
199 | |
200 } | |
OLD | NEW |