nsresult nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements) { mWidth = aWidth; mHeight = aHeight; // Reject over-wide or over-tall images. if (!AllowedImageSize(aWidth, aHeight)) return NS_ERROR_FAILURE; gfxImageSurface::gfxImageFormat format; switch(aMaskRequirements) { case nsMaskRequirements_kNeeds1Bit: format = gfxImageSurface::ImageFormatARGB32; mAlphaDepth = 1; break; case nsMaskRequirements_kNeeds8Bit: format = gfxImageSurface::ImageFormatARGB32; mAlphaDepth = 8; break; default: format = gfxImageSurface::ImageFormatRGB24; mAlphaDepth = 0; break; } mFormat = format; #ifdef XP_WIN if (!ShouldUseImageSurfaces()) { mWinSurface = new gfxWindowsSurface(gfxIntSize(mWidth, mHeight), format); if (mWinSurface && mWinSurface->CairoStatus() == 0) { // no error mImageSurface = mWinSurface->GetImageSurface(); } } if (!mImageSurface) mWinSurface = nsnull; #endif if (!mImageSurface) mImageSurface = new gfxImageSurface(gfxIntSize(mWidth, mHeight), format); if (!mImageSurface || mImageSurface->CairoStatus()) { mImageSurface = nsnull; // guess return NS_ERROR_OUT_OF_MEMORY; } #ifdef XP_MACOSX mQuartzSurface = new gfxQuartzImageSurface(mImageSurface); #endif mStride = mImageSurface->Stride(); return NS_OK; }
nsresult imgFrame::Optimize() { if (gDisableOptimize) return NS_OK; if (mPalettedImageData || mOptSurface || mSinglePixel) return NS_OK; /* Figure out if the entire image is a constant color */ // this should always be true if (mImageSurface->Stride() == mSize.width * 4) { PRUint32 *imgData = (PRUint32*) mImageSurface->Data(); PRUint32 firstPixel = * (PRUint32*) imgData; PRUint32 pixelCount = mSize.width * mSize.height + 1; while (--pixelCount && *imgData++ == firstPixel) ; if (pixelCount == 0) { // all pixels were the same if (mFormat == gfxASurface::ImageFormatARGB32 || mFormat == gfxASurface::ImageFormatRGB24) { mSinglePixelColor = gfxRGBA (firstPixel, (mFormat == gfxImageSurface::ImageFormatRGB24 ? gfxRGBA::PACKED_XRGB : gfxRGBA::PACKED_ARGB_PREMULTIPLIED)); mSinglePixel = PR_TRUE; // blow away the older surfaces (if they exist), to release their memory mImageSurface = nsnull; mOptSurface = nsnull; #ifdef USE_WIN_SURFACE mWinSurface = nsnull; #endif #ifdef XP_MACOSX mQuartzSurface = nsnull; #endif return NS_OK; } } // if it's not RGB24/ARGB32, don't optimize, but we never hit this at the moment } // if we're being forced to use image surfaces due to // resource constraints, don't try to optimize beyond same-pixel. if (mNeverUseDeviceSurface || ShouldUseImageSurfaces()) return NS_OK; mOptSurface = nsnull; #ifdef USE_WIN_SURFACE // we need to special-case windows here, because windows has // a distinction between DIB and DDB and we want to use DDBs as much // as we can. if (mWinSurface) { // Don't do DDBs for large images; see bug 359147 // Note that we bother with DDBs at all because they are much faster // on some systems; on others there isn't much of a speed difference // between DIBs and DDBs. // // Originally this just limited to 1024x1024; but that still // had us hitting overall total memory usage limits (which was // around 220MB on my intel shared memory system with 2GB RAM // and 16-128mb in use by the video card, so I can't make // heads or tails out of this limit). // // So instead, we clamp the max size to 64MB (this limit shuld // be made dynamic based on.. something.. as soon a we figure // out that something) and also limit each individual image to // be less than 4MB to keep very large images out of DDBs. // assume (almost -- we don't quadword-align) worst-case size PRUint32 ddbSize = mSize.width * mSize.height * 4; if (ddbSize <= kMaxSingleDDBSize && ddbSize + gTotalDDBSize <= kMaxDDBSize) { nsRefPtr<gfxWindowsSurface> wsurf = mWinSurface->OptimizeToDDB(nsnull, gfxIntSize(mSize.width, mSize.height), mFormat); if (wsurf) { gTotalDDBs++; gTotalDDBSize += ddbSize; mIsDDBSurface = PR_TRUE; mOptSurface = wsurf; } } if (!mOptSurface && !mFormatChanged) { // just use the DIB if the format has not changed mOptSurface = mWinSurface; } } #endif #ifdef XP_MACOSX if (mQuartzSurface) { mQuartzSurface->Flush(); mOptSurface = mQuartzSurface; } #endif if (mOptSurface == nsnull) mOptSurface = gfxPlatform::GetPlatform()->OptimizeImage(mImageSurface, mFormat); if (mOptSurface) { mImageSurface = nsnull; #ifdef USE_WIN_SURFACE mWinSurface = nsnull; #endif #ifdef XP_MACOSX mQuartzSurface = nsnull; #endif } return NS_OK; }
nsresult imgFrame::Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, gfxASurface::gfxImageFormat aFormat, PRUint8 aPaletteDepth /* = 0 */) { // assert for properties that should be verified by decoders, warn for properties related to bad content if (!AllowedImageSize(aWidth, aHeight)) return NS_ERROR_FAILURE; mOffset.MoveTo(aX, aY); mSize.SizeTo(aWidth, aHeight); mFormat = aFormat; mPaletteDepth = aPaletteDepth; if (aPaletteDepth != 0) { // We're creating for a paletted image. if (aPaletteDepth > 8) { NS_ERROR("This Depth is not supported"); return NS_ERROR_FAILURE; } // Use the fallible allocator here mPalettedImageData = (PRUint8*)moz_malloc(PaletteDataLength() + GetImageDataLength()); NS_ENSURE_TRUE(mPalettedImageData, NS_ERROR_OUT_OF_MEMORY); } else { // For Windows, we must create the device surface first (if we're // going to) so that the image surface can wrap it. Can't be done // the other way around. #ifdef USE_WIN_SURFACE if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) { mWinSurface = new gfxWindowsSurface(gfxIntSize(mSize.width, mSize.height), mFormat); if (mWinSurface && mWinSurface->CairoStatus() == 0) { // no error mImageSurface = mWinSurface->GetAsImageSurface(); } else { mWinSurface = nsnull; } } #endif // For other platforms we create the image surface first and then // possibly wrap it in a device surface. This branch is also used // on Windows if we're not using device surfaces or if we couldn't // create one. if (!mImageSurface) mImageSurface = new gfxImageSurface(gfxIntSize(mSize.width, mSize.height), mFormat); if (!mImageSurface || mImageSurface->CairoStatus()) { mImageSurface = nsnull; // guess return NS_ERROR_OUT_OF_MEMORY; } #ifdef XP_MACOSX if (!mNeverUseDeviceSurface && !ShouldUseImageSurfaces()) { mQuartzSurface = new gfxQuartzImageSurface(mImageSurface); } #endif } return NS_OK; }