commit f1dc23ae227b7948e8cf9c12eae098df74971144
parent f2c14bfe8e8cb9d25f0e6c918760e40be7c0c5e9
Author: Alexandru Marc <amarc@mozilla.com>
Date: Thu, 11 Dec 2025 23:45:41 +0200
Revert "Bug 2005169 - Fix reftest-snapshot and overflow interaction of overflowing replaced elements. r=layout-reviewers,dholbert" for causing bc failures @ browser_ext_menus_events.js
This reverts commit 670fdc48bafd9a3a36d2e3db5d669e71576d5102.
Diffstat:
7 files changed, 95 insertions(+), 100 deletions(-)
diff --git a/layout/generic/ReflowInput.h b/layout/generic/ReflowInput.h
@@ -368,12 +368,6 @@ struct ReflowInput : public SizeComputationInput {
// unconstrained dimensions replaced by zero.
nsSize ComputedSizeAsContainerIfConstrained() const;
- // Return the physical content box relative to the frame itself.
- nsRect ComputedPhysicalContentBoxRelativeToSelf() const {
- auto bp = ComputedPhysicalBorderPadding();
- return nsRect(nsPoint(bp.left, bp.top), ComputedPhysicalSize());
- }
-
// Get the writing mode of the containing block, to resolve float/clear
// logical sides appropriately.
WritingMode GetCBWritingMode() const;
diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -67,23 +67,30 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
*aSnap = false;
auto* f = static_cast<nsHTMLCanvasFrame*>(Frame());
auto* canvas = HTMLCanvasElement::FromNode(f->GetContent());
- if (!canvas->GetIsOpaque()) {
- return {};
+ nsRegion result;
+ if (canvas->GetIsOpaque()) {
+ // OK, the entire region painted by the canvas is opaque. But what is
+ // that region? It's the canvas's "dest rect" (controlled by the
+ // object-fit/object-position CSS properties), clipped to the container's
+ // content box (which is what GetBounds() returns). So, we grab those
+ // rects and intersect them.
+ nsRect constraintRect = GetBounds(aBuilder, aSnap);
+
+ // Need intrinsic size & ratio, for ComputeObjectDestRect:
+ CSSIntSize canvasSize = f->GetCanvasSize();
+ IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSize);
+ AspectRatio intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSize);
+
+ const nsRect destRect = nsLayoutUtils::ComputeObjectDestRect(
+ constraintRect, intrinsicSize, intrinsicRatio, f->StylePosition());
+ return nsRegion(destRect.Intersect(constraintRect));
}
- // OK, the entire region painted by the canvas is opaque. But what is
- // that region? It's the canvas's "dest rect" (controlled by the
- // object-fit/object-position CSS properties), clipped to the container's
- // ink overflow box (which is what GetBounds() returns). So, we grab those
- // rects and intersect them.
- const nsRect constraintRect = GetBounds(aBuilder, aSnap);
- const nsRect destRect =
- f->GetDestRect(f->GetContentRectRelativeToSelf() + ToReferenceFrame());
- return nsRegion(destRect.Intersect(constraintRect));
+ return result;
}
nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
*aSnap = true;
- return Frame()->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
+ return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
}
bool CreateWebRenderCommands(
@@ -104,8 +111,12 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
element->FlushOffscreenCanvas();
auto* canvasFrame = static_cast<nsHTMLCanvasFrame*>(mFrame);
- nsRect dest = canvasFrame->GetDestRect(
- mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame());
+ CSSIntSize canvasSizeInPx = canvasFrame->GetCanvasSize();
+ IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx);
+ AspectRatio intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx);
+ nsRect area = mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame();
+ nsRect dest = nsLayoutUtils::ComputeObjectDestRect(
+ area, intrinsicSize, intrinsicRatio, mFrame->StylePosition());
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
dest, mFrame->PresContext()->AppUnitsPerDevPixel());
@@ -130,7 +141,8 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
aManager->CommandBuilder()
.CreateOrRecycleWebRenderUserData<WebRenderCanvasData>(
this, &isRecycled);
- auto* canvasFrame = static_cast<nsHTMLCanvasFrame*>(mFrame);
+ nsHTMLCanvasFrame* canvasFrame =
+ static_cast<nsHTMLCanvasFrame*>(mFrame);
if (!canvasFrame->UpdateWebRenderCanvasData(aDisplayListBuilder,
canvasData)) {
return true;
@@ -141,8 +153,19 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
// Push IFrame for async image pipeline.
// XXX Remove this once partial display list update is supported.
- nsRect dest = canvasFrame->GetDestRect(
- mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame());
+
+ CSSIntSize canvasSizeInPx =
+ CSSIntSize::FromUnknownSize(data->GetSize());
+ IntrinsicSize intrinsicSize =
+ IntrinsicSizeFromCanvasSize(canvasSizeInPx);
+ AspectRatio intrinsicRatio =
+ IntrinsicRatioFromCanvasSize(canvasSizeInPx);
+
+ nsRect area =
+ mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame();
+ nsRect dest = nsLayoutUtils::ComputeObjectDestRect(
+ area, intrinsicSize, intrinsicRatio, mFrame->StylePosition());
+
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
dest, mFrame->PresContext()->AppUnitsPerDevPixel());
@@ -183,8 +206,15 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
return true;
}
- nsRect dest = canvasFrame->GetDestRect(
- mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame());
+ IntrinsicSize intrinsicSize =
+ IntrinsicSizeFromCanvasSize(canvasSizeInPx);
+ AspectRatio intrinsicRatio =
+ IntrinsicRatioFromCanvasSize(canvasSizeInPx);
+
+ nsRect area =
+ mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame();
+ nsRect dest = nsLayoutUtils::ComputeObjectDestRect(
+ area, intrinsicSize, intrinsicRatio, mFrame->StylePosition());
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
dest, mFrame->PresContext()->AppUnitsPerDevPixel());
@@ -212,22 +242,25 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
}
void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
- auto* f = static_cast<nsHTMLCanvasFrame*>(Frame());
- auto* canvas = HTMLCanvasElement::FromNode(f->GetContent());
+ nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(Frame());
+ HTMLCanvasElement* canvas = HTMLCanvasElement::FromNode(f->GetContent());
+ nsRect area = f->GetContentRectRelativeToSelf() + ToReferenceFrame();
CSSIntSize canvasSizeInPx = f->GetCanvasSize();
+
nsPresContext* presContext = f->PresContext();
canvas->HandlePrintCallback(presContext);
- if (canvasSizeInPx.width <= 0 || canvasSizeInPx.height <= 0) {
+ if (canvasSizeInPx.width <= 0 || canvasSizeInPx.height <= 0 ||
+ area.IsEmpty()) {
return;
}
- nsRect dest = f->GetDestRect(mFrame->GetContentRectRelativeToSelf() +
- ToReferenceFrame());
- if (dest.IsEmpty()) {
- return;
- }
+ IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx);
+ AspectRatio intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx);
+
+ nsRect dest = nsLayoutUtils::ComputeObjectDestRect(
+ area, intrinsicSize, intrinsicRatio, f->StylePosition());
gfxContextMatrixAutoSaveRestore saveMatrix(aCtx);
@@ -372,14 +405,6 @@ nsIFrame::SizeComputationResult nsHTMLCanvasFrame::ComputeSize(
AspectRatioUsage::None};
}
-nsRect nsHTMLCanvasFrame::GetDestRect(const nsRect& aFrameContentBox) const {
- const CSSIntSize canvasSizeInPx = GetCanvasSize();
- IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx);
- AspectRatio intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx);
- return nsLayoutUtils::ComputeObjectDestRect(aFrameContentBox, intrinsicSize,
- intrinsicRatio, StylePosition());
-}
-
void nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aMetrics,
const ReflowInput& aReflowInput,
@@ -399,8 +424,6 @@ void nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
aMetrics.SetSize(wm, finalSize);
aMetrics.SetOverflowAreasToDesiredBounds();
- aMetrics.mOverflowAreas.UnionAllWith(
- GetDestRect(aReflowInput.ComputedPhysicalContentBoxRelativeToSelf()));
FinishAndStoreOverflow(&aMetrics);
// Reflow the single anon block child.
diff --git a/layout/generic/nsHTMLCanvasFrame.h b/layout/generic/nsHTMLCanvasFrame.h
@@ -65,8 +65,6 @@ class nsHTMLCanvasFrame final : public nsContainerFrame {
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
- nsRect GetDestRect(const nsRect& aFrameContentBox) const;
-
#ifdef ACCESSIBILITY
mozilla::a11y::AccType AccessibleType() override;
#endif
diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp
@@ -1635,11 +1635,15 @@ void nsImageFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
}
aMetrics.SetOverflowAreasToDesiredBounds();
- const bool imageOK = mKind != Kind::ImageLoadingContent ||
- ImageOk(mContent->AsElement()->State());
+ bool imageOK = mKind != Kind::ImageLoadingContent ||
+ ImageOk(mContent->AsElement()->State());
// Determine if the size is available
- const bool haveSize = loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE;
+ bool haveSize = false;
+ if (loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) {
+ haveSize = true;
+ }
+
if (!imageOK || !haveSize) {
nsRect altFeedbackSize(
0, 0,
@@ -1652,19 +1656,10 @@ void nsImageFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
// outside the image.
nsRect& inkOverflow = aMetrics.InkOverflow();
inkOverflow.UnionRect(inkOverflow, altFeedbackSize);
- } else {
- // Union with our dest rect (note that it will most likely get clipped in
- // FinishAndStoreOverflow). Only do this if we're not fragmented, since in
- // that case overflow goes into our continuation.
- if (aStatus.IsComplete()) {
- aMetrics.mOverflowAreas.UnionAllWith(
- GetDestRect(aReflowInput.ComputedPhysicalContentBoxRelativeToSelf()));
- }
- if (PresShell()->IsActive()) {
- // We've just reflowed and we should have an accurate size, so we're ready
- // to request a decode.
- MaybeDecodeForPredictedSize();
- }
+ } else if (PresShell()->IsActive()) {
+ // We've just reflowed and we should have an accurate size, so we're ready
+ // to request a decode.
+ MaybeDecodeForPredictedSize();
}
FinishAndStoreOverflow(&aMetrics, aReflowInput.mStyleDisplay);
@@ -2356,8 +2351,10 @@ void nsDisplayImage::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {
}
nsRect nsDisplayImage::GetDestRect() const {
- auto* f = static_cast<nsImageFrame*>(mFrame);
- return f->GetDestRect(f->GetContentRectRelativeToSelf() + ToReferenceFrame());
+ bool snap = true;
+ const nsRect frameContentBox = GetBounds(&snap);
+ nsImageFrame* imageFrame = static_cast<nsImageFrame*>(mFrame);
+ return imageFrame->GetDestRect(frameContentBox);
}
nsRect nsDisplayImage::GetDestRectViewTransition() const {
@@ -2584,8 +2581,7 @@ ImgDrawResult nsImageFrame::PaintImage(gfxContext& aRenderingContext,
"bad width");
nsPoint anchorPoint;
- const nsRect dest =
- GetDestRect(GetContentRectRelativeToSelf() + aPt, &anchorPoint);
+ nsRect dest = GetDestRect(GetContentRectRelativeToSelf() + aPt, &anchorPoint);
SVGImageContext svgContext;
SVGImageContext::MaybeStoreContextPaint(svgContext, this, aImage);
diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h
@@ -458,7 +458,7 @@ class nsDisplayImage final : public nsPaintedDisplayItem {
nsRect GetBounds(bool* aSnap) const {
*aSnap = true;
- return Frame()->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
+ return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
}
nsRect GetBounds(nsDisplayListBuilder*, bool* aSnap) const final {
diff --git a/layout/generic/nsVideoFrame.cpp b/layout/generic/nsVideoFrame.cpp
@@ -219,12 +219,6 @@ bool nsVideoFrame::ReflowFinished() {
return false;
}
-nsRect nsVideoFrame::GetDestRect(const nsRect& aContentBox) const {
- return nsLayoutUtils::ComputeObjectDestRect(
- aContentBox, GetIntrinsicSize(/* aIgnoreContainment = */ true),
- GetIntrinsicRatio(/* aIgnoreContainment = */ true), StylePosition());
-}
-
void nsVideoFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
@@ -341,8 +335,6 @@ void nsVideoFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
aMetrics.SetSize(myWM, logicalDesiredSize);
aMetrics.SetOverflowAreasToDesiredBounds();
- aMetrics.mOverflowAreas.UnionAllWith(
- GetDestRect(aReflowInput.ComputedPhysicalContentBoxRelativeToSelf()));
FinishAndStoreOverflow(&aMetrics);
@@ -393,17 +385,13 @@ Maybe<nsSize> nsVideoFrame::PosterImageSize() const {
}
AspectRatio nsVideoFrame::GetIntrinsicRatio() const {
- return GetIntrinsicRatio(/* aIgnoreContainment = */ false);
-}
-
-AspectRatio nsVideoFrame::GetIntrinsicRatio(bool aIgnoreContainment) const {
if (!HasVideoElement()) {
// Audio elements have no intrinsic ratio.
return AspectRatio();
}
// 'contain:[inline-]size' replaced elements have no intrinsic ratio.
- if (!aIgnoreContainment && GetContainSizeAxes().IsAny()) {
+ if (GetContainSizeAxes().IsAny()) {
return AspectRatio();
}
@@ -454,9 +442,8 @@ bool nsVideoFrame::ShouldDisplayPoster() const {
return true;
}
-IntrinsicSize nsVideoFrame::GetIntrinsicSize(bool aIgnoreContainment) const {
- const auto containAxes =
- aIgnoreContainment ? ContainSizeAxes(false, false) : GetContainSizeAxes();
+IntrinsicSize nsVideoFrame::GetIntrinsicSize() {
+ const auto containAxes = GetContainSizeAxes();
const auto isVideo = HasVideoElement();
// Intrinsic size will be given by contain-intrinsic-size if the element is
// size-contained. If both axes have containment, FinishIntrinsicSize() will
@@ -497,10 +484,6 @@ IntrinsicSize nsVideoFrame::GetIntrinsicSize(bool aIgnoreContainment) const {
IntrinsicSize(kFallbackIntrinsicSize));
}
-IntrinsicSize nsVideoFrame::GetIntrinsicSize() {
- return GetIntrinsicSize(/* aIgnoreContainment = */ false);
-}
-
void nsVideoFrame::UpdatePosterSource(bool aNotify) {
NS_ASSERTION(HasVideoElement(), "Only call this on <video> elements.");
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
@@ -568,9 +551,9 @@ class nsDisplayVideo final : public nsPaintedDisplayItem {
NS_DISPLAY_DECL_NAME("Video", TYPE_VIDEO)
already_AddRefed<ImageContainer> GetImageContainer(gfxRect& aDestGFXRect) {
- auto* f = static_cast<nsVideoFrame*>(Frame());
- nsRect area = f->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
- auto* element = static_cast<HTMLVideoElement*>(f->GetContent());
+ nsRect area = Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
+ HTMLVideoElement* element =
+ static_cast<HTMLVideoElement*>(Frame()->GetContent());
Maybe<CSSIntSize> videoSizeInPx = element->GetVideoSize();
if (videoSizeInPx.isNothing() || area.IsEmpty()) {
@@ -590,9 +573,12 @@ class nsDisplayVideo final : public nsPaintedDisplayItem {
return nullptr;
}
- nsRect dest =
- f->GetDestRect(f->GetContentRectRelativeToSelf() + ToReferenceFrame());
- aDestGFXRect = f->PresContext()->AppUnitsToGfxUnits(dest);
+ const auto aspectRatio = AspectRatio::FromSize(*videoSizeInPx);
+ const IntrinsicSize intrinsicSize(CSSPixel::ToAppUnits(*videoSizeInPx));
+ nsRect dest = nsLayoutUtils::ComputeObjectDestRect(
+ area, intrinsicSize, aspectRatio, Frame()->StylePosition());
+
+ aDestGFXRect = Frame()->PresContext()->AppUnitsToGfxUnits(dest);
aDestGFXRect.Round();
if (aDestGFXRect.IsEmpty()) {
return nullptr;
@@ -601,7 +587,7 @@ class nsDisplayVideo final : public nsPaintedDisplayItem {
return container.forget();
}
- bool CreateWebRenderCommands(
+ virtual bool CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
@@ -630,10 +616,11 @@ class nsDisplayVideo final : public nsPaintedDisplayItem {
// For opaque videos, we will want to override GetOpaqueRegion here.
// This is tracked by bug 1545498.
- nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override {
+ virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
+ bool* aSnap) const override {
*aSnap = true;
nsIFrame* f = Frame();
- return f->InkOverflowRectRelativeToSelf() + ToReferenceFrame();
+ return f->GetContentRectRelativeToSelf() + ToReferenceFrame();
}
// Only report FirstContentfulPaint when the video is set
@@ -643,7 +630,8 @@ class nsDisplayVideo final : public nsPaintedDisplayItem {
return video->VideoWidth() > 0;
}
- void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override {
+ virtual void Paint(nsDisplayListBuilder* aBuilder,
+ gfxContext* aCtx) override {
HTMLVideoElement* element =
static_cast<HTMLVideoElement*>(Frame()->GetContent());
gfxRect destGFXRect;
diff --git a/layout/generic/nsVideoFrame.h b/layout/generic/nsVideoFrame.h
@@ -49,9 +49,7 @@ class nsVideoFrame : public nsContainerFrame,
/* get the size of the video's display */
mozilla::IntrinsicSize GetIntrinsicSize() final;
- mozilla::IntrinsicSize GetIntrinsicSize(bool aIgnoreContainment) const;
mozilla::AspectRatio GetIntrinsicRatio() const final;
- mozilla::AspectRatio GetIntrinsicRatio(bool aIgnoreContainment) const;
SizeComputationResult ComputeSize(
const SizeComputationInput& aSizingInput, mozilla::WritingMode aWM,
const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
@@ -63,8 +61,6 @@ class nsVideoFrame : public nsContainerFrame,
nscoord IntrinsicISize(const mozilla::IntrinsicSizeInput& aInput,
mozilla::IntrinsicISizeType aType) final;
- nsRect GetDestRect(const nsRect& aContentBox) const;
-
void Destroy(DestroyContext&) final;
void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,