Commit 4cc36bde authored by Emilio Cobos Álvarez's avatar Emilio Cobos Álvarez
Browse files

Bug 1824603 - Use BrowsingContext zoom level rather than nsPresContext zoom...

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
parent d1a13aff
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 =
+36 −0
Original line number Diff line number Diff line
/* 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}, ${rect.height}`);
      is(
        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();
});
+24 −13
Original line number Diff line number Diff line
@@ -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,8 @@ 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();
      cbSize.ISize(aWritingMode) *= mFullZoom;
      cbSize.BSize(aWritingMode) *= mFullZoom;
    }

    // We also need to honour the width and height attributes' default values
@@ -274,7 +282,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 +391,12 @@ void SVGOuterSVGFrame::Reflow(nsPresContext* aPresContext,
    changeBits |= COORD_CONTEXT_CHANGED;
    svgElem->SetViewportSize(newViewportSize);
  }
  if (mFullZoom != PresContext()->GetFullZoom() && !mIsInIframe) {
  if (mIsRootContent && !mIsInIframe) {
    const auto oldZoom = mFullZoom;
    mFullZoom = ComputeFullZoom();
    if (oldZoom != mFullZoom) {
      changeBits |= FULL_ZOOM_CHANGED;
    mFullZoom = PresContext()->GetFullZoom();
    }
  }
  if (changeBits && !HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
    NotifyViewportOrTransformChanged(changeBits);
+6 −5
Original line number Diff line number Diff line
@@ -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;
};

////////////////////////////////////////////////////////////////////////