Bug 1501665 Part 10: Modify viewport resize zoom scaling to account for clamped zoom levels. r=botond
☠☠ backed out by af46b1e88998 ☠ ☠
authorBrad Werth <bwerth@mozilla.com>
Mon, 18 Mar 2019 14:59:12 +0000
changeset 464817 520dd24a73fc1a224c38c93ab91d36eecce727ed
parent 464816 3542bf2b89ddf170efe6c723a64f297868bc7db1
child 464818 5bdf0ad9dc6639dd86499fded67183f77407a8ee
push id80720
push userbwerth@mozilla.com
push dateMon, 18 Mar 2019 15:02:22 +0000
treeherderautoland@2fa518cb0dfc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1501665
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1501665 Part 10: Modify viewport resize zoom scaling to account for clamped zoom levels. r=botond Differential Revision: https://phabricator.services.mozilla.com/D21291
layout/base/MobileViewportManager.cpp
--- a/layout/base/MobileViewportManager.cpp
+++ b/layout/base/MobileViewportManager.cpp
@@ -311,19 +311,83 @@ void MobileViewportManager::UpdateResolu
       // 1. screen size changes, CSS viewport does not (pages with no meta
       //    viewport or a fixed size viewport)
       // 2. screen size changes, CSS viewport also does (pages with a
       //    device-width viewport)
       // 3. screen size remains constant, but CSS viewport changes (meta
       //    viewport tag is added or removed)
       // 4. neither screen size nor CSS viewport changes
       if (aDisplayWidthChangeRatio) {
-        newZoom = Some(
-            ScaleZoomWithDisplayWidth(zoom, aDisplayWidthChangeRatio.value(),
-                                      viewportSize, mMobileViewportSize));
+        // One more complication is that our current zoom level may be the
+        // result of clamping to either the minimum or maximum zoom level
+        // allowed by the viewport. If we naively scale the zoom level with
+        // the change in the display width, we might be scaling one of these
+        // clamped values. What we really want to do is to make scaling of the
+        // zoom aware of these minimum and maximum clamping points, so that we
+        // keep display width changes completely reversible.
+
+        // Because of the behavior of ShrinkToDisplaySizeIfNeeded, we are
+        // choosing zoom clamping points based on the content size of the
+        // scrollable rect, which might different from aViewportOrContentSize.
+        CSSSize contentSize = aViewportOrContentSize;
+        nsIScrollableFrame* rootScrollableFrame =
+            mPresShell->GetRootScrollFrameAsScrollable();
+        if (rootScrollableFrame) {
+          nsRect scrollableRect =
+              nsLayoutUtils::CalculateScrollableRectForFrame(
+                  rootScrollableFrame, nullptr);
+          contentSize = CSSSize::FromAppUnits(scrollableRect.Size());
+        }
+
+        // We scale the sizes, though we only care about the scaled widths.
+        ScreenSize minZoomDisplaySize =
+            contentSize * aViewportInfo.GetMinZoom();
+        ScreenSize maxZoomDisplaySize =
+            contentSize * aViewportInfo.GetMaxZoom();
+
+        float ratio = aDisplayWidthChangeRatio.value();
+        ScreenSize newDisplaySize(aDisplaySize);
+        ScreenSize oldDisplaySize = newDisplaySize / ratio;
+
+        // To calculate an adjusted ratio, we use some combination of these
+        // four values:
+        float a(minZoomDisplaySize.width);
+        float b(maxZoomDisplaySize.width);
+        float c(oldDisplaySize.width);
+        float d(newDisplaySize.width);
+
+        // For both oldDisplaySize and aDisplaySize, the values are in one of
+        // three "zones":
+        // 1) Less than or equal to minZoomDisplaySize.
+        // 2) Between minZoomDisplaySize and maxZoomDisplaySize.
+        // 3) Greater than or equal to maxZoomDisplaySize.
+
+        // Depending on which zone each are in, the adjusted ratio is shown in
+        // the table below (using the a-b-c-d coding from above):
+
+        //   d | 1 | 2 | 3 |
+        // c   +---+---+---+
+        //     | a | d | b |
+        // 1   | a | a | a |
+        //     +---+---+---+
+        //     | a | d | b |
+        // 2   | c | c | c |
+        //     +---+---+---+
+        //     | a | d | b |
+        // 3   | b | b | b |
+        //     +---+---+---+
+
+        // Conveniently, the numerator is just d clamped to a..b, and the
+        // denominator is c clamped to a..b.
+        float numerator = clamped(d, a, b);
+        float denominator = clamped(c, a, b);
+
+        float adjustedRatio = numerator / denominator;
+        newZoom = Some(ScaleZoomWithDisplayWidth(
+            zoom, adjustedRatio, viewportSize, mMobileViewportSize));
       }
     }
   } else {  // aType == UpdateType::ContentSize
     MOZ_ASSERT(aType == UpdateType::ContentSize);
     MOZ_ASSERT(aDisplayWidthChangeRatio.isNothing());
 
     // We try to scale down the contents only IF the document has no
     // initial-scale AND IF it's the initial paint AND IF it's not restored