Bug 784908: Part 1: Change names of FrameMetrics variables to be more descriptive, add documentation, change some coordinate spaces. r=roc

This commit is contained in:
Doug Sherk 2012-09-28 22:16:34 -04:00
parent 021c26b6fe
commit c0e08ee726
15 changed files with 362 additions and 213 deletions

View File

@ -206,38 +206,38 @@ const ContentPanning = {
let metrics = data.json;
let displayPort = metrics.displayPort;
let screenWidth = metrics.screenSize.width;
let screenHeight = metrics.screenSize.height;
let compositionWidth = metrics.compositionBounds.width;
let compositionHeight = metrics.compositionBounds.height;
let x = metrics.x;
let y = metrics.y;
this._zoom = metrics.zoom;
this._viewport = new Rect(x, y,
screenWidth / metrics.zoom,
screenHeight / metrics.zoom);
compositionWidth / metrics.zoom,
compositionHeight / metrics.zoom);
this._cssPageRect = new Rect(metrics.cssPageRect.x,
metrics.cssPageRect.y,
metrics.cssPageRect.width,
metrics.cssPageRect.height);
let cwu = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
if (this._screenWidth != screenWidth || this._screenHeight != screenHeight) {
cwu.setCSSViewport(screenWidth, screenHeight);
this._screenWidth = screenWidth;
this._screenHeight = screenHeight;
if (this._compositionWidth != compositionWidth || this._compositionHeight != compositionHeight) {
cwu.setCSSViewport(compositionWidth, compositionHeight);
this._compositionWidth = compositionWidth;
this._compositionHeight = compositionHeight;
}
// Set scroll position
cwu.setScrollPositionClampingScrollPortSize(
screenWidth / metrics.zoom, screenHeight / metrics.zoom);
compositionWidth / metrics.zoom, compositionHeight / metrics.zoom);
content.scrollTo(x, y);
cwu.setResolution(displayPort.resolution, displayPort.resolution);
let element = null;
if (content.document && (element = content.document.documentElement)) {
cwu.setDisplayPortForElement(displayPort.left,
displayPort.top,
cwu.setDisplayPortForElement(displayPort.x,
displayPort.y,
displayPort.width,
displayPort.height,
element);
@ -272,7 +272,7 @@ const ContentPanning = {
let cssPageRect = this._cssPageRect;
let viewport = this._viewport;
let bRect = new Rect(Math.max(cssPageRect.left, rect.x - margin),
let bRect = new Rect(Math.max(cssPageRect.x, rect.x - margin),
rect.y,
rect.w + 2 * margin,
rect.h);

View File

@ -843,27 +843,29 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
}
nsCString data;
data += nsPrintfCString("{ \"x\" : %d", NS_lround(aFrameMetrics.mViewportScrollOffset.x));
data += nsPrintfCString(", \"y\" : %d", NS_lround(aFrameMetrics.mViewportScrollOffset.y));
data += nsPrintfCString("{ \"x\" : %d", NS_lround(aFrameMetrics.mScrollOffset.x));
data += nsPrintfCString(", \"y\" : %d", NS_lround(aFrameMetrics.mScrollOffset.y));
// We don't treat the x and y scales any differently for this
// semi-platform-specific code.
data += nsPrintfCString(", \"zoom\" : %f", aFrameMetrics.mResolution.width);
data += nsPrintfCString(", \"displayPort\" : ");
data += nsPrintfCString("{ \"left\" : %d", aFrameMetrics.mDisplayPort.X());
data += nsPrintfCString(", \"top\" : %d", aFrameMetrics.mDisplayPort.Y());
data += nsPrintfCString(", \"width\" : %d", aFrameMetrics.mDisplayPort.Width());
data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mDisplayPort.Height());
data += nsPrintfCString("{ \"x\" : %f", aFrameMetrics.mDisplayPort.x);
data += nsPrintfCString(", \"y\" : %f", aFrameMetrics.mDisplayPort.y);
data += nsPrintfCString(", \"width\" : %f", aFrameMetrics.mDisplayPort.width);
data += nsPrintfCString(", \"height\" : %f", aFrameMetrics.mDisplayPort.height);
data += nsPrintfCString(", \"resolution\" : %f", aFrameMetrics.mResolution.width);
data += nsPrintfCString(" }");
data += nsPrintfCString(", \"screenSize\" : ");
data += nsPrintfCString("{ \"width\" : %d", aFrameMetrics.mViewport.width);
data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mViewport.height);
data += nsPrintfCString(", \"compositionBounds\" : ");
data += nsPrintfCString("{ \"x\" : %d", aFrameMetrics.mCompositionBounds.x);
data += nsPrintfCString(", \"y\" : %d", aFrameMetrics.mCompositionBounds.y);
data += nsPrintfCString(", \"width\" : %d", aFrameMetrics.mCompositionBounds.width);
data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mCompositionBounds.height);
data += nsPrintfCString(" }");
data += nsPrintfCString(", \"cssPageRect\" : ");
data += nsPrintfCString("{ \"x\" : %f", aFrameMetrics.mCSSContentRect.x);
data += nsPrintfCString(", \"y\" : %f", aFrameMetrics.mCSSContentRect.y);
data += nsPrintfCString(", \"width\" : %f", aFrameMetrics.mCSSContentRect.width);
data += nsPrintfCString(", \"height\" : %f", aFrameMetrics.mCSSContentRect.height);
data += nsPrintfCString("{ \"x\" : %f", aFrameMetrics.mScrollableRect.x);
data += nsPrintfCString(", \"y\" : %f", aFrameMetrics.mScrollableRect.y);
data += nsPrintfCString(", \"width\" : %f", aFrameMetrics.mScrollableRect.width);
data += nsPrintfCString(", \"height\" : %f", aFrameMetrics.mScrollableRect.height);
data += nsPrintfCString(" }");
data += nsPrintfCString(" }");

View File

@ -403,6 +403,21 @@ struct BaseRect {
width = right - x;
height = bottom - y;
}
// Scale 'this' by 1/aScale, converting coordinates to integers so that the result is
// the largest integer-coordinate rectangle contained by the unrounded result.
void ScaleInverseRoundIn(double aScale) { ScaleInverseRoundIn(aScale, aScale); }
// Scale 'this' by 1/aXScale and 1/aYScale, converting coordinates to integers so
// that the result is the largest integer-coordinate rectangle contained by the
// unrounded result.
void ScaleInverseRoundIn(double aXScale, double aYScale)
{
T right = static_cast<T>(floor(double(XMost()) / aXScale));
T bottom = static_cast<T>(floor(double(YMost()) / aYScale));
x = static_cast<T>(ceil(double(x) / aXScale));
y = static_cast<T>(ceil(double(y) / aYScale));
width = gfx_max<T>(0, right - x);
height = gfx_max<T>(0, bottom - y);
}
/**
* Clamp aPoint to this rectangle. It is allowed to end up on any

View File

@ -30,12 +30,15 @@ public:
// will begin at.
FrameMetrics()
: mViewport(0, 0, 0, 0)
: mCompositionBounds(0, 0, 0, 0)
, mContentRect(0, 0, 0, 0)
, mViewportScrollOffset(0, 0)
, mDisplayPort(0, 0, 0, 0)
, mViewport(0, 0, 0, 0)
, mScrollOffset(0, 0)
, mScrollId(NULL_SCROLL_ID)
, mCSSContentRect(0, 0, 0, 0)
, mScrollableRect(0, 0, 0, 0)
, mResolution(1, 1)
, mDevPixelsPerCSSPixel(1)
, mMayHaveTouchListeners(false)
{}
@ -44,7 +47,7 @@ public:
bool operator==(const FrameMetrics& aOther) const
{
return (mViewport.IsEqualEdges(aOther.mViewport) &&
mViewportScrollOffset == aOther.mViewportScrollOffset &&
mScrollOffset == aOther.mScrollOffset &&
mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
mScrollId == aOther.mScrollId);
}
@ -68,21 +71,129 @@ public:
return mScrollId != NULL_SCROLL_ID;
}
// These are all in layer coordinate space.
nsIntRect mViewport;
gfxSize LayersPixelsPerCSSPixel() const
{
return mResolution * mDevPixelsPerCSSPixel;
}
gfx::Point GetScrollOffsetInLayerPixels() const
{
return gfx::Point(mScrollOffset.x * LayersPixelsPerCSSPixel().width,
mScrollOffset.y * LayersPixelsPerCSSPixel().height);
}
// ---------------------------------------------------------------------------
// The following metrics are all in widget space/device pixels.
//
// This is the area within the widget that we're compositing to, which means
// that it is the visible region of this frame. It is not relative to
// anything.
// So { 0, 0, [compositeArea.width], [compositeArea.height] }.
//
// This is useful because, on mobile, the viewport and composition dimensions
// are not always the same. In this case, we calculate the displayport using
// an area bigger than the region we're compositing to. If we used the
// viewport dimensions to calculate the displayport, we'd run into situations
// where we're prerendering the wrong regions and the content may be clipped,
// or too much of it prerendered. If the displayport is the same as the
// viewport, there is no need for this and we can just use the viewport
// instead.
//
// This is only valid on the root layer. Nested iframes do not need this
// metric as they do not have a displayport set. See bug 775452.
nsIntRect mCompositionBounds;
// |mScrollableRect|, stored in device pixels. DECPRECATED, DO NOT USE.
//
// This is valid on any layer where |mScrollableRect| is, though it may be
// more lazily maintained than |mScrollableRect|. That is, when
// |mScrollableRect| is updated, this may lag. For this reason, it's better to
// use |mScrollableRect| for any control logic.
//
// FIXME/bug 785929: Is this really necessary? Can it not be calculated from
// |mScrollableRect| whenever it's needed?
nsIntRect mContentRect;
gfx::Point mViewportScrollOffset;
nsIntRect mDisplayPort;
// ---------------------------------------------------------------------------
// The following metrics are all in CSS pixels. They are not in any uniform
// space, so each is explained separately.
//
// The area of a frame's contents that has been painted, relative to the
// viewport. It is in the same coordinate space as |mViewport|. For example,
// if it is at 0,0, then it's at the same place at the viewport, which is at
// the top-left in the layer, and at the same place as the scroll offset of
// the document.
//
// Note that this is structured in such a way that it doesn't depend on the
// method layout uses to scroll content.
//
// May be larger or smaller than |mScrollableRect|.
//
// To pre-render a margin of 100 CSS pixels around the window,
// { x = -100, y = - 100,
// width = window.innerWidth + 100, height = window.innerHeight + 100 }
//
// This is only valid on the root layer. Nested iframes do not have a
// displayport set on them. See bug 775452.
gfx::Rect mDisplayPort;
// The CSS viewport, which is the dimensions we're using to constrain the
// <html> element of this frame, relative to the top-left of the layer. Note
// that its offset is structured in such a way that it doesn't depend on the
// method layout uses to scroll content.
//
// This is mainly useful on the root layer, however nested iframes can have
// their own viewport, which will just be the size of the window of the
// iframe. For layers that don't correspond to a document, this metric is
// meaningless and invalid.
gfx::Rect mViewport;
// The position of the top-left of the CSS viewport, relative to the document
// (or the document relative to the viewport, if that helps understand it).
//
// Thus it is relative to the document. It is in the same coordinate space as
// |mScrollableRect|, but a different coordinate space than |mViewport| and
// |mDisplayPort|.
//
// It is required that the rect:
// { x = mScrollOffset.x, y = mScrollOffset.y,
// width = mCompositionBounds.x / mResolution.width,
// height = mCompositionBounds.y / mResolution.height }
// Be within |mScrollableRect|.
//
// This is valid for any layer, but is always relative to this frame and
// not any parents, regardless of parent transforms.
gfx::Point mScrollOffset;
// A unique ID assigned to each scrollable frame (unless this is
// ROOT_SCROLL_ID, in which case it is not unique).
ViewID mScrollId;
// Consumers often want to know the origin/size before scaling to pixels
// so we record this as well.
gfx::Rect mCSSContentRect;
// The scrollable bounds of a frame. This is determined by reflow.
// For the top-level |window|,
// { x = window.scrollX, y = window.scrollY, // could be 0, 0
// width = window.innerWidth, height = window.innerHeight }
//
// This is relative to the document. It is in the same coordinate space as
// |mScrollOffset|, but a different coordinate space than |mViewport| and
// |mDisplayPort|. Note also that this coordinate system is understood by
// window.scrollTo().
//
// This is valid on any layer unless it has no content.
gfx::Rect mScrollableRect;
// This represents the resolution at which the associated layer
// will been rendered.
gfxSize mResolution;
// The conversion factor between CSS pixels and device pixels for this frame.
// This can vary based on a variety of things, such as reflowing-zoom. The
// conversion factor for device pixels to layers pixels is just the
// resolution.
float mDevPixelsPerCSSPixel;
// Whether or not this frame may have touch listeners.
bool mMayHaveTouchListeners;
};

View File

@ -143,6 +143,17 @@ AppendToString(nsACString& s, const nsIntRect& r,
return s += sfx;
}
nsACString&
AppendToString(nsACString& s, const Rect& r,
const char* pfx="", const char* sfx="")
{
s += pfx;
s.AppendPrintf(
"(x=%f, y=%f, w=%f, h=%f)",
r.x, r.y, r.width, r.height);
return s += sfx;
}
nsACString&
AppendToString(nsACString& s, const nsIntRegion& r,
const char* pfx="", const char* sfx="")
@ -173,7 +184,7 @@ AppendToString(nsACString& s, const FrameMetrics& m,
{
s += pfx;
AppendToString(s, m.mViewport, "{ viewport=");
AppendToString(s, m.mViewportScrollOffset, " viewportScroll=");
AppendToString(s, m.mScrollOffset, " viewportScroll=");
AppendToString(s, m.mDisplayPort, " displayport=");
AppendToString(s, m.mScrollId, " scrollId=", " }");
return s += sfx;

View File

@ -253,7 +253,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
Layer* primaryScrollable = BasicManager()->GetPrimaryScrollableLayer();
if (primaryScrollable) {
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
scrollOffset = metrics.mViewportScrollOffset;
scrollOffset = metrics.mScrollOffset;
}
int32_t scrollDiffX = scrollOffset.x - mLastScrollOffset.x;
int32_t scrollDiffY = scrollOffset.y - mLastScrollOffset.y;

View File

@ -138,10 +138,10 @@ AsyncPanZoomController::ReceiveInputEvent(const nsInputEvent& aEvent,
{
MonitorAutoLock monitor(mMonitor);
currentZoom = mFrameMetrics.mResolution.width;
currentScrollOffset = gfx::Point(mFrameMetrics.mViewportScrollOffset.x,
mFrameMetrics.mViewportScrollOffset.y);
lastScrollOffset = gfx::Point(mLastContentPaintMetrics.mViewportScrollOffset.x,
mLastContentPaintMetrics.mViewportScrollOffset.y);
currentScrollOffset = gfx::Point(mFrameMetrics.mScrollOffset.x,
mFrameMetrics.mScrollOffset.y);
lastScrollOffset = gfx::Point(mLastContentPaintMetrics.mScrollOffset.x,
mLastContentPaintMetrics.mScrollOffset.y);
}
nsEventStatus status;
@ -669,10 +669,10 @@ void AsyncPanZoomController::SetCompositorParent(CompositorParent* aCompositorPa
}
void AsyncPanZoomController::ScrollBy(const gfx::Point& aOffset) {
gfx::Point newOffset(mFrameMetrics.mViewportScrollOffset.x + aOffset.x,
mFrameMetrics.mViewportScrollOffset.y + aOffset.y);
gfx::Point newOffset(mFrameMetrics.mScrollOffset.x + aOffset.x,
mFrameMetrics.mScrollOffset.y + aOffset.y);
FrameMetrics metrics(mFrameMetrics);
metrics.mViewportScrollOffset = newOffset;
metrics.mScrollOffset = newOffset;
mFrameMetrics = metrics;
}
@ -682,12 +682,12 @@ void AsyncPanZoomController::SetPageRect(const gfx::Rect& aCSSPageRect) {
float scale = mFrameMetrics.mResolution.width;
// The page rect is the css page rect scaled by the current zoom.
pageSize.ScaleRoundOut(1 / scale);
pageSize.ScaleInverseRoundOut(scale);
// Round the page rect so we don't get any truncation, then get the nsIntRect
// from this.
metrics.mContentRect = nsIntRect(pageSize.x, pageSize.y, pageSize.width, pageSize.height);
metrics.mCSSContentRect = aCSSPageRect;
metrics.mScrollableRect = aCSSPageRect;
mFrameMetrics = metrics;
}
@ -703,19 +703,19 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFoc
// Force a recalculation of the page rect based on the new zoom and the
// current CSS page rect (which is unchanged since it's not affected by zoom).
SetPageRect(mFrameMetrics.mCSSContentRect);
SetPageRect(mFrameMetrics.mScrollableRect);
gfx::Point scrollOffset = metrics.mViewportScrollOffset;
gfx::Point scrollOffset = metrics.mScrollOffset;
scrollOffset.x += float(aFocus.x) * (scaleFactor - 1.0f) / oldScale;
scrollOffset.y += float(aFocus.y) * (scaleFactor - 1.0f) / oldScale;
metrics.mViewportScrollOffset = scrollOffset;
metrics.mScrollOffset = scrollOffset;
mFrameMetrics = metrics;
}
bool AsyncPanZoomController::EnlargeDisplayPortAlongAxis(float aViewport,
bool AsyncPanZoomController::EnlargeDisplayPortAlongAxis(float aCompositionBounds,
float aVelocity,
float* aDisplayPortOffset,
float* aDisplayPortLength)
@ -724,77 +724,50 @@ bool AsyncPanZoomController::EnlargeDisplayPortAlongAxis(float aViewport,
const float MAX_SKATE_SIZE_MULTIPLIER = 4.0f;
if (fabsf(aVelocity) > MIN_SKATE_SPEED) {
*aDisplayPortLength = aViewport * clamped(fabsf(aVelocity),
*aDisplayPortLength = aCompositionBounds * clamped(fabsf(aVelocity),
MIN_SKATE_SIZE_MULTIPLIER, MAX_SKATE_SIZE_MULTIPLIER);
*aDisplayPortOffset = aVelocity > 0 ? 0 : aViewport - *aDisplayPortLength;
*aDisplayPortOffset = aVelocity > 0 ? 0 : aCompositionBounds - *aDisplayPortLength;
return true;
}
return false;
}
const nsIntRect AsyncPanZoomController::CalculatePendingDisplayPort() {
const gfx::Rect AsyncPanZoomController::CalculatePendingDisplayPort() {
float scale = mFrameMetrics.mResolution.width;
nsIntRect viewport = mFrameMetrics.mViewport;
viewport.ScaleRoundIn(1 / scale);
nsIntRect compositionBounds = mFrameMetrics.mCompositionBounds;
compositionBounds.ScaleInverseRoundIn(scale);
gfx::Point scrollOffset = mFrameMetrics.mViewportScrollOffset;
gfx::Point scrollOffset = mFrameMetrics.mScrollOffset;
gfx::Point velocity = GetVelocityVector();
// The displayport is relative to the current scroll offset. Here's a little
// diagram to make it easier to see:
//
// - - - -
// | |
// *************
// * | | *
// - -*- @------ -*- -
// | * |=====| * |
// * |=====| *
// | * |=====| * |
// - -*- ------- -*- -
// * | | *
// *************
// | |
// - - - -
//
// The full --- area with === inside it is the actual viewport rect, the *** area
// is the displayport, and the - - - area is an imaginary additional page on all 4
// borders of the actual page. Notice that the displayport intersects half-way with
// each of the imaginary extra pages. The @ symbol at the top left of the
// viewport marks the current scroll offset. From the @ symbol to the far left
// and far top, it is clear that this distance is 1/4 of the displayport's
// height/width dimension.
const float STATIONARY_SIZE_MULTIPLIER = 2.0f;
gfx::Rect displayPort(0, 0,
viewport.width * STATIONARY_SIZE_MULTIPLIER,
viewport.height * STATIONARY_SIZE_MULTIPLIER);
compositionBounds.width * STATIONARY_SIZE_MULTIPLIER,
compositionBounds.height * STATIONARY_SIZE_MULTIPLIER);
// If there's motion along an axis of movement, and it's above a threshold,
// then we want to paint a larger area in the direction of that motion so that
// it's less likely to checkerboard.
bool enlargedX = EnlargeDisplayPortAlongAxis(
viewport.width, velocity.x, &displayPort.x, &displayPort.width);
compositionBounds.width, velocity.x, &displayPort.x, &displayPort.width);
bool enlargedY = EnlargeDisplayPortAlongAxis(
viewport.height, velocity.y, &displayPort.y, &displayPort.height);
compositionBounds.height, velocity.y, &displayPort.y, &displayPort.height);
if (!enlargedX && !enlargedY) {
displayPort.x = -displayPort.width / 4;
displayPort.y = -displayPort.height / 4;
} else if (!enlargedX) {
displayPort.width = viewport.width;
displayPort.width = compositionBounds.width;
} else if (!enlargedY) {
displayPort.height = viewport.height;
displayPort.height = compositionBounds.height;
}
gfx::Rect shiftedDisplayPort = displayPort;
shiftedDisplayPort.MoveBy(scrollOffset.x, scrollOffset.y);
displayPort = shiftedDisplayPort.Intersect(mFrameMetrics.mCSSContentRect);
displayPort = shiftedDisplayPort.Intersect(mFrameMetrics.mScrollableRect);
displayPort.MoveBy(-scrollOffset.x, -scrollOffset.y);
// Round the displayport so we don't get any truncation, then get the nsIntRect
// from this.
displayPort.Round();
return nsIntRect(displayPort.x, displayPort.y, displayPort.width, displayPort.height);
return displayPort;
}
void AsyncPanZoomController::SetDPI(int aDPI) {
@ -814,22 +787,13 @@ void AsyncPanZoomController::ScheduleComposite() {
void AsyncPanZoomController::RequestContentRepaint() {
mFrameMetrics.mDisplayPort = CalculatePendingDisplayPort();
gfx::Point oldScrollOffset = mLastPaintRequestMetrics.mViewportScrollOffset,
newScrollOffset = mFrameMetrics.mViewportScrollOffset;
gfx::Point oldScrollOffset = mLastPaintRequestMetrics.mScrollOffset,
newScrollOffset = mFrameMetrics.mScrollOffset;
// If we're trying to paint what we already think is painted, discard this
// request since it's a pointless paint.
nsRect oldDisplayPort = nsRect(
mLastPaintRequestMetrics.mDisplayPort.x,
mLastPaintRequestMetrics.mDisplayPort.y,
mLastPaintRequestMetrics.mDisplayPort.width,
mLastPaintRequestMetrics.mDisplayPort.height);
gfx::Rect newDisplayPort = gfx::Rect(
mFrameMetrics.mDisplayPort.x,
mFrameMetrics.mDisplayPort.y,
mFrameMetrics.mDisplayPort.width,
mFrameMetrics.mDisplayPort.height);
gfx::Rect oldDisplayPort = mLastPaintRequestMetrics.mDisplayPort;
gfx::Rect newDisplayPort = mFrameMetrics.mDisplayPort;
oldDisplayPort.MoveBy(oldScrollOffset.x, oldScrollOffset.y);
newDisplayPort.MoveBy(newScrollOffset.x, newScrollOffset.y);
@ -892,11 +856,11 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
mEndZoomToMetrics.mResolution.width * sampledPosition +
mStartZoomToMetrics.mResolution.width * (1 - sampledPosition);
mFrameMetrics.mViewportScrollOffset = gfx::Point(
mEndZoomToMetrics.mViewportScrollOffset.x * sampledPosition +
mStartZoomToMetrics.mViewportScrollOffset.x * (1 - sampledPosition),
mEndZoomToMetrics.mViewportScrollOffset.y * sampledPosition +
mStartZoomToMetrics.mViewportScrollOffset.y * (1 - sampledPosition)
mFrameMetrics.mScrollOffset = gfx::Point(
mEndZoomToMetrics.mScrollOffset.x * sampledPosition +
mStartZoomToMetrics.mScrollOffset.x * (1 - sampledPosition),
mEndZoomToMetrics.mScrollOffset.y * sampledPosition +
mStartZoomToMetrics.mScrollOffset.y * (1 - sampledPosition)
);
requestAnimationFrame = true;
@ -920,10 +884,10 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
localScaleY = mFrameMetrics.mResolution.height;
if (frame.IsScrollable()) {
metricsScrollOffset = frame.mViewportScrollOffset;
metricsScrollOffset = frame.GetScrollOffsetInLayerPixels();
}
scrollOffset = mFrameMetrics.mViewportScrollOffset;
scrollOffset = mFrameMetrics.mScrollOffset;
}
nsIntPoint scrollCompensation(
@ -974,8 +938,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
case WAITING_LISTENERS:
// FIXME/bug 784908: Scroll offset is stored in layer pixels in the rest
// of the layers code, but we want it in CSS pixels.
mFrameMetrics.mViewportScrollOffset =
aViewportFrame.mViewportScrollOffset / aViewportFrame.mResolution.width;
mFrameMetrics.mScrollOffset =
aViewportFrame.mScrollOffset / aViewportFrame.mResolution.width;
break;
// Don't clobber if we're in other states.
default:
@ -988,10 +952,15 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
mX.CancelTouch();
mY.CancelTouch();
// The composition bounds are not stored within the layers code, so we have
// to reset them back to what they were every time we overwrite them.
nsIntRect compositionBounds = mFrameMetrics.mCompositionBounds;
mFrameMetrics = aViewportFrame;
mFrameMetrics.mCompositionBounds = compositionBounds;
mFrameMetrics.mResolution.width = 1 / mFrameMetrics.mResolution.width;
mFrameMetrics.mResolution.height = 1 / mFrameMetrics.mResolution.height;
SetPageRect(mFrameMetrics.mCSSContentRect);
SetPageRect(mFrameMetrics.mScrollableRect);
// Bug 776413/fixme: Request a repaint as soon as a page is loaded so that
// we get a larger displayport. This is very bad because we're wasting a
@ -999,9 +968,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
RequestContentRepaint();
mState = NOTHING;
} else if (!mFrameMetrics.mCSSContentRect.IsEqualEdges(aViewportFrame.mCSSContentRect)) {
mFrameMetrics.mCSSContentRect = aViewportFrame.mCSSContentRect;
SetPageRect(mFrameMetrics.mCSSContentRect);
} else if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aViewportFrame.mScrollableRect)) {
mFrameMetrics.mScrollableRect = aViewportFrame.mScrollableRect;
SetPageRect(mFrameMetrics.mScrollableRect);
}
}
@ -1010,10 +979,10 @@ const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() {
return mFrameMetrics;
}
void AsyncPanZoomController::UpdateViewportSize(int aWidth, int aHeight) {
void AsyncPanZoomController::UpdateCompositionBounds(const nsIntRect& aCompositionBounds) {
MonitorAutoLock mon(mMonitor);
FrameMetrics metrics = GetFrameMetrics();
metrics.mViewport = nsIntRect(0, 0, aWidth, aHeight);
metrics.mCompositionBounds = aCompositionBounds;
mFrameMetrics = metrics;
}
@ -1032,27 +1001,29 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
{
MonitorAutoLock mon(mMonitor);
nsIntRect viewport = mFrameMetrics.mViewport;
gfx::Rect cssPageRect = mFrameMetrics.mCSSContentRect;
gfx::Point scrollOffset = mFrameMetrics.mViewportScrollOffset;
nsIntRect compositionBounds = mFrameMetrics.mCompositionBounds;
gfx::Rect cssPageRect = mFrameMetrics.mScrollableRect;
gfx::Point scrollOffset = mFrameMetrics.mScrollOffset;
// If the rect is empty, treat it as a request to zoom out to the full page
// size.
if (zoomToRect.IsEmpty()) {
nsIntRect cssViewport = viewport;
cssViewport.ScaleRoundIn(1 / mFrameMetrics.mResolution.width);
cssViewport.MoveBy(nsIntPoint(NS_lround(scrollOffset.x), NS_lround(scrollOffset.y)));
// composition bounds in CSS coordinates
nsIntRect cssCompositionBounds = compositionBounds;
cssCompositionBounds.ScaleInverseRoundIn(mFrameMetrics.mResolution.width);
cssCompositionBounds.MoveBy(scrollOffset.x, scrollOffset.y);
float y = mFrameMetrics.mViewportScrollOffset.y;
float newHeight = cssViewport.height * cssPageRect.width / cssViewport.width;
float dh = cssViewport.height - newHeight;
float y = mFrameMetrics.mScrollOffset.y;
float newHeight =
cssCompositionBounds.height * cssPageRect.width / cssCompositionBounds.width;
float dh = cssCompositionBounds.height - newHeight;
zoomToRect = gfx::Rect(0.0f,
y + dh/2,
cssPageRect.width,
y + dh/2 + newHeight);
} else {
float targetRatio = float(viewport.width) / float(viewport.height);
float targetRatio = float(compositionBounds.width) / float(compositionBounds.height);
float rectRatio = zoomToRect.width / zoomToRect.height;
if (fabsf(targetRatio - rectRatio) < EPSILON) {
@ -1073,24 +1044,24 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
}
mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height =
NS_MIN(viewport.width / zoomToRect.width, viewport.height / zoomToRect.height);
NS_MIN(compositionBounds.width / zoomToRect.width, compositionBounds.height / zoomToRect.height);
mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height =
clamped(mEndZoomToMetrics.mResolution.width, MIN_ZOOM, MAX_ZOOM);
// Recalculate the zoom to rect using the new dimensions.
zoomToRect.width = viewport.width / mEndZoomToMetrics.mResolution.width;
zoomToRect.height = viewport.height / mEndZoomToMetrics.mResolution.height;
zoomToRect.width = compositionBounds.width / mEndZoomToMetrics.mResolution.width;
zoomToRect.height = compositionBounds.height / mEndZoomToMetrics.mResolution.height;
// Clamp the zoom to rect to the CSS rect to make sure it fits.
zoomToRect = zoomToRect.Intersect(cssPageRect);
// Do one final recalculation to get the resolution.
mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height =
NS_MAX(viewport.width / zoomToRect.width, viewport.height / zoomToRect.height);
NS_MAX(compositionBounds.width / zoomToRect.width, compositionBounds.height / zoomToRect.height);
mStartZoomToMetrics = mFrameMetrics;
mEndZoomToMetrics.mViewportScrollOffset =
mEndZoomToMetrics.mScrollOffset =
gfx::Point(zoomToRect.x, zoomToRect.y);
mAnimationStartTime = TimeStamp::Now();

View File

@ -97,17 +97,13 @@ public:
nsInputEvent* aOutEvent);
/**
* Updates the viewport size, i.e. the dimensions of the frame (not
* necessarily the screen) content will actually be rendered onto in device
* pixels for example, a subframe will not take the entire screen, but we
* still want to know how big it is in device pixels. Ideally we want to be
* using CSS pixels everywhere inside here, but in this case we need to know
* how large of a displayport to set so we use these dimensions plus some
* extra.
*
* XXX: Use nsIntRect instead.
* Updates the composition bounds, i.e. the dimensions of the final size of
* the frame this is tied to during composition onto, in device pixels. In
* general, this will just be:
* { x = 0, y = 0, width = surface.width, height = surface.height }, however
* there is no hard requirement for this.
*/
void UpdateViewportSize(int aWidth, int aHeight);
void UpdateCompositionBounds(const nsIntRect& aCompositionBounds);
/**
* We have found a scrollable subframe, so disable our machinery until we hit
@ -350,7 +346,7 @@ protected:
* a larger area than the screen so that when you scroll down, you don't
* checkerboard immediately.
*/
const nsIntRect CalculatePendingDisplayPort();
const gfx::Rect CalculatePendingDisplayPort();
/**
* Attempts to enlarge the displayport along a single axis. Returns whether or
@ -360,7 +356,7 @@ protected:
* |aDisplayPortLength|. If enlarged, these will be updated with the new
* metrics.
*/
bool EnlargeDisplayPortAlongAxis(float aViewport, float aVelocity,
bool EnlargeDisplayPortAlongAxis(float aCompositionBounds, float aVelocity,
float* aDisplayPortOffset, float* aDisplayPortLength);
/**

View File

@ -140,12 +140,12 @@ bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta) {
}
Axis::Overscroll Axis::GetOverscroll() {
// If the current pan takes the viewport to the left of or above the current
// If the current pan takes the window to the left of or above the current
// page rect.
bool minus = GetOrigin() < GetPageStart();
// If the current pan takes the viewport to the right of or below the current
// If the current pan takes the window to the right of or below the current
// page rect.
bool plus = GetViewportEnd() > GetPageEnd();
bool plus = GetCompositionEnd() > GetPageEnd();
if (minus && plus) {
return OVERSCROLL_BOTH;
}
@ -161,19 +161,20 @@ Axis::Overscroll Axis::GetOverscroll() {
float Axis::GetExcess() {
switch (GetOverscroll()) {
case OVERSCROLL_MINUS: return GetOrigin() - GetPageStart();
case OVERSCROLL_PLUS: return GetViewportEnd() - GetPageEnd();
case OVERSCROLL_BOTH: return (GetViewportEnd() - GetPageEnd()) + (GetPageStart() - GetOrigin());
case OVERSCROLL_PLUS: return GetCompositionEnd() - GetPageEnd();
case OVERSCROLL_BOTH: return (GetCompositionEnd() - GetPageEnd()) +
(GetPageStart() - GetOrigin());
default: return 0;
}
}
Axis::Overscroll Axis::DisplacementWillOverscroll(int32_t aDisplacement) {
// If the current pan plus a displacement takes the viewport to the left of or
// If the current pan plus a displacement takes the window to the left of or
// above the current page rect.
bool minus = GetOrigin() + aDisplacement < GetPageStart();
// If the current pan plus a displacement takes the viewport to the right of or
// If the current pan plus a displacement takes the window to the right of or
// below the current page rect.
bool plus = GetViewportEnd() + aDisplacement > GetPageEnd();
bool plus = GetCompositionEnd() + aDisplacement > GetPageEnd();
if (minus && plus) {
return OVERSCROLL_BOTH;
}
@ -189,7 +190,7 @@ Axis::Overscroll Axis::DisplacementWillOverscroll(int32_t aDisplacement) {
float Axis::DisplacementWillOverscrollAmount(int32_t aDisplacement) {
switch (DisplacementWillOverscroll(aDisplacement)) {
case OVERSCROLL_MINUS: return (GetOrigin() + aDisplacement) - GetPageStart();
case OVERSCROLL_PLUS: return (GetViewportEnd() + aDisplacement) - GetPageEnd();
case OVERSCROLL_PLUS: return (GetCompositionEnd() + aDisplacement) - GetPageEnd();
// Don't handle overscrolled in both directions; a displacement can't cause
// this, it must have already been zoomed out too far.
default: return 0;
@ -201,7 +202,7 @@ Axis::Overscroll Axis::ScaleWillOverscroll(float aScale, int32_t aFocus) {
bool both = ScaleWillOverscrollBothSides(aScale);
bool minus = originAfterScale < GetPageStart() * aScale;
bool plus = (originAfterScale + GetViewportLength()) > GetPageEnd() * aScale;
bool plus = (originAfterScale + GetCompositionLength()) > GetPageEnd() * aScale;
if ((minus && plus) || both) {
return OVERSCROLL_BOTH;
@ -219,7 +220,8 @@ float Axis::ScaleWillOverscrollAmount(float aScale, int32_t aFocus) {
float originAfterScale = (GetOrigin() + aFocus) * aScale - aFocus;
switch (ScaleWillOverscroll(aScale, aFocus)) {
case OVERSCROLL_MINUS: return originAfterScale - GetPageStart() * aScale;
case OVERSCROLL_PLUS: return (originAfterScale + GetViewportLength()) - GetPageEnd() * aScale;
case OVERSCROLL_PLUS: return (originAfterScale + GetCompositionLength()) -
NS_lround(GetPageEnd() * aScale);
// Don't handle OVERSCROLL_BOTH. Client code is expected to deal with it.
default: return 0;
}
@ -229,8 +231,8 @@ float Axis::GetVelocity() {
return mVelocity;
}
float Axis::GetViewportEnd() {
return GetOrigin() + GetViewportLength();
float Axis::GetCompositionEnd() {
return GetOrigin() + GetCompositionLength();
}
float Axis::GetPageEnd() {
@ -238,40 +240,44 @@ float Axis::GetPageEnd() {
}
float Axis::GetOrigin() {
gfx::Point origin = mAsyncPanZoomController->GetFrameMetrics().mViewportScrollOffset;
gfx::Point origin = mAsyncPanZoomController->GetFrameMetrics().mScrollOffset;
return GetPointOffset(origin);
}
float Axis::GetViewportLength() {
nsIntRect viewport = mAsyncPanZoomController->GetFrameMetrics().mViewport;
gfx::Rect scaledViewport = gfx::Rect(viewport.x, viewport.y, viewport.width, viewport.height);
scaledViewport.ScaleRoundIn(1 / mAsyncPanZoomController->GetFrameMetrics().mResolution.width);
return GetRectLength(scaledViewport);
float Axis::GetCompositionLength() {
nsIntRect compositionBounds =
mAsyncPanZoomController->GetFrameMetrics().mCompositionBounds;
gfx::Rect scaledCompositionBounds =
gfx::Rect(compositionBounds.x, compositionBounds.y,
compositionBounds.width, compositionBounds.height);
scaledCompositionBounds.ScaleInverseRoundIn(
mAsyncPanZoomController->GetFrameMetrics().mResolution.width);
return GetRectLength(scaledCompositionBounds);
}
float Axis::GetPageStart() {
gfx::Rect pageRect = mAsyncPanZoomController->GetFrameMetrics().mCSSContentRect;
gfx::Rect pageRect = mAsyncPanZoomController->GetFrameMetrics().mScrollableRect;
return GetRectOffset(pageRect);
}
float Axis::GetPageLength() {
gfx::Rect pageRect = mAsyncPanZoomController->GetFrameMetrics().mCSSContentRect;
gfx::Rect pageRect = mAsyncPanZoomController->GetFrameMetrics().mScrollableRect;
return GetRectLength(pageRect);
}
bool Axis::ScaleWillOverscrollBothSides(float aScale) {
const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics();
gfx::Rect cssContentRect = metrics.mCSSContentRect;
gfx::Rect cssContentRect = metrics.mScrollableRect;
float currentScale = metrics.mResolution.width;
gfx::Rect viewport = gfx::Rect(metrics.mViewport.x,
metrics.mViewport.y,
metrics.mViewport.width,
metrics.mViewport.height);
viewport.ScaleRoundIn(1 / (currentScale * aScale));
nsIntRect compositionBounds = metrics.mCompositionBounds;
gfx::Rect scaledCompositionBounds =
gfx::Rect(compositionBounds.x, compositionBounds.y,
compositionBounds.width, compositionBounds.height);
scaledCompositionBounds.ScaleInverseRoundIn(currentScale * aScale);
return GetRectLength(cssContentRect) < GetRectLength(viewport);
return GetRectLength(cssContentRect) < GetRectLength(scaledCompositionBounds);
}
AxisX::AxisX(AsyncPanZoomController* aAsyncPanZoomController)

View File

@ -165,10 +165,10 @@ public:
bool ScaleWillOverscrollBothSides(float aScale);
float GetOrigin();
float GetViewportLength();
float GetCompositionLength();
float GetPageStart();
float GetPageLength();
float GetViewportEnd();
float GetCompositionEnd();
float GetPageEnd();
virtual float GetPointOffset(const gfx::Point& aPoint) = 0;

View File

@ -467,8 +467,8 @@ private:
}
const FrameMetrics& fm = c->GetFrameMetrics();
gfx3DMatrix m(aContainer->GetTransform());
m.Translate(gfxPoint3D(-fm.mViewportScrollOffset.x,
-fm.mViewportScrollOffset.y, 0));
m.Translate(gfxPoint3D(-fm.GetScrollOffsetInLayerPixels().x,
-fm.GetScrollOffsetInLayerPixels().y, 0));
// The transform already takes the resolution scale into account. Since we
// will apply the resolution scale again when computing the effective
@ -787,30 +787,43 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
float rootScaleX = rootTransform.GetXScale(),
rootScaleY = rootTransform.GetYScale();
// The ratio of layers pixels to device pixels. The Java
// compositor wants to see values in units of device pixels, so we
// map our FrameMetrics values to that space. This is not exposed
// as a FrameMetrics helper because it's a deprecated conversion.
float devPixelRatioX = 1 / rootScaleX, devPixelRatioY = 1 / rootScaleY;
gfx::Point scrollOffsetLayersPixels(metrics.GetScrollOffsetInLayerPixels());
nsIntPoint scrollOffsetDevPixels(
NS_lround(scrollOffsetLayersPixels.x * devPixelRatioX),
NS_lround(scrollOffsetLayersPixels.y * devPixelRatioY));
if (mIsFirstPaint) {
mContentRect = metrics.mContentRect;
const gfx::Point& scrollOffset = metrics.mViewportScrollOffset;
SetFirstPaintViewport(nsIntPoint(NS_lround(scrollOffset.x),
NS_lround(scrollOffset.y)),
SetFirstPaintViewport(scrollOffsetDevPixels,
1/rootScaleX,
mContentRect,
metrics.mCSSContentRect);
metrics.mScrollableRect);
mIsFirstPaint = false;
} else if (!metrics.mContentRect.IsEqualEdges(mContentRect)) {
mContentRect = metrics.mContentRect;
SetPageRect(metrics.mCSSContentRect);
SetPageRect(metrics.mScrollableRect);
}
// We synchronise the viewport information with Java after sending the above
// notifications, so that Java can take these into account in its response.
// Calculate the absolute display port to send to Java
nsIntRect displayPort = metrics.mDisplayPort;
gfx::Point scrollOffset = metrics.mViewportScrollOffset;
displayPort.x += NS_lround(scrollOffset.x);
displayPort.y += NS_lround(scrollOffset.y);
gfx::Rect displayPortLayersPixels(metrics.mDisplayPort);
nsIntRect displayPortDevPixels(
NS_lround(displayPortLayersPixels.x * devPixelRatioX),
NS_lround(displayPortLayersPixels.y * devPixelRatioY),
NS_lround(displayPortLayersPixels.width * devPixelRatioX),
NS_lround(displayPortLayersPixels.height * devPixelRatioY));
SyncViewportInfo(displayPort, 1/rootScaleX, mLayersUpdated,
displayPortDevPixels.x += scrollOffsetDevPixels.x;
displayPortDevPixels.y += scrollOffsetDevPixels.y;
SyncViewportInfo(displayPortDevPixels, 1/rootScaleX, mLayersUpdated,
mScrollOffset, mXScale, mYScale);
mLayersUpdated = false;
@ -825,8 +838,7 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
nsIntPoint metricsScrollOffset(0, 0);
if (metrics.IsScrollable()) {
metricsScrollOffset =
nsIntPoint(NS_lround(scrollOffset.x), NS_lround(scrollOffset.y));
metricsScrollOffset = scrollOffsetDevPixels;
}
nsIntPoint scrollCompensation(

View File

@ -37,7 +37,9 @@ ReusableTileStoreOGL::InvalidateTiles(TiledThebesLayerOGL* aLayer,
// This will be incorrect when the transform involves rotation, but
// it'd be quite hard to retain invalid tiles correctly in this
// situation anyway.
renderBounds = parent->GetEffectiveTransform().TransformBounds(gfxRect(metrics.mDisplayPort));
renderBounds = parent->GetEffectiveTransform().TransformBounds(
gfxRect(metrics.mDisplayPort.x, metrics.mDisplayPort.y,
metrics.mDisplayPort.width, metrics.mDisplayPort.height));
break;
}
}
@ -217,10 +219,14 @@ ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer,
scrollableLayer = parent;
if (!parentMetrics.mDisplayPort.IsEmpty() && scrollableLayer) {
displayPort = parent->GetEffectiveTransform().
TransformBounds(gfxRect(parentMetrics.mDisplayPort));
TransformBounds(gfxRect(
parentMetrics.mDisplayPort.x, parentMetrics.mDisplayPort.y,
parentMetrics.mDisplayPort.width, parentMetrics.mDisplayPort.height));
const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics();
const nsIntSize& contentSize = metrics.mContentRect.Size();
const gfx::Point& scrollOffset = metrics.mViewportScrollOffset;
gfx::Point scrollOffset =
gfx::Point(metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width,
metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height);
const nsIntPoint& contentOrigin = metrics.mContentRect.TopLeft() -
nsIntPoint(NS_lround(scrollOffset.x), NS_lround(scrollOffset.y));
gfxRect contentRect = gfxRect(contentOrigin.x, contentOrigin.y,

View File

@ -960,25 +960,29 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mCSSContentRect);
WriteParam(aMsg, aParam.mScrollableRect);
WriteParam(aMsg, aParam.mViewport);
WriteParam(aMsg, aParam.mContentRect);
WriteParam(aMsg, aParam.mViewportScrollOffset);
WriteParam(aMsg, aParam.mScrollOffset);
WriteParam(aMsg, aParam.mDisplayPort);
WriteParam(aMsg, aParam.mCompositionBounds);
WriteParam(aMsg, aParam.mScrollId);
WriteParam(aMsg, aParam.mResolution);
WriteParam(aMsg, aParam.mDevPixelsPerCSSPixel);
WriteParam(aMsg, aParam.mMayHaveTouchListeners);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
return (ReadParam(aMsg, aIter, &aResult->mCSSContentRect) &&
return (ReadParam(aMsg, aIter, &aResult->mScrollableRect) &&
ReadParam(aMsg, aIter, &aResult->mViewport) &&
ReadParam(aMsg, aIter, &aResult->mContentRect) &&
ReadParam(aMsg, aIter, &aResult->mViewportScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
ReadParam(aMsg, aIter, &aResult->mCompositionBounds) &&
ReadParam(aMsg, aIter, &aResult->mScrollId) &&
ReadParam(aMsg, aIter, &aResult->mResolution) &&
ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) &&
ReadParam(aMsg, aIter, &aResult->mMayHaveTouchListeners));
}
};

View File

@ -575,6 +575,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
bool aMayHaveTouchListeners) {
nsPresContext* presContext = aForFrame->PresContext();
int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel();
float auPerCSSPixel = nsPresContext::AppUnitsPerCSSPixel();
nsIntRect visible = aVisibleRect.ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
@ -582,12 +583,18 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
FrameMetrics metrics;
metrics.mViewport = aViewport.ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
metrics.mViewport = mozilla::gfx::Rect(
NSAppUnitsToDoublePixels(aViewport.x, auPerDevPixel),
NSAppUnitsToDoublePixels(aViewport.y, auPerDevPixel),
NSAppUnitsToDoublePixels(aViewport.width, auPerDevPixel),
NSAppUnitsToDoublePixels(aViewport.height, auPerDevPixel));
if (aDisplayPort) {
metrics.mDisplayPort = aDisplayPort->ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
metrics.mDisplayPort = mozilla::gfx::Rect(
NSAppUnitsToDoublePixels(aDisplayPort->x, auPerDevPixel),
NSAppUnitsToDoublePixels(aDisplayPort->y, auPerDevPixel),
NSAppUnitsToDoublePixels(aDisplayPort->width, auPerDevPixel),
NSAppUnitsToDoublePixels(aDisplayPort->height, auPerDevPixel));
}
nsIScrollableFrame* scrollableFrame = nullptr;
@ -598,7 +605,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
nsRect contentBounds = scrollableFrame->GetScrollRange();
contentBounds.width += scrollableFrame->GetScrollPortRect().width;
contentBounds.height += scrollableFrame->GetScrollPortRect().height;
metrics.mCSSContentRect =
metrics.mScrollableRect =
mozilla::gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
@ -606,13 +613,13 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
metrics.mContentRect = contentBounds.ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
nsPoint scrollPosition = scrollableFrame->GetScrollPosition();
metrics.mViewportScrollOffset = mozilla::gfx::Point(
NSAppUnitsToDoublePixels(scrollPosition.x, auPerDevPixel) * aContainerParameters.mXScale,
NSAppUnitsToDoublePixels(scrollPosition.y, auPerDevPixel) * aContainerParameters.mYScale);
metrics.mScrollOffset = mozilla::gfx::Point(
NSAppUnitsToDoublePixels(scrollPosition.x, auPerCSSPixel),
NSAppUnitsToDoublePixels(scrollPosition.y, auPerCSSPixel));
}
else {
nsRect contentBounds = aForFrame->GetRect();
metrics.mCSSContentRect =
metrics.mScrollableRect =
mozilla::gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
@ -626,6 +633,8 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
nsIPresShell* presShell = presContext->GetPresShell();
metrics.mResolution = gfxSize(presShell->GetXResolution(), presShell->GetYResolution());
metrics.mDevPixelsPerCSSPixel = auPerCSSPixel / auPerDevPixel;
metrics.mMayHaveTouchListeners = aMayHaveTouchListeners;
aRoot->SetFrameMetrics(metrics);
@ -1070,8 +1079,10 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
}
}
nsRect viewport(aBuilder->ToReferenceFrame(aForFrame), aForFrame->GetSize());
RecordFrameMetrics(aForFrame, rootScrollFrame,
root, mVisibleRect, mVisibleRect,
root, mVisibleRect, viewport,
(usingDisplayport ? &displayport : nullptr), id,
containerParameters, mayHaveTouchListeners);
if (usingDisplayport &&

View File

@ -158,7 +158,7 @@ ComputeShadowTreeTransform(nsIFrame* aContainerFrame,
nsIntPoint scrollOffset =
aConfig.mScrollOffset.ToNearestPixels(auPerDevPixel);
// metricsScrollOffset is in layer coordinates.
gfx::Point metricsScrollOffset = aMetrics->mViewportScrollOffset;
gfx::Point metricsScrollOffset = aMetrics->GetScrollOffsetInLayerPixels();
nsIntPoint roundedMetricsScrollOffset =
nsIntPoint(NS_lround(metricsScrollOffset.x), NS_lround(metricsScrollOffset.y));
@ -217,7 +217,9 @@ BuildListForLayer(Layer* aLayer,
nsRect bounds;
{
nscoord auPerDevPixel = aSubdocFrame->PresContext()->AppUnitsPerDevPixel();
bounds = metrics->mViewport.ToAppUnits(auPerDevPixel);
gfx::Rect viewport = metrics->mViewport;
bounds = nsIntRect(viewport.x, viewport.y,
viewport.width, viewport.height).ToAppUnits(auPerDevPixel);
ApplyTransform(bounds, tmpTransform, auPerDevPixel);
}
@ -362,6 +364,7 @@ BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
if (metrics.IsScrollable()) {
nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent()
->PresContext()->AppUnitsPerDevPixel();
nscoord auPerCSSPixel = auPerDevPixel * metrics.mDevPixelsPerCSSPixel;
nsContentView* view = FindViewForId(oldContentViews, scrollId);
if (view) {
// View already exists. Be sure to propagate scales for any values
@ -392,8 +395,8 @@ BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
// The default scale is 1, so no need to propagate scale down.
ViewConfig config;
config.mScrollOffset = nsPoint(
NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.x, auPerDevPixel) * aXScale,
NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.y, auPerDevPixel) * aYScale);
NSIntPixelsToAppUnits(metrics.mScrollOffset.x, auPerCSSPixel) * aXScale,
NSIntPixelsToAppUnits(metrics.mScrollOffset.y, auPerCSSPixel) * aYScale);
view = new nsContentView(aFrameLoader, scrollId, config);
view->mParentScaleX = aAccConfigXScale;
view->mParentScaleY = aAccConfigYScale;
@ -728,7 +731,8 @@ void
RenderFrameParent::NotifyDimensionsChanged(int width, int height)
{
if (mPanZoomController) {
mPanZoomController->UpdateViewportSize(width, height);
mPanZoomController->UpdateCompositionBounds(
nsIntRect(0, 0, width, height));
}
}