Bug 804985 - [browser] don't try to zoom out wider than the page width r=cjones

1. bring the zoom factor into BrowserElementScrollng.js
2. fix the zoom ratio in AsyncPanZoomController::ZoomToRect
3. fix the relation between _isRectZoomedIn and AsyncPanZoomController::ZoomToRect
4. zoom it out if the rect reach the device maximal zoom ratio
This commit is contained in:
Benjamin Chen 2012-11-28 17:18:12 +08:00
Родитель 563634fe75
Коммит 261e6627b6
3 изменённых файлов: 44 добавлений и 42 удалений

Просмотреть файл

@ -26,7 +26,7 @@ const ContentPanning = {
case 'click':
evt.stopPropagation();
evt.preventDefault();
let target = evt.target;
let view = target.ownerDocument ? target.ownerDocument.defaultView
: target;
@ -241,6 +241,9 @@ const ContentPanning = {
this._viewport = new Rect(metrics.x, metrics.y,
metrics.viewport.width,
metrics.viewport.height);
this._cssCompositedRect = new Rect(metrics.x, metrics.y,
metrics.cssCompositedRect.width,
metrics.cssCompositedRect.height);
this._cssPageRect = new Rect(metrics.cssPageRect.x,
metrics.cssPageRect.y,
metrics.cssPageRect.width,
@ -283,7 +286,7 @@ const ContentPanning = {
// if the rect is already taking up most of the visible area and is stretching the
// width of the page, then we want to zoom out instead.
if (this._isRectZoomedIn(bRect, viewport)) {
if (this._isRectZoomedIn(bRect, this._cssCompositedRect)) {
this._zoomOut();
return;
}
@ -291,7 +294,7 @@ const ContentPanning = {
rect.x = Math.round(bRect.x);
rect.y = Math.round(bRect.y);
rect.w = Math.round(bRect.width);
rect.h = Math.round(Math.min(bRect.width * viewport.height / viewport.height, bRect.height));
rect.h = Math.round(bRect.height);
// if the block we're zooming to is really tall, and the user double-tapped
// more than a screenful of height from the top of it, then adjust the y-coordinate
@ -328,25 +331,17 @@ const ContentPanning = {
_isRectZoomedIn: function(aRect, aViewport) {
// This function checks to see if the area of the rect visible in the
// viewport (i.e. the "overlapArea" variable below) is approximately
// the max area of the rect we can show. It also checks that the rect
// is actually on-screen by testing the left and right edges of the rect.
// In effect, this tells us whether or not zooming in to this rect
// will significantly change what the user is seeing.
const minDifference = -20;
const maxDifference = 20;
// viewport (i.e. the "overlapArea" variable below) is approximately
// the max area of the rect we can show.
let vRect = new Rect(aViewport.x, aViewport.y, aViewport.width, aViewport.height);
let overlap = vRect.intersect(aRect);
let overlapArea = overlap.width * overlap.height;
let availHeight = Math.min(aRect.width * vRect.height / vRect.width, aRect.height);
let showing = overlapArea / (aRect.width * availHeight);
let dw = (aRect.width - vRect.width);
let dx = (aRect.x - vRect.x);
let ratioW = (aRect.width / vRect.width);
let ratioH = (aRect.height / vRect.height);
return (showing > 0.9 &&
dx > minDifference && dx < maxDifference &&
dw > minDifference && dw < maxDifference);
return (showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9));
}
};

Просмотреть файл

@ -1173,6 +1173,8 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
return true;
}
gfx::Rect cssCompositedRect =
AsyncPanZoomController::CalculateCompositedRectInCssPixels(aFrameMetrics);
// The BrowserElementScrolling helper must know about these updated metrics
// for other functions it performs, such as double tap handling.
nsCString data;
@ -1200,6 +1202,10 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
data += nsPrintfCString(", \"width\" : %f", aFrameMetrics.mScrollableRect.width);
data += nsPrintfCString(", \"height\" : %f", aFrameMetrics.mScrollableRect.height);
data += nsPrintfCString(" }");
data += nsPrintfCString(", \"cssCompositedRect\" : ");
data += nsPrintfCString("{ \"width\" : %f", cssCompositedRect.width);
data += nsPrintfCString(", \"height\" : %f", cssCompositedRect.height);
data += nsPrintfCString(" }");
data += nsPrintfCString(" }");
DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
@ -1207,8 +1213,6 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mWebNav);
gfx::Rect cssCompositedRect =
AsyncPanZoomController::CalculateCompositedRectInCssPixels(aFrameMetrics);
utils->SetScrollPositionClampingScrollPortSize(
cssCompositedRect.width, cssCompositedRect.height);
ScrollWindowTo(window, aFrameMetrics.mScrollOffset);

Просмотреть файл

@ -1210,33 +1210,11 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
y + dh/2,
cssPageRect.width,
y + dh/2 + newHeight);
} else {
float targetRatio = float(compositionBounds.width) / float(compositionBounds.height);
float rectRatio = zoomToRect.width / zoomToRect.height;
if (fabsf(targetRatio - rectRatio) < EPSILON) {
// All good, do nothing.
} else if (targetRatio < rectRatio) {
// Need to increase zoomToRect height.
float newHeight = zoomToRect.height / targetRatio;
zoomToRect.y -= (newHeight - zoomToRect.height) / 2;
zoomToRect.height = newHeight;
} else { // (targetRatio > rectRatio) {
// Need to increase zoomToRect width.
float newWidth = targetRatio * zoomToRect.width;
zoomToRect.x -= (newWidth - zoomToRect.width) / 2;
zoomToRect.width = newWidth;
}
zoomToRect = zoomToRect.Intersect(cssPageRect);
}
gfxFloat targetResolution =
NS_MIN(compositionBounds.width / zoomToRect.width,
compositionBounds.height / zoomToRect.height);
gfxFloat targetZoom = clamped(float(targetResolution / resolution.width),
mMinZoom, mMaxZoom);
mEndZoomToMetrics.mZoom = gfxSize(targetZoom, targetZoom);
// Recalculate the zoom to rect using the new dimensions.
zoomToRect.width = compositionBounds.width / targetResolution;
@ -1248,8 +1226,33 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
// Do one final recalculation to get the resolution.
targetResolution = NS_MAX(compositionBounds.width / zoomToRect.width,
compositionBounds.height / zoomToRect.height);
targetZoom = targetResolution / resolution.width;
mEndZoomToMetrics.mZoom = gfxSize(targetZoom, targetZoom);
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);
zoomToRect = zoomToRect.Intersect(cssPageRect);
// assign 1 to targetZoom is a shortcut
targetZoom = 1;
}
gfxFloat targetFinalZoom = clamped(targetZoom, mMinZoom, mMaxZoom);
mEndZoomToMetrics.mZoom = gfxSize(targetFinalZoom, targetFinalZoom);
mStartZoomToMetrics = mFrameMetrics;
mEndZoomToMetrics.mScrollOffset =