зеркало из https://github.com/mozilla/gecko-dev.git
Bug 998025 - Overscroll rendering effect. r=kats
--HG-- extra : rebase_source : 8dba78d1e7a471cf739acc59390e1789a6e5873a
This commit is contained in:
Родитель
c205d40a5c
Коммит
97d46f7ecb
|
@ -1815,6 +1815,91 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AsyncPanZoomController::ApplyOverscrollEffect(ViewTransform* aTransform) const {
|
||||||
|
// The overscroll effect applied here is a combination of a translation in
|
||||||
|
// the direction of overscroll, and shrinking in both directions. For
|
||||||
|
// example, when overscrolling past the top of the page, the rectangle of
|
||||||
|
// content that filled the composition bounds will now fill a smaller
|
||||||
|
// rectangle at the bottom of the composition bounds, centred horizontally.
|
||||||
|
// The magnitude of the translation and the shrinking depends on the amount
|
||||||
|
// of the overscroll.
|
||||||
|
// With the effect applied, we can think of the composited region as being
|
||||||
|
// made up of the following subregions.
|
||||||
|
// (1) The shrunk content that used to fill the composited region.
|
||||||
|
// (2) The space created along the axis that has overscroll. This space is
|
||||||
|
// blank, filled by the background color of the overscrolled content.
|
||||||
|
// TODO(botond): Implement handling of background color.
|
||||||
|
// (3) The space created along the other axis. There may or may not be
|
||||||
|
// content available to fill this space, depending on our scroll
|
||||||
|
// position along this axis. If there is content, it's shown from the
|
||||||
|
// displayport. (TODO: Currently we don't take any measures to ensure
|
||||||
|
// that the displayport is large enough to have this content. Perhaps
|
||||||
|
// we should.) Otherwise, these spaces are also blank like (2).
|
||||||
|
// To illustrate, for the case where we are overscrolling past the top of
|
||||||
|
// the page, these regions are (1) the bottom-centre region, (2) the top
|
||||||
|
// regions, and (3) the bottom-left and bottom-right regions of the
|
||||||
|
// composited area, respectively.
|
||||||
|
|
||||||
|
// The maximum proportion of the composition length which can become blank
|
||||||
|
// space along an axis as we overscroll along that axis.
|
||||||
|
const float CLAMPING = 0.5;
|
||||||
|
|
||||||
|
// The proportion of the composition length which will become blank space
|
||||||
|
// along each axis as a result of overscroll along that axis. Since
|
||||||
|
// Axis::ApplyResistance() keeps the magnitude of the overscroll in the range
|
||||||
|
// [0, GetCompositionLength()], these scale factors should be in the range
|
||||||
|
// [0, CLAMPING].
|
||||||
|
float spacePropX = CLAMPING * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength();
|
||||||
|
float spacePropY = CLAMPING * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength();
|
||||||
|
|
||||||
|
// The translation to apply for overscroll along the x axis.
|
||||||
|
CSSPoint translationX;
|
||||||
|
if (mX.GetOverscroll() < 0) {
|
||||||
|
// Overscroll on left.
|
||||||
|
// Keep content at the midpoint of the screen's right edge fixed.
|
||||||
|
translationX.x = spacePropX * mX.GetCompositionLength();
|
||||||
|
translationX.y = (spacePropX * mY.GetCompositionLength()) / 2;
|
||||||
|
} else if (mX.GetOverscroll() > 0) {
|
||||||
|
// Overscroll on right.
|
||||||
|
// Keep content at the midpoint of the screen's left edge fixed.
|
||||||
|
translationX.y = (spacePropX * mY.GetCompositionLength()) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The translation to apply for overscroll along the y axis.
|
||||||
|
CSSPoint translationY;
|
||||||
|
if (mY.GetOverscroll() < 0) {
|
||||||
|
// Overscroll at top.
|
||||||
|
// Keep content at the midpoint of the screen's bottom edge fixed.
|
||||||
|
translationY.x = (spacePropY * mX.GetCompositionLength()) / 2;
|
||||||
|
translationY.y = spacePropY * mY.GetCompositionLength();
|
||||||
|
} else if (mY.GetOverscroll() > 0) {
|
||||||
|
// Overscroll at bottom.
|
||||||
|
// Keep content at the midpoint of the screen's top edge fixed.
|
||||||
|
translationY.x = (spacePropY * mX.GetCompositionLength()) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine the transformations along the two axes.
|
||||||
|
// TODO(botond): This method of combination is imperfect, and results in a
|
||||||
|
// funny-looking snap-back animation when we have overscroll along both axes.
|
||||||
|
// We should fine-tune this.
|
||||||
|
float spaceProp = std::max(spacePropX, spacePropY);
|
||||||
|
CSSPoint translation(std::max(translationX.x, translationY.x),
|
||||||
|
std::max(translationX.y, translationY.y));
|
||||||
|
|
||||||
|
// The prpoportion of the composition length which will be taken up by the
|
||||||
|
// original content; this is the scale we will apply to the content.
|
||||||
|
float contentProp = 1 - spaceProp;
|
||||||
|
|
||||||
|
// In a ViewTransform, the translation is applied before the scale. We want
|
||||||
|
// to apply our translation after our scale, so we compensate for that here.
|
||||||
|
translation.x /= contentProp;
|
||||||
|
translation.y /= contentProp;
|
||||||
|
|
||||||
|
// Finally, apply the transformations.
|
||||||
|
aTransform->mScale.scale *= contentProp;
|
||||||
|
aTransform->mTranslation += translation * mFrameMetrics.LayersPixelsPerCSSPixel();
|
||||||
|
}
|
||||||
|
|
||||||
bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
|
bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
|
||||||
ViewTransform* aNewTransform,
|
ViewTransform* aNewTransform,
|
||||||
ScreenPoint& aScrollOffset) {
|
ScreenPoint& aScrollOffset) {
|
||||||
|
@ -1834,6 +1919,10 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
||||||
aScrollOffset = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom();
|
aScrollOffset = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom();
|
||||||
*aNewTransform = GetCurrentAsyncTransform();
|
*aNewTransform = GetCurrentAsyncTransform();
|
||||||
|
|
||||||
|
// GetCurrentAsyncTransform() does not consider any overscroll we may have.
|
||||||
|
// Adjust the transform to account for that.
|
||||||
|
ApplyOverscrollEffect(aNewTransform);
|
||||||
|
|
||||||
LogRendertraceRect(GetGuid(), "viewport", "red",
|
LogRendertraceRect(GetGuid(), "viewport", "red",
|
||||||
CSSRect(mFrameMetrics.GetScrollOffset(),
|
CSSRect(mFrameMetrics.GetScrollOffset(),
|
||||||
ParentLayerSize(mFrameMetrics.mCompositionBounds.Size()) / mFrameMetrics.GetZoomToParent()));
|
ParentLayerSize(mFrameMetrics.mCompositionBounds.Size()) / mFrameMetrics.GetZoomToParent()));
|
||||||
|
|
|
@ -619,6 +619,12 @@ private:
|
||||||
bool IsTransformingState(PanZoomState aState);
|
bool IsTransformingState(PanZoomState aState);
|
||||||
bool IsPanningState(PanZoomState mState);
|
bool IsPanningState(PanZoomState mState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply to |aTransform| a visual effect that reflects this apzc's
|
||||||
|
* overscrolled state, if any.
|
||||||
|
*/
|
||||||
|
void ApplyOverscrollEffect(ViewTransform* aTransform) const;
|
||||||
|
|
||||||
enum AxisLockMode {
|
enum AxisLockMode {
|
||||||
FREE, /* No locking at all */
|
FREE, /* No locking at all */
|
||||||
STANDARD, /* Default axis locking mode that remains locked until pan ends*/
|
STANDARD, /* Default axis locking mode that remains locked until pan ends*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче