Back to index

lightning-sunbird  0.9+nobinonly
nsICODecoder.cpp
Go to the documentation of this file.
00001 /* vim:set tw=80 expandtab softtabstop=4 ts=4 sw=4: */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Mozilla ICO Decoder.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   David Hyatt <hyatt@netscape.com> (Original Author)
00024  *   Christian Biesinger <cbiesinger@web.de>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /* This is a Cross-Platform ICO Decoder, which should work everywhere, including
00041  * Big-Endian machines like the PowerPC. */
00042 
00043 #include <stdlib.h>
00044 
00045 #include "nsICODecoder.h"
00046 
00047 #include "nsIInputStream.h"
00048 #include "nsIComponentManager.h"
00049 #include "imgIContainerObserver.h"
00050 
00051 #include "imgILoad.h"
00052 
00053 #include "nsIProperties.h"
00054 #include "nsISupportsPrimitives.h"
00055 
00056 #include "nsAutoPtr.h"
00057 
00058 NS_IMPL_ISUPPORTS1(nsICODecoder, imgIDecoder)
00059 
00060 #define ICONCOUNTOFFSET 4
00061 #define DIRENTRYOFFSET 6
00062 #define BITMAPINFOSIZE 40
00063 #define PREFICONSIZE 16
00064 
00065 // ----------------------------------------
00066 // Actual Data Processing
00067 // ----------------------------------------
00068 
00069 nsresult nsICODecoder::SetImageData()
00070 {
00071   PRUint32 bpr;
00072   mFrame->GetImageBytesPerRow(&bpr);
00073  
00074   // Since the ICO is decoded into an exact sized array, the frame may use
00075   // more bytes per row of pixels than the decoding array.
00076 #if defined(XP_MAC) || defined(XP_MACOSX)
00077   PRUint32 decodedLineLen = mDirEntry.mWidth * 4;
00078 #else
00079   PRUint32 decodedLineLen = mDirEntry.mWidth * 3;
00080 #endif
00081 
00082   PRUint8* decodeBufferPos = mDecodedBuffer;
00083   PRUint32 frameOffset = 0;
00084 
00085   for (PRUint32 i = 0;
00086        i < mDirEntry.mHeight;
00087        ++i, frameOffset += bpr, decodeBufferPos += decodedLineLen) {
00088     mFrame->SetImageData(decodeBufferPos, decodedLineLen, frameOffset);
00089   }
00090 
00091   nsIntRect r(0, 0, 0, 0);
00092   mFrame->GetWidth(&r.width);
00093   mFrame->GetHeight(&r.height);
00094   mObserver->OnDataAvailable(nsnull, mFrame, &r);
00095 
00096   return NS_OK;
00097 }
00098 
00099 nsresult nsICODecoder::SetAlphaData()
00100 {
00101   // Alpha data was already set if bpp == 32
00102   if (mHaveAlphaData)
00103     return NS_OK;
00104 
00105   PRUint32 bpr;
00106   mFrame->GetAlphaBytesPerRow(&bpr);
00107   // In case the decoder and frame have different sized alpha buffers, we
00108   // take the smaller of the two row length values as the row length to copy.
00109   PRUint32 rowCopyLen = PR_MIN(bpr, mDirEntry.mWidth);
00110   PRUint8* alphaRow = (PRUint8*)malloc(rowCopyLen);
00111   if (!alphaRow)
00112     return NS_ERROR_OUT_OF_MEMORY;
00113 
00114   PRUint32 decoderRowSize = CalcAlphaRowSize();
00115   PRUint8* alphaBufferPos = mAlphaBuffer;
00116   PRUint32 frameOffset = 0;
00117 
00118   for (PRUint32 i = 0; i < mDirEntry.mHeight; i++) {
00119     PRInt8 byte = 0;
00120     PRUint32 k = 0;
00121     for (PRUint32 j = 0; j < rowCopyLen; ++j) {
00122       if ((j % 8) == 0)
00123         byte = alphaBufferPos[k++];
00124       alphaRow[j] = byte >> 7;
00125       byte <<= 1;
00126     }
00127     mFrame->SetAlphaData(alphaRow, rowCopyLen, frameOffset);
00128     frameOffset += bpr;
00129     alphaBufferPos += decoderRowSize;
00130   }
00131   free(alphaRow);
00132   return NS_OK;
00133 }
00134 
00135 PRUint32 nsICODecoder::CalcAlphaRowSize()
00136 {
00137   PRUint32 rowSize = (mDirEntry.mWidth + 7) / 8; // +7 to round up
00138   if (rowSize % 4)
00139     rowSize += (4 - (rowSize % 4)); // Pad to DWORD Boundary
00140   return rowSize;
00141 }
00142 
00143 nsICODecoder::nsICODecoder()
00144 {
00145   mPos = mNumColors = mRowBytes = mImageOffset = mCurrIcon = mNumIcons = 0;
00146   mCurLine = 1; // Otherwise decoder will never start
00147   mStatus = NS_OK;
00148   mColors = nsnull;
00149   mRow = nsnull;
00150   mHaveAlphaData = 0;
00151   mDecodingAndMask = PR_FALSE;
00152   mDecodedBuffer = nsnull;
00153   mAlphaBuffer = nsnull;
00154 }
00155 
00156 nsICODecoder::~nsICODecoder()
00157 {
00158 }
00159 
00160 NS_IMETHODIMP nsICODecoder::Init(imgILoad *aLoad)
00161 { 
00162   mObserver = do_QueryInterface(aLoad);
00163     
00164   mImage = do_CreateInstance("@mozilla.org/image/container;1");
00165   if (!mImage)
00166     return NS_ERROR_OUT_OF_MEMORY;
00167 
00168   mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
00169   if (!mFrame)
00170     return NS_ERROR_OUT_OF_MEMORY;
00171 
00172   return aLoad->SetImage(mImage);
00173 }
00174 
00175 NS_IMETHODIMP nsICODecoder::Close()
00176 {
00177   mObserver->OnStopContainer(nsnull, mImage);
00178   mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
00179   mObserver = nsnull;
00180 
00181   mImage = nsnull;
00182   mFrame = nsnull;
00183  
00184   mPos = 0;
00185 
00186   delete[] mColors;
00187   mColors = nsnull;
00188 
00189   mCurLine = 0;
00190   mRowBytes = 0;
00191   mImageOffset = 0;
00192   mCurrIcon = 0;
00193   mNumIcons = 0;
00194 
00195   free(mRow);
00196   mRow = nsnull;
00197 
00198   mDecodingAndMask = PR_FALSE;
00199   free(mDecodedBuffer);
00200   free(mAlphaBuffer);
00201 
00202   return NS_OK;
00203 }
00204 
00205 NS_IMETHODIMP nsICODecoder::Flush()
00206 {
00207   // Set Data here because some ICOs don't have a complete AND Mask
00208   // see bug 115357
00209   if (mDecodingAndMask) {
00210     SetAlphaData();
00211     SetImageData();
00212     mObserver->OnStopFrame(nsnull, mFrame);
00213   }
00214   return NS_OK;
00215 }
00216 
00217 
00218 NS_METHOD nsICODecoder::ReadSegCb(nsIInputStream* aIn, void* aClosure,
00219                              const char* aFromRawSegment, PRUint32 aToOffset,
00220                              PRUint32 aCount, PRUint32 *aWriteCount) {
00221   nsICODecoder *decoder = NS_REINTERPRET_CAST(nsICODecoder*, aClosure);
00222   *aWriteCount = aCount;
00223   decoder->mStatus = decoder->ProcessData(aFromRawSegment, aCount);
00224   return decoder->mStatus;
00225 }
00226 
00227 NS_IMETHODIMP nsICODecoder::WriteFrom(nsIInputStream *aInStr, PRUint32 aCount, PRUint32 *aRetval)
00228 {
00229   nsresult rv = aInStr->ReadSegments(ReadSegCb, this, aCount, aRetval);
00230   NS_ENSURE_SUCCESS(rv, rv);
00231   return mStatus;
00232 }
00233 
00234 nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
00235   if (!aCount) // aCount=0 means EOF
00236     return NS_OK;
00237 
00238   while (aCount && (mPos < ICONCOUNTOFFSET)) { // Skip to the # of icons.
00239     if (mPos == 2) { // if the third byte is 1: This is an icon, 2: a cursor
00240       if ((*aBuffer != 1) && (*aBuffer != 2)) {
00241         return NS_ERROR_FAILURE;
00242       }
00243       mIsCursor = (*aBuffer == 2);
00244     }
00245     mPos++; aBuffer++; aCount--;
00246   }
00247 
00248   if (mPos == ICONCOUNTOFFSET && aCount >= 2) {
00249     mNumIcons = LITTLE_TO_NATIVE16(((PRUint16*)aBuffer)[0]);
00250     aBuffer += 2;
00251     mPos += 2;
00252     aCount -= 2;
00253   }
00254 
00255   if (mNumIcons == 0)
00256     return NS_OK; // Nothing to do.
00257 
00258   PRUint16 colorDepth = 0;
00259   while (mCurrIcon < mNumIcons) {
00260     if (mPos >= DIRENTRYOFFSET + (mCurrIcon*sizeof(mDirEntryArray)) && 
00261         mPos < DIRENTRYOFFSET + ((mCurrIcon+1)*sizeof(mDirEntryArray))) {
00262       PRUint32 toCopy = sizeof(mDirEntryArray) - (mPos - DIRENTRYOFFSET - mCurrIcon*sizeof(mDirEntryArray));
00263       if (toCopy > aCount)
00264         toCopy = aCount;
00265       memcpy(mDirEntryArray + sizeof(mDirEntryArray) - toCopy, aBuffer, toCopy);
00266       mPos += toCopy;
00267       aCount -= toCopy;
00268       aBuffer += toCopy;
00269     }
00270     if (aCount == 0)
00271       return NS_OK; // Need more data
00272 
00273     IconDirEntry e;
00274     if (mPos == 22+mCurrIcon*sizeof(mDirEntryArray)) {
00275       mCurrIcon++;
00276       ProcessDirEntry(e);
00277       if ((e.mWidth == PREFICONSIZE && e.mHeight == PREFICONSIZE && e.mBitCount >= colorDepth)
00278            || (mCurrIcon == mNumIcons && mImageOffset == 0)) {
00279         mImageOffset = e.mImageOffset;
00280 
00281         // ensure mImageOffset is >= the size of the direntry headers (bug #245631)
00282         PRUint32 minImageOffset = DIRENTRYOFFSET + mNumIcons*sizeof(mDirEntryArray);
00283         if (mImageOffset < minImageOffset)
00284           return NS_ERROR_FAILURE;
00285 
00286         colorDepth = e.mBitCount;
00287         memcpy(&mDirEntry, &e, sizeof(IconDirEntry));
00288       }
00289     }
00290   }
00291 
00292   while (aCount && mPos < mImageOffset) { // Skip to our offset
00293     mPos++; aBuffer++; aCount--;
00294   }
00295 
00296   if (mCurrIcon == mNumIcons && mPos >= mImageOffset && mPos < mImageOffset + BITMAPINFOSIZE) {
00297     // We've found the icon.
00298     PRUint32 toCopy = sizeof(mBIHraw) - (mPos - mImageOffset);
00299     if (toCopy > aCount)
00300       toCopy = aCount;
00301 
00302     memcpy(mBIHraw + (mPos - mImageOffset), aBuffer, toCopy);
00303     mPos += toCopy;
00304     aCount -= toCopy;
00305     aBuffer += toCopy;
00306   }
00307 
00308   if (mPos == mImageOffset + BITMAPINFOSIZE) {
00309     ProcessInfoHeader();
00310     if (mBIH.bpp <= 8) {
00311       switch (mBIH.bpp) {
00312         case 1:
00313           mNumColors = 2;
00314           break;
00315         case 4:
00316           mNumColors = 16;
00317           break;
00318         case 8:
00319           mNumColors = 256;
00320           break;
00321         default:
00322           return NS_ERROR_FAILURE;
00323       }
00324 
00325       mColors = new colorTable[mNumColors];
00326       if (!mColors)
00327         return NS_ERROR_OUT_OF_MEMORY;
00328     }
00329 
00330     nsresult rv = mImage->Init(mDirEntry.mWidth, mDirEntry.mHeight, mObserver);
00331     NS_ENSURE_SUCCESS(rv, rv);
00332 
00333     if (mIsCursor) {
00334       nsCOMPtr<nsIProperties> props(do_QueryInterface(mImage));
00335       if (props) {
00336         nsCOMPtr<nsISupportsPRUint32> intwrapx = do_CreateInstance("@mozilla.org/supports-PRUint32;1");
00337         nsCOMPtr<nsISupportsPRUint32> intwrapy = do_CreateInstance("@mozilla.org/supports-PRUint32;1");
00338 
00339         if (intwrapx && intwrapy) {
00340           intwrapx->SetData(mDirEntry.mXHotspot);
00341           intwrapy->SetData(mDirEntry.mYHotspot);
00342 
00343           props->Set("hotspotX", intwrapx);
00344           props->Set("hotspotY", intwrapy);
00345         }
00346       }
00347     }
00348 
00349     rv = mObserver->OnStartContainer(nsnull, mImage);
00350     NS_ENSURE_SUCCESS(rv, rv);
00351 
00352     mCurLine = mDirEntry.mHeight;
00353     mRow = (PRUint8*)malloc((mDirEntry.mWidth * mBIH.bpp)/8 + 4);
00354     // +4 because the line is padded to a 4 bit boundary, but I don't want
00355     // to make exact calculations here, that's unnecessary.
00356     // Also, it compensates rounding error.
00357     if (!mRow)
00358       return NS_ERROR_OUT_OF_MEMORY;
00359     
00360     rv = mFrame->Init(0, 0, mDirEntry.mWidth, mDirEntry.mHeight, GFXFORMATALPHA8, 24);
00361     NS_ENSURE_SUCCESS(rv, rv);
00362     rv = mImage->AppendFrame(mFrame);
00363     NS_ENSURE_SUCCESS(rv, rv);
00364     mObserver->OnStartFrame(nsnull, mFrame);
00365     NS_ENSURE_SUCCESS(rv, rv);
00366   }
00367 
00368   if (mColors && (mPos >= mImageOffset + BITMAPINFOSIZE) && 
00369                  (mPos < (mImageOffset + BITMAPINFOSIZE + mNumColors * 4))) {
00370     // We will receive (mNumColors * 4) bytes of color data
00371     PRUint32 colorBytes = mPos - (mImageOffset + 40); // Number of bytes already received
00372     PRUint8 colorNum = colorBytes / 4; // Color which is currently received
00373     PRUint8 at = colorBytes % 4;
00374     while (aCount && (mPos < (mImageOffset + BITMAPINFOSIZE + mNumColors * 4))) {
00375       switch (at) {
00376         case 0:
00377           mColors[colorNum].blue = *aBuffer;
00378           break;
00379         case 1:
00380           mColors[colorNum].green = *aBuffer;
00381           break;
00382         case 2:
00383           mColors[colorNum].red = *aBuffer;
00384           break;
00385         case 3:
00386           colorNum++; // This is a padding byte
00387           break;
00388       }
00389       mPos++; aBuffer++; aCount--;
00390       at = (at + 1) % 4;
00391     }
00392   }
00393 
00394   if (!mDecodingAndMask && (mPos >= (mImageOffset + BITMAPINFOSIZE + mNumColors*4))) {
00395     if (mPos == (mImageOffset + BITMAPINFOSIZE + mNumColors*4)) {
00396       // Increment mPos to avoid reprocessing the info header.
00397       mPos++;
00398 #if defined(XP_MAC) || defined(XP_MACOSX)
00399       mDecodedBuffer = (PRUint8*)malloc(mDirEntry.mHeight*mDirEntry.mWidth*4);
00400 #else
00401       mDecodedBuffer = (PRUint8*)malloc(mDirEntry.mHeight*mDirEntry.mWidth*3);
00402 #endif
00403       if (!mDecodedBuffer)
00404         return NS_ERROR_OUT_OF_MEMORY;
00405     }
00406     PRUint32 alphaRowSize;
00407     mFrame->GetAlphaBytesPerRow(&alphaRowSize);
00408     nsAutoArrayPtr<PRUint8> alphaRow; // Will only be used if bpp == 32
00409     if (mBIH.bpp == 32) {
00410       alphaRow = new PRUint8[alphaRowSize];
00411       if (!alphaRow)
00412         return NS_ERROR_OUT_OF_MEMORY;
00413     }
00414 
00415     // Ensure memory has been allocated before decoding. If we get this far 
00416     // without allocated memory, the file is most likely invalid.
00417     NS_ASSERTION(mRow, "mRow is null");
00418     NS_ASSERTION(mDecodedBuffer, "mDecodedBuffer is null");
00419     if (!mRow || !mDecodedBuffer)
00420       return NS_ERROR_FAILURE;
00421 
00422     PRUint32 rowSize = (mBIH.bpp * mDirEntry.mWidth + 7) / 8; // +7 to round up
00423     if (rowSize % 4)
00424       rowSize += (4 - (rowSize % 4)); // Pad to DWORD Boundary
00425     PRUint32 toCopy;
00426     do {
00427         toCopy = rowSize - mRowBytes;
00428         if (toCopy) {
00429             if (toCopy > aCount)
00430                 toCopy = aCount;
00431             memcpy(mRow + mRowBytes, aBuffer, toCopy);
00432             aCount -= toCopy;
00433             aBuffer += toCopy;
00434             mRowBytes += toCopy;
00435         }
00436         if (rowSize == mRowBytes) {
00437             mCurLine--;
00438             PRUint8* decoded = mDecodedBuffer + (mCurLine * mDirEntry.mWidth * GFXBYTESPERPIXEL);
00439             PRUint8* p = mRow;
00440             PRUint8* d = decoded;
00441             PRUint8* alphaPos = alphaRow; // only used if bpp == 32
00442             PRUint32 lpos = mDirEntry.mWidth;
00443             switch (mBIH.bpp) {
00444               case 1:
00445                 while (lpos > 0) {
00446                   PRInt8 bit;
00447                   PRUint8 idx;
00448                   for (bit = 7; bit >= 0 && lpos > 0; bit--) {
00449                       idx = (*p >> bit) & 1;
00450                       SetPixel(d, idx, mColors);
00451                       --lpos;
00452                   }
00453                   ++p;
00454                 }
00455                 break;
00456               case 4:
00457                 while (lpos > 0) {
00458                   Set4BitPixel(d, *p, lpos, mColors);
00459                   ++p;
00460                 }
00461                 break;
00462               case 8:
00463                 while (lpos > 0) {
00464                   SetPixel(d, *p, mColors);
00465                   --lpos;
00466                   ++p;
00467                 }
00468                 break;
00469               case 16:
00470                 while (lpos > 0) {
00471                   SetPixel(d,
00472                           (p[1] & 124) << 1,
00473                           ((p[1] & 3) << 6) | ((p[0] & 224) >> 2),
00474                           (p[0] & 31) << 3);
00475 
00476                   --lpos;
00477                   p+=2;
00478                 }
00479                 break;
00480               case 32:
00481               case 24:
00482                 while (lpos > 0) {
00483                   SetPixel(d, p[2], p[1], p[0]);
00484                   p += 3;
00485                   --lpos;
00486                   if (mBIH.bpp == 32)
00487                     mHaveAlphaData |= *alphaPos++ = *p++; // Alpha value
00488                 }
00489                 break;
00490               default:
00491                 // This is probably the wrong place to check this...
00492                 return NS_ERROR_FAILURE;
00493             }
00494 
00495             if (mCurLine == 0)
00496               mDecodingAndMask = PR_TRUE;
00497               
00498             mRowBytes = 0;
00499 
00500             // If 32 bit image, gotta set the alpha data here
00501             if (mBIH.bpp == 32)
00502               mFrame->SetAlphaData(alphaRow, alphaRowSize, mCurLine * alphaRowSize);
00503         }
00504     } while (!mDecodingAndMask && aCount > 0);
00505 
00506   }
00507 
00508   if (mDecodingAndMask && !mHaveAlphaData) {
00509     PRUint32 rowSize = CalcAlphaRowSize();
00510 
00511     if (mPos == (1 + mImageOffset + BITMAPINFOSIZE + mNumColors*4)) {
00512       mPos++;
00513       mRowBytes = 0;
00514       mCurLine = mDirEntry.mHeight;
00515       free(mRow);
00516       mRow = (PRUint8*)malloc(rowSize);
00517       if (!mRow)
00518         return NS_ERROR_OUT_OF_MEMORY;
00519       mAlphaBuffer = (PRUint8*)malloc(mDirEntry.mHeight*rowSize);
00520       if (!mAlphaBuffer)
00521         return NS_ERROR_OUT_OF_MEMORY;
00522       memset(mAlphaBuffer, 0xff, mDirEntry.mHeight*rowSize);
00523     }
00524 
00525     // Ensure memory has been allocated before decoding.
00526     NS_ASSERTION(mRow, "mRow is null");
00527     NS_ASSERTION(mAlphaBuffer, "mAlphaBuffer is null");
00528     if (!mRow || !mAlphaBuffer)
00529       return NS_ERROR_FAILURE;
00530 
00531     PRUint32 toCopy;
00532     do {
00533         if (mCurLine == 0) {
00534           return NS_OK;
00535         }
00536 
00537         toCopy = rowSize - mRowBytes;
00538         if (toCopy) {
00539             if (toCopy > aCount)
00540                 toCopy = aCount;
00541             memcpy(mRow + mRowBytes, aBuffer, toCopy);
00542             aCount -= toCopy;
00543             aBuffer += toCopy;
00544             mRowBytes += toCopy;
00545         }
00546         if ((rowSize - mRowBytes) == 0) {
00547             mCurLine--;
00548             PRUint8* decoded = mAlphaBuffer+(mCurLine*rowSize);
00549             PRUint8* p = mRow;
00550             PRUint32 lpos = 0;
00551             while (lpos < rowSize) {
00552               PRUint8 idx = *p;
00553               idx ^= 255;  // We complement the value, since our method of storing transparency is opposite
00554                            // what Win32 uses in its masks.
00555               decoded[lpos] = idx;
00556               lpos++;
00557               p++;
00558             }
00559             
00560             mRowBytes = 0;
00561         }
00562     } while (aCount > 0);
00563   }
00564 
00565   return NS_OK;
00566 }
00567 
00568 void
00569 nsICODecoder::ProcessDirEntry(IconDirEntry& aTarget)
00570 {
00571   memset(&aTarget, 0, sizeof(aTarget));
00572   memcpy(&aTarget.mWidth, mDirEntryArray, sizeof(aTarget.mWidth));
00573   memcpy(&aTarget.mHeight, mDirEntryArray+1, sizeof(aTarget.mHeight));
00574   memcpy(&aTarget.mColorCount, mDirEntryArray+2, sizeof(aTarget.mColorCount));
00575   memcpy(&aTarget.mReserved, mDirEntryArray+3, sizeof(aTarget.mReserved));
00576   
00577   memcpy(&aTarget.mPlanes, mDirEntryArray+4, sizeof(aTarget.mPlanes));
00578   aTarget.mPlanes = LITTLE_TO_NATIVE16(aTarget.mPlanes);
00579 
00580   memcpy(&aTarget.mBitCount, mDirEntryArray+6, sizeof(aTarget.mBitCount));
00581   aTarget.mBitCount = LITTLE_TO_NATIVE16(aTarget.mBitCount);
00582 
00583   memcpy(&aTarget.mBytesInRes, mDirEntryArray+8, sizeof(aTarget.mBytesInRes));
00584   aTarget.mBytesInRes = LITTLE_TO_NATIVE32(aTarget.mBytesInRes);
00585 
00586   memcpy(&aTarget.mImageOffset, mDirEntryArray+12, sizeof(aTarget.mImageOffset));
00587   aTarget.mImageOffset = LITTLE_TO_NATIVE32(aTarget.mImageOffset);
00588 }
00589 
00590 void nsICODecoder::ProcessInfoHeader() {
00591   memset(&mBIH, 0, sizeof(mBIH));
00592   // Ignoring the size; it should always be 40 for icons, anyway
00593 
00594   memcpy(&mBIH.width, mBIHraw + 4, sizeof(mBIH.width));
00595   memcpy(&mBIH.height, mBIHraw + 8, sizeof(mBIH.height));
00596   memcpy(&mBIH.planes, mBIHraw + 12, sizeof(mBIH.planes));
00597   memcpy(&mBIH.bpp, mBIHraw + 14, sizeof(mBIH.bpp));
00598   memcpy(&mBIH.compression, mBIHraw + 16, sizeof(mBIH.compression));
00599   memcpy(&mBIH.image_size, mBIHraw + 20, sizeof(mBIH.image_size));
00600   memcpy(&mBIH.xppm, mBIHraw + 24, sizeof(mBIH.xppm));
00601   memcpy(&mBIH.yppm, mBIHraw + 28, sizeof(mBIH.yppm));
00602   memcpy(&mBIH.colors, mBIHraw + 32, sizeof(mBIH.colors));
00603   memcpy(&mBIH.important_colors, mBIHraw + 36, sizeof(mBIH.important_colors));
00604 
00605   // Convert endianness
00606   mBIH.width = LITTLE_TO_NATIVE32(mBIH.width);
00607   mBIH.height = LITTLE_TO_NATIVE32(mBIH.height);
00608   mBIH.planes = LITTLE_TO_NATIVE16(mBIH.planes);
00609   mBIH.bpp = LITTLE_TO_NATIVE16(mBIH.bpp);
00610 
00611   mBIH.compression = LITTLE_TO_NATIVE32(mBIH.compression);
00612   mBIH.image_size = LITTLE_TO_NATIVE32(mBIH.image_size);
00613   mBIH.xppm = LITTLE_TO_NATIVE32(mBIH.xppm);
00614   mBIH.yppm = LITTLE_TO_NATIVE32(mBIH.yppm);
00615   mBIH.colors = LITTLE_TO_NATIVE32(mBIH.colors);
00616   mBIH.important_colors = LITTLE_TO_NATIVE32(mBIH.important_colors);
00617 }
00618