mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1550523 - Ensure that decoding methods for frozen images request the correct frame. r=tnikkel
With WebRender, we had observed that the print preview for animated images was not displaying correctly. It should display the first frame but it was showing nothing the first time the preview was opened. Once the decoded image was available in the cache, it would display correctly if the preview was reloaded. The StartDecoding and RequestDecode variants always requested FRAME_CURRENT for animated images. They should use FRAME_FIRST for static requests / FrozenImage. Correcting this fixes the print preview. Differential Revision: https://phabricator.services.mozilla.com/D32033
This commit is contained in:
parent
ae27e42724
commit
774c428cae
@ -219,14 +219,23 @@ DynamicImage::Draw(gfxContext* aContext, const nsIntSize& aSize,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DynamicImage::StartDecoding(uint32_t aFlags) { return NS_OK; }
|
||||
DynamicImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool DynamicImage::StartDecodingWithResult(uint32_t aFlags) { return true; }
|
||||
bool DynamicImage::StartDecodingWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicImage::RequestDecodeWithResult(uint32_t aFlags) { return true; }
|
||||
bool DynamicImage::RequestDecodeWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
|
||||
DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,27 @@ FrozenImage::Draw(gfxContext* aContext, const nsIntSize& aSize,
|
||||
aSamplingFilter, aSVGContext, aFlags, aOpacity);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrozenImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
|
||||
return InnerImage()->StartDecoding(aFlags, FRAME_FIRST);
|
||||
}
|
||||
|
||||
bool FrozenImage::StartDecodingWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return InnerImage()->StartDecodingWithResult(aFlags, FRAME_FIRST);
|
||||
}
|
||||
|
||||
bool FrozenImage::RequestDecodeWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return InnerImage()->RequestDecodeWithResult(aFlags, FRAME_FIRST);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FrozenImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return InnerImage()->RequestDecodeForSize(aSize, aFlags, FRAME_FIRST);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
FrozenImage::RequestRefresh(const TimeStamp& aTime) {
|
||||
// Do nothing.
|
||||
|
@ -59,6 +59,13 @@ class FrozenImage : public ImageWrapper {
|
||||
uint32_t aWhichFrame, gfx::SamplingFilter aSamplingFilter,
|
||||
const Maybe<SVGImageContext>& aSVGContext, uint32_t aFlags,
|
||||
float aOpacity) override;
|
||||
NS_IMETHOD StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) override;
|
||||
NS_IMETHOD_(bool)
|
||||
StartDecodingWithResult(uint32_t aFlags, uint32_t aWhichFrame) override;
|
||||
NS_IMETHOD_(bool)
|
||||
RequestDecodeWithResult(uint32_t aFlags, uint32_t aWhichFrame) override;
|
||||
NS_IMETHOD RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
|
||||
uint32_t aWhichFrame) override;
|
||||
NS_IMETHOD_(void) RequestRefresh(const TimeStamp& aTime) override;
|
||||
NS_IMETHOD GetAnimationMode(uint16_t* aAnimationMode) override;
|
||||
NS_IMETHOD SetAnimationMode(uint16_t aAnimationMode) override;
|
||||
|
@ -193,21 +193,24 @@ ImageWrapper::Draw(gfxContext* aContext, const nsIntSize& aSize,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageWrapper::StartDecoding(uint32_t aFlags) {
|
||||
return mInnerImage->StartDecoding(aFlags);
|
||||
ImageWrapper::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
|
||||
return mInnerImage->StartDecoding(aFlags, aWhichFrame);
|
||||
}
|
||||
|
||||
bool ImageWrapper::StartDecodingWithResult(uint32_t aFlags) {
|
||||
return mInnerImage->StartDecodingWithResult(aFlags);
|
||||
bool ImageWrapper::StartDecodingWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return mInnerImage->StartDecodingWithResult(aFlags, aWhichFrame);
|
||||
}
|
||||
|
||||
bool ImageWrapper::RequestDecodeWithResult(uint32_t aFlags) {
|
||||
return mInnerImage->RequestDecodeWithResult(aFlags);
|
||||
bool ImageWrapper::RequestDecodeWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return mInnerImage->RequestDecodeWithResult(aFlags, aWhichFrame);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageWrapper::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
|
||||
return mInnerImage->RequestDecodeForSize(aSize, aFlags);
|
||||
ImageWrapper::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
return mInnerImage->RequestDecodeForSize(aSize, aFlags, aWhichFrame);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1046,7 +1046,7 @@ bool RasterImage::CanDiscard() {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RasterImage::StartDecoding(uint32_t aFlags) {
|
||||
RasterImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
|
||||
if (mError) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -1058,10 +1058,11 @@ RasterImage::StartDecoding(uint32_t aFlags) {
|
||||
|
||||
uint32_t flags = (aFlags & FLAG_ASYNC_NOTIFY) | FLAG_SYNC_DECODE_IF_FAST |
|
||||
FLAG_HIGH_QUALITY_SCALING;
|
||||
return RequestDecodeForSize(mSize, flags);
|
||||
return RequestDecodeForSize(mSize, flags, aWhichFrame);
|
||||
}
|
||||
|
||||
bool RasterImage::StartDecodingWithResult(uint32_t aFlags) {
|
||||
bool RasterImage::StartDecodingWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
if (mError) {
|
||||
return false;
|
||||
}
|
||||
@ -1073,11 +1074,13 @@ bool RasterImage::StartDecodingWithResult(uint32_t aFlags) {
|
||||
|
||||
uint32_t flags = (aFlags & FLAG_ASYNC_NOTIFY) | FLAG_SYNC_DECODE_IF_FAST |
|
||||
FLAG_HIGH_QUALITY_SCALING;
|
||||
DrawableSurface surface = RequestDecodeForSizeInternal(mSize, flags);
|
||||
DrawableSurface surface =
|
||||
RequestDecodeForSizeInternal(mSize, flags, aWhichFrame);
|
||||
return surface && surface->IsFinished();
|
||||
}
|
||||
|
||||
bool RasterImage::RequestDecodeWithResult(uint32_t aFlags) {
|
||||
bool RasterImage::RequestDecodeWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mError) {
|
||||
@ -1085,27 +1088,33 @@ bool RasterImage::RequestDecodeWithResult(uint32_t aFlags) {
|
||||
}
|
||||
|
||||
uint32_t flags = aFlags | FLAG_ASYNC_NOTIFY;
|
||||
DrawableSurface surface = RequestDecodeForSizeInternal(mSize, flags);
|
||||
DrawableSurface surface =
|
||||
RequestDecodeForSizeInternal(mSize, flags, aWhichFrame);
|
||||
return surface && surface->IsFinished();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags) {
|
||||
RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mError) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RequestDecodeForSizeInternal(aSize, aFlags);
|
||||
RequestDecodeForSizeInternal(aSize, aFlags, aWhichFrame);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DrawableSurface RasterImage::RequestDecodeForSizeInternal(const IntSize& aSize,
|
||||
uint32_t aFlags) {
|
||||
DrawableSurface RasterImage::RequestDecodeForSizeInternal(
|
||||
const IntSize& aSize, uint32_t aFlags, uint32_t aWhichFrame) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (aWhichFrame > FRAME_MAX_VALUE) {
|
||||
return DrawableSurface();
|
||||
}
|
||||
|
||||
if (mError) {
|
||||
return DrawableSurface();
|
||||
}
|
||||
@ -1125,10 +1134,8 @@ DrawableSurface RasterImage::RequestDecodeForSizeInternal(const IntSize& aSize,
|
||||
shouldSyncDecodeIfFast ? aFlags : aFlags & ~FLAG_SYNC_DECODE_IF_FAST;
|
||||
|
||||
// Perform a frame lookup, which will implicitly start decoding if needed.
|
||||
PlaybackType playbackType =
|
||||
mAnimationState ? PlaybackType::eAnimated : PlaybackType::eStatic;
|
||||
LookupResult result =
|
||||
LookupFrame(aSize, flags, playbackType, /* aMarkUsed = */ false);
|
||||
LookupResult result = LookupFrame(aSize, flags, ToPlaybackType(aWhichFrame),
|
||||
/* aMarkUsed = */ false);
|
||||
return std::move(result.Surface());
|
||||
}
|
||||
|
||||
@ -1697,7 +1704,8 @@ void RasterImage::NotifyDecodeComplete(
|
||||
if (mWantFullDecode) {
|
||||
mWantFullDecode = false;
|
||||
RequestDecodeForSize(mSize,
|
||||
DECODE_FLAGS_DEFAULT | FLAG_HIGH_QUALITY_SCALING);
|
||||
DECODE_FLAGS_DEFAULT | FLAG_HIGH_QUALITY_SCALING,
|
||||
FRAME_CURRENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -452,7 +452,8 @@ class RasterImage final : public ImageResource,
|
||||
bool IsOpaque();
|
||||
|
||||
DrawableSurface RequestDecodeForSizeInternal(const gfx::IntSize& aSize,
|
||||
uint32_t aFlags);
|
||||
uint32_t aFlags,
|
||||
uint32_t aWhichFrame);
|
||||
|
||||
protected:
|
||||
explicit RasterImage(nsIURI* aURI = nullptr);
|
||||
|
@ -1202,23 +1202,26 @@ void VectorImage::RecoverFromLossOfSurfaces() {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VectorImage::StartDecoding(uint32_t aFlags) {
|
||||
VectorImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
|
||||
// Nothing to do for SVG images
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool VectorImage::StartDecodingWithResult(uint32_t aFlags) {
|
||||
bool VectorImage::StartDecodingWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
// SVG images are ready to draw when they are loaded
|
||||
return mIsFullyLoaded;
|
||||
}
|
||||
|
||||
bool VectorImage::RequestDecodeWithResult(uint32_t aFlags) {
|
||||
bool VectorImage::RequestDecodeWithResult(uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
// SVG images are ready to draw when they are loaded
|
||||
return mIsFullyLoaded;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VectorImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
|
||||
VectorImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
|
||||
uint32_t aWhichFrame) {
|
||||
// Nothing to do for SVG images, though in theory we could rasterize to the
|
||||
// provided size ahead of time if we supported off-main-thread SVG
|
||||
// rasterization...
|
||||
|
@ -467,8 +467,15 @@ interface imgIContainer : nsISupports
|
||||
*
|
||||
* @param aFlags Flags of the FLAG_* variety. Only FLAG_ASYNC_NOTIFY
|
||||
* is accepted; all others are ignored.
|
||||
* @param aWhichFrame Frame specifier of the FRAME_* variety.
|
||||
*/
|
||||
[noscript] void startDecoding(in uint32_t aFlags);
|
||||
[noscript] void startDecoding(in uint32_t aFlags, in uint32_t aWhichFrame);
|
||||
|
||||
%{C++
|
||||
nsresult StartDecoding(uint32_t aFlags) {
|
||||
return StartDecoding(aFlags, FRAME_CURRENT);
|
||||
}
|
||||
%}
|
||||
|
||||
/*
|
||||
* Exactly like startDecoding above except returns whether the current frame
|
||||
@ -476,8 +483,15 @@ interface imgIContainer : nsISupports
|
||||
*
|
||||
* @param aFlags Flags of the FLAG_* variety. Only FLAG_ASYNC_NOTIFY
|
||||
* is accepted; all others are ignored.
|
||||
* @param aWhichFrame Frame specifier of the FRAME_* variety.
|
||||
*/
|
||||
[noscript, notxpcom] boolean startDecodingWithResult(in uint32_t aFlags);
|
||||
[noscript, notxpcom] boolean startDecodingWithResult(in uint32_t aFlags, in uint32_t aWhichFrame);
|
||||
|
||||
%{C++
|
||||
bool StartDecodingWithResult(uint32_t aFlags) {
|
||||
return StartDecodingWithResult(aFlags, FRAME_CURRENT);
|
||||
}
|
||||
%}
|
||||
|
||||
/*
|
||||
* This method triggers decoding for an image, but unlike startDecoding() it
|
||||
@ -485,10 +499,17 @@ interface imgIContainer : nsISupports
|
||||
* request.
|
||||
*
|
||||
* @param aFlags Flags of the FLAG_* variety.
|
||||
* @param aWhichFrame Frame specifier of the FRAME_* variety.
|
||||
* @return True there is a surface that satisfies the request and it is
|
||||
* fully decoded, else false.
|
||||
*/
|
||||
[noscript, notxpcom] boolean requestDecodeWithResult(in uint32_t aFlags);
|
||||
[noscript, notxpcom] boolean requestDecodeWithResult(in uint32_t aFlags, in uint32_t aWhichFrame);
|
||||
|
||||
%{C++
|
||||
bool RequestDecodeWithResult(uint32_t aFlags) {
|
||||
return RequestDecodeWithResult(aFlags, FRAME_CURRENT);
|
||||
}
|
||||
%}
|
||||
|
||||
/*
|
||||
* This method triggers decoding for an image, but unlike startDecoding() it
|
||||
@ -499,9 +520,17 @@ interface imgIContainer : nsISupports
|
||||
* if possible. If the image cannot be scaled to this size while
|
||||
* being decoded, it will be decoded at its intrinsic size.
|
||||
* @param aFlags Flags of the FLAG_* variety.
|
||||
* @param aWhichFrame Frame specifier of the FRAME_* variety.
|
||||
*/
|
||||
[noscript] void requestDecodeForSize([const] in nsIntSize aSize,
|
||||
in uint32_t aFlags);
|
||||
in uint32_t aFlags,
|
||||
in uint32_t aWhichFrame);
|
||||
|
||||
%{C++
|
||||
nsresult RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
|
||||
return RequestDecodeForSize(aSize, aFlags, FRAME_CURRENT);
|
||||
}
|
||||
%}
|
||||
|
||||
/**
|
||||
* Increments the lock count on the image. An image will not be discarded
|
||||
|
Loading…
Reference in New Issue
Block a user