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 * * * * * */
# include "nsComponentManagerUtils.h"
# include "imgIContainerObserver.h"
2007-10-18 17:36:34 -07:00
# include "ImageErrors.h"
# include "imgIDecoder.h"
# include "imgIDecoderObserver.h"
2007-03-22 10:30:00 -07:00
# include "imgContainer.h"
# include "nsIInterfaceRequestor.h"
# include "nsIInterfaceRequestorUtils.h"
# include "nsAutoPtr.h"
2007-10-18 17:36:34 -07:00
# include "nsStringStream.h"
# include "prmem.h"
# include "prlog.h"
# include "prenv.h"
2009-09-12 15:44:18 -07:00
# include "nsTime.h"
# include "ImageLogging.h"
2007-03-22 10:30:00 -07:00
# include "gfxContext.h"
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
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
* non - static imgContainer method .
*/
# define LOG_CONTAINER_ERROR \
PR_BEGIN_MACRO \
PR_LOG ( gImgLog , PR_LOG_ERROR , \
( " ImgContainer: [this=%p] Error " \
" 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? */
static PRBool
DiscardingEnabled ( )
{
static PRBool inited ;
static PRBool 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 ;
}
NS_IMPL_ISUPPORTS4 ( imgContainer , imgIContainer , nsITimerCallback , nsIProperties ,
nsISupportsWeakReference )
2007-03-22 10:30:00 -07:00
//******************************************************************************
imgContainer : : imgContainer ( ) :
mSize ( 0 , 0 ) ,
mAnim ( nsnull ) ,
mAnimationMode ( kNormalAnimMode ) ,
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 ) ,
mDecoderFlags ( imgIDecoder : : DECODER_FLAG_NONE ) ,
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 ) ,
mError ( PR_FALSE )
{
2010-07-01 10:39:44 -07:00
// Set up the discard tracker node.
mDiscardTrackerNode . curr = this ;
mDiscardTrackerNode . prev = mDiscardTrackerNode . next = nsnull ;
2009-09-12 15:44:18 -07:00
// Statistics
num_containers + + ;
2007-03-22 10:30:00 -07:00
}
//******************************************************************************
imgContainer : : ~ imgContainer ( )
{
if ( mAnim )
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 ,
( " CompressedImageAccounting: destroying imgContainer %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-07-01 10:39:44 -07:00
imgDiscardTracker : : 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
}
//******************************************************************************
2009-09-12 15:44:18 -07:00
/* void init(in imgIDecoderObserver aObserver, in string aMimeType,
in PRUint32 aFlags ) ; */
NS_IMETHODIMP imgContainer : : Init ( imgIDecoderObserver * aObserver ,
const char * aMimeType ,
PRUint32 aFlags )
{
// 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-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 ;
}
// Determine our decoder flags. If we're doing decode-on-draw,
// we want to do a quick first pass to get the size but nothing
// else. We instantiate another decoder later to do the full
// decoding.
PRUint32 dFlags = imgIDecoder : : DECODER_FLAG_NONE ;
if ( mDecodeOnDraw )
dFlags | = imgIDecoder : : DECODER_FLAG_HEADERONLY ;
// Instantiate the decoder
nsresult rv = InitDecoder ( dFlags ) ;
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 ) ; */
NS_IMETHODIMP imgContainer : : 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.
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 < imgContainer > img ( new imgContainer ( ) ) ;
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.
img - > Init ( nsnull , " " , INIT_FLAG_NONE ) ;
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 ;
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-05-14 13:47:59 -07:00
img - > mStatusTracker . RecordLoaded ( ) ;
img - > mStatusTracker . RecordDecoded ( ) ;
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; */
NS_IMETHODIMP imgContainer : : GetWidth ( PRInt32 * aWidth )
{
2008-03-19 22:54:30 -07:00
NS_ENSURE_ARG_POINTER ( aWidth ) ;
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
* aWidth = mSize . width ;
return NS_OK ;
}
//******************************************************************************
/* readonly attribute PRInt32 height; */
NS_IMETHODIMP imgContainer : : GetHeight ( PRInt32 * aHeight )
{
2008-03-19 22:54:30 -07:00
NS_ENSURE_ARG_POINTER ( aHeight ) ;
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
* aHeight = mSize . 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
imgFrame * imgContainer : : GetImgFrame ( PRUint32 framenum )
2007-10-18 17:36:34 -07:00
{
2009-09-12 15:44:18 -07:00
nsresult rv = WantDecodedFrames ( ) ;
CONTAINER_ENSURE_TRUE ( NS_SUCCEEDED ( rv ) , nsnull ) ;
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 ) ;
}
2009-11-12 15:18:40 -08:00
imgFrame * imgContainer : : GetDrawableImgFrame ( PRUint32 framenum )
{
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 ;
}
2009-09-12 15:44:18 -07:00
PRUint32 imgContainer : : 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 ;
}
imgFrame * imgContainer : : GetCurrentImgFrame ( )
{
return GetImgFrame ( GetCurrentImgFrameIndex ( ) ) ;
2007-10-18 17:36:34 -07:00
}
2009-11-12 15:18:40 -08:00
imgFrame * imgContainer : : GetCurrentDrawableImgFrame ( )
{
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; */
NS_IMETHODIMP imgContainer : : GetCurrentFrameIsOpaque ( PRBool * 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 ( ) ;
* aIsOpaque = * aIsOpaque & & ( framerect ! = nsIntRect ( 0 , 0 , mSize . width , 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
return NS_OK ;
}
//******************************************************************************
/* [noscript] void getCurrentFrameRect(nsIntRect rect); */
NS_IMETHODIMP imgContainer : : GetCurrentFrameRect ( nsIntRect & aRect )
{
2009-09-12 15:44:18 -07:00
if ( mError )
return NS_ERROR_FAILURE ;
// Get the current 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 have the frame, use that rectangle
if ( curframe )
aRect = curframe - > GetRect ( ) ;
// 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 imgRequest (when it wants to figure out dirty
// rectangles to send out batched observer updates). This should probably be
// revisited when we fix bug 503973.
else {
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
return NS_OK ;
}
//******************************************************************************
/* readonly attribute unsigned long currentFrameIndex; */
NS_IMETHODIMP imgContainer : : GetCurrentFrameIndex ( PRUint32 * aCurrentFrameIdx )
{
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 ( aCurrentFrameIdx ) ;
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
* aCurrentFrameIdx = GetCurrentImgFrameIndex ( ) ;
2007-03-22 10:30:00 -07:00
return NS_OK ;
}
//******************************************************************************
/* readonly attribute unsigned long numFrames; */
NS_IMETHODIMP imgContainer : : GetNumFrames ( PRUint32 * aNumFrames )
{
2009-09-12 15:44:18 -07:00
if ( mError )
return NS_ERROR_FAILURE ;
2008-03-19 22:54:30 -07:00
NS_ENSURE_ARG_POINTER ( aNumFrames ) ;
2007-03-22 10:30:00 -07:00
2009-09-12 15:44:18 -07:00
* aNumFrames = mFrames . Length ( ) ;
2007-03-22 10:30:00 -07: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
/* readonly attribute boolean animated; */
NS_IMETHODIMP imgContainer : : GetAnimated ( PRBool * aAnimated )
{
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 ) ; */
NS_IMETHODIMP imgContainer : : 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 ;
// 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 ) ; */
NS_IMETHODIMP imgContainer : : 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 ;
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 ;
}
//******************************************************************************
2009-09-12 15:44:18 -07:00
/* readonly attribute unsigned long dataSize; */
NS_IMETHODIMP imgContainer : : GetDataSize ( PRUint32 * _retval )
2007-03-22 10:30:00 -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
NS_ENSURE_ARG_POINTER ( _retval ) ;
2007-10-18 17:36:34 -07:00
2009-09-12 15:44:18 -07:00
// Start with 0
* _retval = 0 ;
2007-10-18 17:36:34 -07:00
2009-09-12 15:44:18 -07:00
// Account for any compressed source data
2010-05-21 21:10:14 -07:00
* _retval + = GetSourceDataSize ( ) ;
2009-09-12 15:44:18 -07:00
NS_ABORT_IF_FALSE ( StoringSourceData ( ) | | ( * _retval = = 0 ) ,
" Non-zero source data size when we aren't storing it? " ) ;
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
// Account for any uncompressed frames
2010-05-21 21:10:14 -07:00
* _retval + = GetDecodedDataSize ( ) ;
return NS_OK ;
}
PRUint32 imgContainer : : GetDecodedDataSize ( )
{
PRUint32 val = 0 ;
2009-09-12 15:44:18 -07:00
for ( PRUint32 i = 0 ; i < mFrames . Length ( ) ; + + i ) {
imgFrame * frame = mFrames . SafeElementAt ( i , nsnull ) ;
NS_ABORT_IF_FALSE ( frame , " Null frame in frame array! " ) ;
2010-05-21 21:10:14 -07:00
val + = frame - > EstimateMemoryUsed ( ) ;
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 ;
}
PRUint32 imgContainer : : GetSourceDataSize ( )
{
return mSourceData . 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
}
2010-03-08 11:01:04 -08:00
void imgContainer : : DeleteImgFrame ( PRUint32 framenum )
{
NS_ABORT_IF_FALSE ( framenum < mFrames . Length ( ) , " Deleting invalid frame! " ) ;
delete mFrames [ framenum ] ;
mFrames [ framenum ] = 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
nsresult imgContainer : : InternalAddFrameHelper ( PRUint32 framenum , imgFrame * aFrame ,
PRUint8 * * imageData , PRUint32 * imageLength ,
PRUint32 * * paletteData , PRUint32 * paletteLength )
{
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 ;
}
nsresult imgContainer : : InternalAddFrame ( PRUint32 framenum ,
PRInt32 aX , PRInt32 aY ,
PRInt32 aWidth , PRInt32 aHeight ,
gfxASurface : : gfxImageFormat aFormat ,
PRUint8 aPaletteDepth ,
PRUint8 * * imageData ,
PRUint32 * imageLength ,
PRUint32 * * paletteData ,
PRUint32 * paletteLength )
{
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
2007-03-22 10:30:00 -07:00
if ( ! ensureAnimExists ( ) )
return NS_ERROR_OUT_OF_MEMORY ;
// 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 ( ) ;
2007-03-22 10:30:00 -07:00
if ( frameDisposalMethod = = imgIContainer : : kDisposeClear | |
frameDisposalMethod = = imgIContainer : : 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
2007-10-22 09:13:37 -07:00
// If this is our second frame (We've just added our second frame above),
// count should now be 2. This must be called after we AppendObject
// because StartAnimation checks for > 1 frames
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 ( ) = = 2 )
2007-03-22 10:30:00 -07:00
StartAnimation ( ) ;
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 ;
}
/* [noscript] void appendFrame (in PRInt32 aX, in PRInt32 aY, in PRInt32 aWidth, in PRInt32 aHeight, in gfxImageFormat aFormat, [array, size_is (imageLength)] out PRUint8 imageData, out unsigned long imageLength); */
NS_IMETHODIMP imgContainer : : AppendFrame ( PRInt32 aX , PRInt32 aY , PRInt32 aWidth ,
PRInt32 aHeight ,
gfxASurface : : gfxImageFormat aFormat ,
PRUint8 * * imageData ,
PRUint32 * imageLength )
{
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
return InternalAddFrame ( mFrames . Length ( ) , aX , aY , aWidth , aHeight , aFormat ,
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
/* aPaletteDepth = */ 0 , imageData , imageLength ,
/* aPaletteData = */ nsnull ,
/* aPaletteLength = */ nsnull ) ;
}
/* [noscript] void appendPalettedFrame (in PRInt32 aX, in PRInt32 aY, in PRInt32 aWidth, in PRInt32 aHeight, in gfxImageFormat aFormat, in PRUint8 aPaletteDepth, [array, size_is (imageLength)] out PRUint8 imageData, out unsigned long imageLength, [array, size_is (paletteLength)] out PRUint32 paletteData, out unsigned long paletteLength); */
NS_IMETHODIMP imgContainer : : AppendPalettedFrame ( PRInt32 aX , PRInt32 aY ,
PRInt32 aWidth , PRInt32 aHeight ,
gfxASurface : : gfxImageFormat aFormat ,
PRUint8 aPaletteDepth ,
PRUint8 * * imageData ,
PRUint32 * imageLength ,
PRUint32 * * paletteData ,
PRUint32 * paletteLength )
{
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 ) ;
NS_ENSURE_ARG_POINTER ( paletteData ) ;
NS_ENSURE_ARG_POINTER ( paletteLength ) ;
2009-09-12 15:44:18 -07:00
return InternalAddFrame ( mFrames . Length ( ) , aX , aY , aWidth , aHeight , aFormat ,
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
aPaletteDepth , imageData , imageLength ,
paletteData , paletteLength ) ;
}
2009-09-12 15:44:18 -07:00
/* [noscript] void setSize(in long aWidth, in long aHeight); */
NS_IMETHODIMP imgContainer : : SetSize ( PRInt32 aWidth , PRInt32 aHeight )
{
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 " ) ;
DoError ( ) ;
return NS_ERROR_UNEXPECTED ;
}
// Set the size and flag that we have it
mSize . SizeTo ( aWidth , aHeight ) ;
mHasSize = PR_TRUE ;
return NS_OK ;
}
/* [noscript] void ensureCleanFrame(in unsigned long aFramenum, in PRInt32 aX,
in PRInt32 aY , in PRInt32 aWidth ,
in PRInt32 aHeight , in gfxImageFormat aFormat ,
[ array , size_is ( imageLength ) ]
out PRUint8 imageData ,
out unsigned long imageLength ) ; */
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_IMETHODIMP imgContainer : : EnsureCleanFrame ( PRUint32 aFrameNum , PRInt32 aX , PRInt32 aY ,
PRInt32 aWidth , PRInt32 aHeight ,
gfxASurface : : gfxImageFormat aFormat ,
PRUint8 * * imageData , PRUint32 * imageLength )
{
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! " ) ;
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 ,
/* aPaletteDepth = */ 0 , imageData , imageLength ,
/* aPaletteData = */ nsnull ,
/* aPaletteLength = */ nsnull ) ;
imgFrame * frame = GetImgFrame ( aFrameNum ) ;
if ( ! frame )
return InternalAddFrame ( aFrameNum , aX , aY , aWidth , aHeight , aFormat ,
/* aPaletteDepth = */ 0 , imageData , imageLength ,
/* aPaletteData = */ nsnull ,
/* aPaletteLength = */ nsnull ) ;
// See if we can re-use the frame that already exists.
nsIntRect rect = frame - > GetRect ( ) ;
if ( rect . x ! = aX | | rect . y ! = aY | | rect . width ! = aWidth | | rect . height ! = aHeight | |
frame - > GetFormat ( ) ! = aFormat ) {
2010-03-08 11:01:04 -08:00
DeleteImgFrame ( 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
return InternalAddFrame ( aFrameNum , aX , aY , aWidth , aHeight , aFormat ,
/* aPaletteDepth = */ 0 , imageData , imageLength ,
/* aPaletteData = */ nsnull ,
/* aPaletteLength = */ nsnull ) ;
}
// We can re-use the frame.
frame - > GetImageData ( imageData , imageLength ) ;
return NS_OK ;
}
//******************************************************************************
/* void frameUpdated (in unsigned long framenumber, in nsIntRect rect); */
NS_IMETHODIMP imgContainer : : FrameUpdated ( PRUint32 aFrameNum , nsIntRect & aUpdatedRect )
{
2009-10-07 20:22:42 -07:00
NS_ASSERTION ( aFrameNum < mFrames . Length ( ) , " Invalid frame index! " ) ;
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 ;
imgFrame * frame = GetImgFrame ( 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
NS_ENSURE_TRUE ( frame , NS_ERROR_FAILURE ) ;
frame - > ImageUpdated ( aUpdatedRect ) ;
return NS_OK ;
}
//******************************************************************************
/* void setFrameDisposalMethod (in unsigned long framenumber, in PRInt32 aDisposalMethod); */
NS_IMETHODIMP imgContainer : : SetFrameDisposalMethod ( PRUint32 aFrameNum , PRInt32 aDisposalMethod )
{
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 ;
}
//******************************************************************************
/* void setFrameTimeout (in unsigned long framenumber, in PRInt32 aTimeout); */
NS_IMETHODIMP imgContainer : : SetFrameTimeout ( PRUint32 aFrameNum , PRInt32 aTimeout )
{
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 ;
}
//******************************************************************************
/* void setFrameBlendMethod (in unsigned long framenumber, in PRInt32 aBlendMethod); */
NS_IMETHODIMP imgContainer : : SetFrameBlendMethod ( PRUint32 aFrameNum , PRInt32 aBlendMethod )
{
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 ;
}
//******************************************************************************
/* void setFrameHasNoAlpha (in unsigned long framenumber); */
NS_IMETHODIMP imgContainer : : SetFrameHasNoAlpha ( PRUint32 aFrameNum )
{
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 ;
}
//******************************************************************************
2009-04-05 07:52:18 -07:00
/* void endFrameDecode (in unsigned long framenumber); */
NS_IMETHODIMP imgContainer : : EndFrameDecode ( PRUint32 aFrameNum )
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
// Assume there's another frame.
// currentDecodingFrameIndex is 0 based, aFrameNum is 1 based
if ( mAnim )
mAnim - > currentDecodingFrameIndex = aFrameNum ;
return NS_OK ;
}
//******************************************************************************
/* void decodingComplete (); */
NS_IMETHODIMP imgContainer : : DecodingComplete ( void )
{
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 ;
2007-03-22 10:30:00 -07:00
if ( mAnim )
mAnim - > doneDecoding = 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-07-01 10:39:44 -07:00
rv = imgDiscardTracker : : 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 ;
}
//******************************************************************************
/* attribute unsigned short animationMode; */
NS_IMETHODIMP imgContainer : : GetAnimationMode ( PRUint16 * aAnimationMode )
{
2009-09-12 15:44:18 -07:00
if ( mError )
return NS_ERROR_FAILURE ;
2008-03-19 22:54:30 -07:00
NS_ENSURE_ARG_POINTER ( aAnimationMode ) ;
2007-03-22 10:30:00 -07:00
* aAnimationMode = mAnimationMode ;
return NS_OK ;
}
//******************************************************************************
/* attribute unsigned short animationMode; */
NS_IMETHODIMP imgContainer : : SetAnimationMode ( PRUint16 aAnimationMode )
{
2009-09-12 15:44:18 -07:00
if ( mError )
return NS_ERROR_FAILURE ;
2007-03-22 10:30:00 -07:00
NS_ASSERTION ( aAnimationMode = = imgIContainer : : kNormalAnimMode | |
aAnimationMode = = imgIContainer : : kDontAnimMode | |
aAnimationMode = = imgIContainer : : kLoopOnceAnimMode ,
" Wrong Animation Mode is being set! " ) ;
switch ( mAnimationMode = aAnimationMode ) {
case kDontAnimMode :
StopAnimation ( ) ;
break ;
case kNormalAnimMode :
if ( mLoopCount ! = 0 | |
2009-09-12 15:44:18 -07:00
( mAnim & & ( mAnim - > currentAnimationFrameIndex + 1 < mFrames . Length ( ) ) ) )
2007-03-22 10:30:00 -07:00
StartAnimation ( ) ;
break ;
case kLoopOnceAnimMode :
2009-09-12 15:44:18 -07:00
if ( mAnim & & ( mAnim - > currentAnimationFrameIndex + 1 < mFrames . Length ( ) ) )
2007-03-22 10:30:00 -07:00
StartAnimation ( ) ;
break ;
}
return NS_OK ;
}
//******************************************************************************
/* void startAnimation () */
NS_IMETHODIMP imgContainer : : StartAnimation ( )
{
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 | |
( mAnim & & ( mAnim - > timer | | mAnim - > animating ) ) )
return NS_OK ;
2009-09-12 15:44:18 -07:00
if ( mFrames . Length ( ) > 1 ) {
2007-03-22 10:30:00 -07:00
if ( ! ensureAnimExists ( ) )
return NS_ERROR_OUT_OF_MEMORY ;
2008-03-19 22:54:30 -07:00
// Default timeout to 100: the timer notify code will do the right
// thing, so just get that started.
PRInt32 timeout = 100 ;
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 * currentFrame = GetCurrentImgFrame ( ) ;
2007-03-22 10:30:00 -07:00
if ( currentFrame ) {
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
timeout = currentFrame - > GetTimeout ( ) ;
2007-03-22 10:30:00 -07:00
if ( timeout < = 0 ) // -1 means display this frame forever
return NS_OK ;
2008-03-19 22:54:30 -07:00
}
2007-03-22 10:30:00 -07:00
mAnim - > timer = do_CreateInstance ( " @mozilla.org/timer;1 " ) ;
2008-03-19 22:54:30 -07:00
NS_ENSURE_TRUE ( mAnim - > timer , NS_ERROR_OUT_OF_MEMORY ) ;
2007-03-22 10:30:00 -07:00
// The only way animating becomes true is if the timer is created
mAnim - > animating = PR_TRUE ;
2007-07-08 00:08:04 -07:00
mAnim - > timer - > InitWithCallback ( static_cast < nsITimerCallback * > ( this ) ,
2007-03-22 10:30:00 -07:00
timeout , nsITimer : : TYPE_REPEATING_SLACK ) ;
}
return NS_OK ;
}
//******************************************************************************
/* void stopAnimation (); */
NS_IMETHODIMP imgContainer : : StopAnimation ( )
{
2009-09-12 15:44:18 -07:00
if ( mError )
return NS_ERROR_FAILURE ;
2007-03-22 10:30:00 -07:00
if ( mAnim ) {
mAnim - > animating = PR_FALSE ;
if ( ! mAnim - > timer )
return NS_OK ;
mAnim - > timer - > Cancel ( ) ;
mAnim - > timer = nsnull ;
}
return NS_OK ;
}
//******************************************************************************
/* void resetAnimation (); */
NS_IMETHODIMP imgContainer : : ResetAnimation ( )
{
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 ;
PRBool oldAnimating = mAnim - > animating ;
if ( mAnim - > animating ) {
nsresult rv = StopAnimation ( ) ;
2008-03-19 22:54:30 -07:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
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 ) ) ;
2009-09-12 15:44:18 -07:00
if ( oldAnimating & & 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
if ( oldAnimating )
return StartAnimation ( ) ;
2008-03-19 22:54:30 -07:00
return NS_OK ;
2007-03-22 10:30:00 -07:00
}
//******************************************************************************
/* attribute long loopCount; */
NS_IMETHODIMP imgContainer : : GetLoopCount ( PRInt32 * aLoopCount )
{
2009-09-12 15:44:18 -07:00
if ( mError )
return NS_ERROR_FAILURE ;
2008-03-19 22:54:30 -07:00
NS_ENSURE_ARG_POINTER ( aLoopCount ) ;
2007-03-22 10:30:00 -07:00
* aLoopCount = mLoopCount ;
return NS_OK ;
}
//******************************************************************************
/* attribute long loopCount; */
NS_IMETHODIMP imgContainer : : SetLoopCount ( PRInt32 aLoopCount )
{
2009-09-12 15:44:18 -07:00
if ( mError )
return NS_ERROR_FAILURE ;
2007-03-22 10:30:00 -07:00
// -1 infinite
// 0 no looping, one iteration
// 1 one loop, two iterations
// ...
mLoopCount = aLoopCount ;
return NS_OK ;
}
2007-10-18 17:36:34 -07:00
//******************************************************************************
2009-09-12 15:44:18 -07:00
/* void addSourceData(in nsIInputStream aInputStream, in unsigned long aCount); */
NS_IMETHODIMP imgContainer : : 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 "
" imgContainer! " ) ;
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 ) ;
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 ,
2009-09-12 15:44:18 -07:00
( " CompressedImageAccounting: Added compressed data to imgContainer %p (%s). "
" 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 ;
}
//******************************************************************************
2009-09-12 15:44:18 -07:00
/* void sourceDataComplete(); */
NS_IMETHODIMP imgContainer : : 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 ,
2009-09-12 15:44:18 -07:00
( " CompressedImageAccounting: imgContainer::SourceDataComplete() - data "
" 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-07-01 10:39:44 -07:00
nsresult rv = imgDiscardTracker : : Reset ( & mDiscardTrackerNode ) ;
2009-09-12 15:44:18 -07:00
CONTAINER_ENSURE_SUCCESS ( rv ) ;
}
return NS_OK ;
}
//******************************************************************************
/* void newSourceData(); */
NS_IMETHODIMP imgContainer : : NewSourceData ( )
{
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.
rv = InitDecoder ( imgIDecoder : : DECODER_FLAG_NONE ) ;
CONTAINER_ENSURE_SUCCESS ( rv ) ;
return NS_OK ;
2007-10-18 17:36:34 -07:00
}
2010-06-25 11:21:40 -07:00
//******************************************************************************
/* void setSourceSizeHint(in unsigned long sizeHint); */
NS_IMETHODIMP imgContainer : : SetSourceSizeHint ( PRUint32 sizeHint )
{
if ( sizeHint & & StoringSourceData ( ) )
mSourceData . SetCapacity ( sizeHint ) ;
return NS_OK ;
}
2007-03-22 10:30:00 -07:00
//******************************************************************************
/* void notify(in nsITimer timer); */
NS_IMETHODIMP imgContainer : : Notify ( nsITimer * timer )
{
// This should never happen since the timer is only set up in StartAnimation()
// after mAnim is checked to exist.
2008-01-19 00:10:26 -08:00
NS_ENSURE_TRUE ( mAnim , NS_ERROR_UNEXPECTED ) ;
2007-03-22 10:30:00 -07:00
NS_ASSERTION ( mAnim - > timer = = timer ,
" imgContainer::Notify() called with incorrect timer " ) ;
2008-03-09 12:58:40 -07:00
if ( ! mAnim - > animating | | ! mAnim - > timer )
2007-03-22 10:30:00 -07:00
return NS_OK ;
nsCOMPtr < imgIContainerObserver > observer ( do_QueryReferent ( mObserver ) ) ;
if ( ! observer ) {
// the imgRequest that owns us is dead, we should die now too.
StopAnimation ( ) ;
return NS_OK ;
}
2009-09-12 15:44:18 -07:00
if ( mFrames . Length ( ) = = 0 )
2007-03-22 10:30:00 -07: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
imgFrame * nextFrame = nsnull ;
2007-03-22 10:30:00 -07:00
PRInt32 previousFrameIndex = mAnim - > currentAnimationFrameIndex ;
2009-09-12 15:44:18 -07:00
PRUint32 nextFrameIndex = mAnim - > currentAnimationFrameIndex + 1 ;
2007-03-22 10:30:00 -07:00
PRInt32 timeout = 0 ;
// 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.
// currentDecodingFrameIndex is not set until the second frame has
// finished decoding (see EndFrameDecode)
if ( mAnim - > doneDecoding | |
2007-05-30 01:40:45 -07:00
( nextFrameIndex < mAnim - > currentDecodingFrameIndex ) ) {
2009-09-12 15:44:18 -07:00
if ( mFrames . Length ( ) = = nextFrameIndex ) {
2007-03-22 10:30:00 -07:00
// End of Animation
// If animation mode is "loop once", it's time to stop animating
if ( mAnimationMode = = kLoopOnceAnimMode | | mLoopCount = = 0 ) {
StopAnimation ( ) ;
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 ;
}
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
timeout = nextFrame - > GetTimeout ( ) ;
2007-03-22 10:30:00 -07:00
2007-05-30 01:40:45 -07:00
} else if ( nextFrameIndex = = mAnim - > currentDecodingFrameIndex ) {
2007-03-22 10:30:00 -07:00
// 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 ;
} else { // (nextFrameIndex > currentDecodingFrameIndex)
// We shouldn't get here. However, if we are requesting a frame
// that hasn't been decoded yet, go back to the last frame decoded
NS_WARNING ( " imgContainer::Notify() Frame is passed decoded frame " ) ;
nextFrameIndex = mAnim - > currentDecodingFrameIndex ;
if ( ! ( nextFrame = mFrames [ nextFrameIndex ] ) ) {
// something wrong with the next frame, skip it
mAnim - > currentAnimationFrameIndex = nextFrameIndex ;
mAnim - > timer - > SetDelay ( 100 ) ;
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
timeout = nextFrame - > GetTimeout ( ) ;
2007-03-22 10:30:00 -07:00
}
if ( timeout > 0 )
mAnim - > timer - > SetDelay ( timeout ) ;
else
StopAnimation ( ) ;
nsIntRect dirtyRect ;
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 * frameToUse = nsnull ;
2007-03-22 10:30:00 -07:00
if ( nextFrameIndex = = 0 ) {
frameToUse = nextFrame ;
dirtyRect = mAnim - > firstFrameRefreshArea ;
} else {
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 * prevFrame = mFrames [ previousFrameIndex ] ;
2007-03-22 10:30:00 -07:00
if ( ! prevFrame )
return NS_OK ;
// Change frame and announce it
if ( NS_FAILED ( DoComposite ( & frameToUse , & dirtyRect , prevFrame ,
nextFrame , nextFrameIndex ) ) ) {
// something went wrong, move on to next
NS_WARNING ( " imgContainer::Notify(): Composing Frame Failed \n " ) ;
2009-11-12 15:18:40 -08:00
nextFrame - > SetCompositingFailed ( PR_TRUE ) ;
2007-03-22 10:30:00 -07:00
mAnim - > currentAnimationFrameIndex = nextFrameIndex ;
return NS_OK ;
2009-11-12 15:18:40 -08:00
} else {
nextFrame - > SetCompositingFailed ( PR_FALSE ) ;
2007-03-22 10:30:00 -07:00
}
}
// Set currentAnimationFrameIndex at the last possible moment
mAnim - > currentAnimationFrameIndex = nextFrameIndex ;
// Refreshes the screen
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 , & dirtyRect ) ;
2007-03-22 10:30:00 -07:00
return NS_OK ;
}
//******************************************************************************
// DoComposite gets called when the timer for animation get fired and we have to
// update the composited frame of the animation.
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 imgContainer : : DoComposite ( imgFrame * * aFrameToUse ,
2007-03-22 10:30:00 -07:00
nsIntRect * aDirtyRect ,
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 * aPrevFrame ,
imgFrame * aNextFrame ,
2007-03-22 10:30:00 -07:00
PRInt32 aNextFrameIndex )
{
2008-03-19 22:54:30 -07:00
NS_ENSURE_ARG_POINTER ( aDirtyRect ) ;
NS_ENSURE_ARG_POINTER ( aPrevFrame ) ;
NS_ENSURE_ARG_POINTER ( aNextFrame ) ;
NS_ENSURE_ARG_POINTER ( aFrameToUse ) ;
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 ( ) ;
2007-03-22 10:30:00 -07:00
if ( prevFrameDisposalMethod = = imgIContainer : : kDisposeRestorePrevious & &
! mAnim - > compositingPrevFrame )
prevFrameDisposalMethod = imgIContainer : : 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 ( ) ;
2007-03-22 10:30:00 -07:00
PRBool isFullPrevFrame = ( prevFrameRect . x = = 0 & & prevFrameRect . y = = 0 & &
prevFrameRect . width = = mSize . width & &
prevFrameRect . height = = mSize . height ) ;
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 & &
( prevFrameDisposalMethod = = imgIContainer : : kDisposeClear ) )
prevFrameDisposalMethod = imgIContainer : : 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 ( ) ;
2007-03-22 10:30:00 -07:00
PRBool isFullNextFrame = ( nextFrameRect . x = = 0 & & nextFrameRect . y = = 0 & &
nextFrameRect . width = = mSize . width & &
nextFrameRect . height = = mSize . height ) ;
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
if ( prevFrameDisposalMethod = = imgIContainer : : kDisposeClearAll ) {
aDirtyRect - > SetRect ( 0 , 0 , mSize . width , mSize . height ) ;
* aFrameToUse = aNextFrame ;
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 & &
( nextFrameDisposalMethod ! = imgIContainer : : 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 ) ;
* aFrameToUse = aNextFrame ;
return NS_OK ;
}
2007-03-22 10:30:00 -07:00
}
// Calculate area that needs updating
switch ( prevFrameDisposalMethod ) {
default :
case imgIContainer : : kDisposeNotSpecified :
case imgIContainer : : kDisposeKeep :
* aDirtyRect = nextFrameRect ;
break ;
2007-11-07 13:33:57 -08:00
case imgIContainer : : kDisposeClearAll :
// Whole image container is cleared
aDirtyRect - > SetRect ( 0 , 0 , mSize . width , mSize . height ) ;
break ;
2007-03-22 10:30:00 -07:00
case imgIContainer : : kDisposeClear :
// 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 ;
case imgIContainer : : kDisposeRestorePrevious :
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 ) {
* aFrameToUse = mAnim - > compositingFrame ;
return NS_OK ;
}
PRBool needToBlankComposite = PR_FALSE ;
// 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 ;
}
2007-03-22 10:30:00 -07:00
needToBlankComposite = PR_TRUE ;
2010-06-16 09:54:18 -07:00
} else if ( aNextFrameIndex ! = mAnim - > lastCompositedFrameIndex + 1 ) {
2007-12-20 01:37:34 -08:00
// When we are looping the compositing frame needs to be cleared.
needToBlankComposite = PR_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
PRBool doDisposal = 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
if ( ! aNextFrame - > GetHasAlpha ( ) ) {
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.
doDisposal = PR_FALSE ;
// No need to blank the composite frame
2007-03-22 10:30:00 -07:00
needToBlankComposite = PR_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.
doDisposal = PR_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 ) {
case imgIContainer : : kDisposeClear :
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 ;
case imgIContainer : : kDisposeClearAll :
2007-06-07 08:10:25 -07:00
ClearFrame ( mAnim - > compositingFrame ) ;
2007-11-07 13:33:57 -08:00
break ;
case imgIContainer : : kDisposeRestorePrevious :
// 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
if ( nextFrameDisposalMethod ! = imgIContainer : : kDisposeRestorePrevious )
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
if ( ( nextFrameDisposalMethod = = imgIContainer : : kDisposeRestorePrevious ) & &
( prevFrameDisposalMethod ! = imgIContainer : : kDisposeRestorePrevious ) ) {
// 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 ) {
NS_WARNING ( " Failed to init compositingFrame! \n " ) ;
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
// We don't want to keep composite images for 8bit frames...
if ( isFullNextFrame & & mAnimationMode = = kNormalAnimMode & & mLoopCount ! = 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
! 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 ) ) {
aPrevFrame - > SetFrameDisposalMethod ( imgIContainer : : kDisposeClearAll ) ;
mAnim - > lastCompositedFrameIndex = - 1 ;
* aFrameToUse = aNextFrame ;
return NS_OK ;
}
}
mAnim - > lastCompositedFrameIndex = aNextFrameIndex ;
* aFrameToUse = mAnim - > compositingFrame ;
return NS_OK ;
}
//******************************************************************************
2007-06-07 08:10:25 -07:00
// Fill aFrame with black. Does also clears the mask.
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
void imgContainer : : 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
}
//******************************************************************************
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
void imgContainer : : 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
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
PRBool imgContainer : : 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 .
*/
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 imgContainer : : DrawFrameTo ( imgFrame * aSrc ,
imgFrame * aDst ,
2008-01-21 23:36:57 -08:00
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 ) {
NS_WARNING ( " imgContainer::DrawFrameTo: negative offsets not allowed " ) ;
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
2008-01-21 23:36:57 -08:00
PRInt32 width = PR_MIN ( aSrcRect . width , dstRect . width - aSrcRect . x ) ;
PRInt32 height = PR_MIN ( aSrcRect . height , dstRect . height - aSrcRect . y ) ;
// 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 ) ,
" imgContainer::DrawFrameTo: Invalid aSrcRect " ) ;
// clipped image size may be smaller than source, but not larger
NS_ASSERTION ( ( width < = aSrcRect . width ) & & ( height < = aSrcRect . height ) ,
2007-11-17 01:23:51 -08:00
" imgContainer::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 ( ) ;
2007-10-23 12:33:20 -07:00
if ( blendMethod = = imgIContainer : : 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 *************/
NS_IMETHODIMP imgContainer : : Get ( const char * prop , const nsIID & iid , void * * result )
{
if ( ! mProperties )
return NS_ERROR_FAILURE ;
return mProperties - > Get ( prop , iid , result ) ;
}
NS_IMETHODIMP imgContainer : : Set ( const char * prop , nsISupports * value )
{
if ( ! mProperties )
mProperties = do_CreateInstance ( " @mozilla.org/properties;1 " ) ;
if ( ! mProperties )
return NS_ERROR_OUT_OF_MEMORY ;
return mProperties - > Set ( prop , value ) ;
}
NS_IMETHODIMP imgContainer : : Has ( const char * prop , PRBool * _retval )
{
NS_ENSURE_ARG_POINTER ( _retval ) ;
if ( ! mProperties ) {
* _retval = PR_FALSE ;
return NS_OK ;
}
return mProperties - > Has ( prop , _retval ) ;
}
NS_IMETHODIMP imgContainer : : Undefine ( const char * prop )
{
if ( ! mProperties )
return NS_ERROR_FAILURE ;
return mProperties - > Undefine ( prop ) ;
}
NS_IMETHODIMP imgContainer : : GetKeys ( PRUint32 * count , char * * * keys )
{
if ( ! mProperties ) {
* count = 0 ;
* keys = nsnull ;
return NS_OK ;
}
return mProperties - > GetKeys ( count , keys ) ;
}
2007-10-18 17:36:34 -07:00
void
2010-07-01 10:39:44 -07:00
imgContainer : : Discard ( )
2007-10-18 17:36:34 -07:00
{
2009-09-12 15:44:18 -07:00
// We should be ok for discard
2010-07-01 10:39:44 -07:00
NS_ABORT_IF_FALSE ( 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 ) ;
// 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 "
" data from imgContainer %p (%s) - %d frames (cached count: %d); "
" 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
PRBool
imgContainer : : CanDiscard ( ) {
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.
}
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.
PRBool
imgContainer : : DiscardingActive ( ) {
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
PRBool
imgContainer : : StoringSourceData ( ) {
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
2009-09-12 15:44:18 -07:00
imgContainer : : InitDecoder ( PRUint32 dFlags )
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
// Find and instantiate the decoder
nsCAutoString decoderCID ( NS_LITERAL_CSTRING ( " @mozilla.org/image/decoder;3?type= " ) +
mSourceDataMimeType ) ;
mDecoder = do_CreateInstance ( decoderCID . get ( ) ) ;
CONTAINER_ENSURE_TRUE ( mDecoder , NS_IMAGELIB_ERROR_NO_DECODER ) ;
// Store the flags for this decoder
mDecoderFlags = dFlags ;
// Initialize the decoder
nsCOMPtr < imgIDecoderObserver > observer ( do_QueryReferent ( mObserver ) ) ;
nsresult result = mDecoder - > Init ( this , observer , dFlags ) ;
CONTAINER_ENSURE_SUCCESS ( result ) ;
// Create a decode worker
mWorker = new imgDecodeWorker ( this ) ;
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
imgContainer : : ShutdownDecoder ( eShutdownIntent aIntent )
{
// 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
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're "done" _and_ it's a full decode, flush
if ( ( aIntent = = eShutdownIntent_Done ) & &
! ( mDecoderFlags & & imgIDecoder : : DECODER_FLAG_HEADERONLY ) ) {
mInDecoder = PR_TRUE ;
rv = mDecoder - > Flush ( ) ;
mInDecoder = PR_FALSE ;
2008-01-19 00:10:26 -08:00
2009-09-12 15:44:18 -07:00
// The error case here is a bit tricky. We flag an error, which takes us
// back into this function, and then we return.
if ( NS_FAILED ( rv ) ) {
DoError ( ) ;
return rv ;
}
}
// Close the decoder with the appropriate flags
mInDecoder = PR_TRUE ;
PRUint32 closeFlags = ( aIntent = = eShutdownIntent_Error )
? ( PRUint32 ) imgIDecoder : : CLOSE_FLAG_DONTNOTIFY
: 0 ;
rv = mDecoder - > Close ( closeFlags ) ;
mInDecoder = PR_FALSE ;
// null out the decoder, _then_ check for errors on the close (otherwise the
// error routine might re-invoke ShutdownDecoder)
mDecoder = nsnull ;
if ( NS_FAILED ( rv ) ) {
DoError ( ) ;
return rv ;
}
// Kill off the worker
mWorker = nsnull ;
// We just shut down the decoder. If we didn't get what we want, but expected
// to, flag an error
PRBool failed = PR_FALSE ;
if ( ( mDecoderFlags & imgIDecoder : : DECODER_FLAG_HEADERONLY ) & & ! mHasSize )
failed = PR_TRUE ;
if ( ! ( mDecoderFlags & imgIDecoder : : DECODER_FLAG_HEADERONLY ) & & ! mDecoded )
failed = PR_TRUE ;
if ( ( aIntent = = eShutdownIntent_Done ) & & failed ) {
DoError ( ) ;
return NS_ERROR_FAILURE ;
}
// Clear the flags
mDecoderFlags = imgIDecoder : : DECODER_FLAG_NONE ;
// Reset number of decoded bytes
mBytesDecoded = 0 ;
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
imgContainer : : 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
mInDecoder = PR_TRUE ;
2009-10-15 19:54:44 -07:00
nsresult rv = 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 ( ) ;
}
2009-09-12 15:44:18 -07:00
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
// 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
imgContainer : : 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! " ) ;
rv = imgDiscardTracker : : 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
imgContainer : : RequestDecode ( )
{
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 not storing source data, we have nothing to do
if ( ! StoringSourceData ( ) )
return NS_OK ;
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
2009-09-19 12:33:00 -07:00
// If we've already got a full decoder running, we have nothing to do
if ( mDecoder & & ! ( mDecoderFlags & imgIDecoder : : DECODER_FLAG_HEADERONLY ) )
return NS_OK ;
// If our callstack goes through a header-only decoder, we have a problem.
// We need to shutdown the header-only decoder and replace it with a full
// 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
2009-09-12 15:44:18 -07:00
// If we have a header-only decoder open, interrupt it and shut it down
if ( mDecoder & & ( mDecoderFlags & imgIDecoder : : DECODER_FLAG_HEADERONLY ) ) {
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 " ) ;
rv = InitDecoder ( imgIDecoder : : DECODER_FLAG_NONE ) ;
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 ;
// 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
imgContainer : : 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! " ) ;
// If we have a header-only decoder open, shut it down
if ( mDecoder & & ( mDecoderFlags & imgIDecoder : : DECODER_FLAG_HEADERONLY ) ) {
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 " ) ;
rv = InitDecoder ( imgIDecoder : : DECODER_FLAG_NONE ) ;
CONTAINER_ENSURE_SUCCESS ( rv ) ;
}
// Write everything we have
rv = WriteToDecoder ( mSourceData . Elements ( ) + mBytesDecoded ,
mSourceData . Length ( ) - mBytesDecoded ) ;
CONTAINER_ENSURE_SUCCESS ( rv ) ;
// If we finished the decode, shutdown the decoder
if ( IsDecodeFinished ( ) ) {
rv = ShutdownDecoder ( eShutdownIntent_Done ) ;
CONTAINER_ENSURE_SUCCESS ( rv ) ;
}
// All good!
2007-10-18 17:36:34 -07:00
return NS_OK ;
}
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 ,
* in PRUint32 aFlags ) ; */
NS_IMETHODIMP imgContainer : : Draw ( gfxContext * aContext ,
gfxPattern : : GraphicsFilter aFilter ,
const gfxMatrix & aUserSpaceToImageSpace ,
const gfxRect & aFill ,
const nsIntRect & aSubimage ,
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 ;
2009-09-12 15:44:18 -07:00
NS_ENSURE_ARG_POINTER ( aContext ) ;
// 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 ) ;
2007-10-18 17:36:34 -07:00
return NS_OK ;
}
2009-09-12 15:44:18 -07:00
//******************************************************************************
/* void lockImage() */
2007-10-18 17:36:34 -07:00
NS_IMETHODIMP
2009-09-12 15:44:18 -07:00
imgContainer : : 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-07-01 10:39:44 -07:00
imgDiscardTracker : : 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
2009-09-12 15:44:18 -07:00
imgContainer : : 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 - - ;
// We now _might_ have one of the qualifications for discarding. Re-evaluate.
if ( CanDiscard ( ) ) {
2010-07-01 10:39:44 -07:00
nsresult rv = imgDiscardTracker : : 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
imgContainer : : 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
PRUint32 bytesToDecode = PR_MIN ( aMaxBytes ,
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.
PRBool imgContainer : : IsDecodeFinished ( )
2007-10-18 17:36:34 -07:00
{
2009-09-12 15:44:18 -07:00
// Assume it's not finished
PRBool decodeFinished = PR_FALSE ;
// 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...
if ( mDecoderFlags & imgIDecoder : : DECODER_FLAG_HEADERONLY ) {
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
}
2009-09-12 15:44:18 -07:00
// Indempotent error flagging routine. If a decoder is open,
// sends OnStopContainer and OnStopDecode and shuts down the decoder
void imgContainer : : 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 ;
// If we're mid-decode
if ( mDecoder ) {
// grab the observer and give an OnStopContainer and an OnStopDecode
nsCOMPtr < imgIDecoderObserver > observer = do_QueryReferent ( mObserver ) ;
if ( observer ) {
observer - > OnStopContainer ( nsnull , this ) ;
observer - > OnStopDecode ( nsnull , NS_ERROR_FAILURE , nsnull ) ;
}
// Shutdown the decoder in error mode. We don't care if this flags other
// errors.
( void ) ShutdownDecoder ( eShutdownIntent_Error ) ;
}
// 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
// Tweakable progressive decoding parameters
# define DECODE_BYTES_AT_A_TIME 4096
# define MAX_USEC_BEFORE_YIELD (1000 * 5)
// Decodes some data, then re-posts itself to the end of the event queue if
// there's more processing to be done
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 ;
imgContainer * container = static_cast < imgContainer * > ( iContainer . get ( ) ) ;
2007-10-18 17:36:34 -07:00
2009-09-12 15:44:18 -07:00
NS_ABORT_IF_FALSE ( container - > mInitialized ,
" Worker active for uninitialized container! " ) ;
// If we were pending, we're not anymore
container - > mWorkerPending = PR_FALSE ;
// 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.
if ( container - > mError )
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).
if ( ! container - > mDecoder )
return NS_OK ;
// Header-only decodes are cheap and we more or less want them to be
// synchronous. Write all the data in that case, otherwise write a
// chunk
PRUint32 maxBytes =
( container - > mDecoderFlags & imgIDecoder : : DECODER_FLAG_HEADERONLY )
? container - > mSourceData . Length ( ) : DECODE_BYTES_AT_A_TIME ;
// Loop control
PRBool haveMoreData = PR_TRUE ;
nsTime deadline ( PR_Now ( ) + MAX_USEC_BEFORE_YIELD ) ;
// 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
while ( haveMoreData & & ! container - > IsDecodeFinished ( ) & &
( nsTime ( PR_Now ( ) ) < deadline ) ) {
// Decode a chunk of data
rv = container - > DecodeSomeData ( maxBytes ) ;
if ( NS_FAILED ( rv ) ) {
container - > DoError ( ) ;
return rv ;
}
// Figure out if we still have more data
haveMoreData =
container - > mSourceData . Length ( ) > container - > mBytesDecoded ;
2007-10-18 17:36:34 -07:00
}
2009-09-12 15:44:18 -07:00
// If the decode finished, shutdown the decoder
if ( container - > IsDecodeFinished ( ) ) {
rv = container - > ShutdownDecoder ( imgContainer : : eShutdownIntent_Done ) ;
if ( NS_FAILED ( rv ) ) {
container - > DoError ( ) ;
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.
if ( ! container - > IsDecodeFinished ( ) & & haveMoreData )
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 ;
imgContainer * container = static_cast < imgContainer * > ( 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
NS_ABORT_IF_FALSE ( ! container - > mWorkerPending ,
" Trying to queue up worker with one already pending! " ) ;
// Flag that we're pending
container - > 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
// container without processing. The imgContainer is passed as the closure.
// Always reads everything it gets, even if the data is erroneous.
NS_METHOD
imgContainer : : WriteToContainer ( nsIInputStream * in , void * closure ,
const char * fromRawSegment , PRUint32 toOffset ,
PRUint32 count , PRUint32 * writeCount )
{
// Retrieve the imgContainer
imgIContainer * container = static_cast < imgIContainer * > ( closure ) ;
2007-10-18 17:36:34 -07:00
2009-09-12 15:44:18 -07:00
// Copy the source data. 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.
( void ) container - > AddSourceData ( fromRawSegment , count ) ;
2007-10-18 17:36:34 -07:00
2009-09-12 15:44:18 -07:00
// We wrote everything we got
* writeCount = count ;
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
}