Skip to content

Commit

Permalink
Bug 1852323 - Part 1: Update the mapping of geometry box for clip-pat…
Browse files Browse the repository at this point in the history
…h. r=emilio

It seems mask-origin/mask-clip/clip-path use different mapping for
geometry-box. We should specialize each one. In this patch, we focus on
clip-path.

Differential Revision: https://phabricator.services.mozilla.com/D188146
  • Loading branch information
BorisChiou committed Oct 10, 2023
1 parent 63d2d8a commit 5213031
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 36 deletions.
76 changes: 59 additions & 17 deletions layout/base/nsLayoutUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9708,6 +9708,17 @@ StyleGeometryBox nsLayoutUtils::CoordBoxToGeometryBox(StyleCoordBox aCoordBox) {
return StyleGeometryBox::BorderBox;
}

/* static */
nsRect nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame,
StyleGeometryBox aGeometryBox) {
// We use ComputeSVGReferenceRect for all SVG elements, except <svg>
// element, which does have an associated CSS layout box. In this case we
// should still use ComputeHTMLReferenceRect for region computing.
return aFrame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)
? ComputeSVGReferenceRect(aFrame, aGeometryBox)
: ComputeHTMLReferenceRect(aFrame, aGeometryBox);
}

static StyleGeometryBox ShapeBoxToGeometryBox(const StyleShapeBox& aBox) {
switch (aBox) {
case StyleShapeBox::BorderBox:
Expand Down Expand Up @@ -9742,25 +9753,56 @@ static StyleGeometryBox ClipPathBoxToGeometryBox(
return StyleGeometryBox::NoBox;
}

// The mapping is from
// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
/* static */
nsRect nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame,
StyleGeometryBox aGeometryBox) {
// We use ComputeSVGReferenceRect for all SVG elements, except <svg>
// element, which does have an associated CSS layout box. In this case we
// should still use ComputeHTMLReferenceRect for region computing.
return aFrame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)
? ComputeSVGReferenceRect(aFrame, aGeometryBox)
: ComputeHTMLReferenceRect(aFrame, aGeometryBox);
}

nsRect nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame,
const StyleShapeBox& aBox) {
return ComputeGeometryBox(aFrame, ShapeBoxToGeometryBox(aBox));
}
nsRect nsLayoutUtils::ComputeClipPathGeometryBox(
nsIFrame* aFrame, const StyleShapeGeometryBox& aBox) {
StyleGeometryBox box = ClipPathBoxToGeometryBox(aBox);

if (aFrame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT)) {
// For SVG elements without associated CSS layout box, the used value for
// content-box and padding-box is fill-box and for border-box and margin-box
// is stroke-box.
switch (box) {
case StyleGeometryBox::ContentBox:
case StyleGeometryBox::PaddingBox:
case StyleGeometryBox::FillBox:
return ComputeSVGReferenceRect(aFrame, StyleGeometryBox::FillBox);
case StyleGeometryBox::NoBox:
case StyleGeometryBox::BorderBox:
case StyleGeometryBox::MarginBox:
case StyleGeometryBox::StrokeBox:
return ComputeSVGReferenceRect(aFrame, StyleGeometryBox::StrokeBox);
case StyleGeometryBox::ViewBox:
return ComputeSVGReferenceRect(aFrame, StyleGeometryBox::ViewBox);
default:
MOZ_ASSERT_UNREACHABLE("Unknown clip-path geometry box");
// Use default, border-box (as stroke-box in SVG layout).
return ComputeSVGReferenceRect(aFrame, StyleGeometryBox::StrokeBox);
}
}

nsRect nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame,
const StyleShapeGeometryBox& aBox) {
return ComputeGeometryBox(aFrame, ClipPathBoxToGeometryBox(aBox));
// For elements with associated CSS layout box, the used value for fill-box is
// content-box and for stroke-box and view-box is border-box.
switch (box) {
case StyleGeometryBox::FillBox:
case StyleGeometryBox::ContentBox:
return ComputeHTMLReferenceRect(aFrame, StyleGeometryBox::ContentBox);
case StyleGeometryBox::NoBox:
case StyleGeometryBox::StrokeBox:
case StyleGeometryBox::ViewBox:
case StyleGeometryBox::BorderBox:
return ComputeHTMLReferenceRect(aFrame, StyleGeometryBox::BorderBox);
case StyleGeometryBox::PaddingBox:
return ComputeHTMLReferenceRect(aFrame, StyleGeometryBox::PaddingBox);
case StyleGeometryBox::MarginBox:
return ComputeHTMLReferenceRect(aFrame, StyleGeometryBox::MarginBox);
default:
MOZ_ASSERT_UNREACHABLE("Unknown clip-path geometry box");
// Use default, border-box.
return ComputeHTMLReferenceRect(aFrame, StyleGeometryBox::BorderBox);
}
}

/* static */
Expand Down
6 changes: 2 additions & 4 deletions layout/base/nsLayoutUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -2964,10 +2964,8 @@ class nsLayoutUtils {

static nsRect ComputeGeometryBox(nsIFrame*, StyleGeometryBox);

static nsRect ComputeGeometryBox(nsIFrame*,
const mozilla::StyleShapeGeometryBox&);

static nsRect ComputeGeometryBox(nsIFrame*, const mozilla::StyleShapeBox&);
static nsRect ComputeClipPathGeometryBox(
nsIFrame*, const mozilla::StyleShapeGeometryBox&);

static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame);
Expand Down
4 changes: 2 additions & 2 deletions layout/painting/nsDisplayList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8022,7 +8022,7 @@ static Maybe<wr::WrClipChainId> CreateSimpleClipRegion(

auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
const nsRect refBox =
nsLayoutUtils::ComputeGeometryBox(frame, clipPath.AsShape()._1);
nsLayoutUtils::ComputeClipPathGeometryBox(frame, clipPath.AsShape()._1);

wr::WrClipId clipId{};

Expand Down Expand Up @@ -8103,7 +8103,7 @@ static void FillPolygonDataForDisplayItem(
const auto& clipPath = style->mClipPath;
const auto& shape = *clipPath.AsShape()._0;
const nsRect refBox =
nsLayoutUtils::ComputeGeometryBox(frame, clipPath.AsShape()._1);
nsLayoutUtils::ComputeClipPathGeometryBox(frame, clipPath.AsShape()._1);

// We only fill polygon data for polygons that are below a complexity
// limit.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
</style>
<body>
<p>The test passes if you see a green vertical stripe next to a lime green vertical stripe, both stripes should be of equal size and there should be no red.</p>
<div style="clip-path: polygon(0% 25%, 50% 50px, 100px 75%, 0 150px) fill-box"></div>
<div style="clip-path: polygon(-75px -50%, 50% -25px, 25px 150%, -75px 75px)
fill-box"></div>
</body>
</html>
</html>
10 changes: 3 additions & 7 deletions layout/svg/CSSClipPathInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,9 @@ already_AddRefed<Path> CSSClipPathInstance::CreateClipPath(
nscoord appUnitsPerDevPixel =
mTargetFrame->PresContext()->AppUnitsPerDevPixel();

nsRect r;
if (mClipPathStyle.IsBox()) {
r = nsLayoutUtils::ComputeGeometryBox(mTargetFrame, mClipPathStyle.AsBox());
} else {
r = nsLayoutUtils::ComputeGeometryBox(mTargetFrame,
mClipPathStyle.AsShape()._1);
}
nsRect r = nsLayoutUtils::ComputeClipPathGeometryBox(
mTargetFrame, mClipPathStyle.IsBox() ? mClipPathStyle.AsBox()
: mClipPathStyle.AsShape()._1);

gfxRect rr(r.x, r.y, r.width, r.height);
rr.Scale(1.0 / AppUnitsPerCSSPixel());
Expand Down

This file was deleted.

This file was deleted.

0 comments on commit 5213031

Please sign in to comment.