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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp

Issue 1834223008: All ancestor multicols must have enough rows before laying out some inner multicol. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Forgot to specify line-height in the ref Created 4 years, 8 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
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 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698