OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2007 David Smith (catfish.man@gmail.com) | 4 * (C) 2007 David Smith (catfish.man@gmail.com) |
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. |
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 // the middle of recomputing the style so we can't rely on any of its | 98 // the middle of recomputing the style so we can't rely on any of its |
99 // information), which is why it's easier to just update it for every layout. | 99 // information), which is why it's easier to just update it for every layout. |
100 static TrackedDescendantsMap* gPositionedDescendantsMap = nullptr; | 100 static TrackedDescendantsMap* gPositionedDescendantsMap = nullptr; |
101 static TrackedContainerMap* gPositionedContainerMap = nullptr; | 101 static TrackedContainerMap* gPositionedContainerMap = nullptr; |
102 | 102 |
103 // This map keeps track of the descendants whose 'height' is percentage associat ed | 103 // This map keeps track of the descendants whose 'height' is percentage associat ed |
104 // with a containing block. Like |gPositionedDescendantsMap|, it is also recompu ted | 104 // with a containing block. Like |gPositionedDescendantsMap|, it is also recompu ted |
105 // for every layout (see the comment above about why). | 105 // for every layout (see the comment above about why). |
106 static TrackedDescendantsMap* gPercentHeightDescendantsMap = nullptr; | 106 static TrackedDescendantsMap* gPercentHeightDescendantsMap = nullptr; |
107 | 107 |
108 typedef WTF::HashSet<LayoutBlock*> DelayedUpdateScrollInfoSet; | 108 typedef WTF::HashSet<LayoutBlock*> DelayedUpdateScrollInfoSet; |
mstensho (USE GERRIT)
2016/02/22 10:05:19
I've mentioned this quite a few times already:
Ca
| |
109 static int gDelayUpdateScrollInfo = 0; | 109 static int gDelayUpdateScrollInfo = 0; |
110 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = nullptr; | 110 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = nullptr; |
111 | 111 |
112 LayoutBlock::LayoutBlock(ContainerNode* node) | 112 LayoutBlock::LayoutBlock(ContainerNode* node) |
113 : LayoutBox(node) | 113 : LayoutBox(node) |
114 , m_hasMarginBeforeQuirk(false) | 114 , m_hasMarginBeforeQuirk(false) |
115 , m_hasMarginAfterQuirk(false) | 115 , m_hasMarginAfterQuirk(false) |
116 , m_beingDestroyed(false) | 116 , m_beingDestroyed(false) |
117 , m_hasMarkupTruncation(false) | 117 , m_hasMarkupTruncation(false) |
118 , m_widthAvailableToChildrenChanged(false) | 118 , m_widthAvailableToChildrenChanged(false) |
119 , m_heightAvailableToChildrenChanged(false) | |
119 , m_hasOnlySelfCollapsingChildren(false) | 120 , m_hasOnlySelfCollapsingChildren(false) |
120 , m_descendantsWithFloatsMarkedForLayout(false) | 121 , m_descendantsWithFloatsMarkedForLayout(false) |
121 , m_hasPositionedObjects(false) | 122 , m_hasPositionedObjects(false) |
122 , m_hasPercentHeightDescendants(false) | 123 , m_hasPercentHeightDescendants(false) |
123 { | 124 { |
124 // LayoutBlockFlow calls setChildrenInline(true). | 125 // LayoutBlockFlow calls setChildrenInline(true). |
125 // By default, subclasses do not have inline children. | 126 // By default, subclasses do not have inline children. |
126 } | 127 } |
127 | 128 |
128 void LayoutBlock::removeFromGlobalMaps() | 129 void LayoutBlock::removeFromGlobalMaps() |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 // Remove our fixed positioned descendants from their current contai ning block. | 228 // Remove our fixed positioned descendants from their current contai ning block. |
228 // They will be inserted into our positioned objects list during lay out. | 229 // They will be inserted into our positioned objects list during lay out. |
229 if (LayoutBlock* cb = containerForFixedPosition()) | 230 if (LayoutBlock* cb = containerForFixedPosition()) |
230 cb->removePositionedObjects(this, NewContainingBlock); | 231 cb->removePositionedObjects(this, NewContainingBlock); |
231 } | 232 } |
232 } | 233 } |
233 | 234 |
234 LayoutBox::styleWillChange(diff, newStyle); | 235 LayoutBox::styleWillChange(diff, newStyle); |
235 } | 236 } |
236 | 237 |
237 static bool borderOrPaddingLogicalWidthChanged(const ComputedStyle& oldStyle, co nst ComputedStyle& newStyle) | 238 enum LogicalExtent { LogicalWidth, LogicalHeight }; |
239 static bool borderOrPaddingLogicalDimensionChanged(const ComputedStyle& oldStyle , const ComputedStyle& newStyle, LogicalExtent logicalExtent) | |
238 { | 240 { |
239 if (newStyle.isHorizontalWritingMode()) { | 241 if (newStyle.isHorizontalWritingMode() == (logicalExtent == LogicalWidth)) { |
240 return oldStyle.borderLeftWidth() != newStyle.borderLeftWidth() | 242 return oldStyle.borderLeftWidth() != newStyle.borderLeftWidth() |
241 || oldStyle.borderRightWidth() != newStyle.borderRightWidth() | 243 || oldStyle.borderRightWidth() != newStyle.borderRightWidth() |
242 || oldStyle.paddingLeft() != newStyle.paddingLeft() | 244 || oldStyle.paddingLeft() != newStyle.paddingLeft() |
243 || oldStyle.paddingRight() != newStyle.paddingRight(); | 245 || oldStyle.paddingRight() != newStyle.paddingRight(); |
244 } | 246 } |
245 | 247 |
246 return oldStyle.borderTopWidth() != newStyle.borderTopWidth() | 248 return oldStyle.borderTopWidth() != newStyle.borderTopWidth() |
247 || oldStyle.borderBottomWidth() != newStyle.borderBottomWidth() | 249 || oldStyle.borderBottomWidth() != newStyle.borderBottomWidth() |
248 || oldStyle.paddingTop() != newStyle.paddingTop() | 250 || oldStyle.paddingTop() != newStyle.paddingTop() |
249 || oldStyle.paddingBottom() != newStyle.paddingBottom(); | 251 || oldStyle.paddingBottom() != newStyle.paddingBottom(); |
(...skipping 22 matching lines...) Expand all Loading... | |
272 if (LayoutBlock* cb = containingBlock()) | 274 if (LayoutBlock* cb = containingBlock()) |
273 cb->removePositionedObjects(this, NewContainingBlock); | 275 cb->removePositionedObjects(this, NewContainingBlock); |
274 } | 276 } |
275 } | 277 } |
276 | 278 |
277 if (TextAutosizer* textAutosizer = document().textAutosizer()) | 279 if (TextAutosizer* textAutosizer = document().textAutosizer()) |
278 textAutosizer->record(this); | 280 textAutosizer->record(this); |
279 | 281 |
280 propagateStyleToAnonymousChildren(true); | 282 propagateStyleToAnonymousChildren(true); |
281 | 283 |
282 // It's possible for our border/padding to change, but for the overall logic al width of the block to | 284 // It's possible for our border/padding to change, but for the overall logic al width or height of the block to |
283 // end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true. | 285 // end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true. |
284 m_widthAvailableToChildrenChanged |= oldStyle && diff.needsFullLayout() && n eedsLayout() && borderOrPaddingLogicalWidthChanged(*oldStyle, newStyle); | 286 m_widthAvailableToChildrenChanged |= oldStyle && diff.needsFullLayout() && n eedsLayout() && borderOrPaddingLogicalDimensionChanged(*oldStyle, newStyle, Logi calWidth); |
287 m_heightAvailableToChildrenChanged |= oldStyle && diff.needsFullLayout() && needsLayout() && borderOrPaddingLogicalDimensionChanged(*oldStyle, newStyle, Log icalHeight); | |
285 } | 288 } |
286 | 289 |
287 void LayoutBlock::invalidatePaintOfSubtreesIfNeeded(PaintInvalidationState& chil dPaintInvalidationState) | 290 void LayoutBlock::invalidatePaintOfSubtreesIfNeeded(PaintInvalidationState& chil dPaintInvalidationState) |
288 { | 291 { |
289 LayoutBox::invalidatePaintOfSubtreesIfNeeded(childPaintInvalidationState); | 292 LayoutBox::invalidatePaintOfSubtreesIfNeeded(childPaintInvalidationState); |
290 | 293 |
291 // Take care of positioned objects. This is required as PaintInvalidationSta te keeps a single clip rect. | 294 // Take care of positioned objects. This is required as PaintInvalidationSta te keeps a single clip rect. |
292 if (TrackedLayoutBoxListHashSet* positionedObjects = this->positionedObjects ()) { | 295 if (TrackedLayoutBoxListHashSet* positionedObjects = this->positionedObjects ()) { |
293 for (auto* box : *positionedObjects) { | 296 for (auto* box : *positionedObjects) { |
294 | 297 |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
885 | 888 |
886 // It's safe to check for control clip here, since controls can never be tab le cells. | 889 // It's safe to check for control clip here, since controls can never be tab le cells. |
887 // If we have a lightweight clip, there can never be any overflow from child ren. | 890 // If we have a lightweight clip, there can never be any overflow from child ren. |
888 if (hasControlClip() && m_overflow) | 891 if (hasControlClip() && m_overflow) |
889 clearLayoutOverflow(); | 892 clearLayoutOverflow(); |
890 | 893 |
891 invalidateBackgroundObscurationStatus(); | 894 invalidateBackgroundObscurationStatus(); |
892 | 895 |
893 if (needsScrollAnchoring) | 896 if (needsScrollAnchoring) |
894 scrollableArea()->scrollAnchor().restore(); | 897 scrollableArea()->scrollAnchor().restore(); |
898 | |
899 m_heightAvailableToChildrenChanged = false; | |
895 } | 900 } |
896 | 901 |
897 bool LayoutBlock::widthAvailableToChildrenHasChanged() | 902 bool LayoutBlock::widthAvailableToChildrenHasChanged() |
898 { | 903 { |
904 // TODO(robhogan): Does m_widthAvailableToChildrenChanged always get reset w hen it needs to? | |
mstensho (USE GERRIT)
2016/02/22 10:05:19
To answer your rhetorical question: No! :)
Yeah,
| |
899 bool widthAvailableToChildrenHasChanged = m_widthAvailableToChildrenChanged; | 905 bool widthAvailableToChildrenHasChanged = m_widthAvailableToChildrenChanged; |
900 m_widthAvailableToChildrenChanged = false; | 906 m_widthAvailableToChildrenChanged = false; |
901 | 907 |
902 // If we use border-box sizing, have percentage padding, and our parent has changed width then the width available to our children has changed even | 908 // If we use border-box sizing, have percentage padding, and our parent has changed width then the width available to our children has changed even |
903 // though our own width has remained the same. | 909 // though our own width has remained the same. |
904 widthAvailableToChildrenHasChanged |= style()->boxSizing() == BORDER_BOX && needsPreferredWidthsRecalculation() && view()->layoutState()->containingBlockLog icalWidthChanged(); | 910 widthAvailableToChildrenHasChanged |= style()->boxSizing() == BORDER_BOX && needsPreferredWidthsRecalculation() && view()->layoutState()->containingBlockLog icalWidthChanged(); |
905 | 911 |
906 return widthAvailableToChildrenHasChanged; | 912 return widthAvailableToChildrenHasChanged; |
907 } | 913 } |
908 | 914 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
988 addVisualOverflow(LayoutRect(inflatedRect)); | 994 addVisualOverflow(LayoutRect(inflatedRect)); |
989 } | 995 } |
990 | 996 |
991 bool LayoutBlock::createsNewFormattingContext() const | 997 bool LayoutBlock::createsNewFormattingContext() const |
992 { | 998 { |
993 return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || isFlexItemIncludingDeprecated() | 999 return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || isFlexItemIncludingDeprecated() |
994 || style()->specifiesColumns() || isLayoutFlowThread() || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() | 1000 || style()->specifiesColumns() || isLayoutFlowThread() || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() |
995 || isDocumentElement() || isColumnSpanAll() || isGridItem() || style()-> containsPaint(); | 1001 || isDocumentElement() || isColumnSpanAll() || isGridItem() || style()-> containsPaint(); |
996 } | 1002 } |
997 | 1003 |
1004 bool static changeInAvailableLogicalHeightAffectsChild(LayoutBlock* parent, Layo utBox& child) | |
mstensho (USE GERRIT)
2016/02/22 10:05:19
"bool static"? Can you really say that? Shouldn't
| |
1005 { | |
1006 if (parent->style()->boxSizing() != BORDER_BOX) | |
1007 return false; | |
1008 return parent->style()->isHorizontalWritingMode() && !child.style()->isHoriz ontalWritingMode(); | |
1009 } | |
1010 | |
998 void LayoutBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, L ayoutBox& child) | 1011 void LayoutBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, L ayoutBox& child) |
999 { | 1012 { |
1000 if (child.isOutOfFlowPositioned()) { | 1013 if (child.isOutOfFlowPositioned()) { |
1001 // It's rather useless to mark out-of-flow children at this point. We ma y not be their | 1014 // It's rather useless to mark out-of-flow children at this point. We ma y not be their |
1002 // containing block (and if we are, it's just pure luck), so this would be the wrong place | 1015 // containing block (and if we are, it's just pure luck), so this would be the wrong place |
1003 // for it. Furthermore, it would cause trouble for out-of-flow descendan ts of column | 1016 // for it. Furthermore, it would cause trouble for out-of-flow descendan ts of column |
1004 // spanners, if the containing block is outside the spanner but inside t he multicol container. | 1017 // spanners, if the containing block is outside the spanner but inside t he multicol container. |
1005 return; | 1018 return; |
1006 } | 1019 } |
1007 // FIXME: Technically percentage height objects only need a relayout if thei r percentage isn't going to be turned into | 1020 // FIXME: Technically percentage height objects only need a relayout if thei r percentage isn't going to be turned into |
1008 // an auto value. Add a method to determine this, so that we can avoid the r elayout. | 1021 // an auto value. Add a method to determine this, so that we can avoid the r elayout. |
1009 bool hasRelativeLogicalHeight = child.hasRelativeLogicalHeight() | 1022 bool hasRelativeLogicalHeight = child.hasRelativeLogicalHeight() |
1010 || (child.isAnonymous() && this->hasRelativeLogicalHeight()) | 1023 || (child.isAnonymous() && this->hasRelativeLogicalHeight()) |
1011 || child.stretchesToViewport(); | 1024 || child.stretchesToViewport(); |
1012 if (relayoutChildren || (hasRelativeLogicalHeight && !isLayoutView())) { | 1025 if (relayoutChildren || (hasRelativeLogicalHeight && !isLayoutView()) |
1026 || (m_heightAvailableToChildrenChanged && changeInAvailableLogicalHeight AffectsChild(this, child))) { | |
1013 child.setChildNeedsLayout(MarkOnlyThis); | 1027 child.setChildNeedsLayout(MarkOnlyThis); |
1014 | 1028 |
1015 // If the child has percentage padding or an embedded content box, we al so need to invalidate the childs pref widths. | 1029 // If the child has percentage padding or an embedded content box, we al so need to invalidate the childs pref widths. |
1016 if (child.needsPreferredWidthsRecalculation()) | 1030 if (child.needsPreferredWidthsRecalculation()) |
1017 child.setPreferredLogicalWidthsDirty(MarkOnlyThis); | 1031 child.setPreferredLogicalWidthsDirty(MarkOnlyThis); |
1018 } | 1032 } |
1019 } | 1033 } |
1020 | 1034 |
1021 void LayoutBlock::simplifiedNormalFlowLayout() | 1035 void LayoutBlock::simplifiedNormalFlowLayout() |
1022 { | 1036 { |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1199 SubtreeLayoutScope layoutScope(*positionedObject); | 1213 SubtreeLayoutScope layoutScope(*positionedObject); |
1200 // A fixed position element with an absolute positioned ancestor has no way of knowing if the latter has changed position. So | 1214 // A fixed position element with an absolute positioned ancestor has no way of knowing if the latter has changed position. So |
1201 // if this is a fixed position element, mark it for layout if it has an abspos ancestor and needs to move with that ancestor, i.e. | 1215 // if this is a fixed position element, mark it for layout if it has an abspos ancestor and needs to move with that ancestor, i.e. |
1202 // it has static position. | 1216 // it has static position. |
1203 markFixedPositionObjectForLayoutIfNeeded(positionedObject, layoutScope); | 1217 markFixedPositionObjectForLayoutIfNeeded(positionedObject, layoutScope); |
1204 if (info == LayoutOnlyFixedPositionedObjects) { | 1218 if (info == LayoutOnlyFixedPositionedObjects) { |
1205 positionedObject->layoutIfNeeded(); | 1219 positionedObject->layoutIfNeeded(); |
1206 continue; | 1220 continue; |
1207 } | 1221 } |
1208 | 1222 |
1209 if (!positionedObject->normalChildNeedsLayout() && (relayoutChildren || needsLayoutDueToStaticPosition(positionedObject))) | 1223 if (!positionedObject->normalChildNeedsLayout() && (relayoutChildren || m_heightAvailableToChildrenChanged || needsLayoutDueToStaticPosition(positionedO bject))) |
1210 layoutScope.setChildNeedsLayout(positionedObject); | 1224 layoutScope.setChildNeedsLayout(positionedObject); |
1211 | 1225 |
1212 // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths. | 1226 // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths. |
1213 if (relayoutChildren && positionedObject->needsPreferredWidthsRecalculat ion()) | 1227 if (relayoutChildren && positionedObject->needsPreferredWidthsRecalculat ion()) |
1214 positionedObject->setPreferredLogicalWidthsDirty(MarkOnlyThis); | 1228 positionedObject->setPreferredLogicalWidthsDirty(MarkOnlyThis); |
1215 | 1229 |
1216 LayoutUnit logicalTopEstimate; | 1230 LayoutUnit logicalTopEstimate; |
1217 bool needsBlockDirectionLocationSetBeforeLayout = isPaginated && positio nedObject->paginationBreakability() != ForbidBreaks; | 1231 bool needsBlockDirectionLocationSetBeforeLayout = isPaginated && positio nedObject->paginationBreakability() != ForbidBreaks; |
1218 if (needsBlockDirectionLocationSetBeforeLayout) { | 1232 if (needsBlockDirectionLocationSetBeforeLayout) { |
1219 // Out-of-flow objects are normally positioned after layout (while i n-flow objects are | 1233 // Out-of-flow objects are normally positioned after layout (while i n-flow objects are |
(...skipping 1628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2848 void LayoutBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Layout Object* obj) const | 2862 void LayoutBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Layout Object* obj) const |
2849 { | 2863 { |
2850 showLayoutObject(); | 2864 showLayoutObject(); |
2851 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot Box()) | 2865 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot Box()) |
2852 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa bel2, obj, 1); | 2866 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa bel2, obj, 1); |
2853 } | 2867 } |
2854 | 2868 |
2855 #endif | 2869 #endif |
2856 | 2870 |
2857 } // namespace blink | 2871 } // namespace blink |
OLD | NEW |