mobile/android/chrome/content/ZoomHelper.js

changeset 0
6474c204b198
     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 +};

mercurial