зеркало из https://github.com/mozilla/gecko-dev.git
Fix bugs 57327 and 57835; convert nsImageMac to use PixMaps rather than GWorlds to reduce memory usage, and reduce changes of allocation failure.
This commit is contained in:
Родитель
58b1fc8673
Коммит
0d9777963a
|
@ -160,5 +160,36 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
/** ------------------------------------------------------------
|
||||
* Utility class for saving, locking, and restoring handle state
|
||||
* Ok with null handle
|
||||
*/
|
||||
|
||||
class StHandleLocker
|
||||
{
|
||||
public:
|
||||
|
||||
StHandleLocker(Handle theHandle)
|
||||
: mHandle(theHandle)
|
||||
{
|
||||
if (mHandle)
|
||||
{
|
||||
mOldHandleState = ::HGetState(mHandle);
|
||||
::HLock(mHandle);
|
||||
}
|
||||
}
|
||||
|
||||
~StHandleLocker()
|
||||
{
|
||||
if (mHandle)
|
||||
::HSetState(mHandle, mOldHandleState);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Handle mHandle;
|
||||
SInt8 mOldHandleState;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsGfxUtils_h_
|
||||
|
|
|
@ -40,23 +40,27 @@ static NS_DEFINE_IID(kIImageIID, NS_IIMAGE_IID);
|
|||
* @update
|
||||
*/
|
||||
nsImageMac::nsImageMac()
|
||||
: mImageGWorld(nsnull)
|
||||
: mImageBitsHandle(nsnull)
|
||||
, mWidth(0)
|
||||
, mHeight(0)
|
||||
, mRowBytes(0)
|
||||
, mBytesPerPixel(0)
|
||||
, mAlphaGWorld(nsnull)
|
||||
, mMaskBitsHandle(nsnull)
|
||||
, mAlphaDepth(0)
|
||||
, mAlphaWidth(0)
|
||||
, mAlphaHeight(0)
|
||||
, mARowBytes(0)
|
||||
, mIsTopToBottom(PR_TRUE)
|
||||
, mPixelDataSize(0)
|
||||
, mNaturalWidth(0)
|
||||
, mNaturalHeight(0)
|
||||
, mNaturalWidth(0)
|
||||
, mNaturalHeight(0)
|
||||
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
::memset(&mImagePixmap, 0, sizeof(PixMap));
|
||||
::memset(&mMaskPixmap, 0, sizeof(PixMap));
|
||||
|
||||
}
|
||||
|
||||
/** ---------------------------------------------------
|
||||
|
@ -65,11 +69,22 @@ nsImageMac::nsImageMac()
|
|||
*/
|
||||
nsImageMac::~nsImageMac()
|
||||
{
|
||||
if (mImageGWorld)
|
||||
::DisposeGWorld(mImageGWorld);
|
||||
if (mImageBitsHandle)
|
||||
::DisposeHandle(mImageBitsHandle);
|
||||
|
||||
if (mAlphaGWorld)
|
||||
::DisposeGWorld(mAlphaGWorld);
|
||||
if (mMaskBitsHandle)
|
||||
::DisposeHandle(mMaskBitsHandle);
|
||||
|
||||
// dispose of the color tables if we have them
|
||||
if (mImagePixmap.pmTable)
|
||||
{
|
||||
::DisposeCTable(mImagePixmap.pmTable);
|
||||
}
|
||||
|
||||
if (mMaskPixmap.pmTable)
|
||||
{
|
||||
::DisposeCTable(mMaskPixmap.pmTable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -82,23 +97,19 @@ NS_IMPL_ISUPPORTS(nsImageMac, kIImageIID);
|
|||
PRUint8*
|
||||
nsImageMac::GetBits()
|
||||
{
|
||||
if (!mImageGWorld)
|
||||
if (!mImageBitsHandle)
|
||||
{
|
||||
NS_ASSERTION(0, "Getting bits for non-existent image");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PixMapHandle thePixMap = ::GetGWorldPixMap(mImageGWorld);
|
||||
|
||||
// pixels should be locked here!
|
||||
#if DEBUG
|
||||
GWorldFlags pixelFlags = GetPixelsState(thePixMap);
|
||||
NS_ASSERTION(pixelFlags & pixelsLocked, "Pixels must be locked here");
|
||||
SInt8 pixelFlags = HGetState(mImageBitsHandle);
|
||||
NS_ASSERTION(pixelFlags & (1 << 7), "Pixels must be locked here");
|
||||
#endif
|
||||
|
||||
Ptr pixels = ::GetPixBaseAddr(thePixMap);
|
||||
NS_ASSERTION(pixels, "Getting bits for image failed");
|
||||
return (PRUint8 *)pixels;
|
||||
return (PRUint8 *)*mImageBitsHandle;
|
||||
}
|
||||
|
||||
|
||||
|
@ -109,23 +120,19 @@ nsImageMac::GetBits()
|
|||
PRUint8*
|
||||
nsImageMac::GetAlphaBits()
|
||||
{
|
||||
if (!mAlphaGWorld)
|
||||
if (!mMaskBitsHandle)
|
||||
{
|
||||
NS_ASSERTION(0, "Getting alpha bits for non-existent mask");
|
||||
NS_ASSERTION(0, "Getting bits for non-existent image");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PixMapHandle thePixMap = GetGWorldPixMap(mAlphaGWorld);
|
||||
|
||||
// pixels should be locked here!
|
||||
#if DEBUG
|
||||
GWorldFlags pixelFlags = GetPixelsState(thePixMap);
|
||||
NS_ASSERTION(pixelFlags & pixelsLocked, "Pixels must be locked here");
|
||||
SInt8 pixelFlags = HGetState(mMaskBitsHandle);
|
||||
NS_ASSERTION(pixelFlags & (1 << 7), "Pixels must be locked here");
|
||||
#endif
|
||||
|
||||
Ptr pixels = GetPixBaseAddr(thePixMap);
|
||||
NS_ASSERTION(pixels, "Getting alpha bits failed");
|
||||
return (PRUint8 *)pixels;
|
||||
|
||||
return (PRUint8 *)*mMaskBitsHandle;
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,13 +143,20 @@ nsImageMac::GetAlphaBits()
|
|||
nsresult
|
||||
nsImageMac::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements)
|
||||
{
|
||||
|
||||
OSErr err = noErr;
|
||||
|
||||
// have we already been initted?
|
||||
if (mImageGWorld)
|
||||
if (mImageBitsHandle)
|
||||
{
|
||||
NS_ASSERTION(0, "Initting image twice");
|
||||
::DisposeGWorld(mImageGWorld);
|
||||
mImageGWorld = nsnull;
|
||||
|
||||
::DisposeHandle(mImageBitsHandle);
|
||||
mImageBitsHandle = nsnull;
|
||||
|
||||
if (mMaskBitsHandle) {
|
||||
::DisposeHandle(mMaskBitsHandle);
|
||||
mMaskBitsHandle = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
mWidth = aWidth;
|
||||
|
@ -151,106 +165,52 @@ nsImageMac::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirem
|
|||
SetNaturalWidth(0);
|
||||
SetNaturalHeight(0);
|
||||
|
||||
PRInt16 bufferdepth;
|
||||
err = CreatePixMap(aWidth, aHeight, aDepth, nsnull, mImagePixmap, mImageBitsHandle);
|
||||
if (err != noErr)
|
||||
{
|
||||
if (err == memFullErr)
|
||||
nsMemory::HeapMinimize(PR_FALSE);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
switch(aDepth)
|
||||
{
|
||||
case 8:
|
||||
//mThePixelmap.pmTable = ::GetCTable(8);
|
||||
bufferdepth = 8;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
bufferdepth = 16;
|
||||
break;
|
||||
|
||||
case 24: // 24 and 32 bit are basically the same
|
||||
case 32:
|
||||
bufferdepth = 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_NOTREACHED("Unexpected buffer depth");
|
||||
bufferdepth = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// allocate the GWorld
|
||||
Rect bounds = {0, 0, 0, 0};
|
||||
bounds.right = aWidth;
|
||||
bounds.bottom = aHeight;
|
||||
|
||||
OSErr err = AllocateGWorld(bufferdepth, nsnull, bounds, &mImageGWorld);
|
||||
if (err != noErr)
|
||||
{
|
||||
NS_WARNING("GWorld allocation failed");
|
||||
nsMemory::HeapMinimize(PR_FALSE);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
//ClearGWorld(mImageGWorld);
|
||||
|
||||
// calculate the pixel data size
|
||||
PixMapHandle thePixMap = ::GetGWorldPixMap(mImageGWorld);
|
||||
|
||||
mRowBytes = (**thePixMap).rowBytes & 0x3FFF;
|
||||
mPixelDataSize = mRowBytes * aHeight;
|
||||
mBytesPerPixel = (**thePixMap).cmpCount;
|
||||
|
||||
mRowBytes = mImagePixmap.rowBytes & 0x3FFF; // we only set the top bit, but QuickDraw can use the top 2 bits
|
||||
|
||||
if (aMaskRequirements != nsMaskRequirements_kNoMask)
|
||||
{
|
||||
PRInt16 mAlphaDepth = 0;
|
||||
CTabHandle grayRamp = nsnull;
|
||||
PRInt16 mAlphaDepth = 0;
|
||||
|
||||
switch (aMaskRequirements)
|
||||
{
|
||||
case nsMaskRequirements_kNeeds1Bit:
|
||||
mAlphaDepth = 1;
|
||||
err = AllocateGWorld(mAlphaDepth, nsnull, bounds, &mAlphaGWorld);
|
||||
if (err != noErr)
|
||||
{
|
||||
nsMemory::HeapMinimize(PR_FALSE);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
break;
|
||||
|
||||
case nsMaskRequirements_kNeeds8Bit:
|
||||
{
|
||||
mAlphaDepth = 8;
|
||||
|
||||
// make 8-bit grayscale color table
|
||||
CTabHandle grayRamp = nsnull;
|
||||
/*
|
||||
err = MakeGrayscaleColorTable(256, &grayRamp);
|
||||
if (err != noErr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
err = AllocateGWorld(mAlphaDepth, grayRamp, bounds, &mAlphaGWorld);
|
||||
if (err != noErr)
|
||||
{
|
||||
nsMemory::HeapMinimize(PR_FALSE);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
::DisposeHandle((Handle)grayRamp);
|
||||
*/
|
||||
mAlphaDepth = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NS_NOTREACHED("Uknown mask depth");
|
||||
break;
|
||||
}
|
||||
|
||||
if (mAlphaGWorld)
|
||||
{
|
||||
//ClearGWorld(mAlphaGWorld);
|
||||
err = CreatePixMap(aWidth, aHeight, mAlphaDepth, grayRamp, mMaskPixmap, mMaskBitsHandle);
|
||||
if (err != noErr)
|
||||
{
|
||||
if (err == memFullErr)
|
||||
nsMemory::HeapMinimize(PR_FALSE);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// calculate the pixel data size
|
||||
PixMapHandle maskPixMap = GetGWorldPixMap(mAlphaGWorld);
|
||||
|
||||
mARowBytes = (**maskPixMap).rowBytes & 0x3FFF;
|
||||
mAlphaWidth = aWidth;
|
||||
mAlphaHeight = aHeight;
|
||||
}
|
||||
mARowBytes = mMaskPixmap.rowBytes & 0x3FFF; // we only set the top bit, but QuickDraw can use the top 2 bits
|
||||
mAlphaWidth = aWidth;
|
||||
mAlphaHeight = aHeight;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -273,19 +233,25 @@ void nsImageMac::ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect
|
|||
NS_IMETHODIMP nsImageMac::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSX, PRInt32 aSY,
|
||||
PRInt32 aSWidth, PRInt32 aSHeight, PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
|
||||
{
|
||||
PixMapHandle imagePixMap;
|
||||
Rect srcRect, dstRect, maskRect;
|
||||
|
||||
if (!mImageGWorld)
|
||||
if (!mImageBitsHandle)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// lock and set up bits handles
|
||||
StHandleLocker imageBitsLocker(mImageBitsHandle);
|
||||
StHandleLocker maskBitsLocker(mMaskBitsHandle); // ok with nil handle
|
||||
|
||||
mImagePixmap.baseAddr = *mImageBitsHandle;
|
||||
if (mMaskBitsHandle)
|
||||
mMaskPixmap.baseAddr = *mMaskBitsHandle;
|
||||
|
||||
// currently the top is 0, this may change and this code will have to reflect that
|
||||
if (( mDecodedY2 < aSHeight) ) {
|
||||
// adjust the source and dest height to reflect this
|
||||
aDHeight = float(mDecodedY2/float(aSHeight)) * aDHeight;
|
||||
aSHeight = mDecodedY2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
::SetRect(&srcRect, aSX, aSY, aSX + aSWidth, aSY + aSHeight);
|
||||
maskRect = srcRect;
|
||||
|
@ -294,10 +260,6 @@ NS_IMETHODIMP nsImageMac::Draw(nsIRenderingContext &aContext, nsDrawingSurface a
|
|||
::ForeColor(blackColor);
|
||||
::BackColor(whiteColor);
|
||||
|
||||
imagePixMap = GetGWorldPixMap(mImageGWorld);
|
||||
|
||||
StPixelLocker pixelLocker(imagePixMap); // locks the pixels
|
||||
|
||||
// get the destination pix map
|
||||
nsDrawingSurfaceMac* surface = static_cast<nsDrawingSurfaceMac*>(aSurface);
|
||||
CGrafPtr destPort;
|
||||
|
@ -312,9 +274,9 @@ NS_IMETHODIMP nsImageMac::Draw(nsIRenderingContext &aContext, nsDrawingSurface a
|
|||
aContext.GetDeviceContext(*getter_AddRefs(theDevContext));
|
||||
if (theDevContext->IsPrinter()) // we are printing
|
||||
{
|
||||
if (!mAlphaGWorld)
|
||||
if (!mMaskBitsHandle)
|
||||
{
|
||||
::CopyBits((BitMap*)*imagePixMap, (BitMap*)*destPixels, &srcRect, &dstRect, srcCopy, nsnull);
|
||||
::CopyBits((BitMap*)&mImagePixmap, (BitMap*)*destPixels, &srcRect, &dstRect, srcCopy, nsnull);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -323,7 +285,9 @@ NS_IMETHODIMP nsImageMac::Draw(nsIRenderingContext &aContext, nsDrawingSurface a
|
|||
// if we have a mask, blit the transparent image into a new GWorld which is
|
||||
// just white, and print that. This is marginally better than printing the
|
||||
// image directly, since the transparent pixels come out black.
|
||||
if (AllocateGWorld((**imagePixMap).packSize, nsnull, srcRect, &tempGWorld) == noErr)
|
||||
|
||||
// We do all this because Copy{Deep}Mask is not supported when printing
|
||||
if (AllocateGWorld(mImagePixmap.packSize, nsnull, srcRect, &tempGWorld) == noErr)
|
||||
{
|
||||
// erase it to white
|
||||
ClearGWorld(tempGWorld);
|
||||
|
@ -337,13 +301,10 @@ NS_IMETHODIMP nsImageMac::Draw(nsIRenderingContext &aContext, nsDrawingSurface a
|
|||
// for some reason this copies garbage, so we erase to white above instead.
|
||||
// ::CopyBits((BitMap*)*destPixels, (BitMap*)*tempPixMap, &dstRect, &srcRect, srcCopy, nsnull);
|
||||
|
||||
PixMapHandle maskPixMap = GetGWorldPixMap(mAlphaGWorld);
|
||||
StPixelLocker maskLocker(maskPixMap);
|
||||
|
||||
if (mAlphaDepth > 1)
|
||||
::CopyDeepMask((BitMap*)*imagePixMap, (BitMap*)*maskPixMap, (BitMap*)*tempPixMap, &srcRect, &maskRect, &srcRect, srcCopy, nsnull);
|
||||
::CopyDeepMask((BitMap*)&mImagePixmap, (BitMap*)&mMaskPixmap, (BitMap*)*tempPixMap, &srcRect, &maskRect, &srcRect, srcCopy, nsnull);
|
||||
else
|
||||
::CopyMask((BitMap*)*imagePixMap, (BitMap*)*maskPixMap, (BitMap*)*tempPixMap, &srcRect, &maskRect, &srcRect);
|
||||
::CopyMask((BitMap*)&mImagePixmap, (BitMap*)&mMaskPixmap, (BitMap*)*tempPixMap, &srcRect, &maskRect, &srcRect);
|
||||
|
||||
// now copy to the screen
|
||||
::CopyBits((BitMap*)*tempPixMap, (BitMap*)*destPixels, &srcRect, &dstRect, srcCopy, nsnull);
|
||||
|
@ -355,19 +316,16 @@ NS_IMETHODIMP nsImageMac::Draw(nsIRenderingContext &aContext, nsDrawingSurface a
|
|||
}
|
||||
else // not printing
|
||||
{
|
||||
if (!mAlphaGWorld)
|
||||
if (!mMaskBitsHandle)
|
||||
{
|
||||
::CopyBits((BitMap*)*imagePixMap, (BitMap*)*destPixels, &srcRect, &dstRect, srcCopy, nsnull);
|
||||
::CopyBits((BitMap*)&mImagePixmap, (BitMap*)*destPixels, &srcRect, &dstRect, srcCopy, nsnull);
|
||||
}
|
||||
else
|
||||
{
|
||||
PixMapHandle maskPixMap = GetGWorldPixMap(mAlphaGWorld);
|
||||
StPixelLocker maskLocker(maskPixMap);
|
||||
|
||||
if (mAlphaDepth > 1)
|
||||
::CopyDeepMask((BitMap*)*imagePixMap, (BitMap*)*maskPixMap, (BitMap*)*destPixels, &srcRect, &maskRect, &dstRect, srcCopy, nsnull);
|
||||
::CopyDeepMask((BitMap*)&mImagePixmap, (BitMap*)&mMaskPixmap, (BitMap*)*destPixels, &srcRect, &maskRect, &dstRect, srcCopy, nsnull);
|
||||
else
|
||||
::CopyMask((BitMap*)*imagePixMap, (BitMap*)*maskPixMap, (BitMap*)*destPixels, &srcRect, &maskRect, &dstRect);
|
||||
::CopyMask((BitMap*)&mImagePixmap, (BitMap*)&mMaskPixmap, (BitMap*)*destPixels, &srcRect, &maskRect, &dstRect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,14 +385,14 @@ PRInt32 nsImageMac::GetAlphaLevel()
|
|||
NS_IMETHODIMP
|
||||
nsImageMac::LockImagePixels(PRBool aMaskPixels)
|
||||
{
|
||||
if (!mImageGWorld)
|
||||
if (!mImageBitsHandle)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (aMaskPixels && !mAlphaGWorld)
|
||||
if (aMaskPixels && !mMaskBitsHandle)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
PixMapHandle thePixMap = ::GetGWorldPixMap(aMaskPixels ? mAlphaGWorld : mImageGWorld);
|
||||
::LockPixels(thePixMap);
|
||||
Handle thePixelsHandle = (aMaskPixels ? mMaskBitsHandle : mImageBitsHandle);
|
||||
::HLock(thePixelsHandle);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -444,17 +402,178 @@ nsImageMac::LockImagePixels(PRBool aMaskPixels)
|
|||
NS_IMETHODIMP
|
||||
nsImageMac::UnlockImagePixels(PRBool aMaskPixels)
|
||||
{
|
||||
if (!mImageGWorld)
|
||||
if (!mImageBitsHandle)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (aMaskPixels && !mAlphaGWorld)
|
||||
if (aMaskPixels && !mMaskBitsHandle)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
PixMapHandle thePixMap = ::GetGWorldPixMap(aMaskPixels ? mAlphaGWorld : mImageGWorld);
|
||||
::UnlockPixels(thePixMap);
|
||||
|
||||
Handle thePixelsHandle = (aMaskPixels ? mMaskBitsHandle : mImageBitsHandle);
|
||||
::HUnlock(thePixelsHandle);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/** -----------------------------------------------------------------
|
||||
* Create a PixMap, filling in ioPixMap
|
||||
*/
|
||||
OSErr nsImageMac::CreatePixMap(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, CTabHandle aColorTable, PixMap& ioPixMap, Handle& ioBitsHandle)
|
||||
{
|
||||
PRInt16 bufferdepth;
|
||||
OSErr err = noErr;
|
||||
|
||||
ioPixMap.cmpCount = 0;
|
||||
|
||||
// See IM:QuickDraw pp 4-92 for GetCTable params
|
||||
switch(aDepth)
|
||||
{
|
||||
case 1:
|
||||
ioPixMap.pixelType = 0;
|
||||
ioPixMap.cmpCount = 1;
|
||||
ioPixMap.cmpSize = 1;
|
||||
ioPixMap.pmTable = aColorTable ? aColorTable : GetCTable(32 + 1); // default to black & white colortable
|
||||
bufferdepth = 1;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ioPixMap.pixelType = 0;
|
||||
ioPixMap.cmpCount = 1;
|
||||
ioPixMap.cmpSize = 8;
|
||||
ioPixMap.pmTable = aColorTable ? aColorTable : GetCTable(32 + 8); // default to gray ramp colortable
|
||||
bufferdepth = 8;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
ioPixMap.pixelType = RGBDirect;
|
||||
ioPixMap.cmpCount = 3;
|
||||
ioPixMap.cmpSize = 5;
|
||||
ioPixMap.pmTable = nsnull;
|
||||
bufferdepth = 16;
|
||||
break;
|
||||
|
||||
case 24: // 24 and 32 bit are basically the same
|
||||
case 32:
|
||||
ioPixMap.pixelType = RGBDirect;
|
||||
ioPixMap.cmpCount = 3;
|
||||
ioPixMap.cmpSize = 8;
|
||||
ioPixMap.pmTable = nsnull;
|
||||
bufferdepth = 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ASSERTION(0, "Unhandled image depth");
|
||||
return paramErr;
|
||||
}
|
||||
|
||||
if (ioPixMap.cmpCount)
|
||||
{
|
||||
PRInt32 imageSize;
|
||||
PRInt32 rowBytes = CalculateRowBytes(aWidth, bufferdepth);
|
||||
|
||||
if (rowBytes >= 0x4000)
|
||||
{
|
||||
NS_ASSERTION(0, "PixMap too big for QuickDraw");
|
||||
return paramErr;
|
||||
}
|
||||
|
||||
imageSize = rowBytes * aHeight;
|
||||
|
||||
err = AllocateBitsHandle(imageSize, &ioBitsHandle);
|
||||
if (err != noErr)
|
||||
return err;
|
||||
|
||||
ioPixMap.baseAddr = nsnull; // We can only set this after locking the pixels handle
|
||||
ioPixMap.rowBytes = rowBytes | 0x8000; // set the high bit to tell CopyBits that this is a PixMap
|
||||
ioPixMap.bounds.top = 0;
|
||||
ioPixMap.bounds.left = 0;
|
||||
ioPixMap.bounds.bottom = aHeight;
|
||||
ioPixMap.bounds.right = aWidth;
|
||||
ioPixMap.pixelSize = bufferdepth;
|
||||
ioPixMap.packType = 0;
|
||||
ioPixMap.packSize = 0;
|
||||
ioPixMap.hRes = nsDeviceContextMac::GetScreenResolution() << 16; // is this correct? printing?
|
||||
ioPixMap.vRes = nsDeviceContextMac::GetScreenResolution() << 16;
|
||||
#if TARGET_CARBON
|
||||
ioPixMap.pixelFormat = 0; /*fourCharCode representation*/
|
||||
ioPixMap.pmExt = 0;
|
||||
#else
|
||||
ioPixMap.planeBytes = 0;
|
||||
ioPixMap.pmReserved = 0;
|
||||
#endif
|
||||
ioPixMap.pmVersion = 0;
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/** -----------------------------------------------------------------
|
||||
* Allocate bits handle, trying first in the heap, and then in temp mem.
|
||||
*/
|
||||
OSErr nsImageMac::AllocateBitsHandle(PRInt32 imageSizeBytes, Handle *outHandle)
|
||||
{
|
||||
*outHandle = nsnull;
|
||||
|
||||
// We have to be careful here not to fill the heap. //
|
||||
// The strategy is this:
|
||||
// 1. If we have plenty of heap space free, allocate the GWorld in
|
||||
// the heap.
|
||||
//
|
||||
// 2. When below a certain threshold of free space in the heap,
|
||||
// allocate GWorlds in temp mem.
|
||||
//
|
||||
|
||||
// threshold at which we go to temp mem
|
||||
const long kUseTempMemFreeSpace = (1024 * 1024);
|
||||
const long kUseTempMemContigSpace = (768 * 1024);
|
||||
|
||||
long totalSpace, contiguousSpace;
|
||||
::PurgeSpace(&totalSpace, &contiguousSpace); // this does not purge memory!
|
||||
|
||||
if (totalSpace > kUseTempMemFreeSpace && contiguousSpace > kUseTempMemContigSpace)
|
||||
{
|
||||
*outHandle = ::NewHandleClear(imageSizeBytes);
|
||||
if (*outHandle) return noErr;
|
||||
}
|
||||
|
||||
OSErr err;
|
||||
*outHandle = ::TempNewHandle(imageSizeBytes, &err);
|
||||
if (! *outHandle)
|
||||
return memFullErr;
|
||||
|
||||
::BlockZero(**outHandle, imageSizeBytes);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
/** ---------------------------------------------------
|
||||
* Set the decoded dimens of the image
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsImageMac::SetDecodedRect(PRInt32 x1, PRInt32 y1, PRInt32 x2, PRInt32 y2 )
|
||||
{
|
||||
|
||||
mDecodedX1 = x1;
|
||||
mDecodedY1 = y1;
|
||||
mDecodedX2 = x2;
|
||||
mDecodedY2 = y2;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/** ---------------------------------------------------
|
||||
* Calculate rowBytes, making sure that it comes out as
|
||||
* a multiple of 4. ( 32 / 4 == 8)
|
||||
* See <http://developer.apple.com/technotes/qd/qd_15.html>
|
||||
*/
|
||||
PRInt32 nsImageMac::CalculateRowBytes(PRUint32 aWidth, PRUint32 aDepth)
|
||||
{
|
||||
PRInt32 rowBytes = ((aWidth * aDepth + 31) / 32) * 4;
|
||||
return rowBytes;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/** ---------------------------------------------------
|
||||
|
@ -530,55 +649,3 @@ OSErr nsImageMac::AllocateGWorld(PRInt16 depth, CTabHandle colorTable, const Rec
|
|||
|
||||
return memFullErr;
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------
|
||||
* Make a 256-level grayscale color table, for alpha blending.
|
||||
* Caller must free the color table with ::DisposeHandle((Handle)colorTable)
|
||||
* when done.
|
||||
*/
|
||||
|
||||
OSErr nsImageMac::MakeGrayscaleColorTable(PRInt16 numColors, CTabHandle *outColorTable)
|
||||
{
|
||||
CTabHandle colorTable = nil;
|
||||
|
||||
colorTable = (CTabHandle)::NewHandleClear (8 * numColors + 8); /* Allocate memory for the table */
|
||||
if (!colorTable) return memFullErr;
|
||||
|
||||
(**colorTable).ctSeed = ::GetCTSeed(); // not sure about this one
|
||||
(**colorTable).ctFlags = 0; // not sure about this one
|
||||
(**colorTable).ctSize = numColors - 1;
|
||||
|
||||
RGBColor tempColor = { 0xFFFF, 0xFFFF, 0xFFFF}; // starts at white
|
||||
PRUint16 colorInc = 0xFFFF / numColors;
|
||||
|
||||
for (PRInt16 i = 0; i < numColors; i++)
|
||||
{
|
||||
(**colorTable).ctTable[i].value = i;
|
||||
|
||||
(**colorTable).ctTable[i].rgb = tempColor;
|
||||
|
||||
tempColor.red -= colorInc;
|
||||
tempColor.green -= colorInc;
|
||||
tempColor.blue -= colorInc;
|
||||
}
|
||||
|
||||
*outColorTable = colorTable;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
/** ---------------------------------------------------
|
||||
* Set the decoded dimens of the image
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsImageMac::SetDecodedRect(PRInt32 x1, PRInt32 y1, PRInt32 x2, PRInt32 y2 )
|
||||
{
|
||||
|
||||
mDecodedX1 = x1;
|
||||
mDecodedY1 = y1;
|
||||
mDecodedX2 = x2;
|
||||
mDecodedY2 = y2;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,34 +46,34 @@ public:
|
|||
|
||||
virtual PRUint8* GetBits();
|
||||
virtual PRInt32 GetLineStride() { return mRowBytes; }
|
||||
virtual PRBool GetHasAlphaMask() { return mAlphaGWorld != nsnull; }
|
||||
virtual PRBool GetHasAlphaMask() { return mMaskBitsHandle != nsnull; }
|
||||
|
||||
NS_IMETHOD SetNaturalWidth(PRInt32 naturalwidth) { mNaturalWidth= naturalwidth; return NS_OK;}
|
||||
NS_IMETHOD SetNaturalHeight(PRInt32 naturalheight) { mNaturalHeight= naturalheight; return NS_OK;}
|
||||
virtual PRInt32 GetNaturalWidth() {return mNaturalWidth; }
|
||||
virtual PRInt32 GetNaturalHeight() {return mNaturalHeight; }
|
||||
NS_IMETHOD SetNaturalWidth(PRInt32 naturalwidth) { mNaturalWidth= naturalwidth; return NS_OK;}
|
||||
NS_IMETHOD SetNaturalHeight(PRInt32 naturalheight) { mNaturalHeight= naturalheight; return NS_OK;}
|
||||
virtual PRInt32 GetNaturalWidth() {return mNaturalWidth; }
|
||||
virtual PRInt32 GetNaturalHeight() {return mNaturalHeight; }
|
||||
|
||||
NS_IMETHOD SetDecodedRect(PRInt32 x1, PRInt32 y1, PRInt32 x2, PRInt32 y2);
|
||||
virtual PRInt32 GetDecodedX1() { return mDecodedX1;}
|
||||
virtual PRInt32 GetDecodedY1() { return mDecodedY1;}
|
||||
virtual PRInt32 GetDecodedX2() { return mDecodedX2;}
|
||||
virtual PRInt32 GetDecodedY2() { return mDecodedY2;}
|
||||
NS_IMETHOD SetDecodedRect(PRInt32 x1, PRInt32 y1, PRInt32 x2, PRInt32 y2);
|
||||
virtual PRInt32 GetDecodedX1() { return mDecodedX1;}
|
||||
virtual PRInt32 GetDecodedY1() { return mDecodedY1;}
|
||||
virtual PRInt32 GetDecodedX2() { return mDecodedX2;}
|
||||
virtual PRInt32 GetDecodedY2() { return mDecodedY2;}
|
||||
|
||||
|
||||
virtual PRUint8* GetAlphaBits();
|
||||
virtual PRInt32 GetAlphaWidth() { return mAlphaWidth; }
|
||||
virtual PRInt32 GetAlphaHeight() { return mAlphaHeight; }
|
||||
virtual PRInt32 GetAlphaWidth() { return mAlphaWidth; }
|
||||
virtual PRInt32 GetAlphaHeight() { return mAlphaHeight; }
|
||||
virtual PRInt32 GetAlphaLineStride() { return mARowBytes; }
|
||||
|
||||
virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect);
|
||||
virtual PRBool IsOptimized() { return PR_FALSE; }
|
||||
virtual nsresult Optimize(nsIDeviceContext* aContext);
|
||||
virtual nsColorMap* GetColorMap() { return nsnull;}
|
||||
virtual nsColorMap* GetColorMap() { return nsnull;}
|
||||
|
||||
NS_IMETHOD Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
||||
NS_IMETHOD Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
||||
PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
|
||||
|
||||
NS_IMETHOD Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
||||
NS_IMETHOD Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
||||
PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
|
||||
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight);
|
||||
|
||||
|
@ -85,14 +85,19 @@ public:
|
|||
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels);
|
||||
|
||||
protected:
|
||||
|
||||
void ClearGWorld(GWorldPtr);
|
||||
OSErr MakeGrayscaleColorTable(PRInt16 numColors, CTabHandle *outColorTable);
|
||||
OSErr AllocateGWorld(PRInt16 depth, CTabHandle colorTable, const Rect& bounds, GWorldPtr *outGWorld);
|
||||
|
||||
static OSErr CreatePixMap(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, CTabHandle aColorTable,
|
||||
PixMap& ioPixMap, Handle& ioBitsHandle);
|
||||
static OSErr AllocateBitsHandle(PRInt32 imageSizeBytes, Handle *outHandle);
|
||||
static PRInt32 CalculateRowBytes(PRUint32 aWidth,PRUint32 aDepth);
|
||||
|
||||
static void ClearGWorld(GWorldPtr);
|
||||
static OSErr AllocateGWorld(PRInt16 depth, CTabHandle colorTable, const Rect& bounds, GWorldPtr *outGWorld);
|
||||
|
||||
private:
|
||||
|
||||
GWorldPtr mImageGWorld;
|
||||
PixMap mImagePixmap;
|
||||
Handle mImageBitsHandle; // handle for the image bits
|
||||
|
||||
PRInt32 mWidth;
|
||||
PRInt32 mHeight;
|
||||
|
@ -101,22 +106,23 @@ private:
|
|||
PRInt32 mBytesPerPixel;
|
||||
|
||||
// alpha layer members
|
||||
GWorldPtr mAlphaGWorld;
|
||||
|
||||
PixMap mMaskPixmap; // the alpha level pixel map
|
||||
Handle mMaskBitsHandle; // handle for the mask bits
|
||||
|
||||
PRInt16 mAlphaDepth; // alpha layer depth
|
||||
PRInt16 mAlphaWidth; // alpha layer width
|
||||
PRInt16 mAlphaHeight; // alpha layer height
|
||||
PRInt32 mARowBytes; // alpha row bytes
|
||||
|
||||
PRInt32 mNaturalWidth;
|
||||
PRInt32 mNaturalHeight;
|
||||
PRInt32 mNaturalWidth;
|
||||
PRInt32 mNaturalHeight;
|
||||
|
||||
PRInt32 mDecodedX1; //Keeps track of what part of image
|
||||
PRInt32 mDecodedY1; // has been decoded.
|
||||
PRInt32 mDecodedX2;
|
||||
PRInt32 mDecodedY2;
|
||||
PRInt32 mDecodedX1; //Keeps track of what part of image
|
||||
PRInt32 mDecodedY1; // has been decoded.
|
||||
PRInt32 mDecodedX2;
|
||||
PRInt32 mDecodedY2;
|
||||
|
||||
|
||||
|
||||
//nsPoint mLocation; // alpha mask location
|
||||
|
||||
//PRInt8 mImageCache; // place to save off the old image for fast animation
|
||||
|
|
Загрузка…
Ссылка в новой задаче