зеркало из https://github.com/mozilla/gecko-dev.git
Bug 824920 - Fix zoom ratio and check the zoom offset to prevent over-scroll. r=drs
This commit is contained in:
Родитель
613657d2a5
Коммит
97e11e07df
|
@ -1348,72 +1348,79 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
|
||||||
gfx::Rect cssPageRect = mFrameMetrics.mScrollableRect;
|
gfx::Rect cssPageRect = mFrameMetrics.mScrollableRect;
|
||||||
gfx::Point scrollOffset = mFrameMetrics.mScrollOffset;
|
gfx::Point scrollOffset = mFrameMetrics.mScrollOffset;
|
||||||
gfxSize resolution = CalculateResolution(mFrameMetrics);
|
gfxSize resolution = CalculateResolution(mFrameMetrics);
|
||||||
|
gfxSize currentZoom = mFrameMetrics.mZoom;
|
||||||
|
float targetZoom;
|
||||||
|
gfxFloat targetResolution;
|
||||||
|
|
||||||
// If the rect is empty, treat it as a request to zoom out to the full page
|
// The minimum zoom to prevent over-zoom-out.
|
||||||
// size.
|
// If the zoom factor is lower than this (i.e. we are zoomed more into the page),
|
||||||
if (zoomToRect.IsEmpty()) {
|
// then the CSS content rect, in layers pixels, will be smaller than the
|
||||||
// composition bounds in CSS coordinates
|
// composition bounds. If this happens, we can't fill the target composited
|
||||||
nsIntRect cssCompositionBounds = compositionBounds;
|
// area with this frame.
|
||||||
cssCompositionBounds.ScaleInverseRoundIn(resolution.width,
|
float localMinZoom;
|
||||||
resolution.height);
|
gfx::Rect compositedRect = CalculateCompositedRectInCssPixels(mFrameMetrics);
|
||||||
cssCompositionBounds.MoveBy(scrollOffset.x, scrollOffset.y);
|
localMinZoom =
|
||||||
|
std::max(currentZoom.width / (cssPageRect.width / compositedRect.width),
|
||||||
float y = mFrameMetrics.mScrollOffset.y;
|
currentZoom.height / (cssPageRect.height / compositedRect.height));
|
||||||
float newHeight =
|
localMinZoom = std::max(localMinZoom, mMinZoom);
|
||||||
cssCompositionBounds.height * cssPageRect.width / cssCompositionBounds.width;
|
|
||||||
float dh = cssCompositionBounds.height - newHeight;
|
|
||||||
|
|
||||||
zoomToRect = gfx::Rect(0.0f,
|
|
||||||
y + dh/2,
|
|
||||||
cssPageRect.width,
|
|
||||||
y + dh/2 + newHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxFloat targetResolution =
|
|
||||||
std::min(compositionBounds.width / zoomToRect.width,
|
|
||||||
compositionBounds.height / zoomToRect.height);
|
|
||||||
|
|
||||||
// Recalculate the zoom to rect using the new dimensions.
|
|
||||||
zoomToRect.width = compositionBounds.width / targetResolution;
|
|
||||||
zoomToRect.height = compositionBounds.height / targetResolution;
|
|
||||||
|
|
||||||
// Clamp the zoom to rect to the CSS rect to make sure it fits.
|
|
||||||
zoomToRect = zoomToRect.Intersect(cssPageRect);
|
|
||||||
|
|
||||||
// Do one final recalculation to get the resolution.
|
|
||||||
targetResolution = std::max(compositionBounds.width / zoomToRect.width,
|
|
||||||
compositionBounds.height / zoomToRect.height);
|
|
||||||
float targetZoom = float(targetResolution / resolution.width) * mFrameMetrics.mZoom.width;
|
|
||||||
|
|
||||||
// If current zoom is equal to mMaxZoom,
|
|
||||||
// user still double-tapping it, just zoom-out to the full page size
|
|
||||||
if (mFrameMetrics.mZoom.width == mMaxZoom && targetZoom >= mMaxZoom) {
|
|
||||||
nsIntRect cssCompositionBounds = compositionBounds;
|
|
||||||
cssCompositionBounds.ScaleInverseRoundIn(resolution.width,
|
|
||||||
resolution.height);
|
|
||||||
cssCompositionBounds.MoveBy(scrollOffset.x, scrollOffset.y);
|
|
||||||
|
|
||||||
float y = mFrameMetrics.mScrollOffset.y;
|
|
||||||
float newHeight =
|
|
||||||
cssCompositionBounds.height * cssPageRect.width / cssCompositionBounds.width;
|
|
||||||
float dh = cssCompositionBounds.height - newHeight;
|
|
||||||
|
|
||||||
zoomToRect = gfx::Rect(0.0f,
|
|
||||||
y + dh/2,
|
|
||||||
cssPageRect.width,
|
|
||||||
y + dh/2 + newHeight);
|
|
||||||
|
|
||||||
|
if (!zoomToRect.IsEmpty()) {
|
||||||
|
// Intersect the zoom-to-rect to the CSS rect to make sure it fits.
|
||||||
zoomToRect = zoomToRect.Intersect(cssPageRect);
|
zoomToRect = zoomToRect.Intersect(cssPageRect);
|
||||||
// assign 1 to targetZoom is a shortcut
|
targetResolution =
|
||||||
targetZoom = 1;
|
std::min(compositionBounds.width / zoomToRect.width,
|
||||||
|
compositionBounds.height / zoomToRect.height);
|
||||||
|
targetZoom = float(targetResolution / resolution.width) * currentZoom.width;
|
||||||
|
}
|
||||||
|
// 1. If the rect is empty, request received from browserElementScrolling.js
|
||||||
|
// 2. currentZoom is equal to mMaxZoom and user still double-tapping it
|
||||||
|
// 3. currentZoom is equal to localMinZoom and user still double-tapping it
|
||||||
|
// Treat these three cases as a request to zoom out as much as possible.
|
||||||
|
if (zoomToRect.IsEmpty() ||
|
||||||
|
(currentZoom.width == mMaxZoom && targetZoom >= mMaxZoom) ||
|
||||||
|
(currentZoom.width == localMinZoom && targetZoom <= localMinZoom)) {
|
||||||
|
nsIntRect cssCompositionBounds = compositionBounds;
|
||||||
|
cssCompositionBounds.ScaleInverseRoundIn(resolution.width,
|
||||||
|
resolution.height);
|
||||||
|
|
||||||
|
float y = scrollOffset.y;
|
||||||
|
float newHeight =
|
||||||
|
cssCompositionBounds.height * cssPageRect.width / cssCompositionBounds.width;
|
||||||
|
float dh = cssCompositionBounds.height - newHeight;
|
||||||
|
|
||||||
|
zoomToRect = gfx::Rect(0.0f,
|
||||||
|
y + dh/2,
|
||||||
|
cssPageRect.width,
|
||||||
|
newHeight);
|
||||||
|
zoomToRect = zoomToRect.Intersect(cssPageRect);
|
||||||
|
targetResolution =
|
||||||
|
std::min(compositionBounds.width / zoomToRect.width,
|
||||||
|
compositionBounds.height / zoomToRect.height);
|
||||||
|
targetZoom = float(targetResolution / resolution.width) * currentZoom.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxFloat targetFinalZoom = clamped(targetZoom, mMinZoom, mMaxZoom);
|
targetZoom = clamped(targetZoom, localMinZoom, mMaxZoom);
|
||||||
mEndZoomToMetrics.mZoom = gfxSize(targetFinalZoom, targetFinalZoom);
|
mEndZoomToMetrics.mZoom = gfxSize(targetZoom, targetZoom);
|
||||||
|
|
||||||
|
// Adjust the zoomToRect to a sensible position to prevent overscrolling.
|
||||||
|
FrameMetrics metricsAfterZoom = mFrameMetrics;
|
||||||
|
metricsAfterZoom.mZoom = mEndZoomToMetrics.mZoom;
|
||||||
|
gfx::Rect rectAfterZoom
|
||||||
|
= CalculateCompositedRectInCssPixels(metricsAfterZoom);
|
||||||
|
|
||||||
|
// If either of these conditions are met, the page will be
|
||||||
|
// overscrolled after zoomed
|
||||||
|
if (zoomToRect.y + rectAfterZoom.height > cssPageRect.height) {
|
||||||
|
zoomToRect.y = cssPageRect.height - rectAfterZoom.height;
|
||||||
|
zoomToRect.y = zoomToRect.y > 0 ? zoomToRect.y : 0;
|
||||||
|
}
|
||||||
|
if (zoomToRect.x + rectAfterZoom.width > cssPageRect.width) {
|
||||||
|
zoomToRect.x = cssPageRect.width - rectAfterZoom.width;
|
||||||
|
zoomToRect.x = zoomToRect.x > 0 ? zoomToRect.x : 0;
|
||||||
|
}
|
||||||
|
|
||||||
mStartZoomToMetrics = mFrameMetrics;
|
mStartZoomToMetrics = mFrameMetrics;
|
||||||
mEndZoomToMetrics.mScrollOffset =
|
mEndZoomToMetrics.mScrollOffset = gfx::Point(zoomToRect.x, zoomToRect.y);
|
||||||
gfx::Point(zoomToRect.x, zoomToRect.y);
|
|
||||||
|
|
||||||
mAnimationStartTime = TimeStamp::Now();
|
mAnimationStartTime = TimeStamp::Now();
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче