| OLD | NEW |
| 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 10 matching lines...) Expand all Loading... |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 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/layout/LayoutMultiColumnFlowThread.h" | 27 #include "core/layout/LayoutMultiColumnFlowThread.h" |
| 28 | 28 |
| 29 #include "core/layout/LayoutMultiColumnSet.h" | 29 #include "core/layout/LayoutMultiColumnSet.h" |
| 30 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h" | 30 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h" |
| 31 #include "core/layout/LayoutView.h" |
| 31 #include "core/layout/MultiColumnFragmentainerGroup.h" | 32 #include "core/layout/MultiColumnFragmentainerGroup.h" |
| 33 #include "core/layout/ViewFragmentationContext.h" |
| 32 | 34 |
| 33 namespace blink { | 35 namespace blink { |
| 34 | 36 |
| 35 LayoutMultiColumnFlowThread::LayoutMultiColumnFlowThread() | 37 LayoutMultiColumnFlowThread::LayoutMultiColumnFlowThread() |
| 36 : m_lastSetWorkedOn(nullptr) | 38 : m_lastSetWorkedOn(nullptr) |
| 37 , m_columnCount(1) | 39 , m_columnCount(1) |
| 38 , m_columnHeightAvailable(0) | 40 , m_columnHeightAvailable(0) |
| 39 , m_inBalancingPass(false) | 41 , m_inBalancingPass(false) |
| 40 , m_needsColumnHeightsRecalculation(false) | 42 , m_needsColumnHeightsRecalculation(false) |
| 41 , m_progressionIsInline(true) | 43 , m_progressionIsInline(true) |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 | 350 |
| 349 void LayoutMultiColumnFlowThread::layoutColumns(SubtreeLayoutScope& layoutScope) | 351 void LayoutMultiColumnFlowThread::layoutColumns(SubtreeLayoutScope& layoutScope) |
| 350 { | 352 { |
| 351 // Since we ended up here, it means that the multicol container (our parent)
needed | 353 // Since we ended up here, it means that the multicol container (our parent)
needed |
| 352 // layout. Since contents of the multicol container are diverted to the flow
thread, the flow | 354 // layout. Since contents of the multicol container are diverted to the flow
thread, the flow |
| 353 // thread needs layout as well. | 355 // thread needs layout as well. |
| 354 layoutScope.setChildNeedsLayout(this); | 356 layoutScope.setChildNeedsLayout(this); |
| 355 | 357 |
| 356 m_needsColumnHeightsRecalculation = false; | 358 m_needsColumnHeightsRecalculation = false; |
| 357 | 359 |
| 358 m_blockOffsetInEnclosingFlowThread = enclosingFlowThread() ? multiColumnBloc
kFlow()->offsetFromLogicalTopOfFirstPage() : LayoutUnit(); | 360 m_blockOffsetInEnclosingFragmentationContext = enclosingFragmentationContext
() ? multiColumnBlockFlow()->offsetFromLogicalTopOfFirstPage() : LayoutUnit(); |
| 359 | 361 |
| 360 for (LayoutBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = co
lumnBox->nextSiblingMultiColumnBox()) { | 362 for (LayoutBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = co
lumnBox->nextSiblingMultiColumnBox()) { |
| 361 if (!columnBox->isLayoutMultiColumnSet()) { | 363 if (!columnBox->isLayoutMultiColumnSet()) { |
| 362 ASSERT(columnBox->isLayoutMultiColumnSpannerPlaceholder()); // no ot
her type is expected. | 364 ASSERT(columnBox->isLayoutMultiColumnSpannerPlaceholder()); // no ot
her type is expected. |
| 363 m_needsColumnHeightsRecalculation = true; | 365 m_needsColumnHeightsRecalculation = true; |
| 364 continue; | 366 continue; |
| 365 } | 367 } |
| 366 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox); | 368 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox); |
| 367 layoutScope.setChildNeedsLayout(columnSet); | 369 layoutScope.setChildNeedsLayout(columnSet); |
| 368 if (!m_inBalancingPass) { | 370 if (!m_inBalancingPass) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 return true; | 434 return true; |
| 433 } | 435 } |
| 434 | 436 |
| 435 LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::enclosingFlowThread()
const | 437 LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::enclosingFlowThread()
const |
| 436 { | 438 { |
| 437 if (multiColumnBlockFlow()->isInsideFlowThread()) | 439 if (multiColumnBlockFlow()->isInsideFlowThread()) |
| 438 return toLayoutMultiColumnFlowThread(locateFlowThreadContainingBlockOf(*
multiColumnBlockFlow())); | 440 return toLayoutMultiColumnFlowThread(locateFlowThreadContainingBlockOf(*
multiColumnBlockFlow())); |
| 439 return nullptr; | 441 return nullptr; |
| 440 } | 442 } |
| 441 | 443 |
| 444 FragmentationContext* LayoutMultiColumnFlowThread::enclosingFragmentationContext
() const |
| 445 { |
| 446 if (LayoutMultiColumnFlowThread* enclosingFlowThread = this->enclosingFlowTh
read()) |
| 447 return enclosingFlowThread; |
| 448 return view()->fragmentationContext(); |
| 449 } |
| 450 |
| 442 void LayoutMultiColumnFlowThread::appendNewFragmentainerGroupIfNeeded(LayoutUnit
offsetInFlowThread) | 451 void LayoutMultiColumnFlowThread::appendNewFragmentainerGroupIfNeeded(LayoutUnit
offsetInFlowThread) |
| 443 { | 452 { |
| 444 if (!isPageLogicalHeightKnown()) { | 453 if (!isPageLogicalHeightKnown()) { |
| 445 // If we have no clue about the height of the multicol container, bail.
This situation | 454 // If we have no clue about the height of the multicol container, bail.
This situation |
| 446 // occurs initially when an auto-height multicol container is nested ins
ide another | 455 // occurs initially when an auto-height multicol container is nested ins
ide another |
| 447 // auto-height multicol container. We need at least an estimated height
of the outer | 456 // auto-height multicol container. We need at least an estimated height
of the outer |
| 448 // multicol container before we can check what an inner fragmentainer gr
oup has room for. | 457 // multicol container before we can check what an inner fragmentainer gr
oup has room for. |
| 449 // Its height is indefinite for now. | 458 // Its height is indefinite for now. |
| 450 return; | 459 return; |
| 451 } | 460 } |
| 452 LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offsetInFlowThread)
; | 461 LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offsetInFlowThread)
; |
| 453 if (columnSet->isInitialHeightCalculated()) { | 462 if (columnSet->isInitialHeightCalculated()) { |
| 454 // We only insert additional fragmentainer groups in the initial layout
pass. We only want | 463 // We only insert additional fragmentainer groups in the initial layout
pass. We only want |
| 455 // to balance columns in the last fragmentainer group (if we need to bal
ance at all), so we | 464 // to balance columns in the last fragmentainer group (if we need to bal
ance at all), so we |
| 456 // want that last fragmentainer group to be the same one in all layout p
asses that follow. | 465 // want that last fragmentainer group to be the same one in all layout p
asses that follow. |
| 457 return; | 466 return; |
| 458 } | 467 } |
| 459 | 468 |
| 460 if (!columnSet->hasFragmentainerGroupForColumnAt(offsetInFlowThread)) { | 469 if (!columnSet->hasFragmentainerGroupForColumnAt(offsetInFlowThread)) { |
| 461 LayoutMultiColumnFlowThread* enclosingFlowThread = this->enclosingFlowTh
read(); | 470 FragmentationContext* enclosingFragmentationContext = this->enclosingFra
gmentationContext(); |
| 462 if (!enclosingFlowThread) | 471 if (!enclosingFragmentationContext) |
| 463 return; // Not nested. We'll never need more rows than the one we al
ready have then. | 472 return; // Not nested. We'll never need more rows than the one we al
ready have then. |
| 464 | 473 |
| 465 // We have run out of columns here, so we add another row to hold more c
olumns. When we add | 474 // We have run out of columns here, so we add another row to hold more c
olumns. When we add |
| 466 // a new row, it implicitly means that we're inserting another column in
our enclosing | 475 // a new row, it implicitly means that we're inserting another column in
our enclosing |
| 467 // multicol container. That in turn may mean that we've run out of colum
ns there too. | 476 // multicol container. That in turn may mean that we've run out of colum
ns there too. |
| 468 const MultiColumnFragmentainerGroup& newRow = columnSet->appendNewFragme
ntainerGroup(); | 477 const MultiColumnFragmentainerGroup& newRow = columnSet->appendNewFragme
ntainerGroup(); |
| 469 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(newRow.blockOff
setInEnclosingFlowThread()); | 478 if (LayoutMultiColumnFlowThread* enclosingFlowThread = enclosingFragment
ationContext->associatedFlowThread()) |
| 479 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(newRow.bloc
kOffsetInEnclosingFragmentationContext()); |
| 470 } | 480 } |
| 471 } | 481 } |
| 472 | 482 |
| 483 bool LayoutMultiColumnFlowThread::isFragmentainerLogicalHeightKnown() |
| 484 { |
| 485 return isPageLogicalHeightKnown(); |
| 486 } |
| 487 |
| 488 LayoutUnit LayoutMultiColumnFlowThread::fragmentainerLogicalHeightAt(LayoutUnit
blockOffset) |
| 489 { |
| 490 return pageLogicalHeightForOffset(blockOffset); |
| 491 } |
| 492 |
| 493 LayoutUnit LayoutMultiColumnFlowThread::remainingLogicalHeightAt(LayoutUnit bloc
kOffset) |
| 494 { |
| 495 return pageRemainingLogicalHeightForOffset(blockOffset, AssociateWithLatterP
age); |
| 496 } |
| 497 |
| 473 void LayoutMultiColumnFlowThread::calculateColumnCountAndWidth(LayoutUnit& width
, unsigned& count) const | 498 void LayoutMultiColumnFlowThread::calculateColumnCountAndWidth(LayoutUnit& width
, unsigned& count) const |
| 474 { | 499 { |
| 475 LayoutBlock* columnBlock = multiColumnBlockFlow(); | 500 LayoutBlock* columnBlock = multiColumnBlockFlow(); |
| 476 const ComputedStyle* columnStyle = columnBlock->style(); | 501 const ComputedStyle* columnStyle = columnBlock->style(); |
| 477 LayoutUnit availableWidth = columnBlock->contentLogicalWidth(); | 502 LayoutUnit availableWidth = columnBlock->contentLogicalWidth(); |
| 478 LayoutUnit columnGap = columnBlock->columnGap(); | 503 LayoutUnit columnGap = columnBlock->columnGap(); |
| 479 LayoutUnit computedColumnWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->
columnWidth())); | 504 LayoutUnit computedColumnWidth = max<LayoutUnit>(1, LayoutUnit(columnStyle->
columnWidth())); |
| 480 unsigned computedColumnCount = max<int>(1, columnStyle->columnCount()); | 505 unsigned computedColumnCount = max<int>(1, columnStyle->columnCount()); |
| 481 | 506 |
| 482 ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidt
h()); | 507 ASSERT(!columnStyle->hasAutoColumnCount() || !columnStyle->hasAutoColumnWidt
h()); |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 } | 933 } |
| 909 | 934 |
| 910 void LayoutMultiColumnFlowThread::contentWasLaidOut(LayoutUnit logicalTopInFlowT
hreadAfterPagination) | 935 void LayoutMultiColumnFlowThread::contentWasLaidOut(LayoutUnit logicalTopInFlowT
hreadAfterPagination) |
| 911 { | 936 { |
| 912 // Check if we need another fragmentainer group. If we've run out of columns
in the last | 937 // Check if we need another fragmentainer group. If we've run out of columns
in the last |
| 913 // fragmentainer group (column row), we need to insert another fragmentainer
group to hold more | 938 // fragmentainer group (column row), we need to insert another fragmentainer
group to hold more |
| 914 // columns. | 939 // columns. |
| 915 | 940 |
| 916 // First figure out if there's any chance that we're nested at all. If we ca
n be sure that | 941 // First figure out if there's any chance that we're nested at all. If we ca
n be sure that |
| 917 // we're not, bail early. This code is run very often, and since locating a
containing flow | 942 // we're not, bail early. This code is run very often, and since locating a
containing flow |
| 918 // thread has some cost (depending on tree depth), avoid calling enclosingFl
owThread() right | 943 // thread has some cost (depending on tree depth), avoid calling |
| 919 // away. This test may give some false positives (hence the "mayBe"), if we'
re in an | 944 // enclosingFragmentationContext() right away. This test may give some false
positives (hence |
| 920 // out-of-flow subtree and have an outer multicol container that doesn't aff
ect us, but that's | 945 // the "mayBe"), if we're in an out-of-flow subtree and have an outer multic
ol container that |
| 921 // okay. We'll discover that further down the road when trying to locate our
enclosing flow | 946 // doesn't affect us, but that's okay. We'll discover that further down the
road when trying to |
| 922 // thread for real. | 947 // locate our enclosing flow thread for real. |
| 923 bool mayBeNested = multiColumnBlockFlow()->isInsideFlowThread(); | 948 bool mayBeNested = multiColumnBlockFlow()->isInsideFlowThread() || view()->f
ragmentationContext(); |
| 924 if (!mayBeNested) | 949 if (!mayBeNested) |
| 925 return; | 950 return; |
| 926 appendNewFragmentainerGroupIfNeeded(logicalTopInFlowThreadAfterPagination); | 951 appendNewFragmentainerGroupIfNeeded(logicalTopInFlowThreadAfterPagination); |
| 927 } | 952 } |
| 928 | 953 |
| 929 } | 954 } |
| OLD | NEW |