Bug 1383825 - limit the growth of scaling for animated nsDisplayTransform in fallback case. r=mattwoodrow

MozReview-Commit-ID: 25NNa1CKMEM
This commit is contained in:
Lee Salzman 2017-07-26 00:55:11 -04:00
Родитель fc0b3076bb
Коммит 93a171958a
3 изменённых файлов: 40 добавлений и 18 удалений

Просмотреть файл

@ -652,7 +652,7 @@ gfxUtils::ClipToRegion(DrawTarget* aTarget, const nsIntRegion& aRegion)
}
/*static*/ gfxFloat
gfxUtils::ClampToScaleFactor(gfxFloat aVal)
gfxUtils::ClampToScaleFactor(gfxFloat aVal, bool aRoundDown)
{
// Arbitary scale factor limitation. We can increase this
// for better scaling performance at the cost of worse
@ -678,8 +678,12 @@ gfxUtils::ClampToScaleFactor(gfxFloat aVal)
// next integer value.
if (fabs(power - NS_round(power)) < 1e-5) {
power = NS_round(power);
} else if (inverse) {
// Use floor when we are either inverted or rounding down, but
// not both.
} else if (inverse != aRoundDown) {
power = floor(power);
// Otherwise, ceil when we are not inverted and not rounding
// down, or we are inverted and rounding down.
} else {
power = ceil(power);
}

Просмотреть файл

@ -146,9 +146,10 @@ public:
/**
* Return the smallest power of kScaleResolution (2) greater than or equal to
* aVal.
* aVal. If aRoundDown is specified, the power of 2 will rather be less than
* or equal to aVal.
*/
static gfxFloat ClampToScaleFactor(gfxFloat aVal);
static gfxFloat ClampToScaleFactor(gfxFloat aVal, bool aRoundDown = false);
/**
* Clears surface to aColor (which defaults to transparent black).

Просмотреть файл

@ -5391,6 +5391,23 @@ static void RestrictScaleToMaxLayerSize(gfxSize& aScale,
aScale.height /= scale;
}
}
static nsSize
ComputeDesiredDisplaySizeForAnimation(nsIFrame* aContainerFrame)
{
// Use the size of the nearest widget as the maximum size. This
// is important since it might be a popup that is bigger than the
// pres context's size.
nsPresContext* presContext = aContainerFrame->PresContext();
nsIWidget* widget = aContainerFrame->GetNearestWidget();
if (widget) {
return LayoutDevicePixel::ToAppUnits(widget->GetClientSize(),
presContext->AppUnitsPerDevPixel());
} else {
return presContext->GetVisibleArea().Size();
}
}
static bool
ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
nsDisplayListBuilder* aDisplayListBuilder,
@ -5455,20 +5472,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
aContainerItem->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
EffectCompositor::HasAnimationsForCompositor(
aContainerFrame, eCSSProperty_transform)) {
// Use the size of the nearest widget as the maximum size. This
// is important since it might be a popup that is bigger than the
// pres context's size.
nsPresContext* presContext = aContainerFrame->PresContext();
nsIWidget* widget = aContainerFrame->GetNearestWidget();
nsSize displaySize;
if (widget) {
LayoutDeviceIntSize widgetSize = widget->GetClientSize();
int32_t p2a = presContext->AppUnitsPerDevPixel();
displaySize.width = NSIntPixelsToAppUnits(widgetSize.width, p2a);
displaySize.height = NSIntPixelsToAppUnits(widgetSize.height, p2a);
} else {
displaySize = presContext->GetVisibleArea().Size();
}
nsSize displaySize = ComputeDesiredDisplaySizeForAnimation(aContainerFrame);
// compute scale using the animation on the container (ignoring
// its ancestors)
scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(
@ -5505,6 +5509,19 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
if (clamp) {
scale.width = gfxUtils::ClampToScaleFactor(scale.width);
scale.height = gfxUtils::ClampToScaleFactor(scale.height);
// Limit animated scale factors to not grow excessively beyond the display size.
nsSize maxScale(4, 4);
if (!aVisibleRect.IsEmpty()) {
nsSize displaySize = ComputeDesiredDisplaySizeForAnimation(aContainerFrame);
maxScale = Max(maxScale, displaySize / aVisibleRect.Size());
}
if (scale.width > maxScale.width) {
scale.width = gfxUtils::ClampToScaleFactor(maxScale.width, true);
}
if (scale.height > maxScale.height) {
scale.height = gfxUtils::ClampToScaleFactor(maxScale.height, true);
}
}
} else {
// XXX Do we need to move nearly-integer values to integers here?