| 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) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
| 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) | 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) |
| 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
| 7 * Copyright (C) 2010 Google Inc. All rights reserved. | 7 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #include "core/paint/ObjectPaintInvalidator.h" | 39 #include "core/paint/ObjectPaintInvalidator.h" |
| 40 #include "core/paint/PaintLayer.h" | 40 #include "core/paint/PaintLayer.h" |
| 41 #include "core/style/ShadowList.h" | 41 #include "core/style/ShadowList.h" |
| 42 #include "platform/LengthFunctions.h" | 42 #include "platform/LengthFunctions.h" |
| 43 #include "platform/geometry/TransformState.h" | 43 #include "platform/geometry/TransformState.h" |
| 44 #include "platform/scroll/MainThreadScrollingReason.h" | 44 #include "platform/scroll/MainThreadScrollingReason.h" |
| 45 #include "wtf/PtrUtil.h" | 45 #include "wtf/PtrUtil.h" |
| 46 | 46 |
| 47 namespace blink { | 47 namespace blink { |
| 48 | 48 |
| 49 namespace { |
| 50 inline bool isOutOfFlowPositionedWithImplicitHeight( |
| 51 const LayoutBoxModelObject* child) { |
| 52 return child->isOutOfFlowPositioned() && |
| 53 !child->style()->logicalTop().isAuto() && |
| 54 !child->style()->logicalBottom().isAuto(); |
| 55 } |
| 56 |
| 57 StickyPositionScrollingConstraints* stickyConstraintsForLayoutObject( |
| 58 const LayoutBoxModelObject* obj, |
| 59 const PaintLayer* ancestorOverflowLayer) { |
| 60 if (!obj) |
| 61 return nullptr; |
| 62 |
| 63 PaintLayerScrollableArea* scrollableArea = |
| 64 ancestorOverflowLayer->getScrollableArea(); |
| 65 auto it = scrollableArea->stickyConstraintsMap().find(obj->layer()); |
| 66 if (it == scrollableArea->stickyConstraintsMap().end()) |
| 67 return nullptr; |
| 68 |
| 69 return &it->value; |
| 70 } |
| 71 |
| 72 // Inclusive of |from|, exclusive of |to|. |
| 73 LayoutBoxModelObject* findFirstStickyBetween(LayoutObject* from, |
| 74 LayoutObject* to) { |
| 75 LayoutObject* maybeStickyAncestor = from; |
| 76 while (maybeStickyAncestor && maybeStickyAncestor != to) { |
| 77 if (maybeStickyAncestor->isStickyPositioned()) { |
| 78 return toLayoutBoxModelObject(maybeStickyAncestor); |
| 79 } |
| 80 |
| 81 maybeStickyAncestor = |
| 82 maybeStickyAncestor->isLayoutInline() |
| 83 ? maybeStickyAncestor->containingBlock() |
| 84 : toLayoutBox(maybeStickyAncestor)->locationContainer(); |
| 85 } |
| 86 return nullptr; |
| 87 } |
| 88 } // namespace |
| 89 |
| 49 class FloatStateForStyleChange { | 90 class FloatStateForStyleChange { |
| 50 public: | 91 public: |
| 51 static void setWasFloating(LayoutBoxModelObject* boxModelObject, | 92 static void setWasFloating(LayoutBoxModelObject* boxModelObject, |
| 52 bool wasFloating) { | 93 bool wasFloating) { |
| 53 s_wasFloating = wasFloating; | 94 s_wasFloating = wasFloating; |
| 54 s_boxModelObject = boxModelObject; | 95 s_boxModelObject = boxModelObject; |
| 55 } | 96 } |
| 56 | 97 |
| 57 static bool wasFloating(LayoutBoxModelObject* boxModelObject) { | 98 static bool wasFloating(LayoutBoxModelObject* boxModelObject) { |
| 58 ASSERT(boxModelObject == s_boxModelObject); | 99 ASSERT(boxModelObject == s_boxModelObject); |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 } | 696 } |
| 656 | 697 |
| 657 void LayoutBoxModelObject::updateFromStyle() { | 698 void LayoutBoxModelObject::updateFromStyle() { |
| 658 const ComputedStyle& styleToUse = styleRef(); | 699 const ComputedStyle& styleToUse = styleRef(); |
| 659 setHasBoxDecorationBackground(styleToUse.hasBoxDecorationBackground()); | 700 setHasBoxDecorationBackground(styleToUse.hasBoxDecorationBackground()); |
| 660 setInline(styleToUse.isDisplayInlineType()); | 701 setInline(styleToUse.isDisplayInlineType()); |
| 661 setPositionState(styleToUse.position()); | 702 setPositionState(styleToUse.position()); |
| 662 setHorizontalWritingMode(styleToUse.isHorizontalWritingMode()); | 703 setHorizontalWritingMode(styleToUse.isHorizontalWritingMode()); |
| 663 } | 704 } |
| 664 | 705 |
| 665 static inline bool isOutOfFlowPositionedWithImplicitHeight( | |
| 666 const LayoutBoxModelObject* child) { | |
| 667 return child->isOutOfFlowPositioned() && | |
| 668 !child->style()->logicalTop().isAuto() && | |
| 669 !child->style()->logicalBottom().isAuto(); | |
| 670 } | |
| 671 | |
| 672 LayoutBlock* LayoutBoxModelObject::containingBlockForAutoHeightDetection( | 706 LayoutBlock* LayoutBoxModelObject::containingBlockForAutoHeightDetection( |
| 673 Length logicalHeight) const { | 707 Length logicalHeight) const { |
| 674 // For percentage heights: The percentage is calculated with respect to the | 708 // For percentage heights: The percentage is calculated with respect to the |
| 675 // height of the generated box's containing block. If the height of the | 709 // height of the generated box's containing block. If the height of the |
| 676 // containing block is not specified explicitly (i.e., it depends on content | 710 // containing block is not specified explicitly (i.e., it depends on content |
| 677 // height), and this element is not absolutely positioned, the used height is | 711 // height), and this element is not absolutely positioned, the used height is |
| 678 // calculated as if 'auto' was specified. | 712 // calculated as if 'auto' was specified. |
| 679 if (!logicalHeight.isPercentOrCalc() || isOutOfFlowPositioned()) | 713 if (!logicalHeight.isPercentOrCalc() || isOutOfFlowPositioned()) |
| 680 return nullptr; | 714 return nullptr; |
| 681 | 715 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 | 863 |
| 830 void LayoutBoxModelObject::updateStickyPositionConstraints() const { | 864 void LayoutBoxModelObject::updateStickyPositionConstraints() const { |
| 831 const FloatSize constrainingSize = computeStickyConstrainingRect().size(); | 865 const FloatSize constrainingSize = computeStickyConstrainingRect().size(); |
| 832 | 866 |
| 833 PaintLayerScrollableArea* scrollableArea = | 867 PaintLayerScrollableArea* scrollableArea = |
| 834 layer()->ancestorOverflowLayer()->getScrollableArea(); | 868 layer()->ancestorOverflowLayer()->getScrollableArea(); |
| 835 StickyPositionScrollingConstraints constraints; | 869 StickyPositionScrollingConstraints constraints; |
| 836 FloatSize skippedContainersOffset; | 870 FloatSize skippedContainersOffset; |
| 837 LayoutBlock* containingBlock = this->containingBlock(); | 871 LayoutBlock* containingBlock = this->containingBlock(); |
| 838 // The location container for boxes is not always the containing block. | 872 // The location container for boxes is not always the containing block. |
| 839 LayoutBox* locationContainer = isLayoutInline() | 873 LayoutObject* locationContainer = |
| 840 ? containingBlock | 874 isLayoutInline() ? container() : toLayoutBox(this)->locationContainer(); |
| 841 : toLayoutBox(this)->locationContainer(); | |
| 842 // Skip anonymous containing blocks. | 875 // Skip anonymous containing blocks. |
| 843 while (containingBlock->isAnonymous()) { | 876 while (containingBlock->isAnonymous()) { |
| 844 containingBlock = containingBlock->containingBlock(); | 877 containingBlock = containingBlock->containingBlock(); |
| 845 } | 878 } |
| 846 MapCoordinatesFlags flags = 0; | 879 MapCoordinatesFlags flags = IgnoreStickyOffset; |
| 847 skippedContainersOffset = | 880 skippedContainersOffset = |
| 848 toFloatSize(locationContainer | 881 toFloatSize(locationContainer |
| 849 ->localToAncestorQuadWithoutTransforms( | 882 ->localToAncestorQuadWithoutTransforms( |
| 850 FloatQuad(), containingBlock, flags) | 883 FloatQuad(), containingBlock, flags) |
| 851 .boundingBox() | 884 .boundingBox() |
| 852 .location()); | 885 .location()); |
| 853 LayoutBox* scrollAncestor = | 886 LayoutBox* scrollAncestor = |
| 854 layer()->ancestorOverflowLayer()->isRootLayer() | 887 layer()->ancestorOverflowLayer()->isRootLayer() |
| 855 ? nullptr | 888 ? nullptr |
| 856 : &toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject()); | 889 : &toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject()); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 minimumValueForLength(containingBlock->style()->paddingLeft(), | 949 minimumValueForLength(containingBlock->style()->paddingLeft(), |
| 917 maxContainerWidth) + | 950 maxContainerWidth) + |
| 918 minimumValueForLength(style()->marginLeft(), maxWidth)); | 951 minimumValueForLength(style()->marginLeft(), maxWidth)); |
| 919 | 952 |
| 920 constraints.setScrollContainerRelativeContainingBlockRect( | 953 constraints.setScrollContainerRelativeContainingBlockRect( |
| 921 FloatRect(scrollContainerRelativeContainingBlockRect)); | 954 FloatRect(scrollContainerRelativeContainingBlockRect)); |
| 922 | 955 |
| 923 FloatRect stickyBoxRect = | 956 FloatRect stickyBoxRect = |
| 924 isLayoutInline() ? FloatRect(toLayoutInline(this)->linesBoundingBox()) | 957 isLayoutInline() ? FloatRect(toLayoutInline(this)->linesBoundingBox()) |
| 925 : FloatRect(toLayoutBox(this)->frameRect()); | 958 : FloatRect(toLayoutBox(this)->frameRect()); |
| 959 |
| 926 FloatRect flippedStickyBoxRect = stickyBoxRect; | 960 FloatRect flippedStickyBoxRect = stickyBoxRect; |
| 927 containingBlock->flipForWritingMode(flippedStickyBoxRect); | 961 containingBlock->flipForWritingMode(flippedStickyBoxRect); |
| 928 FloatPoint stickyLocation = | 962 FloatPoint stickyLocation = |
| 929 flippedStickyBoxRect.location() + skippedContainersOffset; | 963 flippedStickyBoxRect.location() + skippedContainersOffset; |
| 930 | 964 |
| 931 // The scrollContainerRelativePaddingBoxRect's position is the padding box so | 965 // The scrollContainerRelativePaddingBoxRect's position is the padding box so |
| 932 // we need to remove the border when finding the position of the sticky box | 966 // we need to remove the border when finding the position of the sticky box |
| 933 // within the scroll ancestor if the container is not our scroll ancestor. If | 967 // within the scroll ancestor if the container is not our scroll ancestor. If |
| 934 // the container is our scroll ancestor, we also need to remove the border | 968 // the container is our scroll ancestor, we also need to remove the border |
| 935 // box because we want the position from within the scroller border. | 969 // box because we want the position from within the scroller border. |
| 936 FloatSize containerBorderOffset(containingBlock->borderLeft(), | 970 FloatSize containerBorderOffset(containingBlock->borderLeft(), |
| 937 containingBlock->borderTop()); | 971 containingBlock->borderTop()); |
| 938 stickyLocation -= containerBorderOffset; | 972 stickyLocation -= containerBorderOffset; |
| 939 constraints.setScrollContainerRelativeStickyBoxRect( | 973 constraints.setScrollContainerRelativeStickyBoxRect( |
| 940 FloatRect(scrollContainerRelativePaddingBoxRect.location() + | 974 FloatRect(scrollContainerRelativePaddingBoxRect.location() + |
| 941 toFloatSize(stickyLocation), | 975 toFloatSize(stickyLocation), |
| 942 flippedStickyBoxRect.size())); | 976 flippedStickyBoxRect.size())); |
| 943 | 977 |
| 978 // To correctly compute the offsets, the constraints need to know about any |
| 979 // nested position:sticky elements between themselves and their |
| 980 // containingBlock, and between the containingBlock and their scrollAncestor. |
| 981 // |
| 982 // The respective search ranges are [container, containingBlock) and |
| 983 // [containingBlock, scrollAncestor). |
| 984 constraints.setNearestStickyBoxShiftingStickyBox( |
| 985 findFirstStickyBetween(locationContainer, containingBlock)); |
| 986 // We cannot use |scrollAncestor| here as it disregards the root |
| 987 // ancestorOverflowLayer(), which we should include. |
| 988 constraints.setNearestStickyBoxShiftingContainingBlock(findFirstStickyBetween( |
| 989 containingBlock, &layer()->ancestorOverflowLayer()->layoutObject())); |
| 990 |
| 944 // We skip the right or top sticky offset if there is not enough space to | 991 // We skip the right or top sticky offset if there is not enough space to |
| 945 // honor both the left/right or top/bottom offsets. | 992 // honor both the left/right or top/bottom offsets. |
| 946 LayoutUnit horizontalOffsets = | 993 LayoutUnit horizontalOffsets = |
| 947 minimumValueForLength(style()->right(), | 994 minimumValueForLength(style()->right(), |
| 948 LayoutUnit(constrainingSize.width())) + | 995 LayoutUnit(constrainingSize.width())) + |
| 949 minimumValueForLength(style()->left(), | 996 minimumValueForLength(style()->left(), |
| 950 LayoutUnit(constrainingSize.width())); | 997 LayoutUnit(constrainingSize.width())); |
| 951 bool skipRight = false; | 998 bool skipRight = false; |
| 952 bool skipLeft = false; | 999 bool skipLeft = false; |
| 953 if (!style()->left().isAuto() && !style()->right().isAuto()) { | 1000 if (!style()->left().isAuto() && !style()->right().isAuto()) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1028 enclosingClippingBox->paddingBottom())); | 1075 enclosingClippingBox->paddingBottom())); |
| 1029 return constrainingRect; | 1076 return constrainingRect; |
| 1030 } | 1077 } |
| 1031 | 1078 |
| 1032 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const { | 1079 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const { |
| 1033 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer(); | 1080 const PaintLayer* ancestorOverflowLayer = layer()->ancestorOverflowLayer(); |
| 1034 // TODO: Force compositing input update if we ask for offset before | 1081 // TODO: Force compositing input update if we ask for offset before |
| 1035 // compositing inputs have been computed? | 1082 // compositing inputs have been computed? |
| 1036 if (!ancestorOverflowLayer) | 1083 if (!ancestorOverflowLayer) |
| 1037 return LayoutSize(); | 1084 return LayoutSize(); |
| 1038 FloatRect constrainingRect = computeStickyConstrainingRect(); | 1085 |
| 1039 PaintLayerScrollableArea* scrollableArea = | 1086 StickyPositionScrollingConstraints* constraints = |
| 1040 ancestorOverflowLayer->getScrollableArea(); | 1087 stickyConstraintsForLayoutObject(this, ancestorOverflowLayer); |
| 1088 if (!constraints) |
| 1089 return LayoutSize(); |
| 1090 |
| 1091 StickyPositionScrollingConstraints* shiftingStickyBoxConstraints = |
| 1092 stickyConstraintsForLayoutObject( |
| 1093 constraints->nearestStickyBoxShiftingStickyBox(), |
| 1094 ancestorOverflowLayer); |
| 1095 |
| 1096 StickyPositionScrollingConstraints* shiftingContainingBlockConstraints = |
| 1097 stickyConstraintsForLayoutObject( |
| 1098 constraints->nearestStickyBoxShiftingContainingBlock(), |
| 1099 ancestorOverflowLayer); |
| 1041 | 1100 |
| 1042 // The sticky offset is physical, so we can just return the delta computed in | 1101 // The sticky offset is physical, so we can just return the delta computed in |
| 1043 // absolute coords (though it may be wrong with transforms). | 1102 // absolute coords (though it may be wrong with transforms). |
| 1044 // TODO: Force compositing input update if we ask for offset with stale | 1103 FloatRect constrainingRect = computeStickyConstrainingRect(); |
| 1045 // compositing inputs. | 1104 return LayoutSize(constraints->computeStickyOffset( |
| 1046 if (!scrollableArea->stickyConstraintsMap().contains(layer())) | 1105 constrainingRect, shiftingStickyBoxConstraints, |
| 1047 return LayoutSize(); | 1106 shiftingContainingBlockConstraints)); |
| 1048 return LayoutSize( | |
| 1049 scrollableArea->stickyConstraintsMap().at(layer()).computeStickyOffset( | |
| 1050 constrainingRect)); | |
| 1051 } | 1107 } |
| 1052 | 1108 |
| 1053 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeTo( | 1109 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeTo( |
| 1054 const LayoutPoint& startPoint, | 1110 const LayoutPoint& startPoint, |
| 1055 const Element* offsetParent) const { | 1111 const Element* offsetParent) const { |
| 1056 // If the element is the HTML body element or doesn't have a parent | 1112 // If the element is the HTML body element or doesn't have a parent |
| 1057 // return 0 and stop this algorithm. | 1113 // return 0 and stop this algorithm. |
| 1058 if (isBody() || !parent()) | 1114 if (isBody() || !parent()) |
| 1059 return LayoutPoint(); | 1115 return LayoutPoint(); |
| 1060 | 1116 |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1410 if (rootElementStyle->hasBackground()) | 1466 if (rootElementStyle->hasBackground()) |
| 1411 return false; | 1467 return false; |
| 1412 | 1468 |
| 1413 if (node() != document().firstBodyElement()) | 1469 if (node() != document().firstBodyElement()) |
| 1414 return false; | 1470 return false; |
| 1415 | 1471 |
| 1416 return true; | 1472 return true; |
| 1417 } | 1473 } |
| 1418 | 1474 |
| 1419 } // namespace blink | 1475 } // namespace blink |
| OLD | NEW |