Bug 1824603 - Use BrowsingContext zoom level rather than nsPresContext zoom level for root SVGs. r=longsonr

This trivially reproduces with ui.textScaleFactor=150 or so.

This needs to match ImageDocument::GetZoomLevel, for the math here to
work out.

Differential Revision: https://phabricator.services.mozilla.com/D174367
This commit is contained in:
Emilio Cobos Álvarez 2023-04-03 16:43:51 +00:00
parent e5f7ae6428
commit 4a15af1330
4 changed files with 72 additions and 18 deletions

View File

@ -26,6 +26,7 @@ skip-if = bits == 64 && (os == "mac" || os == "linux") #Bug 1646862
[browser_containerLoadingContent.js]
skip-if =
os == "win" && os_version == "6.1" # Skip on Azure - frequent failure
[browser_ImageDocument_svg_zoom.js]
[browser_submission_flush.js]
[browser_refresh_after_document_write.js]
support-files =

View File

@ -0,0 +1,38 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const URL = `data:image/svg+xml,<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="green"/></svg>`;
function test_once() {
return BrowserTestUtils.withNewTab(URL, async browser => {
return await SpecialPowers.spawn(browser, [], async function() {
const rect = content.document.documentElement.getBoundingClientRect();
info(
`${rect.width}x${rect.height}, ${content.innerWidth}x${content.innerHeight}`
);
is(
Math.round(rect.height),
content.innerHeight,
"Should fill the viewport and not overflow"
);
});
});
}
add_task(async function test_with_no_text_zoom() {
await test_once();
});
add_task(async function test_with_text_zoom() {
let dpi = window.devicePixelRatio;
await SpecialPowers.pushPrefEnv({ set: [["ui.textScaleFactor", 200]] });
ok(
window.devicePixelRatio > dpi,
"DPI should change as a result of the pref flip"
);
return test_once();
});

View File

@ -40,12 +40,7 @@ NS_IMPL_FRAMEARENA_HELPERS(SVGOuterSVGFrame)
SVGOuterSVGFrame::SVGOuterSVGFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext)
: SVGDisplayContainerFrame(aStyle, aPresContext, kClassID),
mFullZoom(PresContext()->GetFullZoom()),
mCallingReflowSVG(false),
mIsRootContent(false),
mIsInObjectOrEmbed(false),
mIsInIframe(false) {
: SVGDisplayContainerFrame(aStyle, aPresContext, kClassID) {
// Outer-<svg> has CSS layout, so remove this bit:
RemoveStateBits(NS_FRAME_SVG_LAYOUT);
AddStateBits(NS_FRAME_REFLOW_ROOT | NS_FRAME_FONT_INFLATION_CONTAINER |
@ -66,6 +61,16 @@ static inline ContainSizeAxes ContainSizeAxesIfApplicable(
return aFrame->GetContainSizeAxes();
}
// This should match ImageDocument::GetZoomLevel.
float SVGOuterSVGFrame::ComputeFullZoom() const {
MOZ_ASSERT(mIsRootContent);
MOZ_ASSERT(!mIsInIframe);
if (BrowsingContext* bc = PresContext()->Document()->GetBrowsingContext()) {
return bc->FullZoom();
}
return 1.0f;
}
void SVGOuterSVGFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) {
NS_ASSERTION(aContent->IsSVGElement(nsGkAtoms::svg),
@ -98,6 +103,9 @@ void SVGOuterSVGFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
mIsInIframe = nsGkAtoms::iframe->Equals(*type);
}
}
if (!mIsInIframe) {
mFullZoom = ComputeFullZoom();
}
}
MaybeSendIntrinsicSizeAndRatioToEmbedder();
@ -255,7 +263,7 @@ nsIFrame::SizeComputationResult SVGOuterSVGFrame::ComputeSize(
LogicalSize cbSize = aCBSize;
IntrinsicSize intrinsicSize = GetIntrinsicSize();
if (!mContent->GetParent()) {
if (mIsRootContent) {
// We're the root of the outermost browsing context, so we need to scale
// cbSize by the full-zoom so that SVGs with percentage width/height zoom:
@ -264,8 +272,11 @@ nsIFrame::SizeComputationResult SVGOuterSVGFrame::ComputeSize(
"root should not have auto-width/height containing block");
if (!mIsInIframe) {
cbSize.ISize(aWritingMode) *= PresContext()->GetFullZoom();
cbSize.BSize(aWritingMode) *= PresContext()->GetFullZoom();
// NOTE: We can't just use mFullZoom because this can run before Reflow()
// updates it.
const float zoom = ComputeFullZoom();
cbSize.ISize(aWritingMode) *= zoom;
cbSize.BSize(aWritingMode) *= zoom;
}
// We also need to honour the width and height attributes' default values
@ -274,7 +285,7 @@ nsIFrame::SizeComputationResult SVGOuterSVGFrame::ComputeSize(
// intrinsic size. Also note that explicit percentage values are mapped
// into style, so the following isn't for them.)
SVGSVGElement* content = static_cast<SVGSVGElement*>(GetContent());
auto* content = static_cast<SVGSVGElement*>(GetContent());
const SVGAnimatedLength& width =
content->mLengthAttributes[SVGSVGElement::ATTR_WIDTH];
@ -383,9 +394,12 @@ void SVGOuterSVGFrame::Reflow(nsPresContext* aPresContext,
changeBits |= COORD_CONTEXT_CHANGED;
svgElem->SetViewportSize(newViewportSize);
}
if (mFullZoom != PresContext()->GetFullZoom() && !mIsInIframe) {
changeBits |= FULL_ZOOM_CHANGED;
mFullZoom = PresContext()->GetFullZoom();
if (mIsRootContent && !mIsInIframe) {
const auto oldZoom = mFullZoom;
mFullZoom = ComputeFullZoom();
if (oldZoom != mFullZoom) {
changeBits |= FULL_ZOOM_CHANGED;
}
}
if (changeBits && !HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
NotifyViewportOrTransformChanged(changeBits);

View File

@ -143,17 +143,18 @@ class SVGOuterSVGFrame final : public SVGDisplayContainerFrame,
* being used as an image.
*/
bool IsRootOfImage();
float ComputeFullZoom() const;
void MaybeSendIntrinsicSizeAndRatioToEmbedder();
void MaybeSendIntrinsicSizeAndRatioToEmbedder(Maybe<IntrinsicSize>,
Maybe<AspectRatio>);
float mFullZoom;
float mFullZoom = 1.0f;
bool mCallingReflowSVG;
bool mIsRootContent;
bool mIsInObjectOrEmbed;
bool mIsInIframe;
bool mCallingReflowSVG = false;
bool mIsRootContent = false;
bool mIsInObjectOrEmbed = false;
bool mIsInIframe = false;
};
////////////////////////////////////////////////////////////////////////