mobile/android/chrome/content/ZoomHelper.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4 "use strict";
michael@0 5
michael@0 6 var ZoomHelper = {
michael@0 7 zoomInAndSnapToRange: function(aRange) {
michael@0 8 // aRange is always non-null here, since a check happened previously.
michael@0 9 let viewport = BrowserApp.selectedTab.getViewport();
michael@0 10 let fudge = 15; // Add a bit of fudge.
michael@0 11 let boundingElement = aRange.offsetNode;
michael@0 12 while (!boundingElement.getBoundingClientRect && boundingElement.parentNode) {
michael@0 13 boundingElement = boundingElement.parentNode;
michael@0 14 }
michael@0 15
michael@0 16 let rect = ElementTouchHelper.getBoundingContentRect(boundingElement);
michael@0 17 let drRect = aRange.getClientRect();
michael@0 18 let scrollTop =
michael@0 19 BrowserApp.selectedBrowser.contentDocument.documentElement.scrollTop ||
michael@0 20 BrowserApp.selectedBrowser.contentDocument.body.scrollTop;
michael@0 21
michael@0 22 // We subtract half the height of the viewport so that we can (ideally)
michael@0 23 // center the area of interest on the screen.
michael@0 24 let topPos = scrollTop + drRect.top - (viewport.cssHeight / 2.0);
michael@0 25
michael@0 26 // Factor in the border and padding
michael@0 27 let boundingStyle = window.getComputedStyle(boundingElement);
michael@0 28 let leftAdjustment = parseInt(boundingStyle.paddingLeft) +
michael@0 29 parseInt(boundingStyle.borderLeftWidth);
michael@0 30
michael@0 31 BrowserApp.selectedTab._mReflozPositioned = true;
michael@0 32
michael@0 33 rect.type = "Browser:ZoomToRect";
michael@0 34 rect.x = Math.max(viewport.cssPageLeft, rect.x - fudge + leftAdjustment);
michael@0 35 rect.y = Math.max(topPos, viewport.cssPageTop);
michael@0 36 rect.w = viewport.cssWidth;
michael@0 37 rect.h = viewport.cssHeight;
michael@0 38 rect.animate = false;
michael@0 39
michael@0 40 sendMessageToJava(rect);
michael@0 41 BrowserApp.selectedTab._mReflozPoint = null;
michael@0 42 },
michael@0 43
michael@0 44 zoomOut: function() {
michael@0 45 BrowserEventHandler.resetMaxLineBoxWidth();
michael@0 46 sendMessageToJava({ type: "Browser:ZoomToPageWidth" });
michael@0 47 },
michael@0 48
michael@0 49 isRectZoomedIn: function(aRect, aViewport) {
michael@0 50 // This function checks to see if the area of the rect visible in the
michael@0 51 // viewport (i.e. the "overlapArea" variable below) is approximately
michael@0 52 // the max area of the rect we can show. It also checks that the rect
michael@0 53 // is actually on-screen by testing the left and right edges of the rect.
michael@0 54 // In effect, this tells us whether or not zooming in to this rect
michael@0 55 // will significantly change what the user is seeing.
michael@0 56 const minDifference = -20;
michael@0 57 const maxDifference = 20;
michael@0 58 const maxZoomAllowed = 4; // keep this in sync with mobile/android/base/ui/PanZoomController.MAX_ZOOM
michael@0 59
michael@0 60 let vRect = new Rect(aViewport.cssX, aViewport.cssY, aViewport.cssWidth, aViewport.cssHeight);
michael@0 61 let overlap = vRect.intersect(aRect);
michael@0 62 let overlapArea = overlap.width * overlap.height;
michael@0 63 let availHeight = Math.min(aRect.width * vRect.height / vRect.width, aRect.height);
michael@0 64 let showing = overlapArea / (aRect.width * availHeight);
michael@0 65 let dw = (aRect.width - vRect.width);
michael@0 66 let dx = (aRect.x - vRect.x);
michael@0 67
michael@0 68 if (fuzzyEquals(aViewport.zoom, maxZoomAllowed) && overlap.width / aRect.width > 0.9) {
michael@0 69 // we're already at the max zoom and the block is not spilling off the side of the screen so that even
michael@0 70 // if the block isn't taking up most of the viewport we can't pan/zoom in any more. return true so that we zoom out
michael@0 71 return true;
michael@0 72 }
michael@0 73
michael@0 74 return (showing > 0.9 &&
michael@0 75 dx > minDifference && dx < maxDifference &&
michael@0 76 dw > minDifference && dw < maxDifference);
michael@0 77 },
michael@0 78
michael@0 79 /* Zoom to an element, optionally keeping a particular part of it
michael@0 80 * in view if it is really tall.
michael@0 81 */
michael@0 82 zoomToElement: function(aElement, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true) {
michael@0 83 let rect = ElementTouchHelper.getBoundingContentRect(aElement);
michael@0 84 ZoomHelper.zoomToRect(rect, aClickY, aCanZoomOut, aCanScrollHorizontally, aElement);
michael@0 85 },
michael@0 86
michael@0 87 zoomToRect: function(aRect, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true, aElement) {
michael@0 88 const margin = 15;
michael@0 89
michael@0 90 if(!aRect.h || !aRect.w) {
michael@0 91 aRect.h = aRect.height;
michael@0 92 aRect.w = aRect.width;
michael@0 93 }
michael@0 94
michael@0 95 let viewport = BrowserApp.selectedTab.getViewport();
michael@0 96 let bRect = new Rect(aCanScrollHorizontally ? Math.max(viewport.cssPageLeft, aRect.x - margin) : viewport.cssX,
michael@0 97 aRect.y,
michael@0 98 aCanScrollHorizontally ? aRect.w + 2 * margin : viewport.cssWidth,
michael@0 99 aRect.h);
michael@0 100 // constrict the rect to the screen's right edge
michael@0 101 bRect.width = Math.min(bRect.width, viewport.cssPageRight - bRect.x);
michael@0 102
michael@0 103 // if the rect is already taking up most of the visible area and is stretching the
michael@0 104 // width of the page, then we want to zoom out instead.
michael@0 105 if (aElement) {
michael@0 106 if (BrowserEventHandler.mReflozPref) {
michael@0 107 let zoomFactor = BrowserApp.selectedTab.getZoomToMinFontSize(aElement);
michael@0 108
michael@0 109 bRect.width = zoomFactor <= 1.0 ? bRect.width : gScreenWidth / zoomFactor;
michael@0 110 bRect.height = zoomFactor <= 1.0 ? bRect.height : bRect.height / zoomFactor;
michael@0 111 if (zoomFactor == 1.0 || ZoomHelper.isRectZoomedIn(bRect, viewport)) {
michael@0 112 if (aCanZoomOut) {
michael@0 113 ZoomHelper.zoomOut();
michael@0 114 }
michael@0 115 return;
michael@0 116 }
michael@0 117 } else if (ZoomHelper.isRectZoomedIn(bRect, viewport)) {
michael@0 118 if (aCanZoomOut) {
michael@0 119 ZoomHelper.zoomOut();
michael@0 120 }
michael@0 121 return;
michael@0 122 }
michael@0 123 }
michael@0 124
michael@0 125 let rect = {};
michael@0 126
michael@0 127 rect.type = "Browser:ZoomToRect";
michael@0 128 rect.x = bRect.x;
michael@0 129 rect.y = bRect.y;
michael@0 130 rect.w = bRect.width;
michael@0 131 rect.h = Math.min(bRect.width * viewport.cssHeight / viewport.cssWidth, bRect.height);
michael@0 132
michael@0 133 if (aClickY >= 0) {
michael@0 134 // if the block we're zooming to is really tall, and we want to keep a particular
michael@0 135 // part of it in view, then adjust the y-coordinate of the target rect accordingly.
michael@0 136 // the 1.2 multiplier is just a little fuzz to compensate for bRect including horizontal
michael@0 137 // margins but not vertical ones.
michael@0 138 let cssTapY = viewport.cssY + aClickY;
michael@0 139 if ((bRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) {
michael@0 140 rect.y = cssTapY - (rect.h / 2);
michael@0 141 }
michael@0 142 }
michael@0 143
michael@0 144 if (rect.w > viewport.cssWidth || rect.h > viewport.cssHeight) {
michael@0 145 BrowserEventHandler.resetMaxLineBoxWidth();
michael@0 146 }
michael@0 147
michael@0 148 sendMessageToJava(rect);
michael@0 149 },
michael@0 150 };

mercurial