Skip to content

Commit

Permalink
[InteractionRegions] Add support for CSS clip-path
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=271673
<rdar://119124300>

Reviewed by Mike Wyrzykowski.

When generating Interaction Regions, check for `clip-path` rules and use
them to generate the region clip path.
When present, this style takes priority over other types of shape generation
(SVG, Icon Masking etc...).

* Source/WebCore/page/InteractionRegion.cpp:
(WebCore::hasTransparentContainerStyle):
Container with `clip-path` should not be turned into guards.
(WebCore::interactionRegionForRenderedRegion):
Add a `clip-path` shape generation branch.

* LayoutTests/interaction-region/clip-path-expected.txt: Added.
* LayoutTests/interaction-region/clip-path.html: Added.
Add tests using `clip-path`.

Canonical link: https://commits.webkit.org/276742@main
  • Loading branch information
etiennesegonzac committed Mar 27, 2024
1 parent 285d4aa commit c51e76f
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 1 deletion.
24 changes: 24 additions & 0 deletions LayoutTests/interaction-region/clip-path-expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
(GraphicsLayer
(anchor 0.00 0.00)
(bounds 1600.00 2092.00)
(children 1
(GraphicsLayer
(bounds 1600.00 2092.00)
(contentsOpaque 1)
(drawsContent 1)
(backgroundColor #FFFFFF)
(event region
(rect (0,0) width=1600 height=2092)

(interaction regions [
(interaction (0,12.50) width=253.50 height=253.50)
(clipPath move to (126.66,0), add line to (253.33,126.66), add line to (126.66,253.33), add line to (0,126.66), close subpath),
(interaction (269.50,0) width=253 height=278)
(clipPath move to (126.66,0), add line to (253.33,139.09), add line to (126.66,278.19), add line to (0,139.09), close subpath),
(interaction (538.50,14) width=253.50 height=250)
(clipPath move to (126.67,0), add line to (253.34,125), add line to (126.67,250), add line to (0,125), close subpath)])
)
)
)
)

80 changes: 80 additions & 0 deletions LayoutTests/interaction-region/clip-path.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
<html>
<head>
<meta name="viewport" content="width=1600">
<style>
body { margin: 0; }
#test {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
font-family: -apple-system;
}
section {
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.7);
min-height: 250px;
text-align: center;
}
a {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 250px;
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
a > svg, a > img {
display: block;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="test">
<section>
<a href="#">
<svg viewBox="0 0 500 500" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="myGradient">
<stop offset="10%" stop-color="gold" />
<stop offset="95%" stop-color="red" />
</radialGradient>
</defs>
<circle cx="250" cy="250" r="200" fill="url(#myGradient)" />
</svg>
</a>
</section>
<section>
<a href="#">
<img src="../css3/blending/resources/ducky.png" alt="apple logo" />
</a>
</section>
<section>
<a style="background:purple;" href="#">
Just a link
</a>
</section>
</div>
<pre id="results"></pre>
<script>
document.body.addEventListener("click", function(e) {
console.log(e, "event delegation");
});

if (window.testRunner)
testRunner.dumpAsText();

window.onload = function () {
if (!window.internals)
return;

results.textContent = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
document.getElementById('test').remove();
};
</script>
</body>
</html>
7 changes: 6 additions & 1 deletion Source/WebCore/page/InteractionRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ static bool hasTransparentContainerStyle(const RenderStyle& style)
return !style.hasBackground()
&& !style.hasOutline()
&& !style.boxShadow()
&& !style.clipPath()
&& !style.hasExplicitlySetBorderRadius()
// No visible borders or borders that do not create a complete box.
&& (!style.hasVisibleBorder()
Expand Down Expand Up @@ -420,8 +421,12 @@ std::optional<InteractionRegion> interactionRegionForRenderedRegion(RenderObject
float cornerRadius = 0;
OptionSet<InteractionRegion::CornerMask> maskedCorners { };
std::optional<Path> clipPath = std::nullopt;
RefPtr styleClipPath = regionRenderer.style().clipPath();

if (iconImage && originalElement) {
if (styleClipPath && styleClipPath->type() == PathOperation::OperationType::Shape) {
auto boundingRect = originalElement->boundingClientRect();
clipPath = styleClipPath->getPath(TransformOperationData(FloatRect(FloatPoint(), boundingRect.size())));
} else if (iconImage && originalElement) {
LayoutRect imageRect(rect);
Ref shape = Shape::createRasterShape(iconImage.get(), 0, imageRect, imageRect, WritingMode::HorizontalTb, 0);
Shape::DisplayPaths paths;
Expand Down

0 comments on commit c51e76f

Please sign in to comment.