Example #1
0
void
AppendToString(std::stringstream& aStream, const FrameMetrics& m,
               const char* pfx, const char* sfx, bool detailed)
{
  aStream << pfx;
  AppendToString(aStream, m.GetCompositionBounds(), "{ [cb=");
  AppendToString(aStream, m.GetScrollableRect(), "] [sr=");
  AppendToString(aStream, m.GetScrollOffset(), "] [s=");
  if (m.GetDoSmoothScroll()) {
    AppendToString(aStream, m.GetSmoothScrollOffset(), "] [ss=");
  }
  AppendToString(aStream, m.GetDisplayPort(), "] [dp=");
  AppendToString(aStream, m.GetCriticalDisplayPort(), "] [cdp=");
  AppendToString(aStream, m.GetBackgroundColor(), "] [color=");
  if (!detailed) {
    AppendToString(aStream, m.GetScrollId(), "] [scrollId=");
    if (m.GetScrollParentId() != FrameMetrics::NULL_SCROLL_ID) {
      AppendToString(aStream, m.GetScrollParentId(), "] [scrollParent=");
    }
    if (m.IsRootContent()) {
      aStream << "] [rcd";
    }
    if (m.HasClipRect()) {
      AppendToString(aStream, m.ClipRect(), "] [clip=");
    }
    AppendToString(aStream, m.GetZoom(), "] [z=", "] }");
  } else {
    AppendToString(aStream, m.GetDisplayPortMargins(), " [dpm=");
    aStream << nsPrintfCString("] um=%d", m.GetUseDisplayPortMargins()).get();
    AppendToString(aStream, m.GetRootCompositionSize(), "] [rcs=");
    AppendToString(aStream, m.GetViewport(), "] [v=");
    aStream << nsPrintfCString("] [z=(ld=%.3f r=%.3f",
            m.GetDevPixelsPerCSSPixel().scale,
            m.GetPresShellResolution()).get();
    AppendToString(aStream, m.GetCumulativeResolution(), " cr=");
    AppendToString(aStream, m.GetZoom(), " z=");
    AppendToString(aStream, m.GetExtraResolution(), " er=");
    aStream << nsPrintfCString(")] [u=(%d %d %lu)",
            m.GetScrollOffsetUpdated(), m.GetDoSmoothScroll(),
            m.GetScrollGeneration()).get();
    AppendToString(aStream, m.GetScrollParentId(), "] [p=");
    aStream << nsPrintfCString("] [i=(%ld %lld %d)] }",
            m.GetPresShellId(), m.GetScrollId(), m.IsRootContent()).get();
  }
  aStream << sfx;
}
CSSRect
CalculateRectToZoomTo(const nsCOMPtr<nsIDocument>& aRootContentDocument,
                      const CSSPoint& aPoint)
{
  // Ensure the layout information we get is up-to-date.
  aRootContentDocument->FlushPendingNotifications(FlushType::Layout);

  // An empty rect as return value is interpreted as "zoom out".
  const CSSRect zoomOut;

  nsCOMPtr<nsIPresShell> shell = aRootContentDocument->GetShell();
  if (!shell) {
    return zoomOut;
  }

  nsIScrollableFrame* rootScrollFrame = shell->GetRootScrollFrameAsScrollable();
  if (!rootScrollFrame) {
    return zoomOut;
  }

  nsCOMPtr<dom::Element> element = ElementFromPoint(shell, aPoint);
  if (!element) {
    return zoomOut;
  }

  while (element && !ShouldZoomToElement(element)) {
    element = element->GetParentElement();
  }

  if (!element) {
    return zoomOut;
  }

  FrameMetrics metrics = nsLayoutUtils::CalculateBasicFrameMetrics(rootScrollFrame);
  CSSRect compositedArea(metrics.GetScrollOffset(), metrics.CalculateCompositedSizeInCssPixels());
  const CSSCoord margin = 15;
  CSSRect rect = nsLayoutUtils::GetBoundingContentRect(element, rootScrollFrame);

  // If the element is taller than the visible area of the page scale
  // the height of the |rect| so that it has the same aspect ratio as
  // the root frame.  The clipped |rect| is centered on the y value of
  // the touch point. This allows tall narrow elements to be zoomed.
  if (!rect.IsEmpty() && compositedArea.width > 0.0f) {
    const float widthRatio = rect.width / compositedArea.width;
    float targetHeight = compositedArea.height * widthRatio;
    if (widthRatio < 0.9 && targetHeight < rect.height) {
      const CSSPoint scrollPoint = CSSPoint::FromAppUnits(rootScrollFrame->GetScrollPosition());
      float newY = aPoint.y + scrollPoint.y - (targetHeight * 0.5f);
      if ((newY + targetHeight) > (rect.y + rect.height)) {
        rect.y += rect.height - targetHeight;
      } else if (newY > rect.y) {
        rect.y = newY;
      }
      rect.height = targetHeight;
    }
  }

  rect = CSSRect(std::max(metrics.GetScrollableRect().x, rect.x - margin),
                 rect.y,
                 rect.width + 2 * margin,
                 rect.height);
  // Constrict the rect to the screen's right edge
  rect.width = std::min(rect.width, metrics.GetScrollableRect().XMost() - rect.x);

  // 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 (IsRectZoomedIn(rect, compositedArea)) {
    return zoomOut;
  }

  CSSRect rounded(rect);
  rounded.Round();

  // 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 so that we center the actual point the user double-tapped
  // upon. This prevents flying to the top of the page when double-tapping
  // to zoom in (bug 761721). The 1.2 multiplier is just a little fuzz to
  // compensate for 'rect' including horizontal margins but not vertical ones.
  CSSCoord cssTapY = metrics.GetScrollOffset().y + aPoint.y;
  if ((rect.height > rounded.height) && (cssTapY > rounded.y + (rounded.height * 1.2))) {
    rounded.y = cssTapY - (rounded.height / 2);
  }

  return rounded;
}
Example #3
0
CSSRect
CalculateRectToZoomTo(const nsCOMPtr<nsIDocument>& aRootContentDocument,
                      const CSSPoint& aPoint)
{
  // Ensure the layout information we get is up-to-date.
  aRootContentDocument->FlushPendingNotifications(Flush_Layout);

  // An empty rect as return value is interpreted as "zoom out".
  const CSSRect zoomOut;

  nsCOMPtr<nsIPresShell> shell = aRootContentDocument->GetShell();
  if (!shell) {
    return zoomOut;
  }

  nsIScrollableFrame* rootScrollFrame = shell->GetRootScrollFrameAsScrollable();
  if (!rootScrollFrame) {
    return zoomOut;
  }

  nsCOMPtr<dom::Element> element = ElementFromPoint(shell, aPoint);
  if (!element) {
    return zoomOut;
  }

  while (element && !ShouldZoomToElement(element)) {
    element = element->GetParentElement();
  }

  if (!element) {
    return zoomOut;
  }

  FrameMetrics metrics = nsLayoutUtils::CalculateBasicFrameMetrics(rootScrollFrame);
  CSSRect compositedArea(metrics.GetScrollOffset(), metrics.CalculateCompositedSizeInCssPixels());
  const CSSCoord margin = 15;
  CSSRect rect = GetBoundingContentRect(shell, element, rootScrollFrame);
  rect = CSSRect(std::max(metrics.GetScrollableRect().x, rect.x - margin),
                 rect.y,
                 rect.width + 2 * margin,
                 rect.height);
  // Constrict the rect to the screen's right edge
  rect.width = std::min(rect.width, metrics.GetScrollableRect().XMost() - rect.x);

  // 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 (IsRectZoomedIn(rect, compositedArea)) {
    return zoomOut;
  }

  CSSRect rounded(rect);
  rounded.Round();

  // 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 so that we center the actual point the user double-tapped
  // upon. This prevents flying to the top of the page when double-tapping
  // to zoom in (bug 761721). The 1.2 multiplier is just a little fuzz to
  // compensate for 'rect' including horizontal margins but not vertical ones.
  CSSCoord cssTapY = metrics.GetScrollOffset().y + aPoint.y;
  if ((rect.height > rounded.height) && (cssTapY > rounded.y + (rounded.height * 1.2))) {
    rounded.y = cssTapY - (rounded.height / 2);
  }

  return rounded;
}