예제 #1
0
void
AndroidGeckoLayerClient::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
                                          bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
                                          bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
{
    NS_ASSERTION(!isNull(), "SyncFrameMetrics called on null layer client!");
    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
    if (!env)
        return;

    AutoLocalJNIFrame jniFrame(env);

    // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
    LayerRect dpUnrounded = aDisplayPort * aDisplayResolution;
    dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint());
    LayerIntRect dp = gfx::RoundedToInt(dpUnrounded);

    jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncFrameMetricsMethod,
            aScrollOffset.x, aScrollOffset.y, aZoom,
            aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
            aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
            aIsFirstPaint);

    if (jniFrame.CheckForException())
        return;

    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");

    AndroidViewTransform viewTransform;
    viewTransform.Init(viewTransformJObj);
    viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins);
    aOffset.x = viewTransform.GetOffsetX(env);
    aOffset.y = viewTransform.GetOffsetY(env);
}
void
AndroidCompositorWidget::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset,
                                          const CSSToParentLayerScale& aZoom,
                                          const CSSRect& aCssPageRect,
                                          const CSSRect& aDisplayPort,
                                          const CSSToLayerScale& aPaintedResolution,
                                          bool aLayersUpdated,
                                          int32_t aPaintSyncId,
                                          ScreenMargin& aFixedLayerMargins)
{
    auto layerClient = static_cast<nsWindow*>(RealWidget())->GetLayerClient();
    if (!layerClient) {
        return;
    }

    // convert the displayport rect from document-relative CSS pixels to
    // document-relative device pixels
    LayerIntRect dp = gfx::RoundedToInt(aDisplayPort * aPaintedResolution);

    java::ViewTransform::LocalRef viewTransform = layerClient->SyncFrameMetrics(
            aScrollOffset.x, aScrollOffset.y, aZoom.scale,
            aCssPageRect.x, aCssPageRect.y,
            aCssPageRect.XMost(), aCssPageRect.YMost(),
            dp.x, dp.y, dp.width, dp.height,
            aPaintedResolution.scale, aLayersUpdated, aPaintSyncId);

    MOZ_ASSERT(viewTransform, "No view transform object!");

    aFixedLayerMargins.top = viewTransform->FixedLayerMarginTop();
    aFixedLayerMargins.right = viewTransform->FixedLayerMarginRight();
    aFixedLayerMargins.bottom = viewTransform->FixedLayerMarginBottom();
    aFixedLayerMargins.left = viewTransform->FixedLayerMarginLeft();
}
예제 #3
0
void
AndroidGeckoLayerClient::SetPageRect(const CSSRect& aCssPageRect)
{
    NS_ASSERTION(!isNull(), "SetPageRect called on null layer client!");
    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
    if (!env)
        return;

    AutoLocalJNIFrame jniFrame(env, 0);
    return env->CallVoidMethod(wrapped_obj, jSetPageRect,
                               aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}
예제 #4
0
void
AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect)
{
    NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!");
    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
    if (!env)
        return;

    AutoLocalJNIFrame jniFrame(env, 0);
    return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom.scale,
                               aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}
void
AndroidCompositorWidget::SetFirstPaintViewport(const LayerIntPoint& aOffset,
                                               const CSSToLayerScale& aZoom,
                                               const CSSRect& aCssPageRect)
{
    auto layerClient = static_cast<nsWindow*>(RealWidget())->GetLayerClient();
    if (!layerClient) {
        return;
    }

    layerClient->SetFirstPaintViewport(
            float(aOffset.x), float(aOffset.y), aZoom.scale, aCssPageRect.x,
            aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}
예제 #6
0
static void
MaybeAlignAndClampDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics,
                              const CSSPoint& aActualScrollOffset)
{
  // Correct the display-port by the difference between the requested scroll
  // offset and the resulting scroll offset after setting the requested value.
  CSSRect& displayPort = aFrameMetrics.mDisplayPort;
  displayPort += aFrameMetrics.mScrollOffset - aActualScrollOffset;

  // Expand the display port to the next tile boundaries, if tiled thebes layers
  // are enabled.
  if (gfxPlatform::GetPrefLayersEnableTiles()) {
    displayPort =
      ExpandDisplayPortToTileBoundaries(displayPort + aActualScrollOffset,
                                        aFrameMetrics.LayersPixelsPerCSSPixel())
      - aActualScrollOffset;
  }

  // Finally, clamp the display port to the expanded scrollable rect.
  CSSRect scrollableRect = aFrameMetrics.GetExpandedScrollableRect();
  displayPort = scrollableRect.Intersect(displayPort + aActualScrollOffset)
    - aActualScrollOffset;
}
예제 #7
0
void CheckerboardEvent::LogInfo(RendertraceProperty aProperty,
                                const TimeStamp& aTimestamp,
                                const CSSRect& aRect,
                                const std::string& aExtraInfo,
                                const MonitorAutoLock& aProofOfLock) {
  MOZ_ASSERT(mRecordTrace);
  if (mRendertraceInfo.tellp() >= LOG_LENGTH_LIMIT) {
    // The log is already long enough, don't put more things into it. We'll
    // append a truncation message when this event ends.
    return;
  }
  // The log is consumed by the page at
  // http://people.mozilla.org/~kgupta/rendertrace.html and will move to
  // about:checkerboard in bug 1238042. The format is not formally specced, but
  // an informal description can be found at
  // https://github.com/staktrace/rendertrace/blob/master/index.html#L30
  mRendertraceInfo << "RENDERTRACE "
                   << (aTimestamp - mOriginTime).ToMilliseconds() << " rect "
                   << sColors[aProperty] << " " << aRect.X() << " " << aRect.Y()
                   << " " << aRect.Width() << " " << aRect.Height() << " "
                   << "// " << sDescriptions[aProperty] << aExtraInfo
                   << std::endl;
}
예제 #8
0
static bool
IsRectZoomedIn(const CSSRect& aRect, const CSSRect& aCompositedArea)
{
  // This functions checks to see if the area of the rect visible in the
  // composition bounds (i.e. the overlapArea variable below) is approximately
  // the max area of the rect we can show.
  CSSRect overlap = aCompositedArea.Intersect(aRect);
  float overlapArea = overlap.width * overlap.height;
  float availHeight = std::min(aRect.width * aCompositedArea.height / aCompositedArea.width,
                               aRect.height);
  float showing = overlapArea / (aRect.width * availHeight);
  float ratioW = aRect.width / aCompositedArea.width;
  float ratioH = aRect.height / aCompositedArea.height;

  return showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9);
}
예제 #9
0
static float
GetDisplayportCoverage(const CSSRect& aDisplayPort,
                       const Matrix4x4& aTransformToScreen,
                       const IntRect& aScreenRect)
{
  Rect transformedDisplayport =
    aTransformToScreen.TransformBounds(aDisplayPort.ToUnknownRect());

  transformedDisplayport.RoundOut();
  IntRect displayport = IntRect(transformedDisplayport.x,
                                    transformedDisplayport.y,
                                    transformedDisplayport.width,
                                    transformedDisplayport.height);
  if (!displayport.Contains(aScreenRect)) {
    nsIntRegion coveredRegion;
    coveredRegion.And(aScreenRect, displayport);
    return coveredRegion.Area() / (float)(aScreenRect.width * aScreenRect.height);
  }

  return 1.0f;
}
예제 #10
0
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;
}