Bug 1501665 Part 10: Modify viewport resize zoom scaling to account for clamped zoom levels. r=botond
authorBrad Werth <bwerth@mozilla.com>
Mon, 18 Mar 2019 14:59:12 +0000
changeset 464845 8824d55c1b62ca892bf153a66213ada838c65df9
parent 464844 22aac830b13a8ff5f57f8d7c1db94d9caeb26a03
child 464846 916cbe96f1d308779b27af7b842d1c2dba8024c1
push id35727
push userdvarga@mozilla.com
push dateTue, 19 Mar 2019 09:48:59 +0000
treeherdermozilla-central@70baa37ae1eb [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