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