Bug 997604 - Add invalidation rect support to ImageWrappers, and use it in nsImageFrame. r=tn,sr=bz

--HG--
extra : rebase_source : a0b0f79c2bfab604f13e1098d09b2ec61e578a37
This commit is contained in:
Seth Fowler 2014-06-26 16:02:04 -07:00
parent 1740f7e7e4
commit 4cc0ce1c76
9 changed files with 77 additions and 5 deletions

View File

@ -44,6 +44,7 @@ struct Orientation;
[ref] native gfxRect(gfxRect);
native gfxGraphicsFilter(GraphicsFilter);
[ref] native nsIntRect(nsIntRect);
native nsIntRectByVal(nsIntRect);
[ref] native nsIntSize(nsIntSize);
native nsSize(nsSize);
[ptr] native nsIFrame(nsIFrame);
@ -62,7 +63,7 @@ native TempRefSourceSurface(mozilla::TemporaryRef<mozilla::gfx::SourceSurface>);
*
* Internally, imgIContainer also manages animation of images.
*/
[scriptable, builtinclass, uuid(503a830c-734d-4362-91f6-73f83ac59646)]
[scriptable, builtinclass, uuid(48590bac-a5b3-45b1-bd4e-57ab938eab9e)]
interface imgIContainer : nsISupports
{
/**
@ -348,4 +349,14 @@ interface imgIContainer : nsISupports
* resetAnimation(), or requestRefresh() is called for the first time.
*/
[notxpcom] void setAnimationStartTime([const] in TimeStamp aTime);
/*
* Given an invalidation rect in the coordinate system used by the decoder,
* returns an invalidation rect in image space.
*
* This is the identity transformation in most cases, but the result can
* differ if the image is wrapped by an ImageWrapper that changes its size
* or orientation.
*/
[notxpcom] nsIntRectByVal getImageSpaceInvalidationRect([const] in nsIntRect aRect);
};

View File

@ -424,5 +424,18 @@ ClippedImage::GetOrientation()
return InnerImage()->GetOrientation();
}
NS_IMETHODIMP_(nsIntRect)
ClippedImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect)
{
if (!ShouldClip()) {
return InnerImage()->GetImageSpaceInvalidationRect(aRect);
}
nsIntRect rect(InnerImage()->GetImageSpaceInvalidationRect(aRect));
rect = rect.Intersect(mClip);
rect.MoveBy(-mClip.x, -mClip.y);
return rect;
}
} // namespace image
} // namespace mozilla

View File

@ -52,6 +52,7 @@ public:
uint32_t aFlags) MOZ_OVERRIDE;
NS_IMETHOD RequestDiscard() MOZ_OVERRIDE;
NS_IMETHOD_(Orientation) GetOrientation() MOZ_OVERRIDE;
NS_IMETHOD_(nsIntRect) GetImageSpaceInvalidationRect(const nsIntRect& aRect) MOZ_OVERRIDE;
protected:
ClippedImage(Image* aImage, nsIntRect aClip);

View File

@ -317,5 +317,11 @@ ImageWrapper::SetAnimationStartTime(const mozilla::TimeStamp& aTime)
mInnerImage->SetAnimationStartTime(aTime);
}
NS_IMETHODIMP_(nsIntRect)
ImageWrapper::GetImageSpaceInvalidationRect(const nsIntRect& aRect)
{
return mInnerImage->GetImageSpaceInvalidationRect(aRect);
}
} // namespace image
} // namespace mozilla

View File

@ -250,5 +250,32 @@ OrientedImage::Draw(gfxContext* aContext,
aWhichFrame, aFlags);
}
NS_IMETHODIMP_(nsIntRect)
OrientedImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect)
{
nsIntRect rect(InnerImage()->GetImageSpaceInvalidationRect(aRect));
if (mOrientation.IsIdentity()) {
return rect;
}
int32_t width, height;
nsresult rv = InnerImage()->GetWidth(&width);
rv = NS_FAILED(rv) ? rv : InnerImage()->GetHeight(&height);
if (NS_FAILED(rv)) {
// Fall back to identity if the width and height aren't available.
return rect;
}
// Transform the invalidation rect into the correct orientation.
gfxMatrix matrix(OrientationMatrix(nsIntSize(width, height)).Invert());
gfxRect invalidRect(matrix.TransformBounds(gfxRect(rect.x, rect.y,
rect.width, rect.height)));
invalidRect.RoundOut();
return nsIntRect(invalidRect.x, invalidRect.y,
invalidRect.width, invalidRect.height);
}
} // namespace image
} // namespace mozilla

View File

@ -47,6 +47,7 @@ public:
const SVGImageContext* aSVGContext,
uint32_t aWhichFrame,
uint32_t aFlags) MOZ_OVERRIDE;
NS_IMETHOD_(nsIntRect) GetImageSpaceInvalidationRect(const nsIntRect& aRect) MOZ_OVERRIDE;
protected:
OrientedImage(Image* aImage, Orientation aOrientation)

View File

@ -1601,6 +1601,12 @@ RasterImage::SetLoopCount(int32_t aLoopCount)
}
}
NS_IMETHODIMP_(nsIntRect)
RasterImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect)
{
return aRect;
}
nsresult
RasterImage::AddSourceData(const char *aBuffer, uint32_t aCount)
{

View File

@ -570,6 +570,12 @@ VectorImage::SendInvalidationNotifications()
}
}
NS_IMETHODIMP_(nsIntRect)
VectorImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect)
{
return aRect;
}
//******************************************************************************
/* readonly attribute int32_t height; */
NS_IMETHODIMP

View File

@ -216,8 +216,6 @@ nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
nsSplittableFrame::DestroyFrom(aDestructRoot);
}
void
nsImageFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
@ -604,16 +602,19 @@ nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
return NS_OK;
}
nsIntRect rect = mImage ? mImage->GetImageSpaceInvalidationRect(*aRect)
: *aRect;
#ifdef DEBUG_decode
printf("Source rect (%d,%d,%d,%d)\n",
aRect->x, aRect->y, aRect->width, aRect->height);
#endif
if (aRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) {
if (rect.IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) {
InvalidateFrame(nsDisplayItem::TYPE_IMAGE);
InvalidateFrame(nsDisplayItem::TYPE_ALT_FEEDBACK);
} else {
nsRect invalid = SourceRectToDest(*aRect);
nsRect invalid = SourceRectToDest(rect);
InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_IMAGE);
InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_ALT_FEEDBACK);
}