OLD | NEW |
1 /* | 1 /* |
2 * This file is part of the layout object implementation for KHTML. | 2 * This file is part of the layout object implementation for KHTML. |
3 * | 3 * |
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
5 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 5 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
6 * Copyright (C) 2003 Apple Computer, Inc. | 6 * Copyright (C) 2003 Apple Computer, Inc. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 29 matching lines...) Expand all Loading... |
40 class FlexBoxIterator { | 40 class FlexBoxIterator { |
41 public: | 41 public: |
42 FlexBoxIterator(LayoutDeprecatedFlexibleBox* parent) | 42 FlexBoxIterator(LayoutDeprecatedFlexibleBox* parent) |
43 : m_box(parent), m_largestOrdinal(1) { | 43 : m_box(parent), m_largestOrdinal(1) { |
44 if (m_box->style()->boxOrient() == HORIZONTAL && | 44 if (m_box->style()->boxOrient() == HORIZONTAL && |
45 !m_box->style()->isLeftToRightDirection()) | 45 !m_box->style()->isLeftToRightDirection()) |
46 m_forward = m_box->style()->boxDirection() != BNORMAL; | 46 m_forward = m_box->style()->boxDirection() != BNORMAL; |
47 else | 47 else |
48 m_forward = m_box->style()->boxDirection() == BNORMAL; | 48 m_forward = m_box->style()->boxDirection() == BNORMAL; |
49 if (!m_forward) { | 49 if (!m_forward) { |
50 // No choice, since we're going backwards, we have to find out the highest
ordinal up front. | 50 // No choice, since we're going backwards, we have to find out the highest |
| 51 // ordinal up front. |
51 LayoutBox* child = m_box->firstChildBox(); | 52 LayoutBox* child = m_box->firstChildBox(); |
52 while (child) { | 53 while (child) { |
53 if (child->style()->boxOrdinalGroup() > m_largestOrdinal) | 54 if (child->style()->boxOrdinalGroup() > m_largestOrdinal) |
54 m_largestOrdinal = child->style()->boxOrdinalGroup(); | 55 m_largestOrdinal = child->style()->boxOrdinalGroup(); |
55 child = child->nextSiblingBox(); | 56 child = child->nextSiblingBox(); |
56 } | 57 } |
57 } | 58 } |
58 | 59 |
59 reset(); | 60 reset(); |
60 } | 61 } |
(...skipping 13 matching lines...) Expand all Loading... |
74 if (!m_currentChild) { | 75 if (!m_currentChild) { |
75 ++m_ordinalIteration; | 76 ++m_ordinalIteration; |
76 | 77 |
77 if (!m_ordinalIteration) { | 78 if (!m_ordinalIteration) { |
78 m_currentOrdinal = m_forward ? 1 : m_largestOrdinal; | 79 m_currentOrdinal = m_forward ? 1 : m_largestOrdinal; |
79 } else { | 80 } else { |
80 if (static_cast<size_t>(m_ordinalIteration) >= | 81 if (static_cast<size_t>(m_ordinalIteration) >= |
81 m_ordinalValues.size() + 1) | 82 m_ordinalValues.size() + 1) |
82 return nullptr; | 83 return nullptr; |
83 | 84 |
84 // Only copy+sort the values once per layout even if the iterator is r
eset. | 85 // Only copy+sort the values once per layout even if the iterator is |
| 86 // reset. |
85 if (m_ordinalValues.size() != m_sortedOrdinalValues.size()) { | 87 if (m_ordinalValues.size() != m_sortedOrdinalValues.size()) { |
86 copyToVector(m_ordinalValues, m_sortedOrdinalValues); | 88 copyToVector(m_ordinalValues, m_sortedOrdinalValues); |
87 std::sort(m_sortedOrdinalValues.begin(), | 89 std::sort(m_sortedOrdinalValues.begin(), |
88 m_sortedOrdinalValues.end()); | 90 m_sortedOrdinalValues.end()); |
89 } | 91 } |
90 m_currentOrdinal = | 92 m_currentOrdinal = |
91 m_forward ? m_sortedOrdinalValues[m_ordinalIteration - 1] | 93 m_forward ? m_sortedOrdinalValues[m_ordinalIteration - 1] |
92 : m_sortedOrdinalValues[m_sortedOrdinalValues.size() - | 94 : m_sortedOrdinalValues[m_sortedOrdinalValues.size() - |
93 m_ordinalIteration]; | 95 m_ordinalIteration]; |
94 } | 96 } |
(...skipping 23 matching lines...) Expand all Loading... |
118 LayoutDeprecatedFlexibleBox* m_box; | 120 LayoutDeprecatedFlexibleBox* m_box; |
119 LayoutBox* m_currentChild; | 121 LayoutBox* m_currentChild; |
120 bool m_forward; | 122 bool m_forward; |
121 unsigned m_currentOrdinal; | 123 unsigned m_currentOrdinal; |
122 unsigned m_largestOrdinal; | 124 unsigned m_largestOrdinal; |
123 HashSet<unsigned> m_ordinalValues; | 125 HashSet<unsigned> m_ordinalValues; |
124 Vector<unsigned> m_sortedOrdinalValues; | 126 Vector<unsigned> m_sortedOrdinalValues; |
125 int m_ordinalIteration; | 127 int m_ordinalIteration; |
126 }; | 128 }; |
127 | 129 |
128 // Helper methods for obtaining the last line, computing line counts and heights
for line counts | 130 // Helper methods for obtaining the last line, computing line counts and heights |
| 131 // for line counts |
129 // (crawling into blocks). | 132 // (crawling into blocks). |
130 static bool shouldCheckLines(LayoutBlockFlow* blockFlow) { | 133 static bool shouldCheckLines(LayoutBlockFlow* blockFlow) { |
131 return !blockFlow->isFloatingOrOutOfFlowPositioned() && | 134 return !blockFlow->isFloatingOrOutOfFlowPositioned() && |
132 blockFlow->style()->height().isAuto(); | 135 blockFlow->style()->height().isAuto(); |
133 } | 136 } |
134 | 137 |
135 static int getHeightForLineCount(const LayoutBlockFlow* blockFlow, | 138 static int getHeightForLineCount(const LayoutBlockFlow* blockFlow, |
136 int lineCount, | 139 int lineCount, |
137 bool includeBottom, | 140 bool includeBottom, |
138 int& count) { | 141 int& count) { |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 // The first walk over our kids is to find out if we have any flexible children. | 414 // The first walk over our kids is to find out if we have any flexible children. |
412 static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, | 415 static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, |
413 bool relayoutChildren, | 416 bool relayoutChildren, |
414 unsigned& highestFlexGroup, | 417 unsigned& highestFlexGroup, |
415 unsigned& lowestFlexGroup, | 418 unsigned& lowestFlexGroup, |
416 bool& haveFlex) { | 419 bool& haveFlex) { |
417 for (LayoutBox* child = iterator.first(); child; child = iterator.next()) { | 420 for (LayoutBox* child = iterator.first(); child; child = iterator.next()) { |
418 // Check to see if this child flexes. | 421 // Check to see if this child flexes. |
419 if (!childDoesNotAffectWidthOrFlexing(child) && | 422 if (!childDoesNotAffectWidthOrFlexing(child) && |
420 child->style()->boxFlex() > 0.0f) { | 423 child->style()->boxFlex() > 0.0f) { |
421 // We always have to lay out flexible objects again, since the flex distri
bution | 424 // We always have to lay out flexible objects again, since the flex |
| 425 // distribution |
422 // may have changed, and we need to reallocate space. | 426 // may have changed, and we need to reallocate space. |
423 child->clearOverrideSize(); | 427 child->clearOverrideSize(); |
424 if (!relayoutChildren) | 428 if (!relayoutChildren) |
425 child->setChildNeedsLayout(MarkOnlyThis); | 429 child->setChildNeedsLayout(MarkOnlyThis); |
426 haveFlex = true; | 430 haveFlex = true; |
427 unsigned flexGroup = child->style()->boxFlexGroup(); | 431 unsigned flexGroup = child->style()->boxFlexGroup(); |
428 if (lowestFlexGroup == 0) | 432 if (lowestFlexGroup == 0) |
429 lowestFlexGroup = flexGroup; | 433 lowestFlexGroup = flexGroup; |
430 if (flexGroup < lowestFlexGroup) | 434 if (flexGroup < lowestFlexGroup) |
431 lowestFlexGroup = flexGroup; | 435 lowestFlexGroup = flexGroup; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 // Our first pass is done without flexing. We simply lay the children | 469 // Our first pass is done without flexing. We simply lay the children |
466 // out within the box. We have to do a layout first in order to determine | 470 // out within the box. We have to do a layout first in order to determine |
467 // our box's intrinsic height. | 471 // our box's intrinsic height. |
468 LayoutUnit maxAscent; | 472 LayoutUnit maxAscent; |
469 LayoutUnit maxDescent; | 473 LayoutUnit maxDescent; |
470 for (LayoutBox* child = iterator.first(); child; child = iterator.next()) { | 474 for (LayoutBox* child = iterator.first(); child; child = iterator.next()) { |
471 if (child->isOutOfFlowPositioned()) | 475 if (child->isOutOfFlowPositioned()) |
472 continue; | 476 continue; |
473 | 477 |
474 SubtreeLayoutScope layoutScope(*child); | 478 SubtreeLayoutScope layoutScope(*child); |
475 // TODO(jchaffraix): It seems incorrect to check isAtomicInlineLevel in th
is file. | 479 // TODO(jchaffraix): It seems incorrect to check isAtomicInlineLevel in |
| 480 // this file. |
476 // We probably want to check if the element is replaced. | 481 // We probably want to check if the element is replaced. |
477 if (relayoutChildren || (child->isAtomicInlineLevel() && | 482 if (relayoutChildren || (child->isAtomicInlineLevel() && |
478 (child->style()->width().isPercentOrCalc() || | 483 (child->style()->width().isPercentOrCalc() || |
479 child->style()->height().isPercentOrCalc()))) | 484 child->style()->height().isPercentOrCalc()))) |
480 layoutScope.setChildNeedsLayout(child); | 485 layoutScope.setChildNeedsLayout(child); |
481 | 486 |
482 // Compute the child's vertical margins. | 487 // Compute the child's vertical margins. |
483 child->computeAndSetBlockDirectionMargins(this); | 488 child->computeAndSetBlockDirectionMargins(this); |
484 | 489 |
485 if (!child->needsLayout()) | 490 if (!child->needsLayout()) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 | 550 |
546 if (child->style()->visibility() == EVisibility::Collapse) { | 551 if (child->style()->visibility() == EVisibility::Collapse) { |
547 // visibility: collapsed children do not participate in our positioning. | 552 // visibility: collapsed children do not participate in our positioning. |
548 // But we need to lay them down. | 553 // But we need to lay them down. |
549 child->layoutIfNeeded(); | 554 child->layoutIfNeeded(); |
550 continue; | 555 continue; |
551 } | 556 } |
552 | 557 |
553 SubtreeLayoutScope layoutScope(*child); | 558 SubtreeLayoutScope layoutScope(*child); |
554 | 559 |
555 // We need to see if this child's height will change, since we make block
elements fill | 560 // We need to see if this child's height will change, since we make block |
556 // the height of a containing box by default. We cannot actually *set* the
new height | 561 // elements fill the height of a containing box by default. We cannot |
557 // here, though. Need to do that from within layout, or we won't be able t
o detect the | 562 // actually *set* the new height here, though. Need to do that from |
558 // change and duly notify any positioned descendants that are affected by
it. | 563 // within layout, or we won't be able to detect the change and duly |
| 564 // notify any positioned descendants that are affected by it. |
559 LayoutUnit oldChildHeight = child->logicalHeight(); | 565 LayoutUnit oldChildHeight = child->logicalHeight(); |
560 LogicalExtentComputedValues computedValues; | 566 LogicalExtentComputedValues computedValues; |
561 child->computeLogicalHeight(child->logicalHeight(), child->logicalTop(), | 567 child->computeLogicalHeight(child->logicalHeight(), child->logicalTop(), |
562 computedValues); | 568 computedValues); |
563 LayoutUnit newChildHeight = computedValues.m_extent; | 569 LayoutUnit newChildHeight = computedValues.m_extent; |
564 if (oldChildHeight != newChildHeight) | 570 if (oldChildHeight != newChildHeight) |
565 layoutScope.setChildNeedsLayout(child); | 571 layoutScope.setChildNeedsLayout(child); |
566 | 572 |
567 if (!child->needsLayout()) | 573 if (!child->needsLayout()) |
568 markChildForPaginationRelayoutIfNeeded(*child, layoutScope); | 574 markChildForPaginationRelayoutIfNeeded(*child, layoutScope); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 xPos += child->size().width() + child->marginRight(); | 607 xPos += child->size().width() + child->marginRight(); |
602 } | 608 } |
603 | 609 |
604 remainingSpace = size().width() - borderRight() - paddingRight() - | 610 remainingSpace = size().width() - borderRight() - paddingRight() - |
605 verticalScrollbarWidth() - xPos; | 611 verticalScrollbarWidth() - xPos; |
606 | 612 |
607 m_stretchingChildren = false; | 613 m_stretchingChildren = false; |
608 if (flexingChildren) { | 614 if (flexingChildren) { |
609 haveFlex = false; // We're done. | 615 haveFlex = false; // We're done. |
610 } else if (haveFlex) { | 616 } else if (haveFlex) { |
611 // We have some flexible objects. See if we need to grow/shrink them at a
ll. | 617 // We have some flexible objects. See if we need to grow/shrink them at |
| 618 // all. |
612 if (!remainingSpace) | 619 if (!remainingSpace) |
613 break; | 620 break; |
614 | 621 |
615 // Allocate the remaining space among the flexible objects. If we are try
ing to | 622 // Allocate the remaining space among the flexible objects. If we are |
616 // grow, then we go from the lowest flex group to the highest flex group.
For shrinking, | 623 // trying to grow, then we go from the lowest flex group to the highest |
617 // we go from the highest flex group to the lowest group. | 624 // flex group. For shrinking, we go from the highest flex group to the |
| 625 // lowest group. |
618 bool expanding = remainingSpace > 0; | 626 bool expanding = remainingSpace > 0; |
619 unsigned start = expanding ? lowestFlexGroup : highestFlexGroup; | 627 unsigned start = expanding ? lowestFlexGroup : highestFlexGroup; |
620 unsigned end = expanding ? highestFlexGroup : lowestFlexGroup; | 628 unsigned end = expanding ? highestFlexGroup : lowestFlexGroup; |
621 for (unsigned i = start; i <= end && remainingSpace; i++) { | 629 for (unsigned i = start; i <= end && remainingSpace; i++) { |
622 // Always start off by assuming the group can get all the remaining spac
e. | 630 // Always start off by assuming the group can get all the remaining |
| 631 // space. |
623 LayoutUnit groupRemainingSpace = remainingSpace; | 632 LayoutUnit groupRemainingSpace = remainingSpace; |
624 do { | 633 do { |
625 // Flexing consists of multiple passes, since we have to change ratios
every time an object hits its max/min-width | 634 // Flexing consists of multiple passes, since we have to change |
626 // For a given pass, we always start off by computing the totalFlex of
all objects that can grow/shrink at all, and | 635 // ratios every time an object hits its max/min-width For a given |
627 // computing the allowed growth before an object hits its min/max widt
h (and thus | 636 // pass, we always start off by computing the totalFlex of all |
628 // forces a totalFlex recomputation). | 637 // objects that can grow/shrink at all, and computing the allowed |
| 638 // growth before an object hits its min/max width (and thus forces a |
| 639 // totalFlex recomputation). |
629 LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace; | 640 LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace; |
630 float totalFlex = 0.0f; | 641 float totalFlex = 0.0f; |
631 for (LayoutBox* child = iterator.first(); child; | 642 for (LayoutBox* child = iterator.first(); child; |
632 child = iterator.next()) { | 643 child = iterator.next()) { |
633 if (allowedChildFlex(child, expanding, i)) | 644 if (allowedChildFlex(child, expanding, i)) |
634 totalFlex += child->style()->boxFlex(); | 645 totalFlex += child->style()->boxFlex(); |
635 } | 646 } |
636 LayoutUnit spaceAvailableThisPass = groupRemainingSpace; | 647 LayoutUnit spaceAvailableThisPass = groupRemainingSpace; |
637 for (LayoutBox* child = iterator.first(); child; | 648 for (LayoutBox* child = iterator.first(); child; |
638 child = iterator.next()) { | 649 child = iterator.next()) { |
639 LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i); | 650 LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i); |
640 if (allowedFlex) { | 651 if (allowedFlex) { |
641 LayoutUnit projectedFlex = | 652 LayoutUnit projectedFlex = |
642 (allowedFlex == LayoutUnit::max()) | 653 (allowedFlex == LayoutUnit::max()) |
643 ? allowedFlex | 654 ? allowedFlex |
644 : LayoutUnit(allowedFlex * | 655 : LayoutUnit(allowedFlex * |
645 (totalFlex / child->style()->boxFlex())); | 656 (totalFlex / child->style()->boxFlex())); |
646 spaceAvailableThisPass = | 657 spaceAvailableThisPass = |
647 expanding ? std::min(spaceAvailableThisPass, projectedFlex) | 658 expanding ? std::min(spaceAvailableThisPass, projectedFlex) |
648 : std::max(spaceAvailableThisPass, projectedFlex); | 659 : std::max(spaceAvailableThisPass, projectedFlex); |
649 } | 660 } |
650 } | 661 } |
651 | 662 |
652 // The flex groups may not have any flexible objects this time around. | 663 // The flex groups may not have any flexible objects this time around. |
653 if (!spaceAvailableThisPass || totalFlex == 0.0f) { | 664 if (!spaceAvailableThisPass || totalFlex == 0.0f) { |
654 // If we just couldn't grow/shrink any more, then it's time to trans
ition to the next flex group. | 665 // If we just couldn't grow/shrink any more, then it's time to |
| 666 // transition to the next flex group. |
655 groupRemainingSpace = LayoutUnit(); | 667 groupRemainingSpace = LayoutUnit(); |
656 continue; | 668 continue; |
657 } | 669 } |
658 | 670 |
659 // Now distribute the space to objects. | 671 // Now distribute the space to objects. |
660 for (LayoutBox* child = iterator.first(); | 672 for (LayoutBox* child = iterator.first(); |
661 child && spaceAvailableThisPass && totalFlex; | 673 child && spaceAvailableThisPass && totalFlex; |
662 child = iterator.next()) { | 674 child = iterator.next()) { |
663 if (child->style()->visibility() == EVisibility::Collapse) | 675 if (child->style()->visibility() == EVisibility::Collapse) |
664 continue; | 676 continue; |
(...skipping 10 matching lines...) Expand all Loading... |
675 } | 687 } |
676 | 688 |
677 spaceAvailableThisPass -= spaceAdd; | 689 spaceAvailableThisPass -= spaceAdd; |
678 remainingSpace -= spaceAdd; | 690 remainingSpace -= spaceAdd; |
679 groupRemainingSpace -= spaceAdd; | 691 groupRemainingSpace -= spaceAdd; |
680 | 692 |
681 totalFlex -= child->style()->boxFlex(); | 693 totalFlex -= child->style()->boxFlex(); |
682 } | 694 } |
683 } | 695 } |
684 if (groupRemainingSpace == groupRemainingSpaceAtBeginning) { | 696 if (groupRemainingSpace == groupRemainingSpaceAtBeginning) { |
685 // This is not advancing, avoid getting stuck by distributing the re
maining pixels. | 697 // This is not advancing, avoid getting stuck by distributing the |
| 698 // remaining pixels. |
686 LayoutUnit spaceAdd = LayoutUnit(groupRemainingSpace > 0 ? 1 : -1); | 699 LayoutUnit spaceAdd = LayoutUnit(groupRemainingSpace > 0 ? 1 : -1); |
687 for (LayoutBox* child = iterator.first(); | 700 for (LayoutBox* child = iterator.first(); |
688 child && groupRemainingSpace; child = iterator.next()) { | 701 child && groupRemainingSpace; child = iterator.next()) { |
689 if (allowedChildFlex(child, expanding, i)) { | 702 if (allowedChildFlex(child, expanding, i)) { |
690 child->setOverrideLogicalContentWidth( | 703 child->setOverrideLogicalContentWidth( |
691 contentWidthForChild(child) + spaceAdd); | 704 contentWidthForChild(child) + spaceAdd); |
692 flexingChildren = true; | 705 flexingChildren = true; |
693 relayoutChildren = true; | 706 relayoutChildren = true; |
694 remainingSpace -= spaceAdd; | 707 remainingSpace -= spaceAdd; |
695 groupRemainingSpace -= spaceAdd; | 708 groupRemainingSpace -= spaceAdd; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 for (LayoutBox* child = iterator.first(); child; | 765 for (LayoutBox* child = iterator.first(); child; |
753 child = iterator.next()) { | 766 child = iterator.next()) { |
754 if (childDoesNotAffectWidthOrFlexing(child)) | 767 if (childDoesNotAffectWidthOrFlexing(child)) |
755 continue; | 768 continue; |
756 | 769 |
757 placeChild(child, child->location() + LayoutSize(offset, LayoutUnit())); | 770 placeChild(child, child->location() + LayoutSize(offset, LayoutUnit())); |
758 } | 771 } |
759 } | 772 } |
760 } | 773 } |
761 | 774 |
762 // So that the computeLogicalHeight in layoutBlock() knows to relayout positio
ned objects because of | 775 // So that the computeLogicalHeight in layoutBlock() knows to relayout |
763 // a height change, we revert our height back to the intrinsic height before r
eturning. | 776 // positioned objects because of a height change, we revert our height back |
| 777 // to the intrinsic height before returning. |
764 if (heightSpecified) | 778 if (heightSpecified) |
765 setHeight(oldHeight); | 779 setHeight(oldHeight); |
766 } | 780 } |
767 | 781 |
768 void LayoutDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) { | 782 void LayoutDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren) { |
769 LayoutUnit yPos = borderTop() + paddingTop(); | 783 LayoutUnit yPos = borderTop() + paddingTop(); |
770 LayoutUnit toAdd = | 784 LayoutUnit toAdd = |
771 borderBottom() + paddingBottom() + horizontalScrollbarHeight(); | 785 borderBottom() + paddingBottom() + horizontalScrollbarHeight(); |
772 bool heightSpecified = false; | 786 bool heightSpecified = false; |
773 LayoutUnit oldHeight; | 787 LayoutUnit oldHeight; |
774 | 788 |
775 LayoutUnit remainingSpace; | 789 LayoutUnit remainingSpace; |
776 | 790 |
777 FlexBoxIterator iterator(this); | 791 FlexBoxIterator iterator(this); |
778 unsigned highestFlexGroup = 0; | 792 unsigned highestFlexGroup = 0; |
779 unsigned lowestFlexGroup = 0; | 793 unsigned lowestFlexGroup = 0; |
780 bool haveFlex = false, flexingChildren = false; | 794 bool haveFlex = false, flexingChildren = false; |
781 gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, | 795 gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, |
782 lowestFlexGroup, haveFlex); | 796 lowestFlexGroup, haveFlex); |
783 | 797 |
784 // We confine the line clamp ugliness to vertical flexible boxes (thus keeping
it out of | 798 // We confine the line clamp ugliness to vertical flexible boxes (thus keeping |
| 799 // it out of |
785 // mainstream block layout); this is not really part of the XUL box model. | 800 // mainstream block layout); this is not really part of the XUL box model. |
786 bool haveLineClamp = !style()->lineClamp().isNone(); | 801 bool haveLineClamp = !style()->lineClamp().isNone(); |
787 if (haveLineClamp) | 802 if (haveLineClamp) |
788 applyLineClamp(iterator, relayoutChildren); | 803 applyLineClamp(iterator, relayoutChildren); |
789 | 804 |
790 PaintLayerScrollableArea::DelayScrollPositionClampScope delayClampScope; | 805 PaintLayerScrollableArea::DelayScrollPositionClampScope delayClampScope; |
791 | 806 |
792 // We do 2 passes. The first pass is simply to lay everyone out at | 807 // We do 2 passes. The first pass is simply to lay everyone out at |
793 // their preferred widths. The second pass handles flexing the children. | 808 // their preferred widths. The second pass handles flexing the children. |
794 // Our first pass is done without flexing. We simply lay the children | 809 // Our first pass is done without flexing. We simply lay the children |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 | 888 |
874 if (!iterator.first() && hasLineIfEmpty()) | 889 if (!iterator.first() && hasLineIfEmpty()) |
875 setHeight(size().height() + lineHeight(true, | 890 setHeight(size().height() + lineHeight(true, |
876 style()->isHorizontalWritingMode() | 891 style()->isHorizontalWritingMode() |
877 ? HorizontalLine | 892 ? HorizontalLine |
878 : VerticalLine, | 893 : VerticalLine, |
879 PositionOfInteriorLineBoxes)); | 894 PositionOfInteriorLineBoxes)); |
880 | 895 |
881 setHeight(size().height() + toAdd); | 896 setHeight(size().height() + toAdd); |
882 | 897 |
883 // Negative margins can cause our height to shrink below our minimal height
(border/padding). | 898 // Negative margins can cause our height to shrink below our minimal height |
884 // If this happens, ensure that the computed height is increased to the mini
mal height. | 899 // (border/padding). If this happens, ensure that the computed height is |
| 900 // increased to the minimal height. |
885 if (size().height() < minHeight) | 901 if (size().height() < minHeight) |
886 setHeight(minHeight); | 902 setHeight(minHeight); |
887 | 903 |
888 // Now we have to calc our height, so we know how much space we have remaini
ng. | 904 // Now we have to calc our height, so we know how much space we have |
| 905 // remaining. |
889 oldHeight = size().height(); | 906 oldHeight = size().height(); |
890 updateLogicalHeight(); | 907 updateLogicalHeight(); |
891 if (oldHeight != size().height()) | 908 if (oldHeight != size().height()) |
892 heightSpecified = true; | 909 heightSpecified = true; |
893 | 910 |
894 remainingSpace = size().height() - borderBottom() - paddingBottom() - | 911 remainingSpace = size().height() - borderBottom() - paddingBottom() - |
895 horizontalScrollbarHeight() - yPos; | 912 horizontalScrollbarHeight() - yPos; |
896 | 913 |
897 if (flexingChildren) { | 914 if (flexingChildren) { |
898 haveFlex = false; // We're done. | 915 haveFlex = false; // We're done. |
899 } else if (haveFlex) { | 916 } else if (haveFlex) { |
900 // We have some flexible objects. See if we need to grow/shrink them at a
ll. | 917 // We have some flexible objects. See if we need to grow/shrink them at |
| 918 // all. |
901 if (!remainingSpace) | 919 if (!remainingSpace) |
902 break; | 920 break; |
903 | 921 |
904 // Allocate the remaining space among the flexible objects. If we are try
ing to | 922 // Allocate the remaining space among the flexible objects. If we are |
905 // grow, then we go from the lowest flex group to the highest flex group.
For shrinking, | 923 // trying to grow, then we go from the lowest flex group to the highest |
906 // we go from the highest flex group to the lowest group. | 924 // flex group. For shrinking, we go from the highest flex group to the |
| 925 // lowest group. |
907 bool expanding = remainingSpace > 0; | 926 bool expanding = remainingSpace > 0; |
908 unsigned start = expanding ? lowestFlexGroup : highestFlexGroup; | 927 unsigned start = expanding ? lowestFlexGroup : highestFlexGroup; |
909 unsigned end = expanding ? highestFlexGroup : lowestFlexGroup; | 928 unsigned end = expanding ? highestFlexGroup : lowestFlexGroup; |
910 for (unsigned i = start; i <= end && remainingSpace; i++) { | 929 for (unsigned i = start; i <= end && remainingSpace; i++) { |
911 // Always start off by assuming the group can get all the remaining spac
e. | 930 // Always start off by assuming the group can get all the remaining |
| 931 // space. |
912 LayoutUnit groupRemainingSpace = remainingSpace; | 932 LayoutUnit groupRemainingSpace = remainingSpace; |
913 do { | 933 do { |
914 // Flexing consists of multiple passes, since we have to change ratios
every time an object hits its max/min-width | 934 // Flexing consists of multiple passes, since we have to change |
915 // For a given pass, we always start off by computing the totalFlex of
all objects that can grow/shrink at all, and | 935 // ratios every time an object hits its max/min-width For a given |
916 // computing the allowed growth before an object hits its min/max widt
h (and thus | 936 // pass, we always start off by computing the totalFlex of all |
917 // forces a totalFlex recomputation). | 937 // objects that can grow/shrink at all, and computing the allowed |
| 938 // growth before an object hits its min/max width (and thus forces a |
| 939 // totalFlex recomputation). |
918 LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace; | 940 LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace; |
919 float totalFlex = 0.0f; | 941 float totalFlex = 0.0f; |
920 for (LayoutBox* child = iterator.first(); child; | 942 for (LayoutBox* child = iterator.first(); child; |
921 child = iterator.next()) { | 943 child = iterator.next()) { |
922 if (allowedChildFlex(child, expanding, i)) | 944 if (allowedChildFlex(child, expanding, i)) |
923 totalFlex += child->style()->boxFlex(); | 945 totalFlex += child->style()->boxFlex(); |
924 } | 946 } |
925 LayoutUnit spaceAvailableThisPass = groupRemainingSpace; | 947 LayoutUnit spaceAvailableThisPass = groupRemainingSpace; |
926 for (LayoutBox* child = iterator.first(); child; | 948 for (LayoutBox* child = iterator.first(); child; |
927 child = iterator.next()) { | 949 child = iterator.next()) { |
928 LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i); | 950 LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i); |
929 if (allowedFlex) { | 951 if (allowedFlex) { |
930 LayoutUnit projectedFlex = | 952 LayoutUnit projectedFlex = |
931 (allowedFlex == LayoutUnit::max()) | 953 (allowedFlex == LayoutUnit::max()) |
932 ? allowedFlex | 954 ? allowedFlex |
933 : static_cast<LayoutUnit>( | 955 : static_cast<LayoutUnit>( |
934 allowedFlex * | 956 allowedFlex * |
935 (totalFlex / child->style()->boxFlex())); | 957 (totalFlex / child->style()->boxFlex())); |
936 spaceAvailableThisPass = | 958 spaceAvailableThisPass = |
937 expanding ? std::min(spaceAvailableThisPass, projectedFlex) | 959 expanding ? std::min(spaceAvailableThisPass, projectedFlex) |
938 : std::max(spaceAvailableThisPass, projectedFlex); | 960 : std::max(spaceAvailableThisPass, projectedFlex); |
939 } | 961 } |
940 } | 962 } |
941 | 963 |
942 // The flex groups may not have any flexible objects this time around. | 964 // The flex groups may not have any flexible objects this time around. |
943 if (!spaceAvailableThisPass || totalFlex == 0.0f) { | 965 if (!spaceAvailableThisPass || totalFlex == 0.0f) { |
944 // If we just couldn't grow/shrink any more, then it's time to trans
ition to the next flex group. | 966 // If we just couldn't grow/shrink any more, then it's time to |
| 967 // transition to the next flex group. |
945 groupRemainingSpace = LayoutUnit(); | 968 groupRemainingSpace = LayoutUnit(); |
946 continue; | 969 continue; |
947 } | 970 } |
948 | 971 |
949 // Now distribute the space to objects. | 972 // Now distribute the space to objects. |
950 for (LayoutBox* child = iterator.first(); | 973 for (LayoutBox* child = iterator.first(); |
951 child && spaceAvailableThisPass && totalFlex; | 974 child && spaceAvailableThisPass && totalFlex; |
952 child = iterator.next()) { | 975 child = iterator.next()) { |
953 if (allowedChildFlex(child, expanding, i)) { | 976 if (allowedChildFlex(child, expanding, i)) { |
954 LayoutUnit spaceAdd = static_cast<LayoutUnit>( | 977 LayoutUnit spaceAdd = static_cast<LayoutUnit>( |
955 spaceAvailableThisPass * | 978 spaceAvailableThisPass * |
956 (child->style()->boxFlex() / totalFlex)); | 979 (child->style()->boxFlex() / totalFlex)); |
957 if (spaceAdd) { | 980 if (spaceAdd) { |
958 child->setOverrideLogicalContentHeight( | 981 child->setOverrideLogicalContentHeight( |
959 contentHeightForChild(child) + spaceAdd); | 982 contentHeightForChild(child) + spaceAdd); |
960 flexingChildren = true; | 983 flexingChildren = true; |
961 relayoutChildren = true; | 984 relayoutChildren = true; |
962 } | 985 } |
963 | 986 |
964 spaceAvailableThisPass -= spaceAdd; | 987 spaceAvailableThisPass -= spaceAdd; |
965 remainingSpace -= spaceAdd; | 988 remainingSpace -= spaceAdd; |
966 groupRemainingSpace -= spaceAdd; | 989 groupRemainingSpace -= spaceAdd; |
967 | 990 |
968 totalFlex -= child->style()->boxFlex(); | 991 totalFlex -= child->style()->boxFlex(); |
969 } | 992 } |
970 } | 993 } |
971 if (groupRemainingSpace == groupRemainingSpaceAtBeginning) { | 994 if (groupRemainingSpace == groupRemainingSpaceAtBeginning) { |
972 // This is not advancing, avoid getting stuck by distributing the re
maining pixels. | 995 // This is not advancing, avoid getting stuck by distributing the |
| 996 // remaining pixels. |
973 LayoutUnit spaceAdd = LayoutUnit(groupRemainingSpace > 0 ? 1 : -1); | 997 LayoutUnit spaceAdd = LayoutUnit(groupRemainingSpace > 0 ? 1 : -1); |
974 for (LayoutBox* child = iterator.first(); | 998 for (LayoutBox* child = iterator.first(); |
975 child && groupRemainingSpace; child = iterator.next()) { | 999 child && groupRemainingSpace; child = iterator.next()) { |
976 if (allowedChildFlex(child, expanding, i)) { | 1000 if (allowedChildFlex(child, expanding, i)) { |
977 child->setOverrideLogicalContentHeight( | 1001 child->setOverrideLogicalContentHeight( |
978 contentHeightForChild(child) + spaceAdd); | 1002 contentHeightForChild(child) + spaceAdd); |
979 flexingChildren = true; | 1003 flexingChildren = true; |
980 relayoutChildren = true; | 1004 relayoutChildren = true; |
981 remainingSpace -= spaceAdd; | 1005 remainingSpace -= spaceAdd; |
982 groupRemainingSpace -= spaceAdd; | 1006 groupRemainingSpace -= spaceAdd; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 offset += remainingSpace; | 1059 offset += remainingSpace; |
1036 for (LayoutBox* child = iterator.first(); child; | 1060 for (LayoutBox* child = iterator.first(); child; |
1037 child = iterator.next()) { | 1061 child = iterator.next()) { |
1038 if (childDoesNotAffectWidthOrFlexing(child)) | 1062 if (childDoesNotAffectWidthOrFlexing(child)) |
1039 continue; | 1063 continue; |
1040 placeChild(child, child->location() + LayoutSize(LayoutUnit(), offset)); | 1064 placeChild(child, child->location() + LayoutSize(LayoutUnit(), offset)); |
1041 } | 1065 } |
1042 } | 1066 } |
1043 } | 1067 } |
1044 | 1068 |
1045 // So that the computeLogicalHeight in layoutBlock() knows to relayout positio
ned objects because of | 1069 // So that the computeLogicalHeight in layoutBlock() knows to relayout |
1046 // a height change, we revert our height back to the intrinsic height before r
eturning. | 1070 // positioned objects because of a height change, we revert our height back |
| 1071 // to the intrinsic height before returning. |
1047 if (heightSpecified) | 1072 if (heightSpecified) |
1048 setHeight(oldHeight); | 1073 setHeight(oldHeight); |
1049 } | 1074 } |
1050 | 1075 |
1051 void LayoutDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, | 1076 void LayoutDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, |
1052 bool relayoutChildren) { | 1077 bool relayoutChildren) { |
1053 UseCounter::count(document(), UseCounter::LineClamp); | 1078 UseCounter::count(document(), UseCounter::LineClamp); |
1054 | 1079 |
1055 int maxLineCount = 0; | 1080 int maxLineCount = 0; |
1056 for (LayoutBox* child = iterator.first(); child; child = iterator.next()) { | 1081 for (LayoutBox* child = iterator.first(); child; child = iterator.next()) { |
(...skipping 12 matching lines...) Expand all Loading... |
1069 toLayoutBlockFlow(child)->markPositionedObjectsForLayout(); | 1094 toLayoutBlockFlow(child)->markPositionedObjectsForLayout(); |
1070 clearTruncation(toLayoutBlockFlow(child)); | 1095 clearTruncation(toLayoutBlockFlow(child)); |
1071 } | 1096 } |
1072 } | 1097 } |
1073 child->layoutIfNeeded(); | 1098 child->layoutIfNeeded(); |
1074 if (child->style()->height().isAuto() && child->isLayoutBlockFlow()) | 1099 if (child->style()->height().isAuto() && child->isLayoutBlockFlow()) |
1075 maxLineCount = | 1100 maxLineCount = |
1076 std::max(maxLineCount, lineCount(toLayoutBlockFlow(child))); | 1101 std::max(maxLineCount, lineCount(toLayoutBlockFlow(child))); |
1077 } | 1102 } |
1078 | 1103 |
1079 // Get the number of lines and then alter all block flow children with auto he
ight to use the | 1104 // Get the number of lines and then alter all block flow children with auto |
| 1105 // height to use the |
1080 // specified height. We always try to leave room for at least one line. | 1106 // specified height. We always try to leave room for at least one line. |
1081 LineClampValue lineClamp = style()->lineClamp(); | 1107 LineClampValue lineClamp = style()->lineClamp(); |
1082 int numVisibleLines = | 1108 int numVisibleLines = |
1083 lineClamp.isPercentage() | 1109 lineClamp.isPercentage() |
1084 ? std::max(1, (maxLineCount + 1) * lineClamp.value() / 100) | 1110 ? std::max(1, (maxLineCount + 1) * lineClamp.value() / 100) |
1085 : lineClamp.value(); | 1111 : lineClamp.value(); |
1086 if (numVisibleLines >= maxLineCount) | 1112 if (numVisibleLines >= maxLineCount) |
1087 return; | 1113 return; |
1088 | 1114 |
1089 for (LayoutBox* child = iterator.first(); child; child = iterator.next()) { | 1115 for (LayoutBox* child = iterator.first(); child; child = iterator.next()) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 (&horizontalEllipsisCharacter, 1)); | 1150 (&horizontalEllipsisCharacter, 1)); |
1125 const Font& font = style(numVisibleLines == 1)->font(); | 1151 const Font& font = style(numVisibleLines == 1)->font(); |
1126 float totalWidth = | 1152 float totalWidth = |
1127 font.width(constructTextRun(font, &horizontalEllipsisCharacter, 1, | 1153 font.width(constructTextRun(font, &horizontalEllipsisCharacter, 1, |
1128 styleRef(), style()->direction())); | 1154 styleRef(), style()->direction())); |
1129 | 1155 |
1130 // See if this width can be accommodated on the last visible line | 1156 // See if this width can be accommodated on the last visible line |
1131 LineLayoutBlockFlow destBlock = lastVisibleLine->block(); | 1157 LineLayoutBlockFlow destBlock = lastVisibleLine->block(); |
1132 LineLayoutBlockFlow srcBlock = lastLine->block(); | 1158 LineLayoutBlockFlow srcBlock = lastLine->block(); |
1133 | 1159 |
1134 // FIXME: Directions of src/destBlock could be different from our direction
and from one another. | 1160 // FIXME: Directions of src/destBlock could be different from our direction |
| 1161 // and from one another. |
1135 if (!srcBlock.style()->isLeftToRightDirection()) | 1162 if (!srcBlock.style()->isLeftToRightDirection()) |
1136 continue; | 1163 continue; |
1137 | 1164 |
1138 bool leftToRight = destBlock.style()->isLeftToRightDirection(); | 1165 bool leftToRight = destBlock.style()->isLeftToRightDirection(); |
1139 if (!leftToRight) | 1166 if (!leftToRight) |
1140 continue; | 1167 continue; |
1141 | 1168 |
1142 LayoutUnit blockRightEdge = destBlock.logicalRightOffsetForLine( | 1169 LayoutUnit blockRightEdge = destBlock.logicalRightOffsetForLine( |
1143 lastVisibleLine->y(), DoNotIndentText); | 1170 lastVisibleLine->y(), DoNotIndentText); |
1144 if (!lastVisibleLine->lineCanAccommodateEllipsis( | 1171 if (!lastVisibleLine->lineCanAccommodateEllipsis( |
1145 leftToRight, blockRightEdge.toInt(), | 1172 leftToRight, blockRightEdge.toInt(), |
1146 (lastVisibleLine->x() + lastVisibleLine->logicalWidth()).toInt(), | 1173 (lastVisibleLine->x() + lastVisibleLine->logicalWidth()).toInt(), |
1147 totalWidth)) | 1174 totalWidth)) |
1148 continue; | 1175 continue; |
1149 | 1176 |
1150 // Let the truncation code kick in. | 1177 // Let the truncation code kick in. |
1151 // FIXME: the text alignment should be recomputed after the width changes du
e to truncation. | 1178 // FIXME: the text alignment should be recomputed after the width changes |
| 1179 // due to truncation. |
1152 LayoutUnit blockLeftEdge = destBlock.logicalLeftOffsetForLine( | 1180 LayoutUnit blockLeftEdge = destBlock.logicalLeftOffsetForLine( |
1153 lastVisibleLine->y(), DoNotIndentText); | 1181 lastVisibleLine->y(), DoNotIndentText); |
1154 lastVisibleLine->placeEllipsis(ellipsisStr, leftToRight, blockLeftEdge, | 1182 lastVisibleLine->placeEllipsis(ellipsisStr, leftToRight, blockLeftEdge, |
1155 blockRightEdge, LayoutUnit(totalWidth)); | 1183 blockRightEdge, LayoutUnit(totalWidth)); |
1156 destBlock.setHasMarkupTruncation(true); | 1184 destBlock.setHasMarkupTruncation(true); |
1157 } | 1185 } |
1158 } | 1186 } |
1159 | 1187 |
1160 void LayoutDeprecatedFlexibleBox::clearLineClamp() { | 1188 void LayoutDeprecatedFlexibleBox::clearLineClamp() { |
1161 FlexBoxIterator iterator(this); | 1189 FlexBoxIterator iterator(this); |
(...skipping 11 matching lines...) Expand all Loading... |
1173 if (child->isLayoutBlockFlow()) { | 1201 if (child->isLayoutBlockFlow()) { |
1174 toLayoutBlockFlow(child)->markPositionedObjectsForLayout(); | 1202 toLayoutBlockFlow(child)->markPositionedObjectsForLayout(); |
1175 clearTruncation(toLayoutBlockFlow(child)); | 1203 clearTruncation(toLayoutBlockFlow(child)); |
1176 } | 1204 } |
1177 } | 1205 } |
1178 } | 1206 } |
1179 } | 1207 } |
1180 | 1208 |
1181 void LayoutDeprecatedFlexibleBox::placeChild(LayoutBox* child, | 1209 void LayoutDeprecatedFlexibleBox::placeChild(LayoutBox* child, |
1182 const LayoutPoint& location) { | 1210 const LayoutPoint& location) { |
1183 // FIXME Investigate if this can be removed based on other flags. crbug.com/37
0010 | 1211 // FIXME Investigate if this can be removed based on other flags. |
| 1212 // crbug.com/370010 |
1184 child->setMayNeedPaintInvalidation(); | 1213 child->setMayNeedPaintInvalidation(); |
1185 | 1214 |
1186 // Place the child. | 1215 // Place the child. |
1187 child->setLocation(location); | 1216 child->setLocation(location); |
1188 } | 1217 } |
1189 | 1218 |
1190 LayoutUnit LayoutDeprecatedFlexibleBox::allowedChildFlex(LayoutBox* child, | 1219 LayoutUnit LayoutDeprecatedFlexibleBox::allowedChildFlex(LayoutBox* child, |
1191 bool expanding, | 1220 bool expanding, |
1192 unsigned group) { | 1221 unsigned group) { |
1193 if (childDoesNotAffectWidthOrFlexing(child) || | 1222 if (childDoesNotAffectWidthOrFlexing(child) || |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1232 if (minHeight.isFixed() || minHeight.isAuto()) { | 1261 if (minHeight.isFixed() || minHeight.isAuto()) { |
1233 LayoutUnit minHeight(child->style()->minHeight().value()); | 1262 LayoutUnit minHeight(child->style()->minHeight().value()); |
1234 LayoutUnit height = contentHeightForChild(child); | 1263 LayoutUnit height = contentHeightForChild(child); |
1235 LayoutUnit allowedShrinkage = (minHeight - height).clampPositiveToZero(); | 1264 LayoutUnit allowedShrinkage = (minHeight - height).clampPositiveToZero(); |
1236 return allowedShrinkage; | 1265 return allowedShrinkage; |
1237 } | 1266 } |
1238 return LayoutUnit(); | 1267 return LayoutUnit(); |
1239 } | 1268 } |
1240 | 1269 |
1241 } // namespace blink | 1270 } // namespace blink |
OLD | NEW |