Index: Source/core/layout/LayoutObject.cpp |
diff --git a/Source/core/layout/LayoutObject.cpp b/Source/core/layout/LayoutObject.cpp |
index abd4d61201124cc82585b605cd753adc344d9950..7054ed37332a49fc9c6fc1a9a480dc596a89c534 100644 |
--- a/Source/core/layout/LayoutObject.cpp |
+++ b/Source/core/layout/LayoutObject.cpp |
@@ -2040,22 +2040,63 @@ void LayoutObject::mapLocalToContainer(const LayoutBoxModelObject* paintInvalida |
if (paintInvalidationContainer == this) |
return; |
- LayoutObject* o = parent(); |
+ if (paintInvalidationState && paintInvalidationState->canMapToContainer(paintInvalidationContainer)) { |
+ LayoutSize offset = paintInvalidationState->paintOffset(); |
+ if (isBox()) |
+ offset += toLayoutBox(this)->locationOffset(); |
+ if (!isText() && style()->hasInFlowPosition() && hasLayer()) |
+ offset += toLayoutBoxModelObject(this)->layer()->offsetForInFlowPosition(); |
+ transformState.move(offset); |
+ return; |
+ } |
+ |
+ bool containerSkipped; |
+ LayoutObject* o = container(paintInvalidationContainer, &containerSkipped); |
if (!o) |
return; |
- // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called. |
- LayoutPoint centerPoint = roundedLayoutPoint(transformState.mappedPoint()); |
- if (mode & ApplyContainerFlip && o->isBox()) { |
- if (o->style()->isFlippedBlocksWritingMode()) |
- transformState.move(toLayoutBox(o)->flipForWritingMode(roundedLayoutPoint(transformState.mappedPoint())) - centerPoint); |
+ if (isBox()) { |
+ bool isFixedPos = style()->position() == FixedPosition; |
+ bool hasTransform = hasLayer() && toLayoutBox(this)->layer()->transform(); |
+ // If this box has a transform, it acts as a fixed position container for fixed descendants, |
+ // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position. |
+ if (hasTransform && !isFixedPos) |
+ mode &= ~IsFixed; |
+ else if (isFixedPos) |
+ mode |= IsFixed; |
+ |
+ if (wasFixed) |
+ *wasFixed = mode & IsFixed; |
+ |
+ mode &= ~ApplyContainerFlip; |
+ paintInvalidationState = nullptr; |
+ } else if (mode & ApplyContainerFlip && o->isBox()) { |
+ if (o->style()->isFlippedBlocksWritingMode()) { |
+ IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint()); |
+ transformState.move(toLayoutBox(o)->flipForWritingMode(LayoutPoint(centerPoint)) - centerPoint); |
+ } |
mode &= ~ApplyContainerFlip; |
} |
- transformState.move(o->columnOffset(roundedLayoutPoint(transformState.mappedPoint()))); |
+ LayoutSize containerOffset = offsetFromContainer(o); |
+ containerOffset += o->columnOffset(roundedLayoutPoint(transformState.mappedPoint()) + containerOffset); |
- if (o->hasOverflowClip()) |
- transformState.move(-toLayoutBox(o)->scrolledContentOffset()); |
+ bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || (!isText() && style()->preserves3D())); |
+ if (mode & UseTransforms && shouldUseTransformFromContainer(o)) { |
+ TransformationMatrix t; |
+ getTransformFromContainer(o, containerOffset, t); |
+ transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); |
+ } else { |
+ transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); |
+ } |
+ |
+ if (containerSkipped) { |
+ // There can't be a transform between paintInvalidationContainer and o, because transforms create containers, so it should be safe |
+ // to just subtract the delta between the paintInvalidationContainer and o. |
+ LayoutSize containerOffset = paintInvalidationContainer->offsetFromAncestorContainer(o); |
+ transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); |
+ return; |
+ } |
o->mapLocalToContainer(paintInvalidationContainer, transformState, mode, wasFixed, paintInvalidationState); |
} |
@@ -2107,8 +2148,8 @@ void LayoutObject::getTransformFromContainer(const LayoutObject* containerObject |
FloatQuad LayoutObject::localToContainerQuad(const FloatQuad& localQuad, const LayoutBoxModelObject* paintInvalidationContainer, MapCoordinatesFlags mode, bool* wasFixed) const |
{ |
- // Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(), |
- // it will use that point as the reference point to decide which column's transform to apply in multiple-column blocks. |
+ // Track the point at the center of the quad's bounding box. mapLocalToContainer() will use |
+ // that point as the reference point to decide which column we're in for multiple-column blocks. |
TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), localQuad); |
mapLocalToContainer(paintInvalidationContainer, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed); |
transformState.flatten(); |
@@ -2143,19 +2184,12 @@ FloatPoint LayoutObject::localToInvalidationBackingPoint(const LayoutPoint& loca |
return containerPoint; |
} |
-LayoutSize LayoutObject::offsetFromContainer(const LayoutObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const |
+LayoutSize LayoutObject::offsetFromContainer(const LayoutObject* o) const |
{ |
ASSERT(o == container()); |
- |
- LayoutSize offset = o->columnOffset(point); |
- |
if (o->hasOverflowClip()) |
- offset -= toLayoutBox(o)->scrolledContentOffset(); |
- |
- if (offsetDependsOnPoint) |
- *offsetDependsOnPoint = o->isLayoutFlowThread(); |
- |
- return offset; |
+ return LayoutSize(-toLayoutBox(o)->scrolledContentOffset()); |
+ return LayoutSize(); |
} |
LayoutSize LayoutObject::offsetFromAncestorContainer(const LayoutObject* container) const |
@@ -2172,7 +2206,8 @@ LayoutSize LayoutObject::offsetFromAncestorContainer(const LayoutObject* contain |
if (!nextContainer) |
break; |
ASSERT(!currContainer->hasTransformRelatedProperty()); |
- LayoutSize currentOffset = currContainer->offsetFromContainer(nextContainer, referencePoint); |
+ LayoutSize currentOffset = currContainer->offsetFromContainer(nextContainer); |
+ currentOffset += container->columnOffset(referencePoint + currentOffset); |
offset += currentOffset; |
referencePoint.move(currentOffset); |
currContainer = nextContainer; |