Bug 770001. When comparing clips, adjust for any change in the ThebesLayer coordinate system. When clips are different, try to accumulate differences intelligently, taking into account that changes in clips outside the bounds of the clipped display item don't matter. r=mattwoodrow

--HG--
extra : rebase_source : d958c629307045f2592ffe658cd1a2e608713cbd
This commit is contained in:
Robert O'Callahan 2012-07-02 11:46:21 +12:00
Родитель d2ee12f6f9
Коммит b1e87e032b
3 изменённых файлов: 61 добавлений и 11 удалений

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

@ -1991,7 +1991,8 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer,
ThebesDisplayItemLayerUserData* data =
static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
InvalidatePostTransformRegion(t,
oldGeometry->ComputeInvalidationRegion().ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
oldGeometry->ComputeInvalidationRegion().
ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
mLayerBuilder->GetLastPaintOffset(t));
}
if (aNewLayer) {
@ -2000,7 +2001,8 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer,
ThebesDisplayItemLayerUserData* data =
static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
InvalidatePostTransformRegion(newThebesLayer,
geometry->ComputeInvalidationRegion().ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
geometry->ComputeInvalidationRegion().
ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
GetTranslationForThebesLayer(newThebesLayer));
}
}
@ -2028,27 +2030,27 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer,
#ifdef DEBUG_INVALIDATIONS
printf("Display item type %s(%p) added to layer %p!\n", aItem->Name(), f, aNewLayer);
#endif
} else if (aItem->IsInvalid() || *oldClip != aClip) {
// Either layout marked item as needing repainting, or the clip on it changed, invalidate
// the entire old and new areas.
// TODO: We could be smarter about handling clip changes here instead of repainting everything.
} else if (aItem->IsInvalid()) {
// Layout marked item as needing repainting. Invalidate the entire old
// and new areas.
combined.Or(geometry->ComputeInvalidationRegion(), oldGeometry->ComputeInvalidationRegion());
#ifdef DEBUG_INVALIDATIONS
printf("Display item type %s(%p) (in layer %p) belongs to an invalidated frame!\n", aItem->Name(), f, aNewLayer);
#endif
} else {
// No obvious differences, so let the display item check for geometry changes and decide what needs to be
// repainted.
ThebesDisplayItemLayerUserData* data =
static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
nsIntPoint paintOffset = GetTranslationForThebesLayer(newThebesLayer);
nsPoint offset((paintOffset.x + data->mActiveScrolledRootPosition.x) * mAppUnitsPerDevPixel / data->mXScale,
(paintOffset.y + data->mActiveScrolledRootPosition.y) * mAppUnitsPerDevPixel / data->mYScale);
nsPoint prevOffset((oldGeometry->mPaintOffset.x + oldGeometry->mActiveScrolledRootPosition.x) * oldGeometry->mAppUnitsPerDevPixel / data->mXScale,
(oldGeometry->mPaintOffset.y + oldGeometry->mActiveScrolledRootPosition.y) * oldGeometry->mAppUnitsPerDevPixel / data->mYScale);
nsPoint shift = offset - prevOffset;
// Let the display item check for geometry changes and decide what needs to be
// repainted.
oldGeometry->MoveBy(shift);
aItem->ComputeInvalidationRegion(mBuilder, oldGeometry, &combined);
oldClip->AddOffsetAndComputeDifference(shift, oldGeometry->ComputeInvalidationRegion(),
aClip, geometry->ComputeInvalidationRegion(),
&combined);
#ifdef DEBUG_INVALIDATIONS
if (!combined.IsEmpty()) {
printf("Display item type %s(%p) (in layer %p) changed geometry!\n", aItem->Name(), f, aNewLayer);
@ -3158,6 +3160,43 @@ FrameLayerBuilder::Clip::RemoveRoundedCorners()
mRoundedClipRects.Clear();
}
static void
AccumulateRectDifference(const nsRect& aR1, const nsRect& aR2, nsRegion* aOut)
{
if (aR1.IsEqualInterior(aR2))
return;
nsRegion r;
r.Xor(aR1, aR2);
aOut->Or(*aOut, r);
}
void
FrameLayerBuilder::Clip::AddOffsetAndComputeDifference(const nsPoint& aOffset,
const nsRect& aBounds,
const Clip& aOther,
const nsRect& aOtherBounds,
nsRegion* aDifference)
{
if (mHaveClipRect != aOther.mHaveClipRect ||
mRoundedClipRects.Length() != aOther.mRoundedClipRects.Length()) {
aDifference->Or(*aDifference, aBounds);
aDifference->Or(*aDifference, aOtherBounds);
return;
}
if (mHaveClipRect) {
AccumulateRectDifference((mClipRect + aOffset).Intersect(aBounds),
aOther.mClipRect.Intersect(aOtherBounds),
aDifference);
}
for (PRUint32 i = 0; i < mRoundedClipRects.Length(); ++i) {
if (mRoundedClipRects[i] + aOffset != aOther.mRoundedClipRects[i]) {
// The corners make it tricky so we'll just add both rects here.
aDifference->Or(*aDifference, mRoundedClipRects[i].mRect.Intersect(aBounds));
aDifference->Or(*aDifference, aOther.mRoundedClipRects[i].mRect.Intersect(aOtherBounds));
}
}
}
gfxRect
CalculateBounds(nsTArray<FrameLayerBuilder::Clip::RoundedRect> aRects, PRInt32 A2D)
{

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

@ -398,6 +398,11 @@ public:
// Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h
nscoord mRadii[8];
RoundedRect operator+(const nsPoint& aOffset) const {
RoundedRect r = *this;
r.mRect += aOffset;
return r;
}
bool operator==(const RoundedRect& aOther) const {
if (!mRect.IsEqualInterior(aOther.mRect)) {
return false;
@ -460,6 +465,12 @@ public:
// Gets rid of any rounded corners in this clip.
void RemoveRoundedCorners();
// Adds the difference between Intersect(*this + aPoint, aBounds) and
// Intersect(aOther, aOtherBounds) to aDifference.
void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds,
const Clip& aOther, const nsRect& aOtherBounds,
nsRegion* aDifference);
bool operator==(const Clip& aOther) const {
return mHaveClipRect == aOther.mHaveClipRect &&
(!mHaveClipRect || mClipRect.IsEqualInterior(aOther.mClipRect)) &&

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

@ -28,7 +28,7 @@ public:
* Compute the area required to be invalidated if this
* display item is removed.
*/
nsRegion ComputeInvalidationRegion() { return mBounds; }
const nsRect& ComputeInvalidationRegion() { return mBounds; }
/**
* Shifts all retained areas of the nsDisplayItemGeometry by the given offset.