Bug 513681 - part 13 - switch from "HEADERONLY" flag to IsSizeDecode()/SetSizeDecode().r=joe,a=blocker

This commit is contained in:
Bobby Holley 2010-08-22 22:30:46 -04:00
parent 157e0862fb
commit 24cf517be4
12 changed files with 74 additions and 86 deletions

View File

@ -87,7 +87,7 @@ nsBMPDecoder::InitInternal()
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("nsBMPDecoder::Init(%p)\n", mImage.get()));
// Fire OnStartDecode at init time to support bug 512435
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) && mObserver)
if (!IsSizeDecode() && mObserver)
mObserver->OnStartDecode(nsnull);
return NS_OK;
@ -99,7 +99,7 @@ nsBMPDecoder::ShutdownInternal(PRUint32 aFlags)
PR_LOG(gBMPLog, PR_LOG_DEBUG, ("nsBMPDecoder::Close()\n"));
// Send notifications if appropriate
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) &&
if (!IsSizeDecode() &&
!mError && !(aFlags & CLOSE_FLAG_DONTNOTIFY)) {
if (mObserver)
mObserver->OnStopFrame(nsnull, 0);
@ -220,9 +220,9 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
NS_ENSURE_SUCCESS(rv, rv);
}
// We have the size. If we're doing a header-only decode, we got what
// We have the size. If we're doing a size decode, we got what
// we came for.
if (mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY)
if (IsSizeDecode())
return NS_OK;
// We're doing a real decode.

View File

@ -132,7 +132,7 @@ nsresult
nsGIFDecoder2::InitInternal()
{
// Fire OnStartDecode at init time to support bug 512435
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) && mObserver)
if (!IsSizeDecode() && mObserver)
mObserver->OnStartDecode(nsnull);
// Start with the version (GIF89a|GIF87a)
@ -146,7 +146,7 @@ nsresult
nsGIFDecoder2::ShutdownInternal(PRUint32 aFlags)
{
// Send notifications if appropriate
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) &&
if (!IsSizeDecode() &&
!mError && !(aFlags & CLOSE_FLAG_DONTNOTIFY)) {
if (mCurrentFrame == mGIFStruct.images_decoded)
EndImageFrame();
@ -260,8 +260,8 @@ void nsGIFDecoder2::BeginGIF()
if (mObserver)
mObserver->OnStartContainer(nsnull, mImage);
// If we're doing a header-only decode, we have what we came for
if (mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY)
// If we're doing a size decode, we have what we came for
if (IsSizeDecode())
return;
}
@ -1020,8 +1020,8 @@ nsresult nsGIFDecoder2::GifWrite(const PRUint8 *buf, PRUint32 len)
// Create the image container with the right size.
BeginGIF();
// If we were doing header-only, we're done
if (mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY)
// If we were doing a size decode, we're done
if (IsSizeDecode())
return NS_OK;
}

View File

@ -90,7 +90,7 @@ nsresult
nsICODecoder::InitInternal()
{
// Fire OnStartDecode at init time to support bug 512435
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) && mObserver)
if (!IsSizeDecode() && mObserver)
mObserver->OnStartDecode(nsnull);
return NS_OK;
@ -102,7 +102,7 @@ nsICODecoder::ShutdownInternal(PRUint32 aFlags)
nsresult rv = NS_OK;
// Send notifications if appropriate
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) &&
if (!IsSizeDecode() &&
!mError && !(aFlags & CLOSE_FLAG_DONTNOTIFY)) {
// Tell the image that it's data has been updated
nsIntRect r(0, 0, mDirEntry.mWidth, mDirEntry.mHeight);
@ -240,7 +240,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
rv = mObserver->OnStartContainer(nsnull, mImage);
NS_ENSURE_SUCCESS(rv, rv);
}
if (mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY)
if (IsSizeDecode())
return NS_OK;
if (mBIH.bpp <= 8) {

View File

@ -70,7 +70,7 @@ nsresult
nsIconDecoder::InitInternal()
{
// Fire OnStartDecode at init time to support bug 512435
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) && mObserver)
if (!IsSizeDecode() && mObserver)
mObserver->OnStartDecode(nsnull);
return NS_OK;
@ -82,7 +82,7 @@ nsIconDecoder::ShutdownInternal(PRUint32 aFlags)
// If we haven't notified of completion yet for a full/success decode, we
// didn't finish. Notify in error mode
if (!(aFlags & CLOSE_FLAG_DONTNOTIFY) &&
!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) &&
!IsSizeDecode() &&
!mNotifiedDone)
NotifyDone(/* aSuccess = */ PR_FALSE);
@ -126,8 +126,8 @@ nsIconDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
if (mObserver)
mObserver->OnStartContainer(nsnull, mImage);
// If We're doing a header-only decode, we're done
if (mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) {
// If We're doing a size decode, we're done
if (IsSizeDecode()) {
mState = iconStateFinished;
break;
}

View File

@ -139,7 +139,7 @@ nsresult
nsJPEGDecoder::InitInternal()
{
/* Fire OnStartDecode at init time to support bug 512435 */
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) && mObserver)
if (!IsSizeDecode() && mObserver)
mObserver->OnStartDecode(nsnull);
/* We set up the normal JPEG error routines, then override error_exit. */
@ -189,7 +189,7 @@ nsJPEGDecoder::ShutdownInternal(PRUint32 aFlags)
*/
if ((mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) &&
(mState != JPEG_ERROR) &&
!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) &&
!IsSizeDecode() &&
!(aFlags & CLOSE_FLAG_DONTNOTIFY))
this->Write(nsnull, 0);
@ -206,7 +206,7 @@ nsJPEGDecoder::ShutdownInternal(PRUint32 aFlags)
/* If we're doing a full decode and haven't notified of completion yet,
* we must not have got everything we wanted. Send error notifications. */
if (!(aFlags & CLOSE_FLAG_DONTNOTIFY) &&
!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) &&
!IsSizeDecode() &&
!mNotifiedDone)
NotifyDone(/* aSuccess = */ PR_FALSE);
@ -261,8 +261,8 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
if (mObserver)
mObserver->OnStartContainer(nsnull, mImage);
/* If we're doing a header-only decode, we're done. */
if (mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY)
/* If we're doing a size decode, we're done. */
if (IsSizeDecode())
return NS_OK;
/* We're doing a full decode. */

View File

@ -71,7 +71,7 @@ static PRLogModuleInfo *gPNGDecoderAccountingLog =
/* limit image dimensions (bug #251381) */
#define MOZ_PNG_MAX_DIMENSION 1000000L
// For header-only decodes
// For size decodes
#define WIDTH_OFFSET 16
#define HEIGHT_OFFSET (WIDTH_OFFSET + 4)
#define BYTES_NEEDED_FOR_DIMENSIONS (HEIGHT_OFFSET + 4)
@ -242,11 +242,11 @@ nsPNGDecoder::InitInternal()
#endif
// Fire OnStartDecode at init time to support bug 512435
if (!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) && mObserver)
if (!IsSizeDecode() && mObserver)
mObserver->OnStartDecode(nsnull);
// For header-only decodes, we only need a small buffer
if (mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) {
// For size decodes, we only need a small buffer
if (IsSizeDecode()) {
mHeaderBuf = (PRUint8 *)nsMemory::Alloc(BYTES_NEEDED_FOR_DIMENSIONS);
if (!mHeaderBuf)
return NS_ERROR_OUT_OF_MEMORY;
@ -303,7 +303,7 @@ nsPNGDecoder::ShutdownInternal(PRUint32 aFlags)
// If we're a full/success decode but haven't sent stop notifications yet,
// we didn't get all the data we needed. Send error notifications.
if (!(aFlags & CLOSE_FLAG_DONTNOTIFY) &&
!(mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) &&
!IsSizeDecode() &&
!mNotifiedDone)
NotifyDone(/* aSuccess = */ PR_FALSE);
@ -323,7 +323,7 @@ nsPNGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
goto error;
// If we only want width/height, we don't need to go through libpng
if (mFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) {
if (IsSizeDecode()) {
// Are we done?
if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS)

View File

@ -86,7 +86,7 @@ public:
gfxASurface::gfxImageFormat format;
// For header-only decodes
// For size decodes
PRUint8 *mHeaderBuf;
PRUint32 mHeaderBytesRead;

View File

@ -54,20 +54,6 @@ interface imgIDecoderObserver;
[scriptable, uuid(6fc61088-5443-4539-9e24-629a266a800a)]
interface imgIDecoder : nsISupports
{
/**
* Bits that can be passed to the decoder to affect decoding.
* @name decodeflags
*
* Meanings:
*
* DECODER_FLAG_NONE: No flags
*
* DECODER_FLAG_HEADERONLY: Read basic data from the image in order to
* set up the image container, but don't read any actual image data.
*/
const long DECODER_FLAG_NONE = 0x0;
const long DECODER_FLAG_HEADERONLY = 0x1;
/**
* Initialize an image decoder.
* @param aContainer The image container to decode to.

View File

@ -70,6 +70,7 @@ NS_IMETHODIMP Decoder::Flush()
Decoder::Decoder()
: mInitialized(false)
, mSizeDecode(false)
{
}
@ -83,8 +84,7 @@ Decoder::~Decoder()
*/
nsresult
Decoder::Init(RasterImage* aImage, imgIDecoderObserver* aObserver,
PRUint32 aFlags)
Decoder::Init(RasterImage* aImage, imgIDecoderObserver* aObserver)
{
// We should always have an image
NS_ABORT_IF_FALSE(aImage, "Can't initialize decoder without an image!");
@ -92,7 +92,6 @@ Decoder::Init(RasterImage* aImage, imgIDecoderObserver* aObserver,
// Save our paremeters
mImage = aImage;
mObserver = aObserver;
mFlags = aFlags;
// Implementation-specific initialization
nsresult rv = InitInternal();

View File

@ -68,12 +68,10 @@ public:
*
* @param aContainer The image container to decode to.
* @param aObserver The observer for decode notification events.
* @param aFlags Flags for the decoder
*
* Notifications Sent: TODO
*/
nsresult Init(RasterImage* aImage, imgIDecoderObserver* aObserver,
PRUint32 aFlags);
nsresult Init(RasterImage* aImage, imgIDecoderObserver* aObserver);
/**
* Writes data to the decoder.
@ -109,6 +107,20 @@ public:
// XXX - This is uncommented in a later patch when we stop inheriting imgIDecoder
// NS_INLINE_DECL_REFCOUNTING(Decoder)
/*
* State.
*/
// If we're doing a "size decode", we more or less pass through the image
// data, stopping only to scoop out the image dimensions. A size decode
// must be enabled by SetSizeDecode() _before_calling Init().
bool IsSizeDecode() { return mSizeDecode; };
void SetSizeDecode(bool aSizeDecode)
{
NS_ABORT_IF_FALSE(!mInitialized, "Can't set size decode after Init()!");
mSizeDecode = aSizeDecode;
}
protected:
/*
@ -127,9 +139,9 @@ protected:
*/
nsRefPtr<RasterImage> mImage;
nsCOMPtr<imgIDecoderObserver> mObserver;
PRUint32 mFlags;
bool mInitialized;
bool mSizeDecode;
};
} // namespace imagelib

View File

@ -159,7 +159,6 @@ RasterImage::RasterImage() :
mDecoder(nsnull),
mWorker(nsnull),
mBytesDecoded(0),
mDecoderFlags(imgIDecoder::DECODER_FLAG_NONE),
mHasSize(PR_FALSE),
mDecodeOnDraw(PR_FALSE),
mMultipart(PR_FALSE),
@ -261,16 +260,12 @@ RasterImage::Init(imgIDecoderObserver *aObserver,
return NS_OK;
}
// Determine our decoder flags. If we're doing decode-on-draw,
// we want to do a quick first pass to get the size but nothing
// else. We instantiate another decoder later to do the full
// decoding.
PRUint32 dFlags = imgIDecoder::DECODER_FLAG_NONE;
if (mDecodeOnDraw)
dFlags |= imgIDecoder::DECODER_FLAG_HEADERONLY;
// Instantiate the decoder
nsresult rv = InitDecoder(dFlags);
//
// If we're doing decode-on-draw, we want to do a quick first pass to get
// the size but nothing else. We instantiate another decoder later to do
// the full decoding.
nsresult rv = InitDecoder(/* aDoSizeDecode = */ mDecodeOnDraw);
CONTAINER_ENSURE_SUCCESS(rv);
// Mark us as initialized
@ -1396,7 +1391,7 @@ RasterImage::NewSourceData()
// We're decode-on-load here. Open up a new decoder just like what happens when
// we call Init() for decode-on-load images.
rv = InitDecoder(imgIDecoder::DECODER_FLAG_NONE);
rv = InitDecoder(/* aDoSizeDecode = */ false);
CONTAINER_ENSURE_SUCCESS(rv);
return NS_OK;
@ -2103,7 +2098,7 @@ RasterImage::StoringSourceData() {
// Sets up a decoder for this image. It is an error to call this function
// when decoding is already in process (ie - when mDecoder is non-null).
nsresult
RasterImage::InitDecoder(PRUint32 dFlags)
RasterImage::InitDecoder(bool aDoSizeDecode)
{
// Ensure that the decoder is not already initialized
NS_ABORT_IF_FALSE(!mDecoder, "Calling InitDecoder() while already decoding!");
@ -2142,12 +2137,10 @@ RasterImage::InitDecoder(PRUint32 dFlags)
NS_ABORT_IF_FALSE(0, "Shouldn't get here!");
}
// Store the flags for this decoder
mDecoderFlags = dFlags;
// Initialize the decoder
nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
nsresult result = mDecoder->Init(this, observer, dFlags);
mDecoder->SetSizeDecode(aDoSizeDecode);
nsresult result = mDecoder->Init(this, observer);
CONTAINER_ENSURE_SUCCESS(result);
// Create a decode worker
@ -2175,6 +2168,9 @@ RasterImage::ShutdownDecoder(eShutdownIntent aIntent)
// Ensure that the decoder is initialized
NS_ABORT_IF_FALSE(mDecoder, "Calling ShutdownDecoder() with no active decoder!");
// Figure out what kind of decode we were doing before we get rid of our decoder
bool wasSizeDecode = mDecoder->IsSizeDecode();
// Close the decoder with the appropriate flags
mInDecoder = PR_TRUE;
PRUint32 closeFlags = (aIntent == eShutdownIntent_Error)
@ -2197,18 +2193,15 @@ RasterImage::ShutdownDecoder(eShutdownIntent aIntent)
// We just shut down the decoder. If we didn't get what we want, but expected
// to, flag an error
PRBool failed = PR_FALSE;
if ((mDecoderFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) && !mHasSize)
if (wasSizeDecode && !mHasSize)
failed = PR_TRUE;
if (!(mDecoderFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) && !mDecoded)
if (!wasSizeDecode && !mDecoded)
failed = PR_TRUE;
if ((aIntent == eShutdownIntent_Done) && failed) {
DoError();
return NS_ERROR_FAILURE;
}
// Clear the flags
mDecoderFlags = imgIDecoder::DECODER_FLAG_NONE;
// Reset number of decoded bytes
mBytesDecoded = 0;
@ -2295,11 +2288,11 @@ RasterImage::RequestDecode()
return NS_OK;
// If we've already got a full decoder running, we have nothing to do
if (mDecoder && !(mDecoderFlags & imgIDecoder::DECODER_FLAG_HEADERONLY))
if (mDecoder && !mDecoder->IsSizeDecode())
return NS_OK;
// If our callstack goes through a header-only decoder, we have a problem.
// We need to shutdown the header-only decoder and replace it with a full
// If our callstack goes through a size decoder, we have a problem.
// We need to shutdown the size decode and replace it with a full
// decoder, but can't do that from within the decoder itself. Thus, we post
// an asynchronous event to the event loop to do it later. Since
// RequestDecode() is an asynchronous function this works fine (though it's
@ -2312,8 +2305,8 @@ RasterImage::RequestDecode()
}
// If we have a header-only decoder open, interrupt it and shut it down
if (mDecoder && (mDecoderFlags & imgIDecoder::DECODER_FLAG_HEADERONLY)) {
// If we have a size decode open, interrupt it and shut it down
if (mDecoder && mDecoder->IsSizeDecode()) {
rv = ShutdownDecoder(eShutdownIntent_Interrupted);
CONTAINER_ENSURE_SUCCESS(rv);
}
@ -2321,7 +2314,7 @@ RasterImage::RequestDecode()
// If we don't have a decoder, create one
if (!mDecoder) {
NS_ABORT_IF_FALSE(mFrames.IsEmpty(), "Trying to decode to non-empty frame-array");
rv = InitDecoder(imgIDecoder::DECODER_FLAG_NONE);
rv = InitDecoder(/* aDoSizeDecode = */ false);
CONTAINER_ENSURE_SUCCESS(rv);
}
@ -2359,8 +2352,8 @@ RasterImage::SyncDecode()
// disallow this type of call in the API, and check for it in API methods.
NS_ABORT_IF_FALSE(!mInDecoder, "Yikes, forcing sync in reentrant call!");
// If we have a header-only decoder open, shut it down
if (mDecoder && (mDecoderFlags & imgIDecoder::DECODER_FLAG_HEADERONLY)) {
// If we have a size decode open, shut it down
if (mDecoder && mDecoder->IsSizeDecode()) {
rv = ShutdownDecoder(eShutdownIntent_Interrupted);
CONTAINER_ENSURE_SUCCESS(rv);
}
@ -2368,7 +2361,7 @@ RasterImage::SyncDecode()
// If we don't have a decoder, create one
if (!mDecoder) {
NS_ABORT_IF_FALSE(mFrames.IsEmpty(), "Trying to decode to non-empty frame-array");
rv = InitDecoder(imgIDecoder::DECODER_FLAG_NONE);
rv = InitDecoder(/* aDoSizeDecode = */ false);
CONTAINER_ENSURE_SUCCESS(rv);
}
@ -2518,7 +2511,7 @@ RasterImage::IsDecodeFinished()
"just shut down on SourceDataComplete!");
// The decode is complete if we got what we wanted...
if (mDecoderFlags & imgIDecoder::DECODER_FLAG_HEADERONLY) {
if (mDecoder->IsSizeDecode()) {
if (mHasSize)
decodeFinished = PR_TRUE;
}
@ -2606,11 +2599,10 @@ imgDecodeWorker::Run()
if (!image->mDecoder)
return NS_OK;
// Header-only decodes are cheap and we more or less want them to be
// Size decodes are cheap and we more or less want them to be
// synchronous. Write all the data in that case, otherwise write a
// chunk
PRUint32 maxBytes =
(image->mDecoderFlags & imgIDecoder::DECODER_FLAG_HEADERONLY)
PRUint32 maxBytes = image->mDecoder->IsSizeDecode()
? image->mSourceData.Length() : DECODE_BYTES_AT_A_TIME;
// Loop control

View File

@ -462,7 +462,6 @@ private: // data
nsRefPtr<Decoder> mDecoder;
nsRefPtr<imgDecodeWorker> mWorker;
PRUint32 mBytesDecoded;
PRUint32 mDecoderFlags;
// Boolean flags (clustered together to conserve space):
PRPackedBool mHasSize:1; // Has SetSize() been called?
@ -484,7 +483,7 @@ private: // data
// Decoding
nsresult WantDecodedFrames();
nsresult SyncDecode();
nsresult InitDecoder(PRUint32 dFlags);
nsresult InitDecoder(bool aDoSizeDecode);
nsresult WriteToDecoder(const char *aBuffer, PRUint32 aCount);
nsresult DecodeSomeData(PRUint32 aMaxBytes);
PRBool IsDecodeFinished();