| 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 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 return adapter.result(); | 377 return adapter.result(); |
| 378 } | 378 } |
| 379 | 379 |
| 380 void LayoutMultiColumnFlowThread::layoutColumns(SubtreeLayoutScope& layoutScope) | 380 void LayoutMultiColumnFlowThread::layoutColumns(SubtreeLayoutScope& layoutScope) |
| 381 { | 381 { |
| 382 // Since we ended up here, it means that the multicol container (our parent)
needed | 382 // Since we ended up here, it means that the multicol container (our parent)
needed |
| 383 // layout. Since contents of the multicol container are diverted to the flow
thread, the flow | 383 // layout. Since contents of the multicol container are diverted to the flow
thread, the flow |
| 384 // thread needs layout as well. | 384 // thread needs layout as well. |
| 385 layoutScope.setChildNeedsLayout(this); | 385 layoutScope.setChildNeedsLayout(this); |
| 386 | 386 |
| 387 m_blockOffsetInEnclosingFragmentationContext = enclosingFragmentationContext
() ? multiColumnBlockFlow()->offsetFromLogicalTopOfFirstPage() : LayoutUnit(); | 387 if (FragmentationContext* enclosingFragmentationContext = this->enclosingFra
gmentationContext()) { |
| 388 m_blockOffsetInEnclosingFragmentationContext = multiColumnBlockFlow()->o
ffsetFromLogicalTopOfFirstPage(); |
| 389 |
| 390 if (LayoutMultiColumnFlowThread* enclosingFlowThread = enclosingFragment
ationContext->associatedFlowThread()) { |
| 391 if (LayoutMultiColumnSet* firstSet = firstMultiColumnSet()) { |
| 392 // Before we can start to lay out the contents of this multicol
container, we need |
| 393 // to make sure that all ancestor multicol containers have estab
lished a row to hold |
| 394 // the first column contents of this container (this multicol co
ntainer may start at |
| 395 // the beginning of a new outer row). Without sufficient rows in
all ancestor |
| 396 // multicol containers, we may use the wrong column height. |
| 397 LayoutUnit offset = m_blockOffsetInEnclosingFragmentationContext
+ firstSet->logicalTopFromMulticolContentEdge(); |
| 398 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(offset,
AssociateWithLatterPage); |
| 399 } |
| 400 } |
| 401 } |
| 388 | 402 |
| 389 for (LayoutBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = co
lumnBox->nextSiblingMultiColumnBox()) { | 403 for (LayoutBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = co
lumnBox->nextSiblingMultiColumnBox()) { |
| 390 if (!columnBox->isLayoutMultiColumnSet()) { | 404 if (!columnBox->isLayoutMultiColumnSet()) { |
| 391 ASSERT(columnBox->isLayoutMultiColumnSpannerPlaceholder()); // no ot
her type is expected. | 405 ASSERT(columnBox->isLayoutMultiColumnSpannerPlaceholder()); // no ot
her type is expected. |
| 392 continue; | 406 continue; |
| 393 } | 407 } |
| 394 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox); | 408 LayoutMultiColumnSet* columnSet = toLayoutMultiColumnSet(columnBox); |
| 395 layoutScope.setChildNeedsLayout(columnSet); | 409 layoutScope.setChildNeedsLayout(columnSet); |
| 396 if (!m_columnHeightsChanged) { | 410 if (!m_columnHeightsChanged) { |
| 397 // This is the initial layout pass. We need to reset the column heig
ht, because contents | 411 // This is the initial layout pass. We need to reset the column heig
ht, because contents |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 return nullptr; | 462 return nullptr; |
| 449 } | 463 } |
| 450 | 464 |
| 451 FragmentationContext* LayoutMultiColumnFlowThread::enclosingFragmentationContext
() const | 465 FragmentationContext* LayoutMultiColumnFlowThread::enclosingFragmentationContext
() const |
| 452 { | 466 { |
| 453 if (LayoutMultiColumnFlowThread* enclosingFlowThread = this->enclosingFlowTh
read()) | 467 if (LayoutMultiColumnFlowThread* enclosingFlowThread = this->enclosingFlowTh
read()) |
| 454 return enclosingFlowThread; | 468 return enclosingFlowThread; |
| 455 return view()->fragmentationContext(); | 469 return view()->fragmentationContext(); |
| 456 } | 470 } |
| 457 | 471 |
| 458 void LayoutMultiColumnFlowThread::appendNewFragmentainerGroupIfNeeded(LayoutUnit
bottomOffsetInFlowThread) | 472 void LayoutMultiColumnFlowThread::appendNewFragmentainerGroupIfNeeded(LayoutUnit
offsetInFlowThread, PageBoundaryRule pageBoundaryRule) |
| 459 { | 473 { |
| 460 if (!isPageLogicalHeightKnown()) { | 474 if (!isPageLogicalHeightKnown()) { |
| 461 // If we have no clue about the height of the multicol container, bail.
This situation | 475 // If we have no clue about the height of the multicol container, bail.
This situation |
| 462 // occurs initially when an auto-height multicol container is nested ins
ide another | 476 // occurs initially when an auto-height multicol container is nested ins
ide another |
| 463 // auto-height multicol container. We need at least an estimated height
of the outer | 477 // auto-height multicol container. We need at least an estimated height
of the outer |
| 464 // multicol container before we can check what an inner fragmentainer gr
oup has room for. | 478 // multicol container before we can check what an inner fragmentainer gr
oup has room for. |
| 465 // Its height is indefinite for now. | 479 // Its height is indefinite for now. |
| 466 return; | 480 return; |
| 467 } | 481 } |
| 468 // TODO(mstensho): bottomOffsetInFlowThread is an endpoint-exclusive offset,
i.e. the offset | 482 // TODO(mstensho): If pageBoundaryRule is AssociateWithFormerPage, offsetInF
lowThread is an |
| 469 // just after the bottom of some object. So, ideally, columnSetAtBlockOffset
() should be | 483 // endpoint-exclusive offset, i.e. the offset just after the bottom of some
object. So, ideally, |
| 470 // informed about this (i.e. take a PageBoundaryRule argument). This is not
the only place with | 484 // columnSetAtBlockOffset() should be informed about this (i.e. take a PageB
oundaryRule |
| 471 // this issue; see also pageRemainingLogicalHeightForOffset(). | 485 // argument). This is not the only place with this issue; see also |
| 472 LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(bottomOffsetInFlowT
hread); | 486 // pageRemainingLogicalHeightForOffset(). |
| 487 LayoutMultiColumnSet* columnSet = columnSetAtBlockOffset(offsetInFlowThread)
; |
| 473 if (columnSet->isInitialHeightCalculated()) { | 488 if (columnSet->isInitialHeightCalculated()) { |
| 474 // We only insert additional fragmentainer groups in the initial layout
pass. We only want | 489 // We only insert additional fragmentainer groups in the initial layout
pass. We only want |
| 475 // to balance columns in the last fragmentainer group (if we need to bal
ance at all), so we | 490 // to balance columns in the last fragmentainer group (if we need to bal
ance at all), so we |
| 476 // want that last fragmentainer group to be the same one in all layout p
asses that follow. | 491 // want that last fragmentainer group to be the same one in all layout p
asses that follow. |
| 477 return; | 492 return; |
| 478 } | 493 } |
| 479 | 494 |
| 480 if (!columnSet->hasFragmentainerGroupForColumnAt(bottomOffsetInFlowThread))
{ | 495 if (!columnSet->hasFragmentainerGroupForColumnAt(offsetInFlowThread, pageBou
ndaryRule)) { |
| 481 FragmentationContext* enclosingFragmentationContext = this->enclosingFra
gmentationContext(); | 496 FragmentationContext* enclosingFragmentationContext = this->enclosingFra
gmentationContext(); |
| 482 if (!enclosingFragmentationContext) | 497 if (!enclosingFragmentationContext) |
| 483 return; // Not nested. We'll never need more rows than the one we al
ready have then. | 498 return; // Not nested. We'll never need more rows than the one we al
ready have then. |
| 484 ASSERT(!isLayoutPagedFlowThread()); | 499 ASSERT(!isLayoutPagedFlowThread()); |
| 485 // We have run out of columns here, so we add another row to hold more c
olumns. When we add | 500 // We have run out of columns here, so we add another row to hold more c
olumns. When we add |
| 486 // a new row, it implicitly means that we're inserting another column in
our enclosing | 501 // a new row, it implicitly means that we're inserting another column in
our enclosing |
| 487 // multicol container. That in turn may mean that we've run out of colum
ns there too. | 502 // multicol container. That in turn may mean that we've run out of colum
ns there too. |
| 488 const MultiColumnFragmentainerGroup& newRow = columnSet->appendNewFragme
ntainerGroup(); | 503 const MultiColumnFragmentainerGroup& newRow = columnSet->appendNewFragme
ntainerGroup(); |
| 489 if (LayoutMultiColumnFlowThread* enclosingFlowThread = enclosingFragment
ationContext->associatedFlowThread()) | 504 if (LayoutMultiColumnFlowThread* enclosingFlowThread = enclosingFragment
ationContext->associatedFlowThread()) |
| 490 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(newRow.bloc
kOffsetInEnclosingFragmentationContext() + newRow.logicalHeight()); | 505 enclosingFlowThread->appendNewFragmentainerGroupIfNeeded(newRow.bloc
kOffsetInEnclosingFragmentationContext(), AssociateWithLatterPage); |
| 491 } | 506 } |
| 492 } | 507 } |
| 493 | 508 |
| 494 bool LayoutMultiColumnFlowThread::isFragmentainerLogicalHeightKnown() | 509 bool LayoutMultiColumnFlowThread::isFragmentainerLogicalHeightKnown() |
| 495 { | 510 { |
| 496 return isPageLogicalHeightKnown(); | 511 return isPageLogicalHeightKnown(); |
| 497 } | 512 } |
| 498 | 513 |
| 499 LayoutUnit LayoutMultiColumnFlowThread::fragmentainerLogicalHeightAt(LayoutUnit
blockOffset) | 514 LayoutUnit LayoutMultiColumnFlowThread::fragmentainerLogicalHeightAt(LayoutUnit
blockOffset) |
| 500 { | 515 { |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 // First figure out if there's any chance that we're nested at all. If we ca
n be sure that | 964 // First figure out if there's any chance that we're nested at all. If we ca
n be sure that |
| 950 // we're not, bail early. This code is run very often, and since locating a
containing flow | 965 // we're not, bail early. This code is run very often, and since locating a
containing flow |
| 951 // thread has some cost (depending on tree depth), avoid calling | 966 // thread has some cost (depending on tree depth), avoid calling |
| 952 // enclosingFragmentationContext() right away. This test may give some false
positives (hence | 967 // enclosingFragmentationContext() right away. This test may give some false
positives (hence |
| 953 // the "mayBe"), if we're in an out-of-flow subtree and have an outer multic
ol container that | 968 // the "mayBe"), if we're in an out-of-flow subtree and have an outer multic
ol container that |
| 954 // doesn't affect us, but that's okay. We'll discover that further down the
road when trying to | 969 // doesn't affect us, but that's okay. We'll discover that further down the
road when trying to |
| 955 // locate our enclosing flow thread for real. | 970 // locate our enclosing flow thread for real. |
| 956 bool mayBeNested = multiColumnBlockFlow()->isInsideFlowThread() || view()->f
ragmentationContext(); | 971 bool mayBeNested = multiColumnBlockFlow()->isInsideFlowThread() || view()->f
ragmentationContext(); |
| 957 if (!mayBeNested) | 972 if (!mayBeNested) |
| 958 return; | 973 return; |
| 959 appendNewFragmentainerGroupIfNeeded(logicalBottomInFlowThreadAfterPagination
); | 974 appendNewFragmentainerGroupIfNeeded(logicalBottomInFlowThreadAfterPagination
, AssociateWithFormerPage); |
| 960 } | 975 } |
| 961 | 976 |
| 962 bool LayoutMultiColumnFlowThread::canSkipLayout(const LayoutBox& root) const | 977 bool LayoutMultiColumnFlowThread::canSkipLayout(const LayoutBox& root) const |
| 963 { | 978 { |
| 964 // Objects containing spanners is all we need to worry about, so if there ar
e no spanners at all | 979 // Objects containing spanners is all we need to worry about, so if there ar
e no spanners at all |
| 965 // in this multicol container, we can just return the good news right away. | 980 // in this multicol container, we can just return the good news right away. |
| 966 if (!hasAnyColumnSpanners(*this)) | 981 if (!hasAnyColumnSpanners(*this)) |
| 967 return true; | 982 return true; |
| 968 | 983 |
| 969 LayoutObject* next; | 984 LayoutObject* next; |
| 970 for (const LayoutObject* object = &root; object; object = next) { | 985 for (const LayoutObject* object = &root; object; object = next) { |
| 971 if (object->isColumnSpanAll()) { | 986 if (object->isColumnSpanAll()) { |
| 972 // A spanner potentially ends one fragmentainer group and begins a n
ew one, and thus | 987 // A spanner potentially ends one fragmentainer group and begins a n
ew one, and thus |
| 973 // determines the flow thread portion bottom and top of adjacent fra
gmentainer | 988 // determines the flow thread portion bottom and top of adjacent fra
gmentainer |
| 974 // groups. It's just too hard to guess these values without laying o
ut. | 989 // groups. It's just too hard to guess these values without laying o
ut. |
| 975 return false; | 990 return false; |
| 976 } | 991 } |
| 977 if (canContainSpannerInParentFragmentationContext(*object)) | 992 if (canContainSpannerInParentFragmentationContext(*object)) |
| 978 next = object->nextInPreOrder(&root); | 993 next = object->nextInPreOrder(&root); |
| 979 else | 994 else |
| 980 next = object->nextInPreOrderAfterChildren(&root); | 995 next = object->nextInPreOrderAfterChildren(&root); |
| 981 } | 996 } |
| 982 return true; | 997 return true; |
| 983 } | 998 } |
| 984 | 999 |
| 985 } // namespace blink | 1000 } // namespace blink |
| OLD | NEW |