decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr,
decoder->mImageFrame->SetImageData(decoder->mRGBLine,
int HaveDecodedRow(  void* aClientData,  PRUint8* aRowBufPtr,   // Pointer to single scanline temporary buffer  PRUint8* aRGBrowBufPtr,// Pointer to temporary storage for dithering/mapping  int aXOffset,          // With respect to GIF logical screen origin  int aLength,           // Length of the row?  int aRowNumber,        // Row number?  int aDuplicateCount,   // Number of times to duplicate the row?  PRUint8 aDrawMode,     // il_draw_mode  int aInterlacePass)    // interlace pass (1-4){  nsGIFDecoder2* decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);  PRUint32 bpr, abpr;  // We have to delay allocation of the image frame until now because  // we won't have control block info (transparency) until now. The conrol  // block of a GIF stream shows up after the image header since transparency  // is added in GIF89a and control blocks are how the extensions are done.  // How annoying.  if(! decoder->mImageFrame) {    gfx_format format = gfxIFormats::RGB;    if (decoder->mGIFStruct->is_transparent) {      format = gfxIFormats::RGB_A1;    }#if defined(XP_PC) || defined(XP_BEOS)    // XXX this works...    format += 1; // RGB to BGR#endif    // initalize the frame and append it to the container    decoder->mImageFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");    decoder->mImageFrame->Init(      decoder->mGIFStruct->x_offset, decoder->mGIFStruct->y_offset,       decoder->mGIFStruct->width, decoder->mGIFStruct->height, format);    decoder->mImageContainer->AppendFrame(decoder->mImageFrame);    if (decoder->mObserver)      decoder->mObserver->OnStartFrame(nsnull, nsnull, decoder->mImageFrame);    decoder->mImageFrame->GetImageBytesPerRow(&bpr);    decoder->mImageFrame->GetAlphaBytesPerRow(&abpr);    if (format == gfxIFormats::RGB_A1 || format == gfxIFormats::BGR_A1) {      if (decoder->mAlphaLine)        nsMemory::Free(decoder->mAlphaLine);      decoder->mAlphaLine = (PRUint8 *)nsMemory::Alloc(abpr);    }  } else {    decoder->mImageFrame->GetImageBytesPerRow(&bpr);    decoder->mImageFrame->GetAlphaBytesPerRow(&abpr);  }    if (aRowBufPtr) {    nscoord width;    decoder->mImageFrame->GetWidth(&width);    PRUint32 iwidth = width;    gfx_format format;    decoder->mImageFrame->GetFormat(&format);    // XXX map the data into colors    int cmapsize;    GIF_RGB* cmap;    cmapsize = decoder->mGIFStruct->global_colormap_size;    cmap = decoder->mGIFStruct->global_colormap;    if(decoder->mGIFStruct->global_colormap &&       decoder->mGIFStruct->screen_bgcolor < cmapsize) {      gfx_color bgColor = 0;      bgColor |= cmap[decoder->mGIFStruct->screen_bgcolor].red;      bgColor |= cmap[decoder->mGIFStruct->screen_bgcolor].green << 8;      bgColor |= cmap[decoder->mGIFStruct->screen_bgcolor].blue << 16;      decoder->mImageFrame->SetBackgroundColor(bgColor);    }    if(decoder->mGIFStruct->local_colormap) {      cmapsize = decoder->mGIFStruct->local_colormap_size;      cmap = decoder->mGIFStruct->local_colormap;    }    PRUint8* rgbRowIndex = aRGBrowBufPtr;    PRUint8* rowBufIndex = aRowBufPtr;            switch (format) {    case gfxIFormats::RGB:      {        while(rowBufIndex != decoder->mGIFStruct->rowend) {#ifdef XP_MAC          *rgbRowIndex++ = 0; // Mac is always 32bits per pixel, this is pad#endif          *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;          *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;          *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;          ++rowBufIndex;        }        for (int i=0; i<aDuplicateCount; i++)          decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr,                                             bpr, (aRowNumber+i)*bpr);      }      break;    case gfxIFormats::BGR:      {        while(rowBufIndex != decoder->mGIFStruct->rowend) {          *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;          *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;          *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;          ++rowBufIndex;        }        for (int i=0; i<aDuplicateCount; i++)          decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr,                                             bpr, (aRowNumber+i)*bpr);      }      break;    case gfxIFormats::RGB_A1:    case gfxIFormats::BGR_A1:      {        if (decoder->mGIFStruct->is_transparent) {          gfx_color transColor = 0;            transColor |= cmap[decoder->mGIFStruct->tpixel].red;            transColor |= cmap[decoder->mGIFStruct->tpixel].green << 8;            transColor |= cmap[decoder->mGIFStruct->tpixel].blue << 16;            decoder->mImageFrame->SetTransparentColor(transColor);        }        memset(aRGBrowBufPtr, 0, bpr);        memset(decoder->mAlphaLine, 0, abpr);        PRUint32 iwidth = (PRUint32)width;        for (PRUint32 x=0; x<iwidth; x++) {          if (*rowBufIndex != decoder->mGIFStruct->tpixel) {#if defined(XP_PC) || defined(XP_BEOS)            *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;            *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;            *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;#else#ifdef XP_MAC          *rgbRowIndex++ = 0; // Mac is always 32bits per pixel, this is pad#endif            *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;            *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;            *rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;#endif            decoder->mAlphaLine[x>>3] |= 1<<(7-x&0x7);          } else {#ifdef XP_MAC            rgbRowIndex+=4;#else            rgbRowIndex+=3;#endif          }          ++rowBufIndex;        }        for (int i=0; i<aDuplicateCount; i++) {          decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr,                                             bpr, (aRowNumber+i)*bpr);          decoder->mImageFrame->SetAlphaData(decoder->mAlphaLine,                                             abpr, (aRowNumber+i)*abpr);        }      }      break;    default:      break;    }    decoder->mCurrentRow = aRowNumber+aDuplicateCount-1;    decoder->mCurrentPass = aInterlacePass;    if (aInterlacePass == 1)      decoder->mLastFlushedPass = aInterlacePass;   // interlaced starts at 1  }  return 0;}