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 |