Skip to content

Commit

Permalink
[motion-path] Update "<coord-box>" implementation for offset-path
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=260944
rdar://110938788

Reviewed by Tim Nguyen.

Update coord-box to use the containing block's bounding rect if it
 exists. We also need to take into account the containing block's
border radius.

* LayoutTests/TestExpectations:
* Source/WebCore/rendering/MotionPath.cpp:
(WebCore::offsetFromContainer):
(WebCore::MotionPath::motionPathDataForRenderer):
* Source/WebCore/rendering/PathOperation.cpp:
(WebCore::BoxPathOperation::getPath const):
* Source/WebCore/rendering/PathOperation.h:

Canonical link: https://commits.webkit.org/267524@main
  • Loading branch information
nmoucht committed Aug 31, 2023
1 parent e2aa0c2 commit c377f2d
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 36 deletions.
5 changes: 1 addition & 4 deletions LayoutTests/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -5290,11 +5290,8 @@ imported/w3c/web-platform-tests/css/motion/offset-path-url-011.html [ ImageOnlyF
imported/w3c/web-platform-tests/css/motion/offset-path-ray-011.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/motion/offset-path-ray-014.html [ ImageOnlyFailure ]

# CSS motion path tests for missing <coord-box> support.
# CSS motion path tests for missing <coord-box> support with border-radius.
imported/w3c/web-platform-tests/css/motion/offset-path-coord-box-001.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/motion/offset-path-coord-box-002.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/motion/offset-path-coord-box-003.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/motion/offset-path-coord-box-004.html [ ImageOnlyFailure ]

# CSS motion path tests for missing parsing support for <coord-box> with ray.
imported/w3c/web-platform-tests/css/motion/offset-path-ray-015.html [ ImageOnlyFailure ]
Expand Down
44 changes: 31 additions & 13 deletions Source/WebCore/rendering/MotionPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@

namespace WebCore {

static FloatPoint offsetFromContainer(const RenderObject& renderer, const FloatRect& referenceRect)
static FloatPoint offsetFromContainer(const RenderObject& renderer, RenderBlock& container)
{
auto offsetFromContainingBlock = renderer.localToContainerPoint(FloatPoint(), renderer.containingBlock());
auto offset = offsetFromContainingBlock - referenceRect.location();
return { offset.width(), offset.height() };
auto offsetFromContainingBlock = renderer.offsetFromContainer(container, LayoutPoint());
return FloatPoint(offsetFromContainingBlock);
}

std::optional<MotionPathData> MotionPath::motionPathDataForRenderer(const RenderElement& renderer)
Expand All @@ -46,29 +45,33 @@ std::optional<MotionPathData> MotionPath::motionPathDataForRenderer(const Render
if (!pathOperation || !is<RenderLayerModelObject>(renderer))
return std::nullopt;

auto startingPositionForOffsetPosition = [&](const LengthPoint& offsetPosition, const FloatRect& referenceRect) -> FloatPoint {
auto startingPositionForOffsetPosition = [&](const LengthPoint& offsetPosition, const FloatRect& referenceRect, RenderBlock& container) -> FloatPoint {
// FIXME: Implement offset-position: normal.
// If offset-position is auto, use top / left corner of the box.
if (offsetPosition.x().isAuto() && offsetPosition.y().isAuto())
return offsetFromContainer(renderer, referenceRect);
return offsetFromContainer(renderer, container);
return floatPointForLengthPoint(offsetPosition, referenceRect.size());
};

if (is<BoxPathOperation>(pathOperation)) {
auto& boxPathOperation = downcast<BoxPathOperation>(*pathOperation);
data.containingBlockBoundingRect = snapRectToDevicePixelsIfNeeded(renderer.referenceBoxRect(boxPathOperation.referenceBox()), downcast<RenderLayerModelObject>(renderer));
return data;
if (auto* container = renderer.containingBlock()) {
auto& boxPathOperation = downcast<BoxPathOperation>(*pathOperation);
data.containingBlockBoundingRect = snapRectToDevicePixelsIfNeeded(container->referenceBoxRect(boxPathOperation.referenceBox()), downcast<RenderLayerModelObject>(renderer));
data.offsetFromContainingBlock = offsetFromContainer(renderer, *container);
return data;
}
return std::nullopt;
}
if (is<RayPathOperation>(pathOperation)) {
if (auto* parentBlock = renderer.containingBlock()) {
if (auto* container = renderer.containingBlock()) {
auto& rayPathOperation = downcast<RayPathOperation>(*pathOperation);
auto pathReferenceBoxRect = snapRectToDevicePixelsIfNeeded(parentBlock->transformReferenceBoxRect(parentBlock->style()), downcast<RenderLayerModelObject>(renderer));
auto pathReferenceBoxRect = snapRectToDevicePixelsIfNeeded(container->transformReferenceBoxRect(container->style()), downcast<RenderLayerModelObject>(renderer));

auto offsetPosition = renderer.style().offsetPosition();
auto startingPosition = rayPathOperation.position();
auto usedStartingPosition = startingPosition.x().isAuto() ? startingPositionForOffsetPosition(offsetPosition, pathReferenceBoxRect) : floatPointForLengthPoint(startingPosition, pathReferenceBoxRect.size());
auto usedStartingPosition = startingPosition.x().isAuto() ? startingPositionForOffsetPosition(offsetPosition, pathReferenceBoxRect, *container) : floatPointForLengthPoint(startingPosition, pathReferenceBoxRect.size());
data.usedStartingPosition = usedStartingPosition;
data.offsetFromContainingBlock = offsetFromContainer(renderer, pathReferenceBoxRect);
data.offsetFromContainingBlock = offsetFromContainer(renderer, *container);
data.containingBlockBoundingRect = pathReferenceBoxRect;

return data;
Expand Down Expand Up @@ -185,4 +188,19 @@ std::optional<Path> MotionPath::computePathForRay(const RayPathOperation& rayPat
return path;
}

std::optional<Path> MotionPath::computePathForBox(const BoxPathOperation&, const TransformOperationData& data)
{
if (auto motionPathData = data.motionPathData()) {
Path path;
auto rect = motionPathData->containingBlockBoundingRect;
auto shiftedPoint = motionPathData->offsetFromContainingBlock;
shiftedPoint.scale(-1);
rect.moveBy(shiftedPoint);
path.addRect(rect);
return path;
}
return std::nullopt;
}


} // namespace WebCore
2 changes: 2 additions & 0 deletions Source/WebCore/rendering/MotionPath.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

namespace WebCore {

class BoxPathOperation;
class RenderElement;
class PathOperation;
class RayPathOperation;
Expand All @@ -44,6 +45,7 @@ class MotionPath {
static std::optional<MotionPathData> motionPathDataForRenderer(const RenderElement&);
static bool needsUpdateAfterContainingBlockLayout(const PathOperation&);
static void applyMotionPathTransform(const RenderStyle&, const TransformOperationData&, TransformationMatrix&);
WEBCORE_EXPORT static std::optional<Path> computePathForBox(const BoxPathOperation&, const TransformOperationData&);
static std::optional<Path> computePathForRay(const RayPathOperation&, const TransformOperationData&);
static double lengthForRayPath(const RayPathOperation&, const MotionPathData&);
static double lengthForRayContainPath(const FloatRect& elementRect, double computedPathLength);
Expand Down
23 changes: 5 additions & 18 deletions Source/WebCore/rendering/PathOperation.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,9 @@ class BoxPathOperation final : public PathOperation {
return adoptRef(*new BoxPathOperation(referenceBox));
}

static Ref<BoxPathOperation> create(Path&& path, CSSBoxType referenceBox)
{
return adoptRef(*new BoxPathOperation(WTFMove(path), referenceBox));
}

Ref<PathOperation> clone() const final
{
auto path = m_path;
return adoptRef(*new BoxPathOperation(WTFMove(path), m_referenceBox));
return adoptRef(*new BoxPathOperation(m_referenceBox));
}

const Path pathForReferenceRect(const FloatRoundedRect& boundingRect) const
Expand All @@ -191,8 +185,10 @@ class BoxPathOperation final : public PathOperation {
return path;
}

const std::optional<Path> getPath(const TransformOperationData&) const final { return m_path; }
const Path& path() const { return m_path; }
const std::optional<Path> getPath(const TransformOperationData& data) const final
{
return MotionPath::computePathForBox(*this, data);
}
CSSBoxType referenceBox() const { return m_referenceBox; }

private:
Expand All @@ -209,15 +205,6 @@ class BoxPathOperation final : public PathOperation {
, m_referenceBox(referenceBox)
{
}

BoxPathOperation(Path&& path, CSSBoxType referenceBox)
: PathOperation(Box)
, m_path(WTFMove(path))
, m_referenceBox(referenceBox)
{
}

Path m_path;
CSSBoxType m_referenceBox;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2702,7 +2702,6 @@ header: <WebCore/PathOperation.h>
}

[RefCounted, CustomHeader] class WebCore::BoxPathOperation {
WebCore::Path path();
WebCore::CSSBoxType referenceBox();
}

Expand Down

0 comments on commit c377f2d

Please sign in to comment.