2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2001
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Stuart Parmenter <pavlov@netscape.com>
|
|
|
|
* Chris Saari <saari@netscape.com>
|
|
|
|
* Asko Tontti <atontti@cc.hut.fi>
|
|
|
|
* Arron Mogge <paper@animecity.nu>
|
|
|
|
* Andrew Smith
|
2007-10-18 17:36:34 -07:00
|
|
|
* Federico Mena-Quintero <federico@novell.com>
|
2009-09-12 15:44:18 -07:00
|
|
|
* Bobby Holley <bobbyholley@gmail.com>
|
2007-03-22 10:30:00 -07:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
2011-09-08 11:05:11 -07:00
|
|
|
#include "base/histogram.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsComponentManagerUtils.h"
|
|
|
|
#include "imgIContainerObserver.h"
|
2007-10-18 17:36:34 -07:00
|
|
|
#include "ImageErrors.h"
|
2010-08-22 19:30:46 -07:00
|
|
|
#include "Decoder.h"
|
2007-10-18 17:36:34 -07:00
|
|
|
#include "imgIDecoderObserver.h"
|
2010-08-13 21:09:49 -07:00
|
|
|
#include "RasterImage.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIInterfaceRequestor.h"
|
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
|
|
#include "nsAutoPtr.h"
|
2007-10-18 17:36:34 -07:00
|
|
|
#include "nsStringStream.h"
|
|
|
|
#include "prmem.h"
|
|
|
|
#include "prenv.h"
|
2009-09-12 15:44:18 -07:00
|
|
|
#include "ImageLogging.h"
|
2011-07-19 08:18:43 -07:00
|
|
|
#include "mozilla/TimeStamp.h"
|
2011-07-20 14:51:54 -07:00
|
|
|
#include "mozilla/Telemetry.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-08-22 19:30:45 -07:00
|
|
|
#include "nsPNGDecoder.h"
|
|
|
|
#include "nsGIFDecoder2.h"
|
|
|
|
#include "nsJPEGDecoder.h"
|
|
|
|
#include "nsBMPDecoder.h"
|
|
|
|
#include "nsICODecoder.h"
|
|
|
|
#include "nsIconDecoder.h"
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "gfxContext.h"
|
|
|
|
|
2011-07-19 08:18:43 -07:00
|
|
|
using namespace mozilla;
|
2010-08-13 21:09:49 -07:00
|
|
|
using namespace mozilla::imagelib;
|
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
// a mask for flags that will affect the decoding
|
|
|
|
#define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION)
|
|
|
|
#define DECODE_FLAGS_DEFAULT 0
|
|
|
|
|
2007-10-18 17:36:34 -07:00
|
|
|
/* Accounting for compressed data */
|
|
|
|
#if defined(PR_LOGGING)
|
|
|
|
static PRLogModuleInfo *gCompressedImageAccountingLog = PR_NewLogModule ("CompressedImageAccounting");
|
|
|
|
#else
|
|
|
|
#define gCompressedImageAccountingLog
|
|
|
|
#endif
|
|
|
|
|
2010-08-25 15:58:27 -07:00
|
|
|
// Tweakable progressive decoding parameters
|
|
|
|
static PRUint32 gDecodeBytesAtATime = 200000;
|
|
|
|
static PRUint32 gMaxMSBeforeYield = 400;
|
2010-08-26 15:54:21 -07:00
|
|
|
static PRUint32 gMaxBytesForSyncDecode = 150000;
|
2010-08-25 15:58:27 -07:00
|
|
|
|
|
|
|
void
|
|
|
|
RasterImage::SetDecodeBytesAtATime(PRUint32 aBytesAtATime)
|
|
|
|
{
|
|
|
|
gDecodeBytesAtATime = aBytesAtATime;
|
|
|
|
}
|
|
|
|
void
|
|
|
|
RasterImage::SetMaxMSBeforeYield(PRUint32 aMaxMS)
|
|
|
|
{
|
|
|
|
gMaxMSBeforeYield = aMaxMS;
|
|
|
|
}
|
2010-08-26 15:54:21 -07:00
|
|
|
void
|
|
|
|
RasterImage::SetMaxBytesForSyncDecode(PRUint32 aMaxBytes)
|
|
|
|
{
|
|
|
|
gMaxBytesForSyncDecode = aMaxBytes;
|
|
|
|
}
|
2010-08-25 15:58:27 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
/* We define our own error checking macros here for 2 reasons:
|
|
|
|
*
|
|
|
|
* 1) Most of the failures we encounter here will (hopefully) be
|
|
|
|
* the result of decoding failures (ie, bad data) and not code
|
|
|
|
* failures. As such, we don't want to clutter up debug consoles
|
|
|
|
* with spurious messages about NS_ENSURE_SUCCESS failures.
|
|
|
|
*
|
|
|
|
* 2) We want to set the internal error flag, shutdown properly,
|
|
|
|
* and end up in an error state.
|
|
|
|
*
|
|
|
|
* So this macro should be called when the desired failure behavior
|
|
|
|
* is to put the container into an error state and return failure.
|
|
|
|
* It goes without saying that macro won't compile outside of a
|
2010-08-13 21:09:49 -07:00
|
|
|
* non-static RasterImage method.
|
2009-09-12 15:44:18 -07:00
|
|
|
*/
|
|
|
|
#define LOG_CONTAINER_ERROR \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
PR_LOG (gImgLog, PR_LOG_ERROR, \
|
2010-08-13 21:09:49 -07:00
|
|
|
("RasterImage: [this=%p] Error " \
|
2009-09-12 15:44:18 -07:00
|
|
|
"detected at line %u for image of " \
|
|
|
|
"type %s\n", this, __LINE__, \
|
|
|
|
mSourceDataMimeType.get())); \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
|
|
|
#define CONTAINER_ENSURE_SUCCESS(status) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
nsresult _status = status; /* eval once */ \
|
|
|
|
if (_status) { \
|
|
|
|
LOG_CONTAINER_ERROR; \
|
|
|
|
DoError(); \
|
|
|
|
return _status; \
|
|
|
|
} \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
|
|
|
#define CONTAINER_ENSURE_TRUE(arg, rv) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
if (!(arg)) { \
|
|
|
|
LOG_CONTAINER_ERROR; \
|
|
|
|
DoError(); \
|
|
|
|
return rv; \
|
|
|
|
} \
|
|
|
|
PR_END_MACRO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int num_containers;
|
|
|
|
static int num_discardable_containers;
|
|
|
|
static PRInt64 total_source_bytes;
|
|
|
|
static PRInt64 discardable_source_bytes;
|
|
|
|
|
|
|
|
/* Are we globally disabling image discarding? */
|
2011-07-20 14:52:30 -07:00
|
|
|
static bool
|
2009-09-12 15:44:18 -07:00
|
|
|
DiscardingEnabled()
|
|
|
|
{
|
2011-07-20 14:52:30 -07:00
|
|
|
static bool inited;
|
|
|
|
static bool enabled;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
if (!inited) {
|
|
|
|
inited = PR_TRUE;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
enabled = (PR_GetEnv("MOZ_DISABLE_IMAGE_DISCARD") == nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
return enabled;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
namespace mozilla {
|
|
|
|
namespace imagelib {
|
|
|
|
|
2010-09-07 17:34:18 -07:00
|
|
|
#ifndef DEBUG
|
2011-10-07 00:24:27 -07:00
|
|
|
NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
2009-09-12 15:44:18 -07:00
|
|
|
nsISupportsWeakReference)
|
2010-09-07 17:34:18 -07:00
|
|
|
#else
|
2011-10-07 00:24:27 -07:00
|
|
|
NS_IMPL_ISUPPORTS5(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
2010-09-07 17:34:18 -07:00
|
|
|
imgIContainerDebug, nsISupportsWeakReference)
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
//******************************************************************************
|
2010-08-23 15:44:07 -07:00
|
|
|
RasterImage::RasterImage(imgStatusTracker* aStatusTracker) :
|
|
|
|
Image(aStatusTracker), // invoke superclass's constructor
|
2007-03-22 10:30:00 -07:00
|
|
|
mSize(0,0),
|
2011-01-12 17:45:13 -08:00
|
|
|
mFrameDecodeFlags(DECODE_FLAGS_DEFAULT),
|
2007-03-22 10:30:00 -07:00
|
|
|
mAnim(nsnull),
|
|
|
|
mLoopCount(-1),
|
2007-10-18 17:36:34 -07:00
|
|
|
mObserver(nsnull),
|
2010-05-12 14:41:47 -07:00
|
|
|
mLockCount(0),
|
|
|
|
mDecoder(nsnull),
|
|
|
|
mWorker(nsnull),
|
|
|
|
mBytesDecoded(0),
|
2011-09-08 11:05:11 -07:00
|
|
|
mDecodeCount(0),
|
2010-09-07 17:34:18 -07:00
|
|
|
#ifdef DEBUG
|
|
|
|
mFramesNotified(0),
|
|
|
|
#endif
|
2010-05-12 14:41:47 -07:00
|
|
|
mHasSize(PR_FALSE),
|
2009-09-12 15:44:18 -07:00
|
|
|
mDecodeOnDraw(PR_FALSE),
|
|
|
|
mMultipart(PR_FALSE),
|
2007-10-18 17:36:34 -07:00
|
|
|
mDiscardable(PR_FALSE),
|
2009-09-12 15:44:18 -07:00
|
|
|
mHasSourceData(PR_FALSE),
|
|
|
|
mDecoded(PR_FALSE),
|
2009-10-06 21:39:30 -07:00
|
|
|
mHasBeenDecoded(PR_FALSE),
|
2009-09-12 15:44:18 -07:00
|
|
|
mWorkerPending(PR_FALSE),
|
|
|
|
mInDecoder(PR_FALSE),
|
2010-09-07 17:33:02 -07:00
|
|
|
mAnimationFinished(PR_FALSE)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
2010-07-01 10:39:44 -07:00
|
|
|
// Set up the discard tracker node.
|
|
|
|
mDiscardTrackerNode.curr = this;
|
|
|
|
mDiscardTrackerNode.prev = mDiscardTrackerNode.next = nsnull;
|
2011-09-08 11:05:11 -07:00
|
|
|
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(0);
|
2010-07-01 10:39:44 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Statistics
|
|
|
|
num_containers++;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::~RasterImage()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-05-17 07:01:36 -07:00
|
|
|
delete mAnim;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
for (unsigned int i = 0; i < mFrames.Length(); ++i)
|
|
|
|
delete mFrames[i];
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Discardable statistics
|
|
|
|
if (mDiscardable) {
|
|
|
|
num_discardable_containers--;
|
|
|
|
discardable_source_bytes -= mSourceData.Length();
|
2007-10-18 17:36:34 -07:00
|
|
|
|
|
|
|
PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG,
|
2010-08-13 21:09:49 -07:00
|
|
|
("CompressedImageAccounting: destroying RasterImage %p. "
|
2009-09-12 15:44:18 -07:00
|
|
|
"Total Containers: %d, Discardable containers: %d, "
|
|
|
|
"Total source bytes: %lld, Source bytes for discardable containers %lld",
|
2007-10-18 17:36:34 -07:00
|
|
|
this,
|
2009-09-12 15:44:18 -07:00
|
|
|
num_containers,
|
|
|
|
num_discardable_containers,
|
|
|
|
total_source_bytes,
|
|
|
|
discardable_source_bytes));
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
DiscardTracker::Remove(&mDiscardTrackerNode);
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// If we have a decoder open, shut it down
|
|
|
|
if (mDecoder) {
|
|
|
|
nsresult rv = ShutdownDecoder(eShutdownIntent_Interrupted);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
NS_WARNING("Failed to shut down decoder in destructor!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Total statistics
|
|
|
|
num_containers--;
|
|
|
|
total_source_bytes -= mSourceData.Length();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::Init(imgIDecoderObserver *aObserver,
|
|
|
|
const char* aMimeType,
|
2010-09-12 08:22:26 -07:00
|
|
|
const char* aURIString,
|
2010-08-13 21:09:49 -07:00
|
|
|
PRUint32 aFlags)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
|
|
|
// We don't support re-initialization
|
|
|
|
if (mInitialized)
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
|
|
|
|
// Not sure an error can happen before init, but be safe
|
|
|
|
if (mError)
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aMimeType);
|
|
|
|
|
|
|
|
// We must be non-discardable and non-decode-on-draw for
|
|
|
|
// multipart channels
|
|
|
|
NS_ABORT_IF_FALSE(!(aFlags & INIT_FLAG_MULTIPART) ||
|
|
|
|
(!(aFlags & INIT_FLAG_DISCARDABLE) &&
|
|
|
|
!(aFlags & INIT_FLAG_DECODE_ON_DRAW)),
|
|
|
|
"Can't be discardable or decode-on-draw for multipart");
|
2008-01-19 00:10:26 -08:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Store initialization data
|
2007-03-22 10:30:00 -07:00
|
|
|
mObserver = do_GetWeakReference(aObserver);
|
2009-09-12 15:44:18 -07:00
|
|
|
mSourceDataMimeType.Assign(aMimeType);
|
2010-09-12 08:22:26 -07:00
|
|
|
mURIString.Assign(aURIString);
|
2010-05-25 15:27:29 -07:00
|
|
|
mDiscardable = !!(aFlags & INIT_FLAG_DISCARDABLE);
|
|
|
|
mDecodeOnDraw = !!(aFlags & INIT_FLAG_DECODE_ON_DRAW);
|
|
|
|
mMultipart = !!(aFlags & INIT_FLAG_MULTIPART);
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Statistics
|
|
|
|
if (mDiscardable) {
|
|
|
|
num_discardable_containers++;
|
|
|
|
discardable_source_bytes += mSourceData.Length();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we're being called from ExtractFrame (used by borderimage),
|
|
|
|
// we don't actually do any decoding. Bail early.
|
|
|
|
// XXX - This should be removed when we fix borderimage
|
|
|
|
if (mSourceDataMimeType.Length() == 0) {
|
|
|
|
mInitialized = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate the decoder
|
2010-08-22 19:30:46 -07:00
|
|
|
//
|
|
|
|
// 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);
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
|
|
|
|
// Mark us as initialized
|
|
|
|
mInitialized = PR_TRUE;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
2009-09-12 15:44:18 -07:00
|
|
|
/* [noscript] imgIContainer extractFrame(PRUint32 aWhichFrame,
|
|
|
|
* [const] in nsIntRect aRegion,
|
|
|
|
* in PRUint32 aFlags); */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::ExtractFrame(PRUint32 aWhichFrame,
|
|
|
|
const nsIntRect &aRegion,
|
|
|
|
PRUint32 aFlags,
|
|
|
|
imgIContainer **_retval)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (aWhichFrame > FRAME_MAX_VALUE)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2010-07-26 13:45:15 -07:00
|
|
|
// Disallowed in the API
|
|
|
|
if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Make a new container. This should switch to another class with bug 505959.
|
2010-08-13 21:09:49 -07:00
|
|
|
nsRefPtr<RasterImage> img(new RasterImage());
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_TRUE(img, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We don't actually have a mimetype in this case. The empty string tells the
|
|
|
|
// init routine not to try to instantiate a decoder. This should be fixed in
|
|
|
|
// bug 505959.
|
2010-09-12 08:22:26 -07:00
|
|
|
img->Init(nsnull, "", "", INIT_FLAG_NONE);
|
2009-09-12 15:44:18 -07:00
|
|
|
img->SetSize(aRegion.width, aRegion.height);
|
|
|
|
img->mDecoded = PR_TRUE; // Also, we need to mark the image as decoded
|
2009-10-06 21:39:30 -07:00
|
|
|
img->mHasBeenDecoded = PR_TRUE;
|
2011-01-12 17:45:13 -08:00
|
|
|
img->mFrameDecodeFlags = aFlags & DECODE_FLAGS_MASK;
|
|
|
|
|
|
|
|
if (img->mFrameDecodeFlags != mFrameDecodeFlags) {
|
|
|
|
// if we can't discard, then we're screwed; we have no way
|
|
|
|
// to re-decode. Similarly if we aren't allowed to do a sync
|
|
|
|
// decode.
|
|
|
|
if (!(aFlags & FLAG_SYNC_DECODE))
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
if (!CanForciblyDiscard() || mDecoder || mAnim)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
ForceDiscard();
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
mFrameDecodeFlags = img->mFrameDecodeFlags;
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If a synchronous decode was requested, do it
|
|
|
|
if (aFlags & FLAG_SYNC_DECODE) {
|
|
|
|
rv = SyncDecode();
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Get the frame. If it's not there, it's probably the caller's fault for
|
|
|
|
// not waiting for the data to be loaded from the network or not passing
|
|
|
|
// FLAG_SYNC_DECODE
|
|
|
|
PRUint32 frameIndex = (aWhichFrame == FRAME_FIRST) ?
|
|
|
|
0 : GetCurrentImgFrameIndex();
|
2009-11-12 15:18:40 -08:00
|
|
|
imgFrame *frame = GetDrawableImgFrame(frameIndex);
|
2009-09-12 15:44:18 -07:00
|
|
|
if (!frame) {
|
|
|
|
*_retval = nsnull;
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
// The frame can be smaller than the image. We want to extract only the part
|
|
|
|
// of the frame that actually exists.
|
|
|
|
nsIntRect framerect = frame->GetRect();
|
|
|
|
framerect.IntersectRect(framerect, aRegion);
|
|
|
|
|
2009-08-04 19:39:05 -07:00
|
|
|
if (framerect.IsEmpty())
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
nsAutoPtr<imgFrame> subframe;
|
2009-09-12 15:44:18 -07:00
|
|
|
rv = frame->Extract(framerect, getter_Transfers(subframe));
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
img->mFrames.AppendElement(subframe.forget());
|
|
|
|
|
2010-08-23 15:44:07 -07:00
|
|
|
img->mStatusTracker->RecordLoaded();
|
|
|
|
img->mStatusTracker->RecordDecoded();
|
2010-05-14 13:47:59 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
*_retval = img.forget().get();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
/* readonly attribute PRInt32 width; */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::GetWidth(PRInt32 *aWidth)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-03-19 22:54:30 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aWidth);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-10-06 15:18:52 -07:00
|
|
|
if (mError) {
|
|
|
|
*aWidth = 0;
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
2010-10-06 15:18:52 -07:00
|
|
|
}
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
*aWidth = mSize.width;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
/* readonly attribute PRInt32 height; */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::GetHeight(PRInt32 *aHeight)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-03-19 22:54:30 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aHeight);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-10-06 15:18:52 -07:00
|
|
|
if (mError) {
|
|
|
|
*aHeight = 0;
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
2010-10-06 15:18:52 -07:00
|
|
|
}
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
*aHeight = mSize.height;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* unsigned short GetType(); */
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::GetType(PRUint16 *aType)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aType);
|
|
|
|
|
2010-12-07 10:40:28 -08:00
|
|
|
*aType = GetType();
|
2010-08-13 21:09:49 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-12-07 10:40:28 -08:00
|
|
|
//******************************************************************************
|
|
|
|
/* [noscript, notxpcom] PRUint16 GetType(); */
|
|
|
|
NS_IMETHODIMP_(PRUint16)
|
|
|
|
RasterImage::GetType()
|
|
|
|
{
|
|
|
|
return imgIContainer::TYPE_RASTER;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
imgFrame*
|
2011-07-21 11:14:41 -07:00
|
|
|
RasterImage::GetImgFrameNoDecode(PRUint32 framenum)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
if (!mAnim) {
|
|
|
|
NS_ASSERTION(framenum == 0, "Don't ask for a frame > 0 if we're not animated!");
|
|
|
|
return mFrames.SafeElementAt(0, nsnull);
|
|
|
|
}
|
|
|
|
if (mAnim->lastCompositedFrameIndex == PRInt32(framenum))
|
2008-03-19 22:54:30 -07:00
|
|
|
return mAnim->compositingFrame;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return mFrames.SafeElementAt(framenum, nsnull);
|
|
|
|
}
|
|
|
|
|
2011-07-21 11:14:41 -07:00
|
|
|
imgFrame*
|
|
|
|
RasterImage::GetImgFrame(PRUint32 framenum)
|
|
|
|
{
|
|
|
|
nsresult rv = WantDecodedFrames();
|
|
|
|
CONTAINER_ENSURE_TRUE(NS_SUCCEEDED(rv), nsnull);
|
|
|
|
return GetImgFrameNoDecode(framenum);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
imgFrame*
|
|
|
|
RasterImage::GetDrawableImgFrame(PRUint32 framenum)
|
2009-11-12 15:18:40 -08:00
|
|
|
{
|
|
|
|
imgFrame *frame = GetImgFrame(framenum);
|
|
|
|
|
|
|
|
// We will return a paletted frame if it's not marked as compositing failed
|
|
|
|
// so we can catch crashes for reasons we haven't investigated.
|
|
|
|
if (frame && frame->GetCompositingFailed())
|
|
|
|
return nsnull;
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
PRUint32
|
|
|
|
RasterImage::GetCurrentImgFrameIndex() const
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
|
|
|
if (mAnim)
|
|
|
|
return mAnim->currentAnimationFrameIndex;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
imgFrame*
|
|
|
|
RasterImage::GetCurrentImgFrame()
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
|
|
|
return GetImgFrame(GetCurrentImgFrameIndex());
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
imgFrame*
|
|
|
|
RasterImage::GetCurrentDrawableImgFrame()
|
2009-11-12 15:18:40 -08:00
|
|
|
{
|
|
|
|
return GetDrawableImgFrame(GetCurrentImgFrameIndex());
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//******************************************************************************
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
/* readonly attribute boolean currentFrameIsOpaque; */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
RasterImage::GetCurrentFrameIsOpaque(bool *aIsOpaque)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aIsOpaque);
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// See if we can get an image frame
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
imgFrame *curframe = GetCurrentImgFrame();
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we don't get a frame, the safe answer is "not opaque"
|
|
|
|
if (!curframe)
|
|
|
|
*aIsOpaque = PR_FALSE;
|
|
|
|
|
|
|
|
// Otherwise, we can make a more intelligent decision
|
|
|
|
else {
|
|
|
|
*aIsOpaque = !curframe->GetNeedsBackground();
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We are also transparent if the current frame's size doesn't cover our
|
|
|
|
// entire area.
|
|
|
|
nsIntRect framerect = curframe->GetRect();
|
2011-04-18 20:07:23 -07:00
|
|
|
*aIsOpaque = *aIsOpaque && framerect.IsEqualInterior(nsIntRect(0, 0, mSize.width, mSize.height));
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-23 15:44:07 -07:00
|
|
|
void
|
|
|
|
RasterImage::GetCurrentFrameRect(nsIntRect& aRect)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
// Get the current frame
|
2010-08-23 15:44:07 -07:00
|
|
|
imgFrame* curframe = GetCurrentImgFrame();
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we have the frame, use that rectangle
|
2010-08-23 15:44:07 -07:00
|
|
|
if (curframe) {
|
2009-09-12 15:44:18 -07:00
|
|
|
aRect = curframe->GetRect();
|
2010-08-23 15:44:07 -07:00
|
|
|
} else {
|
|
|
|
// If the frame doesn't exist, we pass the empty rectangle. It's not clear
|
|
|
|
// whether this is appropriate in general, but at the moment the only
|
|
|
|
// consumer of this method is imgStatusTracker (when it wants to figure out
|
|
|
|
// dirty rectangles to send out batched observer updates). This should
|
|
|
|
// probably be revisited when we fix bug 503973.
|
2009-09-12 15:44:18 -07:00
|
|
|
aRect.MoveTo(0, 0);
|
|
|
|
aRect.SizeTo(0, 0);
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2010-08-22 19:30:44 -07:00
|
|
|
PRUint32
|
|
|
|
RasterImage::GetCurrentFrameIndex()
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2010-08-22 19:30:44 -07:00
|
|
|
return GetCurrentImgFrameIndex();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2010-08-22 19:30:44 -07:00
|
|
|
PRUint32
|
|
|
|
RasterImage::GetNumFrames()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2010-08-22 19:30:44 -07:00
|
|
|
return mFrames.Length();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
/* readonly attribute boolean animated; */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
RasterImage::GetAnimated(bool *aAnimated)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aAnimated);
|
|
|
|
|
2009-10-06 21:39:30 -07:00
|
|
|
// If we have mAnim, we can know for sure
|
|
|
|
if (mAnim) {
|
|
|
|
*aAnimated = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we need to have been decoded to know for sure, since if we were
|
|
|
|
// decoded at least once mAnim would have been created for animated images
|
|
|
|
if (!mHasBeenDecoded)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
|
|
// We know for sure
|
|
|
|
*aAnimated = PR_FALSE;
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************************
|
2009-09-12 15:44:18 -07:00
|
|
|
/* [noscript] gfxImageSurface copyFrame(in PRUint32 aWhichFrame,
|
|
|
|
* in PRUint32 aFlags); */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::CopyFrame(PRUint32 aWhichFrame,
|
|
|
|
PRUint32 aFlags,
|
|
|
|
gfxImageSurface **_retval)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (aWhichFrame > FRAME_MAX_VALUE)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2010-07-26 13:45:15 -07:00
|
|
|
// Disallowed in the API
|
|
|
|
if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
nsresult rv;
|
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
|
|
|
|
if (desiredDecodeFlags != mFrameDecodeFlags) {
|
|
|
|
// if we can't discard, then we're screwed; we have no way
|
|
|
|
// to re-decode. Similarly if we aren't allowed to do a sync
|
|
|
|
// decode.
|
|
|
|
if (!(aFlags & FLAG_SYNC_DECODE))
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
if (!CanForciblyDiscard() || mDecoder || mAnim)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
ForceDiscard();
|
|
|
|
|
|
|
|
mFrameDecodeFlags = desiredDecodeFlags;
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If requested, synchronously flush any data we have lying around to the decoder
|
|
|
|
if (aFlags & FLAG_SYNC_DECODE) {
|
|
|
|
rv = SyncDecode();
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
|
2008-03-19 22:54:30 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Get the frame. If it's not there, it's probably the caller's fault for
|
|
|
|
// not waiting for the data to be loaded from the network or not passing
|
|
|
|
// FLAG_SYNC_DECODE
|
|
|
|
PRUint32 frameIndex = (aWhichFrame == FRAME_FIRST) ?
|
|
|
|
0 : GetCurrentImgFrameIndex();
|
2009-11-12 15:18:40 -08:00
|
|
|
imgFrame *frame = GetDrawableImgFrame(frameIndex);
|
2009-09-12 15:44:18 -07:00
|
|
|
if (!frame) {
|
|
|
|
*_retval = nsnull;
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
nsRefPtr<gfxPattern> pattern;
|
|
|
|
frame->GetPattern(getter_AddRefs(pattern));
|
|
|
|
nsIntRect intframerect = frame->GetRect();
|
|
|
|
gfxRect framerect(intframerect.x, intframerect.y, intframerect.width, intframerect.height);
|
|
|
|
|
|
|
|
// Create a 32-bit image surface of our size, but draw using the frame's
|
|
|
|
// rect, implicitly padding the frame out to the image's size.
|
|
|
|
nsRefPtr<gfxImageSurface> imgsurface = new gfxImageSurface(gfxIntSize(mSize.width, mSize.height),
|
|
|
|
gfxASurface::ImageFormatARGB32);
|
|
|
|
gfxContext ctx(imgsurface);
|
|
|
|
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
|
|
|
|
ctx.SetPattern(pattern);
|
|
|
|
ctx.Rectangle(framerect);
|
|
|
|
ctx.Fill();
|
2007-07-16 15:55:21 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
*_retval = imgsurface.forget().get();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
//******************************************************************************
|
2009-09-12 15:44:18 -07:00
|
|
|
/* [noscript] gfxASurface getFrame(in PRUint32 aWhichFrame,
|
|
|
|
* in PRUint32 aFlags); */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::GetFrame(PRUint32 aWhichFrame,
|
|
|
|
PRUint32 aFlags,
|
|
|
|
gfxASurface **_retval)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (aWhichFrame > FRAME_MAX_VALUE)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2010-07-26 13:45:15 -07:00
|
|
|
// Disallowed in the API
|
|
|
|
if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
2011-05-31 13:36:38 -07:00
|
|
|
if (mDecoded) {
|
|
|
|
// If we have decoded data, and it is not a perfect match for what we are
|
|
|
|
// looking for, we must discard to be able to generate the proper data.
|
|
|
|
PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
|
|
|
|
if (desiredDecodeFlags != mFrameDecodeFlags) {
|
|
|
|
// if we can't discard, then we're screwed; we have no way
|
|
|
|
// to re-decode. Similarly if we aren't allowed to do a sync
|
|
|
|
// decode.
|
|
|
|
if (!(aFlags & FLAG_SYNC_DECODE))
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
if (!CanForciblyDiscard() || mDecoder || mAnim)
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
|
|
ForceDiscard();
|
|
|
|
|
|
|
|
mFrameDecodeFlags = desiredDecodeFlags;
|
|
|
|
}
|
2011-01-12 17:45:13 -08:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If the caller requested a synchronous decode, do it
|
|
|
|
if (aFlags & FLAG_SYNC_DECODE) {
|
|
|
|
rv = SyncDecode();
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the frame. If it's not there, it's probably the caller's fault for
|
|
|
|
// not waiting for the data to be loaded from the network or not passing
|
|
|
|
// FLAG_SYNC_DECODE
|
|
|
|
PRUint32 frameIndex = (aWhichFrame == FRAME_FIRST) ?
|
|
|
|
0 : GetCurrentImgFrameIndex();
|
2009-11-12 15:18:40 -08:00
|
|
|
imgFrame *frame = GetDrawableImgFrame(frameIndex);
|
2009-09-12 15:44:18 -07:00
|
|
|
if (!frame) {
|
|
|
|
*_retval = nsnull;
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<gfxASurface> framesurf;
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
// If this frame covers the entire image, we can just reuse its existing
|
|
|
|
// surface.
|
|
|
|
nsIntRect framerect = frame->GetRect();
|
|
|
|
if (framerect.x == 0 && framerect.y == 0 &&
|
|
|
|
framerect.width == mSize.width &&
|
|
|
|
framerect.height == mSize.height)
|
|
|
|
rv = frame->GetSurface(getter_AddRefs(framesurf));
|
|
|
|
|
|
|
|
// The image doesn't have a surface because it's been optimized away. Create
|
|
|
|
// one.
|
|
|
|
if (!framesurf) {
|
|
|
|
nsRefPtr<gfxImageSurface> imgsurf;
|
2009-09-12 15:44:18 -07:00
|
|
|
rv = CopyFrame(aWhichFrame, aFlags, getter_AddRefs(imgsurf));
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
framesurf = imgsurf;
|
|
|
|
}
|
|
|
|
|
|
|
|
*_retval = framesurf.forget().get();
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2011-07-18 06:20:27 -07:00
|
|
|
namespace {
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
PRUint32
|
2011-07-18 06:20:27 -07:00
|
|
|
GetDecodedSize(const nsTArray<imgFrame *> &aFrames,
|
|
|
|
gfxASurface::MemoryLocation aLocation)
|
2010-05-21 21:10:14 -07:00
|
|
|
{
|
|
|
|
PRUint32 val = 0;
|
2011-07-18 06:20:27 -07:00
|
|
|
for (PRUint32 i = 0; i < aFrames.Length(); ++i) {
|
|
|
|
imgFrame *frame = aFrames.SafeElementAt(i, nsnull);
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(frame, "Null frame in frame array!");
|
2011-07-18 06:20:27 -07:00
|
|
|
val += frame->EstimateMemoryUsed(aLocation);
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2010-05-21 21:10:14 -07:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2011-07-18 06:20:27 -07:00
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
PRUint32
|
|
|
|
RasterImage::GetDecodedHeapSize()
|
|
|
|
{
|
|
|
|
return GetDecodedSize(mFrames, gfxASurface::MEMORY_IN_PROCESS_HEAP);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32
|
|
|
|
RasterImage::GetDecodedNonheapSize()
|
|
|
|
{
|
|
|
|
return GetDecodedSize(mFrames, gfxASurface::MEMORY_IN_PROCESS_NONHEAP);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32
|
|
|
|
RasterImage::GetDecodedOutOfProcessSize()
|
|
|
|
{
|
|
|
|
return GetDecodedSize(mFrames, gfxASurface::MEMORY_OUT_OF_PROCESS);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
PRUint32
|
2011-07-18 06:20:27 -07:00
|
|
|
RasterImage::GetSourceHeapSize()
|
2010-05-21 21:10:14 -07:00
|
|
|
{
|
2010-10-06 08:37:12 -07:00
|
|
|
PRUint32 sourceDataSize = mSourceData.Length();
|
|
|
|
|
|
|
|
NS_ABORT_IF_FALSE(StoringSourceData() || (sourceDataSize == 0),
|
|
|
|
"Non-zero source data size when we aren't storing it?");
|
|
|
|
return sourceDataSize;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
void
|
|
|
|
RasterImage::DeleteImgFrame(PRUint32 framenum)
|
2010-03-08 11:01:04 -08:00
|
|
|
{
|
|
|
|
NS_ABORT_IF_FALSE(framenum < mFrames.Length(), "Deleting invalid frame!");
|
|
|
|
|
|
|
|
delete mFrames[framenum];
|
|
|
|
mFrames[framenum] = nsnull;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
|
|
|
RasterImage::InternalAddFrameHelper(PRUint32 framenum, imgFrame *aFrame,
|
|
|
|
PRUint8 **imageData, PRUint32 *imageLength,
|
|
|
|
PRUint32 **paletteData, PRUint32 *paletteLength)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(framenum <= mFrames.Length(), "Invalid frame index!");
|
|
|
|
if (framenum > mFrames.Length())
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
nsAutoPtr<imgFrame> frame(aFrame);
|
|
|
|
|
|
|
|
if (paletteData && paletteLength)
|
|
|
|
frame->GetPaletteData(paletteData, paletteLength);
|
|
|
|
|
|
|
|
frame->GetImageData(imageData, imageLength);
|
|
|
|
|
2010-02-25 10:14:30 -08:00
|
|
|
// We are in the middle of decoding. This will be unlocked when we finish the
|
|
|
|
// decoder->Write() call.
|
|
|
|
frame->LockImageData();
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
mFrames.InsertElementAt(framenum, frame.forget());
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
|
|
|
RasterImage::InternalAddFrame(PRUint32 framenum,
|
|
|
|
PRInt32 aX, PRInt32 aY,
|
|
|
|
PRInt32 aWidth, PRInt32 aHeight,
|
|
|
|
gfxASurface::gfxImageFormat aFormat,
|
|
|
|
PRUint8 aPaletteDepth,
|
|
|
|
PRUint8 **imageData,
|
|
|
|
PRUint32 *imageLength,
|
|
|
|
PRUint32 **paletteData,
|
|
|
|
PRUint32 *paletteLength)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2010-02-25 10:14:30 -08:00
|
|
|
// We assume that we're in the middle of decoding because we unlock the
|
|
|
|
// previous frame when we create a new frame, and only when decoding do we
|
|
|
|
// lock frames.
|
|
|
|
NS_ABORT_IF_FALSE(mInDecoder, "Only decoders may add frames!");
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(framenum <= mFrames.Length(), "Invalid frame index!");
|
|
|
|
if (framenum > mFrames.Length())
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
nsAutoPtr<imgFrame> frame(new imgFrame());
|
|
|
|
NS_ENSURE_TRUE(frame, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
nsresult rv = frame->Init(aX, aY, aWidth, aHeight, aFormat, aPaletteDepth);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2010-02-25 10:14:30 -08:00
|
|
|
// We know we are in a decoder. Therefore, we must unlock the previous frame
|
|
|
|
// when we move on to decoding into the next frame.
|
|
|
|
if (mFrames.Length() > 0) {
|
|
|
|
imgFrame *prevframe = mFrames.ElementAt(mFrames.Length() - 1);
|
|
|
|
prevframe->UnlockImageData();
|
|
|
|
}
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
if (mFrames.Length() == 0) {
|
|
|
|
return InternalAddFrameHelper(framenum, frame.forget(), imageData, imageLength,
|
|
|
|
paletteData, paletteLength);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
if (mFrames.Length() == 1) {
|
2007-10-22 09:13:37 -07:00
|
|
|
// Since we're about to add our second frame, initialize animation stuff
|
2011-07-23 11:49:00 -07:00
|
|
|
EnsureAnimExists();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// If we dispose of the first frame by clearing it, then the
|
|
|
|
// First Frame's refresh area is all of itself.
|
|
|
|
// RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
PRInt32 frameDisposalMethod = mFrames[0]->GetFrameDisposalMethod();
|
2010-08-13 21:09:49 -07:00
|
|
|
if (frameDisposalMethod == kDisposeClear ||
|
|
|
|
frameDisposalMethod == kDisposeRestorePrevious)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
mAnim->firstFrameRefreshArea = mFrames[0]->GetRect();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Calculate firstFrameRefreshArea
|
|
|
|
// Some gifs are huge but only have a small area that they animate
|
|
|
|
// We only need to refresh that small area when Frame 0 comes around again
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
nsIntRect frameRect = frame->GetRect();
|
2007-03-22 10:30:00 -07:00
|
|
|
mAnim->firstFrameRefreshArea.UnionRect(mAnim->firstFrameRefreshArea,
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
frameRect);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
rv = InternalAddFrameHelper(framenum, frame.forget(), imageData, imageLength,
|
|
|
|
paletteData, paletteLength);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2010-09-07 17:33:02 -07:00
|
|
|
// We may be able to start animating, if we now have enough frames
|
|
|
|
EvaluateAnimation();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::SetSize(PRInt32 aWidth, PRInt32 aHeight)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Ensure that we have positive values
|
|
|
|
// XXX - Why isn't the size unsigned? Should this be changed?
|
|
|
|
if ((aWidth < 0) || (aHeight < 0))
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
// if we already have a size, check the new size against the old one
|
|
|
|
if (mHasSize &&
|
|
|
|
((aWidth != mSize.width) || (aHeight != mSize.height))) {
|
|
|
|
|
|
|
|
// Alter the warning depending on whether the channel is multipart
|
|
|
|
if (!mMultipart)
|
|
|
|
NS_WARNING("Image changed size on redecode! This should not happen!");
|
|
|
|
else
|
|
|
|
NS_WARNING("Multipart channel sent an image of a different size");
|
|
|
|
|
2011-05-11 02:46:59 -07:00
|
|
|
// Make the decoder aware of the error so that it doesn't try to call
|
|
|
|
// FinishInternal during ShutdownDecoder.
|
|
|
|
if (mDecoder)
|
|
|
|
mDecoder->PostResizeError();
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
DoError();
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the size and flag that we have it
|
|
|
|
mSize.SizeTo(aWidth, aHeight);
|
|
|
|
mHasSize = PR_TRUE;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2011-07-14 11:47:43 -07:00
|
|
|
RasterImage::EnsureFrame(PRUint32 aFrameNum, PRInt32 aX, PRInt32 aY,
|
|
|
|
PRInt32 aWidth, PRInt32 aHeight,
|
|
|
|
gfxASurface::gfxImageFormat aFormat,
|
|
|
|
PRUint8 aPaletteDepth,
|
|
|
|
PRUint8 **imageData, PRUint32 *imageLength,
|
|
|
|
PRUint32 **paletteData, PRUint32 *paletteLength)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(imageData);
|
|
|
|
NS_ENSURE_ARG_POINTER(imageLength);
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(aFrameNum <= mFrames.Length(), "Invalid frame index!");
|
2011-07-14 11:47:43 -07:00
|
|
|
|
|
|
|
if (aPaletteDepth > 0) {
|
|
|
|
NS_ENSURE_ARG_POINTER(paletteData);
|
|
|
|
NS_ENSURE_ARG_POINTER(paletteLength);
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
if (aFrameNum > mFrames.Length())
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
// Adding a frame that doesn't already exist.
|
2009-09-12 15:44:18 -07:00
|
|
|
if (aFrameNum == mFrames.Length())
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return InternalAddFrame(aFrameNum, aX, aY, aWidth, aHeight, aFormat,
|
2011-07-14 11:47:43 -07:00
|
|
|
aPaletteDepth, imageData, imageLength,
|
|
|
|
paletteData, paletteLength);
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
imgFrame *frame = GetImgFrame(aFrameNum);
|
|
|
|
if (!frame)
|
|
|
|
return InternalAddFrame(aFrameNum, aX, aY, aWidth, aHeight, aFormat,
|
2011-07-14 11:47:43 -07:00
|
|
|
aPaletteDepth, imageData, imageLength,
|
|
|
|
paletteData, paletteLength);
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
// See if we can re-use the frame that already exists.
|
|
|
|
nsIntRect rect = frame->GetRect();
|
2010-12-07 18:20:52 -08:00
|
|
|
if (rect.x == aX && rect.y == aY && rect.width == aWidth &&
|
2011-07-14 11:47:43 -07:00
|
|
|
rect.height == aHeight && frame->GetFormat() == aFormat &&
|
|
|
|
frame->GetPaletteDepth() == aPaletteDepth) {
|
2010-12-07 18:20:52 -08:00
|
|
|
frame->GetImageData(imageData, imageLength);
|
2011-07-14 11:47:43 -07:00
|
|
|
if (paletteData) {
|
|
|
|
frame->GetPaletteData(paletteData, paletteLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can re-use the frame if it has image data.
|
|
|
|
if (*imageData && paletteData && *paletteData) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
if (*imageData && !paletteData) {
|
2010-12-07 18:20:52 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2010-12-07 18:20:52 -08:00
|
|
|
DeleteImgFrame(aFrameNum);
|
2011-07-14 11:47:43 -07:00
|
|
|
return InternalAddFrame(aFrameNum, aX, aY, aWidth, aHeight, aFormat,
|
|
|
|
aPaletteDepth, imageData, imageLength,
|
|
|
|
paletteData, paletteLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
RasterImage::EnsureFrame(PRUint32 aFramenum, PRInt32 aX, PRInt32 aY,
|
|
|
|
PRInt32 aWidth, PRInt32 aHeight,
|
|
|
|
gfxASurface::gfxImageFormat aFormat,
|
|
|
|
PRUint8** imageData, PRUint32* imageLength)
|
|
|
|
{
|
|
|
|
return EnsureFrame(aFramenum, aX, aY, aWidth, aHeight, aFormat,
|
|
|
|
/* aPaletteDepth = */ 0, imageData, imageLength,
|
|
|
|
/* aPaletteData = */ nsnull,
|
|
|
|
/* aPaletteLength = */ nsnull);
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
}
|
|
|
|
|
2010-08-24 14:12:04 -07:00
|
|
|
void
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::FrameUpdated(PRUint32 aFrameNum, nsIntRect &aUpdatedRect)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2010-08-24 13:40:45 -07:00
|
|
|
NS_ABORT_IF_FALSE(aFrameNum < mFrames.Length(), "Invalid frame index!");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2011-07-21 11:14:41 -07:00
|
|
|
imgFrame *frame = GetImgFrameNoDecode(aFrameNum);
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(frame, "Calling FrameUpdated on frame that doesn't exist!");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
frame->ImageUpdated(aUpdatedRect);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
|
|
|
RasterImage::SetFrameDisposalMethod(PRUint32 aFrameNum,
|
|
|
|
PRInt32 aDisposalMethod)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
NS_ABORT_IF_FALSE(aFrameNum < mFrames.Length(), "Invalid frame index!");
|
|
|
|
if (aFrameNum >= mFrames.Length())
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
imgFrame *frame = GetImgFrame(aFrameNum);
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(frame,
|
|
|
|
"Calling SetFrameDisposalMethod on frame that doesn't exist!");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
frame->SetFrameDisposalMethod(aDisposalMethod);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::SetFrameTimeout(PRUint32 aFrameNum, PRInt32 aTimeout)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
NS_ABORT_IF_FALSE(aFrameNum < mFrames.Length(), "Invalid frame index!");
|
|
|
|
if (aFrameNum >= mFrames.Length())
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
imgFrame *frame = GetImgFrame(aFrameNum);
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(frame, "Calling SetFrameTimeout on frame that doesn't exist!");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
frame->SetTimeout(aTimeout);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::SetFrameBlendMethod(PRUint32 aFrameNum, PRInt32 aBlendMethod)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
NS_ABORT_IF_FALSE(aFrameNum < mFrames.Length(), "Invalid frame index!");
|
|
|
|
if (aFrameNum >= mFrames.Length())
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
imgFrame *frame = GetImgFrame(aFrameNum);
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(frame, "Calling SetFrameBlendMethod on frame that doesn't exist!");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
frame->SetBlendMethod(aBlendMethod);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::SetFrameHasNoAlpha(PRUint32 aFrameNum)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
NS_ABORT_IF_FALSE(aFrameNum < mFrames.Length(), "Invalid frame index!");
|
|
|
|
if (aFrameNum >= mFrames.Length())
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
imgFrame *frame = GetImgFrame(aFrameNum);
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(frame, "Calling SetFrameHasNoAlpha on frame that doesn't exist!");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
frame->SetHasNoAlpha();
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::DecodingComplete()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Flag that we're done decoding.
|
|
|
|
// XXX - these should probably be combined when we fix animated image
|
|
|
|
// discarding with bug 500402.
|
|
|
|
mDecoded = PR_TRUE;
|
2009-10-06 21:39:30 -07:00
|
|
|
mHasBeenDecoded = PR_TRUE;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// We now have one of the qualifications for discarding. Re-evaluate.
|
|
|
|
if (CanDiscard()) {
|
2010-07-01 10:39:44 -07:00
|
|
|
NS_ABORT_IF_FALSE(!DiscardingActive(),
|
2009-09-12 15:44:18 -07:00
|
|
|
"We shouldn't have been discardable before this");
|
2010-08-13 21:09:49 -07:00
|
|
|
rv = DiscardTracker::Reset(&mDiscardTrackerNode);
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there's only 1 frame, optimize it. Optimizing animated images
|
|
|
|
// is not supported.
|
|
|
|
//
|
|
|
|
// We don't optimize the frame for multipart images because we reuse
|
|
|
|
// the frame.
|
|
|
|
if ((mFrames.Length() == 1) && !mMultipart) {
|
|
|
|
rv = mFrames[0]->Optimize();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
2010-09-07 17:33:02 -07:00
|
|
|
/* void StartAnimation () */
|
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::StartAnimation()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2010-09-07 17:33:02 -07:00
|
|
|
NS_ABORT_IF_FALSE(ShouldAnimate(), "Should not animate!");
|
|
|
|
|
2011-07-23 11:49:00 -07:00
|
|
|
EnsureAnimExists();
|
2010-09-07 17:33:02 -07:00
|
|
|
|
2011-10-07 00:24:27 -07:00
|
|
|
NS_ABORT_IF_FALSE(mAnim && !mAnim->timer, "Anim must exist and not have a timer yet");
|
|
|
|
|
|
|
|
// Default timeout to 100: the timer notify code will do the right
|
|
|
|
// thing, so just get that started.
|
|
|
|
PRInt32 timeout = 100;
|
|
|
|
imgFrame *currentFrame = GetCurrentImgFrame();
|
2010-09-07 17:33:02 -07:00
|
|
|
if (currentFrame) {
|
2011-10-07 00:24:27 -07:00
|
|
|
timeout = currentFrame->GetTimeout();
|
|
|
|
if (timeout < 0) { // -1 means display this frame forever
|
2010-09-07 17:33:02 -07:00
|
|
|
mAnimationFinished = PR_TRUE;
|
|
|
|
return NS_ERROR_ABORT;
|
2008-03-19 22:54:30 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-10-07 00:24:27 -07:00
|
|
|
mAnim->timer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
NS_ENSURE_TRUE(mAnim->timer, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
mAnim->timer->InitWithCallback(static_cast<nsITimerCallback*>(this),
|
|
|
|
timeout, nsITimer::TYPE_REPEATING_SLACK);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
/* void stopAnimation (); */
|
2010-09-07 17:33:02 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::StopAnimation()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2010-09-07 17:33:02 -07:00
|
|
|
NS_ABORT_IF_FALSE(mAnimating, "Should be animating!");
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2011-10-07 00:24:27 -07:00
|
|
|
if (mAnim->timer) {
|
|
|
|
mAnim->timer->Cancel();
|
|
|
|
mAnim->timer = nsnull;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
/* void resetAnimation (); */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::ResetAnimation()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mAnimationMode == kDontAnimMode ||
|
2007-10-03 14:41:12 -07:00
|
|
|
!mAnim || mAnim->currentAnimationFrameIndex == 0)
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
|
2011-03-31 14:05:31 -07:00
|
|
|
mAnimationFinished = PR_FALSE;
|
|
|
|
|
2010-09-07 17:33:02 -07:00
|
|
|
if (mAnimating)
|
|
|
|
StopAnimation();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
mAnim->lastCompositedFrameIndex = -1;
|
|
|
|
mAnim->currentAnimationFrameIndex = 0;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Note - We probably want to kick off a redecode somewhere around here when
|
|
|
|
// we fix bug 500402.
|
|
|
|
|
|
|
|
// Update display if we were animating before
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
|
2010-09-07 17:33:02 -07:00
|
|
|
if (mAnimating && observer)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
observer->FrameChanged(this, &(mAnim->firstFrameRefreshArea));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-03-31 14:05:31 -07:00
|
|
|
if (ShouldAnimate()) {
|
2010-09-07 17:33:02 -07:00
|
|
|
StartAnimation();
|
2011-03-31 14:05:31 -07:00
|
|
|
// The animation may not have been running before, if mAnimationFinished
|
|
|
|
// was false (before we changed it to true in this function). So, mark the
|
|
|
|
// animation as running.
|
|
|
|
mAnimating = PR_TRUE;
|
|
|
|
}
|
2010-09-07 17:33:02 -07:00
|
|
|
|
2008-03-19 22:54:30 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
void
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::SetLoopCount(PRInt32 aLoopCount)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
2010-08-13 21:09:49 -07:00
|
|
|
return;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// -1 infinite
|
|
|
|
// 0 no looping, one iteration
|
|
|
|
// 1 one loop, two iterations
|
|
|
|
// ...
|
|
|
|
mLoopCount = aLoopCount;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::AddSourceData(const char *aBuffer, PRUint32 aCount)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
2007-10-18 17:36:34 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aBuffer);
|
|
|
|
nsresult rv = NS_OK;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We should not call this if we're not initialized
|
|
|
|
NS_ABORT_IF_FALSE(mInitialized, "Calling AddSourceData() on uninitialized "
|
2010-08-13 21:09:49 -07:00
|
|
|
"RasterImage!");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We should not call this if we're already finished adding source data
|
|
|
|
NS_ABORT_IF_FALSE(!mHasSourceData, "Calling AddSourceData() after calling "
|
|
|
|
"sourceDataComplete()!");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// This call should come straight from necko - no reentrancy allowed
|
|
|
|
NS_ABORT_IF_FALSE(!mInDecoder, "Re-entrant call to AddSourceData!");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we're not storing source data, write it directly to the decoder
|
|
|
|
if (!StoringSourceData()) {
|
|
|
|
rv = WriteToDecoder(aBuffer, aCount);
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
2010-08-25 13:11:09 -07:00
|
|
|
|
|
|
|
// We're not storing source data, so this data is probably coming straight
|
|
|
|
// from the network. In this case, we want to display data as soon as we
|
|
|
|
// get it, so we want to flush invalidations after every write.
|
2011-05-11 02:46:59 -07:00
|
|
|
nsRefPtr<Decoder> kungFuDeathGrip = mDecoder;
|
2010-08-25 13:11:09 -07:00
|
|
|
mInDecoder = PR_TRUE;
|
|
|
|
mDecoder->FlushInvalidations();
|
|
|
|
mInDecoder = PR_FALSE;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Otherwise, we're storing data in the source buffer
|
|
|
|
else {
|
|
|
|
|
|
|
|
// Store the data
|
|
|
|
char *newElem = mSourceData.AppendElements(aBuffer, aCount);
|
|
|
|
if (!newElem)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If there's a decoder open, that means we want to do more decoding.
|
|
|
|
// Wake up the worker if it's not up already
|
|
|
|
if (mDecoder && !mWorkerPending) {
|
|
|
|
NS_ABORT_IF_FALSE(mWorker, "We should have a worker here!");
|
|
|
|
rv = mWorker->Run();
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Statistics
|
|
|
|
total_source_bytes += aCount;
|
|
|
|
if (mDiscardable)
|
|
|
|
discardable_source_bytes += aCount;
|
2007-10-18 17:36:34 -07:00
|
|
|
PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG,
|
2010-08-13 21:09:49 -07:00
|
|
|
("CompressedImageAccounting: Added compressed data to RasterImage %p (%s). "
|
2009-09-12 15:44:18 -07:00
|
|
|
"Total Containers: %d, Discardable containers: %d, "
|
|
|
|
"Total source bytes: %lld, Source bytes for discardable containers %lld",
|
2007-10-18 17:36:34 -07:00
|
|
|
this,
|
2009-09-12 15:44:18 -07:00
|
|
|
mSourceDataMimeType.get(),
|
|
|
|
num_containers,
|
|
|
|
num_discardable_containers,
|
|
|
|
total_source_bytes,
|
|
|
|
discardable_source_bytes));
|
2007-10-18 17:36:34 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note! buf must be declared as char buf[9]; */
|
|
|
|
// just used for logging and hashing the header
|
|
|
|
static void
|
|
|
|
get_header_str (char *buf, char *data, PRSize data_len)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int n;
|
|
|
|
static char hex[] = "0123456789abcdef";
|
|
|
|
|
|
|
|
n = data_len < 4 ? data_len : 4;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
buf[i * 2] = hex[(data[i] >> 4) & 0x0f];
|
|
|
|
buf[i * 2 + 1] = hex[data[i] & 0x0f];
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[i * 2] = 0;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::SourceDataComplete()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we've been called before, ignore. Otherwise, flag that we have everything
|
|
|
|
if (mHasSourceData)
|
2007-10-18 17:36:34 -07:00
|
|
|
return NS_OK;
|
2009-09-12 15:44:18 -07:00
|
|
|
mHasSourceData = PR_TRUE;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// This call should come straight from necko - no reentrancy allowed
|
|
|
|
NS_ABORT_IF_FALSE(!mInDecoder, "Re-entrant call to AddSourceData!");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we're not storing any source data, then all the data was written
|
|
|
|
// directly to the decoder in the AddSourceData() calls. This means we're
|
|
|
|
// done, so we can shut down the decoder.
|
|
|
|
if (!StoringSourceData()) {
|
|
|
|
nsresult rv = ShutdownDecoder(eShutdownIntent_Done);
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If there's a decoder open, we need to wake up the worker if it's not
|
|
|
|
// already. This is so the worker can account for the fact that the source
|
|
|
|
// data is complete. For some decoders, DecodingComplete() is only called
|
|
|
|
// when the decoder is Close()-ed, and thus the SourceDataComplete() call
|
|
|
|
// is the only way we can transition to a 'decoded' state. Furthermore,
|
|
|
|
// it's always possible for any image type to have the data stream stop
|
|
|
|
// abruptly at any point, in which case we need to trigger an error.
|
|
|
|
if (mDecoder && !mWorkerPending) {
|
|
|
|
NS_ABORT_IF_FALSE(mWorker, "We should have a worker here!");
|
|
|
|
nsresult rv = mWorker->Run();
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free up any extra space in the backing buffer
|
|
|
|
mSourceData.Compact();
|
|
|
|
|
|
|
|
// Log header information
|
2007-10-18 17:36:34 -07:00
|
|
|
if (PR_LOG_TEST(gCompressedImageAccountingLog, PR_LOG_DEBUG)) {
|
|
|
|
char buf[9];
|
2009-09-12 15:44:18 -07:00
|
|
|
get_header_str(buf, mSourceData.Elements(), mSourceData.Length());
|
2007-10-18 17:36:34 -07:00
|
|
|
PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG,
|
2010-08-13 21:09:49 -07:00
|
|
|
("CompressedImageAccounting: RasterImage::SourceDataComplete() - data "
|
2009-09-12 15:44:18 -07:00
|
|
|
"is done for container %p (%s) - header %p is 0x%s (length %d)",
|
2007-10-18 17:36:34 -07:00
|
|
|
this,
|
2009-09-12 15:44:18 -07:00
|
|
|
mSourceDataMimeType.get(),
|
|
|
|
mSourceData.Elements(),
|
2007-10-18 17:36:34 -07:00
|
|
|
buf,
|
2009-09-12 15:44:18 -07:00
|
|
|
mSourceData.Length()));
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We now have one of the qualifications for discarding. Re-evaluate.
|
|
|
|
if (CanDiscard()) {
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult rv = DiscardTracker::Reset(&mDiscardTrackerNode);
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::NewSourceData()
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// The source data should be complete before calling this
|
|
|
|
NS_ABORT_IF_FALSE(mHasSourceData,
|
|
|
|
"Calling NewSourceData before SourceDataComplete!");
|
|
|
|
if (!mHasSourceData)
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
|
|
|
|
// Only supported for multipart channels. It wouldn't be too hard to change this,
|
|
|
|
// but it would involve making sure that things worked for decode-on-draw and
|
|
|
|
// discarding. Presently there's no need for this, so we don't.
|
|
|
|
NS_ABORT_IF_FALSE(mMultipart, "NewSourceData not supported for multipart");
|
|
|
|
if (!mMultipart)
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
|
|
|
|
// We're multipart, so we shouldn't be storing source data
|
|
|
|
NS_ABORT_IF_FALSE(!StoringSourceData(),
|
|
|
|
"Shouldn't be storing source data for multipart");
|
|
|
|
|
|
|
|
// We're not storing the source data and we got SourceDataComplete. We should
|
|
|
|
// have shut down the previous decoder
|
|
|
|
NS_ABORT_IF_FALSE(!mDecoder, "Shouldn't have a decoder in NewSourceData");
|
|
|
|
|
|
|
|
// The decoder was shut down and we didn't flag an error, so we should be decoded
|
|
|
|
NS_ABORT_IF_FALSE(mDecoded, "Should be decoded in NewSourceData");
|
|
|
|
|
|
|
|
// Reset some flags
|
|
|
|
mDecoded = PR_FALSE;
|
|
|
|
mHasSourceData = PR_FALSE;
|
|
|
|
|
|
|
|
// We're decode-on-load here. Open up a new decoder just like what happens when
|
|
|
|
// we call Init() for decode-on-load images.
|
2010-08-22 19:30:46 -07:00
|
|
|
rv = InitDecoder(/* aDoSizeDecode = */ false);
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
|
|
|
|
return NS_OK;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::SetSourceSizeHint(PRUint32 sizeHint)
|
2010-06-25 11:21:40 -07:00
|
|
|
{
|
|
|
|
if (sizeHint && StoringSourceData())
|
2011-06-08 19:21:53 -07:00
|
|
|
return mSourceData.SetCapacity(sizeHint) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
2010-06-25 11:21:40 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//******************************************************************************
|
2011-10-07 00:24:27 -07:00
|
|
|
/* void notify(in nsITimer timer); */
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Notify(nsITimer *timer)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
mFramesNotified++;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// This should never happen since the timer is only set up in StartAnimation()
|
|
|
|
// after mAnim is checked to exist.
|
|
|
|
NS_ABORT_IF_FALSE(mAnim, "Need anim for Notify()");
|
|
|
|
NS_ABORT_IF_FALSE(timer, "Need timer for Notify()");
|
|
|
|
NS_ABORT_IF_FALSE(mAnim->timer == timer,
|
|
|
|
"RasterImage::Notify() called with incorrect timer");
|
|
|
|
|
|
|
|
if (!mAnimating || !ShouldAnimate())
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
|
|
|
|
if (!observer) {
|
|
|
|
// the imgRequest that owns us is dead, we should die now too.
|
|
|
|
NS_ABORT_IF_FALSE(mAnimationConsumers == 0,
|
|
|
|
"If no observer, should have no consumers");
|
|
|
|
if (mAnimating)
|
|
|
|
StopAnimation();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mFrames.Length() == 0)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
imgFrame *nextFrame = nsnull;
|
|
|
|
PRInt32 previousFrameIndex = mAnim->currentAnimationFrameIndex;
|
|
|
|
PRUint32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1;
|
|
|
|
PRInt32 timeout = 0;
|
|
|
|
|
|
|
|
// Figure out if we have the next full frame. This is more complicated than
|
|
|
|
// just checking for mFrames.Length() because decoders append their frames
|
|
|
|
// before they're filled in.
|
|
|
|
NS_ABORT_IF_FALSE(mDecoder || nextFrameIndex <= mFrames.Length(),
|
|
|
|
"How did we get 2 indicies too far by incrementing?");
|
|
|
|
|
|
|
|
// If we don't have a decoder, we know we've got everything we're going to get.
|
|
|
|
// If we do, we only display fully-downloaded frames; everything else gets delayed.
|
|
|
|
bool haveFullNextFrame = !mDecoder || nextFrameIndex < mDecoder->GetCompleteFrameCount();
|
|
|
|
|
|
|
|
// If we're done decoding the next frame, go ahead and display it now and
|
|
|
|
// reinit the timer with the next frame's delay time.
|
|
|
|
if (haveFullNextFrame) {
|
|
|
|
if (mFrames.Length() == nextFrameIndex) {
|
|
|
|
// End of Animation
|
|
|
|
|
|
|
|
// If animation mode is "loop once", it's time to stop animating
|
|
|
|
if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) {
|
|
|
|
mAnimationFinished = PR_TRUE;
|
|
|
|
EvaluateAnimation();
|
|
|
|
return NS_OK;
|
|
|
|
} else {
|
|
|
|
// We may have used compositingFrame to build a frame, and then copied
|
|
|
|
// it back into mFrames[..]. If so, delete composite to save memory
|
|
|
|
if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1)
|
|
|
|
mAnim->compositingFrame = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nextFrameIndex = 0;
|
|
|
|
if (mLoopCount > 0)
|
|
|
|
mLoopCount--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(nextFrame = mFrames[nextFrameIndex])) {
|
|
|
|
// something wrong with the next frame, skip it
|
|
|
|
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
|
|
|
mAnim->timer->SetDelay(100);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
timeout = nextFrame->GetTimeout();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Uh oh, the frame we want to show is currently being decoded (partial)
|
|
|
|
// Wait a bit and try again
|
|
|
|
mAnim->timer->SetDelay(100);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (timeout > 0)
|
|
|
|
mAnim->timer->SetDelay(timeout);
|
|
|
|
else {
|
|
|
|
mAnimationFinished = PR_TRUE;
|
|
|
|
EvaluateAnimation();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIntRect dirtyRect;
|
|
|
|
|
|
|
|
if (nextFrameIndex == 0) {
|
|
|
|
dirtyRect = mAnim->firstFrameRefreshArea;
|
|
|
|
} else {
|
|
|
|
imgFrame *prevFrame = mFrames[previousFrameIndex];
|
|
|
|
if (!prevFrame)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// Change frame and announce it
|
2011-10-07 21:03:47 -07:00
|
|
|
if (NS_FAILED(DoComposite(&dirtyRect, prevFrame,
|
2011-10-07 00:24:27 -07:00
|
|
|
nextFrame, nextFrameIndex))) {
|
|
|
|
// something went wrong, move on to next
|
|
|
|
NS_WARNING("RasterImage::Notify(): Composing Frame Failed\n");
|
|
|
|
nextFrame->SetCompositingFailed(PR_TRUE);
|
|
|
|
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
|
|
|
return NS_OK;
|
|
|
|
} else {
|
|
|
|
nextFrame->SetCompositingFailed(PR_FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Set currentAnimationFrameIndex at the last possible moment
|
|
|
|
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
|
|
|
// Refreshes the screen
|
|
|
|
observer->FrameChanged(this, &dirtyRect);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
2007-03-22 10:30:00 -07:00
|
|
|
// DoComposite gets called when the timer for animation get fired and we have to
|
|
|
|
// update the composited frame of the animation.
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
2011-10-07 21:03:47 -07:00
|
|
|
RasterImage::DoComposite(nsIntRect* aDirtyRect,
|
2010-08-13 21:09:49 -07:00
|
|
|
imgFrame* aPrevFrame,
|
|
|
|
imgFrame* aNextFrame,
|
|
|
|
PRInt32 aNextFrameIndex)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-03-19 22:54:30 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aDirtyRect);
|
|
|
|
NS_ENSURE_ARG_POINTER(aPrevFrame);
|
|
|
|
NS_ENSURE_ARG_POINTER(aNextFrame);
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
PRInt32 prevFrameDisposalMethod = aPrevFrame->GetFrameDisposalMethod();
|
2010-08-13 21:09:49 -07:00
|
|
|
if (prevFrameDisposalMethod == kDisposeRestorePrevious &&
|
2007-03-22 10:30:00 -07:00
|
|
|
!mAnim->compositingPrevFrame)
|
2010-08-13 21:09:49 -07:00
|
|
|
prevFrameDisposalMethod = kDisposeClear;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
nsIntRect prevFrameRect = aPrevFrame->GetRect();
|
2011-07-20 14:52:30 -07:00
|
|
|
bool isFullPrevFrame = (prevFrameRect.x == 0 && prevFrameRect.y == 0 &&
|
|
|
|
prevFrameRect.width == mSize.width &&
|
|
|
|
prevFrameRect.height == mSize.height);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-11-07 13:33:57 -08:00
|
|
|
// Optimization: DisposeClearAll if the previous frame is the same size as
|
2007-03-22 10:30:00 -07:00
|
|
|
// container and it's clearing itself
|
2007-11-07 13:33:57 -08:00
|
|
|
if (isFullPrevFrame &&
|
2010-08-13 21:09:49 -07:00
|
|
|
(prevFrameDisposalMethod == kDisposeClear))
|
|
|
|
prevFrameDisposalMethod = kDisposeClearAll;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
PRInt32 nextFrameDisposalMethod = aNextFrame->GetFrameDisposalMethod();
|
|
|
|
nsIntRect nextFrameRect = aNextFrame->GetRect();
|
2011-07-20 14:52:30 -07:00
|
|
|
bool isFullNextFrame = (nextFrameRect.x == 0 && nextFrameRect.y == 0 &&
|
|
|
|
nextFrameRect.width == mSize.width &&
|
|
|
|
nextFrameRect.height == mSize.height);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
if (!aNextFrame->GetIsPaletted()) {
|
2007-11-07 13:33:57 -08:00
|
|
|
// Optimization: Skip compositing if the previous frame wants to clear the
|
|
|
|
// whole image
|
2010-08-13 21:09:49 -07:00
|
|
|
if (prevFrameDisposalMethod == kDisposeClearAll) {
|
2007-11-07 13:33:57 -08:00
|
|
|
aDirtyRect->SetRect(0, 0, mSize.width, mSize.height);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Optimization: Skip compositing if this frame is the same size as the
|
|
|
|
// container and it's fully drawing over prev frame (no alpha)
|
|
|
|
if (isFullNextFrame &&
|
2010-08-13 21:09:49 -07:00
|
|
|
(nextFrameDisposalMethod != kDisposeRestorePrevious) &&
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
!aNextFrame->GetHasAlpha()) {
|
2007-11-07 13:33:57 -08:00
|
|
|
aDirtyRect->SetRect(0, 0, mSize.width, mSize.height);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate area that needs updating
|
|
|
|
switch (prevFrameDisposalMethod) {
|
|
|
|
default:
|
2010-08-13 21:09:49 -07:00
|
|
|
case kDisposeNotSpecified:
|
|
|
|
case kDisposeKeep:
|
2007-03-22 10:30:00 -07:00
|
|
|
*aDirtyRect = nextFrameRect;
|
|
|
|
break;
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
case kDisposeClearAll:
|
2007-11-07 13:33:57 -08:00
|
|
|
// Whole image container is cleared
|
|
|
|
aDirtyRect->SetRect(0, 0, mSize.width, mSize.height);
|
|
|
|
break;
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
case kDisposeClear:
|
2007-03-22 10:30:00 -07:00
|
|
|
// Calc area that needs to be redrawn (the combination of previous and
|
|
|
|
// this frame)
|
|
|
|
// XXX - This could be done with multiple framechanged calls
|
|
|
|
// Having prevFrame way at the top of the image, and nextFrame
|
|
|
|
// way at the bottom, and both frames being small, we'd be
|
|
|
|
// telling framechanged to refresh the whole image when only two
|
|
|
|
// small areas are needed.
|
|
|
|
aDirtyRect->UnionRect(nextFrameRect, prevFrameRect);
|
|
|
|
break;
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
case kDisposeRestorePrevious:
|
2007-03-22 10:30:00 -07:00
|
|
|
aDirtyRect->SetRect(0, 0, mSize.width, mSize.height);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Optimization:
|
|
|
|
// Skip compositing if the last composited frame is this frame
|
|
|
|
// (Only one composited frame was made for this animation. Example:
|
|
|
|
// Only Frame 3 of a 10 frame image required us to build a composite frame
|
|
|
|
// On the second loop, we do not need to rebuild the frame
|
|
|
|
// since it's still sitting in compositingFrame)
|
|
|
|
if (mAnim->lastCompositedFrameIndex == aNextFrameIndex) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-07-20 14:52:30 -07:00
|
|
|
bool needToBlankComposite = false;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Create the Compositing Frame
|
|
|
|
if (!mAnim->compositingFrame) {
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
mAnim->compositingFrame = new imgFrame();
|
|
|
|
if (!mAnim->compositingFrame) {
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_WARNING("Failed to init compositingFrame!\n");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
nsresult rv = mAnim->compositingFrame->Init(0, 0, mSize.width, mSize.height,
|
|
|
|
gfxASurface::ImageFormatARGB32);
|
2009-11-18 15:20:27 -08:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
mAnim->compositingFrame = nsnull;
|
|
|
|
return rv;
|
|
|
|
}
|
2011-07-20 14:52:30 -07:00
|
|
|
needToBlankComposite = true;
|
2010-06-16 09:54:18 -07:00
|
|
|
} else if (aNextFrameIndex != mAnim->lastCompositedFrameIndex+1) {
|
|
|
|
|
2010-09-07 12:10:42 -07:00
|
|
|
// If we are not drawing on top of last composited frame,
|
|
|
|
// then we are building a new composite frame, so let's clear it first.
|
2011-07-20 14:52:30 -07:00
|
|
|
needToBlankComposite = true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-11-07 13:33:57 -08:00
|
|
|
// More optimizations possible when next frame is not transparent
|
2010-09-07 12:10:42 -07:00
|
|
|
// But if the next frame has kDisposeRestorePrevious,
|
|
|
|
// this "no disposal" optimization is not possible,
|
|
|
|
// because the frame in "after disposal operation" state
|
|
|
|
// needs to be stored in compositingFrame, so it can be
|
|
|
|
// copied into compositingPrevFrame later.
|
2011-07-20 14:52:30 -07:00
|
|
|
bool doDisposal = true;
|
2010-09-07 12:10:42 -07:00
|
|
|
if (!aNextFrame->GetHasAlpha() &&
|
|
|
|
nextFrameDisposalMethod != kDisposeRestorePrevious) {
|
2007-11-07 13:33:57 -08:00
|
|
|
if (isFullNextFrame) {
|
|
|
|
// Optimization: No need to dispose prev.frame when
|
|
|
|
// next frame is full frame and not transparent.
|
2011-07-20 14:52:30 -07:00
|
|
|
doDisposal = false;
|
2007-11-07 13:33:57 -08:00
|
|
|
// No need to blank the composite frame
|
2011-07-20 14:52:30 -07:00
|
|
|
needToBlankComposite = false;
|
2007-11-07 13:33:57 -08:00
|
|
|
} else {
|
|
|
|
if ((prevFrameRect.x >= nextFrameRect.x) &&
|
|
|
|
(prevFrameRect.y >= nextFrameRect.y) &&
|
|
|
|
(prevFrameRect.x + prevFrameRect.width <= nextFrameRect.x + nextFrameRect.width) &&
|
|
|
|
(prevFrameRect.y + prevFrameRect.height <= nextFrameRect.y + nextFrameRect.height)) {
|
|
|
|
// Optimization: No need to dispose prev.frame when
|
|
|
|
// next frame fully overlaps previous frame.
|
2011-07-20 14:52:30 -07:00
|
|
|
doDisposal = false;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-11-07 13:33:57 -08:00
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-11-07 13:33:57 -08:00
|
|
|
if (doDisposal) {
|
|
|
|
// Dispose of previous: clear, restore, or keep (copy)
|
|
|
|
switch (prevFrameDisposalMethod) {
|
2010-08-13 21:09:49 -07:00
|
|
|
case kDisposeClear:
|
2007-11-07 13:33:57 -08:00
|
|
|
if (needToBlankComposite) {
|
|
|
|
// If we just created the composite, it could have anything in it's
|
|
|
|
// buffer. Clear whole frame
|
|
|
|
ClearFrame(mAnim->compositingFrame);
|
|
|
|
} else {
|
|
|
|
// Only blank out previous frame area (both color & Mask/Alpha)
|
|
|
|
ClearFrame(mAnim->compositingFrame, prevFrameRect);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
case kDisposeClearAll:
|
2007-06-07 08:10:25 -07:00
|
|
|
ClearFrame(mAnim->compositingFrame);
|
2007-11-07 13:33:57 -08:00
|
|
|
break;
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
case kDisposeRestorePrevious:
|
2007-11-07 13:33:57 -08:00
|
|
|
// It would be better to copy only the area changed back to
|
|
|
|
// compositingFrame.
|
|
|
|
if (mAnim->compositingPrevFrame) {
|
|
|
|
CopyFrameImage(mAnim->compositingPrevFrame, mAnim->compositingFrame);
|
|
|
|
|
|
|
|
// destroy only if we don't need it for this frame's disposal
|
2010-08-13 21:09:49 -07:00
|
|
|
if (nextFrameDisposalMethod != kDisposeRestorePrevious)
|
2007-11-07 13:33:57 -08:00
|
|
|
mAnim->compositingPrevFrame = nsnull;
|
|
|
|
} else {
|
|
|
|
ClearFrame(mAnim->compositingFrame);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Copy previous frame into compositingFrame before we put the new frame on top
|
|
|
|
// Assumes that the previous frame represents a full frame (it could be
|
|
|
|
// smaller in size than the container, as long as the frame before it erased
|
|
|
|
// itself)
|
|
|
|
// Note: Frame 1 never gets into DoComposite(), so (aNextFrameIndex - 1) will
|
|
|
|
// always be a valid frame number.
|
|
|
|
if (mAnim->lastCompositedFrameIndex != aNextFrameIndex - 1) {
|
2009-09-02 08:48:23 -07:00
|
|
|
if (isFullPrevFrame && !aPrevFrame->GetIsPaletted()) {
|
2007-11-07 13:33:57 -08:00
|
|
|
// Just copy the bits
|
|
|
|
CopyFrameImage(aPrevFrame, mAnim->compositingFrame);
|
|
|
|
} else {
|
|
|
|
if (needToBlankComposite) {
|
|
|
|
// Only blank composite when prev is transparent or not full.
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
if (aPrevFrame->GetHasAlpha() || !isFullPrevFrame) {
|
2007-11-07 13:33:57 -08:00
|
|
|
ClearFrame(mAnim->compositingFrame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DrawFrameTo(aPrevFrame, mAnim->compositingFrame, prevFrameRect);
|
|
|
|
}
|
|
|
|
}
|
2009-09-02 08:48:23 -07:00
|
|
|
}
|
2007-11-07 13:33:57 -08:00
|
|
|
} else if (needToBlankComposite) {
|
|
|
|
// If we just created the composite, it could have anything in it's
|
|
|
|
// buffers. Clear them
|
|
|
|
ClearFrame(mAnim->compositingFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the frame we are composing wants the previous image restored afer
|
2007-10-23 12:33:20 -07:00
|
|
|
// it is done. Don't store it (again) if last frame wanted its image restored
|
2007-03-22 10:30:00 -07:00
|
|
|
// too
|
2010-08-13 21:09:49 -07:00
|
|
|
if ((nextFrameDisposalMethod == kDisposeRestorePrevious) &&
|
|
|
|
(prevFrameDisposalMethod != kDisposeRestorePrevious)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// We are storing the whole image.
|
|
|
|
// It would be better if we just stored the area that nextFrame is going to
|
|
|
|
// overwrite.
|
|
|
|
if (!mAnim->compositingPrevFrame) {
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
mAnim->compositingPrevFrame = new imgFrame();
|
|
|
|
if (!mAnim->compositingPrevFrame) {
|
2010-09-07 12:10:42 -07:00
|
|
|
NS_WARNING("Failed to init compositingPrevFrame!\n");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
nsresult rv = mAnim->compositingPrevFrame->Init(0, 0, mSize.width, mSize.height,
|
|
|
|
gfxASurface::ImageFormatARGB32);
|
2009-11-18 15:20:27 -08:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
mAnim->compositingPrevFrame = nsnull;
|
|
|
|
return rv;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
CopyFrameImage(mAnim->compositingFrame, mAnim->compositingPrevFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
// blit next frame into it's correct spot
|
2007-08-25 12:18:44 -07:00
|
|
|
DrawFrameTo(aNextFrame, mAnim->compositingFrame, nextFrameRect);
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Set timeout of CompositeFrame to timeout of frame we just composed
|
|
|
|
// Bug 177948
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
PRInt32 timeout = aNextFrame->GetTimeout();
|
2007-03-22 10:30:00 -07:00
|
|
|
mAnim->compositingFrame->SetTimeout(timeout);
|
|
|
|
|
2007-11-07 13:33:57 -08:00
|
|
|
// Tell the image that it is fully 'downloaded'.
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
nsresult rv = mAnim->compositingFrame->ImageUpdated(mAnim->compositingFrame->GetRect());
|
2008-09-10 13:23:29 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2007-11-07 13:33:57 -08:00
|
|
|
|
2010-09-07 12:10:42 -07:00
|
|
|
// We don't want to keep composite images for 8bit frames.
|
|
|
|
// Also this optimization won't work if the next frame has
|
|
|
|
// kDisposeRestorePrevious, because it would need to be restored
|
|
|
|
// into "after prev disposal but before next blend" state,
|
|
|
|
// not into empty frame.
|
2007-11-07 13:33:57 -08:00
|
|
|
if (isFullNextFrame && mAnimationMode == kNormalAnimMode && mLoopCount != 0 &&
|
2010-09-07 12:10:42 -07:00
|
|
|
nextFrameDisposalMethod != kDisposeRestorePrevious &&
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
!aNextFrame->GetIsPaletted()) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// We have a composited full frame
|
|
|
|
// Store the composited frame into the mFrames[..] so we don't have to
|
|
|
|
// continuously re-build it
|
|
|
|
// Then set the previous frame's disposal to CLEAR_ALL so we just draw the
|
|
|
|
// frame next time around
|
|
|
|
if (CopyFrameImage(mAnim->compositingFrame, aNextFrame)) {
|
2010-08-13 21:09:49 -07:00
|
|
|
aPrevFrame->SetFrameDisposalMethod(kDisposeClearAll);
|
2007-03-22 10:30:00 -07:00
|
|
|
mAnim->lastCompositedFrameIndex = -1;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mAnim->lastCompositedFrameIndex = aNextFrameIndex;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
2007-06-07 08:10:25 -07:00
|
|
|
// Fill aFrame with black. Does also clears the mask.
|
2010-08-13 21:09:49 -07:00
|
|
|
void
|
|
|
|
RasterImage::ClearFrame(imgFrame *aFrame)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
if (!aFrame)
|
|
|
|
return;
|
|
|
|
|
2009-11-18 15:20:24 -08:00
|
|
|
nsresult rv = aFrame->LockImageData();
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
2008-03-05 22:51:13 -08:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
nsRefPtr<gfxASurface> surf;
|
|
|
|
aFrame->GetSurface(getter_AddRefs(surf));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-06-07 08:10:25 -07:00
|
|
|
// Erase the surface to transparent
|
|
|
|
gfxContext ctx(surf);
|
|
|
|
ctx.SetOperator(gfxContext::OPERATOR_CLEAR);
|
|
|
|
ctx.Paint();
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
aFrame->UnlockImageData();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
2010-08-13 21:09:49 -07:00
|
|
|
void
|
|
|
|
RasterImage::ClearFrame(imgFrame *aFrame, nsIntRect &aRect)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
if (!aFrame || aRect.width <= 0 || aRect.height <= 0)
|
2007-03-22 10:30:00 -07:00
|
|
|
return;
|
|
|
|
|
2009-11-18 15:20:24 -08:00
|
|
|
nsresult rv = aFrame->LockImageData();
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
2008-03-05 22:51:13 -08:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
nsRefPtr<gfxASurface> surf;
|
|
|
|
aFrame->GetSurface(getter_AddRefs(surf));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-06-07 08:10:25 -07:00
|
|
|
// Erase the destination rectangle to transparent
|
|
|
|
gfxContext ctx(surf);
|
|
|
|
ctx.SetOperator(gfxContext::OPERATOR_CLEAR);
|
|
|
|
ctx.Rectangle(gfxRect(aRect.x, aRect.y, aRect.width, aRect.height));
|
|
|
|
ctx.Fill();
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
aFrame->UnlockImageData();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
|
|
// Whether we succeed or fail will not cause a crash, and there's not much
|
|
|
|
// we can do about a failure, so there we don't return a nsresult
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::CopyFrameImage(imgFrame *aSrcFrame,
|
|
|
|
imgFrame *aDstFrame)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
PRUint8* aDataSrc;
|
|
|
|
PRUint8* aDataDest;
|
|
|
|
PRUint32 aDataLengthSrc;
|
|
|
|
PRUint32 aDataLengthDest;
|
|
|
|
|
|
|
|
if (!aSrcFrame || !aDstFrame)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
if (NS_FAILED(aDstFrame->LockImageData()))
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
// Copy Image Over
|
|
|
|
aSrcFrame->GetImageData(&aDataSrc, &aDataLengthSrc);
|
|
|
|
aDstFrame->GetImageData(&aDataDest, &aDataLengthDest);
|
|
|
|
if (!aDataDest || !aDataSrc || aDataLengthDest != aDataLengthSrc) {
|
|
|
|
aDstFrame->UnlockImageData();
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
memcpy(aDataDest, aDataSrc, aDataLengthSrc);
|
|
|
|
aDstFrame->UnlockImageData();
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2007-06-21 13:45:49 -07:00
|
|
|
|
2007-08-25 12:18:44 -07:00
|
|
|
//******************************************************************************
|
2008-01-21 23:36:57 -08:00
|
|
|
/*
|
|
|
|
* aSrc is the current frame being drawn,
|
|
|
|
* aDst is the composition frame where the current frame is drawn into.
|
|
|
|
* aSrcRect is the size of the current frame, and the position of that frame
|
|
|
|
* in the composition frame.
|
|
|
|
*/
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult
|
|
|
|
RasterImage::DrawFrameTo(imgFrame *aSrc,
|
|
|
|
imgFrame *aDst,
|
|
|
|
nsIntRect& aSrcRect)
|
2007-08-25 12:18:44 -07:00
|
|
|
{
|
2008-01-21 23:36:57 -08:00
|
|
|
NS_ENSURE_ARG_POINTER(aSrc);
|
|
|
|
NS_ENSURE_ARG_POINTER(aDst);
|
2007-08-25 12:18:44 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
nsIntRect dstRect = aDst->GetRect();
|
2007-11-07 13:33:57 -08:00
|
|
|
|
2008-01-21 23:36:57 -08:00
|
|
|
// According to both AGIF and APNG specs, offsets are unsigned
|
|
|
|
if (aSrcRect.x < 0 || aSrcRect.y < 0) {
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_WARNING("RasterImage::DrawFrameTo: negative offsets not allowed");
|
2008-01-21 23:36:57 -08:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
// Outside the destination frame, skip it
|
|
|
|
if ((aSrcRect.x > dstRect.width) || (aSrcRect.y > dstRect.height)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
if (aSrc->GetIsPaletted()) {
|
2007-11-17 01:23:51 -08:00
|
|
|
// Larger than the destination frame, clip it
|
2011-06-02 05:56:50 -07:00
|
|
|
PRInt32 width = NS_MIN(aSrcRect.width, dstRect.width - aSrcRect.x);
|
|
|
|
PRInt32 height = NS_MIN(aSrcRect.height, dstRect.height - aSrcRect.y);
|
2008-01-21 23:36:57 -08:00
|
|
|
|
|
|
|
// The clipped image must now fully fit within destination image frame
|
|
|
|
NS_ASSERTION((aSrcRect.x >= 0) && (aSrcRect.y >= 0) &&
|
|
|
|
(aSrcRect.x + width <= dstRect.width) &&
|
|
|
|
(aSrcRect.y + height <= dstRect.height),
|
2010-08-13 21:09:49 -07:00
|
|
|
"RasterImage::DrawFrameTo: Invalid aSrcRect");
|
2008-01-21 23:36:57 -08:00
|
|
|
|
|
|
|
// clipped image size may be smaller than source, but not larger
|
|
|
|
NS_ASSERTION((width <= aSrcRect.width) && (height <= aSrcRect.height),
|
2010-08-13 21:09:49 -07:00
|
|
|
"RasterImage::DrawFrameTo: source must be smaller than dest");
|
2007-11-07 13:33:57 -08:00
|
|
|
|
|
|
|
if (NS_FAILED(aDst->LockImageData()))
|
|
|
|
return NS_ERROR_FAILURE;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2007-11-07 13:33:57 -08:00
|
|
|
// Get pointers to image data
|
|
|
|
PRUint32 size;
|
|
|
|
PRUint8 *srcPixels;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
PRUint32 *colormap;
|
|
|
|
PRUint32 *dstPixels;
|
2007-11-07 13:33:57 -08:00
|
|
|
|
|
|
|
aSrc->GetImageData(&srcPixels, &size);
|
|
|
|
aSrc->GetPaletteData(&colormap, &size);
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
aDst->GetImageData((PRUint8 **)&dstPixels, &size);
|
2007-11-07 13:33:57 -08:00
|
|
|
if (!srcPixels || !dstPixels || !colormap) {
|
|
|
|
aDst->UnlockImageData();
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip to the right offset
|
2008-01-21 23:36:57 -08:00
|
|
|
dstPixels += aSrcRect.x + (aSrcRect.y * dstRect.width);
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
if (!aSrc->GetHasAlpha()) {
|
2007-12-21 03:41:59 -08:00
|
|
|
for (PRInt32 r = height; r > 0; --r) {
|
|
|
|
for (PRInt32 c = 0; c < width; c++) {
|
|
|
|
dstPixels[c] = colormap[srcPixels[c]];
|
2007-11-07 13:33:57 -08:00
|
|
|
}
|
2007-12-21 03:41:59 -08:00
|
|
|
// Go to the next row in the source resp. destination image
|
2008-01-21 23:36:57 -08:00
|
|
|
srcPixels += aSrcRect.width;
|
2007-12-21 03:41:59 -08:00
|
|
|
dstPixels += dstRect.width;
|
2007-11-07 13:33:57 -08:00
|
|
|
}
|
|
|
|
} else {
|
2007-12-21 03:41:59 -08:00
|
|
|
for (PRInt32 r = height; r > 0; --r) {
|
|
|
|
for (PRInt32 c = 0; c < width; c++) {
|
|
|
|
const PRUint32 color = colormap[srcPixels[c]];
|
2007-11-07 13:33:57 -08:00
|
|
|
if (color)
|
2007-12-21 03:41:59 -08:00
|
|
|
dstPixels[c] = color;
|
2007-11-07 13:33:57 -08:00
|
|
|
}
|
2007-12-21 03:41:59 -08:00
|
|
|
// Go to the next row in the source resp. destination image
|
2008-01-21 23:36:57 -08:00
|
|
|
srcPixels += aSrcRect.width;
|
2007-12-21 03:41:59 -08:00
|
|
|
dstPixels += dstRect.width;
|
2007-11-07 13:33:57 -08:00
|
|
|
}
|
|
|
|
}
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2007-11-07 13:33:57 -08:00
|
|
|
aDst->UnlockImageData();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-03-05 22:51:13 -08:00
|
|
|
nsRefPtr<gfxPattern> srcPatt;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
aSrc->GetPattern(getter_AddRefs(srcPatt));
|
2007-08-25 12:18:44 -07:00
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
aDst->LockImageData();
|
2007-08-25 12:18:44 -07:00
|
|
|
nsRefPtr<gfxASurface> dstSurf;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
aDst->GetSurface(getter_AddRefs(dstSurf));
|
2007-08-25 12:18:44 -07:00
|
|
|
|
|
|
|
gfxContext dst(dstSurf);
|
2008-01-21 23:36:57 -08:00
|
|
|
dst.Translate(gfxPoint(aSrcRect.x, aSrcRect.y));
|
|
|
|
dst.Rectangle(gfxRect(0, 0, aSrcRect.width, aSrcRect.height), PR_TRUE);
|
2007-10-23 12:33:20 -07:00
|
|
|
|
|
|
|
// first clear the surface if the blend flag says so
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
PRInt32 blendMethod = aSrc->GetBlendMethod();
|
2010-08-13 21:09:49 -07:00
|
|
|
if (blendMethod == kBlendSource) {
|
2008-01-21 23:36:57 -08:00
|
|
|
gfxContext::GraphicsOperator defaultOperator = dst.CurrentOperator();
|
2007-10-23 12:33:20 -07:00
|
|
|
dst.SetOperator(gfxContext::OPERATOR_CLEAR);
|
|
|
|
dst.Fill();
|
2008-01-21 23:36:57 -08:00
|
|
|
dst.SetOperator(defaultOperator);
|
2007-10-23 12:33:20 -07:00
|
|
|
}
|
2008-03-05 22:51:13 -08:00
|
|
|
dst.SetPattern(srcPatt);
|
2007-08-25 12:18:44 -07:00
|
|
|
dst.Paint();
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
aDst->UnlockImageData();
|
|
|
|
|
2007-08-25 12:18:44 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-21 13:45:49 -07:00
|
|
|
/********* Methods to implement lazy allocation of nsIProperties object *************/
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Get(const char *prop, const nsIID & iid, void * *result)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
if (!mProperties)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mProperties->Get(prop, iid, result);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Set(const char *prop, nsISupports *value)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
if (!mProperties)
|
|
|
|
mProperties = do_CreateInstance("@mozilla.org/properties;1");
|
|
|
|
if (!mProperties)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
return mProperties->Set(prop, value);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
2011-09-28 23:19:26 -07:00
|
|
|
RasterImage::Has(const char *prop, bool *_retval)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
if (!mProperties) {
|
|
|
|
*_retval = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return mProperties->Has(prop, _retval);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Undefine(const char *prop)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
if (!mProperties)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mProperties->Undefine(prop);
|
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::GetKeys(PRUint32 *count, char ***keys)
|
2007-06-21 13:45:49 -07:00
|
|
|
{
|
|
|
|
if (!mProperties) {
|
|
|
|
*count = 0;
|
|
|
|
*keys = nsnull;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return mProperties->GetKeys(count, keys);
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
|
|
|
void
|
2011-01-12 17:45:13 -08:00
|
|
|
RasterImage::Discard(bool force)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
// We should be ok for discard
|
2011-01-12 17:45:13 -08:00
|
|
|
NS_ABORT_IF_FALSE(force ? CanForciblyDiscard() : CanDiscard(), "Asked to discard but can't!");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We should never discard when we have an active decoder
|
2010-07-01 10:39:44 -07:00
|
|
|
NS_ABORT_IF_FALSE(!mDecoder, "Asked to discard with open decoder!");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// As soon as an image becomes animated, it becomes non-discardable and any
|
|
|
|
// timers are cancelled.
|
2010-07-01 10:39:44 -07:00
|
|
|
NS_ABORT_IF_FALSE(!mAnim, "Asked to discard for animated image!");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// For post-operation logging
|
2010-07-01 10:39:44 -07:00
|
|
|
int old_frame_count = mFrames.Length();
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Delete all the decoded frames, then clear the array.
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
for (int i = 0; i < old_frame_count; ++i)
|
2010-07-01 10:39:44 -07:00
|
|
|
delete mFrames[i];
|
|
|
|
mFrames.Clear();
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Flag that we no longer have decoded frames for this image
|
2010-07-01 10:39:44 -07:00
|
|
|
mDecoded = PR_FALSE;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Notify that we discarded
|
2010-07-01 10:39:44 -07:00
|
|
|
nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
|
2009-09-12 15:44:18 -07:00
|
|
|
if (observer)
|
|
|
|
observer->OnDiscard(nsnull);
|
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
if (force)
|
|
|
|
DiscardTracker::Remove(&mDiscardTrackerNode);
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Log
|
2007-10-18 17:36:34 -07:00
|
|
|
PR_LOG(gCompressedImageAccountingLog, PR_LOG_DEBUG,
|
2009-09-12 15:44:18 -07:00
|
|
|
("CompressedImageAccounting: discarded uncompressed image "
|
2010-08-13 21:09:49 -07:00
|
|
|
"data from RasterImage %p (%s) - %d frames (cached count: %d); "
|
2009-09-12 15:44:18 -07:00
|
|
|
"Total Containers: %d, Discardable containers: %d, "
|
|
|
|
"Total source bytes: %lld, Source bytes for discardable containers %lld",
|
2010-07-01 10:39:44 -07:00
|
|
|
this,
|
|
|
|
mSourceDataMimeType.get(),
|
2007-10-18 17:36:34 -07:00
|
|
|
old_frame_count,
|
2010-07-01 10:39:44 -07:00
|
|
|
mFrames.Length(),
|
2009-09-12 15:44:18 -07:00
|
|
|
num_containers,
|
|
|
|
num_discardable_containers,
|
|
|
|
total_source_bytes,
|
|
|
|
discardable_source_bytes));
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Helper method to determine if we can discard an image
|
2011-08-05 06:57:16 -07:00
|
|
|
bool
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::CanDiscard() {
|
2009-09-12 15:44:18 -07:00
|
|
|
return (DiscardingEnabled() && // Globally enabled...
|
|
|
|
mDiscardable && // ...Enabled at creation time...
|
|
|
|
(mLockCount == 0) && // ...not temporarily disabled...
|
|
|
|
mHasSourceData && // ...have the source data...
|
|
|
|
mDecoded); // ...and have something to discard.
|
|
|
|
}
|
|
|
|
|
2011-08-05 06:57:16 -07:00
|
|
|
bool
|
2011-01-12 17:45:13 -08:00
|
|
|
RasterImage::CanForciblyDiscard() {
|
2011-07-21 11:15:17 -07:00
|
|
|
return mDiscardable && // ...Enabled at creation time...
|
|
|
|
mHasSourceData; // ...have the source data...
|
2011-01-12 17:45:13 -08:00
|
|
|
}
|
|
|
|
|
2010-07-01 10:39:44 -07:00
|
|
|
// Helper method to tell us whether the clock is currently running for
|
|
|
|
// discarding this image. Mainly for assertions.
|
2011-08-05 06:57:16 -07:00
|
|
|
bool
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::DiscardingActive() {
|
2010-07-01 10:39:44 -07:00
|
|
|
return !!(mDiscardTrackerNode.prev || mDiscardTrackerNode.next);
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Helper method to determine if we're storing the source data in a buffer
|
|
|
|
// or just writing it directly to the decoder
|
2011-08-05 06:57:16 -07:00
|
|
|
bool
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::StoringSourceData() {
|
2009-09-12 15:44:18 -07:00
|
|
|
return (mDecodeOnDraw || mDiscardable);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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).
|
2007-10-18 17:36:34 -07:00
|
|
|
nsresult
|
2010-08-22 19:30:46 -07:00
|
|
|
RasterImage::InitDecoder(bool aDoSizeDecode)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
// Ensure that the decoder is not already initialized
|
|
|
|
NS_ABORT_IF_FALSE(!mDecoder, "Calling InitDecoder() while already decoding!");
|
|
|
|
|
|
|
|
// We shouldn't be firing up a decoder if we already have the frames decoded
|
|
|
|
NS_ABORT_IF_FALSE(!mDecoded, "Calling InitDecoder() but already decoded!");
|
|
|
|
|
|
|
|
// Since we're not decoded, we should not have a discard timer active
|
2010-07-01 10:39:44 -07:00
|
|
|
NS_ABORT_IF_FALSE(!DiscardingActive(), "Discard Timer active in InitDecoder()!");
|
2009-09-12 15:44:18 -07:00
|
|
|
|
2010-08-22 19:30:45 -07:00
|
|
|
// Figure out which decoder we want
|
|
|
|
eDecoderType type = GetDecoderType(mSourceDataMimeType.get());
|
|
|
|
CONTAINER_ENSURE_TRUE(type != eDecoderType_unknown, NS_IMAGELIB_ERROR_NO_DECODER);
|
|
|
|
|
2011-09-27 09:24:03 -07:00
|
|
|
nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
|
2010-08-22 19:30:45 -07:00
|
|
|
// Instantiate the appropriate decoder
|
|
|
|
switch (type) {
|
|
|
|
case eDecoderType_png:
|
2011-09-27 09:24:03 -07:00
|
|
|
mDecoder = new nsPNGDecoder(this, observer);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_gif:
|
2011-09-27 09:24:03 -07:00
|
|
|
mDecoder = new nsGIFDecoder2(this, observer);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_jpeg:
|
2011-09-27 09:24:03 -07:00
|
|
|
mDecoder = new nsJPEGDecoder(this, observer);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_bmp:
|
2011-09-27 09:24:03 -07:00
|
|
|
mDecoder = new nsBMPDecoder(this, observer);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_ico:
|
2011-09-27 09:24:03 -07:00
|
|
|
mDecoder = new nsICODecoder(this, observer);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
case eDecoderType_icon:
|
2011-09-27 09:24:03 -07:00
|
|
|
mDecoder = new nsIconDecoder(this, observer);
|
2010-08-22 19:30:45 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_ABORT_IF_FALSE(0, "Shouldn't get here!");
|
|
|
|
}
|
2010-08-11 17:49:50 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Initialize the decoder
|
2010-08-22 19:30:46 -07:00
|
|
|
mDecoder->SetSizeDecode(aDoSizeDecode);
|
2011-01-12 17:45:13 -08:00
|
|
|
mDecoder->SetDecodeFlags(mFrameDecodeFlags);
|
2011-09-27 09:24:03 -07:00
|
|
|
mDecoder->Init();
|
2010-09-12 08:22:31 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(mDecoder->GetDecoderError());
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Create a decode worker
|
|
|
|
mWorker = new imgDecodeWorker(this);
|
2011-09-08 11:05:11 -07:00
|
|
|
|
|
|
|
if (!aDoSizeDecode) {
|
|
|
|
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Subtract(mDecodeCount);
|
|
|
|
mDecodeCount++;
|
|
|
|
Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(mDecodeCount);
|
|
|
|
}
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_TRUE(mWorker, NS_ERROR_OUT_OF_MEMORY);
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Flushes, closes, and nulls-out a decoder. Cleans up any related decoding
|
|
|
|
// state. It is an error to call this function when there is no initialized
|
|
|
|
// decoder.
|
|
|
|
//
|
|
|
|
// aIntent specifies the intent of the shutdown. If aIntent is
|
|
|
|
// eShutdownIntent_Done, an error is flagged if we didn't get what we should
|
|
|
|
// have out of the decode. If aIntent is eShutdownIntent_Interrupted, we don't
|
|
|
|
// check this. If aIntent is eShutdownIntent_Error, we shut down in error mode.
|
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::ShutdownDecoder(eShutdownIntent aIntent)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
|
|
|
// Ensure that our intent is valid
|
|
|
|
NS_ABORT_IF_FALSE((aIntent >= 0) || (aIntent < eShutdownIntent_AllCount),
|
|
|
|
"Invalid shutdown intent");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Ensure that the decoder is initialized
|
|
|
|
NS_ABORT_IF_FALSE(mDecoder, "Calling ShutdownDecoder() with no active decoder!");
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2010-08-22 19:30:46 -07:00
|
|
|
// Figure out what kind of decode we were doing before we get rid of our decoder
|
|
|
|
bool wasSizeDecode = mDecoder->IsSizeDecode();
|
|
|
|
|
2010-09-12 08:22:30 -07:00
|
|
|
// Finalize the decoder
|
2011-05-11 02:46:59 -07:00
|
|
|
// null out mDecoder, _then_ check for errors on the close (otherwise the
|
|
|
|
// error routine might re-invoke ShutdownDecoder)
|
|
|
|
nsRefPtr<Decoder> decoder = mDecoder;
|
|
|
|
mDecoder = nsnull;
|
|
|
|
|
2010-09-12 08:22:30 -07:00
|
|
|
mInDecoder = PR_TRUE;
|
2011-05-11 02:46:59 -07:00
|
|
|
decoder->Finish();
|
2010-09-12 08:22:30 -07:00
|
|
|
mInDecoder = PR_FALSE;
|
2010-08-22 07:13:09 -07:00
|
|
|
|
2011-05-11 02:46:59 -07:00
|
|
|
nsresult decoderStatus = decoder->GetDecoderError();
|
2010-09-12 08:22:30 -07:00
|
|
|
if (NS_FAILED(decoderStatus)) {
|
2009-09-12 15:44:18 -07:00
|
|
|
DoError();
|
2010-09-12 08:22:30 -07:00
|
|
|
return decoderStatus;
|
2009-09-12 15:44:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Kill off the worker
|
|
|
|
mWorker = nsnull;
|
2011-07-21 11:15:17 -07:00
|
|
|
mWorkerPending = PR_FALSE;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// We just shut down the decoder. If we didn't get what we want, but expected
|
|
|
|
// to, flag an error
|
2011-07-20 14:52:30 -07:00
|
|
|
bool failed = false;
|
2010-08-22 19:30:46 -07:00
|
|
|
if (wasSizeDecode && !mHasSize)
|
2011-07-20 14:52:30 -07:00
|
|
|
failed = true;
|
2010-08-22 19:30:46 -07:00
|
|
|
if (!wasSizeDecode && !mDecoded)
|
2011-07-20 14:52:30 -07:00
|
|
|
failed = true;
|
2009-09-12 15:44:18 -07:00
|
|
|
if ((aIntent == eShutdownIntent_Done) && failed) {
|
|
|
|
DoError();
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset number of decoded bytes
|
|
|
|
mBytesDecoded = 0;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-15 19:54:44 -07:00
|
|
|
// Writes the data to the decoder, updating the total number of bytes written.
|
2009-09-12 15:44:18 -07:00
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::WriteToDecoder(const char *aBuffer, PRUint32 aCount)
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
// We should have a decoder
|
|
|
|
NS_ABORT_IF_FALSE(mDecoder, "Trying to write to null decoder!");
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2010-02-25 10:14:30 -08:00
|
|
|
// The decoder will start decoding into the current frame (if we have one).
|
|
|
|
// When it needs to add another frame, we will unlock this frame and lock the
|
|
|
|
// new frame.
|
|
|
|
// Our invariant is that, while in the decoder, the last frame is always
|
|
|
|
// locked, and all others are unlocked.
|
|
|
|
if (mFrames.Length() > 0) {
|
|
|
|
imgFrame *curframe = mFrames.ElementAt(mFrames.Length() - 1);
|
|
|
|
curframe->LockImageData();
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Write
|
2011-05-11 02:46:59 -07:00
|
|
|
nsRefPtr<Decoder> kungFuDeathGrip = mDecoder;
|
2009-09-12 15:44:18 -07:00
|
|
|
mInDecoder = PR_TRUE;
|
2010-09-12 08:22:31 -07:00
|
|
|
mDecoder->Write(aBuffer, aCount);
|
2009-09-12 15:44:18 -07:00
|
|
|
mInDecoder = PR_FALSE;
|
2010-02-25 10:14:30 -08:00
|
|
|
|
|
|
|
// We unlock the current frame, even if that frame is different from the
|
|
|
|
// frame we entered the decoder with. (See above.)
|
|
|
|
if (mFrames.Length() > 0) {
|
|
|
|
imgFrame *curframe = mFrames.ElementAt(mFrames.Length() - 1);
|
|
|
|
curframe->UnlockImageData();
|
|
|
|
}
|
|
|
|
|
2011-05-11 02:46:59 -07:00
|
|
|
if (!mDecoder)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2010-09-12 08:22:31 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(mDecoder->GetDecoderError());
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Keep track of the total number of bytes written over the lifetime of the
|
|
|
|
// decoder
|
|
|
|
mBytesDecoded += aCount;
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-20 18:50:15 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// This function is called in situations where it's clear that we want the
|
|
|
|
// frames in decoded form (Draw, GetFrame, CopyFrame, ExtractFrame, etc).
|
|
|
|
// If we're completely decoded, this method resets the discard timer (if
|
|
|
|
// we're discardable), since wanting the frames now is a good indicator of
|
|
|
|
// wanting them again soon. If we're not decoded, this method kicks off
|
|
|
|
// asynchronous decoding to generate the frames.
|
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::WantDecodedFrames()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
nsresult rv;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2010-07-01 10:39:44 -07:00
|
|
|
// If we can discard, the clock should be running. Reset it.
|
2009-09-12 15:44:18 -07:00
|
|
|
if (CanDiscard()) {
|
2010-07-01 10:39:44 -07:00
|
|
|
NS_ABORT_IF_FALSE(DiscardingActive(),
|
|
|
|
"Decoded and discardable but discarding not activated!");
|
2010-08-13 21:09:49 -07:00
|
|
|
rv = DiscardTracker::Reset(&mDiscardTrackerNode);
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Request a decode (no-op if we're decoded)
|
|
|
|
return RequestDecode();
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* void requestDecode() */
|
|
|
|
NS_IMETHODIMP
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::RequestDecode()
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
|
|
|
nsresult rv;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we're fully decoded, we have nothing to do
|
|
|
|
if (mDecoded)
|
|
|
|
return NS_OK;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2011-09-21 09:19:49 -07:00
|
|
|
// If we're not storing source data, we have nothing to do
|
|
|
|
if (!StoringSourceData())
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-09-19 12:33:00 -07:00
|
|
|
// If we've already got a full decoder running, we have nothing to do
|
2010-08-22 19:30:46 -07:00
|
|
|
if (mDecoder && !mDecoder->IsSizeDecode())
|
2009-09-19 12:33:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
|
2010-08-22 19:30:46 -07:00
|
|
|
// 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
|
2009-09-19 12:33:00 -07:00
|
|
|
// 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
|
|
|
|
// a little slower).
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mInDecoder) {
|
|
|
|
nsRefPtr<imgDecodeRequestor> requestor = new imgDecodeRequestor(this);
|
|
|
|
if (!requestor)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
return NS_DispatchToCurrentThread(requestor);
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
// If we have a size decode open, interrupt it and shut it down; or if
|
|
|
|
// the decoder has different flags than what we need
|
|
|
|
if (mDecoder &&
|
|
|
|
(mDecoder->IsSizeDecode() || mDecoder->GetDecodeFlags() != mFrameDecodeFlags))
|
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
rv = ShutdownDecoder(eShutdownIntent_Interrupted);
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// 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");
|
2010-08-22 19:30:46 -07:00
|
|
|
rv = InitDecoder(/* aDoSizeDecode = */ false);
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we already have a pending worker, we're done
|
|
|
|
if (mWorkerPending)
|
|
|
|
return NS_OK;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we've read all the data we have, we're done
|
|
|
|
if (mBytesDecoded == mSourceData.Length())
|
|
|
|
return NS_OK;
|
|
|
|
|
2010-08-26 15:54:21 -07:00
|
|
|
// If it's a smallish image, it's not worth it to do things async
|
|
|
|
if (!mDecoded && !mInDecoder && mHasSourceData && (mSourceData.Length() < gMaxBytesForSyncDecode))
|
|
|
|
return SyncDecode();
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we get this far, dispatch the worker. We do this instead of starting
|
2010-07-28 14:52:14 -07:00
|
|
|
// any immediate decoding to guarantee that all our decode notifications are
|
|
|
|
// dispatched asynchronously, and to ensure we stay responsive.
|
2009-09-12 15:44:18 -07:00
|
|
|
return mWorker->Dispatch();
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Synchronously decodes as much data as possible
|
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::SyncDecode()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// If we're decoded already, no worries
|
|
|
|
if (mDecoded)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// If we're not storing source data, there isn't much to do here
|
|
|
|
if (!StoringSourceData())
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// We really have no good way of forcing a synchronous decode if we're being
|
|
|
|
// called in a re-entrant manner (ie, from an event listener fired by a
|
2010-07-26 13:45:15 -07:00
|
|
|
// decoder), because the decoding machinery is already tied up. We thus explicitly
|
|
|
|
// disallow this type of call in the API, and check for it in API methods.
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ABORT_IF_FALSE(!mInDecoder, "Yikes, forcing sync in reentrant call!");
|
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
// If we have a size decoder open, or one with different flags than
|
|
|
|
// what we need, shut it down
|
|
|
|
if (mDecoder &&
|
|
|
|
(mDecoder->IsSizeDecode() || mDecoder->GetDecodeFlags() != mFrameDecodeFlags))
|
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
rv = ShutdownDecoder(eShutdownIntent_Interrupted);
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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");
|
2010-08-22 19:30:46 -07:00
|
|
|
rv = InitDecoder(/* aDoSizeDecode = */ false);
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write everything we have
|
|
|
|
rv = WriteToDecoder(mSourceData.Elements() + mBytesDecoded,
|
|
|
|
mSourceData.Length() - mBytesDecoded);
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
|
2010-08-25 13:11:09 -07:00
|
|
|
// When we're doing a sync decode, we want to get as much information from the
|
|
|
|
// image as possible. We've send the decoder all of our data, so now's a good
|
|
|
|
// time to flush any invalidations (in case we don't have all the data and what
|
|
|
|
// we got left us mid-frame).
|
2011-05-11 02:46:59 -07:00
|
|
|
nsRefPtr<Decoder> kungFuDeathGrip = mDecoder;
|
2010-08-25 13:11:09 -07:00
|
|
|
mInDecoder = PR_TRUE;
|
|
|
|
mDecoder->FlushInvalidations();
|
|
|
|
mInDecoder = PR_FALSE;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we finished the decode, shutdown the decoder
|
2011-05-11 02:46:59 -07:00
|
|
|
if (mDecoder && IsDecodeFinished()) {
|
2009-09-12 15:44:18 -07:00
|
|
|
rv = ShutdownDecoder(eShutdownIntent_Done);
|
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
|
2011-05-11 02:46:59 -07:00
|
|
|
// All good if no errors!
|
|
|
|
return mError ? NS_ERROR_FAILURE : NS_OK;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
//******************************************************************************
|
2010-07-05 13:49:05 -07:00
|
|
|
/* [noscript] void draw(in gfxContext aContext,
|
|
|
|
* in gfxGraphicsFilter aFilter,
|
|
|
|
* [const] in gfxMatrix aUserSpaceToImageSpace,
|
|
|
|
* [const] in gfxRect aFill,
|
|
|
|
* [const] in nsIntRect aSubimage,
|
2010-09-08 13:40:39 -07:00
|
|
|
* [const] in nsIntSize aViewportSize,
|
2010-07-05 13:49:05 -07:00
|
|
|
* in PRUint32 aFlags); */
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::Draw(gfxContext *aContext,
|
|
|
|
gfxPattern::GraphicsFilter aFilter,
|
|
|
|
const gfxMatrix &aUserSpaceToImageSpace,
|
|
|
|
const gfxRect &aFill,
|
|
|
|
const nsIntRect &aSubimage,
|
2010-09-08 13:40:39 -07:00
|
|
|
const nsIntSize& /*aViewportSize - ignored*/,
|
2010-08-13 21:09:49 -07:00
|
|
|
PRUint32 aFlags)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2010-07-26 13:45:15 -07:00
|
|
|
// Disallowed in the API
|
|
|
|
if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
// Illegal -- you can't draw with non-default decode flags.
|
|
|
|
// (Disabling colorspace conversion might make sense to allow, but
|
|
|
|
// we don't currently.)
|
|
|
|
if ((aFlags & DECODE_FLAGS_MASK) != DECODE_FLAGS_DEFAULT)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(aContext);
|
|
|
|
|
2011-01-12 17:45:13 -08:00
|
|
|
// We can only draw with the default decode flags
|
|
|
|
if (mFrameDecodeFlags != DECODE_FLAGS_DEFAULT) {
|
|
|
|
if (!CanForciblyDiscard())
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
ForceDiscard();
|
|
|
|
|
|
|
|
mFrameDecodeFlags = DECODE_FLAGS_DEFAULT;
|
|
|
|
}
|
|
|
|
|
2011-08-10 16:12:08 -07:00
|
|
|
if (!mDecoded) {
|
|
|
|
mDrawStartTime = TimeStamp::Now();
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If a synchronous draw is requested, flush anything that might be sitting around
|
|
|
|
if (aFlags & FLAG_SYNC_DECODE) {
|
|
|
|
nsresult rv = SyncDecode();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
2009-11-12 15:18:40 -08:00
|
|
|
imgFrame *frame = GetCurrentDrawableImgFrame();
|
2009-09-12 15:44:18 -07:00
|
|
|
if (!frame) {
|
|
|
|
return NS_OK; // Getting the frame (above) touches the image and kicks off decoding
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIntRect framerect = frame->GetRect();
|
|
|
|
nsIntMargin padding(framerect.x, framerect.y,
|
|
|
|
mSize.width - framerect.XMost(),
|
|
|
|
mSize.height - framerect.YMost());
|
|
|
|
|
|
|
|
frame->Draw(aContext, aFilter, aUserSpaceToImageSpace, aFill, padding, aSubimage);
|
|
|
|
|
2011-08-10 16:12:08 -07:00
|
|
|
if (mDecoded && !mDrawStartTime.IsNull()) {
|
|
|
|
TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime;
|
|
|
|
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_ON_DRAW_LATENCY, PRInt32(drawLatency.ToMicroseconds()));
|
|
|
|
// clear the value of mDrawStartTime
|
|
|
|
mDrawStartTime = TimeStamp();
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-09-08 13:40:38 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* [notxpcom] nsIFrame GetRootLayoutFrame() */
|
|
|
|
nsIFrame*
|
|
|
|
RasterImage::GetRootLayoutFrame()
|
|
|
|
{
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* void lockImage() */
|
2007-10-18 17:36:34 -07:00
|
|
|
NS_IMETHODIMP
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::LockImage()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Cancel the discard timer if it's there
|
2010-08-13 21:09:49 -07:00
|
|
|
DiscardTracker::Remove(&mDiscardTrackerNode);
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Increment the lock count
|
|
|
|
mLockCount++;
|
|
|
|
|
2007-10-18 17:36:34 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* void unlockImage() */
|
2007-10-18 17:36:34 -07:00
|
|
|
NS_IMETHODIMP
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::UnlockImage()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mError)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// It's an error to call this function if the lock count is 0
|
|
|
|
NS_ABORT_IF_FALSE(mLockCount > 0,
|
|
|
|
"Calling UnlockImage with mLockCount == 0!");
|
|
|
|
if (mLockCount == 0)
|
|
|
|
return NS_ERROR_ABORT;
|
|
|
|
|
2010-07-01 10:39:44 -07:00
|
|
|
// We're locked, so discarding should not be active
|
|
|
|
NS_ABORT_IF_FALSE(!DiscardingActive(), "Locked, but discarding activated");
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Decrement our lock count
|
|
|
|
mLockCount--;
|
|
|
|
|
2011-07-21 11:15:17 -07:00
|
|
|
// If we've decoded this image once before, we're currently decoding again,
|
|
|
|
// and our lock count is now zero (so nothing is forcing us to keep the
|
|
|
|
// decoded data around), try to cancel the decode and throw away whatever
|
|
|
|
// we've decoded.
|
|
|
|
if (mHasBeenDecoded && mDecoder &&
|
|
|
|
mLockCount == 0 && CanForciblyDiscard()) {
|
|
|
|
PR_LOG(gCompressedImageAccountingLog, PR_LOG_DEBUG,
|
|
|
|
("RasterImage[0x%p] canceling decode because image "
|
|
|
|
"is now unlocked.", this));
|
|
|
|
ShutdownDecoder(eShutdownIntent_Interrupted);
|
|
|
|
ForceDiscard();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we might still be a candidate for discarding in the future. If
|
|
|
|
// we are, add ourselves to the discard tracker.
|
2009-09-12 15:44:18 -07:00
|
|
|
if (CanDiscard()) {
|
2010-08-13 21:09:49 -07:00
|
|
|
nsresult rv = DiscardTracker::Reset(&mDiscardTrackerNode);
|
2009-09-12 15:44:18 -07:00
|
|
|
CONTAINER_ENSURE_SUCCESS(rv);
|
|
|
|
}
|
|
|
|
|
2007-10-18 17:36:34 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Flushes up to aMaxBytes to the decoder.
|
|
|
|
nsresult
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::DecodeSomeData(PRUint32 aMaxBytes)
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
// We should have a decoder if we get here
|
|
|
|
NS_ABORT_IF_FALSE(mDecoder, "trying to decode without decoder!");
|
|
|
|
|
|
|
|
// If we have nothing to decode, return
|
|
|
|
if (mBytesDecoded == mSourceData.Length())
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
|
|
|
|
// write the proper amount of data
|
2011-06-02 05:56:50 -07:00
|
|
|
PRUint32 bytesToDecode = NS_MIN(aMaxBytes,
|
2009-09-12 15:44:18 -07:00
|
|
|
mSourceData.Length() - mBytesDecoded);
|
|
|
|
nsresult rv = WriteToDecoder(mSourceData.Elements() + mBytesDecoded,
|
|
|
|
bytesToDecode);
|
|
|
|
|
|
|
|
return rv;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// There are various indicators that tell us we're finished with the decode
|
|
|
|
// task at hand and can shut down the decoder.
|
2010-08-22 19:30:46 -07:00
|
|
|
//
|
|
|
|
// This method may not be called if there is no decoder.
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2010-08-13 21:09:49 -07:00
|
|
|
RasterImage::IsDecodeFinished()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2010-08-22 19:30:46 -07:00
|
|
|
// Precondition
|
|
|
|
NS_ABORT_IF_FALSE(mDecoder, "Can't call IsDecodeFinished() without decoder!");
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Assume it's not finished
|
2011-09-28 23:19:26 -07:00
|
|
|
bool decodeFinished = false;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// There shouldn't be any reason to call this if we're not storing
|
|
|
|
// source data
|
|
|
|
NS_ABORT_IF_FALSE(StoringSourceData(),
|
|
|
|
"just shut down on SourceDataComplete!");
|
|
|
|
|
|
|
|
// The decode is complete if we got what we wanted...
|
2010-08-22 19:30:46 -07:00
|
|
|
if (mDecoder->IsSizeDecode()) {
|
2009-09-12 15:44:18 -07:00
|
|
|
if (mHasSize)
|
|
|
|
decodeFinished = PR_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (mDecoded)
|
|
|
|
decodeFinished = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ...or if we have all the source data and wrote all the source data.
|
|
|
|
//
|
|
|
|
// (NB - This can be distinct from the above case even for non-erroneous
|
|
|
|
// images because the decoder might not call DecodingComplete() until we
|
|
|
|
// call Close() in ShutdownDecoder())
|
|
|
|
if (mHasSourceData && (mBytesDecoded == mSourceData.Length()))
|
|
|
|
decodeFinished = PR_TRUE;
|
|
|
|
|
|
|
|
return decodeFinished;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2010-09-12 08:22:30 -07:00
|
|
|
// Indempotent error flagging routine. If a decoder is open, shuts it down.
|
2010-08-13 21:09:49 -07:00
|
|
|
void
|
|
|
|
RasterImage::DoError()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we've flagged an error before, we have nothing to do
|
|
|
|
if (mError)
|
|
|
|
return;
|
|
|
|
|
2010-09-12 08:22:30 -07:00
|
|
|
// If we're mid-decode, shut down the decoder.
|
|
|
|
if (mDecoder)
|
|
|
|
ShutdownDecoder(eShutdownIntent_Error);
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Put the container in an error state
|
|
|
|
mError = PR_TRUE;
|
|
|
|
|
|
|
|
// Log our error
|
|
|
|
LOG_CONTAINER_ERROR;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Decodes some data, then re-posts itself to the end of the event queue if
|
|
|
|
// there's more processing to be done
|
2010-08-13 21:09:49 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
imgDecodeWorker::Run()
|
2007-10-18 17:36:34 -07:00
|
|
|
{
|
2009-09-12 15:44:18 -07:00
|
|
|
nsresult rv;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If we shutdown the decoder in this function, we could lose ourselves
|
|
|
|
nsCOMPtr<nsIRunnable> kungFuDeathGrip(this);
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// The container holds a strong reference to us. Cycles are bad.
|
|
|
|
nsCOMPtr<imgIContainer> iContainer(do_QueryReferent(mContainer));
|
|
|
|
if (!iContainer)
|
|
|
|
return NS_OK;
|
2010-08-13 21:09:51 -07:00
|
|
|
RasterImage* image = static_cast<RasterImage*>(iContainer.get());
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2010-08-13 21:09:51 -07:00
|
|
|
NS_ABORT_IF_FALSE(image->mInitialized,
|
2009-09-12 15:44:18 -07:00
|
|
|
"Worker active for uninitialized container!");
|
|
|
|
|
|
|
|
// If we were pending, we're not anymore
|
2010-08-13 21:09:51 -07:00
|
|
|
image->mWorkerPending = PR_FALSE;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// If an error is flagged, it probably happened while we were waiting
|
|
|
|
// in the event queue. Bail early, but no need to bother the run queue
|
|
|
|
// by returning an error.
|
2010-08-13 21:09:51 -07:00
|
|
|
if (image->mError)
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// If we don't have a decoder, we must have finished already (for example,
|
|
|
|
// a synchronous decode request came while the worker was pending).
|
2010-08-13 21:09:51 -07:00
|
|
|
if (!image->mDecoder)
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_OK;
|
|
|
|
|
2011-05-11 02:46:59 -07:00
|
|
|
nsRefPtr<Decoder> decoderKungFuDeathGrip = image->mDecoder;
|
|
|
|
|
2010-08-22 19:30:46 -07:00
|
|
|
// Size decodes are cheap and we more or less want them to be
|
2009-09-12 15:44:18 -07:00
|
|
|
// synchronous. Write all the data in that case, otherwise write a
|
|
|
|
// chunk
|
2010-08-22 19:30:46 -07:00
|
|
|
PRUint32 maxBytes = image->mDecoder->IsSizeDecode()
|
2010-08-25 15:58:27 -07:00
|
|
|
? image->mSourceData.Length() : gDecodeBytesAtATime;
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Loop control
|
2011-07-20 14:52:30 -07:00
|
|
|
bool haveMoreData = true;
|
2011-08-11 11:42:15 -07:00
|
|
|
PRInt32 chunkCount = 0;
|
2011-07-20 14:51:54 -07:00
|
|
|
TimeStamp start = TimeStamp::Now();
|
|
|
|
TimeStamp deadline = start + TimeDuration::FromMilliseconds(gMaxMSBeforeYield);
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// We keep decoding chunks until one of three possible events occur:
|
|
|
|
// 1) We don't have any data left to decode
|
|
|
|
// 2) The decode completes
|
|
|
|
// 3) We hit the deadline and need to yield to keep the UI snappy
|
2010-08-13 21:09:51 -07:00
|
|
|
while (haveMoreData && !image->IsDecodeFinished() &&
|
2011-07-19 08:18:43 -07:00
|
|
|
(TimeStamp::Now() < deadline)) {
|
2009-09-12 15:44:18 -07:00
|
|
|
|
|
|
|
// Decode a chunk of data
|
2011-08-11 11:42:15 -07:00
|
|
|
chunkCount++;
|
2010-08-13 21:09:51 -07:00
|
|
|
rv = image->DecodeSomeData(maxBytes);
|
2009-09-12 15:44:18 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
2010-08-13 21:09:51 -07:00
|
|
|
image->DoError();
|
2009-09-12 15:44:18 -07:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Figure out if we still have more data
|
|
|
|
haveMoreData =
|
2010-08-13 21:09:51 -07:00
|
|
|
image->mSourceData.Length() > image->mBytesDecoded;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2011-07-20 14:51:54 -07:00
|
|
|
TimeDuration decodeLatency = TimeStamp::Now() - start;
|
2011-09-21 09:19:53 -07:00
|
|
|
if (chunkCount && !image->mDecoder->IsSizeDecode()) {
|
2011-08-11 11:42:15 -07:00
|
|
|
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_LATENCY, PRInt32(decodeLatency.ToMicroseconds()));
|
|
|
|
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS, chunkCount);
|
|
|
|
}
|
2011-08-04 13:25:12 -07:00
|
|
|
// accumulate the total decode time
|
|
|
|
mDecodeTime += decodeLatency;
|
|
|
|
|
2010-08-25 13:11:09 -07:00
|
|
|
// Flush invalidations _after_ we've written everything we're going to.
|
2010-08-25 16:07:01 -07:00
|
|
|
// Furthermore, if this is a redecode, we don't want to do progressive
|
|
|
|
// display at all. In that case, let Decoder::PostFrameStop() do the
|
|
|
|
// flush once the whole frame is ready.
|
|
|
|
if (!image->mHasBeenDecoded) {
|
|
|
|
image->mInDecoder = PR_TRUE;
|
|
|
|
image->mDecoder->FlushInvalidations();
|
|
|
|
image->mInDecoder = PR_FALSE;
|
|
|
|
}
|
2010-08-25 13:11:09 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If the decode finished, shutdown the decoder
|
2011-05-11 02:46:59 -07:00
|
|
|
if (image->mDecoder && image->IsDecodeFinished()) {
|
2011-09-21 09:19:53 -07:00
|
|
|
|
|
|
|
if (!image->mDecoder->IsSizeDecode()) {
|
|
|
|
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_TIME, PRInt32(mDecodeTime.ToMicroseconds()));
|
2011-09-22 13:25:56 -07:00
|
|
|
|
|
|
|
// We only record the speed for some decoders. The rest have SpeedHistogram return HistogramCount.
|
|
|
|
Telemetry::ID id = image->mDecoder->SpeedHistogram();
|
|
|
|
if (id < Telemetry::HistogramCount) {
|
|
|
|
PRInt32 KBps = PRInt32((image->mBytesDecoded/1024.0)/mDecodeTime.ToSeconds());
|
|
|
|
Telemetry::Accumulate(id, KBps);
|
|
|
|
}
|
2011-09-21 09:19:53 -07:00
|
|
|
}
|
|
|
|
|
2010-08-13 21:09:51 -07:00
|
|
|
rv = image->ShutdownDecoder(RasterImage::eShutdownIntent_Done);
|
2009-09-12 15:44:18 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
2010-08-13 21:09:51 -07:00
|
|
|
image->DoError();
|
2009-09-12 15:44:18 -07:00
|
|
|
return rv;
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// If Conditions 1 & 2 are still true, then the only reason we bailed was
|
|
|
|
// because we hit the deadline. Repost ourselves to the end of the event
|
|
|
|
// queue.
|
2010-08-22 19:30:46 -07:00
|
|
|
if (image->mDecoder && !image->IsDecodeFinished() && haveMoreData)
|
2009-09-12 15:44:18 -07:00
|
|
|
return this->Dispatch();
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Otherwise, return success
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Queues the worker up at the end of the event queue
|
|
|
|
NS_METHOD imgDecodeWorker::Dispatch()
|
|
|
|
{
|
|
|
|
// The container holds a strong reference to us. Cycles are bad.
|
|
|
|
nsCOMPtr<imgIContainer> iContainer(do_QueryReferent(mContainer));
|
|
|
|
if (!iContainer)
|
|
|
|
return NS_OK;
|
2010-08-13 21:09:51 -07:00
|
|
|
RasterImage* image = static_cast<RasterImage*>(iContainer.get());
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We should not be called if there's already a pending worker
|
2010-08-13 21:09:51 -07:00
|
|
|
NS_ABORT_IF_FALSE(!image->mWorkerPending,
|
2009-09-12 15:44:18 -07:00
|
|
|
"Trying to queue up worker with one already pending!");
|
|
|
|
|
|
|
|
// Flag that we're pending
|
2010-08-13 21:09:51 -07:00
|
|
|
image->mWorkerPending = PR_TRUE;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// Dispatch
|
|
|
|
return NS_DispatchToCurrentThread(this);
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// nsIInputStream callback to copy the incoming image data directly to the
|
2010-08-13 21:09:51 -07:00
|
|
|
// RasterImage without processing. The RasterImage is passed as the closure.
|
2009-09-12 15:44:18 -07:00
|
|
|
// Always reads everything it gets, even if the data is erroneous.
|
|
|
|
NS_METHOD
|
2010-08-13 21:09:51 -07:00
|
|
|
RasterImage::WriteToRasterImage(nsIInputStream* /* unused */,
|
|
|
|
void* aClosure,
|
|
|
|
const char* aFromRawSegment,
|
|
|
|
PRUint32 /* unused */,
|
|
|
|
PRUint32 aCount,
|
|
|
|
PRUint32* aWriteCount)
|
2009-09-12 15:44:18 -07:00
|
|
|
{
|
2010-08-13 21:09:49 -07:00
|
|
|
// Retrieve the RasterImage
|
2010-08-13 21:09:51 -07:00
|
|
|
RasterImage* image = static_cast<RasterImage*>(aClosure);
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2011-06-08 19:21:53 -07:00
|
|
|
// Copy the source data. Unless we hit OOM, we squelch the return value
|
|
|
|
// here, because returning an error means that ReadSegments stops
|
|
|
|
// reading data, violating our invariant that we read everything we get.
|
|
|
|
// If we hit OOM then we fail and the load is aborted.
|
|
|
|
nsresult rv = image->AddSourceData(aFromRawSegment, aCount);
|
|
|
|
if (rv == NS_ERROR_OUT_OF_MEMORY) {
|
|
|
|
image->DoError();
|
|
|
|
return rv;
|
|
|
|
}
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
// We wrote everything we got
|
2010-08-13 21:09:51 -07:00
|
|
|
*aWriteCount = aCount;
|
2007-10-18 17:36:34 -07:00
|
|
|
|
2009-09-12 15:44:18 -07:00
|
|
|
return NS_OK;
|
2007-10-18 17:36:34 -07:00
|
|
|
}
|
2010-08-13 21:09:49 -07:00
|
|
|
|
2011-08-05 06:57:16 -07:00
|
|
|
bool
|
2010-09-07 17:33:02 -07:00
|
|
|
RasterImage::ShouldAnimate()
|
|
|
|
{
|
|
|
|
return Image::ShouldAnimate() && mFrames.Length() >= 2 &&
|
2010-11-17 12:39:23 -08:00
|
|
|
!mAnimationFinished;
|
2010-09-07 17:33:02 -07:00
|
|
|
}
|
|
|
|
|
2010-09-07 17:34:18 -07:00
|
|
|
//******************************************************************************
|
|
|
|
/* readonly attribute PRUint32 framesNotified; */
|
|
|
|
#ifdef DEBUG
|
|
|
|
NS_IMETHODIMP
|
|
|
|
RasterImage::GetFramesNotified(PRUint32 *aFramesNotified)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aFramesNotified);
|
|
|
|
|
|
|
|
*aFramesNotified = mFramesNotified;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-08-13 21:09:49 -07:00
|
|
|
} // namespace imagelib
|
|
|
|
} // namespace mozilla
|