b=810274 include bounds with layer pixels as possible destinations to minimize subpixel scrolls r=roc

--HG--
extra : transplant_source : %22c%20R%E6%BF%C6%10%02%7C%1E%9F%CA%C7%2B%8C%98A%28%D3
This commit is contained in:
Karl Tomlinson 2013-06-06 15:49:10 +12:00
parent 4ff9f7630b
commit 154b99ab77

View File

@ -46,6 +46,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/StandardInteger.h"
#include "mozilla/Util.h"
#include "mozilla/MathAlgorithms.h"
#include "FrameLayerBuilder.h"
#include "nsSMILKeySpline.h"
#include "nsSubDocumentFrame.h"
@ -1822,39 +1823,65 @@ void nsGfxScrollFrameInner::ScrollVisual(nsPoint aOldScrolledFramePos)
}
/**
* Return an appunit value close to aDesired and between aLower and aUpper
* such that (aDesired - aCurrent)*aRes/aAppUnitsPerPixel is an integer (or
* as close as we can get modulo rounding to appunits). If that
* can't be done, just returns aDesired.
* Clamp desired scroll position aDesired and range [aDestLower, aDestUpper]
* to [aBoundLower, aBoundUpper] and then select the appunit value from among
* aBoundLower, aBoundUpper and those such that (aDesired - aCurrent) *
* aRes/aAppUnitsPerPixel is an integer (or as close as we can get
* modulo rounding to appunits) that is in [aDestLower, aDestUpper] and
* closest to aDesired. If no such value exists, return the nearest in
* [aDestLower, aDestUpper].
*/
static nscoord
AlignWithLayerPixels(nscoord aDesired, nscoord aLower,
nscoord aUpper, nscoord aAppUnitsPerPixel,
double aRes, nscoord aCurrent)
ClampAndAlignWithPixels(nscoord aDesired,
nscoord aBoundLower, nscoord aBoundUpper,
nscoord aDestLower, nscoord aDestUpper,
nscoord aAppUnitsPerPixel, double aRes,
nscoord aCurrent)
{
// Intersect scroll range with allowed range, by clamping the ends
// of aRange to be within bounds
nscoord destLower = clamped(aDestLower, aBoundLower, aBoundUpper);
nscoord destUpper = clamped(aDestUpper, aBoundLower, aBoundUpper);
nscoord desired = clamped(aDesired, destLower, destUpper);
double currentLayerVal = (aRes*aCurrent)/aAppUnitsPerPixel;
double desiredLayerVal = (aRes*aDesired)/aAppUnitsPerPixel;
double desiredLayerVal = (aRes*desired)/aAppUnitsPerPixel;
double delta = desiredLayerVal - currentLayerVal;
double nearestVal = NS_round(delta) + currentLayerVal;
double nearestLayerVal = NS_round(delta) + currentLayerVal;
// Convert back from ThebesLayer space to appunits relative to the top-left
// of the scrolled frame.
nscoord nearestAppUnitVal =
NSToCoordRoundWithClamp(nearestVal*aAppUnitsPerPixel/aRes);
nscoord aligned =
NSToCoordRoundWithClamp(nearestLayerVal*aAppUnitsPerPixel/aRes);
// Check if nearest layer pixel result fit into allowed and scroll range
if (nearestAppUnitVal >= aLower && nearestAppUnitVal <= aUpper) {
return nearestAppUnitVal;
} else if (nearestVal != desiredLayerVal) {
// Check if opposite pixel boundary fit into scroll range
double oppositeVal = nearestVal + ((nearestVal < desiredLayerVal) ? 1 : -1);
nscoord oppositeAppUnitVal =
NSToCoordRoundWithClamp(oppositeVal*aAppUnitsPerPixel/aRes);
if (oppositeAppUnitVal >= aLower && oppositeAppUnitVal <= aUpper) {
return oppositeAppUnitVal;
}
// Use a bound if it is within the allowed range and closer to desired than
// the nearest pixel-aligned value.
if (aBoundUpper == destUpper &&
static_cast<decltype(Abs(desired))>(aBoundUpper - desired) <
Abs(desired - aligned))
return aBoundUpper;
if (aBoundLower == destLower &&
static_cast<decltype(Abs(desired))>(desired - aBoundLower) <
Abs(aligned - desired))
return aBoundLower;
// Accept the nearest pixel-aligned value if it is within the allowed range.
if (aligned >= destLower && aligned <= destUpper)
return aligned;
// Check if opposite pixel boundary fits into allowed range.
double oppositeLayerVal =
nearestLayerVal + ((nearestLayerVal < desiredLayerVal) ? 1.0 : -1.0);
nscoord opposite =
NSToCoordRoundWithClamp(oppositeLayerVal*aAppUnitsPerPixel/aRes);
if (opposite >= destLower && opposite <= destUpper) {
return opposite;
}
return aDesired;
// No alignment available.
return desired;
}
/**
@ -1870,16 +1897,14 @@ ClampAndAlignWithLayerPixels(const nsPoint& aPt,
nscoord aAppUnitsPerPixel,
const gfxSize& aScale)
{
nsPoint pt = aBounds.ClampPoint(aPt);
// Intersect scroll range with allowed range, by clamping the corners
// of aRange to be within bounds
nsPoint rangeTopLeft = aBounds.ClampPoint(aRange.TopLeft());
nsPoint rangeBottomRight = aBounds.ClampPoint(aRange.BottomRight());
return nsPoint(AlignWithLayerPixels(pt.x, rangeTopLeft.x, rangeBottomRight.x,
aAppUnitsPerPixel, aScale.width, aCurrent.x),
AlignWithLayerPixels(pt.y, rangeTopLeft.y, rangeBottomRight.y,
aAppUnitsPerPixel, aScale.height, aCurrent.y));
return nsPoint(ClampAndAlignWithPixels(aPt.x, aBounds.x, aBounds.XMost(),
aRange.x, aRange.XMost(),
aAppUnitsPerPixel, aScale.width,
aCurrent.x),
ClampAndAlignWithPixels(aPt.y, aBounds.y, aBounds.YMost(),
aRange.y, aRange.YMost(),
aAppUnitsPerPixel, aScale.height,
aCurrent.y));
}
/* static */ void