LCOV - code coverage report
Current view: top level - gfx/layers/apz/util - DoubleTapToZoom.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 72 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "DoubleTapToZoom.h"
       7             : 
       8             : #include <algorithm>  // for std::min, std::max
       9             : 
      10             : #include "mozilla/AlreadyAddRefed.h"
      11             : #include "mozilla/dom/Element.h"
      12             : #include "nsCOMPtr.h"
      13             : #include "nsIContent.h"
      14             : #include "nsIDocument.h"
      15             : #include "nsIDOMHTMLLIElement.h"
      16             : #include "nsIDOMHTMLQuoteElement.h"
      17             : #include "nsIDOMWindow.h"
      18             : #include "nsIFrame.h"
      19             : #include "nsIFrameInlines.h"
      20             : #include "nsIPresShell.h"
      21             : #include "nsLayoutUtils.h"
      22             : #include "nsStyleConsts.h"
      23             : 
      24             : namespace mozilla {
      25             : namespace layers {
      26             : 
      27             : // Returns the DOM element found at |aPoint|, interpreted as being relative to
      28             : // the root frame of |aShell|. If the point is inside a subdocument, returns
      29             : // an element inside the subdocument, rather than the subdocument element
      30             : // (and does so recursively).
      31             : // The implementation was adapted from nsDocument::ElementFromPoint(), with
      32             : // the notable exception that we don't pass nsLayoutUtils::IGNORE_CROSS_DOC
      33             : // to GetFrameForPoint(), so as to get the behaviour described above in the
      34             : // presence of subdocuments.
      35             : static already_AddRefed<dom::Element>
      36           0 : ElementFromPoint(const nsCOMPtr<nsIPresShell>& aShell,
      37             :                  const CSSPoint& aPoint)
      38             : {
      39           0 :   if (nsIFrame* rootFrame = aShell->GetRootFrame()) {
      40           0 :     if (nsIFrame* frame = nsLayoutUtils::GetFrameForPoint(rootFrame,
      41           0 :           CSSPoint::ToAppUnits(aPoint),
      42             :           nsLayoutUtils::IGNORE_PAINT_SUPPRESSION |
      43           0 :           nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME)) {
      44           0 :       while (frame && (!frame->GetContent() || frame->GetContent()->IsInAnonymousSubtree())) {
      45           0 :         frame = nsLayoutUtils::GetParentOrPlaceholderFor(frame);
      46             :       }
      47           0 :       nsIContent* content = frame->GetContent();
      48           0 :       if (content && !content->IsElement()) {
      49           0 :         content = content->GetParent();
      50             :       }
      51           0 :       if (content) {
      52           0 :         nsCOMPtr<dom::Element> result = content->AsElement();
      53           0 :         return result.forget();
      54             :       }
      55             :     }
      56             :   }
      57           0 :   return nullptr;
      58             : }
      59             : 
      60             : static bool
      61           0 : ShouldZoomToElement(const nsCOMPtr<dom::Element>& aElement) {
      62           0 :   if (nsIFrame* frame = aElement->GetPrimaryFrame()) {
      63           0 :     if (frame->GetDisplay() == StyleDisplay::Inline) {
      64           0 :       return false;
      65             :     }
      66             :   }
      67           0 :   if (aElement->IsAnyOfHTMLElements(nsGkAtoms::li, nsGkAtoms::q)) {
      68           0 :     return false;
      69             :   }
      70           0 :   return true;
      71             : }
      72             : 
      73             : static bool
      74           0 : IsRectZoomedIn(const CSSRect& aRect, const CSSRect& aCompositedArea)
      75             : {
      76             :   // This functions checks to see if the area of the rect visible in the
      77             :   // composition bounds (i.e. the overlapArea variable below) is approximately
      78             :   // the max area of the rect we can show.
      79           0 :   CSSRect overlap = aCompositedArea.Intersect(aRect);
      80           0 :   float overlapArea = overlap.width * overlap.height;
      81           0 :   float availHeight = std::min(aRect.width * aCompositedArea.height / aCompositedArea.width,
      82           0 :                                aRect.height);
      83           0 :   float showing = overlapArea / (aRect.width * availHeight);
      84           0 :   float ratioW = aRect.width / aCompositedArea.width;
      85           0 :   float ratioH = aRect.height / aCompositedArea.height;
      86             : 
      87           0 :   return showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9);
      88             : }
      89             : 
      90             : CSSRect
      91           0 : CalculateRectToZoomTo(const nsCOMPtr<nsIDocument>& aRootContentDocument,
      92             :                       const CSSPoint& aPoint)
      93             : {
      94             :   // Ensure the layout information we get is up-to-date.
      95           0 :   aRootContentDocument->FlushPendingNotifications(FlushType::Layout);
      96             : 
      97             :   // An empty rect as return value is interpreted as "zoom out".
      98           0 :   const CSSRect zoomOut;
      99             : 
     100           0 :   nsCOMPtr<nsIPresShell> shell = aRootContentDocument->GetShell();
     101           0 :   if (!shell) {
     102           0 :     return zoomOut;
     103             :   }
     104             : 
     105           0 :   nsIScrollableFrame* rootScrollFrame = shell->GetRootScrollFrameAsScrollable();
     106           0 :   if (!rootScrollFrame) {
     107           0 :     return zoomOut;
     108             :   }
     109             : 
     110           0 :   nsCOMPtr<dom::Element> element = ElementFromPoint(shell, aPoint);
     111           0 :   if (!element) {
     112           0 :     return zoomOut;
     113             :   }
     114             : 
     115           0 :   while (element && !ShouldZoomToElement(element)) {
     116           0 :     element = element->GetParentElement();
     117             :   }
     118             : 
     119           0 :   if (!element) {
     120           0 :     return zoomOut;
     121             :   }
     122             : 
     123           0 :   FrameMetrics metrics = nsLayoutUtils::CalculateBasicFrameMetrics(rootScrollFrame);
     124           0 :   CSSRect compositedArea(metrics.GetScrollOffset(), metrics.CalculateCompositedSizeInCssPixels());
     125           0 :   const CSSCoord margin = 15;
     126           0 :   CSSRect rect = nsLayoutUtils::GetBoundingContentRect(element, rootScrollFrame);
     127             : 
     128             :   // If the element is taller than the visible area of the page scale
     129             :   // the height of the |rect| so that it has the same aspect ratio as
     130             :   // the root frame.  The clipped |rect| is centered on the y value of
     131             :   // the touch point. This allows tall narrow elements to be zoomed.
     132           0 :   if (!rect.IsEmpty() && compositedArea.width > 0.0f) {
     133           0 :     const float widthRatio = rect.width / compositedArea.width;
     134           0 :     float targetHeight = compositedArea.height * widthRatio;
     135           0 :     if (widthRatio < 0.9 && targetHeight < rect.height) {
     136           0 :       const CSSPoint scrollPoint = CSSPoint::FromAppUnits(rootScrollFrame->GetScrollPosition());
     137           0 :       float newY = aPoint.y + scrollPoint.y - (targetHeight * 0.5f);
     138           0 :       if ((newY + targetHeight) > (rect.y + rect.height)) {
     139           0 :         rect.y += rect.height - targetHeight;
     140           0 :       } else if (newY > rect.y) {
     141           0 :         rect.y = newY;
     142             :       }
     143           0 :       rect.height = targetHeight;
     144             :     }
     145             :   }
     146             : 
     147           0 :   rect = CSSRect(std::max(metrics.GetScrollableRect().x, rect.x - margin),
     148             :                  rect.y,
     149           0 :                  rect.width + 2 * margin,
     150             :                  rect.height);
     151             :   // Constrict the rect to the screen's right edge
     152           0 :   rect.width = std::min(rect.width, metrics.GetScrollableRect().XMost() - rect.x);
     153             : 
     154             :   // If the rect is already taking up most of the visible area and is
     155             :   // stretching the width of the page, then we want to zoom out instead.
     156           0 :   if (IsRectZoomedIn(rect, compositedArea)) {
     157           0 :     return zoomOut;
     158             :   }
     159             : 
     160           0 :   CSSRect rounded(rect);
     161           0 :   rounded.Round();
     162             : 
     163             :   // If the block we're zooming to is really tall, and the user double-tapped
     164             :   // more than a screenful of height from the top of it, then adjust the
     165             :   // y-coordinate so that we center the actual point the user double-tapped
     166             :   // upon. This prevents flying to the top of the page when double-tapping
     167             :   // to zoom in (bug 761721). The 1.2 multiplier is just a little fuzz to
     168             :   // compensate for 'rect' including horizontal margins but not vertical ones.
     169           0 :   CSSCoord cssTapY = metrics.GetScrollOffset().y + aPoint.y;
     170           0 :   if ((rect.height > rounded.height) && (cssTapY > rounded.y + (rounded.height * 1.2))) {
     171           0 :     rounded.y = cssTapY - (rounded.height / 2);
     172             :   }
     173             : 
     174           0 :   return rounded;
     175             : }
     176             : 
     177             : }
     178             : }

Generated by: LCOV version 1.13