diff options
author | ahze <ahze@df743ca5-7f9a-e211-a948-0013205c9059> | 2007-11-20 22:26:27 +0800 |
---|---|---|
committer | ahze <ahze@df743ca5-7f9a-e211-a948-0013205c9059> | 2007-11-20 22:26:27 +0800 |
commit | 7731ad11fe0582d0846dc89960383c0a5b944275 (patch) | |
tree | 08089f4a9ebd0570a818586eb35c4178ff931d5c | |
parent | 73f86b3e1be20c22b6024e1a12beae74aec11107 (diff) | |
download | marcuscom-ports-experimental-7731ad11fe0582d0846dc89960383c0a5b944275.tar.gz marcuscom-ports-experimental-7731ad11fe0582d0846dc89960383c0a5b944275.tar.zst marcuscom-ports-experimental-7731ad11fe0582d0846dc89960383c0a5b944275.zip |
Update to 3.0b1
git-svn-id: svn://creme-brulee.marcuscom.com/ports-experimental/trunk@17394 df743ca5-7f9a-e211-a948-0013205c9059
-rw-r--r-- | www/firefox-devel/Makefile | 10 | ||||
-rw-r--r-- | www/firefox-devel/distinfo | 6 | ||||
-rw-r--r-- | www/firefox-devel/files/patch-bugzilla296818 | 1618 |
3 files changed, 7 insertions, 1627 deletions
diff --git a/www/firefox-devel/Makefile b/www/firefox-devel/Makefile index 3b51243..1d54fec 100644 --- a/www/firefox-devel/Makefile +++ b/www/firefox-devel/Makefile @@ -3,17 +3,15 @@ # Whom: Alan Eldridge <alane@FreeBSD.org> # # $FreeBSD$ -# $MCom: ports-experimental/www/firefox-devel/Makefile,v 1.5 2007/09/20 18:09:32 ahze Exp $ +# $MCom: ports-experimental/www/firefox-devel/Makefile,v 1.6 2007/09/26 18:33:23 ahze Exp $ PORTNAME= firefox -DISTVERSION= 3.0.a8 +DISTVERSION= 3.0b1 PORTEPOCH= 1 CATEGORIES= www ipv6 MASTER_SITES= ${MASTER_SITE_MOZILLA} -MASTER_SITE_SUBDIR= ${PORTNAME}/releases/granparadiso/alpha8/source/ -#MASTER_SITE_SUBDIR= ${PORTNAME}/releases/${DISTVERSION}/source -DISTNAME= granparadiso-alpha8-source -#DISTNAME= ${PORTNAME}-${DISTVERSION}-source +MASTER_SITE_SUBDIR= ${PORTNAME}/releases/${DISTVERSION}/source +DISTNAME= ${PORTNAME}-${DISTVERSION}-source MAINTAINER= gnome@FreeBSD.org COMMENT= Web browser based on the browser portion of Mozilla diff --git a/www/firefox-devel/distinfo b/www/firefox-devel/distinfo index 436ca85..b7fb9af 100644 --- a/www/firefox-devel/distinfo +++ b/www/firefox-devel/distinfo @@ -1,3 +1,3 @@ -MD5 (granparadiso-alpha8-source.tar.bz2) = ffcf7c99940fc3a304f9c06890741497 -SHA256 (granparadiso-alpha8-source.tar.bz2) = d06eae776376796bacb85f4b36d140d566d0ad8b3d1161ae4d60f53c64e1c27a -SIZE (granparadiso-alpha8-source.tar.bz2) = 34327675 +MD5 (firefox-3.0b1-source.tar.bz2) = 770510a9c7b2b4bdb1692a65473bc950 +SHA256 (firefox-3.0b1-source.tar.bz2) = c96a6def1acdca6886124b3b7f2a3d0ecb217a4f582b37c67d63e416d541b00a +SIZE (firefox-3.0b1-source.tar.bz2) = 34385058 diff --git a/www/firefox-devel/files/patch-bugzilla296818 b/www/firefox-devel/files/patch-bugzilla296818 deleted file mode 100644 index f46ef75..0000000 --- a/www/firefox-devel/files/patch-bugzilla296818 +++ /dev/null @@ -1,1618 +0,0 @@ -diff --git ChangeLog ChangeLog -new file mode 100644 -index 0000000..c9c7dce ---- /dev/null -+++ ChangeLog -@@ -0,0 +1,277 @@ -+2007-09-06 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -+ (nsJPEGDecoder::WriteFrom): Write the restore data regardless of -+ the state we are in, right when we first fill the buffer. -+ -+2007-09-06 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (imgContainer::RestoreDataDone): Print the first four bytes of the -+ restore data, to check it later. -+ (imgContainer::ReloadImages): Likewise. -+ -+2007-09-06 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/decoders/png/nsPNGDecoder.cpp (info_callback): -+ Reuse the image container if the loader has one; don't always -+ create a new one. This lets containers reload themselves. -+ -+2007-09-06 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (imgContainer::AppendFrame): Unconditionally increment mNumFrames! -+ (imgContainer::RestoreDiscardedData): Check the number of restored -+ frames here. -+ (imgContainer::ReloadImages): Flush and close the decoder. -+ (imgContainer::RestoreDataDone): No-op if we are already restoring -+ the data. -+ -+2007-09-06 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/decoders/png/nsPNGDecoder.cpp (*): Print the -+ imgContainer pointers when logging. -+ -+ * modules/libpr0n/src/imgContainer.cpp (*): Likewise. -+ -+2007-09-04 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (imgContainer::ReloadImages): Oops, use an nsCOMPtr<> for the -+ ContainerLoader, not a direct pointer. -+ (ContainerLoader NS_IMPL_ISUPPORTS3): Oops, we also implement -+ imgIContainerObserver. -+ (class ContainerLoader): Implement nsISupportsWeakReference as -+ well; imgContainer needs it from the observer. -+ (imgContainer::RestoreDiscardedData): Log how many frames we got -+ and how many we expected. -+ (imgContainer::ReloadImages): Assert that we got the right number -+ of frames. -+ (imgContainer::GetCurrentFrameNoRef): Log failures from -+ RestoreDiscardedData(). -+ -+ * modules/libpr0n/decoders/png/nsPNGDecoder.cpp (end_callback): -+ Don't tell the container that the restore data is done here... -+ (nsPNGDecoder::Close): ... but do it here instead. This is -+ because end_callback() gets called from within ReadDataOut(); we -+ don't want end_callback() to inform the container that the restore -+ data is done before actually writing the restore data to it! -+ -+2007-09-04 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/decoders/png/nsPNGDecoder.cpp (info_callback): -+ Set the image container as discardable. -+ (ReadDataOut): Store the compressed data in the image container to -+ restore from it later. -+ (end_callback): Tell the image container that we finished feeding -+ it the restore data. -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (imgContainer::SetDiscardable): Log the MIME type of the -+ discardable container. -+ -+ * modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -+ (nsJPEGDecoder::WriteFrom): Clean up a printf format, and do the -+ logging only on success. -+ -+ * gfx/thebes/public/gfxXlibSurface.h: Add myself to the contributors. -+ * modules/libpr0n/public/imgIContainer.idl: Likewise. -+ * modules/libpr0n/src/imgContainer.cpp: Likewise. -+ * modules/libpr0n/src/imgContainer.h: Likewise. -+ -+2007-09-03 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (imgContainer::AddRestoreData): No-op if we are being called -+ during the restore process (we already have the data; there is no -+ need to save it again). -+ (class ContainerLoader): Put the macro to implement QI for -+ imgILoad and imgIDecoderObserver. -+ (imgContainer::AppendFrame): Don't increment mNumFrames if we are -+ restoring the image data. Fix the use of the frame counters. -+ (imgContainer::sDiscardTimerCallback): Implement. -+ (imgContainer::GetCurrentFrame): Oops, preserve the semantics of -+ the original function --- if the actual getter gives us a null -+ frame, return NS_ERROR_FAILURE. -+ -+2007-08-31 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.h (class imgContainer): New -+ prototype for a ReloadImages() method. -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (imgContainer::RestoreDiscardedData): Call ReloadImages(). -+ (imgContainer::ReloadImages): Implement. -+ (class ContainerLoader): New helper class that implements -+ imgILoader and imgIDecoderObserver. We'll use this to re-load the -+ imgContainer from an image decoder. -+ -+2007-08-31 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (imgContainer::RestoreDiscardedData): Reset the timer; if we got -+ here it means that the data may be used again soon. -+ -+2007-08-30 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.h (class imgContainer): Add an -+ mDiscarded field. We'll use it to know if the uncompressed image -+ data has been discarded already and needs to be regenerated on -+ demand. -+ (class imgContainer): New prototype for a RestoreDiscardedData() method. -+ -+ * modules/libpr0n/src/imgContainer.cpp (imgContainer): Initialize -+ mDiscarded. -+ (imgContainer::GetCurrentFrameNoRef): Return an nsresult rather -+ than the image frame; return the actual image frame as a -+ reference. Ensure that the discarded data gets restored. -+ (imgContainer::GetCurrentFrame): Return the error from -+ GetCurrentFrameNoRef() if it fails. -+ (imgContainer::StartAnimation): Likewise. -+ (imgContainer::GetFrameAt): Ensure that the discarded data gets restored. -+ (imgContainer::ResetAnimation): Likewise. -+ (imgContainer::Notify): Likewise. -+ (imgContainer::RestoreDiscardedData): Just a stub for now. -+ -+ * modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -+ (nsJPEGDecoder::WriteFrom): Oops, use "count" for the restore -+ data, not "mBufferLen". -+ -+2007-08-29 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.h (class imgContainer): Add a -+ mNumFrames field. Since we'll discard the contents of mFrames, we -+ can't rely on mFrames.Count() for the frame count. -+ -+ * modules/libpr0n/src/imgContainer.cpp (imgContainer): Initialize mNumFrames. -+ (imgContainer::AppendFrame): Maintain the frame count in mNumFrames. -+ (imgContainer::GetNumFrames): Use mNumFrames instead of mFrames.Count(). -+ (imgContainer::GetFrameAt): Likewise. -+ (imgContainer::DecodingComplete): Likewise. -+ (imgContainer::SetAnimationMode): Likewise. -+ (imgContainer::StartAnimation): Likewise. -+ (imgContainer::Notify): Likewise. -+ -+2007-08-29 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.h -+ (imgContainer::inlinedGetCurrentFrame): Removed to make it not -+ inline. -+ (imgContainer::GetCurrentFrameNoRef): New prototype. -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (imgContainer::GetCurrentFrameNoRef): Implement this here. -+ (imgContainer::GetCurrentFrame, imgContainer::StartAnimation): Use -+ GetCurrentFrameNoRef() instead of inlinedGetCurrentFrame(). -+ -+2007-08-28 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/public/imgIContainer.idl (restoreDataDone): New -+ method. We'll use this to tell the container when we finish -+ feeding it the compressed data. After that, it can begin its -+ discard process whenever it wants. -+ -+ * modules/libpr0n/src/imgContainer.h (class imgContainer): Add -+ mRestoreDataDone and mDiscardTimer fields. -+ -+ * modules/libpr0n/src/imgContainer.cpp (imgContainer): Initialize -+ the new fields. -+ (imgContainer::RestoreDataDone): Implement. When turned on, we -+ start the discard timer. -+ (imgContainer::ResetDiscardTimer): New method. -+ (~imgContainer): Cancel and destroy the timer. -+ (imgContainer::sDiscardTimerCallback): New callback. Here we'll -+ discard the uncompressed image data in the image frames. For now -+ this is just a stub. -+ -+ * modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -+ (nsJPEGDecoder::WriteFrom): Tell the imgContainer when we are done -+ feeding data to it. -+ -+2007-08-28 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.cpp (discarding_is_enabled): -+ Stub function, to be replaced with something better in the -+ future. This lets us disable image discarding by setting a -+ MOZ_DISABLE_IMAGE_DISCARD environment variable. -+ (imgContainer::SetDiscardable): Noop if discarding is disabled. -+ (imgContainer::AddRestoreData): Likewise. -+ -+2007-08-28 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -+ (nsJPEGDecoder::WriteFrom): Mark the imgContainer as discardable -+ when we create it. And when writing to the JPEG decoder, add the -+ compressed data to the imgContainer so that it can restore itself -+ later. -+ -+2007-08-28 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgContainer.cpp -+ (gCompressedImageAccountingLog): Create a -+ "CompressedImageAccounting" log domain. -+ (~imgContainer): Log the destruction of compressed data. -+ (imgContainer::AddRestoreData): Log the addition of compressed data. -+ (imgContainer::SetDiscardable): Log the creation of a compressed imgContainer. -+ -+2007-08-28 Federico Mena Quintero <federico@novell.com> -+ -+ -+ * modules/libpr0n/src/imgContainer.cpp (~imgContainer): Free the -+ restore data and the MIME type. -+ -+2007-08-22 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/public/imgIContainer.idl (setDiscardable): New -+ method. When this is called (can be called only once) from an -+ image decoder, the image container will discard its uncompressed -+ image data after a timeout. -+ (addRestoreData): New method. Image decoders should call this -+ repeatedly after calling setDiscardable(); this is used to feed -+ the original, compressed image data to the image container so that -+ it can uncompress it on demand after discarding it. -+ -+ * modules/libpr0n/src/imgContainer.cpp (imgContainer::SetDiscardable): -+ Implement. -+ (imgContainer::AddRestoreData): Implement. -+ -+2007-08-20 Federico Mena Quintero <federico@novell.com> -+ -+ * gfx/thebes/src/gfxXlibSurface.cpp -+ (gfxXlibSurface::LogSurfaceCreation, surface_destroy_func): Count -+ the number of surfaces in addition to the number of pixels. -+ -+2007-08-17 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/public/ImageLogging.h: Remove gImgAccountingLog -+ from here. -+ -+ * modules/libpr0n/src/imgRequest.cpp: Likewise. -+ -+ * modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -+ (gJPEGDecodeAccountingLog): Create a "JPEGDecoderAccounting" log domain. -+ (nsJPEGDecoder::WriteFrom): Use that log domain. -+ -+ * gfx/thebes/src/gfxXlibSurface.cpp (gXlibSurfaceAccountingLog): -+ Define a "XlibSurfaceAccounting" log domain. -+ (gfxXlibSurface::LogSurfaceCreation): New method to log when an -+ Xlib surface is created from a pixmap. Keeps a counter of how -+ many pixels are allocated globally. -+ (gfxXlibSurface::HookSurfaceDestructionForLogging): Utility method -+ to set user data on the cairo surface, so that we can know when it -+ is destroyed. -+ (gfxXlibSurface::gfxXlibSurface): Log the creation of the surface, -+ and hook it so that we can know when it is destroyed. -+ -+2007-08-17 Federico Mena Quintero <federico@novell.com> -+ -+ * modules/libpr0n/src/imgRequest.cpp (gImgAccountingLog): New -+ logging domain "imgAccounting". We'll use this to log when images -+ get allocated, freed, requested, etc. -+ -+ * modules/libpr0n/public/ImageLogging.h (gImgAccountingLog): -+ Declare this. -+ -+ * modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -+ (nsJPEGDecoder::WriteFrom): Log the creation of an image frame. -+ -diff --git gfx/thebes/public/gfxXlibSurface.h gfx/thebes/public/gfxXlibSurface.h -index 078dc73..ea7ba24 100644 ---- gfx/thebes/public/gfxXlibSurface.h -+++ gfx/thebes/public/gfxXlibSurface.h -@@ -21,6 +21,7 @@ - * Contributor(s): - * Stuart Parmenter <pavlov@pavlov.net> - * Vladimir Vukicevic <vladimir@pobox.com> -+ * Federico Mena-Quintero <federico@novell.com> - * - * 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 -@@ -85,6 +86,9 @@ public: - // when the gfxXlibSurface is destroyed. - void TakePixmap(); - -+ void LogSurfaceCreation (); -+ void HookSurfaceDestructionForLogging (); -+ - protected: - // if TakePixmap() was already called on this - PRBool mPixmapTaken; -diff --git gfx/thebes/src/gfxXlibSurface.cpp gfx/thebes/src/gfxXlibSurface.cpp -index dc2a19f..f9c191c 100644 ---- gfx/thebes/src/gfxXlibSurface.cpp -+++ gfx/thebes/src/gfxXlibSurface.cpp -@@ -21,6 +21,7 @@ - * Contributor(s): - * Stuart Parmenter <pavlov@pavlov.net> - * Vladimir Vukicevic <vladimir@pobox.com> -+ * Federico Mena-Quintero <federico@novell.com> - * - * 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 -@@ -37,6 +38,7 @@ - * ***** END LICENSE BLOCK ***** */ - - #include "gfxXlibSurface.h" -+#include "prlog.h" - - #include "cairo.h" - #include "cairo-xlib.h" -@@ -51,6 +53,18 @@ typedef struct { - - static void pixmap_free_func (void *); - -+ -+#if defined(PR_LOGGING) -+static PRLogModuleInfo *gXlibSurfaceAccountingLog = PR_NewLogModule ("XlibSurfaceAccounting"); -+#else -+#define gXlibSurfaceAccountingLog -+#endif -+ -+static cairo_user_data_key_t surface_free_key; -+static int num_surfaces_allocated; -+static PRInt64 pixels_allocated; -+ -+ - #define XLIB_IMAGE_SIDE_SIZE_LIMIT 0xffff - - gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual) -@@ -59,6 +73,9 @@ gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual) - DoSizeQuery(); - cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, mSize.width, mSize.height); - Init(surf); -+ -+ LogSurfaceCreation (); -+ HookSurfaceDestructionForLogging(); - } - - gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, const gfxIntSize& size) -@@ -69,6 +86,9 @@ gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, - - cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, mSize.width, mSize.height); - Init(surf); -+ -+ LogSurfaceCreation (); -+ HookSurfaceDestructionForLogging(); - } - - gfxXlibSurface::gfxXlibSurface(Display *dpy, Visual *visual, const gfxIntSize& size) -@@ -87,6 +107,9 @@ gfxXlibSurface::gfxXlibSurface(Display *dpy, Visual *visual, const gfxIntSize& s - - Init(surf); - TakePixmap(); -+ -+ LogSurfaceCreation (); -+ HookSurfaceDestructionForLogging(); - } - - gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, XRenderPictFormat *format, -@@ -100,6 +123,9 @@ gfxXlibSurface::gfxXlibSurface(Display *dpy, Drawable drawable, XRenderPictForma - ScreenOfDisplay(dpy,DefaultScreen(dpy)), - format, mSize.width, mSize.height); - Init(surf); -+ -+ LogSurfaceCreation (); -+ HookSurfaceDestructionForLogging(); - } - - gfxXlibSurface::gfxXlibSurface(Display *dpy, XRenderPictFormat *format, const gfxIntSize& size) -@@ -115,6 +141,9 @@ gfxXlibSurface::gfxXlibSurface(Display *dpy, XRenderPictFormat *format, const gf - format, mSize.width, mSize.height); - Init(surf); - TakePixmap(); -+ -+ LogSurfaceCreation (); -+ HookSurfaceDestructionForLogging(); - } - - gfxXlibSurface::gfxXlibSurface(cairo_surface_t *csurf) -@@ -124,6 +153,9 @@ gfxXlibSurface::gfxXlibSurface(cairo_surface_t *csurf) - mDisplay = cairo_xlib_surface_get_display(csurf); - - Init(csurf, PR_TRUE); -+ -+ LogSurfaceCreation (); -+ HookSurfaceDestructionForLogging(); - } - - gfxXlibSurface::~gfxXlibSurface() -@@ -198,3 +230,63 @@ pixmap_free_func (void *data) - - delete pfs; - } -+ -+void -+gfxXlibSurface::LogSurfaceCreation () -+{ -+ gfxIntSize size; -+ -+ size = GetSize (); -+ -+ num_surfaces_allocated++; -+ pixels_allocated += (PRInt64) size.width * size.height; -+ -+ PR_LOG (gXlibSurfaceAccountingLog, PR_LOG_DEBUG, -+ ("XlibSurfaceAccounting: Xlib surface %p created, %ux%u pixels - %d surfaces with %lld global pixels allocated", -+ CairoSurface (), -+ size.width, -+ size.height, -+ num_surfaces_allocated, -+ pixels_allocated)); -+} -+ -+struct SurfaceFreeData { -+ gfxIntSize size; -+ cairo_surface_t *surface; -+}; -+ -+static void -+surface_destroy_func (void *closure) -+{ -+ SurfaceFreeData *data; -+ -+ data = (SurfaceFreeData *) closure; -+ -+ num_surfaces_allocated--; -+ pixels_allocated -= (PRInt64) data->size.width * data->size.height; -+ -+ PR_LOG (gXlibSurfaceAccountingLog, PR_LOG_DEBUG, -+ ("XlibSurfaceAccounting: Destroying Xlib surface %p, %dx%d pixels - %d surfaces with %lld global pixels allocated", -+ data->surface, -+ data->size.width, -+ data->size.height, -+ num_surfaces_allocated, -+ pixels_allocated)); -+ -+ delete data; -+} -+ -+void -+gfxXlibSurface::HookSurfaceDestructionForLogging () -+{ -+ SurfaceFreeData *data; -+ -+ data = new SurfaceFreeData; -+ data->size = GetSize (); -+ data->surface = CairoSurface (); -+ -+ cairo_surface_set_user_data (data->surface, -+ &surface_free_key, -+ data, -+ surface_destroy_func); -+} -diff --git modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -index 16b9fd8..48431e4 100644 ---- modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -+++ modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp -@@ -22,6 +22,7 @@ - * - * Contributor(s): - * Stuart Parmenter <stuart@mozilla.com> -+ * Federico Mena-Quintero <federico@novell.com> - * - * 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 -@@ -63,8 +64,10 @@ NS_IMPL_ISUPPORTS1(nsJPEGDecoder, imgIDecoder) - - #if defined(PR_LOGGING) - PRLogModuleInfo *gJPEGlog = PR_NewLogModule("JPEGDecoder"); -+static PRLogModuleInfo *gJPEGDecoderAccountingLog = PR_NewLogModule ("JPEGDecoderAccounting"); - #else - #define gJPEGlog -+#define gJPEGDecoderAccountingLog - #endif - - -@@ -208,6 +211,15 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR - nsresult rv = inStr->Read((char*)mBuffer, count, &mBufferLen); - *_retval = mBufferLen; - -+ if (mImage) { -+ nsresult result = mImage->AddRestoreData ((char *) mBuffer, count); -+ -+ if (NS_FAILED (result)) { -+ mState = JPEG_ERROR; -+ return result; -+ } -+ } -+ - NS_ASSERTION(NS_SUCCEEDED(rv), "nsJPEGDecoder::WriteFrom -- inStr->Read failed"); - } - // else no input stream.. Flush() ? -@@ -357,6 +369,9 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR - /* Check if the request already has an image container. - this is the case when multipart/x-mixed-replace is being downloaded - if we already have one and it has the same width and height, reuse it. -+ -+ This is also the case when an existing container is reloading itself from -+ us. - */ - mImageLoad->GetImage(getter_AddRefs(mImage)); - if (mImage) { -@@ -370,6 +385,8 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR - } - - if (!mImage) { -+ nsresult result; -+ - mImage = do_CreateInstance("@mozilla.org/image/container;1"); - if (!mImage) { - mState = JPEG_ERROR; -@@ -377,6 +394,18 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR - } - mImageLoad->SetImage(mImage); - mImage->Init(mInfo.image_width, mInfo.image_height, mObserver); -+ -+ result = mImage->SetDiscardable ("image/jpeg"); /* FIXME: is this MIME type always right for this decoder? */ -+ if (NS_FAILED (result)) { -+ mState = JPEG_ERROR; -+ return result; -+ } -+ -+ result = mImage->AddRestoreData ((char *) mBuffer, count); -+ if (NS_FAILED (result)) { -+ mState = JPEG_ERROR; -+ return result; -+ } - } - - mObserver->OnStartContainer(nsnull, mImage); -@@ -416,7 +445,11 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR - } - - mImage->AppendFrame(mFrame); -- } -+ -+ PR_LOG (gJPEGDecoderAccountingLog, PR_LOG_DEBUG, -+ ("JPEGDecoderAccounting: nsJPEGDecoder::WriteFrom -- created image frame with %ux%u pixels", -+ mInfo.image_width, mInfo.image_height)); -+ } - - mObserver->OnStartFrame(nsnull, mFrame); - -@@ -538,6 +571,8 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR - - case JPEG_DONE: - { -+ nsresult result; -+ - LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_DONE case"); - - /* Step 7: Finish decompression */ -@@ -547,6 +582,12 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR - - mState = JPEG_SINK_NON_JPEG_TRAILER; - -+ result = mImage->RestoreDataDone (); -+ if (NS_FAILED (result)) { -+ mState = JPEG_ERROR; -+ return result; -+ } -+ - /* we're done dude */ - break; - } ---- modules/libpr0n/public/imgIContainer.idl -+++ modules/libpr0n/public/imgIContainer.idl -@@ -22,6 +22,7 @@ - * - * Contributor(s): - * Stuart Parmenter <pavlov@netscape.com> -+ * Federico Mena-Quintero <federico@novell.com> - * - * 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 -@@ -144,4 +145,10 @@ interface imgIContainer : nsISupports - * @note -1 means forever. - */ - attribute long loopCount; -+ -+ /* Methods to discard uncompressed images and restore them again */ -+ [noscript] void setDiscardable(in string aMimeType); -+ [noscript] void addRestoreData(in charPtr aBuffer, -+ in unsigned long aCount); -+ [noscript] void restoreDataDone(); - }; -diff --git modules/libpr0n/src/imgContainer.cpp modules/libpr0n/src/imgContainer.cpp -index 776c4ee..22d8735 100644 ---- modules/libpr0n/src/imgContainer.cpp -+++ modules/libpr0n/src/imgContainer.cpp -@@ -25,6 +25,7 @@ - * Asko Tontti <atontti@cc.hut.fi> - * Arron Mogge <paper@animecity.nu> - * Andrew Smith -+ * Federico Mena-Quintero <federico@novell.com> - * - * 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 -@@ -42,23 +43,49 @@ - - #include "nsComponentManagerUtils.h" - #include "imgIContainerObserver.h" -+#include "ImageErrors.h" - #include "nsIImage.h" -+#include "imgILoad.h" -+#include "imgIDecoder.h" -+#include "imgIDecoderObserver.h" - #include "imgContainer.h" - #include "nsIInterfaceRequestor.h" - #include "nsIInterfaceRequestorUtils.h" - #include "nsAutoPtr.h" -+#include "nsStringStream.h" -+#include "prmem.h" -+#include "prlog.h" - - #include "gfxContext.h" - -+/* Accounting for compressed data */ -+#if defined(PR_LOGGING) -+static PRLogModuleInfo *gCompressedImageAccountingLog = PR_NewLogModule ("CompressedImageAccounting"); -+#else -+#define gCompressedImageAccountingLog -+#endif -+ -+static int num_containers_with_discardable_data; -+static PRInt64 num_compressed_image_bytes; -+ -+ - NS_IMPL_ISUPPORTS3(imgContainer, imgIContainer, nsITimerCallback, nsIProperties) - - //****************************************************************************** - imgContainer::imgContainer() : - mSize(0,0), -+ mNumFrames(0), - mAnim(nsnull), - mAnimationMode(kNormalAnimMode), - mLoopCount(-1), -- mObserver(nsnull) -+ mObserver(nsnull), -+ mDiscardable(PR_FALSE), -+ mDiscarded(PR_FALSE), -+ mDiscardableMimeType(nsnull), -+ mRestoreData(nsnull), -+ mRestoreDataLength(0), -+ mRestoreDataDone(PR_FALSE), -+ mDiscardTimer(nsnull) - { - } - -@@ -67,6 +94,32 @@ imgContainer::~imgContainer() - { - if (mAnim) - delete mAnim; -+ -+ if (mDiscardableMimeType) { -+ free (mDiscardableMimeType); -+ mDiscardableMimeType = nsnull; -+ } -+ -+ if (mRestoreData) { -+ PR_Free (mRestoreData); -+ -+ num_containers_with_discardable_data--; -+ num_compressed_image_bytes -= mRestoreDataLength; -+ -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: destroying imgContainer %p. " -+ "Compressed containers: %d, Compressed data bytes: %lld", -+ this, -+ num_containers_with_discardable_data, -+ num_compressed_image_bytes)); -+ -+ mRestoreDataLength = 0; -+ } -+ -+ if (mDiscardTimer) { -+ mDiscardTimer->Cancel (); -+ mDiscardTimer = nsnull; -+ } - } - - //****************************************************************************** -@@ -124,15 +177,53 @@ NS_IMETHODIMP imgContainer::GetHeight(PRInt32 *aHeight) - return NS_OK; - } - -+nsresult imgContainer::GetCurrentFrameNoRef (gfxIImageFrame** aFrame) -+{ -+ nsresult result; -+ -+ result = RestoreDiscardedData (); -+ if (NS_FAILED (result)) { -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: imgContainer::GetCurrentFrameNoRef(): error %d in RestoreDiscardedData(); " -+ "returning a null frame from imgContainer %p", -+ result, -+ this)); -+ -+ *aFrame = nsnull; -+ return result; -+ } -+ -+ if (!mAnim) -+ *aFrame = mFrames.SafeObjectAt(0); -+ else if (mAnim->lastCompositedFrameIndex == mAnim->currentAnimationFrameIndex) -+ *aFrame = mAnim->compositingFrame; -+ else -+ *aFrame = mFrames.SafeObjectAt(mAnim->currentAnimationFrameIndex); -+ -+ if (!*aFrame) -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: imgContainer::GetCurrentFrameNoRef(): returning null frame from imgContainer %p " -+ "(no errors when restoring data)", -+ this)); -+ -+ return NS_OK; -+} -+ - //****************************************************************************** - /* readonly attribute gfxIImageFrame currentFrame; */ - NS_IMETHODIMP imgContainer::GetCurrentFrame(gfxIImageFrame **aCurrentFrame) - { -+ nsresult result; -+ - NS_ASSERTION(aCurrentFrame, "imgContainer::GetCurrentFrame; Invalid Arg"); - if (!aCurrentFrame) - return NS_ERROR_INVALID_POINTER; - -- if (!(*aCurrentFrame = inlinedGetCurrentFrame())) -+ result = GetCurrentFrameNoRef (aCurrentFrame); -+ if (NS_FAILED (result)) -+ return result; -+ -+ if (!*aCurrentFrame) - return NS_ERROR_FAILURE; - - NS_ADDREF(*aCurrentFrame); -@@ -148,7 +239,7 @@ NS_IMETHODIMP imgContainer::GetNumFrames(PRUint32 *aNumFrames) - if (!aNumFrames) - return NS_ERROR_INVALID_ARG; - -- *aNumFrames = mFrames.Count(); -+ *aNumFrames = mNumFrames; - - return NS_OK; - } -@@ -157,16 +248,24 @@ NS_IMETHODIMP imgContainer::GetNumFrames(PRUint32 *aNumFrames) - /* gfxIImageFrame getFrameAt (in unsigned long index); */ - NS_IMETHODIMP imgContainer::GetFrameAt(PRUint32 index, gfxIImageFrame **_retval) - { -+ nsresult result; -+ - NS_ASSERTION(_retval, "imgContainer::GetFrameAt; Invalid Arg"); - if (!_retval) - return NS_ERROR_INVALID_POINTER; - -- if (!mFrames.Count()) { -+ if (mNumFrames == 0) { - *_retval = nsnull; - return NS_OK; - } - -- NS_ENSURE_ARG(index < static_cast<PRUint32>(mFrames.Count())); -+ NS_ENSURE_ARG((int) index < mNumFrames); -+ -+ result = RestoreDiscardedData (); -+ if (NS_FAILED (result)) { -+ *_retval = nsnull; -+ return result; -+ } - - if (!(*_retval = mFrames[index])) - return NS_ERROR_FAILURE; -@@ -183,16 +282,17 @@ NS_IMETHODIMP imgContainer::AppendFrame(gfxIImageFrame *item) - NS_ASSERTION(item, "imgContainer::AppendFrame; Invalid Arg"); - if (!item) - return NS_ERROR_INVALID_ARG; -- -- PRInt32 numFrames = mFrames.Count(); -- -- if (numFrames == 0) { -+ -+ if (mFrames.Count () == 0) { - // This may not be an animated image, don't do all the animation stuff. - mFrames.AppendObject(item); -+ -+ mNumFrames++; -+ - return NS_OK; - } - -- if (numFrames == 1) { -+ if (mFrames.Count () == 1) { - // Now that we got a second frame, initialize animation stuff. - if (!ensureAnimExists()) - return NS_ERROR_OUT_OF_MEMORY; -@@ -216,11 +316,13 @@ NS_IMETHODIMP imgContainer::AppendFrame(gfxIImageFrame *item) - itemRect); - - mFrames.AppendObject(item); -+ -+ mNumFrames++; - - // If this is our second frame, start the animation. - // Must be called after AppendObject because StartAnimation checks for > 1 - // frame -- if (numFrames == 1) -+ if (mFrames.Count () == 1) - StartAnimation(); - - return NS_OK; -@@ -230,6 +332,7 @@ NS_IMETHODIMP imgContainer::AppendFrame(gfxIImageFrame *item) - /* void removeFrame (in gfxIImageFrame item); */ - NS_IMETHODIMP imgContainer::RemoveFrame(gfxIImageFrame *item) - { -+ /* Remember to decrement mNumFrames if you implement this */ - return NS_ERROR_NOT_IMPLEMENTED; - } - -@@ -253,7 +356,7 @@ NS_IMETHODIMP imgContainer::DecodingComplete(void) - mAnim->doneDecoding = PR_TRUE; - // If there's only 1 frame, optimize it. - // Optimizing animated images is not supported -- if (mFrames.Count() == 1) -+ if (mNumFrames == 1) - mFrames[0]->SetMutable(PR_FALSE); - return NS_OK; - } -@@ -292,11 +395,11 @@ NS_IMETHODIMP imgContainer::SetAnimationMode(PRUint16 aAnimationMode) - break; - case kNormalAnimMode: - if (mLoopCount != 0 || -- (mAnim && (mAnim->currentAnimationFrameIndex + 1 < mFrames.Count()))) -+ (mAnim && (mAnim->currentAnimationFrameIndex + 1 < mNumFrames))) - StartAnimation(); - break; - case kLoopOnceAnimMode: -- if (mAnim && (mAnim->currentAnimationFrameIndex + 1 < mFrames.Count())) -+ if (mAnim && (mAnim->currentAnimationFrameIndex + 1 < mNumFrames)) - StartAnimation(); - break; - } -@@ -312,12 +415,18 @@ NS_IMETHODIMP imgContainer::StartAnimation() - (mAnim && (mAnim->timer || mAnim->animating))) - return NS_OK; - -- if (mFrames.Count() > 1) { -+ if (mNumFrames > 1) { - if (!ensureAnimExists()) - return NS_ERROR_OUT_OF_MEMORY; - - PRInt32 timeout; -- gfxIImageFrame *currentFrame = inlinedGetCurrentFrame(); -+ nsresult result; -+ gfxIImageFrame *currentFrame; -+ -+ result = GetCurrentFrameNoRef (¤tFrame); -+ if (NS_FAILED (result)) -+ return result; -+ - if (currentFrame) { - currentFrame->GetTimeout(&timeout); - if (timeout <= 0) // -1 means display this frame forever -@@ -376,8 +485,15 @@ NS_IMETHODIMP imgContainer::ResetAnimation() - mAnim->currentAnimationFrameIndex = 0; - // Update display - nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver)); -- if (observer) -+ if (observer) { -+ nsresult result; -+ -+ result = RestoreDiscardedData (); -+ if (NS_FAILED (result)) -+ return result; -+ - observer->FrameChanged(this, mFrames[0], &(mAnim->firstFrameRefreshArea)); -+ } - - if (oldAnimating) - return StartAnimation(); -@@ -411,10 +527,161 @@ NS_IMETHODIMP imgContainer::SetLoopCount(PRInt32 aLoopCount) - return NS_OK; - } - -+static PRBool -+discarding_is_enabled (void) -+{ -+ static PRBool inited; -+ static PRBool enabled; -+ -+ if (!inited) { -+ inited = PR_TRUE; -+ -+ enabled = (getenv ("MOZ_DISABLE_IMAGE_DISCARD") == nsnull); -+ } -+ -+ return enabled; -+} -+ -+//****************************************************************************** -+/* void setDiscardable(in string mime_type); */ -+NS_IMETHODIMP imgContainer::SetDiscardable (const char* aMimeType) -+{ -+ NS_ASSERTION(aMimeType, "imgContainer::SetDiscardable() called with null aMimeType"); -+ -+ if (!discarding_is_enabled ()) -+ return NS_OK; -+ -+ if (mDiscardable) { -+ NS_WARNING ("imgContainer::SetDiscardable(): cannot change an imgContainer which is already discardable"); -+ return NS_ERROR_FAILURE; -+ } -+ -+ mDiscardableMimeType = strdup (aMimeType); -+ if (!mDiscardableMimeType) -+ return NS_ERROR_OUT_OF_MEMORY; -+ -+ mDiscardable = PR_TRUE; -+ -+ num_containers_with_discardable_data++; -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: Making imgContainer %p (%s) discardable. " -+ "Compressed containers: %d, Compressed data bytes: %lld", -+ this, -+ aMimeType, -+ num_containers_with_discardable_data, -+ num_compressed_image_bytes)); -+ -+ return NS_OK; -+} -+ -+//****************************************************************************** -+/* void addRestoreData(in nsIInputStream aInputStream, in unsigned long aCount); */ -+NS_IMETHODIMP imgContainer::AddRestoreData (char *aBuffer, PRUint32 aCount) -+{ -+ PRSize new_size; -+ char *new_buffer; -+ -+ NS_ASSERTION(aBuffer, "imgContainer::AddRestoreData() called with null aBuffer"); -+ -+ if (!discarding_is_enabled ()) -+ return NS_OK; -+ -+ if (!mDiscardable) { -+ NS_WARNING ("imgContainer::AddRestoreData() can only be called if SetDiscardable is called first"); -+ return NS_ERROR_FAILURE; -+ } -+ -+ if (mRestoreDataDone) { -+ /* We are being called from the decoder while the data is being restored -+ * (i.e. we were fully loaded once, then we discarded the image data, then -+ * we are being restored). We don't want to save the compressed data again, -+ * since we already have it. -+ */ -+ return NS_OK; -+ } -+ -+ new_size = mRestoreDataLength + aCount; -+ -+ new_buffer = (char *) PR_Realloc (mRestoreData, new_size); -+ if (new_buffer) -+ mRestoreData = new_buffer; -+ else { -+ /* Hmm, should we discard the whole buffer? The caller isn't going to be able to recover... */ -+ return NS_ERROR_OUT_OF_MEMORY; -+ } -+ -+ memcpy (mRestoreData + mRestoreDataLength, aBuffer, aCount); -+ mRestoreDataLength = new_size; -+ -+ num_compressed_image_bytes += aCount; -+ -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: Added compressed data to imgContainer %p (%s). " -+ "Compressed containers: %d, Compressed data bytes: %lld", -+ this, -+ mDiscardableMimeType, -+ num_containers_with_discardable_data, -+ num_compressed_image_bytes)); -+ -+ return NS_OK; -+} -+ -+/* Note! buf must be declared as char buf[9]; */ -+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; -+} -+ -+//****************************************************************************** -+/* void restoreDataDone(); */ -+NS_IMETHODIMP imgContainer::RestoreDataDone (void) -+{ -+ char buf[9]; -+ -+ if (!discarding_is_enabled ()) -+ return NS_OK; -+ -+ if (mRestoreDataDone) -+ return NS_OK; -+ -+ mRestoreDataDone = PR_TRUE; -+ -+ get_header_str (buf, mRestoreData, mRestoreDataLength); -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: imgContainer::RestoreDataDone() - data is done for container %p (%s), %d real frames (cached as %d frames) - header %p is 0x%s (length %d)", -+ this, -+ mDiscardableMimeType, -+ mFrames.Count (), -+ mNumFrames, -+ mRestoreData, -+ buf, -+ (int) mRestoreDataLength)); -+ -+ return ResetDiscardTimer (); -+} -+ - //****************************************************************************** - /* void notify(in nsITimer timer); */ - NS_IMETHODIMP imgContainer::Notify(nsITimer *timer) - { -+ nsresult result; -+ -+ result = RestoreDiscardedData (); -+ if (NS_FAILED (result)) -+ return result; -+ - // This should never happen since the timer is only set up in StartAnimation() - // after mAnim is checked to exist. - NS_ASSERTION(mAnim, "imgContainer::Notify() called but mAnim is null"); -@@ -433,8 +700,7 @@ NS_IMETHODIMP imgContainer::Notify(nsITimer *timer) - return NS_OK; - } - -- PRInt32 numFrames = mFrames.Count(); -- if (!numFrames) -+ if (mNumFrames == 0) - return NS_OK; - - gfxIImageFrame *nextFrame = nsnull; -@@ -448,7 +714,7 @@ NS_IMETHODIMP imgContainer::Notify(nsITimer *timer) - // finished decoding (see EndFrameDecode) - if (mAnim->doneDecoding || - (nextFrameIndex < mAnim->currentDecodingFrameIndex)) { -- if (numFrames == nextFrameIndex) { -+ if (mNumFrames == nextFrameIndex) { - // End of Animation - - // If animation mode is "loop once", it's time to stop animating -@@ -875,3 +1141,328 @@ NS_IMETHODIMP imgContainer::GetKeys(PRUint32 *count, char ***keys) - } - return mProperties->GetKeys(count, keys); - } -+ -+static int -+get_discard_timer_ms (void) -+{ -+ /* FIXME: don't hardcode this */ -+ return 5000; /* 5 seconds */ -+} -+ -+void -+imgContainer::sDiscardTimerCallback (nsITimer *aTimer, void *aClosure) -+{ -+ imgContainer *self = (imgContainer *) aClosure; -+ int old_frame_count; -+ -+ NS_ASSERTION (aTimer == self->mDiscardTimer, -+ "imgContainer::DiscardTimerCallback() got a callback for an unknown timer"); -+ -+ self->mDiscardTimer = nsnull; -+ -+ old_frame_count = self->mFrames.Count (); -+ -+ if (self->mAnim) { -+ delete self->mAnim; -+ self->mAnim = nsnull; -+ } -+ -+ self->mFrames.Clear (); -+ -+ self->mDiscarded = PR_TRUE; -+ -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: discarded uncompressed image data from imgContainer %p (%s) - %d frames (cached count: %d); " -+ "Compressed containers: %d, Compressed data bytes: %lld", -+ self, -+ self->mDiscardableMimeType, -+ old_frame_count, -+ self->mNumFrames, -+ num_containers_with_discardable_data, -+ num_compressed_image_bytes)); -+} -+ -+nsresult -+imgContainer::ResetDiscardTimer (void) -+{ -+ if (!discarding_is_enabled ()) -+ return NS_OK; -+ -+ if (!mDiscardTimer) { -+ mDiscardTimer = do_CreateInstance("@mozilla.org/timer;1"); -+ -+ if (!mDiscardTimer) -+ return NS_ERROR_OUT_OF_MEMORY; -+ } else { -+ if (NS_FAILED (mDiscardTimer->Cancel ())) -+ return NS_ERROR_FAILURE; -+ } -+ -+ return mDiscardTimer->InitWithFuncCallback (sDiscardTimerCallback, -+ (void *) this, -+ get_discard_timer_ms (), -+ nsITimer::TYPE_ONE_SHOT); -+} -+ -+nsresult -+imgContainer::RestoreDiscardedData (void) -+{ -+ nsresult result; -+ int num_expected_frames; -+ -+ if (!mDiscarded) -+ return NS_OK; -+ -+ result = ResetDiscardTimer (); -+ if (NS_FAILED (result)) -+ return result; -+ -+ num_expected_frames = mNumFrames; -+ -+ result = ReloadImages (); -+ if (NS_FAILED (result)) { -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: imgContainer::RestoreDiscardedData() for container %p failed to ReloadImages()", -+ this)); -+ return result; -+ } -+ -+ mDiscarded = PR_FALSE; -+ -+ NS_ASSERTION (mNumFrames == mFrames.Count (), -+ "number of restored image frames doesn't match"); -+ NS_ASSERTION (num_expected_frames == mNumFrames, -+ "number of restored image frames doesn't match the original number of frames!"); -+ -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG, -+ ("CompressedImageAccounting: imgContainer::RestoreDiscardedData() restored discarded data " -+ "for imgContainer %p (%s) - %d image frames. " -+ "Compressed containers: %d, Compressed data bytes: %lld", -+ this, -+ mDiscardableMimeType, -+ mNumFrames, -+ num_containers_with_discardable_data, -+ num_compressed_image_bytes)); -+ -+ return NS_OK; -+} -+ -+class ContainerLoader : public imgILoad, -+ public imgIDecoderObserver, -+ public nsSupportsWeakReference -+{ -+public: -+ -+ NS_DECL_ISUPPORTS -+ NS_DECL_IMGILOAD -+ NS_DECL_IMGIDECODEROBSERVER -+ NS_DECL_IMGICONTAINEROBSERVER -+ -+ ContainerLoader (void); -+ -+private: -+ -+ imgIContainer *mContainer; -+}; -+ -+NS_IMPL_ISUPPORTS4 (ContainerLoader, imgILoad, imgIDecoderObserver, imgIContainerObserver, nsISupportsWeakReference) -+ -+ContainerLoader::ContainerLoader (void) -+{ -+} -+ -+/* Implement imgILoad::image getter */ -+NS_IMETHODIMP -+ContainerLoader::GetImage(imgIContainer **aImage) -+{ -+ *aImage = mContainer; -+ NS_IF_ADDREF (*aImage); -+ return NS_OK; -+} -+ -+/* Implement imgILoad::image setter */ -+NS_IMETHODIMP -+ContainerLoader::SetImage(imgIContainer *aImage) -+{ -+ mContainer = aImage; -+ return NS_OK; -+} -+ -+/* Implement imgILoad::isMultiPartChannel getter */ -+NS_IMETHODIMP -+ContainerLoader::GetIsMultiPartChannel(PRBool *aIsMultiPartChannel) -+{ -+ *aIsMultiPartChannel = PR_FALSE; /* FIXME: is this always right? */ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onStartRequest() */ -+NS_IMETHODIMP -+ContainerLoader::OnStartRequest (imgIRequest *aRequest) -+{ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onStartDecode() */ -+NS_IMETHODIMP -+ContainerLoader::OnStartDecode (imgIRequest *aRequest) -+{ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onStartContainer() */ -+NS_IMETHODIMP -+ContainerLoader::OnStartContainer (imgIRequest *aRequest, imgIContainer *aContainer) -+{ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onStartFrame() */ -+NS_IMETHODIMP -+ContainerLoader::OnStartFrame (imgIRequest *aRequest, gfxIImageFrame *aFrame) -+{ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onDataAvailable() */ -+NS_IMETHODIMP -+ContainerLoader::OnDataAvailable (imgIRequest *aRequest, gfxIImageFrame *aFrame, const nsIntRect * aRect) -+{ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onStopFrame() */ -+NS_IMETHODIMP -+ContainerLoader::OnStopFrame (imgIRequest *aRequest, gfxIImageFrame *aFrame) -+{ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onStopContainer() */ -+NS_IMETHODIMP -+ContainerLoader::OnStopContainer (imgIRequest *aRequest, imgIContainer *aContainer) -+{ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onStopDecode() */ -+NS_IMETHODIMP -+ContainerLoader::OnStopDecode (imgIRequest *aRequest, nsresult status, const PRUnichar *statusArg) -+{ -+ return NS_OK; -+} -+ -+/* Implement imgIDecoderObserver::onStopRequest() */ -+NS_IMETHODIMP -+ContainerLoader::OnStopRequest (imgIRequest *aRequest, PRBool aIsLastPart) -+{ -+ return NS_OK; -+} -+ -+/* implement imgIContainerObserver::frameChanged() */ -+NS_IMETHODIMP -+ContainerLoader::FrameChanged (imgIContainer *aContainer, gfxIImageFrame *aFrame, nsIntRect * aDirtyRect) -+{ -+ return NS_OK; -+} -+ -+static char * -+make_id_from_mime_type (char *mime_type) -+{ -+ const char idbase[] = "@mozilla.org/image/decoder;2?type="; -+ int idbase_len = strlen (idbase); -+ char *id; -+ -+ id = (char *) PR_Malloc (strlen (mime_type) + idbase_len + 1); -+ if (!id) -+ return nsnull; -+ -+ strcpy (id, idbase); -+ strcpy (id + idbase_len, mime_type); -+ -+ return id; -+} -+ -+nsresult -+imgContainer::ReloadImages (void) -+{ -+ char *id; -+ nsCOMPtr<imgILoad> loader; -+ nsCOMPtr<imgIDecoder> decoder; -+ nsresult result; -+ PRUint32 written; -+ nsCOMPtr<nsIInputStream> stream; -+ char buf[9]; -+ -+ NS_ASSERTION (mRestoreData, -+ "imgContainer::ReloadImages(): mRestoreData should not be null"); -+ NS_ASSERTION (mRestoreDataDone, -+ "imgContainer::ReloadImages(): mRestoreDataDone shoudl be true!"); -+ -+ id = make_id_from_mime_type (mDiscardableMimeType); -+ if (!id) -+ return NS_ERROR_OUT_OF_MEMORY; -+ -+ mNumFrames = 0; -+ NS_ASSERTION (mFrames.Count() == 0, -+ "imgContainer::ReloadImages(): mFrames should be empty"); -+ -+ decoder = do_CreateInstance (id); -+ PR_Free (id); -+ -+ if (!decoder) { -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_WARNING, -+ ("CompressedImageAccounting: imgContainer::ReloadImages() could not create decoder for %s", -+ mDiscardableMimeType)); -+ return NS_IMAGELIB_ERROR_NO_DECODER; -+ } -+ -+ loader = new ContainerLoader (); -+ if (!loader) { -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_WARNING, -+ ("CompressedImageAccounting: imgContainer::ReloadImages() could not allocate ContainerLoader " -+ "when reloading the images for container %p", -+ this)); -+ return NS_ERROR_OUT_OF_MEMORY; -+ } -+ -+ loader->SetImage (this); -+ -+ result = decoder->Init (loader); -+ if (NS_FAILED (result)) { -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_WARNING, -+ ("CompressedImageAccounting: imgContainer::ReloadImages() image container %p " -+ "failed to initialize the decoder (%s)", -+ this, -+ mDiscardableMimeType)); -+ return result; -+ } -+ -+ result = NS_NewByteInputStream (getter_AddRefs (stream), mRestoreData, mRestoreDataLength, NS_ASSIGNMENT_DEPEND); -+ NS_ENSURE_SUCCESS (result, result); -+ -+ get_header_str (buf, mRestoreData, mRestoreDataLength); -+ PR_LOG (gCompressedImageAccountingLog, PR_LOG_WARNING, -+ ("CompressedImageAccounting: imgContainer::ReloadImages() starting to restore images for container %p (%s) - " -+ "header %p is 0x%s (length %d)", -+ this, -+ mDiscardableMimeType, -+ mRestoreData, -+ buf, -+ (int) mRestoreDataLength)); -+ -+ result = decoder->WriteFrom (stream, mRestoreDataLength, &written); -+ NS_ENSURE_SUCCESS (result, result); -+ -+ result = decoder->Flush (); -+ if (!(result == NS_OK || result == NS_ERROR_NOT_IMPLEMENTED)) /* PNG doesn't implement Flush(), for example */ -+ return result; -+ -+ result = decoder->Close (); -+ NS_ENSURE_SUCCESS (result, result); -+ -+ NS_ASSERTION (mFrames.Count() == mNumFrames, -+ "imgContainer::ReloadImages(): the restored mFrames.Count() doesn't match mNumFrames!"); -+ -+ return result; -+} -diff --git modules/libpr0n/src/imgContainer.h modules/libpr0n/src/imgContainer.h -index 3db7034..aa56939 100644 ---- modules/libpr0n/src/imgContainer.h -+++ modules/libpr0n/src/imgContainer.h -@@ -23,6 +23,7 @@ - * Contributor(s): - * Stuart Parmenter <pavlov@netscape.com> - * Chris Saari <saari@netscape.com> -+ * Federico Mena-Quintero <federico@novell.com> - * - * 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 -@@ -194,14 +195,8 @@ private: - timer->Cancel(); - } - }; -- -- inline gfxIImageFrame* inlinedGetCurrentFrame() { -- if (!mAnim) -- return mFrames.SafeObjectAt(0); -- if (mAnim->lastCompositedFrameIndex == mAnim->currentAnimationFrameIndex) -- return mAnim->compositingFrame; -- return mFrames.SafeObjectAt(mAnim->currentAnimationFrameIndex); -- } -+ -+ nsresult GetCurrentFrameNoRef(gfxIImageFrame** aFrame); - - inline Anim* ensureAnimExists() { - if (!mAnim) -@@ -274,10 +269,15 @@ private: - nsIntSize mSize; - - //! All the <gfxIImageFrame>s of the PNG -+ // *** IMPORTANT: if you use mFrames in a method, call RestoreDiscardedData() first to ensure -+ // that the frames actually exist (they may have been discarded to save memory). - nsCOMArray<gfxIImageFrame> mFrames; -+ int mNumFrames; /* stored separately from mFrames.Count() to support discarded images */ - - nsCOMPtr<nsIProperties> mProperties; -- -+ -+ // *** IMPORTANT: if you use mAnim in a method, call RestoreDiscardedData() first to ensure -+ // that the frames actually exist (they may have been discarded to save memory). - imgContainer::Anim* mAnim; - - //! See imgIContainer for mode constants -@@ -288,6 +288,19 @@ private: - - //! imgIContainerObserver - nsWeakPtr mObserver; -+ -+ PRBool mDiscardable; -+ PRBool mDiscarded; -+ char* mDiscardableMimeType; -+ char* mRestoreData; -+ PRSize mRestoreDataLength; -+ PRBool mRestoreDataDone; -+ nsCOMPtr<nsITimer> mDiscardTimer; -+ -+ nsresult ResetDiscardTimer (void); -+ nsresult RestoreDiscardedData (void); -+ nsresult ReloadImages (void); -+ static void sDiscardTimerCallback (nsITimer *aTimer, void *aClosure); - }; - - #endif /* __imgContainer_h__ */ ---- modules/libpr0n/decoders/png/nsPNGDecoder.cpp.orig 2007-09-10 16:01:18.000000000 -0400 -+++ modules/libpr0n/decoders/png/nsPNGDecoder.cpp 2007-09-26 13:39:26.000000000 -0400 -@@ -23,6 +23,7 @@ - * Contributor(s): - * Stuart Parmenter <stuart@mozilla.com> - * Andrew Smith -+ * Federico Mena-Quintero <federico@novell.com> - * - * 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 -@@ -73,6 +74,7 @@ - - #ifdef PR_LOGGING - PRLogModuleInfo *gPNGLog = PR_NewLogModule("PNGDecoder"); -+static PRLogModuleInfo *gPNGDecoderAccountingLog = PR_NewLogModule ("PNGDecoderAccounting"); - #endif - - NS_IMPL_ISUPPORTS1(nsPNGDecoder, imgIDecoder) -@@ -119,6 +121,12 @@ - - if (mObserver) - mObserver->OnStartFrame(nsnull, mFrame); -+ -+ PR_LOG (gPNGDecoderAccountingLog, PR_LOG_DEBUG, -+ ("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created image frame with %dx%d pixels in container %p", -+ width, height, -+ mImage.get ())); -+ - - mFrameHasNoAlpha = PR_TRUE; - } -@@ -215,9 +223,25 @@ - /* void close (); */ - NS_IMETHODIMP nsPNGDecoder::Close() - { -+ nsresult result; -+ - if (mPNG) - png_destroy_read_struct(&mPNG, mInfo ? &mInfo : NULL, NULL); - -+ result = mImage->RestoreDataDone (); -+ if (NS_FAILED (result)) { -+ PR_LOG (gPNGDecoderAccountingLog, PR_LOG_DEBUG, -+ ("PNGDecoderAccounting: nsPNGDecoder::Close(): failure in RestoreDataDone() for image container %p", -+ mImage.get ())); -+ -+ mError = PR_TRUE; -+ return result; -+ } -+ -+ PR_LOG (gPNGDecoderAccountingLog, PR_LOG_DEBUG, -+ ("PNGDecoderAccounting: nsPNGDecoder::Close(): image container %p is now with RestoreDataDone", -+ mImage.get ())); -+ - return NS_OK; - } - -@@ -236,6 +260,7 @@ - PRUint32 *writeCount) - { - nsPNGDecoder *decoder = static_cast<nsPNGDecoder*>(closure); -+ nsresult result; - - if (decoder->mError) { - *writeCount = 0; -@@ -250,10 +275,24 @@ - *writeCount = 0; - return NS_ERROR_FAILURE; - } -- - png_process_data(decoder->mPNG, decoder->mInfo, - reinterpret_cast<unsigned char *>(const_cast<char *>(fromRawSegment)), count); - -+ result = decoder->mImage->AddRestoreData ((char *) fromRawSegment, count); -+ if (NS_FAILED (result)) { -+ PR_LOG (gPNGDecoderAccountingLog, PR_LOG_DEBUG, -+ ("PNGDecoderAccounting: ReadDataOut(): failed to add restore data to image container %p", -+ decoder->mImage.get ())); -+ -+ decoder->mError = PR_TRUE; -+ *writeCount = 0; -+ return result; -+ } -+ -+ PR_LOG (gPNGDecoderAccountingLog, PR_LOG_DEBUG, -+ ("PNGDecoderAccounting: ReadDataOut(): Added restore data to image container %p", -+ decoder->mImage.get ())); -+ - *writeCount = count; - return NS_OK; - } -@@ -527,13 +566,41 @@ - if (decoder->mObserver) - decoder->mObserver->OnStartDecode(nsnull); - -- decoder->mImage = do_CreateInstance("@mozilla.org/image/container;1"); -- if (!decoder->mImage) -- longjmp(decoder->mPNG->jmpbuf, 5); // NS_ERROR_OUT_OF_MEMORY -+ /* The image container may already exist if it is reloading itself from us. -+ * Check that it has the same width/height; otherwise create a new container. -+ */ -+ decoder->mImageLoad->GetImage (getter_AddRefs (decoder->mImage)); -+ if (decoder->mImage) { -+ PRInt32 container_width, container_height; - -- decoder->mImageLoad->SetImage(decoder->mImage); -+ decoder->mImage->GetWidth (&container_width); -+ decoder->mImage->GetHeight (&container_height); - -- decoder->mImage->Init(width, height, decoder->mObserver); -+ if (container_width != width || container_height != height) -+ decoder->mImage = nsnull; -+ } -+ -+ if (!decoder->mImage) { -+ decoder->mImage = do_CreateInstance("@mozilla.org/image/container;1"); -+ if (!decoder->mImage) -+ longjmp(decoder->mPNG->jmpbuf, 5); // NS_ERROR_OUT_OF_MEMORY -+ -+ decoder->mImageLoad->SetImage(decoder->mImage); -+ -+ decoder->mImage->Init(width, height, decoder->mObserver); -+ -+ /* FIXME: is this MIME type always right for this decoder? */ -+ if (NS_FAILED (decoder->mImage->SetDiscardable ("image/png"))) { -+ PR_LOG (gPNGDecoderAccountingLog, PR_LOG_DEBUG, -+ ("PNGDecoderAccounting: info_callback(): failed to set image container %p as discardable", -+ decoder->mImage.get ())); -+ longjmp(decoder->mPNG->jmpbuf, 5); // NS_ERROR_OUT_OF_MEMORY -+ } -+ -+ PR_LOG (gPNGDecoderAccountingLog, PR_LOG_DEBUG, -+ ("PNGDecoderAccounting: info_callback(): set image container %p as discardable", -+ decoder->mImage.get ())); -+ } - - if (decoder->mObserver) - decoder->mObserver->OnStartContainer(nsnull, decoder->mImage); -@@ -775,7 +842,7 @@ - } - - decoder->mImage->DecodingComplete(); -- -+ - if (decoder->mObserver) { - if (!(decoder->apngFlags & FRAME_HIDDEN)) - decoder->mObserver->OnStopFrame(nsnull, decoder->mFrame); |