OLD | NEW |
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 Loading... |
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(§ion); |
| 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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |