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

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

Issue 288263002: [New Multicolumn] Rebalance properly when child content changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: code review 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 flipForWritingMode(flowThreadPoint); 132 flipForWritingMode(flowThreadPoint);
133 LayoutUnit blockOffset = isHorizontalWritingMode() ? flowThreadPoint.y() : f lowThreadPoint.x(); 133 LayoutUnit blockOffset = isHorizontalWritingMode() ? flowThreadPoint.y() : f lowThreadPoint.x();
134 RenderRegion* renderRegion = regionAtBlockOffset(blockOffset); 134 RenderRegion* renderRegion = regionAtBlockOffset(blockOffset);
135 if (!renderRegion) 135 if (!renderRegion)
136 return LayoutSize(0, 0); 136 return LayoutSize(0, 0);
137 return toRenderMultiColumnSet(renderRegion)->flowThreadTranslationAtOffset(b lockOffset); 137 return toRenderMultiColumnSet(renderRegion)->flowThreadTranslationAtOffset(b lockOffset);
138 } 138 }
139 139
140 void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa youtScope& layoutScope) 140 void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa youtScope& layoutScope)
141 { 141 {
142 // Update the dimensions of our regions before we lay out the flow thread. 142 if (relayoutChildren)
143 // FIXME: Eventually this is going to get way more complicated, and we will be destroying regions 143 layoutScope.setChildNeedsLayout(this);
144 // instead of trying to keep them around. 144
145 bool shouldInvalidateRegions = false; 145 if (!needsLayout()) {
146 // Just before the multicol container (our parent RenderBlockFlow) finis hes laying out, it
147 // will call recalculateColumnHeights() on us unconditionally, but we on ly want that method
148 // to do any work if we actually laid out the flow thread. Otherwise, th e balancing
149 // machinery would kick in needlessly, and trigger additional layout pas ses. Furthermore, we
150 // actually depend on a proper flowthread layout pass in order to do bal ancing, since it's
151 // flowthread layout that sets up content runs.
152 m_needsColumnHeightsRecalculation = false;
153 return;
154 }
155
146 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet()) { 156 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet()) {
147 if (relayoutChildren || columnSet->needsLayout()) { 157 if (!m_inBalancingPass) {
148 if (!m_inBalancingPass) 158 // This is the initial layout pass. We need to reset the column heig ht, because contents
149 columnSet->prepareForLayout(); 159 // typically have changed.
150 shouldInvalidateRegions = true; 160 columnSet->resetColumnHeight();
161
162 columnSet->setComputedColumnWidthAndCount(columnWidth(), columnCount ());
151 } 163 }
152 } 164 }
153 165
154 if (shouldInvalidateRegions) 166 invalidateRegions();
155 invalidateRegions(); 167 m_needsColumnHeightsRecalculation = requiresBalancing();
156 168 layout();
157 if (relayoutChildren)
158 layoutScope.setChildNeedsLayout(this);
159
160 if (requiresBalancing()) {
161 // At the end of multicol layout, relayoutForPagination() is called unco nditionally, but if
162 // no children are to be laid out (e.g. fixed width with layout already being up-to-date),
163 // we want to prevent it from doing any work, so that the column balanci ng machinery doesn't
164 // kick in and trigger additional unnecessary layout passes. Actually, i t's not just a good
165 // idea in general to not waste time on balancing content that hasn't be en re-laid out; we
166 // are actually required to guarantee this. The calculation of implicit breaks needs to be
167 // preceded by a proper layout pass, since it's layout that sets up cont ent runs, and the
168 // runs get deleted right after every pass.
169 m_needsColumnHeightsRecalculation = shouldInvalidateRegions || needsLayo ut();
170 }
171
172 layoutIfNeeded();
173 } 169 }
174 170
175 bool RenderMultiColumnFlowThread::computeColumnCountAndWidth() 171 bool RenderMultiColumnFlowThread::computeColumnCountAndWidth()
176 { 172 {
177 RenderBlock* columnBlock = multiColumnBlockFlow(); 173 RenderBlock* columnBlock = multiColumnBlockFlow();
178 LayoutUnit oldColumnWidth = m_columnWidth; 174 LayoutUnit oldColumnWidth = m_columnWidth;
179 175
180 // Calculate our column width and column count. 176 // Calculate our column width and column count.
181 m_columnCount = 1; 177 m_columnCount = 1;
182 m_columnWidth = columnBlock->contentLogicalWidth(); 178 m_columnWidth = columnBlock->contentLogicalWidth();
(...skipping 15 matching lines...) Expand all
198 } else { 194 } else {
199 m_columnCount = std::max<LayoutUnit>(std::min<LayoutUnit>(colCount, (ava ilWidth + colGap) / (colWidth + colGap)), 1); 195 m_columnCount = std::max<LayoutUnit>(std::min<LayoutUnit>(colCount, (ava ilWidth + colGap) / (colWidth + colGap)), 1);
200 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap; 196 m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap;
201 } 197 }
202 198
203 return m_columnWidth != oldColumnWidth; 199 return m_columnWidth != oldColumnWidth;
204 } 200 }
205 201
206 bool RenderMultiColumnFlowThread::recalculateColumnHeights() 202 bool RenderMultiColumnFlowThread::recalculateColumnHeights()
207 { 203 {
204 // All column sets that needed layout have now been laid out, so we can fina lly validate them.
205 validateRegions();
206
208 if (!m_needsColumnHeightsRecalculation) 207 if (!m_needsColumnHeightsRecalculation)
209 return false; 208 return false;
210 209
211 // Column heights may change here because of balancing. We may have to do mu ltiple layout 210 // Column heights may change here because of balancing. We may have to do mu ltiple layout
212 // passes, depending on how the contents is fitted to the changed column hei ghts. In most 211 // passes, depending on how the contents is fitted to the changed column hei ghts. In most
213 // cases, laying out again twice or even just once will suffice. Sometimes w e need more 212 // cases, laying out again twice or even just once will suffice. Sometimes w e need more
214 // passes than that, though, but the number of retries should not exceed the number of 213 // passes than that, though, but the number of retries should not exceed the number of
215 // columns, unless we have a bug. 214 // columns, unless we have a bug.
216 bool needsRelayout = false; 215 bool needsRelayout = false;
217 for (RenderMultiColumnSet* multicolSet = firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) { 216 for (RenderMultiColumnSet* multicolSet = firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) {
218 if (multicolSet->recalculateColumnHeight(!m_inBalancingPass)) { 217 needsRelayout |= multicolSet->recalculateColumnHeight(m_inBalancingPass ? RenderMultiColumnSet::StretchBySpaceShortage : RenderMultiColumnSet::GuessFrom FlowThreadPortion);
218 if (needsRelayout) {
219 // Once a column set gets a new column height, that column set and a ll successive column
220 // sets need to be laid out over again, since their logical top will be affected by
221 // this, and therefore their column heights may change as well, at l east if the multicol
222 // height is constrained.
219 multicolSet->setChildNeedsLayout(MarkOnlyThis); 223 multicolSet->setChildNeedsLayout(MarkOnlyThis);
220 needsRelayout = true;
221 } 224 }
222 } 225 }
223 226
224 if (needsRelayout) 227 if (needsRelayout)
225 setChildNeedsLayout(MarkOnlyThis); 228 setChildNeedsLayout(MarkOnlyThis);
226 229
227 m_inBalancingPass = needsRelayout; 230 m_inBalancingPass = needsRelayout;
228 return needsRelayout; 231 return needsRelayout;
229 } 232 }
230 233
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 } 316 }
314 317
315 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const 318 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
316 { 319 {
317 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet()) 320 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
318 return columnSet->computedColumnHeight(); 321 return columnSet->computedColumnHeight();
319 return false; 322 return false;
320 } 323 }
321 324
322 } 325 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698