Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp

Issue 2346383005: Compute sticky position constraints without considering transforms. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 23 matching lines...) Expand all
34 #include "core/layout/LayoutGeometryMap.h" 34 #include "core/layout/LayoutGeometryMap.h"
35 #include "core/layout/LayoutInline.h" 35 #include "core/layout/LayoutInline.h"
36 #include "core/layout/LayoutTheme.h" 36 #include "core/layout/LayoutTheme.h"
37 #include "core/layout/LayoutView.h" 37 #include "core/layout/LayoutView.h"
38 #include "core/layout/compositing/CompositedLayerMapping.h" 38 #include "core/layout/compositing/CompositedLayerMapping.h"
39 #include "core/layout/compositing/PaintLayerCompositor.h" 39 #include "core/layout/compositing/PaintLayerCompositor.h"
40 #include "core/paint/ObjectPaintInvalidator.h" 40 #include "core/paint/ObjectPaintInvalidator.h"
41 #include "core/paint/PaintLayer.h" 41 #include "core/paint/PaintLayer.h"
42 #include "core/style/ShadowList.h" 42 #include "core/style/ShadowList.h"
43 #include "platform/LengthFunctions.h" 43 #include "platform/LengthFunctions.h"
44 #include "platform/geometry/TransformState.h"
44 #include "wtf/PtrUtil.h" 45 #include "wtf/PtrUtil.h"
45 46
46 namespace blink { 47 namespace blink {
47 48
48 class FloatStateForStyleChange { 49 class FloatStateForStyleChange {
49 public: 50 public:
50 static void setWasFloating(LayoutBoxModelObject* boxModelObject, bool wasFlo ating) 51 static void setWasFloating(LayoutBoxModelObject* boxModelObject, bool wasFlo ating)
51 { 52 {
52 s_wasFloating = wasFloating; 53 s_wasFloating = wasFloating;
53 s_boxModelObject = boxModelObject; 54 s_boxModelObject = boxModelObject;
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 StickyPositionScrollingConstraints constraints; 687 StickyPositionScrollingConstraints constraints;
687 FloatSize skippedContainersOffset; 688 FloatSize skippedContainersOffset;
688 LayoutBlock* containingBlock = this->containingBlock(); 689 LayoutBlock* containingBlock = this->containingBlock();
689 // Skip anonymous containing blocks. 690 // Skip anonymous containing blocks.
690 while (containingBlock->isAnonymous()) { 691 while (containingBlock->isAnonymous()) {
691 skippedContainersOffset += toFloatSize(FloatPoint(containingBlock->frame Rect().location())); 692 skippedContainersOffset += toFloatSize(FloatPoint(containingBlock->frame Rect().location()));
692 containingBlock = containingBlock->containingBlock(); 693 containingBlock = containingBlock->containingBlock();
693 } 694 }
694 LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject()); 695 LayoutBox* scrollAncestor = layer()->ancestorOverflowLayer()->isRootLayer() ? nullptr : toLayoutBox(layer()->ancestorOverflowLayer()->layoutObject());
695 696
696 LayoutRect containerContentRect = containingBlock->layoutOverflowRect();
697 LayoutUnit maxContainerWidth = containingBlock->isLayoutView() ? containingB lock->logicalWidth() : containingBlock->containingBlockLogicalWidthForContent(); 697 LayoutUnit maxContainerWidth = containingBlock->isLayoutView() ? containingB lock->logicalWidth() : containingBlock->containingBlockLogicalWidthForContent();
698 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call 698 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call
699 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine. 699 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine.
700 // Compute the container-relative area within which the sticky element is al lowed to move. 700 // Compute the container-relative area within which the sticky element is al lowed to move.
701 LayoutUnit maxWidth = containingBlock->availableLogicalWidth(); 701 LayoutUnit maxWidth = containingBlock->availableLogicalWidth();
702 702
703 // Map the containing block to the scroll ancestor without transforms.
704 FloatRect scrollContainerRelativePaddingBoxRect(containingBlock->layoutOverf lowRect());
705 if (containingBlock != scrollAncestor) {
706 FloatQuad localQuad(FloatRect(containingBlock->paddingBoxRect()));
707 TransformState transformState(TransformState::ApplyTransformDirection, l ocalQuad.boundingBox().center(), localQuad);
708 containingBlock->mapLocalToAncestor(scrollAncestor, transformState, Appl yContainerFlip);
709 transformState.flatten();
710 scrollContainerRelativePaddingBoxRect = transformState.lastPlanarQuad(). boundingBox();
711
712 // The sticky position constraint rects should be independent of the cur rent scroll position, so after
713 // mapping we add in the scroll position to get the container's position within the ancestor scroller's
714 // unscrolled layout overflow.
715 FloatSize scrollOffset(scrollAncestor ? toFloatSize(scrollAncestor->getS crollableArea()->adjustedScrollOffset()) : FloatSize());
716 scrollContainerRelativePaddingBoxRect.move(scrollOffset);
717 }
718
719 LayoutRect scrollContainerRelativeContainingBlockRect(scrollContainerRelativ ePaddingBoxRect);
703 // This is removing the padding of the containing block's overflow rect to g et the flow 720 // This is removing the padding of the containing block's overflow rect to g et the flow
704 // box rectangle and removing the margin of the sticky element to ensure tha t space between 721 // box rectangle and removing the margin of the sticky element to ensure tha t space between
705 // the sticky element and its containing flow box. It is an open issue wheth er the margin 722 // the sticky element and its containing flow box. It is an open issue wheth er the margin
706 // should collapse (See https://www.w3.org/TR/css-position-3/#sticky-pos). 723 // should collapse (See https://www.w3.org/TR/css-position-3/#sticky-pos).
707 containerContentRect.contractEdges( 724 scrollContainerRelativeContainingBlockRect.contractEdges(
708 minimumValueForLength(containingBlock->style()->paddingTop(), maxContain erWidth) + minimumValueForLength(style()->marginTop(), maxWidth), 725 minimumValueForLength(containingBlock->style()->paddingTop(), maxContain erWidth) + minimumValueForLength(style()->marginTop(), maxWidth),
709 minimumValueForLength(containingBlock->style()->paddingRight(), maxConta inerWidth) + minimumValueForLength(style()->marginRight(), maxWidth), 726 minimumValueForLength(containingBlock->style()->paddingRight(), maxConta inerWidth) + minimumValueForLength(style()->marginRight(), maxWidth),
710 minimumValueForLength(containingBlock->style()->paddingBottom(), maxCont ainerWidth) + minimumValueForLength(style()->marginBottom(), maxWidth), 727 minimumValueForLength(containingBlock->style()->paddingBottom(), maxCont ainerWidth) + minimumValueForLength(style()->marginBottom(), maxWidth),
711 minimumValueForLength(containingBlock->style()->paddingLeft(), maxContai nerWidth) + minimumValueForLength(style()->marginLeft(), maxWidth)); 728 minimumValueForLength(containingBlock->style()->paddingLeft(), maxContai nerWidth) + minimumValueForLength(style()->marginLeft(), maxWidth));
712 729
713 // Map to the scroll ancestor. 730 constraints.setScrollContainerRelativeContainingBlockRect(FloatRect(scrollCo ntainerRelativeContainingBlockRect));
714 FloatRect scrollContainerRelativeContainingBlockRect(containingBlock->localT oAncestorQuad(FloatRect(containerContentRect), scrollAncestor).boundingBox());
715 FloatSize scrollOffset(scrollAncestor ? toFloatSize(scrollAncestor->getScrol lableArea()->adjustedScrollOffset()) : FloatSize());
716
717 // The sticky position constraint rects should be independent of the current scroll position, so after
718 // mapping we add in the scroll position to get the container's position wit hin the ancestor scroller's
719 // unscrolled layout overflow.
720 if (containingBlock != scrollAncestor)
721 scrollContainerRelativeContainingBlockRect.move(scrollOffset);
722 constraints.setScrollContainerRelativeContainingBlockRect(scrollContainerRel ativeContainingBlockRect);
723 731
724 FloatRect stickyBoxRect = isLayoutInline() 732 FloatRect stickyBoxRect = isLayoutInline()
725 ? FloatRect(toLayoutInline(this)->linesBoundingBox()) 733 ? FloatRect(toLayoutInline(this)->linesBoundingBox())
726 : FloatRect(toLayoutBox(this)->frameRect()); 734 : FloatRect(toLayoutBox(this)->frameRect());
727 FloatRect flippedStickyBoxRect = stickyBoxRect; 735 FloatRect flippedStickyBoxRect = stickyBoxRect;
728 containingBlock->flipForWritingMode(flippedStickyBoxRect); 736 containingBlock->flipForWritingMode(flippedStickyBoxRect);
729 FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContain ersOffset; 737 FloatPoint stickyLocation = flippedStickyBoxRect.location() + skippedContain ersOffset;
730 738
731 // TODO(flackr): Unfortunate to call localToAncestorQuad again, but we can't just offset from the previously computed rect if there are transforms. 739 // The scrollContainerRelativePaddingBoxRect's position is the padding box s o we need to remove the border when finding
732 // Map to the scroll ancestor. 740 // the position of the sticky box within the scroll ancestor if the containe r is not our scroll ancestor.
733 FloatRect scrollContainerRelativeContainerFrame = containingBlock->localToAn cestorQuad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), scrollAn cestor).boundingBox(); 741 if (containingBlock != scrollAncestor) {
734 // The sticky position constraint rects should be independent of the current scroll position, so after 742 FloatSize containerBorderOffset(containingBlock->borderLeft(), containin gBlock->borderTop());
735 // mapping we add in the scroll position to get the container's position wit hin the ancestor scroller's 743 stickyLocation -= containerBorderOffset;
736 // unscrolled layout overflow. 744 }
737 if (containingBlock != scrollAncestor) 745 constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContaine rRelativePaddingBoxRect.location() + toFloatSize(stickyLocation), flippedStickyB oxRect.size()));
738 scrollContainerRelativeContainerFrame.move(scrollOffset);
739
740 constraints.setScrollContainerRelativeStickyBoxRect(FloatRect(scrollContaine rRelativeContainerFrame.location() + toFloatSize(stickyLocation), flippedStickyB oxRect.size()));
741 746
742 // We skip the right or top sticky offset if there is not enough space to ho nor both the left/right or top/bottom offsets. 747 // We skip the right or top sticky offset if there is not enough space to ho nor both the left/right or top/bottom offsets.
743 LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())) + 748 LayoutUnit horizontalOffsets = minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())) +
744 minimumValueForLength(style()->left(), LayoutUnit(constrainingSize.width ())); 749 minimumValueForLength(style()->left(), LayoutUnit(constrainingSize.width ()));
745 bool skipRight = false; 750 bool skipRight = false;
746 bool skipLeft = false; 751 bool skipLeft = false;
747 if (!style()->left().isAuto() && !style()->right().isAuto()) { 752 if (!style()->left().isAuto() && !style()->right().isAuto()) {
748 if (horizontalOffsets > containerContentRect.width() 753 if (horizontalOffsets > scrollContainerRelativeContainingBlockRect.width ()
749 || horizontalOffsets + containerContentRect.width() > constrainingSi ze.width()) { 754 || horizontalOffsets + scrollContainerRelativeContainingBlockRect.wi dth() > constrainingSize.width()) {
750 skipRight = style()->isLeftToRightDirection(); 755 skipRight = style()->isLeftToRightDirection();
751 skipLeft = !skipRight; 756 skipLeft = !skipRight;
752 } 757 }
753 } 758 }
754 759
755 if (!style()->left().isAuto() && !skipLeft) { 760 if (!style()->left().isAuto() && !skipLeft) {
756 constraints.setLeftOffset(minimumValueForLength(style()->left(), LayoutU nit(constrainingSize.width()))); 761 constraints.setLeftOffset(minimumValueForLength(style()->left(), LayoutU nit(constrainingSize.width())));
757 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Left); 762 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Left);
758 } 763 }
759 764
760 if (!style()->right().isAuto() && !skipRight) { 765 if (!style()->right().isAuto() && !skipRight) {
761 constraints.setRightOffset(minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width()))); 766 constraints.setRightOffset(minimumValueForLength(style()->right(), Layou tUnit(constrainingSize.width())));
762 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Right); 767 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Right);
763 } 768 }
764 769
765 bool skipBottom = false; 770 bool skipBottom = false;
766 // TODO(flackr): Exclude top or bottom edge offset depending on the writing mode when related 771 // TODO(flackr): Exclude top or bottom edge offset depending on the writing mode when related
767 // sections are fixed in spec: http://lists.w3.org/Archives/Public/www-style /2014May/0286.html 772 // sections are fixed in spec: http://lists.w3.org/Archives/Public/www-style /2014May/0286.html
768 LayoutUnit verticalOffsets = minimumValueForLength(style()->top(), LayoutUni t(constrainingSize.height())) + 773 LayoutUnit verticalOffsets = minimumValueForLength(style()->top(), LayoutUni t(constrainingSize.height())) +
769 minimumValueForLength(style()->bottom(), LayoutUnit(constrainingSize.hei ght())); 774 minimumValueForLength(style()->bottom(), LayoutUnit(constrainingSize.hei ght()));
770 if (!style()->top().isAuto() && !style()->bottom().isAuto()) { 775 if (!style()->top().isAuto() && !style()->bottom().isAuto()) {
771 if (verticalOffsets > containerContentRect.height() 776 if (verticalOffsets > scrollContainerRelativeContainingBlockRect.height( )
772 || verticalOffsets + containerContentRect.height() > constrainingSiz e.height()) { 777 || verticalOffsets + scrollContainerRelativeContainingBlockRect.heig ht() > constrainingSize.height()) {
773 skipBottom = true; 778 skipBottom = true;
774 } 779 }
775 } 780 }
776 781
777 if (!style()->top().isAuto()) { 782 if (!style()->top().isAuto()) {
778 constraints.setTopOffset(minimumValueForLength(style()->top(), LayoutUni t(constrainingSize.height()))); 783 constraints.setTopOffset(minimumValueForLength(style()->top(), LayoutUni t(constrainingSize.height())));
779 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Top); 784 constraints.addAnchorEdge(StickyPositionScrollingConstraints::AnchorEdge Top);
780 } 785 }
781 786
782 if (!style()->bottom().isAuto() && !skipBottom) { 787 if (!style()->bottom().isAuto() && !skipBottom) {
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
1183 if (rootElementStyle->hasBackground()) 1188 if (rootElementStyle->hasBackground())
1184 return false; 1189 return false;
1185 1190
1186 if (node() != document().firstBodyElement()) 1191 if (node() != document().firstBodyElement())
1187 return false; 1192 return false;
1188 1193
1189 return true; 1194 return true;
1190 } 1195 }
1191 1196
1192 } // namespace blink 1197 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/layout/LayoutBoxModelObjectTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698