Bug 549468 - Add basic support for .ico icon encoder. r=joe
authorBrian R. Bondy <netzen@gmail.com>
Thu, 25 Aug 2011 16:09:05 -0400
changeset 75921 35b13356df7870bd0fb7dfd6e41cd49407a8359e
parent 75920 cefa6f2d2dfb43b47c2fb241b65fac149e20f58c
child 75922 f097100df8aa0aae62fde3bc4556f1232718bcde
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersjoe
bugs549468
milestone9.0a1
Bug 549468 - Add basic support for .ico icon encoder. r=joe
modules/libpr0n/build/Makefile.in
modules/libpr0n/build/nsImageModule.cpp
modules/libpr0n/decoders/nsICODecoder.h
modules/libpr0n/encoders/Makefile.in
modules/libpr0n/encoders/bmp/Makefile.in
modules/libpr0n/encoders/bmp/nsBMPEncoder.cpp
modules/libpr0n/encoders/bmp/nsBMPEncoder.h
modules/libpr0n/encoders/ico/Makefile.in
modules/libpr0n/encoders/ico/nsICOEncoder.cpp
modules/libpr0n/encoders/ico/nsICOEncoder.h
modules/libpr0n/encoders/jpeg/nsJPEGEncoder.cpp
modules/libpr0n/encoders/png/Makefile.in
modules/libpr0n/encoders/png/nsPNGEncoder.cpp
modules/libpr0n/encoders/png/nsPNGEncoder.h
modules/libpr0n/public/imgIEncoder.idl
modules/libpr0n/src/ICOFileHeaders.h
--- a/modules/libpr0n/build/Makefile.in
+++ b/modules/libpr0n/build/Makefile.in
@@ -52,23 +52,25 @@ LIBXUL_LIBRARY = 1
 
 CPPSRCS = \
 		nsImageModule.cpp \
 		$(NULL)
 
 LOCAL_INCLUDES	= \
 		-I. \
 		-I$(srcdir)/../src \
+		-I$(srcdir)/../encoders/ico \
 		-I$(srcdir)/../encoders/png \
 		-I$(srcdir)/../encoders/jpeg \
 		-I$(srcdir)/../encoders/bmp \
 		$(NULL)
 
 SHARED_LIBRARY_LIBS = \
 		../src/$(LIB_PREFIX)imglib2_s.$(LIB_SUFFIX) \
 		../decoders/$(LIB_PREFIX)imgdecoders_s.$(LIB_SUFFIX) \
+		../encoders/ico/$(LIB_PREFIX)imgicoe_s.$(LIB_SUFFIX) \
 		../encoders/png/$(LIB_PREFIX)imgpnge_s.$(LIB_SUFFIX) \
 		../encoders/jpeg/$(LIB_PREFIX)imgjpege_s.$(LIB_SUFFIX) \
 		../encoders/bmp/$(LIB_PREFIX)imgbmpe_s.$(LIB_SUFFIX) \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/modules/libpr0n/build/nsImageModule.cpp
+++ b/modules/libpr0n/build/nsImageModule.cpp
@@ -50,59 +50,64 @@
 #undef LoadImage
 
 #include "imgLoader.h"
 #include "imgRequest.h"
 #include "imgRequestProxy.h"
 #include "imgTools.h"
 #include "DiscardTracker.h"
 
+#include "nsICOEncoder.h"
 #include "nsPNGEncoder.h"
 #include "nsJPEGEncoder.h"
 #include "nsBMPEncoder.h"
 
 // objects that just require generic constructors
 namespace mozilla {
 namespace imagelib {
 NS_GENERIC_FACTORY_CONSTRUCTOR(RasterImage)
 }
 }
 using namespace mozilla::imagelib;
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(imgLoader, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequestProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(imgTools)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsICOEncoder)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJPEGEncoder)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsPNGEncoder)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBMPEncoder)
 NS_DEFINE_NAMED_CID(NS_IMGLOADER_CID);
 NS_DEFINE_NAMED_CID(NS_IMGREQUESTPROXY_CID);
 NS_DEFINE_NAMED_CID(NS_IMGTOOLS_CID);
 NS_DEFINE_NAMED_CID(NS_RASTERIMAGE_CID);
+NS_DEFINE_NAMED_CID(NS_ICOENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_JPEGENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_PNGENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_BMPENCODER_CID);
 
 static const mozilla::Module::CIDEntry kImageCIDs[] = {
   { &kNS_IMGLOADER_CID, false, NULL, imgLoaderConstructor, },
   { &kNS_IMGREQUESTPROXY_CID, false, NULL, imgRequestProxyConstructor, },
   { &kNS_IMGTOOLS_CID, false, NULL, imgToolsConstructor, },
   { &kNS_RASTERIMAGE_CID, false, NULL, RasterImageConstructor, },
+  { &kNS_ICOENCODER_CID, false, NULL, nsICOEncoderConstructor, },
   { &kNS_JPEGENCODER_CID, false, NULL, nsJPEGEncoderConstructor, },
   { &kNS_PNGENCODER_CID, false, NULL, nsPNGEncoderConstructor, },
   { &kNS_BMPENCODER_CID, false, NULL, nsBMPEncoderConstructor, },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kImageContracts[] = {
   { "@mozilla.org/image/cache;1", &kNS_IMGLOADER_CID },
   { "@mozilla.org/image/loader;1", &kNS_IMGLOADER_CID },
   { "@mozilla.org/image/request;1", &kNS_IMGREQUESTPROXY_CID },
   { "@mozilla.org/image/tools;1", &kNS_IMGTOOLS_CID },
   { "@mozilla.org/image/rasterimage;1", &kNS_RASTERIMAGE_CID },
+  { "@mozilla.org/image/encoder;2?type=image/vnd.microsoft.icon", &kNS_ICOENCODER_CID },
   { "@mozilla.org/image/encoder;2?type=image/jpeg", &kNS_JPEGENCODER_CID },
   { "@mozilla.org/image/encoder;2?type=image/png", &kNS_PNGENCODER_CID },
   { "@mozilla.org/image/encoder;2?type=image/bmp", &kNS_BMPENCODER_CID },
   { NULL }
 };
 
 static const mozilla::Module::CategoryEntry kImageCategories[] = {
   { "Gecko-Content-Viewers", "image/gif", "@mozilla.org/content/document-loader-factory;1" },
--- a/modules/libpr0n/decoders/nsICODecoder.h
+++ b/modules/libpr0n/decoders/nsICODecoder.h
@@ -42,44 +42,23 @@
 #ifndef _nsICODecoder_h
 #define _nsICODecoder_h
 
 #include "nsAutoPtr.h"
 #include "Decoder.h"
 #include "imgIDecoderObserver.h"
 #include "nsBMPDecoder.h"
 #include "nsPNGDecoder.h"
+#include "ICOFileHeaders.h"
 
 namespace mozilla {
 namespace imagelib {
 
-#define ICODIRENTRYSIZE 16
-#define PNGSIGNATURESIZE 8
-#define BMPFILEHEADERSIZE 14
-
 class RasterImage;
 
-struct IconDirEntry
-{
-  PRUint8   mWidth;
-  PRUint8   mHeight;
-  PRUint8   mColorCount;
-  PRUint8   mReserved;
-  union {
-    PRUint16 mPlanes;   // ICO
-    PRUint16 mXHotspot; // CUR
-  };
-  union {
-    PRUint16 mBitCount; // ICO
-    PRUint16 mYHotspot; // CUR
-  };
-  PRUint32  mBytesInRes;
-  PRUint32  mImageOffset;
-};
-
 class nsICODecoder : public Decoder
 {
 public:
 
   nsICODecoder();
   virtual ~nsICODecoder();
 
   virtual void WriteInternal(const char* aBuffer, PRUint32 aCount);
--- a/modules/libpr0n/encoders/Makefile.in
+++ b/modules/libpr0n/encoders/Makefile.in
@@ -35,15 +35,16 @@
 
 DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS += png \
+DIRS += ico \
+	png \
 	jpeg \
 	bmp \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/modules/libpr0n/encoders/bmp/Makefile.in
+++ b/modules/libpr0n/encoders/bmp/Makefile.in
@@ -43,16 +43,15 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= imgbmpe
 LIBRARY_NAME	= imgbmpe_s
 FORCE_STATIC_LIB = 1
 MODULE_NAME	= imgEncoderBMPModule
 LIBXUL_LIBRARY = 1
 
-# Decoders need RasterImage.h
 LOCAL_INCLUDES += -I$(topsrcdir)/modules/libpr0n/src/
 
 CPPSRCS		= nsBMPEncoder.cpp
 
 include $(topsrcdir)/config/rules.mk
 
 
--- a/modules/libpr0n/encoders/bmp/nsBMPEncoder.cpp
+++ b/modules/libpr0n/encoders/bmp/nsBMPEncoder.cpp
@@ -169,16 +169,32 @@ NS_IMETHODIMP nsBMPEncoder::StartImageEn
   mImageBufferCurr = mImageBufferStart;
 
   EncodeFileHeader();
   EncodeInfoHeader();
 
   return NS_OK;
 }
 
+// Returns the image buffer size
+NS_IMETHODIMP nsBMPEncoder::GetImageBufferSize(PRUint32 *aOutputSize)
+{
+  NS_ENSURE_ARG_POINTER(aOutputSize);
+  *aOutputSize = mImageBufferSize;
+  return NS_OK;
+}
+
+// Returns a pointer to the start of the image buffer
+NS_IMETHODIMP nsBMPEncoder::GetImageBuffer(char **aOutputBuffer)
+{
+  NS_ENSURE_ARG_POINTER(aOutputBuffer);
+  *aOutputBuffer = reinterpret_cast<char*>(mImageBufferStart);
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsBMPEncoder::AddImageFrame(const PRUint8* aData,
                                           PRUint32 aLength, // (unused,
                                                             // req'd by JS)
                                           PRUint32 aWidth,
                                           PRUint32 aHeight,
                                           PRUint32 aStride,
                                           PRUint32 aInputFormat,
                                           const nsAString& aFrameOptions)
--- a/modules/libpr0n/encoders/bmp/nsBMPEncoder.h
+++ b/modules/libpr0n/encoders/bmp/nsBMPEncoder.h
@@ -58,18 +58,16 @@ class nsBMPEncoder : public imgIEncoder
   typedef mozilla::ReentrantMonitor ReentrantMonitor;
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_IMGIENCODER
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIASYNCINPUTSTREAM
 
   nsBMPEncoder();
-
-private:
   ~nsBMPEncoder();
 
 protected:
   // See InitData in the cpp for valid parse options
   nsresult ParseOptions(const nsAString& aOptions, PRUint32* bpp);
   // Obtains data with no alpha in machine-independent byte order
   void ConvertHostARGBRow(const PRUint8* aSrc, PRUint8* aDest,
                           PRUint32 aPixelWidth);
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/encoders/ico/Makefile.in
@@ -0,0 +1,60 @@
+# ***** 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
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Brian R. Bondy <netzen@gmail.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
+# 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 *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= imgicoe
+LIBRARY_NAME	= imgicoe_s
+FORCE_STATIC_LIB = 1
+MODULE_NAME	= imgEncoderICOModule
+LIBXUL_LIBRARY = 1
+
+# Decoders need RasterImage.h
+LOCAL_INCLUDES += -I$(topsrcdir)/modules/libpr0n/src/
+LOCAL_INCLUDES += -I$(topsrcdir)/modules/libpr0n/encoders/bmp/
+LOCAL_INCLUDES += -I$(topsrcdir)/modules/libpr0n/encoders/png/
+
+CPPSRCS		= nsICOEncoder.cpp
+
+include $(topsrcdir)/config/rules.mk
+
+
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/encoders/ico/nsICOEncoder.cpp
@@ -0,0 +1,565 @@
+/* ***** 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 an implementation of an icon encoder.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian R. Bondy <netzen@gmail.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
+ * 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 "nsCRT.h"
+#include "Endian.h"
+#include "nsBMPEncoder.h"
+#include "nsPNGEncoder.h"
+#include "nsICOEncoder.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "nsString.h"
+#include "nsStreamUtils.h"
+
+using namespace mozilla;
+using namespace mozilla::imagelib;
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsICOEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
+
+nsICOEncoder::nsICOEncoder() : mFinished(PR_FALSE),
+                               mImageBufferStart(nsnull), 
+                               mImageBufferCurr(0),
+                               mImageBufferSize(0), 
+                               mImageBufferReadPoint(0), 
+                               mCallback(nsnull),
+                               mCallbackTarget(nsnull), 
+                               mNotifyThreshold(0),
+                               mUsePNG(PR_TRUE)
+{
+}
+
+nsICOEncoder::~nsICOEncoder()
+{
+  if (mImageBufferStart) {
+    moz_free(mImageBufferStart);
+    mImageBufferStart = nsnull;
+    mImageBufferCurr = nsnull;
+  }
+}
+
+// nsICOEncoder::InitFromData
+// Two output options are supported: format=<png|bmp>;bpp=<bpp_value>
+// format specifies whether to use png or bitmap format
+// bpp specifies the bits per pixel to use where bpp_value can be 24 or 32
+NS_IMETHODIMP nsICOEncoder::InitFromData(const PRUint8* aData,
+                                         PRUint32 aLength,
+                                         PRUint32 aWidth,
+                                         PRUint32 aHeight,
+                                         PRUint32 aStride,
+                                         PRUint32 aInputFormat,
+                                         const nsAString& aOutputOptions)
+{
+  // validate input format
+  if (aInputFormat != INPUT_FORMAT_RGB &&
+      aInputFormat != INPUT_FORMAT_RGBA &&
+      aInputFormat != INPUT_FORMAT_HOSTARGB) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // Stride is the padded width of each row, so it better be longer
+  if ((aInputFormat == INPUT_FORMAT_RGB &&
+       aStride < aWidth * 3) ||
+      ((aInputFormat == INPUT_FORMAT_RGBA || aInputFormat == INPUT_FORMAT_HOSTARGB) &&
+       aStride < aWidth * 4)) {
+    NS_WARNING("Invalid stride for InitFromData");
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  nsresult rv;
+  rv = StartImageEncode(aWidth, aHeight, aInputFormat, aOutputOptions);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = AddImageFrame(aData, aLength, aWidth, aHeight, aStride,
+                     aInputFormat, aOutputOptions);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = EndImageEncode();
+  return rv;
+}
+
+// Returns the image buffer size
+NS_IMETHODIMP 
+nsICOEncoder::GetImageBufferSize(PRUint32 *aOutputSize)
+{
+  NS_ENSURE_ARG_POINTER(aOutputSize);
+  *aOutputSize = mImageBufferSize;
+  return NS_OK;
+}
+
+// Returns a pointer to the start of the image buffer
+NS_IMETHODIMP 
+nsICOEncoder::GetImageBuffer(char **aOutputBuffer)
+{
+  NS_ENSURE_ARG_POINTER(aOutputBuffer);
+  *aOutputBuffer = reinterpret_cast<char*>(mImageBufferStart);
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+nsICOEncoder::AddImageFrame(const PRUint8* aData,
+                            PRUint32 aLength,
+                            PRUint32 aWidth,
+                            PRUint32 aHeight,
+                            PRUint32 aStride,
+                            PRUint32 aInputFormat, 
+                            const nsAString& aFrameOptions)
+{
+  if (mUsePNG) {
+
+    mContainedEncoder = new nsPNGEncoder();
+    nsresult rv;
+    nsAutoString noParams;
+    rv = mContainedEncoder->InitFromData(aData, aLength, aWidth, aHeight,
+                                         aStride, aInputFormat, noParams);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    PRUint32 imageBufferSize;
+    mContainedEncoder->GetImageBufferSize(&imageBufferSize);
+    mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE + 
+                       imageBufferSize;
+    mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize));
+    if (!mImageBufferStart) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    mImageBufferCurr = mImageBufferStart;
+    mICODirEntry.mBytesInRes = imageBufferSize;
+
+    EncodeFileHeader();
+    EncodeInfoHeader();
+
+    char *imageBuffer;
+    rv = mContainedEncoder->GetImageBuffer(&imageBuffer);
+    NS_ENSURE_SUCCESS(rv, rv);
+    memcpy(mImageBufferCurr, imageBuffer, imageBufferSize);
+    mImageBufferCurr += imageBufferSize;
+  } else {
+    mContainedEncoder = new nsBMPEncoder();
+    nsresult rv;
+
+    nsAutoString params;
+    params.AppendASCII("bpp=");
+    params.AppendInt(mICODirEntry.mBitCount);
+
+    rv = mContainedEncoder->InitFromData(aData, aLength, aWidth, aHeight,
+                                         aStride, aInputFormat, params);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    PRUint32 andMaskSize = ((mICODirEntry.mWidth + 31) / 32) * 4 * // row AND mask
+                           mICODirEntry.mHeight; // num rows
+
+    PRUint32 imageBufferSize;
+    mContainedEncoder->GetImageBufferSize(&imageBufferSize);
+    mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE + 
+                       imageBufferSize + andMaskSize;
+    mImageBufferStart = static_cast<PRUint8*>(moz_malloc(mImageBufferSize));
+    if (!mImageBufferStart) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    mImageBufferCurr = mImageBufferStart;
+
+    // The icon buffer does not include the BFH at all.
+    mICODirEntry.mBytesInRes = imageBufferSize - BFH_LENGTH + andMaskSize;
+
+    // Encode the icon headers
+    EncodeFileHeader();
+    EncodeInfoHeader();
+
+    char *imageBuffer;
+    rv = mContainedEncoder->GetImageBuffer(&imageBuffer);
+    NS_ENSURE_SUCCESS(rv, rv);
+    memcpy(mImageBufferCurr, imageBuffer + BFH_LENGTH, 
+           imageBufferSize - BFH_LENGTH);
+    // We need to fix the BMP height to be *2 for the AND mask
+    PRUint32 fixedHeight = mICODirEntry.mHeight * 2;
+    fixedHeight = NATIVE32_TO_LITTLE(fixedHeight);
+    // The height is stored at an offset of 8 from the DIB header
+    memcpy(mImageBufferCurr + 8, &fixedHeight, sizeof(fixedHeight));
+    mImageBufferCurr += imageBufferSize - BFH_LENGTH;
+
+    // Calculate rowsize in DWORD's
+    PRUint32 rowSize = ((mICODirEntry.mWidth + 31) / 32) * 4; // + 31 to round up
+    PRInt32 currentLine = mICODirEntry.mHeight;
+    
+    // Write out the AND mask
+    while (currentLine > 0) {
+      currentLine--;
+      PRUint8* encoded = mImageBufferCurr + currentLine * rowSize;
+      PRUint8* encodedEnd = encoded + rowSize;
+      while (encoded != encodedEnd) {
+        *encoded = 0; // make everything visible
+        encoded++;
+      }
+    }
+
+    mImageBufferCurr += andMaskSize;
+  }
+
+  return NS_OK;
+}
+
+// See ::InitFromData for other info.
+NS_IMETHODIMP nsICOEncoder::StartImageEncode(PRUint32 aWidth,
+                                             PRUint32 aHeight,
+                                             PRUint32 aInputFormat,
+                                             const nsAString& aOutputOptions)
+{
+  // can't initialize more than once
+  if (mImageBufferStart || mImageBufferCurr) {
+    return NS_ERROR_ALREADY_INITIALIZED;
+  }
+
+  // validate input format
+  if (aInputFormat != INPUT_FORMAT_RGB &&
+      aInputFormat != INPUT_FORMAT_RGBA &&
+      aInputFormat != INPUT_FORMAT_HOSTARGB) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // Icons are only 1 byte, so make sure our bitmap is in range
+  if (aWidth > 255 || aHeight > 255) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // parse and check any provided output options
+  PRUint32 bpp = 24;
+  PRBool usePNG = PR_TRUE;
+  nsresult rv = ParseOptions(aOutputOptions, &bpp, &usePNG);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mUsePNG = usePNG;
+
+  InitFileHeader();
+  InitInfoHeader(bpp, (PRUint8)aWidth, (PRUint8)aHeight); // range checks above
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsICOEncoder::EndImageEncode()
+{
+  // must be initialized
+  if (!mImageBufferStart || !mImageBufferCurr) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  mFinished = PR_TRUE;
+  NotifyListener();
+
+  // if output callback can't get enough memory, it will free our buffer
+  if (!mImageBufferStart || !mImageBufferCurr) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  return NS_OK;
+}
+
+// Parses the encoder options and sets the bits per pixel to use and PNG or BMP
+// See InitFromData for a description of the parse options
+nsresult
+nsICOEncoder::ParseOptions(const nsAString& aOptions, PRUint32* bpp, 
+                           PRBool *usePNG)
+{
+  // If no parsing options just use the default of 24BPP and PNG yes
+  if (aOptions.Length() == 0) {
+    if (usePNG) {
+      *usePNG = PR_TRUE;
+    }
+    if (bpp) {
+      *bpp = 24;
+    }
+  }
+
+  // Parse the input string into a set of name/value pairs.
+  // From format: format=<png|bmp>;bpp=<bpp_value>
+  // to format: [0] = format=<png|bmp>, [1] = bpp=<bpp_value>
+  nsTArray<nsCString> nameValuePairs;
+  if (!ParseString(NS_ConvertUTF16toUTF8(aOptions), ';', nameValuePairs)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // For each name/value pair in the set
+  for (int i = 0; i < nameValuePairs.Length(); ++i) {
+
+    // Split the name value pair [0] = name, [1] = value
+    nsTArray<nsCString> nameValuePair;
+    if (!ParseString(nameValuePairs[i], '=', nameValuePair)) {
+      return NS_ERROR_INVALID_ARG;
+    }
+    if (nameValuePair.Length() != 2) {
+      return NS_ERROR_INVALID_ARG;
+    }
+
+    // Parse the format portion of the string format=<png|bmp>;bpp=<bpp_value>
+    if (nameValuePair[0].Equals("format", nsCaseInsensitiveCStringComparator())) {
+      if (nameValuePair[1].Equals("png", nsCaseInsensitiveCStringComparator())) {
+        *usePNG = PR_TRUE;
+      }
+      else if (nameValuePair[1].Equals("bmp", nsCaseInsensitiveCStringComparator())) {
+        *usePNG = PR_FALSE;
+      }
+      else {
+        return NS_ERROR_INVALID_ARG;
+      }
+    }
+
+    // Parse the bpp portion of the string format=<png|bmp>;bpp=<bpp_value>
+    if (nameValuePair[0].Equals("bpp", nsCaseInsensitiveCStringComparator())) {
+      if (nameValuePair[1].Equals("24")) {
+        *bpp = 24;
+      }
+      else if (nameValuePair[1].Equals("32")) {
+        *bpp = 32;
+      }
+      else {
+        return NS_ERROR_INVALID_ARG;
+      }
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsICOEncoder::Close()
+{
+  if (mImageBufferStart) {
+    moz_free(mImageBufferStart);
+    mImageBufferStart = nsnull;
+    mImageBufferSize = 0;
+    mImageBufferReadPoint = 0;
+    mImageBufferCurr = nsnull;
+  }
+
+  return NS_OK;
+}
+
+// Obtains the available bytes to read
+NS_IMETHODIMP nsICOEncoder::Available(PRUint32 *_retval)
+{
+  if (!mImageBufferStart || !mImageBufferCurr) {
+    return NS_BASE_STREAM_CLOSED;
+  }
+
+  *_retval = GetCurrentImageBufferOffset() - mImageBufferReadPoint;
+  return NS_OK;
+}
+
+// [noscript] Reads bytes which are available
+NS_IMETHODIMP nsICOEncoder::Read(char *aBuf, PRUint32 aCount,
+                                 PRUint32 *_retval)
+{
+  return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
+}
+
+// [noscript] Reads segments
+NS_IMETHODIMP nsICOEncoder::ReadSegments(nsWriteSegmentFun aWriter,
+                                         void *aClosure, PRUint32 aCount,
+                                         PRUint32 *_retval)
+{
+  PRUint32 maxCount = GetCurrentImageBufferOffset() - mImageBufferReadPoint;
+  if (maxCount == 0) {
+    *_retval = 0;
+    return mFinished ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
+  }
+
+  if (aCount > maxCount) {
+    aCount = maxCount;
+  }
+
+  nsresult rv = aWriter(this, aClosure,
+                        reinterpret_cast<const char*>(mImageBufferStart + 
+                                                      mImageBufferReadPoint),
+                        0, aCount, _retval);
+  if (NS_SUCCEEDED(rv)) {
+    NS_ASSERTION(*_retval <= aCount, "bad write count");
+    mImageBufferReadPoint += *_retval;
+  }
+  // errors returned from the writer end here!
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+nsICOEncoder::IsNonBlocking(PRBool *_retval)
+{
+  *_retval = PR_TRUE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+nsICOEncoder::AsyncWait(nsIInputStreamCallback *aCallback,
+                        PRUint32 aFlags,
+                        PRUint32 aRequestedCount,
+                        nsIEventTarget *aTarget)
+{
+  if (aFlags != 0) {
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
+  if (mCallback || mCallbackTarget) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  mCallbackTarget = aTarget;
+  // 0 means "any number of bytes except 0"
+  mNotifyThreshold = aRequestedCount;
+  if (!aRequestedCount) {
+    mNotifyThreshold = 1024; // We don't want to notify incessantly
+  }
+
+  // We set the callback absolutely last, because NotifyListener uses it to
+  // determine if someone needs to be notified.  If we don't set it last,
+  // NotifyListener might try to fire off a notification to a null target
+  // which will generally cause non-threadsafe objects to be used off the main thread
+  mCallback = aCallback;
+
+  // What we are being asked for may be present already
+  NotifyListener();
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsICOEncoder::CloseWithStatus(nsresult aStatus)
+{
+  return Close();
+}
+
+void
+nsICOEncoder::NotifyListener()
+{
+  if (mCallback &&
+      (GetCurrentImageBufferOffset() - mImageBufferReadPoint >= mNotifyThreshold ||
+       mFinished)) {
+    nsCOMPtr<nsIInputStreamCallback> callback;
+    if (mCallbackTarget) {
+      NS_NewInputStreamReadyEvent(getter_AddRefs(callback),
+                                  mCallback,
+                                  mCallbackTarget);
+    } else {
+      callback = mCallback;
+    }
+
+    NS_ASSERTION(callback, "Shouldn't fail to make the callback");
+    // Null the callback first because OnInputStreamReady could reenter
+    // AsyncWait
+    mCallback = nsnull;
+    mCallbackTarget = nsnull;
+    mNotifyThreshold = 0;
+
+    callback->OnInputStreamReady(this);
+  }
+}
+
+// Initializes the icon file header mICOFileHeader
+void 
+nsICOEncoder::InitFileHeader()
+{
+  memset(&mICOFileHeader, 0, sizeof(mICOFileHeader));
+  mICOFileHeader.mReserved = 0;
+  mICOFileHeader.mType = 1;
+  mICOFileHeader.mCount = 1;
+}
+
+// Initializes the icon directory info header mICODirEntry
+void 
+nsICOEncoder::InitInfoHeader(PRUint32 aBPP, PRUint8 aWidth, PRUint8 aHeight)
+{
+  memset(&mICODirEntry, 0, sizeof(mICODirEntry));
+  mICODirEntry.mBitCount = aBPP;
+  mICODirEntry.mBytesInRes = 0;
+  mICODirEntry.mColorCount = 0;
+  mICODirEntry.mWidth = aWidth;
+  mICODirEntry.mHeight = aHeight;
+  mICODirEntry.mImageOffset = ICONFILEHEADERSIZE + ICODIRENTRYSIZE;
+  mICODirEntry.mPlanes = 1;
+  mICODirEntry.mReserved = 0;
+}
+
+// Encodes the icon file header mICOFileHeader
+void 
+nsICOEncoder::EncodeFileHeader() 
+{  
+  IconFileHeader littleEndianIFH = mICOFileHeader;
+  littleEndianIFH.mReserved = NATIVE16_TO_LITTLE(littleEndianIFH.mReserved);
+  littleEndianIFH.mType = NATIVE16_TO_LITTLE(littleEndianIFH.mType);
+  littleEndianIFH.mCount = NATIVE16_TO_LITTLE(littleEndianIFH.mCount);
+
+  memcpy(mImageBufferCurr, &littleEndianIFH.mReserved, 
+         sizeof(littleEndianIFH.mReserved));
+  mImageBufferCurr += sizeof(littleEndianIFH.mReserved);
+  memcpy(mImageBufferCurr, &littleEndianIFH.mType, 
+         sizeof(littleEndianIFH.mType));
+  mImageBufferCurr += sizeof(littleEndianIFH.mType);
+  memcpy(mImageBufferCurr, &littleEndianIFH.mCount, 
+         sizeof(littleEndianIFH.mCount));
+  mImageBufferCurr += sizeof(littleEndianIFH.mCount);
+}
+
+// Encodes the icon directory info header mICODirEntry
+void 
+nsICOEncoder::EncodeInfoHeader()
+{
+  IconDirEntry littleEndianmIDE = mICODirEntry;
+
+  littleEndianmIDE.mPlanes = NATIVE16_TO_LITTLE(littleEndianmIDE.mPlanes);
+  littleEndianmIDE.mBitCount = NATIVE16_TO_LITTLE(littleEndianmIDE.mBitCount);
+  littleEndianmIDE.mBytesInRes = 
+    NATIVE32_TO_LITTLE(littleEndianmIDE.mBytesInRes);
+  littleEndianmIDE.mImageOffset  = 
+    NATIVE32_TO_LITTLE(littleEndianmIDE.mImageOffset);
+
+  memcpy(mImageBufferCurr, &littleEndianmIDE.mWidth, 
+         sizeof(littleEndianmIDE.mWidth));
+  mImageBufferCurr += sizeof(littleEndianmIDE.mWidth);
+  memcpy(mImageBufferCurr, &littleEndianmIDE.mHeight, 
+         sizeof(littleEndianmIDE.mHeight));
+  mImageBufferCurr += sizeof(littleEndianmIDE.mHeight);
+  memcpy(mImageBufferCurr, &littleEndianmIDE.mColorCount, 
+         sizeof(littleEndianmIDE.mColorCount));
+  mImageBufferCurr += sizeof(littleEndianmIDE.mColorCount);
+  memcpy(mImageBufferCurr, &littleEndianmIDE.mReserved, 
+         sizeof(littleEndianmIDE.mReserved));
+  mImageBufferCurr += sizeof(littleEndianmIDE.mReserved);
+  memcpy(mImageBufferCurr, &littleEndianmIDE.mPlanes, 
+         sizeof(littleEndianmIDE.mPlanes));
+  mImageBufferCurr += sizeof(littleEndianmIDE.mPlanes);
+  memcpy(mImageBufferCurr, &littleEndianmIDE.mBitCount, 
+         sizeof(littleEndianmIDE.mBitCount));
+  mImageBufferCurr += sizeof(littleEndianmIDE.mBitCount);
+  memcpy(mImageBufferCurr, &littleEndianmIDE.mBytesInRes, 
+         sizeof(littleEndianmIDE.mBytesInRes));
+  mImageBufferCurr += sizeof(littleEndianmIDE.mBytesInRes);
+  memcpy(mImageBufferCurr, &littleEndianmIDE.mImageOffset, 
+         sizeof(littleEndianmIDE.mImageOffset));
+  mImageBufferCurr += sizeof(littleEndianmIDE.mImageOffset);
+}
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/encoders/ico/nsICOEncoder.h
@@ -0,0 +1,115 @@
+/* ***** 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 an implementation of an icon encoder.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian R. Bondy <netzen@gmail.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
+ * 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 "imgIEncoder.h"
+
+#include "mozilla/ReentrantMonitor.h"
+
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "ICOFileHeaders.h"
+
+class nsBMPEncoder;
+class nsPNGEncoder;
+
+#define NS_ICOENCODER_CID \
+{ /*92AE3AB2-8968-41B1-8709-B6123BCEAF21 */          \
+     0x92ae3ab2,                                     \
+     0x8968,                                         \
+     0x41b1,                                         \
+    {0x87, 0x09, 0xb6, 0x12, 0x3b, 0Xce, 0xaf, 0x21} \
+}
+
+// Provides ICO encoding functionality. Use InitFromData() to do the
+// encoding. See that function definition for encoding options.
+
+class nsICOEncoder : public imgIEncoder
+{
+  typedef mozilla::ReentrantMonitor ReentrantMonitor;
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_IMGIENCODER
+  NS_DECL_NSIINPUTSTREAM
+  NS_DECL_NSIASYNCINPUTSTREAM
+
+  nsICOEncoder();
+  ~nsICOEncoder();
+
+protected:
+  nsresult ParseOptions(const nsAString& aOptions, PRUint32* bpp, 
+                        PRBool *usePNG);
+  void NotifyListener();
+
+  // Initializes the icon file header mICOFileHeader
+  void InitFileHeader();
+  // Initializes the icon directory info header mICODirEntry
+  void InitInfoHeader(PRUint32 aBPP, PRUint8 aWidth, PRUint8 aHeight);
+  // Encodes the icon file header mICOFileHeader
+  void EncodeFileHeader();
+  // Encodes the icon directory info header mICODirEntry
+  void EncodeInfoHeader();
+  // Obtains the current offset filled up to for the image buffer
+  inline PRInt32 GetCurrentImageBufferOffset()
+  {
+    return static_cast<PRInt32>(mImageBufferCurr - mImageBufferStart);
+  }
+
+  // Holds either a PNG or a BMP depending on the encoding options specified
+  // or if no encoding options specified will use the default (PNG)
+  nsCOMPtr<imgIEncoder> mContainedEncoder;
+
+  // These headers will always contain endian independent stuff 
+  mozilla::imagelib::IconFileHeader mICOFileHeader;
+  mozilla::imagelib::IconDirEntry mICODirEntry;
+
+  // Keeps track of the start of the image buffer
+  PRUint8* mImageBufferStart;
+  // Keeps track of the current position in the image buffer
+  PRUint8* mImageBufferCurr;
+  // Keeps track of the image buffer size
+  PRUint32 mImageBufferSize;
+  // Keeps track of the number of bytes in the image buffer which are read
+  PRUint32 mImageBufferReadPoint;
+  // Stores PR_TRUE if the image is done being encoded  
+  PRPackedBool mFinished;
+  // Stores PR_TRUE if the contained image is a PNG
+  PRPackedBool mUsePNG;
+
+  nsCOMPtr<nsIInputStreamCallback> mCallback;
+  nsCOMPtr<nsIEventTarget> mCallbackTarget;
+  PRUint32 mNotifyThreshold;
+};
--- a/modules/libpr0n/encoders/jpeg/nsJPEGEncoder.cpp
+++ b/modules/libpr0n/encoders/jpeg/nsJPEGEncoder.cpp
@@ -214,16 +214,32 @@ NS_IMETHODIMP nsJPEGEncoder::InitFromDat
 NS_IMETHODIMP nsJPEGEncoder::StartImageEncode(PRUint32 aWidth,
                                               PRUint32 aHeight,
                                               PRUint32 aInputFormat,
                                               const nsAString& aOutputOptions)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+// Returns the image buffer size
+NS_IMETHODIMP  nsJPEGEncoder::GetImageBufferSize(PRUint32 *aOutputSize)
+{
+  NS_ENSURE_ARG_POINTER(aOutputSize);
+  *aOutputSize = mImageBufferSize;
+  return NS_OK;
+}
+
+// Returns a pointer to the start of the image buffer
+NS_IMETHODIMP nsJPEGEncoder::GetImageBuffer(char **aOutputBuffer)
+{
+  NS_ENSURE_ARG_POINTER(aOutputBuffer);
+  *aOutputBuffer = reinterpret_cast<char*>(mImageBuffer);
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsJPEGEncoder::AddImageFrame(const PRUint8* aData,
                                            PRUint32 aLength,
                                            PRUint32 aWidth,
                                            PRUint32 aHeight,
                                            PRUint32 aStride,
                                            PRUint32 aFrameFormat,
                                            const nsAString& aFrameOptions)
 {
--- a/modules/libpr0n/encoders/png/Makefile.in
+++ b/modules/libpr0n/encoders/png/Makefile.in
@@ -45,13 +45,15 @@ LIBRARY_NAME	= imgpnge_s
 FORCE_STATIC_LIB = 1
 MODULE_NAME	= imgEncoderPNGModule
 LIBXUL_LIBRARY = 1
 
 DEFINES		+= -DMOZ_PNG_WRITE \
 	-DMOZ_PNG_READ \
 	$(NULL)
 
+LOCAL_INCLUDES += -I$(topsrcdir)/modules/libpr0n/src/
+
 CPPSRCS		= nsPNGEncoder.cpp
 
 include $(topsrcdir)/config/rules.mk
 
 
--- a/modules/libpr0n/encoders/png/nsPNGEncoder.cpp
+++ b/modules/libpr0n/encoders/png/nsPNGEncoder.cpp
@@ -200,16 +200,31 @@ NS_IMETHODIMP nsPNGEncoder::StartImageEn
 
   // XXX: support PLTE, gAMA, tRNS, bKGD?
 
   png_write_info(mPNG, mPNGinfo);
 
   return NS_OK;
 }
 
+// Returns the image buffer size
+NS_IMETHODIMP nsPNGEncoder::GetImageBufferSize(PRUint32 *aOutputSize)
+{
+  NS_ENSURE_ARG_POINTER(aOutputSize);
+  *aOutputSize = mImageBufferSize;
+  return NS_OK;
+}
+
+// Returns a pointer to the start of the image buffer
+NS_IMETHODIMP nsPNGEncoder::GetImageBuffer(char **aOutputBuffer)
+{
+  NS_ENSURE_ARG_POINTER(aOutputBuffer);
+  *aOutputBuffer = reinterpret_cast<char*>(mImageBuffer);
+  return NS_OK;
+}
 
 NS_IMETHODIMP nsPNGEncoder::AddImageFrame(const PRUint8* aData,
                                           PRUint32 aLength, // (unused,
                                                             // req'd by JS)
                                           PRUint32 aWidth,
                                           PRUint32 aHeight,
                                           PRUint32 aStride,
                                           PRUint32 aInputFormat,
--- a/modules/libpr0n/encoders/png/nsPNGEncoder.h
+++ b/modules/libpr0n/encoders/png/nsPNGEncoder.h
@@ -59,18 +59,16 @@ class nsPNGEncoder : public imgIEncoder
   typedef mozilla::ReentrantMonitor ReentrantMonitor;
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_IMGIENCODER
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIASYNCINPUTSTREAM
 
   nsPNGEncoder();
-
-private:
   ~nsPNGEncoder();
 
 protected:
   nsresult ParseOptions(const nsAString& aOptions,
                         PRBool* useTransparency,
                         PRBool* skipFirstFrame,
                         PRUint32* numAnimatedFrames,
                         PRUint32* numIterations,
--- a/modules/libpr0n/public/imgIEncoder.idl
+++ b/modules/libpr0n/public/imgIEncoder.idl
@@ -39,17 +39,17 @@
 
 #include "nsISupports.idl"
 #include "nsIAsyncInputStream.idl"
 #include "nsIEventTarget.idl"
 
 /**
  * imgIEncoder interface
  */
-[scriptable, uuid(4bcba4ec-7a44-43f9-a70f-1e92cdc625b9)]
+[scriptable, uuid(d02e2d95-072d-4b91-8b8f-1300e45fcb2b)]
 interface imgIEncoder : nsIAsyncInputStream
 {
   // Possible values for outputOptions. Multiple values are semicolon-separated.
   //
   // PNG:
   // ----
   // transparency=[yes|no|none]  --  default: "yes"
   //     Overrides default from input format. "no" and "none" are equivalent.
@@ -151,9 +151,16 @@ interface imgIEncoder : nsIAsyncInputStr
                     in unsigned long length,
                     in PRUint32 width,
                     in PRUint32 height,
                     in PRUint32 stride,
                     in PRUint32 frameFormat,
                     in AString frameOptions);
 
   void endImageEncode();
+
+  /*
+   * Sometimes an encoder can contain another encoder and direct access
+   * to its buffer is necessary. 
+   */
+  [noscript] unsigned long getImageBufferSize();
+  [noscript] charPtr getImageBuffer();
 };
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/src/ICOFileHeaders.h
@@ -0,0 +1,79 @@
+/* ***** 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 icon header definitions.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian R. Bondy <netzen@gmail.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
+ * 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 ***** */
+
+
+#ifndef MOZILLA_IMAGELIB_ICOHEADERS_H_
+#define MOZILLA_IMAGELIB_ICOHEADERS_H_
+
+namespace mozilla {
+  namespace imagelib {
+
+    #define ICONFILEHEADERSIZE 6
+    #define ICODIRENTRYSIZE 16
+    #define PNGSIGNATURESIZE 8
+    #define BMPFILEHEADERSIZE 14
+
+    struct IconFileHeader
+    {
+      PRUint16   mReserved;
+      PRUint16   mType;
+      PRUint16   mCount;
+    };
+
+    struct IconDirEntry
+    {
+      PRUint8   mWidth;
+      PRUint8   mHeight;
+      PRUint8   mColorCount;
+      PRUint8   mReserved;
+      union {
+        PRUint16 mPlanes;   // ICO
+        PRUint16 mXHotspot; // CUR
+      };
+      union {
+        PRUint16 mBitCount; // ICO
+        PRUint16 mYHotspot; // CUR
+      };
+      PRUint32  mBytesInRes;
+      PRUint32  mImageOffset;
+    };
+
+
+  } // namespace imagelib
+} // namespace mozilla
+
+#endif