# Patch to be able to compile Mozilla using the system libpng libraries, even
# when they lack support for the APNG format, by Miriam Ruiz

# Adapted from original code made by Mike Hommey and the Maintainers of the
# Mozilla-related packages in Debian

--- src.orig/configure.in
+++ src/configure.in
@@ -4396,6 +4396,7 @@
     CFLAGS="-I${PNG_DIR}/include $CFLAGS"
     LDFLAGS="-L${PNG_DIR}/lib $LDFLAGS"
 fi
+APNG=1
 if test -z "$PNG_DIR" -o "$PNG_DIR" = no; then
     SYSTEM_PNG=
 else
@@ -4404,10 +4405,11 @@
                  AC_MSG_ERROR([--with-system-png requested but no working libpng found]), 
                  $PNG_LIBS)
     AC_CHECK_LIB(png, png_get_acTL, ,
-                 AC_MSG_ERROR([--with-system-png won't work because the system's libpng doesn't have APNG support]),
+                 AC_MSG_WARN([system's libpng doesn't have APNG support])
+		 APNG=,
                  $_SAVE_PNG_LIBS)
 fi
-if test "$SYSTEM_PNG" = 1; then
+if test "$SYSTEM_PNG" = 0; then
     LIBS="$PNG_LIBS $LIBS"
     AC_TRY_COMPILE([ #include <stdio.h>
                      #include <sys/types.h>
@@ -8079,6 +8081,7 @@
 AC_SUBST(SYSTEM_LIBXUL)
 AC_SUBST(SYSTEM_JPEG)
 AC_SUBST(SYSTEM_PNG)
+AC_SUBST(APNG)
 AC_SUBST(SYSTEM_ZLIB)
 AC_SUBST(SYSTEM_BZ2)
 
--- src.orig/config/autoconf.mk.in
+++ src/config/autoconf.mk.in
@@ -229,6 +229,7 @@
 MOZ_NATIVE_BZ2	= @SYSTEM_BZ2@
 MOZ_NATIVE_JPEG	= @SYSTEM_JPEG@
 MOZ_NATIVE_PNG	= @SYSTEM_PNG@
+APNG		= @APNG@
 MOZ_TREE_CAIRO = @MOZ_TREE_CAIRO@
 
 MOZ_UPDATE_XTERM = @MOZ_UPDATE_XTERM@
--- src.orig/modules/libpr0n/decoders/png/nsPNGDecoder.cpp
+++ src/modules/libpr0n/decoders/png/nsPNGDecoder.cpp
@@ -61,7 +61,9 @@
 static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr);
 static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row,
                            png_uint_32 row_num, int pass);
+#ifdef APNG
 static void PNGAPI frame_info_callback(png_structp png_ptr, png_uint_32 frame_num);
+#endif
 static void PNGAPI end_callback(png_structp png_ptr, png_infop info_ptr);
 static void PNGAPI error_callback(png_structp png_ptr, png_const_charp error_msg);
 static void PNGAPI warning_callback(png_structp png_ptr, png_const_charp warning_msg);
@@ -77,7 +79,10 @@
   mPNG(nsnull), mInfo(nsnull),
   mCMSLine(nsnull), interlacebuf(nsnull),
   mInProfile(nsnull), mTransform(nsnull),
-  mChannels(0), mError(PR_FALSE), mFrameIsHidden(PR_FALSE)
+  mChannels(0), mError(PR_FALSE)
+#ifdef APNG
+  , mFrameIsHidden(PR_FALSE)
+#endif
 {
 }
 
@@ -112,8 +117,10 @@
   mFrameRect.width = width;
   mFrameRect.height = height;
 
+#ifdef APNG
   if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL))
     SetAnimFrameInfo();
+#endif
 
   PRUint32 numFrames = 0;
   mImage->GetNumFrames(&numFrames);
@@ -129,6 +136,7 @@
   mFrameHasNoAlpha = PR_TRUE;
 }
 
+#ifdef APNG
 // set timeout and frame disposal method for the current frame
 void nsPNGDecoder::SetAnimFrameInfo()
 {
@@ -172,6 +180,7 @@
   /*else // 'over' is the default
       mImage->SetFrameBlendMethod(numFrames - 1, imgIContainer::kBlendOver); */
 }
+#endif
 
 // set timeout and frame disposal method for the current frame
 void nsPNGDecoder::EndImageFrame()
@@ -640,12 +649,15 @@
   else if (channels == 2 || channels == 4)
     decoder->format = gfxASurface::ImageFormatARGB32;
 
+#ifdef APNG
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL))
     png_set_progressive_frame_fn(png_ptr, frame_info_callback, NULL);
   
   if (png_get_first_frame_is_hidden(png_ptr, info_ptr)) {
     decoder->mFrameIsHidden = PR_TRUE;
-  } else {
+  } else
+#endif
+  {
     decoder->CreateFrame(0, 0, width, height, decoder->format);
   }
   
@@ -709,9 +721,11 @@
    */
   nsPNGDecoder *decoder = static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
   
+#ifdef APNG
   // skip this frame
   if (decoder->mFrameIsHidden)
     return;
+#endif
 
   if (new_row) {
     PRInt32 width = decoder->mFrameRect.width;
@@ -805,6 +819,7 @@
   }
 }
 
+#ifdef APNG
 // got the header of a new frame that's coming
 void
 frame_info_callback(png_structp png_ptr, png_uint_32 frame_num)
@@ -814,11 +829,15 @@
   
   nsPNGDecoder *decoder = static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
   
+#ifdef APNG
   // old frame is done
   if (!decoder->mFrameIsHidden)
+#endif
     decoder->EndImageFrame();
   
+#ifdef APNG
   decoder->mFrameIsHidden = PR_FALSE;
+#endif
   
   x_offset = png_get_next_frame_x_offset(png_ptr, decoder->mInfo);
   y_offset = png_get_next_frame_y_offset(png_ptr, decoder->mInfo);
@@ -827,6 +846,7 @@
   
   decoder->CreateFrame(x_offset, y_offset, width, height, decoder->format);
 }
+#endif
 
 void
 end_callback(png_structp png_ptr, png_infop info_ptr)
@@ -845,12 +865,14 @@
 
   nsPNGDecoder *decoder = static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));
   
+#ifdef APNG
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) {
     PRInt32 num_plays = png_get_num_plays(png_ptr, info_ptr);
     decoder->mImage->SetLoopCount(num_plays - 1);
   }
   
   if (!decoder->mFrameIsHidden)
+#endif
     decoder->EndImageFrame();
   
   decoder->mImage->DecodingComplete();
--- src.orig/modules/libpr0n/decoders/png/nsPNGDecoder.h
+++ src/modules/libpr0n/decoders/png/nsPNGDecoder.h
@@ -73,7 +73,9 @@
   void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset, 
                    PRInt32 width, PRInt32 height, 
                    gfxASurface::gfxImageFormat format);
+#ifdef APNG
   void SetAnimFrameInfo();
+#endif
   
   void EndImageFrame();
 
@@ -95,7 +97,9 @@
   PRUint8 mChannels;
   PRPackedBool mError;
   PRPackedBool mFrameHasNoAlpha;
+#ifdef APNG
   PRPackedBool mFrameIsHidden;
+#endif
 };
 
 #endif // nsPNGDecoder_h__
--- src.orig/modules/libpr0n/encoders/png/nsPNGEncoder.cpp
+++ src/modules/libpr0n/encoders/png/nsPNGEncoder.cpp
@@ -51,7 +51,9 @@
 NS_IMPL_THREADSAFE_ISUPPORTS2(nsPNGEncoder, imgIEncoder, nsIInputStream)
 
 nsPNGEncoder::nsPNGEncoder() : mPNG(nsnull), mPNGinfo(nsnull),
+#ifdef APNG
                                mIsAnimation(PR_FALSE),
+#endif
                                mImageBuffer(nsnull), mImageBufferSize(0),
                                mImageBufferUsed(0), mImageBufferReadPoint(0)
 {
@@ -109,9 +111,12 @@
                                              PRUint32 aInputFormat,
                                              const nsAString& aOutputOptions)
 {
-  PRBool useTransparency = PR_TRUE, skipFirstFrame = PR_FALSE;
+  PRBool useTransparency = PR_TRUE;
+#ifdef APNG
+  PRBool skipFirstFrame = PR_FALSE;
   PRUint32 numFrames = 1;
   PRUint32 numPlays = 0; // For animations, 0 == forever
+#endif
 
   // can't initialize more than once
   if (mImageBuffer != nsnull)
@@ -124,14 +129,19 @@
     return NS_ERROR_INVALID_ARG;
 
   // parse and check any provided output options
-  nsresult rv = ParseOptions(aOutputOptions, &useTransparency, &skipFirstFrame,
-                             &numFrames, &numPlays, nsnull, nsnull,
-                             nsnull, nsnull, nsnull);
+  nsresult rv = ParseOptions(aOutputOptions, &useTransparency,
+#ifdef APNG
+                             &skipFirstFrame, &numFrames, &numPlays,
+			     nsnull, nsnull, nsnull,
+#endif
+			     nsnull, nsnull);
   if (rv != NS_OK) { return rv; }
 
+#ifdef APNG
   if (numFrames > 1) {
     mIsAnimation = PR_TRUE;
   }
+#endif
 
   // initialize
   mPNG = png_create_write_struct(PNG_LIBPNG_VER_STRING,
@@ -181,10 +191,12 @@
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
                PNG_FILTER_TYPE_DEFAULT);
 
+#ifdef APNG
   if (mIsAnimation) {
     png_set_first_frame_is_hidden(mPNG, mPNGinfo, skipFirstFrame);
     png_set_acTL(mPNG, mPNGinfo, numFrames, numPlays);
   }
+#endif
 
   // XXX: support PLTE, gAMA, tRNS, bKGD?
 
@@ -203,9 +215,11 @@
                                           const nsAString& aFrameOptions)
 {
   PRBool useTransparency= PR_TRUE;
+#ifdef APNG
   PRUint32 delay_ms = 500;
   PRUint32 dispose_op = PNG_DISPOSE_OP_NONE;
   PRUint32 blend_op = PNG_BLEND_OP_SOURCE;
+#endif
   PRUint32 x_offset = 0, y_offset = 0;
 
   // must be initialized
@@ -229,17 +243,22 @@
   }
 
   // parse and check any provided output options
-  nsresult rv = ParseOptions(aFrameOptions, &useTransparency, nsnull,
-                             nsnull, nsnull, &dispose_op, &blend_op,
-                             &delay_ms, &x_offset, &y_offset);
+  nsresult rv = ParseOptions(aFrameOptions, &useTransparency,
+#ifdef APNG
+                             nsnull, nsnull, nsnull, &dispose_op,
+			     &blend_op, &delay_ms,
+#endif
+                             &x_offset, &y_offset);
   if (rv != NS_OK) { return rv; }
 
+#ifdef APNG
   if (mIsAnimation) {
     // XXX the row pointers arg (#3) is unused, can it be removed?
     png_write_frame_head(mPNG, mPNGinfo, nsnull,
                          aWidth, aHeight, x_offset, y_offset,
                          delay_ms, 1000, dispose_op, blend_op);
   }
+#endif
 
   // Stride is the padded width of each row, so it better be longer (I'm afraid
   // people will not understand what stride means, so check it well)
@@ -283,9 +302,11 @@
     return NS_ERROR_INVALID_ARG;
   }
 
+#ifdef APNG
   if (mIsAnimation) {
     png_write_frame_tail(mPNG, mPNGinfo);
   }
+#endif
 
   return NS_OK;
 }
@@ -321,12 +342,14 @@
 nsresult
 nsPNGEncoder::ParseOptions(const nsAString& aOptions,
                            PRBool* useTransparency,
+#ifdef APNG
                            PRBool* skipFirstFrame,
                            PRUint32* numFrames,
                            PRUint32* numPlays,
                            PRUint32* frameDispose,
                            PRUint32* frameBlend,
                            PRUint32* frameDelay,
+#endif
                            PRUint32* offsetX,
                            PRUint32* offsetY)
 {
@@ -355,6 +378,7 @@
         return NS_ERROR_INVALID_ARG;
       }
 
+#ifdef APNG
     // skipfirstframe=[yes|no]
     } else if (nsCRT::strcmp(token, "skipfirstframe") == 0 && skipFirstFrame) {
       if (!value) { return NS_ERROR_INVALID_ARG; }
@@ -414,6 +438,7 @@
       if (!value) { return NS_ERROR_INVALID_ARG; }
 
       if (PR_sscanf(value, "%u", frameDelay) != 1) { return NS_ERROR_INVALID_ARG; }
+#endif
 
     // xoffset=#
     } else if (nsCRT::strcmp(token, "xoffset") == 0 && offsetX) {
--- src.orig/modules/libpr0n/encoders/png/nsPNGEncoder.h
+++ src/modules/libpr0n/encoders/png/nsPNGEncoder.h
@@ -65,12 +65,14 @@
 protected:
   nsresult ParseOptions(const nsAString& aOptions,
                            PRBool* useTransparency,
+#ifdef APNG
                            PRBool* skipFirstFrame,
                            PRUint32* numAnimatedFrames,
                            PRUint32* numIterations,
                            PRUint32* frameDispose,
                            PRUint32* frameBlend,
                            PRUint32* frameDelay,
+#endif
                            PRUint32* offsetX,
                            PRUint32* offsetY);
   void ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
@@ -83,7 +85,9 @@
   png_struct* mPNG;
   png_info* mPNGinfo;
 
+#ifdef APNG
   PRBool mIsAnimation;
+#endif
 
   // image buffer
   PRUint8* mImageBuffer;

