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

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

Issue 147233002: Remove internal recursion for RenderBlockFlow and RenderMultiColumnBlock layout (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Make the shouldRelayout* methods const and add comment for the while loop Created 6 years, 10 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
« no previous file with comments | « Source/core/rendering/RenderBlockFlow.h ('k') | Source/core/rendering/RenderMultiColumnBlock.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google 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 are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 20 matching lines...) Expand all
31 #include "config.h" 31 #include "config.h"
32 #include "core/rendering/RenderBlockFlow.h" 32 #include "core/rendering/RenderBlockFlow.h"
33 33
34 #include "core/accessibility/AXObjectCache.h" 34 #include "core/accessibility/AXObjectCache.h"
35 #include "core/frame/FrameView.h" 35 #include "core/frame/FrameView.h"
36 #include "core/rendering/FastTextAutosizer.h" 36 #include "core/rendering/FastTextAutosizer.h"
37 #include "core/rendering/HitTestLocation.h" 37 #include "core/rendering/HitTestLocation.h"
38 #include "core/rendering/LayoutRectRecorder.h" 38 #include "core/rendering/LayoutRectRecorder.h"
39 #include "core/rendering/LayoutRepainter.h" 39 #include "core/rendering/LayoutRepainter.h"
40 #include "core/rendering/RenderLayer.h" 40 #include "core/rendering/RenderLayer.h"
41 #include "core/rendering/RenderMultiColumnBlock.h"
41 #include "core/rendering/RenderNamedFlowFragment.h" 42 #include "core/rendering/RenderNamedFlowFragment.h"
42 #include "core/rendering/RenderNamedFlowThread.h" 43 #include "core/rendering/RenderNamedFlowThread.h"
43 #include "core/rendering/RenderText.h" 44 #include "core/rendering/RenderText.h"
44 #include "core/rendering/RenderView.h" 45 #include "core/rendering/RenderView.h"
45 #include "core/rendering/line/LineWidth.h" 46 #include "core/rendering/line/LineWidth.h"
46 #include "core/rendering/svg/SVGTextRunRenderingContext.h" 47 #include "core/rendering/svg/SVGTextRunRenderingContext.h"
47 #include "platform/text/BidiTextRun.h" 48 #include "platform/text/BidiTextRun.h"
48 49
49 using namespace std; 50 using namespace std;
50 51
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 { 181 {
181 if (lineGridBox()) 182 if (lineGridBox())
182 lineGridBox()->destroy(); 183 lineGridBox()->destroy();
183 184
184 if (renderNamedFlowFragment()) 185 if (renderNamedFlowFragment())
185 setRenderNamedFlowFragment(0); 186 setRenderNamedFlowFragment(0);
186 187
187 RenderBlock::willBeDestroyed(); 188 RenderBlock::willBeDestroyed();
188 } 189 }
189 190
190 bool RenderBlockFlow::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer& statePusher) 191 bool RenderBlockFlow::shouldRelayoutForPagination(LayoutUnit& pageLogicalHeight, LayoutUnit layoutOverflowLogicalBottom) const
191 { 192 {
192 if (!hasColumns())
193 return false;
194
195 OwnPtr<RenderOverflow> savedOverflow = m_overflow.release();
196 if (childrenInline())
197 addOverflowFromInlineChildren();
198 else
199 addOverflowFromBlockChildren();
200 LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layout OverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingB efore();
201
202 // FIXME: We don't balance properly at all in the presence of forced page br eaks. We need to understand what 193 // FIXME: We don't balance properly at all in the presence of forced page br eaks. We need to understand what
203 // the distance between forced page breaks is so that we can avoid making th e minimum column height too tall. 194 // the distance between forced page breaks is so that we can avoid making th e minimum column height too tall.
204 ColumnInfo* colInfo = columnInfo(); 195 ColumnInfo* colInfo = columnInfo();
205 if (!hasSpecifiedPageLogicalHeight) { 196 LayoutUnit columnHeight = pageLogicalHeight;
206 LayoutUnit columnHeight = pageLogicalHeight; 197 const int minColumnCount = colInfo->forcedBreaks() + 1;
207 int minColumnCount = colInfo->forcedBreaks() + 1; 198 const int desiredColumnCount = colInfo->desiredColumnCount();
208 int desiredColumnCount = colInfo->desiredColumnCount(); 199 if (minColumnCount >= desiredColumnCount) {
209 if (minColumnCount >= desiredColumnCount) { 200 // The forced page breaks are in control of the balancing. Just set the column height to the
210 // The forced page breaks are in control of the balancing. Just set the column height to the 201 // maximum page break distance.
211 // maximum page break distance. 202 if (!pageLogicalHeight) {
212 if (!pageLogicalHeight) { 203 LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumD istanceBetweenForcedBreaks(),
213 LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maxi mumDistanceBetweenForcedBreaks(), 204 view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset());
214 view()->layoutState()->pageLogicalOffset(this, borderBefore( ) + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset( )); 205 columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBr eaks);
215 columnHeight = max(colInfo->minimumColumnHeight(), distanceBetwe enBreaks);
216 }
217 } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeig ht, desiredColumnCount)) {
218 // Now that we know the intrinsic height of the columns, we have to rebalance them.
219 columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf ((float)layoutOverflowLogicalBottom / desiredColumnCount));
220 } 206 }
221 207 } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeight, desiredColumnCount)) {
222 if (columnHeight && columnHeight != pageLogicalHeight) { 208 // Now that we know the intrinsic height of the columns, we have to reba lance them.
223 statePusher.pop(); 209 columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((fl oat)layoutOverflowLogicalBottom / desiredColumnCount));
224 setEverHadLayout(true);
225 layoutBlockFlow(false, columnHeight);
226 return true;
227 }
228 } 210 }
229 211
230 if (pageLogicalHeight) 212 if (columnHeight && columnHeight != pageLogicalHeight) {
231 colInfo->setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBotto m / pageLogicalHeight), pageLogicalHeight); 213 pageLogicalHeight = columnHeight;
232 214 return true;
233 if (columnCount(colInfo)) {
234 setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeigh t() + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
235 m_overflow.clear();
236 } else {
237 m_overflow = savedOverflow.release();
238 } 215 }
239 216
240 return false; 217 return false;
241 } 218 }
242 219
220 void RenderBlockFlow::setColumnCountAndHeight(unsigned count, LayoutUnit pageLog icalHeight)
221 {
222 ColumnInfo* colInfo = columnInfo();
223 if (pageLogicalHeight)
224 colInfo->setColumnCountAndHeight(count, pageLogicalHeight);
225
226 if (columnCount(colInfo)) {
227 setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeigh t() + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
228 m_overflow.clear();
229 }
230 }
231
243 bool RenderBlockFlow::isSelfCollapsingBlock() const 232 bool RenderBlockFlow::isSelfCollapsingBlock() const
244 { 233 {
245 m_hasOnlySelfCollapsingChildren = RenderBlock::isSelfCollapsingBlock(); 234 m_hasOnlySelfCollapsingChildren = RenderBlock::isSelfCollapsingBlock();
246 return m_hasOnlySelfCollapsingChildren; 235 return m_hasOnlySelfCollapsingChildren;
247 } 236 }
248 237
249 void RenderBlockFlow::layoutBlock(bool relayoutChildren) 238 void RenderBlockFlow::layoutBlock(bool relayoutChildren)
250 { 239 {
251 layoutBlockFlow(relayoutChildren);
252 }
253
254 inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit p ageLogicalHeight)
255 {
256 ASSERT(needsLayout()); 240 ASSERT(needsLayout());
257 ASSERT(isInlineBlockOrInlineTable() || !isInline()); 241 ASSERT(isInlineBlockOrInlineTable() || !isInline());
258 242
259 // If we are self-collapsing with self-collapsing descendants this will get set to save us burrowing through our 243 // If we are self-collapsing with self-collapsing descendants this will get set to save us burrowing through our
260 // descendants every time in |isSelfCollapsingBlock|. We reset it here so th at |isSelfCollapsingBlock| attempts to burrow 244 // descendants every time in |isSelfCollapsingBlock|. We reset it here so th at |isSelfCollapsingBlock| attempts to burrow
261 // at least once and so that it always gives a reliable result reflecting th e latest layout. 245 // at least once and so that it always gives a reliable result reflecting th e latest layout.
262 m_hasOnlySelfCollapsingChildren = false; 246 m_hasOnlySelfCollapsingChildren = false;
263 247
264 if (!relayoutChildren && simplifiedLayout()) 248 if (!relayoutChildren && simplifiedLayout())
265 return; 249 return;
266 250
251 SubtreeLayoutScope layoutScope(this);
252
253 // Multiple passes might be required for column and pagination based layout
254 // In the case of the old column code the number of passes will only be two
255 // however, in the newer column code the number of passes could equal the
256 // number of columns.
257 bool success = false;
258 LayoutUnit pageLogicalHeight = 0;
259 while (!success)
260 success = tryLayoutBlockFlow(relayoutChildren, pageLogicalHeight, layout Scope);
esprehn 2014/01/27 19:45:52 I'm not a fan of the success and try pattern here.
261 }
262
263 inline bool RenderBlockFlow::tryLayoutBlockFlow(bool relayoutChildren, LayoutUni t &pageLogicalHeight, SubtreeLayoutScope& layoutScope)
esprehn 2014/01/27 19:45:52 Do we need to rename this? It's not really "trying
264 {
267 LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); 265 LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
268 266
269 if (updateLogicalWidthAndColumnWidth()) 267 if (updateLogicalWidthAndColumnWidth())
270 relayoutChildren = true; 268 relayoutChildren = true;
271 269
272 rebuildFloatsFromIntruding(); 270 rebuildFloatsFromIntruding();
273 271
274 bool pageLogicalHeightChanged = false; 272 bool pageLogicalHeightChanged = false;
275 bool hasSpecifiedPageLogicalHeight = false; 273 bool hasSpecifiedPageLogicalHeight = false;
276 checkForPaginationLogicalHeightChange(pageLogicalHeight, pageLogicalHeightCh anged, hasSpecifiedPageLogicalHeight); 274 checkForPaginationLogicalHeightChange(pageLogicalHeight, pageLogicalHeightCh anged, hasSpecifiedPageLogicalHeight);
(...skipping 20 matching lines...) Expand all
297 // 295 //
298 // Start out by setting our margin values to our current margins. Table cell s have 296 // Start out by setting our margin values to our current margins. Table cell s have
299 // no margins, so we don't fill in the values for table cells. 297 // no margins, so we don't fill in the values for table cells.
300 if (!isTableCell()) { 298 if (!isTableCell()) {
301 initMaxMarginValues(); 299 initMaxMarginValues();
302 setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk()); 300 setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk());
303 setHasMarginAfterQuirk(style()->hasMarginAfterQuirk()); 301 setHasMarginAfterQuirk(style()->hasMarginAfterQuirk());
304 setPaginationStrut(0); 302 setPaginationStrut(0);
305 } 303 }
306 304
307 SubtreeLayoutScope layoutScope(this);
308
309 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); 305 LayoutUnit beforeEdge = borderBefore() + paddingBefore();
310 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeig ht(); 306 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeig ht();
311 LayoutUnit previousHeight = logicalHeight(); 307 LayoutUnit previousHeight = logicalHeight();
312 setLogicalHeight(beforeEdge); 308 setLogicalHeight(beforeEdge);
313 309
314 m_repaintLogicalTop = 0; 310 m_repaintLogicalTop = 0;
315 m_repaintLogicalBottom = 0; 311 m_repaintLogicalBottom = 0;
316 LayoutUnit maxFloatLogicalBottom = 0; 312 LayoutUnit maxFloatLogicalBottom = 0;
317 if (!firstChild() && !isAnonymousBlock()) 313 if (!firstChild() && !isAnonymousBlock())
318 setChildrenInline(true); 314 setChildrenInline(true);
319 315
320 FastTextAutosizer* textAutosizer = document().fastTextAutosizer(); 316 FastTextAutosizer* textAutosizer = document().fastTextAutosizer();
321 if (textAutosizer) 317 if (textAutosizer)
322 textAutosizer->beginLayout(this); 318 textAutosizer->beginLayout(this);
323 319
324 if (childrenInline()) 320 if (childrenInline())
325 layoutInlineChildren(relayoutChildren, m_repaintLogicalTop, m_repaintLog icalBottom, afterEdge); 321 layoutInlineChildren(relayoutChildren, m_repaintLogicalTop, m_repaintLog icalBottom, afterEdge);
326 else 322 else
327 layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom, layoutScope , beforeEdge, afterEdge); 323 layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom, layoutScope , beforeEdge, afterEdge);
328 324
329 if (textAutosizer) 325 if (textAutosizer)
330 textAutosizer->endLayout(this); 326 textAutosizer->endLayout(this);
331 327
332 if (frameView()->partialLayout().isStopping()) { 328 if (frameView()->partialLayout().isStopping()) {
333 statePusher.pop(); 329 statePusher.pop();
334 return; 330 return true;
335 } 331 }
336 332
337 // Expand our intrinsic height to encompass floats. 333 // Expand our intrinsic height to encompass floats.
338 if (lowestFloatLogicalBottom() > (logicalHeight() - afterEdge) && expandsToE ncloseOverhangingFloats()) 334 if (lowestFloatLogicalBottom() > (logicalHeight() - afterEdge) && expandsToE ncloseOverhangingFloats())
339 setLogicalHeight(lowestFloatLogicalBottom() + afterEdge); 335 setLogicalHeight(lowestFloatLogicalBottom() + afterEdge);
340 336
341 if (relayoutForPagination(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher) || relayoutToAvoidWidows(statePusher)) { 337 if (isRenderMultiColumnBlock()) {
342 ASSERT(!shouldBreakAtLineToAvoidWidow()); 338 if (toRenderMultiColumnBlock(this)->shouldRelayoutMultiColumnBlock()) {
343 return; 339 setChildNeedsLayout(MarkOnlyThis);
340 statePusher.pop();
341 return false;
342 }
343 } else if (hasColumns()) {
344 OwnPtr<RenderOverflow> savedOverflow = m_overflow.release();
345 if (childrenInline())
346 addOverflowFromInlineChildren();
347 else
348 addOverflowFromBlockChildren();
349 LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? la youtOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - padd ingBefore();
350 m_overflow = savedOverflow.release();
351
352 if (!hasSpecifiedPageLogicalHeight && shouldRelayoutForPagination(pageLo gicalHeight, layoutOverflowLogicalBottom)) {
353 statePusher.pop();
354 setEverHadLayout(true);
355 return false;
356 }
357
358 setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageL ogicalHeight), pageLogicalHeight);
359 }
360
361 if (shouldBreakAtLineToAvoidWidow()) {
362 statePusher.pop();
363 setEverHadLayout(true);
364 return false;
344 } 365 }
345 366
346 // Calculate our new height. 367 // Calculate our new height.
347 LayoutUnit oldHeight = logicalHeight(); 368 LayoutUnit oldHeight = logicalHeight();
348 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); 369 LayoutUnit oldClientAfterEdge = clientLogicalBottom();
349 370
350 // Before updating the final size of the flow thread make sure a forced brea k is applied after the content. 371 // Before updating the final size of the flow thread make sure a forced brea k is applied after the content.
351 // This ensures the size information is correctly computed for the last auto -height region receiving content. 372 // This ensures the size information is correctly computed for the last auto -height region receiving content.
352 if (isRenderFlowThread()) 373 if (isRenderFlowThread())
353 toRenderFlowThread(this)->applyBreakAfterContent(oldClientAfterEdge); 374 toRenderFlowThread(this)->applyBreakAfterContent(oldClientAfterEdge);
(...skipping 22 matching lines...) Expand all
376 updateRegionsAndShapesAfterChildLayout(flowThread, heightChanged); 397 updateRegionsAndShapesAfterChildLayout(flowThread, heightChanged);
377 398
378 // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway). 399 // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
379 computeOverflow(oldClientAfterEdge); 400 computeOverflow(oldClientAfterEdge);
380 401
381 statePusher.pop(); 402 statePusher.pop();
382 403
383 fitBorderToLinesIfNeeded(); 404 fitBorderToLinesIfNeeded();
384 405
385 if (frameView()->partialLayout().isStopping()) 406 if (frameView()->partialLayout().isStopping())
386 return; 407 return true;
387 408
388 if (renderView->layoutState()->m_pageLogicalHeight) 409 if (renderView->layoutState()->m_pageLogicalHeight)
389 setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop())); 410 setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop()));
390 411
391 updateLayerTransform(); 412 updateLayerTransform();
392 413
393 // Update our scroll information if we're overflow:auto/scroll/hidden now th at we know if 414 // Update our scroll information if we're overflow:auto/scroll/hidden now th at we know if
394 // we overflow or not. 415 // we overflow or not.
395 updateScrollInfoAfterLayout(); 416 updateScrollInfoAfterLayout();
396 417
397 // Repaint with our new bounds if they are different from our old bounds. 418 // Repaint with our new bounds if they are different from our old bounds.
398 bool didFullRepaint = repainter.repaintAfterLayout(); 419 bool didFullRepaint = repainter.repaintAfterLayout();
399 if (!didFullRepaint && m_repaintLogicalTop != m_repaintLogicalBottom && (sty le()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) { 420 if (!didFullRepaint && m_repaintLogicalTop != m_repaintLogicalBottom && (sty le()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
400 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) 421 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
401 setShouldRepaintOverflowIfNeeded(true); 422 setShouldRepaintOverflowIfNeeded(true);
402 else 423 else
403 repaintOverflow(); 424 repaintOverflow();
404 } 425 }
405 426
406 clearNeedsLayout(); 427 clearNeedsLayout();
428 return true;
407 } 429 }
408 430
409 void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom) 431 void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom)
410 { 432 {
411 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore(); 433 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore();
412 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore(); 434 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore();
413 435
414 // The child is a normal flow object. Compute the margins we will use for co llapsing now. 436 // The child is a normal flow object. Compute the margins we will use for co llapsing now.
415 child->computeAndSetBlockDirectionMargins(this); 437 child->computeAndSetBlockDirectionMargins(this);
416 438
(...skipping 2408 matching lines...) Expand 10 before | Expand all | Expand 10 after
2825 RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData() 2847 RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData()
2826 { 2848 {
2827 if (m_rareData) 2849 if (m_rareData)
2828 return *m_rareData; 2850 return *m_rareData;
2829 2851
2830 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); 2852 m_rareData = adoptPtr(new RenderBlockFlowRareData(this));
2831 return *m_rareData; 2853 return *m_rareData;
2832 } 2854 }
2833 2855
2834 } // namespace WebCore 2856 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderBlockFlow.h ('k') | Source/core/rendering/RenderMultiColumnBlock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698