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 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 | 562 |
563 else if (!style()->bottom().isAuto() | 563 else if (!style()->bottom().isAuto() |
564 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight() | 564 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight() |
565 || !style()->bottom().hasPercent() | 565 || !style()->bottom().hasPercent() |
566 || containingBlock->stretchesToViewport())) | 566 || containingBlock->stretchesToViewport())) |
567 offset.expand(0, -valueForLength(style()->bottom(), containingBlock->ava ilableHeight())); | 567 offset.expand(0, -valueForLength(style()->bottom(), containingBlock->ava ilableHeight())); |
568 | 568 |
569 return offset; | 569 return offset; |
570 } | 570 } |
571 | 571 |
572 void LayoutBoxModelObject::computeStickyPositionConstraints(StickyPositionViewpo rtConstraints& constraints, const LayoutRect& constrainingRect) const | |
573 { | |
574 LayoutBlock* containingBlock = this->containingBlock(); | |
575 | |
576 LayoutRect containerContentRect = containingBlock->contentBoxRect(); | |
577 LayoutUnit maxWidth = containingBlock->availableLogicalWidth(); | |
578 | |
579 // Sticky positioned element ignore any override logical width on the contai ning block (as they don't call | |
580 // containingBlockLogicalWidthForContent). It's unclear whether this is tota lly fine. | |
581 // Compute the container-relative area within which the sticky element is al lowed to move. | |
582 containerContentRect.contractEdges( | |
583 minimumValueForLength(style()->marginTop(), maxWidth), | |
584 minimumValueForLength(style()->marginRight(), maxWidth), | |
585 minimumValueForLength(style()->marginBottom(), maxWidth), | |
586 minimumValueForLength(style()->marginLeft(), maxWidth)); | |
587 | |
588 // Map to the view to avoid including page scale factor. | |
589 constraints.setAbsoluteContainingBlockRect(LayoutRect(containingBlock->local ToContainerQuad(FloatRect(containerContentRect), view()).boundingBox())); | |
590 | |
591 LayoutRect stickyBoxRect = frameRectForStickyPositioning(); | |
592 LayoutRect flippedStickyBoxRect = stickyBoxRect; | |
593 containingBlock->flipForWritingMode(flippedStickyBoxRect); | |
594 LayoutPoint stickyLocation = flippedStickyBoxRect.location(); | |
595 | |
596 // FIXME: sucks to call localToAbsolute again, but we can't just offset from the previously computed rect if there are transforms. | |
597 // Map to the view to avoid including page scale factor. | |
598 LayoutRect absContainerFrame = LayoutRect(containingBlock->localToContainerQ uad(FloatRect(FloatPoint(), FloatSize(containingBlock->size())), view()).boundin gBox()); | |
599 | |
600 if (containingBlock->hasOverflowClip()) { | |
601 LayoutSize scrollOffset(containingBlock->layer()->scrollableArea()->adju stedScrollOffset()); | |
602 stickyLocation -= scrollOffset; | |
603 } | |
604 | |
605 // We can't call localToAbsolute on |this| because that will recur. FIXME: F or now, assume that |this| is not transformed. | |
606 LayoutRect absoluteStickyBoxRect(LayoutPoint(absContainerFrame.location()) + stickyLocation, flippedStickyBoxRect.size()); | |
chrishtr
2015/09/17 01:18:56
This is bad for performance. Do we really need to
flackr
2015/10/07 20:38:11
We need to save this rect because sticky objects o
| |
607 constraints.setAbsoluteStickyBoxRect(absoluteStickyBoxRect); | |
608 | |
609 LayoutUnit horizontalOffsets = constraints.rightOffset() + constraints.leftO ffset(); | |
610 bool skipRight = false; | |
611 bool skipLeft = false; | |
612 if (!style()->left().isAuto() && !style()->right().isAuto()) { | |
613 if (horizontalOffsets > containerContentRect.width() | |
614 || horizontalOffsets + containerContentRect.width() > constrainingRe ct.width()) { | |
615 skipRight = style()->isLeftToRightDirection(); | |
616 skipLeft = !skipRight; | |
617 } | |
618 } | |
619 | |
620 if (!style()->left().isAuto() && !skipLeft) { | |
621 constraints.setLeftOffset(minimumValueForLength(style()->left(), constra iningRect.width())); | |
622 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft); | |
623 } | |
624 | |
625 if (!style()->right().isAuto() && !skipRight) { | |
626 constraints.setRightOffset(minimumValueForLength(style()->right(), const rainingRect.width())); | |
627 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight); | |
628 } | |
629 | |
630 bool skipBottom = false; | |
631 // FIXME(ostap): Exclude top or bottom edge offset depending on the writing mode when related | |
632 // sections are fixed in spec: http://lists.w3.org/Archives/Public/www-style /2014May/0286.html | |
633 LayoutUnit verticalOffsets = constraints.topOffset() + constraints.bottomOff set(); | |
634 if (!style()->top().isAuto() && !style()->bottom().isAuto()) { | |
635 if (verticalOffsets > containerContentRect.height() | |
636 || verticalOffsets + containerContentRect.height() > constrainingRec t.height()) { | |
637 skipBottom = true; | |
638 } | |
639 } | |
640 | |
641 if (!style()->top().isAuto()) { | |
642 constraints.setTopOffset(minimumValueForLength(style()->top(), constrain ingRect.height())); | |
643 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop); | |
644 } | |
645 | |
646 if (!style()->bottom().isAuto() && !skipBottom) { | |
647 constraints.setBottomOffset(minimumValueForLength(style()->bottom(), con strainingRect.height())); | |
648 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom); | |
649 } | |
650 } | |
651 | |
652 static inline LayoutBox* findScrollAncestor(const Node* startNode) | |
653 { | |
654 ASSERT(startNode->layoutObject()); | |
655 LayoutBox* curBox = startNode->layoutObject()->containingBlock(); | |
656 | |
657 // Scrolling propagates along the containing block chain. | |
658 while (curBox && !curBox->isLayoutView()) { | |
659 if (curBox->hasOverflowClip()) | |
660 return curBox; | |
661 curBox = curBox->containingBlock(); | |
662 } | |
663 | |
664 return nullptr; | |
665 } | |
666 | |
667 LayoutRect LayoutBoxModelObject::computeStickyConstrainingRect() const | |
668 { | |
669 LayoutRect constrainingRect; | |
670 | |
671 ASSERT(hasLayer()); | |
672 LayoutBox* enclosingClippingBox = findScrollAncestor(node()); | |
673 if (enclosingClippingBox) { | |
674 LayoutRect clipRect = enclosingClippingBox->overflowClipRect(LayoutPoint ()); | |
675 clipRect.move(enclosingClippingBox->paddingLeft(), enclosingClippingBox- >paddingTop()); | |
676 clipRect.contract(LayoutSize(enclosingClippingBox->paddingLeft() + enclo singClippingBox->paddingRight(), | |
677 enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBo ttom())); | |
678 constrainingRect = LayoutRect(enclosingClippingBox->localToContainerQuad (FloatRect(clipRect), view()).boundingBox()); | |
chrishtr
2015/09/17 01:18:56
Does clippedOverflowRectForPaintInvalidation do th
flackr
2015/10/07 20:38:11
Unless I'm not understanding / using this correctl
| |
679 } else { | |
680 LayoutRect viewportRect(view()->frameView()->visibleContentRect()); | |
681 constrainingRect = viewportRect; | |
682 } | |
683 | |
684 return constrainingRect; | |
685 } | |
686 | |
687 LayoutSize LayoutBoxModelObject::stickyPositionOffset() const | |
688 { | |
689 LayoutRect constrainingRect = computeStickyConstrainingRect(); | |
690 StickyPositionViewportConstraints constraints; | |
691 computeStickyPositionConstraints(constraints, constrainingRect); | |
692 | |
693 // The sticky offset is physical, so we can just return the delta computed i n absolute coords (though it may be wrong with transforms). | |
694 return LayoutSize(constraints.computeStickyOffset(constrainingRect)); | |
695 } | |
696 | |
572 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeToOffsetParent(const L ayoutPoint& startPoint) const | 697 LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeToOffsetParent(const L ayoutPoint& startPoint) const |
573 { | 698 { |
574 // If the element is the HTML body element or doesn't have a parent | 699 // If the element is the HTML body element or doesn't have a parent |
575 // return 0 and stop this algorithm. | 700 // return 0 and stop this algorithm. |
576 if (isBody() || !parent()) | 701 if (isBody() || !parent()) |
577 return LayoutPoint(); | 702 return LayoutPoint(); |
578 | 703 |
579 LayoutPoint referencePoint = startPoint; | 704 LayoutPoint referencePoint = startPoint; |
580 referencePoint.move(parent()->columnOffset(referencePoint)); | 705 referencePoint.move(parent()->columnOffset(referencePoint)); |
581 | 706 |
582 // If the offsetParent of the element is null, or is the HTML body element, | 707 // If the offsetParent of the element is null, or is the HTML body element, |
583 // return the distance between the canvas origin and the left border edge | 708 // return the distance between the canvas origin and the left border edge |
584 // of the element and stop this algorithm. | 709 // of the element and stop this algorithm. |
585 Element* element = offsetParent(); | 710 Element* element = offsetParent(); |
586 if (!element) | 711 if (!element) |
587 return referencePoint; | 712 return referencePoint; |
588 | 713 |
589 if (const LayoutBoxModelObject* offsetParent = element->layoutBoxModelObject ()) { | 714 if (const LayoutBoxModelObject* offsetParent = element->layoutBoxModelObject ()) { |
590 if (offsetParent->isBox() && !offsetParent->isBody()) | 715 if (offsetParent->isBox() && !offsetParent->isBody()) |
591 referencePoint.move(-toLayoutBox(offsetParent)->borderLeft(), -toLay outBox(offsetParent)->borderTop()); | 716 referencePoint.move(-toLayoutBox(offsetParent)->borderLeft(), -toLay outBox(offsetParent)->borderTop()); |
592 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) { | 717 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) { |
593 if (isInFlowPositioned()) | 718 if (isInFlowPositioned()) |
594 referencePoint.move(relativePositionOffset()); | 719 referencePoint.move(offsetForInFlowPosition()); |
595 | 720 |
596 LayoutObject* current; | 721 LayoutObject* current; |
597 for (current = parent(); current != offsetParent && current->parent( ); current = current->parent()) { | 722 for (current = parent(); current != offsetParent && current->parent( ); current = current->parent()) { |
598 // FIXME: What are we supposed to do inside SVG content? | 723 // FIXME: What are we supposed to do inside SVG content? |
599 if (!isOutOfFlowPositioned()) { | 724 if (!isOutOfFlowPositioned()) { |
600 if (current->isBox() && !current->isTableRow()) | 725 if (current->isBox() && !current->isTableRow()) |
601 referencePoint.moveBy(toLayoutBox(current)->topLeftLocat ion()); | 726 referencePoint.moveBy(toLayoutBox(current)->topLeftLocat ion()); |
602 referencePoint.move(current->parent()->columnOffset(referenc ePoint)); | 727 referencePoint.move(current->parent()->columnOffset(referenc ePoint)); |
603 } | 728 } |
604 } | 729 } |
605 | 730 |
606 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent ->isPositioned()) | 731 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent ->isPositioned()) |
607 referencePoint.moveBy(toLayoutBox(offsetParent)->topLeftLocation ()); | 732 referencePoint.moveBy(toLayoutBox(offsetParent)->topLeftLocation ()); |
608 } | 733 } |
609 } | 734 } |
610 | 735 |
611 return referencePoint; | 736 return referencePoint; |
612 } | 737 } |
613 | 738 |
614 LayoutSize LayoutBoxModelObject::offsetForInFlowPosition() const | 739 LayoutSize LayoutBoxModelObject::offsetForInFlowPosition() const |
615 { | 740 { |
616 return isRelPositioned() ? relativePositionOffset() : LayoutSize(); | 741 if (isRelPositioned()) |
742 return relativePositionOffset(); | |
743 | |
744 if (isStickyPositioned()) | |
745 return stickyPositionOffset(); | |
746 | |
747 return LayoutSize(); | |
617 } | 748 } |
618 | 749 |
619 LayoutUnit LayoutBoxModelObject::offsetLeft() const | 750 LayoutUnit LayoutBoxModelObject::offsetLeft() const |
620 { | 751 { |
621 // Note that LayoutInline and LayoutBox override this to pass a different | 752 // Note that LayoutInline and LayoutBox override this to pass a different |
622 // startPoint to adjustedPositionRelativeToOffsetParent. | 753 // startPoint to adjustedPositionRelativeToOffsetParent. |
623 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x(); | 754 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x(); |
624 } | 755 } |
625 | 756 |
626 LayoutUnit LayoutBoxModelObject::offsetTop() const | 757 LayoutUnit LayoutBoxModelObject::offsetTop() const |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
928 const LayoutObject* LayoutBoxModelObject::pushMappingToContainer(const LayoutBox ModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const | 1059 const LayoutObject* LayoutBoxModelObject::pushMappingToContainer(const LayoutBox ModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const |
929 { | 1060 { |
930 ASSERT(ancestorToStopAt != this); | 1061 ASSERT(ancestorToStopAt != this); |
931 | 1062 |
932 bool ancestorSkipped; | 1063 bool ancestorSkipped; |
933 LayoutObject* container = this->container(ancestorToStopAt, &ancestorSkipped ); | 1064 LayoutObject* container = this->container(ancestorToStopAt, &ancestorSkipped ); |
934 if (!container) | 1065 if (!container) |
935 return nullptr; | 1066 return nullptr; |
936 | 1067 |
937 bool isInline = isLayoutInline(); | 1068 bool isInline = isLayoutInline(); |
938 bool isFixedPos = !isInline && style()->position() == FixedPosition; | 1069 bool isViewportConstrained = !isInline && (style()->hasViewportConstrainedPo sition()); |
939 bool hasTransform = !isInline && hasLayer() && layer()->transform(); | 1070 bool hasTransform = !isInline && hasLayer() && layer()->transform(); |
940 | 1071 |
941 LayoutSize adjustmentForSkippedAncestor; | 1072 LayoutSize adjustmentForSkippedAncestor; |
942 if (ancestorSkipped) { | 1073 if (ancestorSkipped) { |
943 // There can't be a transform between paintInvalidationContainer and anc estorToStopAt, because transforms create containers, so it should be safe | 1074 // There can't be a transform between paintInvalidationContainer and anc estorToStopAt, because transforms create containers, so it should be safe |
944 // to just subtract the delta between the ancestor and ancestorToStopAt. | 1075 // to just subtract the delta between the ancestor and ancestorToStopAt. |
945 adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorCont ainer(container); | 1076 adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorCont ainer(container); |
946 } | 1077 } |
947 | 1078 |
948 bool offsetDependsOnPoint = false; | 1079 bool offsetDependsOnPoint = false; |
949 LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), & offsetDependsOnPoint); | 1080 LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), & offsetDependsOnPoint); |
950 | 1081 |
951 bool preserve3D = container->style()->preserves3D() || style()->preserves3D( ); | 1082 bool preserve3D = container->style()->preserves3D() || style()->preserves3D( ); |
952 if (shouldUseTransformFromContainer(container)) { | 1083 if (shouldUseTransformFromContainer(container)) { |
953 TransformationMatrix t; | 1084 TransformationMatrix t; |
954 getTransformFromContainer(container, containerOffset, t); | 1085 getTransformFromContainer(container, containerOffset, t); |
955 t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustm entForSkippedAncestor.height().toFloat()); | 1086 t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustm entForSkippedAncestor.height().toFloat()); |
956 geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform); | 1087 geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isViewportCo nstrained, hasTransform); |
957 } else { | 1088 } else { |
958 containerOffset += adjustmentForSkippedAncestor; | 1089 containerOffset += adjustmentForSkippedAncestor; |
959 geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint , isFixedPos, hasTransform); | 1090 geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint , isViewportConstrained, hasTransform); |
960 } | 1091 } |
961 | 1092 |
962 return ancestorSkipped ? ancestorToStopAt : container; | 1093 return ancestorSkipped ? ancestorToStopAt : container; |
963 } | 1094 } |
964 | 1095 |
965 void LayoutBoxModelObject::moveChildTo(LayoutBoxModelObject* toBoxModelObject, L ayoutObject* child, LayoutObject* beforeChild, bool fullRemoveInsert) | 1096 void LayoutBoxModelObject::moveChildTo(LayoutBoxModelObject* toBoxModelObject, L ayoutObject* child, LayoutObject* beforeChild, bool fullRemoveInsert) |
966 { | 1097 { |
967 // We assume that callers have cleared their positioned objects list for chi ld moves (!fullRemoveInsert) so the | 1098 // We assume that callers have cleared their positioned objects list for chi ld moves (!fullRemoveInsert) so the |
968 // positioned layoutObject maps don't become stale. It would be too slow to do the map lookup on each call. | 1099 // positioned layoutObject maps don't become stale. It would be too slow to do the map lookup on each call. |
969 ASSERT(!fullRemoveInsert || !isLayoutBlock() || !toLayoutBlock(this)->hasPos itionedObjects()); | 1100 ASSERT(!fullRemoveInsert || !isLayoutBlock() || !toLayoutBlock(this)->hasPos itionedObjects()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1017 if (rootElementStyle->hasBackground()) | 1148 if (rootElementStyle->hasBackground()) |
1018 return false; | 1149 return false; |
1019 | 1150 |
1020 if (node() != document().firstBodyElement()) | 1151 if (node() != document().firstBodyElement()) |
1021 return false; | 1152 return false; |
1022 | 1153 |
1023 return true; | 1154 return true; |
1024 } | 1155 } |
1025 | 1156 |
1026 } // namespace blink | 1157 } // namespace blink |
OLD | NEW |