Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: Source/core/rendering/RenderMultiColumnSet.cpp

Issue 296413007: [New Multicolumn] Add support for column-span:all (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@359976
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 11 matching lines...) Expand all
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "core/rendering/RenderMultiColumnSet.h" 27 #include "core/rendering/RenderMultiColumnSet.h"
28 28
29 #include "core/rendering/PaintInfo.h" 29 #include "core/rendering/PaintInfo.h"
30 #include "core/rendering/RenderLayer.h" 30 #include "core/rendering/RenderLayer.h"
31 #include "core/rendering/RenderMultiColumnFlowThread.h" 31 #include "core/rendering/RenderMultiColumnFlowThread.h"
32 #include "core/rendering/RenderMultiColumnSpannerPlaceholder.h"
32 33
33 using namespace std; 34 using namespace std;
34 35
35 namespace WebCore { 36 namespace WebCore {
36 37
37 RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread) 38 RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread)
38 : RenderRegion(0, flowThread) 39 : RenderRegion(0, flowThread)
39 , m_columnHeight(0) 40 , m_columnHeight(0)
40 , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight()) 41 , m_maxColumnHeight(RenderFlowThread::maxLogicalHeight())
41 , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight()) 42 , m_minSpaceShortage(RenderFlowThread::maxLogicalHeight())
(...skipping 21 matching lines...) Expand all
63 64
64 RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() cons t 65 RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() cons t
65 { 66 {
66 for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling-> previousSibling()) { 67 for (RenderObject* sibling = previousSibling(); sibling; sibling = sibling-> previousSibling()) {
67 if (sibling->isRenderMultiColumnSet()) 68 if (sibling->isRenderMultiColumnSet())
68 return toRenderMultiColumnSet(sibling); 69 return toRenderMultiColumnSet(sibling);
69 } 70 }
70 return 0; 71 return 0;
71 } 72 }
72 73
74 RenderObject* RenderMultiColumnSet::firstRendererInFlowThread() const
75 {
76 if (RenderBox* sibling = RenderMultiColumnFlowThread::previousColumnSetOrSpa nnerSiblingOf(this)) {
77 // Adjacent sets should not occur. Currently we would have no way of fig uring out what each
78 // of them contains then.
79 ASSERT(!sibling->isRenderMultiColumnSet());
80 RenderMultiColumnSpannerPlaceholder* placeholder = multiColumnFlowThread ()->findColumnSpannerPlaceholder(sibling);
rune 2014/07/01 08:41:38 Perhaps add an ASSERT(placeholder) as well?
mstensho (USE GERRIT) 2014/08/26 09:43:58 Is it really necessary? It's gonna crash if it's N
rune 2014/08/27 07:00:01 It adds the information that it's not missing a nu
81 return placeholder->nextInPreOrderAfterChildren();
82 }
83 return flowThread()->firstChild();
84 }
85
86 RenderObject* RenderMultiColumnSet::lastRendererInFlowThread() const
87 {
88 if (RenderBox* sibling = RenderMultiColumnFlowThread::nextColumnSetOrSpanner SiblingOf(this)) {
89 // Adjacent sets should not occur. Currently we would have no way of fig uring out what each
90 // of them contains then.
91 ASSERT(!sibling->isRenderMultiColumnSet());
92 RenderMultiColumnSpannerPlaceholder* placeholder = multiColumnFlowThread ()->findColumnSpannerPlaceholder(sibling);
93 return placeholder->previousInPreOrder();
94 }
95 return flowThread()->lastLeafChild();
96 }
97
98 static bool precedesRenderer(RenderObject* renderer, RenderObject* boundary)
99 {
100 for (; renderer; renderer = renderer->nextInPreOrder()) {
101 if (renderer == boundary)
102 return true;
103 }
104 return false;
105 }
106
107 bool RenderMultiColumnSet::renders(RenderObject* renderer) const
108 {
109 if (!previousSiblingMultiColumnSet() && !nextSiblingMultiColumnSet()) {
110 // There is only one set. This is easy, then.
111 return renderer->isDescendantOf(m_flowThread);
112 }
113
114 RenderObject* firstRenderer = firstRendererInFlowThread();
115 RenderObject* lastRenderer = lastRendererInFlowThread();
116 ASSERT(firstRenderer);
117 ASSERT(lastRenderer);
118
119 // This is SLOW! But luckily very uncommon.
rune 2014/07/01 08:41:38 Perhaps note in which cases it happens. Is it when
mstensho (USE GERRIT) 2014/08/26 09:43:58 Done.
rune 2014/08/27 08:17:38 Acknowledged.
120 return precedesRenderer(firstRenderer, renderer) && precedesRenderer(rendere r, lastRenderer);
rune 2014/07/01 08:41:38 Do you need to check both? From where you call ren
mstensho (USE GERRIT) 2014/08/26 09:43:58 Done. We don't look inside spanners here, so no n
rune 2014/08/27 08:17:38 I see that this code has been transformed in an op
mstensho (USE GERRIT) 2014/08/27 08:24:05 This code is new in this CL and an issue was raise
rune 2014/08/27 08:36:31 It such a long time since I reviewed this as well.
mstensho (USE GERRIT) 2014/08/27 08:47:02 That's what I did in practice. But I lumped it all
rune 2014/08/27 10:22:27 Acknowledged.
121 }
122
123 void RenderMultiColumnSet::setLogicalTopInFlowThread(LayoutUnit logicalTop)
124 {
125 LayoutRect rect = flowThreadPortionRect();
126 if (isHorizontalWritingMode())
127 rect.setY(logicalTop);
128 else
129 rect.setX(logicalTop);
130 setFlowThreadPortionRect(rect);
131 }
132
133 void RenderMultiColumnSet::setLogicalBottomInFlowThread(LayoutUnit logicalBottom )
134 {
135 LayoutRect rect = flowThreadPortionRect();
136 if (isHorizontalWritingMode())
137 rect.shiftMaxYEdgeTo(logicalBottom);
138 else
139 rect.shiftMaxXEdgeTo(logicalBottom);
140 setFlowThreadPortionRect(rect);
141 }
142
143 bool RenderMultiColumnSet::heightIsAuto() const
144 {
145 RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread();
146 if (!flowThread->isRenderPagedFlowThread()) {
147 if (RenderBox* next = RenderMultiColumnFlowThread::nextColumnSetOrSpanne rSiblingOf(this)) {
148 if (!next->isRenderMultiColumnSet()) {
149 // If we're followed by a spanner, we need to balance.
150 ASSERT(flowThread->findColumnSpannerPlaceholder(next));
151 return true;
152 }
153 }
154 if (multiColumnBlockFlow()->style()->columnFill() == ColumnFillBalance)
155 return true;
156 }
157 return !flowThread->columnHeightAvailable();
158 }
159
73 LayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockO ffset) const 160 LayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockO ffset) const
74 { 161 {
75 unsigned columnIndex = columnIndexAtOffset(blockOffset); 162 unsigned columnIndex = columnIndexAtOffset(blockOffset);
76 LayoutRect portionRect(flowThreadPortionRectAt(columnIndex)); 163 LayoutRect portionRect(flowThreadPortionRectAt(columnIndex));
77 flipForWritingMode(portionRect); 164 flipForWritingMode(portionRect);
78 LayoutRect columnRect(columnRectAt(columnIndex)); 165 LayoutRect columnRect(columnRectAt(columnIndex));
79 flipForWritingMode(columnRect); 166 flipForWritingMode(columnRect);
80 return contentBoxRect().location() + columnRect.location() - portionRect.loc ation(); 167 return contentBoxRect().location() + columnRect.location() - portionRect.loc ation();
81 } 168 }
82 169
83 LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) c onst 170 LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) c onst
84 { 171 {
85 // Adjust for the top offset within the content box of the multicol containe r (containing 172 // Adjust for the top offset within the content box of the multicol containe r (containing
86 // block), unless this is the first set. We know that the top offset for the first set will be 173 // block), unless this is the first set. We know that the top offset for the first set will be
87 // zero, but if the multicol container has non-zero top border or padding, t he set's top offset 174 // zero, but if the multicol container has non-zero top border or padding, t he set's top offset
88 // (initially being 0 and relative to the border box) will be negative until it has been laid 175 // (initially being 0 and relative to the border box) will be negative until it has been laid
89 // out. Had we used this bogus offset, we would calculate the wrong height, and risk performing 176 // out. Had we used this bogus offset, we would calculate the wrong height, and risk performing
90 // a wasted layout iteration. Of course all other sets (if any) have this pr oblem in the first 177 // a wasted layout iteration. Of course all other sets (if any) have this pr oblem in the first
91 // layout pass too, but there's really nothing we can do there until the flo w thread has been 178 // layout pass too, but there's really nothing we can do there until the flo w thread has been
92 // laid out anyway. 179 // laid out anyway.
93 if (previousSiblingMultiColumnSet()) { 180 if (RenderMultiColumnFlowThread::previousColumnSetOrSpannerSiblingOf(this)) {
94 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); 181 RenderBlockFlow* multicolBlock = multiColumnBlockFlow();
95 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderAndPa ddingBefore(); 182 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderAndPa ddingBefore();
96 height -= contentLogicalTop; 183 height -= contentLogicalTop;
97 } 184 }
98 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created. 185 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created.
99 } 186 }
100 187
101 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons t 188 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons t
102 { 189 {
103 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); 190 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height! 273 ASSERT(m_minSpaceShortage > 0); // We should never _shrink_ the height!
187 ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If th is happens, we probably have a bug. 274 ASSERT(m_minSpaceShortage != RenderFlowThread::maxLogicalHeight()); // If th is happens, we probably have a bug.
188 if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight()) 275 if (m_minSpaceShortage == RenderFlowThread::maxLogicalHeight())
189 return m_columnHeight; // So bail out rather than looping infinitely. 276 return m_columnHeight; // So bail out rather than looping infinitely.
190 277
191 return m_columnHeight + m_minSpaceShortage; 278 return m_columnHeight + m_minSpaceShortage;
192 } 279 }
193 280
194 void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) 281 void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage)
195 { 282 {
196 if (!multiColumnFlowThread()->heightIsAuto()) 283 if (!heightIsAuto())
197 return; 284 return;
198 if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last ().breakOffset()) 285 if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last ().breakOffset())
199 return; 286 return;
200 // Append another item as long as we haven't exceeded used column count. Wha t ends up in the 287 // Append another item as long as we haven't exceeded used column count. Wha t ends up in the
201 // overflow area shouldn't affect column balancing. 288 // overflow area shouldn't affect column balancing.
202 if (m_contentRuns.size() < usedColumnCount()) 289 if (m_contentRuns.size() < usedColumnCount())
203 m_contentRuns.append(ContentRun(endOffsetFromFirstPage)); 290 m_contentRuns.append(ContentRun(endOffsetFromFirstPage));
204 } 291 }
205 292
206 bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation cal culationMode) 293 bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation cal culationMode)
207 { 294 {
208 ASSERT(multiColumnFlowThread()->heightIsAuto()); 295 LayoutUnit oldColumnHeight = m_columnHeight;
209 296
210 LayoutUnit oldColumnHeight = m_columnHeight; 297 m_maxColumnHeight = calculateMaxColumnHeight();
211 if (calculationMode == GuessFromFlowThreadPortion) { 298
212 // Post-process the content runs and find out where the implicit breaks will occur. 299 if (heightIsAuto()) {
213 distributeImplicitBreaks(); 300 if (calculationMode == GuessFromFlowThreadPortion) {
301 // Post-process the content runs and find out where the implicit bre aks will occur.
302 distributeImplicitBreaks();
303 }
304 LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode);
305 setAndConstrainColumnHeight(newColumnHeight);
306 // After having calculated an initial column height, the multicol contai ner typically needs at
307 // least one more layout pass with a new column height, but if a height was specified, we only
308 // need to do this if we think that we need less space than specified. C onversely, if we
309 // determined that the columns need to be as tall as the specified heigh t of the container, we
310 // have already laid it out correctly, and there's no need for another p ass.
311 } else {
312 // The position of the column set may have changed, in which case height available for
313 // columns may have changed as well.
314 setAndConstrainColumnHeight(m_columnHeight);
214 } 315 }
215 LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode);
216 setAndConstrainColumnHeight(newColumnHeight);
217
218 // After having calculated an initial column height, the multicol container typically needs at
219 // least one more layout pass with a new column height, but if a height was specified, we only
220 // need to do this if we think that we need less space than specified. Conve rsely, if we
221 // determined that the columns need to be as tall as the specified height of the container, we
222 // have already laid it out correctly, and there's no need for another pass.
223 316
224 // We can get rid of the content runs now, if we haven't already done so. Th ey are only needed 317 // We can get rid of the content runs now, if we haven't already done so. Th ey are only needed
225 // to calculate the initial balanced column height. In fact, we have to get rid of them before 318 // to calculate the initial balanced column height. In fact, we have to get rid of them before
226 // the next layout pass, since each pass will rebuild this. 319 // the next layout pass, since each pass will rebuild this.
227 m_contentRuns.clear(); 320 m_contentRuns.clear();
228 321
229 if (m_columnHeight == oldColumnHeight) 322 if (m_columnHeight == oldColumnHeight)
230 return false; // No change. We're done. 323 return false; // No change. We're done.
231 324
232 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight(); 325 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight();
(...skipping 14 matching lines...) Expand all
247 340
248 void RenderMultiColumnSet::resetColumnHeight() 341 void RenderMultiColumnSet::resetColumnHeight()
249 { 342 {
250 // Nuke previously stored minimum column height. Contents may have changed f or all we know. 343 // Nuke previously stored minimum column height. Contents may have changed f or all we know.
251 m_minimumColumnHeight = 0; 344 m_minimumColumnHeight = 0;
252 345
253 m_maxColumnHeight = calculateMaxColumnHeight(); 346 m_maxColumnHeight = calculateMaxColumnHeight();
254 347
255 LayoutUnit oldColumnHeight = pageLogicalHeight(); 348 LayoutUnit oldColumnHeight = pageLogicalHeight();
256 349
257 if (multiColumnFlowThread()->heightIsAuto()) 350 if (heightIsAuto())
258 m_columnHeight = 0; 351 m_columnHeight = 0;
259 else 352 else
260 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh read()->columnHeightAvailable())); 353 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh read()->columnHeightAvailable()));
261 354
262 if (pageLogicalHeight() != oldColumnHeight) 355 if (pageLogicalHeight() != oldColumnHeight)
263 setChildNeedsLayout(MarkOnlyThis); 356 setChildNeedsLayout(MarkOnlyThis);
264 357
265 // Content runs are only needed in the initial layout pass, in order to find an initial column 358 // Content runs are only needed in the initial layout pass, in order to find an initial column
266 // height, and should have been deleted afterwards. We're about to rebuild t he content runs, so 359 // height, and should have been deleted afterwards. We're about to rebuild t he content runs, so
267 // the list needs to be empty. 360 // the list needs to be empty.
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
647 if (!hasOverflowClip()) 740 if (!hasOverflowClip())
648 addVisualOverflow(lastRect); 741 addVisualOverflow(lastRect);
649 } 742 }
650 743
651 const char* RenderMultiColumnSet::renderName() const 744 const char* RenderMultiColumnSet::renderName() const
652 { 745 {
653 return "RenderMultiColumnSet"; 746 return "RenderMultiColumnSet";
654 } 747 }
655 748
656 } 749 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698