gecko-dev/gfx/layers/apz/src/Axis.cpp

678 строки
24 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Axis.h"
#include <math.h> // for fabsf, pow, powf
#include <algorithm> // for max
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
#include "mozilla/layers/APZCTreeManager.h" // for APZCTreeManager
#include "mozilla/layers/APZThreadUtils.h" // for AssertOnControllerThread
#include "FrameMetrics.h" // for FrameMetrics
#include "mozilla/Attributes.h" // for final
#include "mozilla/ComputedTimingFunction.h" // for ComputedTimingFunction
#include "mozilla/Preferences.h" // for Preferences
#include "mozilla/gfx/Rect.h" // for RoundedIn
#include "mozilla/mozalloc.h" // for operator new
#include "mozilla/FloatingPoint.h" // for FuzzyEqualsAdditive
#include "mozilla/StaticPtr.h" // for StaticAutoPtr
#include "nsMathUtils.h" // for NS_lround
#include "nsPrintfCString.h" // for nsPrintfCString
#include "nsThreadUtils.h" // for NS_DispatchToMainThread, etc
#include "nscore.h" // for NS_IMETHOD
#include "gfxPrefs.h" // for the preferences
#define AXIS_LOG(...)
// #define AXIS_LOG(...) printf_stderr("AXIS: " __VA_ARGS__)
namespace mozilla {
namespace layers {
// When we compute the velocity we do so by taking two input events and
// dividing the distance delta over the time delta. In some cases the time
// delta can be really small, which can make the velocity computation very
// volatile. To avoid this we impose a minimum time delta below which we do
// not recompute the velocity.
const uint32_t MIN_VELOCITY_SAMPLE_TIME_MS = 5;
bool FuzzyEqualsCoordinate(float aValue1, float aValue2)
{
return FuzzyEqualsAdditive(aValue1, aValue2, COORDINATE_EPSILON)
|| FuzzyEqualsMultiplicative(aValue1, aValue2);
}
extern StaticAutoPtr<ComputedTimingFunction> gVelocityCurveFunction;
Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
: mPos(0),
mVelocitySampleTimeMs(0),
mVelocitySamplePos(0),
mVelocity(0.0f),
mAxisLocked(false),
mAsyncPanZoomController(aAsyncPanZoomController),
mOverscroll(0),
mFirstOverscrollAnimationSample(0),
mLastOverscrollPeak(0),
mOverscrollScale(1.0f)
{
}
float Axis::ToLocalVelocity(float aVelocityInchesPerMs) const {
ScreenPoint velocity = MakePoint(aVelocityInchesPerMs * APZCTreeManager::GetDPI());
// Use ToScreenCoordinates() to convert a point rather than a vector by
// treating the point as a vector, and using (0, 0) as the anchor.
ScreenPoint panStart = mAsyncPanZoomController->ToScreenCoordinates(
mAsyncPanZoomController->PanStart(),
ParentLayerPoint());
ParentLayerPoint localVelocity =
mAsyncPanZoomController->ToParentLayerCoordinates(velocity, panStart);
return localVelocity.Length();
}
void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord aAdditionalDelta, uint32_t aTimestampMs) {
// mVelocityQueue is controller-thread only
APZThreadUtils::AssertOnControllerThread();
if (aTimestampMs <= mVelocitySampleTimeMs + MIN_VELOCITY_SAMPLE_TIME_MS) {
// See also the comment on MIN_VELOCITY_SAMPLE_TIME_MS.
// We still update mPos so that the positioning is correct (and we don't run
// into problems like bug 1042734) but the velocity will remain where it was.
// In particular we don't update either mVelocitySampleTimeMs or
// mVelocitySamplePos so that eventually when we do get an event with the
// required time delta we use the corresponding distance delta as well.
AXIS_LOG("%p|%s skipping velocity computation for small time delta %dms\n",
mAsyncPanZoomController, Name(), (aTimestampMs - mVelocitySampleTimeMs));
mPos = aPos;
return;
}
float newVelocity = mAxisLocked ? 0.0f : (float)(mVelocitySamplePos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mVelocitySampleTimeMs);
newVelocity = ApplyFlingCurveToVelocity(newVelocity);
AXIS_LOG("%p|%s updating velocity to %f with touch\n",
mAsyncPanZoomController, Name(), newVelocity);
mVelocity = newVelocity;
mPos = aPos;
mVelocitySampleTimeMs = aTimestampMs;
mVelocitySamplePos = aPos;
AddVelocityToQueue(aTimestampMs, mVelocity);
}
float Axis::ApplyFlingCurveToVelocity(float aVelocity) const {
float newVelocity = aVelocity;
if (gfxPrefs::APZMaxVelocity() > 0.0f) {
bool velocityIsNegative = (newVelocity < 0);
newVelocity = fabs(newVelocity);
float maxVelocity = ToLocalVelocity(gfxPrefs::APZMaxVelocity());
newVelocity = std::min(newVelocity, maxVelocity);
if (gfxPrefs::APZCurveThreshold() > 0.0f && gfxPrefs::APZCurveThreshold() < gfxPrefs::APZMaxVelocity()) {
float curveThreshold = ToLocalVelocity(gfxPrefs::APZCurveThreshold());
if (newVelocity > curveThreshold) {
// here, 0 < curveThreshold < newVelocity <= maxVelocity, so we apply the curve
float scale = maxVelocity - curveThreshold;
float funcInput = (newVelocity - curveThreshold) / scale;
float funcOutput =
gVelocityCurveFunction->GetValue(funcInput,
ComputedTimingFunction::BeforeFlag::Unset);
float curvedVelocity = (funcOutput * scale) + curveThreshold;
AXIS_LOG("%p|%s curving up velocity from %f to %f\n",
mAsyncPanZoomController, Name(), newVelocity, curvedVelocity);
newVelocity = curvedVelocity;
}
}
if (velocityIsNegative) {
newVelocity = -newVelocity;
}
}
return newVelocity;
}
void Axis::AddVelocityToQueue(uint32_t aTimestampMs, float aVelocity) {
mVelocityQueue.AppendElement(std::make_pair(aTimestampMs, aVelocity));
if (mVelocityQueue.Length() > gfxPrefs::APZMaxVelocityQueueSize()) {
mVelocityQueue.RemoveElementAt(0);
}
}
void Axis::HandleTouchVelocity(uint32_t aTimestampMs, float aSpeed) {
// mVelocityQueue is controller-thread only
APZThreadUtils::AssertOnControllerThread();
mVelocity = ApplyFlingCurveToVelocity(aSpeed);
mVelocitySampleTimeMs = aTimestampMs;
AddVelocityToQueue(aTimestampMs, mVelocity);
}
void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) {
mStartPos = aPos;
mPos = aPos;
mVelocitySampleTimeMs = aTimestampMs;
mVelocitySamplePos = aPos;
mAxisLocked = false;
}
bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement,
/* ParentLayerCoord */ float& aDisplacementOut,
/* ParentLayerCoord */ float& aOverscrollAmountOut,
bool aForceOverscroll /* = false */)
{
if (mAxisLocked) {
aOverscrollAmountOut = 0;
aDisplacementOut = 0;
return false;
}
if (aForceOverscroll) {
aOverscrollAmountOut = aDisplacement;
aDisplacementOut = 0;
return false;
}
EndOverscrollAnimation();
ParentLayerCoord displacement = aDisplacement;
// First consume any overscroll in the opposite direction along this axis.
ParentLayerCoord consumedOverscroll = 0;
if (mOverscroll > 0 && aDisplacement < 0) {
consumedOverscroll = std::min(mOverscroll, -aDisplacement);
} else if (mOverscroll < 0 && aDisplacement > 0) {
consumedOverscroll = 0.f - std::min(-mOverscroll, aDisplacement);
}
mOverscroll -= consumedOverscroll;
displacement += consumedOverscroll;
// Split the requested displacement into an allowed displacement that does
// not overscroll, and an overscroll amount.
aOverscrollAmountOut = DisplacementWillOverscrollAmount(displacement);
if (aOverscrollAmountOut != 0.0f) {
// No need to have a velocity along this axis anymore; it won't take us
// anywhere, so we're just spinning needlessly.
AXIS_LOG("%p|%s has overscrolled, clearing velocity\n",
mAsyncPanZoomController, Name());
mVelocity = 0.0f;
displacement -= aOverscrollAmountOut;
}
aDisplacementOut = displacement;
return fabsf(consumedOverscroll) > EPSILON;
}
ParentLayerCoord Axis::ApplyResistance(ParentLayerCoord aRequestedOverscroll) const {
// 'resistanceFactor' is a value between 0 and 1, which:
// - tends to 1 as the existing overscroll tends to 0
// - tends to 0 as the existing overscroll tends to the composition length
// The actual overscroll is the requested overscroll multiplied by this
// factor; this should prevent overscrolling by more than the composition
// length.
float resistanceFactor = 1 - fabsf(GetOverscroll()) / GetCompositionLength();
return resistanceFactor < 0 ? ParentLayerCoord(0) : aRequestedOverscroll * resistanceFactor;
}
void Axis::OverscrollBy(ParentLayerCoord aOverscroll) {
MOZ_ASSERT(CanScroll());
// We can get some spurious calls to OverscrollBy() with near-zero values
// due to rounding error. Ignore those (they might trip the asserts below.)
if (FuzzyEqualsAdditive(aOverscroll.value, 0.0f, COORDINATE_EPSILON)) {
return;
}
EndOverscrollAnimation();
aOverscroll = ApplyResistance(aOverscroll);
if (aOverscroll > 0) {
#ifdef DEBUG
if (!FuzzyEqualsCoordinate(GetCompositionEnd().value, GetPageEnd().value)) {
nsPrintfCString message("composition end (%f) is not equal (within error) to page end (%f)\n",
GetCompositionEnd().value, GetPageEnd().value);
NS_ASSERTION(false, message.get());
MOZ_CRASH("GFX: Overscroll issue > 0");
}
#endif
MOZ_ASSERT(mOverscroll >= 0);
} else if (aOverscroll < 0) {
#ifdef DEBUG
if (!FuzzyEqualsCoordinate(GetOrigin().value, GetPageStart().value)) {
nsPrintfCString message("composition origin (%f) is not equal (within error) to page origin (%f)\n",
GetOrigin().value, GetPageStart().value);
NS_ASSERTION(false, message.get());
MOZ_CRASH("GFX: Overscroll issue < 0");
}
#endif
MOZ_ASSERT(mOverscroll <= 0);
}
mOverscroll += aOverscroll;
}
ParentLayerCoord Axis::GetOverscroll() const {
ParentLayerCoord result = (mOverscroll - mLastOverscrollPeak) / mOverscrollScale;
// Assert that we return overscroll in the correct direction
#ifdef DEBUG
if ((result.value * mFirstOverscrollAnimationSample.value) < 0.0f) {
nsPrintfCString message("GetOverscroll() (%f) and first overscroll animation sample (%f) have different signs\n",
result.value, mFirstOverscrollAnimationSample.value);
NS_ASSERTION(false, message.get());
MOZ_CRASH("GFX: Overscroll issue");
}
#endif
return result;
}
void Axis::StartOverscrollAnimation(float aVelocity) {
// Make sure any state from a previous animation has been cleared.
MOZ_ASSERT(mFirstOverscrollAnimationSample == 0 &&
mLastOverscrollPeak == 0 &&
mOverscrollScale == 1);
SetVelocity(aVelocity);
}
void Axis::EndOverscrollAnimation() {
ParentLayerCoord overscroll = GetOverscroll();
mFirstOverscrollAnimationSample = 0;
mLastOverscrollPeak = 0;
mOverscrollScale = 1.0f;
mOverscroll = overscroll;
}
void Axis::StepOverscrollAnimation(double aStepDurationMilliseconds) {
// Apply spring physics to the overscroll as time goes on.
// Note: this method of sampling isn't perfectly smooth, as it assumes
// a constant velocity over 'aDelta', instead of an accelerating velocity.
// (The way we applying friction to flings has the same issue.)
// Hooke's law with damping:
// F = -kx - bv
// where
// k is a constant related to the stiffness of the spring
// The larger the constant, the stiffer the spring.
// x is the displacement of the end of the spring from its equilibrium
// In our scenario, it's the amount of overscroll on the axis.
// b is a constant that provides damping (friction)
// v is the velocity of the point at the end of the spring
// See http://gafferongames.com/game-physics/spring-physics/
const float kSpringStiffness = gfxPrefs::APZOverscrollSpringStiffness();
const float kSpringFriction = gfxPrefs::APZOverscrollSpringFriction();
// Apply spring force.
float springForce = -1 * kSpringStiffness * mOverscroll;
// Assume unit mass, so force = acceleration.
float oldVelocity = mVelocity;
mVelocity += springForce * aStepDurationMilliseconds;
// Apply dampening.
mVelocity *= pow(double(1 - kSpringFriction), aStepDurationMilliseconds);
AXIS_LOG("%p|%s sampled overscroll animation, leaving velocity at %f\n",
mAsyncPanZoomController, Name(), mVelocity);
// At the peak of each oscillation, record new offset and scaling factors for
// overscroll, to ensure that GetOverscroll always returns a value of the
// same sign, and that this value is correctly adjusted as the spring is
// dampened.
// To handle the case where one of the velocity samples is exaclty zero,
// consider a sign change to have occurred when the outgoing velocity is zero.
bool velocitySignChange = (oldVelocity * mVelocity) < 0 || mVelocity == 0;
if (mFirstOverscrollAnimationSample == 0.0f) {
mFirstOverscrollAnimationSample = mOverscroll;
// It's possible to start sampling overscroll with velocity == 0, or
// velocity in the opposite direction of overscroll, so make sure we
// correctly record the peak in this case.
if (mOverscroll != 0 && ((mOverscroll > 0 ? oldVelocity : -oldVelocity) <= 0.0f)) {
velocitySignChange = true;
}
}
if (velocitySignChange) {
bool oddOscillation = (mOverscroll.value * mFirstOverscrollAnimationSample.value) < 0.0f;
mLastOverscrollPeak = oddOscillation ? mOverscroll : -mOverscroll;
mOverscrollScale = 2.0f;
}
// Adjust the amount of overscroll based on the velocity.
// Note that we allow for oscillations.
mOverscroll += (mVelocity * aStepDurationMilliseconds);
// Our mechanism for translating a set of mOverscroll values that oscillate
// around zero to a set of GetOverscroll() values that have the same sign
// (so content is always stretched, never compressed) assumes that
// mOverscroll does not exceed mLastOverscrollPeak in magnitude. If our
// calculations were exact, this would be the case, as a dampened spring
// should never attain a displacement greater in magnitude than a previous
// peak. In our approximation calculations, however, this may not hold
// exactly. To ensure the assumption is not violated, we clamp the magnitude
// of mOverscroll.
if (mLastOverscrollPeak != 0 && fabs(mOverscroll) > fabs(mLastOverscrollPeak)) {
mOverscroll = (mOverscroll >= 0) ? fabs(mLastOverscrollPeak) : -fabs(mLastOverscrollPeak);
}
}
bool Axis::SampleOverscrollAnimation(const TimeDuration& aDelta) {
// Short-circuit early rather than running through all the sampling code.
if (mVelocity == 0.0f && mOverscroll == 0.0f) {
return false;
}
// We approximate the curve traced out by the velocity of the spring
// over time by breaking up the curve into small segments over which we
// consider the velocity to be constant. If the animation is sampled
// sufficiently often, then treating |aDelta| as a single segment of this
// sort would be fine, but the frequency at which the animation is sampled
// can be affected by external factors, and as the segment size grows larger,
// the approximation gets worse and the approximated curve can even diverge
// (i.e. oscillate forever, with displacements of increasing absolute value)!
// To avoid this, we break up |aDelta| into smaller segments of length 1 ms
// each, and a segment of any remaining fractional milliseconds.
double milliseconds = aDelta.ToMilliseconds();
int wholeMilliseconds = (int) aDelta.ToMilliseconds();
double fractionalMilliseconds = milliseconds - wholeMilliseconds;
for (int i = 0; i < wholeMilliseconds; ++i) {
StepOverscrollAnimation(1);
}
StepOverscrollAnimation(fractionalMilliseconds);
// If both the velocity and the displacement fall below a threshold, stop
// the animation so we don't continue doing tiny oscillations that aren't
// noticeable.
if (fabs(mOverscroll) < gfxPrefs::APZOverscrollStopDistanceThreshold() &&
fabs(mVelocity) < gfxPrefs::APZOverscrollStopVelocityThreshold()) {
// "Jump" to the at-rest state. The jump shouldn't be noticeable as the
// velocity and overscroll are already low.
AXIS_LOG("%p|%s oscillation dropped below threshold, going to rest\n",
mAsyncPanZoomController, Name());
ClearOverscroll();
mVelocity = 0;
return false;
}
// Otherwise, continue the animation.
return true;
}
bool Axis::IsOverscrolled() const {
return mOverscroll != 0.f;
}
void Axis::ClearOverscroll() {
EndOverscrollAnimation();
mOverscroll = 0;
}
ParentLayerCoord Axis::PanStart() const {
return mStartPos;
}
ParentLayerCoord Axis::PanDistance() const {
return fabs(mPos - mStartPos);
}
ParentLayerCoord Axis::PanDistance(ParentLayerCoord aPos) const {
return fabs(aPos - mStartPos);
}
void Axis::EndTouch(uint32_t aTimestampMs) {
// mVelocityQueue is controller-thread only
APZThreadUtils::AssertOnControllerThread();
mAxisLocked = false;
mVelocity = 0;
int count = 0;
while (!mVelocityQueue.IsEmpty()) {
uint32_t timeDelta = (aTimestampMs - mVelocityQueue[0].first);
if (timeDelta < gfxPrefs::APZVelocityRelevanceTime()) {
count++;
mVelocity += mVelocityQueue[0].second;
}
mVelocityQueue.RemoveElementAt(0);
}
if (count > 1) {
mVelocity /= count;
}
AXIS_LOG("%p|%s ending touch, computed velocity %f\n",
mAsyncPanZoomController, Name(), mVelocity);
}
void Axis::CancelGesture() {
// mVelocityQueue is controller-thread only
APZThreadUtils::AssertOnControllerThread();
AXIS_LOG("%p|%s cancelling touch, clearing velocity queue\n",
mAsyncPanZoomController, Name());
mVelocity = 0.0f;
while (!mVelocityQueue.IsEmpty()) {
mVelocityQueue.RemoveElementAt(0);
}
}
bool Axis::CanScroll() const {
return GetPageLength() - GetCompositionLength() > COORDINATE_EPSILON;
}
bool Axis::CanScroll(ParentLayerCoord aDelta) const
{
if (!CanScroll() || mAxisLocked) {
return false;
}
return fabs(DisplacementWillOverscrollAmount(aDelta) - aDelta) > COORDINATE_EPSILON;
}
CSSCoord Axis::ClampOriginToScrollableRect(CSSCoord aOrigin) const
{
CSSToParentLayerScale zoom = GetScaleForAxis(GetFrameMetrics().GetZoom());
ParentLayerCoord origin = aOrigin * zoom;
ParentLayerCoord result;
if (origin < GetPageStart()) {
result = GetPageStart();
} else if (origin + GetCompositionLength() > GetPageEnd()) {
result = GetPageEnd() - GetCompositionLength();
} else {
return aOrigin;
}
return result / zoom;
}
bool Axis::CanScrollNow() const {
return !mAxisLocked && CanScroll();
}
bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta,
float aFriction,
float aThreshold) {
if (fabsf(mVelocity) <= aThreshold) {
// If the velocity is very low, just set it to 0 and stop the fling,
// otherwise we'll just asymptotically approach 0 and the user won't
// actually see any changes.
mVelocity = 0.0f;
return false;
} else {
mVelocity *= pow(1.0f - aFriction, float(aDelta.ToMilliseconds()));
}
AXIS_LOG("%p|%s reduced velocity to %f due to friction\n",
mAsyncPanZoomController, Name(), mVelocity);
return true;
}
ParentLayerCoord Axis::DisplacementWillOverscrollAmount(ParentLayerCoord aDisplacement) const {
ParentLayerCoord newOrigin = GetOrigin() + aDisplacement;
ParentLayerCoord newCompositionEnd = GetCompositionEnd() + aDisplacement;
// If the current pan plus a displacement takes the window to the left of or
// above the current page rect.
bool minus = newOrigin < GetPageStart();
// If the current pan plus a displacement takes the window to the right of or
// below the current page rect.
bool plus = newCompositionEnd > GetPageEnd();
if (minus && plus) {
// Don't handle overscrolled in both directions; a displacement can't cause
// this, it must have already been zoomed out too far.
return 0;
}
if (minus) {
return newOrigin - GetPageStart();
}
if (plus) {
return newCompositionEnd - GetPageEnd();
}
return 0;
}
CSSCoord Axis::ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const {
// Internally, do computations in ParentLayer coordinates *before* the scale
// is applied.
CSSToParentLayerScale zoom = GetFrameMetrics().GetZoom().ToScaleFactor();
ParentLayerCoord focus = aFocus * zoom;
ParentLayerCoord originAfterScale = (GetOrigin() + focus) - (focus / aScale);
bool both = ScaleWillOverscrollBothSides(aScale);
bool minus = GetPageStart() - originAfterScale > COORDINATE_EPSILON;
bool plus = (originAfterScale + (GetCompositionLength() / aScale)) - GetPageEnd() > COORDINATE_EPSILON;
if ((minus && plus) || both) {
// If we ever reach here it's a bug in the client code.
MOZ_ASSERT(false, "In an OVERSCROLL_BOTH condition in ScaleWillOverscrollAmount");
return 0;
}
if (minus) {
return (originAfterScale - GetPageStart()) / zoom;
}
if (plus) {
return (originAfterScale + (GetCompositionLength() / aScale) - GetPageEnd()) / zoom;
}
return 0;
}
bool Axis::IsAxisLocked() const {
return mAxisLocked;
}
float Axis::GetVelocity() const {
return mAxisLocked ? 0 : mVelocity;
}
void Axis::SetVelocity(float aVelocity) {
AXIS_LOG("%p|%s direct-setting velocity to %f\n",
mAsyncPanZoomController, Name(), aVelocity);
mVelocity = aVelocity;
}
ParentLayerCoord Axis::GetCompositionEnd() const {
return GetOrigin() + GetCompositionLength();
}
ParentLayerCoord Axis::GetPageEnd() const {
return GetPageStart() + GetPageLength();
}
ParentLayerCoord Axis::GetOrigin() const {
ParentLayerPoint origin = GetFrameMetrics().GetScrollOffset() * GetFrameMetrics().GetZoom();
return GetPointOffset(origin);
}
ParentLayerCoord Axis::GetCompositionLength() const {
return GetRectLength(GetFrameMetrics().GetCompositionBounds());
}
ParentLayerCoord Axis::GetPageStart() const {
ParentLayerRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom();
return GetRectOffset(pageRect);
}
ParentLayerCoord Axis::GetPageLength() const {
ParentLayerRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom();
return GetRectLength(pageRect);
}
bool Axis::ScaleWillOverscrollBothSides(float aScale) const {
const FrameMetrics& metrics = GetFrameMetrics();
ParentLayerRect screenCompositionBounds = metrics.GetCompositionBounds()
/ ParentLayerToParentLayerScale(aScale);
return GetRectLength(screenCompositionBounds) - GetPageLength() > COORDINATE_EPSILON;
}
const FrameMetrics& Axis::GetFrameMetrics() const {
return mAsyncPanZoomController->GetFrameMetrics();
}
AxisX::AxisX(AsyncPanZoomController* aAsyncPanZoomController)
: Axis(aAsyncPanZoomController)
{
}
ParentLayerCoord AxisX::GetPointOffset(const ParentLayerPoint& aPoint) const
{
return aPoint.x;
}
ParentLayerCoord AxisX::GetRectLength(const ParentLayerRect& aRect) const
{
return aRect.width;
}
ParentLayerCoord AxisX::GetRectOffset(const ParentLayerRect& aRect) const
{
return aRect.x;
}
CSSToParentLayerScale AxisX::GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const
{
return CSSToParentLayerScale(aScale.xScale);
}
ScreenPoint AxisX::MakePoint(ScreenCoord aCoord) const
{
return ScreenPoint(aCoord, 0);
}
const char* AxisX::Name() const
{
return "X";
}
AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController)
: Axis(aAsyncPanZoomController)
{
}
ParentLayerCoord AxisY::GetPointOffset(const ParentLayerPoint& aPoint) const
{
return aPoint.y;
}
ParentLayerCoord AxisY::GetRectLength(const ParentLayerRect& aRect) const
{
return aRect.height;
}
ParentLayerCoord AxisY::GetRectOffset(const ParentLayerRect& aRect) const
{
return aRect.y;
}
CSSToParentLayerScale AxisY::GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const
{
return CSSToParentLayerScale(aScale.yScale);
}
ScreenPoint AxisY::MakePoint(ScreenCoord aCoord) const
{
return ScreenPoint(0, aCoord);
}
const char* AxisY::Name() const
{
return "Y";
}
} // namespace layers
} // namespace mozilla