1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/chrome/content/ZoomHelper.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,150 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +"use strict"; 1.8 + 1.9 +var ZoomHelper = { 1.10 + zoomInAndSnapToRange: function(aRange) { 1.11 + // aRange is always non-null here, since a check happened previously. 1.12 + let viewport = BrowserApp.selectedTab.getViewport(); 1.13 + let fudge = 15; // Add a bit of fudge. 1.14 + let boundingElement = aRange.offsetNode; 1.15 + while (!boundingElement.getBoundingClientRect && boundingElement.parentNode) { 1.16 + boundingElement = boundingElement.parentNode; 1.17 + } 1.18 + 1.19 + let rect = ElementTouchHelper.getBoundingContentRect(boundingElement); 1.20 + let drRect = aRange.getClientRect(); 1.21 + let scrollTop = 1.22 + BrowserApp.selectedBrowser.contentDocument.documentElement.scrollTop || 1.23 + BrowserApp.selectedBrowser.contentDocument.body.scrollTop; 1.24 + 1.25 + // We subtract half the height of the viewport so that we can (ideally) 1.26 + // center the area of interest on the screen. 1.27 + let topPos = scrollTop + drRect.top - (viewport.cssHeight / 2.0); 1.28 + 1.29 + // Factor in the border and padding 1.30 + let boundingStyle = window.getComputedStyle(boundingElement); 1.31 + let leftAdjustment = parseInt(boundingStyle.paddingLeft) + 1.32 + parseInt(boundingStyle.borderLeftWidth); 1.33 + 1.34 + BrowserApp.selectedTab._mReflozPositioned = true; 1.35 + 1.36 + rect.type = "Browser:ZoomToRect"; 1.37 + rect.x = Math.max(viewport.cssPageLeft, rect.x - fudge + leftAdjustment); 1.38 + rect.y = Math.max(topPos, viewport.cssPageTop); 1.39 + rect.w = viewport.cssWidth; 1.40 + rect.h = viewport.cssHeight; 1.41 + rect.animate = false; 1.42 + 1.43 + sendMessageToJava(rect); 1.44 + BrowserApp.selectedTab._mReflozPoint = null; 1.45 + }, 1.46 + 1.47 + zoomOut: function() { 1.48 + BrowserEventHandler.resetMaxLineBoxWidth(); 1.49 + sendMessageToJava({ type: "Browser:ZoomToPageWidth" }); 1.50 + }, 1.51 + 1.52 + isRectZoomedIn: function(aRect, aViewport) { 1.53 + // This function checks to see if the area of the rect visible in the 1.54 + // viewport (i.e. the "overlapArea" variable below) is approximately 1.55 + // the max area of the rect we can show. It also checks that the rect 1.56 + // is actually on-screen by testing the left and right edges of the rect. 1.57 + // In effect, this tells us whether or not zooming in to this rect 1.58 + // will significantly change what the user is seeing. 1.59 + const minDifference = -20; 1.60 + const maxDifference = 20; 1.61 + const maxZoomAllowed = 4; // keep this in sync with mobile/android/base/ui/PanZoomController.MAX_ZOOM 1.62 + 1.63 + let vRect = new Rect(aViewport.cssX, aViewport.cssY, aViewport.cssWidth, aViewport.cssHeight); 1.64 + let overlap = vRect.intersect(aRect); 1.65 + let overlapArea = overlap.width * overlap.height; 1.66 + let availHeight = Math.min(aRect.width * vRect.height / vRect.width, aRect.height); 1.67 + let showing = overlapArea / (aRect.width * availHeight); 1.68 + let dw = (aRect.width - vRect.width); 1.69 + let dx = (aRect.x - vRect.x); 1.70 + 1.71 + if (fuzzyEquals(aViewport.zoom, maxZoomAllowed) && overlap.width / aRect.width > 0.9) { 1.72 + // we're already at the max zoom and the block is not spilling off the side of the screen so that even 1.73 + // 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 1.74 + return true; 1.75 + } 1.76 + 1.77 + return (showing > 0.9 && 1.78 + dx > minDifference && dx < maxDifference && 1.79 + dw > minDifference && dw < maxDifference); 1.80 + }, 1.81 + 1.82 + /* Zoom to an element, optionally keeping a particular part of it 1.83 + * in view if it is really tall. 1.84 + */ 1.85 + zoomToElement: function(aElement, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true) { 1.86 + let rect = ElementTouchHelper.getBoundingContentRect(aElement); 1.87 + ZoomHelper.zoomToRect(rect, aClickY, aCanZoomOut, aCanScrollHorizontally, aElement); 1.88 + }, 1.89 + 1.90 + zoomToRect: function(aRect, aClickY = -1, aCanZoomOut = true, aCanScrollHorizontally = true, aElement) { 1.91 + const margin = 15; 1.92 + 1.93 + if(!aRect.h || !aRect.w) { 1.94 + aRect.h = aRect.height; 1.95 + aRect.w = aRect.width; 1.96 + } 1.97 + 1.98 + let viewport = BrowserApp.selectedTab.getViewport(); 1.99 + let bRect = new Rect(aCanScrollHorizontally ? Math.max(viewport.cssPageLeft, aRect.x - margin) : viewport.cssX, 1.100 + aRect.y, 1.101 + aCanScrollHorizontally ? aRect.w + 2 * margin : viewport.cssWidth, 1.102 + aRect.h); 1.103 + // constrict the rect to the screen's right edge 1.104 + bRect.width = Math.min(bRect.width, viewport.cssPageRight - bRect.x); 1.105 + 1.106 + // if the rect is already taking up most of the visible area and is stretching the 1.107 + // width of the page, then we want to zoom out instead. 1.108 + if (aElement) { 1.109 + if (BrowserEventHandler.mReflozPref) { 1.110 + let zoomFactor = BrowserApp.selectedTab.getZoomToMinFontSize(aElement); 1.111 + 1.112 + bRect.width = zoomFactor <= 1.0 ? bRect.width : gScreenWidth / zoomFactor; 1.113 + bRect.height = zoomFactor <= 1.0 ? bRect.height : bRect.height / zoomFactor; 1.114 + if (zoomFactor == 1.0 || ZoomHelper.isRectZoomedIn(bRect, viewport)) { 1.115 + if (aCanZoomOut) { 1.116 + ZoomHelper.zoomOut(); 1.117 + } 1.118 + return; 1.119 + } 1.120 + } else if (ZoomHelper.isRectZoomedIn(bRect, viewport)) { 1.121 + if (aCanZoomOut) { 1.122 + ZoomHelper.zoomOut(); 1.123 + } 1.124 + return; 1.125 + } 1.126 + } 1.127 + 1.128 + let rect = {}; 1.129 + 1.130 + rect.type = "Browser:ZoomToRect"; 1.131 + rect.x = bRect.x; 1.132 + rect.y = bRect.y; 1.133 + rect.w = bRect.width; 1.134 + rect.h = Math.min(bRect.width * viewport.cssHeight / viewport.cssWidth, bRect.height); 1.135 + 1.136 + if (aClickY >= 0) { 1.137 + // if the block we're zooming to is really tall, and we want to keep a particular 1.138 + // part of it in view, then adjust the y-coordinate of the target rect accordingly. 1.139 + // the 1.2 multiplier is just a little fuzz to compensate for bRect including horizontal 1.140 + // margins but not vertical ones. 1.141 + let cssTapY = viewport.cssY + aClickY; 1.142 + if ((bRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) { 1.143 + rect.y = cssTapY - (rect.h / 2); 1.144 + } 1.145 + } 1.146 + 1.147 + if (rect.w > viewport.cssWidth || rect.h > viewport.cssHeight) { 1.148 + BrowserEventHandler.resetMaxLineBoxWidth(); 1.149 + } 1.150 + 1.151 + sendMessageToJava(rect); 1.152 + }, 1.153 +};