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

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

Issue 2421613002: Lay out table children in visual order, and set position and size. (Closed)
Patch Set: Created 4 years, 2 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
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutTable.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3 * (C) 1997 Torben Weis (weis@kde.org) 3 * (C) 1997 Torben Weis (weis@kde.org)
4 * (C) 1998 Waldo Bastian (bastian@kde.org) 4 * (C) 1998 Waldo Bastian (bastian@kde.org)
5 * (C) 1999 Lars Knoll (knoll@kde.org) 5 * (C) 1999 Lars Knoll (knoll@kde.org)
6 * (C) 1999 Antti Koivisto (koivisto@kde.org) 6 * (C) 1999 Antti Koivisto (koivisto@kde.org)
7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc.
8 * All rights reserved. 8 * All rights reserved.
9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) 9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
10 * 10 *
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 } else if (styleLogicalHeight.isIntrinsic()) { 405 } else if (styleLogicalHeight.isIntrinsic()) {
406 computedLogicalHeight = computeIntrinsicLogicalContentHeightUsing( 406 computedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(
407 styleLogicalHeight, logicalHeight() - borderAndPadding, 407 styleLogicalHeight, logicalHeight() - borderAndPadding,
408 borderAndPadding); 408 borderAndPadding);
409 } else { 409 } else {
410 ASSERT_NOT_REACHED(); 410 ASSERT_NOT_REACHED();
411 } 411 }
412 return computedLogicalHeight.clampNegativeToZero(); 412 return computedLogicalHeight.clampNegativeToZero();
413 } 413 }
414 414
415 void LayoutTable::layoutCaption(LayoutTableCaption& caption) { 415 void LayoutTable::layoutCaption(LayoutTableCaption& caption,
416 SubtreeLayoutScope& layouter) {
417 if (!caption.needsLayout())
418 markChildForPaginationRelayoutIfNeeded(caption, layouter);
416 if (caption.needsLayout()) { 419 if (caption.needsLayout()) {
417 // The margins may not be available but ensure the caption is at least 420 // The margins may not be available but ensure the caption is at least
418 // located beneath any previous sibling caption so that it does not 421 // located beneath any previous sibling caption so that it does not
419 // mistakenly think any floats in the previous caption intrude into it. 422 // mistakenly think any floats in the previous caption intrude into it.
420 caption.setLogicalLocation( 423 caption.setLogicalLocation(
421 LayoutPoint(caption.marginStart(), 424 LayoutPoint(caption.marginStart(),
422 collapsedMarginBeforeForChild(caption) + logicalHeight())); 425 collapsedMarginBeforeForChild(caption) + logicalHeight()));
423 // If LayoutTableCaption ever gets a layout() function, use it here. 426 // If LayoutTableCaption ever gets a layout() function, use it here.
424 caption.layoutIfNeeded(); 427 caption.layoutIfNeeded();
425 } 428 }
426 // Apply the margins to the location now that they are definitely available 429 // Apply the margins to the location now that they are definitely available
427 // from layout 430 // from layout
428 LayoutUnit captionLogicalTop = 431 LayoutUnit captionLogicalTop =
429 collapsedMarginBeforeForChild(caption) + logicalHeight(); 432 collapsedMarginBeforeForChild(caption) + logicalHeight();
430 caption.setLogicalLocation( 433 caption.setLogicalLocation(
431 LayoutPoint(caption.marginStart(), captionLogicalTop)); 434 LayoutPoint(caption.marginStart(), captionLogicalTop));
432 435
433 if (!selfNeedsLayout()) 436 if (!selfNeedsLayout())
434 caption.setMayNeedPaintInvalidation(); 437 caption.setMayNeedPaintInvalidation();
435 438
436 setLogicalHeight(logicalHeight() + caption.logicalHeight() + 439 setLogicalHeight(logicalHeight() + caption.logicalHeight() +
437 collapsedMarginBeforeForChild(caption) + 440 collapsedMarginBeforeForChild(caption) +
438 collapsedMarginAfterForChild(caption)); 441 collapsedMarginAfterForChild(caption));
439 } 442 }
440 443
444 void LayoutTable::layoutSection(LayoutTableSection& section,
445 SubtreeLayoutScope& layouter,
446 LayoutUnit logicalLeft) {
447 section.setLogicalLocation(LayoutPoint(logicalLeft, logicalHeight()));
448 if (m_columnLogicalWidthChanged)
449 layouter.setChildNeedsLayout(&section);
450 if (!section.needsLayout())
451 markChildForPaginationRelayoutIfNeeded(section, layouter);
452 section.layoutIfNeeded();
453 int sectionLogicalHeight = section.calcRowLogicalHeight();
454 section.setLogicalHeight(LayoutUnit(sectionLogicalHeight));
455 setLogicalHeight(logicalHeight() + sectionLogicalHeight);
456 }
457
441 void LayoutTable::distributeExtraLogicalHeight(int extraLogicalHeight) { 458 void LayoutTable::distributeExtraLogicalHeight(int extraLogicalHeight) {
442 if (extraLogicalHeight <= 0) 459 if (extraLogicalHeight <= 0)
443 return; 460 return;
444 461
445 // FIXME: Distribute the extra logical height between all table sections 462 // FIXME: Distribute the extra logical height between all table sections
446 // instead of giving it all to the first one. 463 // instead of giving it all to the first one.
447 if (LayoutTableSection* section = firstBody()) 464 if (LayoutTableSection* section = firstBody())
448 extraLogicalHeight -= 465 extraLogicalHeight -=
449 section->distributeExtraLogicalHeightToRows(extraLogicalHeight); 466 section->distributeExtraLogicalHeightToRows(extraLogicalHeight);
450 467
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 TextAutosizer::LayoutScope textAutosizerLayoutScope(this); 523 TextAutosizer::LayoutScope textAutosizerLayoutScope(this);
507 524
508 recalcSectionsIfNeeded(); 525 recalcSectionsIfNeeded();
509 // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we 526 // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we
510 // don't have to make sure to call this before we call borderStart/borderEnd 527 // don't have to make sure to call this before we call borderStart/borderEnd
511 // to avoid getting a stale value. 528 // to avoid getting a stale value.
512 recalcBordersInRowDirection(); 529 recalcBordersInRowDirection();
513 530
514 SubtreeLayoutScope layouter(*this); 531 SubtreeLayoutScope layouter(*this);
515 532
516 // If any table section moved vertically, we will just issue paint
517 // invalidations for everything from that section down (it is quite unlikely
518 // that any of the following sections did not shift).
519 bool sectionMoved = false;
520 { 533 {
521 LayoutState state(*this, locationOffset()); 534 LayoutState state(*this, locationOffset());
522 LayoutUnit oldLogicalWidth = logicalWidth(); 535 LayoutUnit oldLogicalWidth = logicalWidth();
523 LayoutUnit oldLogicalHeight = logicalHeight(); 536 LayoutUnit oldLogicalHeight = logicalHeight();
524 537
525 setLogicalHeight(LayoutUnit()); 538 setLogicalHeight(LayoutUnit());
526 updateLogicalWidth(); 539 updateLogicalWidth();
527 540
528 if (logicalWidth() != oldLogicalWidth) { 541 if (logicalWidth() != oldLogicalWidth) {
529 for (unsigned i = 0; i < m_captions.size(); i++) 542 for (unsigned i = 0; i < m_captions.size(); i++)
530 layouter.setNeedsLayout(m_captions[i], 543 layouter.setNeedsLayout(m_captions[i],
531 LayoutInvalidationReason::TableChanged); 544 LayoutInvalidationReason::TableChanged);
532 } 545 }
533 // FIXME: The optimisation below doesn't work since the internal table 546 // FIXME: The optimisation below doesn't work since the internal table
534 // layout could have changed. We need to add a flag to the table 547 // layout could have changed. We need to add a flag to the table
535 // layout that tells us if something has changed in the min max 548 // layout that tells us if something has changed in the min max
536 // calculations to do it correctly. 549 // calculations to do it correctly.
537 // if ( oldWidth != width() || columns.size() + 1 != columnPos.size() ) 550 // if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
538 m_tableLayout->layout(); 551 m_tableLayout->layout();
539 552
540 LayoutUnit totalSectionLogicalHeight; 553 // Lay out top captions.
541 LayoutUnit oldTableLogicalTop; 554 // FIXME: Collapse caption margin.
542 for (unsigned i = 0; i < m_captions.size(); i++) 555 for (unsigned i = 0; i < m_captions.size(); i++) {
543 oldTableLogicalTop += m_captions[i]->logicalHeight() + 556 if (m_captions[i]->style()->captionSide() == ECaptionSide::Bottom)
544 m_captions[i]->marginBefore() + 557 continue;
545 m_captions[i]->marginAfter(); 558 layoutCaption(*m_captions[i], layouter);
559 }
560
561 LayoutTableSection* topSection = this->topSection();
562 LayoutTableSection* bottomSection = this->bottomSection();
563
564 // This is the border-before edge of the "table box", relative to the "table
565 // wrapper box", i.e. right after all top captions.
566 // https://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#model
567 LayoutUnit tableBoxLogicalTop = logicalHeight();
546 568
547 bool collapsing = collapseBorders(); 569 bool collapsing = collapseBorders();
548 570 if (collapsing) {
549 for (LayoutObject* child = firstChild(); child; 571 // Need to set up the table borders before we can position the sections.
550 child = child->nextSibling()) { 572 for (LayoutTableSection* section = topSection; section;
551 if (!child->needsLayout() && child->isBox()) 573 section = sectionBelow(section))
552 markChildForPaginationRelayoutIfNeeded(*toLayoutBox(child), layouter); 574 section->recalcOuterBorder();
553 if (child->isTableSection()) {
554 LayoutTableSection* section = toLayoutTableSection(child);
555 if (m_columnLogicalWidthChanged)
556 layouter.setChildNeedsLayout(section);
557 section->layoutIfNeeded();
558 totalSectionLogicalHeight += section->calcRowLogicalHeight();
559 if (collapsing)
560 section->recalcOuterBorder();
561 ASSERT(!section->needsLayout());
562 } else if (child->isLayoutTableCol()) {
563 child->layoutIfNeeded();
564 ASSERT(!child->needsLayout());
565 } else {
566 // FIXME: We should never have other type of children (they should be
567 // wrapped in an anonymous table section) but our code is too crazy and
568 // this can happen in practice. Until this is fixed, let's make sure we
569 // don't leave non laid out children in the tree.
570 child->layoutIfNeeded();
571 }
572 }
573
574 // FIXME: Collapse caption margin.
575 if (!m_captions.isEmpty()) {
576 for (unsigned i = 0; i < m_captions.size(); i++) {
577 if (m_captions[i]->style()->captionSide() == ECaptionSide::Bottom)
578 continue;
579 layoutCaption(*m_captions[i]);
580 }
581 sectionMoved = logicalHeight() != oldTableLogicalTop;
582 } 575 }
583 576
584 LayoutUnit borderAndPaddingBefore = 577 LayoutUnit borderAndPaddingBefore =
585 borderBefore() + (collapsing ? LayoutUnit() : paddingBefore()); 578 borderBefore() + (collapsing ? LayoutUnit() : paddingBefore());
586 LayoutUnit borderAndPaddingAfter = 579 LayoutUnit borderAndPaddingAfter =
587 borderAfter() + (collapsing ? LayoutUnit() : paddingAfter()); 580 borderAfter() + (collapsing ? LayoutUnit() : paddingAfter());
588 581
589 setLogicalHeight(logicalHeight() + borderAndPaddingBefore); 582 setLogicalHeight(tableBoxLogicalTop + borderAndPaddingBefore);
583
584 LayoutUnit sectionLogicalLeft = LayoutUnit(
585 style()->isLeftToRightDirection() ? borderStart() : borderEnd());
586 if (!collapsing) {
587 sectionLogicalLeft +=
588 style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
589 }
590
591 // Lay out table header group.
592 if (LayoutTableSection* section = header())
593 layoutSection(*section, layouter, sectionLogicalLeft);
594
595 // Lay out table body groups, and column groups.
596 for (LayoutObject* child = firstChild(); child;
597 child = child->nextSibling()) {
598 if (child->isTableSection()) {
599 if (child != header() && child != footer()) {
600 LayoutTableSection& section = *toLayoutTableSection(child);
601 layoutSection(section, layouter, sectionLogicalLeft);
602 }
603 } else if (child->isLayoutTableCol()) {
604 child->layoutIfNeeded();
605 } else {
606 DCHECK(child->isTableCaption());
607 }
608 }
609
610 // Lay out table footer.
611 if (LayoutTableSection* section = footer())
612 layoutSection(*section, layouter, sectionLogicalLeft);
613
614 setLogicalHeight(tableBoxLogicalTop + borderAndPaddingBefore);
590 615
591 LayoutUnit computedLogicalHeight; 616 LayoutUnit computedLogicalHeight;
592 617
593 Length logicalHeightLength = style()->logicalHeight(); 618 Length logicalHeightLength = style()->logicalHeight();
594 if (logicalHeightLength.isIntrinsic() || 619 if (logicalHeightLength.isIntrinsic() ||
595 (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive())) 620 (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive()))
596 computedLogicalHeight = 621 computedLogicalHeight =
597 convertStyleLogicalHeightToComputedHeight(logicalHeightLength); 622 convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
598 623
599 Length logicalMaxHeightLength = style()->logicalMaxHeight(); 624 Length logicalMaxHeightLength = style()->logicalMaxHeight();
600 if (logicalMaxHeightLength.isIntrinsic() || 625 if (logicalMaxHeightLength.isIntrinsic() ||
601 (logicalMaxHeightLength.isSpecified() && 626 (logicalMaxHeightLength.isSpecified() &&
602 !logicalMaxHeightLength.isNegative())) { 627 !logicalMaxHeightLength.isNegative())) {
603 LayoutUnit computedMaxLogicalHeight = 628 LayoutUnit computedMaxLogicalHeight =
604 convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength); 629 convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength);
605 computedLogicalHeight = 630 computedLogicalHeight =
606 std::min(computedLogicalHeight, computedMaxLogicalHeight); 631 std::min(computedLogicalHeight, computedMaxLogicalHeight);
607 } 632 }
608 633
609 Length logicalMinHeightLength = style()->logicalMinHeight(); 634 Length logicalMinHeightLength = style()->logicalMinHeight();
610 if (logicalMinHeightLength.isIntrinsic() || 635 if (logicalMinHeightLength.isIntrinsic() ||
611 (logicalMinHeightLength.isSpecified() && 636 (logicalMinHeightLength.isSpecified() &&
612 !logicalMinHeightLength.isNegative())) { 637 !logicalMinHeightLength.isNegative())) {
613 LayoutUnit computedMinLogicalHeight = 638 LayoutUnit computedMinLogicalHeight =
614 convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength); 639 convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
615 computedLogicalHeight = 640 computedLogicalHeight =
616 std::max(computedLogicalHeight, computedMinLogicalHeight); 641 std::max(computedLogicalHeight, computedMinLogicalHeight);
617 } 642 }
618 643
644 LayoutUnit totalSectionLogicalHeight;
645 if (topSection) {
646 totalSectionLogicalHeight =
647 bottomSection->logicalBottom() - topSection->logicalTop();
648 }
649
619 distributeExtraLogicalHeight( 650 distributeExtraLogicalHeight(
620 floorToInt(computedLogicalHeight - totalSectionLogicalHeight)); 651 floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
621 652
622 bool isPaginated = view()->layoutState()->isPaginated(); 653 bool isPaginated = view()->layoutState()->isPaginated();
623 LayoutTableSection* topSection = this->topSection();
624 LayoutUnit logicalOffset = 654 LayoutUnit logicalOffset =
625 topSection ? topSection->logicalTop() : LayoutUnit(); 655 topSection ? topSection->logicalTop() : LayoutUnit();
626 for (LayoutTableSection* section = topSection; section; 656 for (LayoutTableSection* section = topSection; section;
627 section = sectionBelow(section)) { 657 section = sectionBelow(section)) {
628 section->setLogicalTop(logicalOffset); 658 section->setLogicalTop(logicalOffset);
629 section->layoutRows(); 659 section->layoutRows();
630 logicalOffset += section->logicalHeight(); 660 logicalOffset += section->logicalHeight();
631 // If the section is a repeating header group that allows at least one row 661 // If the section is a repeating header group that allows at least one row
632 // of content then store the offset for other sections to offset their 662 // of content then store the offset for other sections to offset their
633 // rows against. 663 // rows against.
(...skipping 11 matching lines...) Expand all
645 } 675 }
646 } 676 }
647 677
648 if (!topSection && computedLogicalHeight > totalSectionLogicalHeight && 678 if (!topSection && computedLogicalHeight > totalSectionLogicalHeight &&
649 !document().inQuirksMode()) { 679 !document().inQuirksMode()) {
650 // Completely empty tables (with no sections or anything) should at least 680 // Completely empty tables (with no sections or anything) should at least
651 // honor specified height in strict mode. 681 // honor specified height in strict mode.
652 setLogicalHeight(logicalHeight() + computedLogicalHeight); 682 setLogicalHeight(logicalHeight() + computedLogicalHeight);
653 } 683 }
654 684
655 LayoutUnit sectionLogicalLeft = LayoutUnit(
656 style()->isLeftToRightDirection() ? borderStart() : borderEnd());
657 if (!collapsing)
658 sectionLogicalLeft +=
659 style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
660
661 // position the table sections 685 // position the table sections
662 LayoutTableSection* section = topSection; 686 LayoutTableSection* section = topSection;
663 while (section) { 687 while (section) {
664 if (!sectionMoved && section->logicalTop() != logicalHeight())
665 sectionMoved = true;
666 section->setLogicalLocation( 688 section->setLogicalLocation(
667 LayoutPoint(sectionLogicalLeft, logicalHeight())); 689 LayoutPoint(sectionLogicalLeft, logicalHeight()));
668 690
669 // As we may skip invalidation on the table, we need to ensure that
670 // sections are invalidated when they moved.
671 if (sectionMoved && !section->selfNeedsLayout())
672 section->setMayNeedPaintInvalidation();
673
674 setLogicalHeight(logicalHeight() + section->logicalHeight()); 691 setLogicalHeight(logicalHeight() + section->logicalHeight());
675 692
676 section->updateLayerTransformAfterLayout(); 693 section->updateLayerTransformAfterLayout();
677 section->addVisualEffectOverflow(); 694 section->addVisualEffectOverflow();
678 695
679 section = sectionBelow(section); 696 section = sectionBelow(section);
680 } 697 }
681 698
682 setLogicalHeight(logicalHeight() + borderAndPaddingAfter); 699 setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
683 700
701 // Lay out bottom captions.
684 for (unsigned i = 0; i < m_captions.size(); i++) { 702 for (unsigned i = 0; i < m_captions.size(); i++) {
685 if (m_captions[i]->style()->captionSide() != ECaptionSide::Bottom) 703 if (m_captions[i]->style()->captionSide() != ECaptionSide::Bottom)
686 continue; 704 continue;
687 layoutCaption(*m_captions[i]); 705 layoutCaption(*m_captions[i], layouter);
688 } 706 }
689 707
690 updateLogicalHeight(); 708 updateLogicalHeight();
691 709
692 // table can be containing block of positioned elements. 710 // table can be containing block of positioned elements.
693 bool dimensionChanged = oldLogicalWidth != logicalWidth() || 711 bool dimensionChanged = oldLogicalWidth != logicalWidth() ||
694 oldLogicalHeight != logicalHeight(); 712 oldLogicalHeight != logicalHeight();
695 layoutPositionedObjects(dimensionChanged); 713 layoutPositionedObjects(dimensionChanged);
696 714
697 updateLayerTransformAfterLayout(); 715 updateLayerTransformAfterLayout();
(...skipping 962 matching lines...) Expand 10 before | Expand all | Expand 10 after
1660 } 1678 }
1661 1679
1662 LayoutUnit LayoutTable::paddingRight() const { 1680 LayoutUnit LayoutTable::paddingRight() const {
1663 if (collapseBorders()) 1681 if (collapseBorders())
1664 return LayoutUnit(); 1682 return LayoutUnit();
1665 1683
1666 return LayoutBlock::paddingRight(); 1684 return LayoutBlock::paddingRight();
1667 } 1685 }
1668 1686
1669 } // namespace blink 1687 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutTable.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698