Bug 984460 - Fill in a missing piece of code to compute the right dirty rect in the face of CSS transforms. r=mattwoodrow

This commit is contained in:
Kartikaya Gupta 2014-04-23 09:26:52 -04:00
Родитель bf96d695e0
Коммит a15a9aedef
3 изменённых файлов: 42 добавлений и 12 удалений

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

@ -5098,6 +5098,36 @@ nsRect nsDisplayTransform::TransformRectOut(const nsRect &aUntransformedBounds,
factor);
}
bool nsDisplayTransform::UntransformRect(const nsRect &aTransformedBounds,
const nsRect &aChildBounds,
const nsIFrame* aFrame,
const nsPoint &aOrigin,
nsRect *aOutRect)
{
NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
gfx3DMatrix transform = GetResultingTransformMatrix(aFrame, aOrigin, factor, nullptr);
if (transform.IsSingular()) {
return false;
}
gfxRect result(NSAppUnitsToFloatPixels(aTransformedBounds.x, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.y, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.width, factor),
NSAppUnitsToFloatPixels(aTransformedBounds.height, factor));
gfxRect childGfxBounds(NSAppUnitsToFloatPixels(aChildBounds.x, factor),
NSAppUnitsToFloatPixels(aChildBounds.y, factor),
NSAppUnitsToFloatPixels(aChildBounds.width, factor),
NSAppUnitsToFloatPixels(aChildBounds.height, factor));
result = transform.UntransformBounds(result, childGfxBounds);
*aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(result, factor);
return true;
}
bool nsDisplayTransform::UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
nsRect *aOutRect)
{

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

@ -3258,6 +3258,12 @@ public:
/* UntransformRect is like TransformRect, except that it inverts the
* transform.
*/
static bool UntransformRect(const nsRect &aTransformedBounds,
const nsRect &aChildBounds,
const nsIFrame* aFrame,
const nsPoint &aOrigin,
nsRect *aOutRect);
bool UntransformVisibleRect(nsDisplayListBuilder* aBuilder,
nsRect* aOutRect);

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

@ -1929,22 +1929,16 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
if (overflow.IsEmpty() && !Preserves3DChildren()) {
return;
}
// Trying to back-transform arbitrary rects gives us really weird results. I believe
// this is from points that lie beyond the vanishing point. As a workaround we transform
// the overflow rect into screen space and compare in that coordinate system.
// Transform the overflow rect into screen space.
nsPoint offset = aBuilder->ToReferenceFrame(this);
nsRect trans = nsDisplayTransform::TransformRect(overflow + offset, this, offset);
dirtyRect += offset;
if (dirtyRect.Intersects(trans)) {
// If they intersect, we take our whole overflow rect. We could instead take the intersection
// and then reverse transform it but I doubt this extra work is worthwhile.
dirtyRect = overflow;
nsRect untransformedDirtyRect;
if (nsDisplayTransform::UntransformRect(dirtyRect, overflow, this, offset, &untransformedDirtyRect)) {
dirtyRect = untransformedDirtyRect;
} else {
if (!Preserves3DChildren()) {
return;
}
NS_WARNING("Unable to untransform dirty rect!");
// This should only happen if the transform is singular, in which case nothing is visible anyway
dirtyRect.SetEmpty();
}
}