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

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

Issue 712553003: [New Multicolumn] Actual support for layout of column-span:all. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rebase master Created 6 years, 1 month 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 14 matching lines...) Expand all
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "core/rendering/RenderMultiColumnFlowThread.h" 27 #include "core/rendering/RenderMultiColumnFlowThread.h"
28 28
29 #include "core/rendering/RenderMultiColumnSet.h" 29 #include "core/rendering/RenderMultiColumnSet.h"
30 #include "core/rendering/RenderMultiColumnSpannerSet.h" 30 #include "core/rendering/RenderMultiColumnSpannerSet.h"
31 31
32 namespace blink { 32 namespace blink {
33 33
34 RenderMultiColumnFlowThread::RenderMultiColumnFlowThread() 34 RenderMultiColumnFlowThread::RenderMultiColumnFlowThread()
35 : m_columnCount(1) 35 : m_lastSetWorkedOn(0)
36 , m_columnCount(1)
36 , m_columnHeightAvailable(0) 37 , m_columnHeightAvailable(0)
37 , m_inBalancingPass(false) 38 , m_inBalancingPass(false)
38 , m_needsColumnHeightsRecalculation(false) 39 , m_needsColumnHeightsRecalculation(false)
39 , m_progressionIsInline(true) 40 , m_progressionIsInline(true)
40 { 41 {
41 setFlowThreadState(InsideInFlowThread); 42 setFlowThreadState(InsideInFlowThread);
42 } 43 }
43 44
44 RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread() 45 RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread()
45 { 46 {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 // Just before the multicol container (our parent RenderBlockFlow) finis hes laying out, it 156 // Just before the multicol container (our parent RenderBlockFlow) finis hes laying out, it
156 // will call recalculateColumnHeights() on us unconditionally, but we on ly want that method 157 // will call recalculateColumnHeights() on us unconditionally, but we on ly want that method
157 // to do any work if we actually laid out the flow thread. Otherwise, th e balancing 158 // to do any work if we actually laid out the flow thread. Otherwise, th e balancing
158 // machinery would kick in needlessly, and trigger additional layout pas ses. Furthermore, we 159 // machinery would kick in needlessly, and trigger additional layout pas ses. Furthermore, we
159 // actually depend on a proper flowthread layout pass in order to do bal ancing, since it's 160 // actually depend on a proper flowthread layout pass in order to do bal ancing, since it's
160 // flowthread layout that sets up content runs. 161 // flowthread layout that sets up content runs.
161 m_needsColumnHeightsRecalculation = false; 162 m_needsColumnHeightsRecalculation = false;
162 return; 163 return;
163 } 164 }
164 165
165 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet()) { 166 if (!m_inBalancingPass) {
166 if (!m_inBalancingPass) { 167 // This is the initial layout pass. We need to reset the column height, because contents
167 // This is the initial layout pass. We need to reset the column heig ht, because contents 168 // typically have changed.
168 // typically have changed. 169 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet())
169 columnSet->resetColumnHeight(); 170 columnSet->resetColumnHeight();
170 }
171 } 171 }
172 172
173 invalidateRegions(); 173 invalidateRegions();
174 m_needsColumnHeightsRecalculation = heightIsAuto(); 174 m_needsColumnHeightsRecalculation = true;
Julien - ping for review 2014/11/17 23:47:11 That seems overly broad as you will force recomput
mstensho (USE GERRIT) 2014/11/18 13:29:26 Done. You're right. There's no need for this if t
175 layout(); 175 layout();
176 } 176 }
177 177
178 bool RenderMultiColumnFlowThread::recalculateColumnHeights() 178 bool RenderMultiColumnFlowThread::recalculateColumnHeights()
179 { 179 {
180 // All column sets that needed layout have now been laid out, so we can fina lly validate them. 180 // All column sets that needed layout have now been laid out, so we can fina lly validate them.
181 validateRegions(); 181 validateRegions();
182 182
183 if (!m_needsColumnHeightsRecalculation) 183 if (!m_needsColumnHeightsRecalculation)
184 return false; 184 return false;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 m_spannerMap.clear(); 309 m_spannerMap.clear();
310 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they 310 // Detach all column sets from the flow thread. Cannot destroy them at this point, since they
311 // are siblings of this object, and there may be pointers to this object's s ibling somewhere 311 // are siblings of this object, and there may be pointers to this object's s ibling somewhere
312 // further up on the call stack. 312 // further up on the call stack.
313 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet()) 313 for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; col umnSet = columnSet->nextSiblingMultiColumnSet())
314 columnSet->detachRegion(); 314 columnSet->detachRegion();
315 multiColumnBlockFlow()->resetMultiColumnFlowThread(); 315 multiColumnBlockFlow()->resetMultiColumnFlowThread();
316 RenderFlowThread::willBeRemovedFromTree(); 316 RenderFlowThread::willBeRemovedFromTree();
317 } 317 }
318 318
319 bool RenderMultiColumnFlowThread::isColumnSpanner(const RenderObject* descendant ) const
320 {
321 ASSERT(descendant->isDescendantOf(this));
322 return m_spannerMap.get(descendant);
323 }
324
325 bool RenderMultiColumnFlowThread::isInsideColumnSpanner(const RenderObject* desc endant) const
326 {
327 ASSERT(descendant->isDescendantOf(this));
328 return containingColumnSpannerSet(descendant);
329 }
330
331 LayoutUnit RenderMultiColumnFlowThread::enterColumnSpannerBeforeLayout(RenderBox * renderer, LayoutUnit logicalTop, SubtreeLayoutScope& layoutScope)
332 {
333 ASSERT(renderer->isDescendantOf(this));
334 RenderMultiColumnSpannerSet* spannerSet = m_spannerMap.get(renderer);
335 ASSERT(spannerSet);
Julien - ping for review 2014/11/17 23:47:11 The 2 ASSERTs above could be replaced by: ASSERT(
mstensho (USE GERRIT) 2014/11/18 13:29:26 Done.
336
337 // FIXME: it's really only necessary to mark the spanner set for layout when the height of
338 // |renderer| changes.
339 spannerSet->setChildNeedsLayout(MarkOnlyThis, &layoutScope);
340
341 RenderMultiColumnSet* previousSet = spannerSet->previousSiblingMultiColumnSe t();
342 if (!previousSet) {
343 // The first set is entered at the beginning of flow thread layout. If t he first set happens
344 // to be a spanner, we have nothing more to do here.
345 return LayoutUnit();
346 }
347
348 RenderBlock* cb = renderer->containingBlock();
349 LayoutUnit logicalTopInFlowThread = cb->offsetFromLogicalTopOfFirstPage() + logicalTop;
350 LayoutUnit adjustment;
351 if (!previousSet->isRenderMultiColumnSpannerSet() && previousSet->pageLogica lHeight()) {
352 // Pad flow thread offset to a column boundary, so that contents that's supposed to come
353 // after the spanner (or the spanner itself) don't bleed into the column preceding the
354 // spanner.
355 LayoutUnit columnLogicalTopInFlowThread = previousSet->pageLogicalTopFor Offset(logicalTopInFlowThread);
356 if (columnLogicalTopInFlowThread != logicalTopInFlowThread) {
357 adjustment = columnLogicalTopInFlowThread + previousSet->pageLogical Height() - logicalTopInFlowThread;
358 logicalTopInFlowThread += adjustment;
359 }
360 }
361
362 if (!previousSet->isRenderMultiColumnSpannerSet())
363 previousSet->endFlow(logicalTopInFlowThread);
364 spannerSet->beginFlow(logicalTopInFlowThread);
365
366 m_lastSetWorkedOn = spannerSet;
367 return adjustment;
368 }
369
370 void RenderMultiColumnFlowThread::leaveColumnSpannerAfterLayout(RenderBox* rende rer, LayoutUnit logicalBottom)
371 {
372 ASSERT(m_lastSetWorkedOn == m_spannerMap.get(renderer));
373
374 RenderBlock* cb = renderer->containingBlock();
375 LayoutUnit logicalBottomInFlowThread = cb->offsetFromLogicalTopOfFirstPage() + logicalBottom;
376 m_lastSetWorkedOn->endFlow(logicalBottomInFlowThread);
377 RenderMultiColumnSet* nextSet = m_lastSetWorkedOn->nextSiblingMultiColumnSet ();
378 if (nextSet) {
379 m_lastSetWorkedOn = nextSet;
380 if (!m_lastSetWorkedOn->isRenderMultiColumnSpannerSet())
381 m_lastSetWorkedOn->beginFlow(logicalBottomInFlowThread);
382 }
383 }
384
319 void RenderMultiColumnFlowThread::flowThreadDescendantWasInserted(RenderObject* descendant) 385 void RenderMultiColumnFlowThread::flowThreadDescendantWasInserted(RenderObject* descendant)
320 { 386 {
321 // Go through the subtree that was just inserted and create column sets (nee ded by regular 387 // Go through the subtree that was just inserted and create column sets (nee ded by regular
322 // column content) and spanner sets (one needed by each spanner). 388 // column content) and spanner sets (one needed by each spanner).
323 for (RenderObject* renderer = descendant; renderer; renderer = renderer->nex tInPreOrder(descendant)) { 389 for (RenderObject* renderer = descendant; renderer; renderer = renderer->nex tInPreOrder(descendant)) {
324 if (containingColumnSpannerSet(renderer)) 390 if (containingColumnSpannerSet(renderer))
325 continue; // Inside a column spanner set. Nothing to do, then. 391 continue; // Inside a column spanner set. Nothing to do, then.
326 if (descendantIsValidColumnSpanner(renderer)) { 392 if (descendantIsValidColumnSpanner(renderer)) {
327 // This renderer is a spanner, so it needs to establish a spanner se t. 393 // This renderer is a spanner, so it needs to establish a spanner se t.
328 createAndInsertSpannerSet(toRenderBox(renderer)); 394 createAndInsertSpannerSet(toRenderBox(renderer));
(...skipping 15 matching lines...) Expand all
344 410
345 void RenderMultiColumnFlowThread::updateLogicalWidth() 411 void RenderMultiColumnFlowThread::updateLogicalWidth()
346 { 412 {
347 LayoutUnit columnWidth; 413 LayoutUnit columnWidth;
348 calculateColumnCountAndWidth(columnWidth, m_columnCount); 414 calculateColumnCountAndWidth(columnWidth, m_columnCount);
349 setLogicalWidth(columnWidth); 415 setLogicalWidth(columnWidth);
350 } 416 }
351 417
352 void RenderMultiColumnFlowThread::layout() 418 void RenderMultiColumnFlowThread::layout()
353 { 419 {
420 ASSERT(!m_lastSetWorkedOn);
421 m_lastSetWorkedOn = firstMultiColumnSet();
422 if (m_lastSetWorkedOn)
423 m_lastSetWorkedOn->beginFlow(LayoutUnit());
354 RenderFlowThread::layout(); 424 RenderFlowThread::layout();
355 if (RenderMultiColumnSet* lastSet = lastMultiColumnSet()) 425 if (RenderMultiColumnSet* lastSet = lastMultiColumnSet()) {
Julien - ping for review 2014/11/17 23:47:11 Are we not expecting that m_lastSetWorkedOn to be
mstensho (USE GERRIT) 2014/11/18 13:29:26 Done. Adding that assertion caused some tests to
426 lastSet->endFlow(logicalHeight());
356 lastSet->expandToEncompassFlowThreadContentsIfNeeded(); 427 lastSet->expandToEncompassFlowThreadContentsIfNeeded();
428 }
429 m_lastSetWorkedOn = 0;
357 } 430 }
358 431
359 void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spa ceShortage) 432 void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spa ceShortage)
360 { 433 {
361 // Only positive values are interesting (and allowed) here. Zero space short age may be reported 434 // Only positive values are interesting (and allowed) here. Zero space short age may be reported
362 // when we're at the top of a column and the element has zero height. Ignore this, and also 435 // when we're at the top of a column and the element has zero height. Ignore this, and also
363 // ignore any negative values, which may occur when we set an early break in order to honor 436 // ignore any negative values, which may occur when we set an early break in order to honor
364 // widows in the next column. 437 // widows in the next column.
365 if (spaceShortage <= 0) 438 if (spaceShortage <= 0)
366 return; 439 return;
367 440
368 if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) 441 if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset))
369 multicolSet->recordSpaceShortage(spaceShortage); 442 multicolSet->recordSpaceShortage(spaceShortage);
370 } 443 }
371 444
372 void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay outUnit minHeight) 445 void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay outUnit minHeight)
373 { 446 {
374 if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) 447 if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset))
375 multicolSet->updateMinimumColumnHeight(minHeight); 448 multicolSet->updateMinimumColumnHeight(minHeight);
376 } 449 }
377 450
378 RenderMultiColumnSet* RenderMultiColumnFlowThread::columnSetAtBlockOffset(Layout Unit /*offset*/) const 451 RenderMultiColumnSet* RenderMultiColumnFlowThread::columnSetAtBlockOffset(Layout Unit offset) const
379 { 452 {
380 // For now there's only one column set, so this is easy: 453 if (m_lastSetWorkedOn) {
381 return firstMultiColumnSet(); 454 // Layout in progress. We are calculating the set heights as we speak, s o the column set range
455 // information is not up-to-date.
456 // FIXME: need to check if m_lastSetWorkedOn contains the offset, and if it doesn't, we need
457 // to locate the right set.
Julien - ping for review 2014/11/17 23:47:11 This FIXME is actionable but it's not super clear
mstensho (USE GERRIT) 2014/11/18 13:29:26 Done. I'll just remove the FIXME. There are no te
458 return m_lastSetWorkedOn;
459 }
460
461 ASSERT(!m_regionsInvalidated);
462 if (offset <= 0)
463 return m_multiColumnSetList.isEmpty() ? 0 : m_multiColumnSetList.first() ;
464
465 MultiColumnSetSearchAdapter adapter(offset);
466 m_multiColumnSetIntervalTree.allOverlapsWithAdapter<MultiColumnSetSearchAdap ter>(adapter);
467
468 // If no set was found, the offset is in the flow thread overflow.
469 if (!adapter.result() && !m_multiColumnSetList.isEmpty())
470 return m_multiColumnSetList.last();
471 return adapter.result();
382 } 472 }
383 473
384 bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, Render Object* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment) 474 bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, Render Object* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment)
385 { 475 {
386 if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) { 476 if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) {
387 multicolSet->addContentRun(offset); 477 multicolSet->addContentRun(offset);
388 if (offsetBreakAdjustment) 478 if (offsetBreakAdjustment)
389 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit(); 479 *offsetBreakAdjustment = pageLogicalHeightForOffset(offset) ? pageRe mainingLogicalHeightForOffset(offset, IncludePageBoundary) : LayoutUnit();
390 return true; 480 return true;
391 } 481 }
392 return false; 482 return false;
393 } 483 }
394 484
395 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const 485 bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const
396 { 486 {
397 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet()) 487 if (RenderMultiColumnSet* columnSet = lastMultiColumnSet())
398 return columnSet->pageLogicalHeight(); 488 return columnSet->pageLogicalHeight();
399 return false; 489 return false;
400 } 490 }
401 491
402 } 492 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698