diff --git a/dom/html/test/browser.ini b/dom/html/test/browser.ini index 45b045453fab..cb02f7f551b2 100644 --- a/dom/html/test/browser.ini +++ b/dom/html/test/browser.ini @@ -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 = diff --git a/dom/html/test/browser_ImageDocument_svg_zoom.js b/dom/html/test/browser_ImageDocument_svg_zoom.js new file mode 100644 index 000000000000..2c22ad4dd8ce --- /dev/null +++ b/dom/html/test/browser_ImageDocument_svg_zoom.js @@ -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,`; + +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(); +}); diff --git a/layout/svg/SVGOuterSVGFrame.cpp b/layout/svg/SVGOuterSVGFrame.cpp index 4d3e919197f8..7c2e57550af2 100644 --- a/layout/svg/SVGOuterSVGFrame.cpp +++ b/layout/svg/SVGOuterSVGFrame.cpp @@ -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- 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(GetContent()); + auto* content = static_cast(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); diff --git a/layout/svg/SVGOuterSVGFrame.h b/layout/svg/SVGOuterSVGFrame.h index 8db256c690a4..68ac7caba585 100644 --- a/layout/svg/SVGOuterSVGFrame.h +++ b/layout/svg/SVGOuterSVGFrame.h @@ -143,17 +143,18 @@ class SVGOuterSVGFrame final : public SVGDisplayContainerFrame, * being used as an image. */ bool IsRootOfImage(); + float ComputeFullZoom() const; void MaybeSendIntrinsicSizeAndRatioToEmbedder(); void MaybeSendIntrinsicSizeAndRatioToEmbedder(Maybe, Maybe); - 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; }; ////////////////////////////////////////////////////////////////////////