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

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

Issue 288263002: [New Multicolumn] Rebalance properly when child content changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rebase master 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 { 77 {
78 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); 78 RenderBlockFlow* multicolBlock = multiColumnBlockFlow();
79 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderBefore() - multicolBlock->paddingBefore(); 79 LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderBefore() - multicolBlock->paddingBefore();
80 80
81 height -= contentLogicalTop; 81 height -= contentLogicalTop;
82 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created. 82 return max(height, LayoutUnit(1)); // Let's avoid zero height, as that would probably cause an infinite amount of columns to be created.
83 } 83 }
84 84
85 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons t 85 LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) cons t
86 { 86 {
87 LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortio nRect().y() : flowThreadPortionRect().x());
88 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); 87 unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns);
89 return portionLogicalTop + columnIndex * computedColumnHeight(); 88 return logicalTopInFlowThread() + columnIndex * computedColumnHeight();
90 } 89 }
91 90
92 void RenderMultiColumnSet::setAndConstrainColumnHeight(LayoutUnit newHeight) 91 void RenderMultiColumnSet::setAndConstrainColumnHeight(LayoutUnit newHeight)
93 { 92 {
94 m_computedColumnHeight = newHeight; 93 m_computedColumnHeight = newHeight;
95 if (m_computedColumnHeight > m_maxColumnHeight) 94 if (m_computedColumnHeight > m_maxColumnHeight)
96 m_computedColumnHeight = m_maxColumnHeight; 95 m_computedColumnHeight = m_maxColumnHeight;
97 // FIXME: the height may also be affected by the enclosing pagination contex t, if any. 96 // FIXME: the height may also be affected by the enclosing pagination contex t, if any.
98 } 97 }
99 98
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 } 198 }
200 LayoutUnit newColumnHeight = calculateColumnHeight(initial); 199 LayoutUnit newColumnHeight = calculateColumnHeight(initial);
201 setAndConstrainColumnHeight(newColumnHeight); 200 setAndConstrainColumnHeight(newColumnHeight);
202 201
203 // After having calculated an initial column height, the multicol container typically needs at 202 // After having calculated an initial column height, the multicol container typically needs at
204 // least one more layout pass with a new column height, but if a height was specified, we only 203 // least one more layout pass with a new column height, but if a height was specified, we only
205 // need to do this if we think that we need less space than specified. Conve rsely, if we 204 // need to do this if we think that we need less space than specified. Conve rsely, if we
206 // determined that the columns need to be as tall as the specified height of the container, we 205 // determined that the columns need to be as tall as the specified height of the container, we
207 // have already laid it out correctly, and there's no need for another pass. 206 // have already laid it out correctly, and there's no need for another pass.
208 207
208 // We can get rid of the content runs now, if we haven't already done so. Th ey are only needed
209 // to calculate the initial balanced column height. In fact, we have to get rid of them before
210 // the next layout pass, since each pass will rebuild this.
211 m_contentRuns.clear();
212
209 if (m_computedColumnHeight == oldColumnHeight) 213 if (m_computedColumnHeight == oldColumnHeight)
210 return false; // No change. We're done. 214 return false; // No change. We're done.
211 215
212 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight(); 216 m_minSpaceShortage = RenderFlowThread::maxLogicalHeight();
213 m_contentRuns.clear();
214 return true; // Need another pass. 217 return true; // Need another pass.
215 } 218 }
216 219
217 void RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage) 220 void RenderMultiColumnSet::recordSpaceShortage(LayoutUnit spaceShortage)
218 { 221 {
219 if (spaceShortage >= m_minSpaceShortage) 222 if (spaceShortage >= m_minSpaceShortage)
220 return; 223 return;
221 224
222 // The space shortage is what we use as our stretch amount. We need a positi ve number here in 225 // The space shortage is what we use as our stretch amount. We need a positi ve number here in
223 // order to get anywhere. 226 // order to get anywhere.
(...skipping 17 matching lines...) Expand all
241 LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + ( colCount - 1) * colGap; 244 LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + ( colCount - 1) * colGap;
242 LayoutUnit currentContentLogicalWidth = contentLogicalWidth(); 245 LayoutUnit currentContentLogicalWidth = contentLogicalWidth();
243 LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentCon tentLogicalWidth); 246 LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentCon tentLogicalWidth);
244 if (!delta) 247 if (!delta)
245 return; 248 return;
246 249
247 // Increase our logical width by the delta. 250 // Increase our logical width by the delta.
248 setLogicalWidth(logicalWidth() + delta); 251 setLogicalWidth(logicalWidth() + delta);
249 } 252 }
250 253
251 void RenderMultiColumnSet::prepareForLayout() 254 void RenderMultiColumnSet::prepareForLayout(bool initial)
Julien - ping for review 2014/05/20 17:03:04 We should replace the first-pass boolean logic wit
mstensho (USE GERRIT) 2014/05/22 15:07:18 Done. I did the second best thing - removed the p
252 { 255 {
253 RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); 256 RenderBlockFlow* multicolBlock = multiColumnBlockFlow();
254 RenderStyle* multicolStyle = multicolBlock->style();
255 257
256 // Set box logical top. 258 // Set box logical top.
257 ASSERT(!previousSiblingBox() || !previousSiblingBox()->isRenderMultiColumnSe t()); // FIXME: multiple set not implemented; need to examine previous set to ca lculate the correct logical top. 259 ASSERT(!previousSiblingBox() || !previousSiblingBox()->isRenderMultiColumnSe t()); // FIXME: multiple set not implemented; need to examine previous set to ca lculate the correct logical top.
258 setLogicalTop(multicolBlock->borderBefore() + multicolBlock->paddingBefore() ); 260 setLogicalTop(multicolBlock->borderAndPaddingBefore());
259 261
260 // Set box width. 262 if (initial) {
261 updateLogicalWidth(); 263 m_maxColumnHeight = calculateMaxColumnHeight();
262 264 updateLogicalWidth();
Julien - ping for review 2014/05/20 17:03:04 It's weird that prepareForLayout actually does wha
mstensho (USE GERRIT) 2014/05/22 15:07:18 Done. All it really needed from updateLogicalWidt
265 }
263 if (multiColumnFlowThread()->requiresBalancing()) { 266 if (multiColumnFlowThread()->requiresBalancing()) {
264 // Set maximum column height. We will not stretch beyond this. 267 if (initial)
265 m_maxColumnHeight = RenderFlowThread::maxLogicalHeight(); 268 m_computedColumnHeight = 0;
266 if (!multicolStyle->logicalHeight().isAuto()) {
267 m_maxColumnHeight = multicolBlock->computeContentLogicalHeight(multi colStyle->logicalHeight(), -1);
268 if (m_maxColumnHeight == -1)
269 m_maxColumnHeight = RenderFlowThread::maxLogicalHeight();
270 }
271 if (!multicolStyle->logicalMaxHeight().isUndefined()) {
272 LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHe ight(multicolStyle->logicalMaxHeight(), -1);
273 if (logicalMaxHeight != -1 && m_maxColumnHeight > logicalMaxHeight)
274 m_maxColumnHeight = logicalMaxHeight;
275 }
276 m_maxColumnHeight = heightAdjustedForSetOffset(m_maxColumnHeight);
277 m_computedColumnHeight = 0; // Restart balancing.
278 } else { 269 } else {
279 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh read()->columnHeightAvailable())); 270 setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowTh read()->columnHeightAvailable()));
280 } 271 }
281 272
282 m_contentRuns.clear(); 273 // Content runs are only needed in the initial layout pass, in order to find an initial column
274 // height, and should have been deleted afterwards. We're about to rebuild t he content runs, so
275 // the list needs to be empty.
276 ASSERT(m_contentRuns.isEmpty());
283 277
284 // Nuke previously stored minimum column height. Contents may have changed f or all we know. 278 // Nuke previously stored minimum column height. Contents may have changed f or all we know.
285 m_minimumColumnHeight = 0; 279 m_minimumColumnHeight = 0;
280
281 setNeedsLayoutAndFullRepaint();
Julien - ping for review 2014/05/20 17:03:04 There is no branch in prepareForLayout, which mean
mstensho (USE GERRIT) 2014/05/21 09:02:33 No, that looks very unnecessary, apart from being
mstensho (USE GERRIT) 2014/05/22 15:07:18 Done. We now call setChildNeedsLayout(MarkOnlyThi
286 } 282 }
287 283
288 void RenderMultiColumnSet::expandToEncompassFlowThreadContentsIfNeeded() 284 void RenderMultiColumnSet::expandToEncompassFlowThreadContentsIfNeeded()
289 { 285 {
290 ASSERT(multiColumnFlowThread()->lastMultiColumnSet() == this); 286 ASSERT(multiColumnFlowThread()->lastMultiColumnSet() == this);
291 LayoutRect rect(flowThreadPortionRect()); 287 LayoutRect rect(flowThreadPortionRect());
292 288
293 // Get the offset within the flow thread in its block progression direction. Then get the 289 // Get the offset within the flow thread in its block progression direction. Then get the
294 // flow thread's remaining logical height including its overflow and expand our rect 290 // flow thread's remaining logical height including its overflow and expand our rect
295 // to encompass that remaining height and overflow. The idea is that we will generate 291 // to encompass that remaining height and overflow. The idea is that we will generate
296 // additional columns and pages to hold that overflow, since people do write bad 292 // additional columns and pages to hold that overflow, since people do write bad
297 // content like <body style="height:0px"> in multi-column layouts. 293 // content like <body style="height:0px"> in multi-column layouts.
298 bool isHorizontal = flowThread()->isHorizontalWritingMode(); 294 bool isHorizontal = flowThread()->isHorizontalWritingMode();
299 LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x(); 295 LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x();
300 LayoutRect layoutRect = flowThread()->layoutOverflowRect(); 296 LayoutRect layoutRect = flowThread()->layoutOverflowRect();
301 LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : l ayoutRect.maxX()) - logicalTopOffset; 297 LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : l ayoutRect.maxX()) - logicalTopOffset;
302 setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect. width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height())); 298 setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect. width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height()));
303 } 299 }
304 300
305 void RenderMultiColumnSet::layout() 301 void RenderMultiColumnSet::layout()
306 { 302 {
307 RenderRegion::layout(); 303 RenderRegion::layout();
308 304
309 if (!nextSiblingMultiColumnSet()) { 305 // At this point the logical top of the column set is known. Update maximum column height
310 // This is the last set, i.e. the last region. Seize the opportunity to validate them. 306 // (multicol height may be constrained, and in order to calculate it, we nee d to know our top).
311 multiColumnFlowThread()->validateRegions(); 307 m_maxColumnHeight = calculateMaxColumnHeight();
312 }
313 } 308 }
314 309
315 void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTo p, LogicalExtentComputedValues& computedValues) const 310 void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTo p, LogicalExtentComputedValues& computedValues) const
316 { 311 {
317 computedValues.m_extent = m_computedColumnHeight; 312 computedValues.m_extent = m_computedColumnHeight;
318 computedValues.m_position = logicalTop; 313 computedValues.m_position = logicalTop;
319 } 314 }
320 315
316 LayoutUnit RenderMultiColumnSet::calculateMaxColumnHeight() const
317 {
318 RenderBlockFlow* multicolBlock = multiColumnBlockFlow();
319 RenderStyle* multicolStyle = multicolBlock->style();
320 LayoutUnit availableHeight = multiColumnFlowThread()->columnHeightAvailable( );
321 LayoutUnit maxColumnHeight = availableHeight ? availableHeight : RenderFlowT hread::maxLogicalHeight();
322 if (!multicolStyle->logicalMaxHeight().isUndefined()) {
323 LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHeight (multicolStyle->logicalMaxHeight(), -1);
324 if (logicalMaxHeight != -1 && maxColumnHeight > logicalMaxHeight)
325 maxColumnHeight = logicalMaxHeight;
326 }
327 return heightAdjustedForSetOffset(maxColumnHeight);
328 }
329
321 LayoutUnit RenderMultiColumnSet::columnGap() const 330 LayoutUnit RenderMultiColumnSet::columnGap() const
322 { 331 {
323 RenderBlockFlow* parentBlock = multiColumnBlockFlow(); 332 RenderBlockFlow* parentBlock = multiColumnBlockFlow();
324 if (parentBlock->style()->hasNormalColumnGap()) 333 if (parentBlock->style()->hasNormalColumnGap())
325 return parentBlock->style()->fontDescription().computedPixelSize(); // " 1em" is recommended as the normal gap setting. Matches <p> margins. 334 return parentBlock->style()->fontDescription().computedPixelSize(); // " 1em" is recommended as the normal gap setting. Matches <p> margins.
326 return parentBlock->style()->columnGap(); 335 return parentBlock->style()->columnGap();
327 } 336 }
328 337
329 unsigned RenderMultiColumnSet::columnCount() const 338 unsigned RenderMultiColumnSet::columnCount() const
330 { 339 {
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 fragments.append(fragment); 639 fragments.append(fragment);
631 } 640 }
632 } 641 }
633 642
634 const char* RenderMultiColumnSet::renderName() const 643 const char* RenderMultiColumnSet::renderName() const
635 { 644 {
636 return "RenderMultiColumnSet"; 645 return "RenderMultiColumnSet";
637 } 646 }
638 647
639 } 648 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698