| OLD | NEW |
| 1 /* | 1 /* |
| 2 * This file is part of the render object implementation for KHTML. | 2 * This file is part of the render 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 return child->logicalWidth() - child->borderAndPaddingLogicalWidth(); | 175 return child->logicalWidth() - child->borderAndPaddingLogicalWidth(); |
| 176 } | 176 } |
| 177 | 177 |
| 178 static LayoutUnit contentHeightForChild(RenderBox* child) | 178 static LayoutUnit contentHeightForChild(RenderBox* child) |
| 179 { | 179 { |
| 180 if (child->hasOverrideHeight()) | 180 if (child->hasOverrideHeight()) |
| 181 return child->overrideLogicalContentHeight(); | 181 return child->overrideLogicalContentHeight(); |
| 182 return child->logicalHeight() - child->borderAndPaddingLogicalHeight(); | 182 return child->logicalHeight() - child->borderAndPaddingLogicalHeight(); |
| 183 } | 183 } |
| 184 | 184 |
| 185 void RenderDeprecatedFlexibleBox::styleWillChange(StyleDifference diff, const Re
nderStyle* newStyle) | |
| 186 { | |
| 187 RenderStyle* oldStyle = style(); | |
| 188 if (oldStyle && !oldStyle->lineClamp().isNone() && newStyle->lineClamp().isN
one()) | |
| 189 clearLineClamp(); | |
| 190 | |
| 191 RenderBlock::styleWillChange(diff, newStyle); | |
| 192 } | |
| 193 | |
| 194 void RenderDeprecatedFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minL
ogicalWidth, LayoutUnit& maxLogicalWidth) const | 185 void RenderDeprecatedFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minL
ogicalWidth, LayoutUnit& maxLogicalWidth) const |
| 195 { | 186 { |
| 196 if (hasMultipleLines() || isVertical()) { | 187 if (hasMultipleLines() || isVertical()) { |
| 197 for (RenderBox* child = firstChildBox(); child; child = child->nextSibli
ngBox()) { | 188 for (RenderBox* child = firstChildBox(); child; child = child->nextSibli
ngBox()) { |
| 198 if (childDoesNotAffectWidthOrFlexing(child)) | 189 if (childDoesNotAffectWidthOrFlexing(child)) |
| 199 continue; | 190 continue; |
| 200 | 191 |
| 201 LayoutUnit margin = marginWidthForChild(child); | 192 LayoutUnit margin = marginWidthForChild(child); |
| 202 LayoutUnit width = child->minPreferredLogicalWidth() + margin; | 193 LayoutUnit width = child->minPreferredLogicalWidth() + margin; |
| 203 minLogicalWidth = max(width, minLogicalWidth); | 194 minLogicalWidth = max(width, minLogicalWidth); |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 LayoutUnit oldHeight = 0; | 628 LayoutUnit oldHeight = 0; |
| 638 | 629 |
| 639 LayoutUnit remainingSpace = 0; | 630 LayoutUnit remainingSpace = 0; |
| 640 | 631 |
| 641 FlexBoxIterator iterator(this); | 632 FlexBoxIterator iterator(this); |
| 642 unsigned int highestFlexGroup = 0; | 633 unsigned int highestFlexGroup = 0; |
| 643 unsigned int lowestFlexGroup = 0; | 634 unsigned int lowestFlexGroup = 0; |
| 644 bool haveFlex = false, flexingChildren = false; | 635 bool haveFlex = false, flexingChildren = false; |
| 645 gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestF
lexGroup, haveFlex); | 636 gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestF
lexGroup, haveFlex); |
| 646 | 637 |
| 647 // We confine the line clamp ugliness to vertical flexible boxes (thus keepi
ng it out of | |
| 648 // mainstream block layout); this is not really part of the XUL box model. | |
| 649 bool haveLineClamp = !style()->lineClamp().isNone(); | |
| 650 if (haveLineClamp) | |
| 651 applyLineClamp(iterator, relayoutChildren); | |
| 652 | |
| 653 RenderBlock::startDelayUpdateScrollInfo(); | 638 RenderBlock::startDelayUpdateScrollInfo(); |
| 654 | 639 |
| 655 // We do 2 passes. The first pass is simply to lay everyone out at | 640 // We do 2 passes. The first pass is simply to lay everyone out at |
| 656 // their preferred widths. The second pass handles flexing the children. | 641 // their preferred widths. The second pass handles flexing the children. |
| 657 // Our first pass is done without flexing. We simply lay the children | 642 // Our first pass is done without flexing. We simply lay the children |
| 658 // out within the box. | 643 // out within the box. |
| 659 do { | 644 do { |
| 660 setHeight(borderTop() + paddingTop()); | 645 setHeight(borderTop() + paddingTop()); |
| 661 LayoutUnit minHeight = height() + toAdd; | 646 LayoutUnit minHeight = height() + toAdd; |
| 662 | 647 |
| 663 for (RenderBox* child = iterator.first(); child; child = iterator.next()
) { | 648 for (RenderBox* child = iterator.first(); child; child = iterator.next()
) { |
| 664 if (child->isOutOfFlowPositioned()) { | 649 if (child->isOutOfFlowPositioned()) { |
| 665 child->containingBlock()->insertPositionedObject(child); | 650 child->containingBlock()->insertPositionedObject(child); |
| 666 RenderLayer* childLayer = child->layer(); | 651 RenderLayer* childLayer = child->layer(); |
| 667 childLayer->setStaticInlinePosition(borderStart() + paddingStart
()); // FIXME: Not right for regions. | 652 childLayer->setStaticInlinePosition(borderStart() + paddingStart
()); // FIXME: Not right for regions. |
| 668 if (childLayer->staticBlockPosition() != height()) { | 653 if (childLayer->staticBlockPosition() != height()) { |
| 669 childLayer->setStaticBlockPosition(height()); | 654 childLayer->setStaticBlockPosition(height()); |
| 670 if (child->style()->hasStaticBlockPosition(style()->isHorizo
ntalWritingMode())) | 655 if (child->style()->hasStaticBlockPosition(style()->isHorizo
ntalWritingMode())) |
| 671 child->setChildNeedsLayout(MarkOnlyThis); | 656 child->setChildNeedsLayout(MarkOnlyThis); |
| 672 } | 657 } |
| 673 continue; | 658 continue; |
| 674 } | 659 } |
| 675 | 660 |
| 676 SubtreeLayoutScope layoutScope(child); | 661 SubtreeLayoutScope layoutScope(child); |
| 677 if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (
child->style()->width().isPercent() || child->style()->height().isPercent())))) | 662 if (relayoutChildren || (child->isReplaced() && (child->style()->wid
th().isPercent() || child->style()->height().isPercent()))) |
| 678 layoutScope.setChildNeedsLayout(child); | 663 layoutScope.setChildNeedsLayout(child); |
| 679 | 664 |
| 680 if (child->style()->visibility() == COLLAPSE) { | 665 if (child->style()->visibility() == COLLAPSE) { |
| 681 // visibility: collapsed children do not participate in our posi
tioning. | 666 // visibility: collapsed children do not participate in our posi
tioning. |
| 682 // But we need to lay them down. | 667 // But we need to lay them down. |
| 683 child->layoutIfNeeded(); | 668 child->layoutIfNeeded(); |
| 684 continue; | 669 continue; |
| 685 } | 670 } |
| 686 | 671 |
| 687 // Compute the child's vertical margins. | 672 // Compute the child's vertical margins. |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 } | 856 } |
| 872 } | 857 } |
| 873 } | 858 } |
| 874 | 859 |
| 875 // So that the computeLogicalHeight in layoutBlock() knows to relayout posit
ioned objects because of | 860 // So that the computeLogicalHeight in layoutBlock() knows to relayout posit
ioned objects because of |
| 876 // a height change, we revert our height back to the intrinsic height before
returning. | 861 // a height change, we revert our height back to the intrinsic height before
returning. |
| 877 if (heightSpecified) | 862 if (heightSpecified) |
| 878 setHeight(oldHeight); | 863 setHeight(oldHeight); |
| 879 } | 864 } |
| 880 | 865 |
| 881 void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool
relayoutChildren) | |
| 882 { | |
| 883 UseCounter::count(&document(), UseCounter::LineClamp); | |
| 884 | |
| 885 int maxLineCount = 0; | |
| 886 for (RenderBox* child = iterator.first(); child; child = iterator.next()) { | |
| 887 if (childDoesNotAffectWidthOrFlexing(child)) | |
| 888 continue; | |
| 889 | |
| 890 child->clearOverrideSize(); | |
| 891 if (relayoutChildren || (child->isReplaced() && (child->style()->width()
.isPercent() || child->style()->height().isPercent())) | |
| 892 || (child->style()->height().isAuto() && child->isRenderBlock())) { | |
| 893 child->setChildNeedsLayout(MarkOnlyThis); | |
| 894 | |
| 895 // Dirty all the positioned objects. | |
| 896 if (child->isRenderBlock()) { | |
| 897 toRenderBlock(child)->markPositionedObjectsForLayout(); | |
| 898 toRenderBlock(child)->clearTruncation(); | |
| 899 } | |
| 900 } | |
| 901 child->layoutIfNeeded(); | |
| 902 if (child->style()->height().isAuto() && child->isRenderBlock()) | |
| 903 maxLineCount = max(maxLineCount, toRenderBlock(child)->lineCount()); | |
| 904 } | |
| 905 | |
| 906 // Get the number of lines and then alter all block flow children with auto
height to use the | |
| 907 // specified height. We always try to leave room for at least one line. | |
| 908 LineClampValue lineClamp = style()->lineClamp(); | |
| 909 int numVisibleLines = lineClamp.isPercentage() ? max(1, (maxLineCount + 1) *
lineClamp.value() / 100) : lineClamp.value(); | |
| 910 if (numVisibleLines >= maxLineCount) | |
| 911 return; | |
| 912 | |
| 913 for (RenderBox* child = iterator.first(); child; child = iterator.next()) { | |
| 914 if (childDoesNotAffectWidthOrFlexing(child) || !child->style()->height()
.isAuto() || !child->isRenderBlock()) | |
| 915 continue; | |
| 916 | |
| 917 RenderBlock* blockChild = toRenderBlock(child); | |
| 918 int lineCount = blockChild->lineCount(); | |
| 919 if (lineCount <= numVisibleLines) | |
| 920 continue; | |
| 921 | |
| 922 LayoutUnit newHeight = blockChild->heightForLineCount(numVisibleLines); | |
| 923 if (newHeight == child->height()) | |
| 924 continue; | |
| 925 | |
| 926 child->setOverrideLogicalContentHeight(newHeight - child->borderAndPaddi
ngHeight()); | |
| 927 child->forceChildLayout(); | |
| 928 | |
| 929 // FIXME: For now don't support RTL. | |
| 930 if (style()->direction() != LTR) | |
| 931 continue; | |
| 932 | |
| 933 // Get the last line | |
| 934 RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount - 1); | |
| 935 if (!lastLine) | |
| 936 continue; | |
| 937 | |
| 938 RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines
- 1); | |
| 939 if (!lastVisibleLine) | |
| 940 continue; | |
| 941 | |
| 942 const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' }; | |
| 943 DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace
, 2)); | |
| 944 DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1))
; | |
| 945 const Font& font = style(numVisibleLines == 1)->font(); | |
| 946 | |
| 947 // Get ellipsis width, and if the last child is an anchor, it will go af
ter the ellipsis, so add in a space and the anchor width too | |
| 948 LayoutUnit totalWidth; | |
| 949 InlineBox* anchorBox = lastLine->lastChild(); | |
| 950 if (anchorBox && anchorBox->renderer()->style()->isLink()) | |
| 951 totalWidth = anchorBox->logicalWidth() + font.width(constructTextRun
(this, font, ellipsisAndSpace, 2, style())); | |
| 952 else { | |
| 953 anchorBox = 0; | |
| 954 totalWidth = font.width(constructTextRun(this, font, &horizontalElli
psis, 1, style())); | |
| 955 } | |
| 956 | |
| 957 // See if this width can be accommodated on the last visible line | |
| 958 RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer()); | |
| 959 RenderBlock* srcBlock = toRenderBlock(lastLine->renderer()); | |
| 960 | |
| 961 // FIXME: Directions of src/destBlock could be different from our direct
ion and from one another. | |
| 962 if (!srcBlock->style()->isLeftToRightDirection()) | |
| 963 continue; | |
| 964 | |
| 965 bool leftToRight = destBlock->style()->isLeftToRightDirection(); | |
| 966 if (!leftToRight) | |
| 967 continue; | |
| 968 | |
| 969 LayoutUnit blockRightEdge = destBlock->logicalRightOffsetForLine(lastVis
ibleLine->y(), false); | |
| 970 if (!lastVisibleLine->lineCanAccommodateEllipsis(leftToRight, blockRight
Edge, lastVisibleLine->x() + lastVisibleLine->logicalWidth(), totalWidth)) | |
| 971 continue; | |
| 972 | |
| 973 // Let the truncation code kick in. | |
| 974 // FIXME: the text alignment should be recomputed after the width change
s due to truncation. | |
| 975 LayoutUnit blockLeftEdge = destBlock->logicalLeftOffsetForLine(lastVisib
leLine->y(), false); | |
| 976 lastVisibleLine->placeEllipsis(anchorBox ? ellipsisAndSpaceStr : ellipsi
sStr, leftToRight, blockLeftEdge, blockRightEdge, totalWidth, anchorBox); | |
| 977 destBlock->setHasMarkupTruncation(true); | |
| 978 } | |
| 979 } | |
| 980 | |
| 981 void RenderDeprecatedFlexibleBox::clearLineClamp() | |
| 982 { | |
| 983 FlexBoxIterator iterator(this); | |
| 984 for (RenderBox* child = iterator.first(); child; child = iterator.next()) { | |
| 985 if (childDoesNotAffectWidthOrFlexing(child)) | |
| 986 continue; | |
| 987 | |
| 988 child->clearOverrideSize(); | |
| 989 if ((child->isReplaced() && (child->style()->width().isPercent() || chil
d->style()->height().isPercent())) | |
| 990 || (child->style()->height().isAuto() && child->isRenderBlock())) { | |
| 991 child->setChildNeedsLayout(); | |
| 992 | |
| 993 if (child->isRenderBlock()) { | |
| 994 toRenderBlock(child)->markPositionedObjectsForLayout(); | |
| 995 toRenderBlock(child)->clearTruncation(); | |
| 996 } | |
| 997 } | |
| 998 } | |
| 999 } | |
| 1000 | |
| 1001 void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint
& location) | 866 void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint
& location) |
| 1002 { | 867 { |
| 1003 LayoutRect oldRect = child->frameRect(); | 868 LayoutRect oldRect = child->frameRect(); |
| 1004 | 869 |
| 1005 // Place the child. | 870 // Place the child. |
| 1006 child->setLocation(location); | 871 child->setLocation(location); |
| 1007 | 872 |
| 1008 // If the child moved, we have to repaint it as well as any floating/positio
ned | 873 // If the child moved, we have to repaint it as well as any floating/positio
ned |
| 1009 // descendants. An exception is if we need a layout. In this case, we know
we're going to | 874 // descendants. An exception is if we need a layout. In this case, we know
we're going to |
| 1010 // repaint ourselves (and the child) anyway. | 875 // repaint ourselves (and the child) anyway. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 if (isPseudoElement()) | 946 if (isPseudoElement()) |
| 1082 return "RenderDeprecatedFlexibleBox (generated)"; | 947 return "RenderDeprecatedFlexibleBox (generated)"; |
| 1083 if (isAnonymous()) | 948 if (isAnonymous()) |
| 1084 return "RenderDeprecatedFlexibleBox (generated)"; | 949 return "RenderDeprecatedFlexibleBox (generated)"; |
| 1085 if (isRelPositioned()) | 950 if (isRelPositioned()) |
| 1086 return "RenderDeprecatedFlexibleBox (relative positioned)"; | 951 return "RenderDeprecatedFlexibleBox (relative positioned)"; |
| 1087 return "RenderDeprecatedFlexibleBox"; | 952 return "RenderDeprecatedFlexibleBox"; |
| 1088 } | 953 } |
| 1089 | 954 |
| 1090 } // namespace WebCore | 955 } // namespace WebCore |
| OLD | NEW |