Skip to content

Commit

Permalink
Refactor TransformState preserve-3d checks into a shared location.
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=248279
<rdar://problem/102632513>

Reviewed by Simon Fraser.

We're currently checking preserve-3d in lots of places in order to do
point-mapping, this moves most of them into shared helpers in RenderObject.

* Source/WebCore/rendering/RenderBox.cpp:
(WebCore::RenderBox::mapLocalToContainer const):
(WebCore::RenderBox::pushMappingToContainer const):
* Source/WebCore/rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::mapAbsoluteToLocalPoint const):
* Source/WebCore/rendering/RenderInline.cpp:
(WebCore::RenderInline::mapLocalToContainer const):
(WebCore::RenderInline::pushMappingToContainer const):
* Source/WebCore/rendering/RenderLayerModelObject.cpp:
(WebCore::RenderLayerModelObject::mapLocalToSVGContainer const):
* Source/WebCore/rendering/RenderMultiColumnFlow.cpp:
(WebCore::RenderMultiColumnFlow::mapAbsoluteToLocalPoint const):
* Source/WebCore/rendering/RenderObject.cpp:
(WebCore::RenderObject::pushOntoTransformState const):
(WebCore::RenderObject::pushOntoGeometryMap const):
(WebCore::RenderObject::offsetFromAncestorContainer const):
* Source/WebCore/rendering/RenderObject.h:
* Source/WebCore/rendering/svg/RenderSVGModelObject.cpp:
(WebCore::RenderSVGModelObject::pushMappingToContainer const):
(WebCore::RenderSVGModelObject::mapAbsoluteToLocalPoint const):

Canonical link: https://commits.webkit.org/257093@main
  • Loading branch information
mattwoodrow committed Nov 29, 2022
1 parent 1f4c8ac commit d081a7f
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 112 deletions.
40 changes: 3 additions & 37 deletions Source/WebCore/rendering/RenderBox.cpp
Expand Up @@ -2267,22 +2267,10 @@ void RenderBox::mapLocalToContainer(const RenderLayerModelObject* ancestorContai
// order to avoid piping this flag down the method chain.
if (mode.contains(IgnoreStickyOffsets) && isStickilyPositioned())
containerOffset -= stickyPositionOffset();

bool preserve3D = mode.contains(UseTransforms) && (container->style().preserves3D() || style().preserves3D());
if (mode.contains(UseTransforms) && shouldUseTransformFromContainer(container)) {
TransformationMatrix t;
getTransformFromContainer(container, 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 ancestorContainer and o, because transforms create containers, so it should be safe
// to just subtract the delta between the ancestorContainer and o.
LayoutSize containerOffset = ancestorContainer->offsetFromAncestorContainer(*container);
transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
pushOntoTransformState(transformState, mode, ancestorContainer, container, containerOffset, containerSkipped);
if (containerSkipped)
return;
}

mode.remove(ApplyContainerFlip);

Expand All @@ -2298,29 +2286,7 @@ const RenderObject* RenderBox::pushMappingToContainer(const RenderLayerModelObje
if (!container)
return nullptr;

bool isFixedPos = isFixedPositioned();
LayoutSize adjustmentForSkippedAncestor;
if (ancestorSkipped) {
// There can't be a transform between repaintContainer and container, because transforms create containers, so it should be safe
// to just subtract the delta between the ancestor and container.
adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(*container);
}

bool offsetDependsOnPoint = false;
LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint);

bool preserve3D = container->style().preserves3D() || style().preserves3D();
if (shouldUseTransformFromContainer(container) && (geometryMap.mapCoordinatesFlags() & UseTransforms)) {
TransformationMatrix t;
getTransformFromContainer(container, containerOffset, t);
t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height());

geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform());
} else {
containerOffset += adjustmentForSkippedAncestor;
geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform());
}

pushOntoGeometryMap(geometryMap, ancestorToStopAt, container, ancestorSkipped);
return ancestorSkipped ? ancestorToStopAt : container;
}

Expand Down
8 changes: 1 addition & 7 deletions Source/WebCore/rendering/RenderBoxModelObject.cpp
Expand Up @@ -901,13 +901,7 @@ void RenderBoxModelObject::mapAbsoluteToLocalPoint(OptionSet<MapCoordinatesMode>

LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint());

bool preserve3D = mode.contains(UseTransforms) && (container->style().preserves3D() || style().preserves3D());
if (mode.contains(UseTransforms) && shouldUseTransformFromContainer(container)) {
TransformationMatrix t;
getTransformFromContainer(container, containerOffset, t);
transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
} else
transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
pushOntoTransformState(transformState, mode, nullptr, container, containerOffset, false);
}

bool RenderBoxModelObject::hasRunningAcceleratedAnimations() const
Expand Down
37 changes: 3 additions & 34 deletions Source/WebCore/rendering/RenderInline.cpp
Expand Up @@ -744,21 +744,9 @@ void RenderInline::mapLocalToContainer(const RenderLayerModelObject* ancestorCon

LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(transformState.mappedPoint()));

bool preserve3D = mode.contains(UseTransforms) && (container->style().preserves3D() || style().preserves3D());
if (mode.contains(UseTransforms) && shouldUseTransformFromContainer(container)) {
TransformationMatrix t;
getTransformFromContainer(container, 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 ancestorContainer and o, because transforms create containers, so it should be safe
// to just subtract the delta between the ancestorContainer and o.
LayoutSize containerOffset = ancestorContainer->offsetFromAncestorContainer(*container);
transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
pushOntoTransformState(transformState, mode, ancestorContainer, container, containerOffset, containerSkipped);
if (containerSkipped)
return;
}

container->mapLocalToContainer(ancestorContainer, transformState, mode, wasFixed);
}
Expand All @@ -772,27 +760,8 @@ const RenderObject* RenderInline::pushMappingToContainer(const RenderLayerModelO
if (!container)
return nullptr;

LayoutSize adjustmentForSkippedAncestor;
if (ancestorSkipped) {
// There can't be a transform between ancestorToStopAt and container, because transforms create containers, so it should be safe
// to just subtract the delta between the ancestor and container.
adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(*container);
}
pushOntoGeometryMap(geometryMap, ancestorToStopAt, container, ancestorSkipped);

bool offsetDependsOnPoint = false;
LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint);

bool preserve3D = container->style().preserves3D() || style().preserves3D();
if (shouldUseTransformFromContainer(container)) {
TransformationMatrix t;
getTransformFromContainer(container, containerOffset, t);
t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height()); // FIXME: right?
geometryMap.push(this, t, preserve3D, offsetDependsOnPoint);
} else {
containerOffset += adjustmentForSkippedAncestor;
geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint);
}

return ancestorSkipped ? ancestorToStopAt : container;
}

Expand Down
8 changes: 1 addition & 7 deletions Source/WebCore/rendering/RenderLayerModelObject.cpp
Expand Up @@ -363,13 +363,7 @@ void RenderLayerModelObject::mapLocalToSVGContainer(const RenderLayerModelObject

auto containerOffset = offsetFromContainer(*container, LayoutPoint(transformState.mappedPoint()));

bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D());
if (mode & UseTransforms && shouldUseTransformFromContainer(container)) {
TransformationMatrix t;
getTransformFromContainer(container, containerOffset, t);
transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
} else
transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
pushOntoTransformState(transformState, mode, nullptr, container, containerOffset, false);

mode.remove(ApplyContainerFlip);

Expand Down
8 changes: 1 addition & 7 deletions Source/WebCore/rendering/RenderMultiColumnFlow.cpp
Expand Up @@ -309,13 +309,7 @@ void RenderMultiColumnFlow::mapAbsoluteToLocalPoint(OptionSet<MapCoordinatesMode
// Once we have a good guess as to which fragment we hit tested through (and yes, this was just a heuristic, but it's
// the best we could do), then we can map from the fragment into the flow thread.
LayoutSize translationOffset = physicalTranslationFromFragmentToFlow(candidateColumnSet, candidatePoint) + candidateContainerOffset;
bool preserve3D = mode.contains(UseTransforms) && (parent()->style().preserves3D() || style().preserves3D());
if (mode.contains(UseTransforms) && shouldUseTransformFromContainer(parent())) {
TransformationMatrix t;
getTransformFromContainer(parent(), translationOffset, t);
transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
} else
transformState.move(translationOffset.width(), translationOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
pushOntoTransformState(transformState, mode, nullptr, parent(), translationOffset, false);
}

LayoutSize RenderMultiColumnFlow::physicalTranslationFromFragmentToFlow(const RenderMultiColumnSet* columnSet, const LayoutPoint& physicalPoint) const
Expand Down
46 changes: 45 additions & 1 deletion Source/WebCore/rendering/RenderObject.cpp
Expand Up @@ -1492,6 +1492,50 @@ void RenderObject::getTransformFromContainer(const RenderObject* containerObject
#endif
}

void RenderObject::pushOntoTransformState(TransformState& transformState, OptionSet<MapCoordinatesMode> mode, const RenderLayerModelObject* repaintContainer, const RenderElement* container, const LayoutSize& offsetInContainer, bool containerSkipped) const
{
bool preserve3D = mode.contains(UseTransforms) && (container->style().preserves3D() || style().preserves3D());
if (mode.contains(UseTransforms) && shouldUseTransformFromContainer(container)) {
TransformationMatrix matrix;
getTransformFromContainer(container, offsetInContainer, matrix);
transformState.applyTransform(matrix, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
} else
transformState.move(offsetInContainer.width(), offsetInContainer.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);

if (containerSkipped) {
// There can't be a transform between repaintContainer and container, because transforms create containers, so it should be safe
// to just subtract the delta between the repaintContainer and container.
LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*container);
transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
}
}

void RenderObject::pushOntoGeometryMap(RenderGeometryMap& geometryMap, const RenderLayerModelObject* repaintContainer, RenderElement* container, bool containerSkipped) const
{
bool isFixedPos = isFixedPositioned();
LayoutSize adjustmentForSkippedAncestor;
if (containerSkipped) {
// There can't be a transform between repaintContainer and container, because transforms create containers, so it should be safe
// to just subtract the delta between the ancestor and container.
adjustmentForSkippedAncestor = -repaintContainer->offsetFromAncestorContainer(*container);
}

bool offsetDependsOnPoint = false;
LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint);

bool preserve3D = container->style().preserves3D() || style().preserves3D();
if (shouldUseTransformFromContainer(container) && (geometryMap.mapCoordinatesFlags() & UseTransforms)) {
TransformationMatrix t;
getTransformFromContainer(container, containerOffset, t);
t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height());

geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform());
} else {
containerOffset += adjustmentForSkippedAncestor;
geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform());
}
}

FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, const RenderLayerModelObject* container, OptionSet<MapCoordinatesMode> mode, bool* wasFixed) const
{
// Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(),
Expand Down Expand Up @@ -1526,7 +1570,7 @@ LayoutSize RenderObject::offsetFromContainer(RenderElement& container, const Lay
return offset;
}

LayoutSize RenderObject::offsetFromAncestorContainer(RenderElement& container) const
LayoutSize RenderObject::offsetFromAncestorContainer(const RenderElement& container) const
{
LayoutSize offset;
LayoutPoint referencePoint;
Expand Down
5 changes: 4 additions & 1 deletion Source/WebCore/rendering/RenderObject.h
Expand Up @@ -605,7 +605,7 @@ class RenderObject : public CachedImageClient {
// different offsets apply at different points, so return the offset that applies to the given point.
virtual LayoutSize offsetFromContainer(RenderElement&, const LayoutPoint&, bool* offsetDependsOnPoint = nullptr) const;
// Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms.
LayoutSize offsetFromAncestorContainer(RenderElement&) const;
LayoutSize offsetFromAncestorContainer(const RenderElement&) const;

#if PLATFORM(IOS_FAMILY)
virtual void collectSelectionGeometries(Vector<SelectionGeometry>&, unsigned startOffset = 0, unsigned endOffset = std::numeric_limits<unsigned>::max());
Expand Down Expand Up @@ -781,6 +781,9 @@ class RenderObject : public CachedImageClient {
bool shouldUseTransformFromContainer(const RenderObject* container) const;
void getTransformFromContainer(const RenderObject* container, const LayoutSize& offsetInContainer, TransformationMatrix&) const;

void pushOntoTransformState(TransformState&, OptionSet<MapCoordinatesMode>, const RenderLayerModelObject* repaintContainer, const RenderElement* container, const LayoutSize& offsetInContainer, bool containerSkipped) const;
void pushOntoGeometryMap(RenderGeometryMap&, const RenderLayerModelObject* repaintContainer, RenderElement* container, bool containerSkipped) const;

virtual void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& /* additionalOffset */, const RenderLayerModelObject* /* paintContainer */ = nullptr) const { };

LayoutRect absoluteOutlineBounds() const { return outlineBoundsForRepaint(nullptr); }
Expand Down
20 changes: 2 additions & 18 deletions Source/WebCore/rendering/svg/RenderSVGModelObject.cpp
Expand Up @@ -100,17 +100,7 @@ const RenderObject* RenderSVGModelObject::pushMappingToContainer(const RenderLay

ASSERT_UNUSED(ancestorSkipped, !ancestorSkipped);

bool offsetDependsOnPoint = false;
LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint);

bool preserve3D = container->style().preserves3D() || style().preserves3D();
if (shouldUseTransformFromContainer(container) && (geometryMap.mapCoordinatesFlags() & UseTransforms)) {
TransformationMatrix t;
getTransformFromContainer(container, containerOffset, t);
geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, false /* isFixedPos */, hasTransform());
} else
geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, false /* isFixedPos */, hasTransform());

pushOntoGeometryMap(geometryMap, ancestorToStopAt, container, ancestorSkipped);
return container;
}

Expand Down Expand Up @@ -178,13 +168,7 @@ void RenderSVGModelObject::mapAbsoluteToLocalPoint(OptionSet<MapCoordinatesMode>

LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint());

bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D());
if (mode & UseTransforms && shouldUseTransformFromContainer(container)) {
TransformationMatrix t;
getTransformFromContainer(container, containerOffset, t);
transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
} else
transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
pushOntoTransformState(transformState, mode, nullptr, container, containerOffset, false);
}

void RenderSVGModelObject::mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState& transformState, OptionSet<MapCoordinatesMode> mode, bool* wasFixed) const
Expand Down

0 comments on commit d081a7f

Please sign in to comment.