зеркало из https://github.com/mozilla/pjs.git
Bug 283091 - LockImagePixels should regenerate alpha bits. r=sfraser, sr=tor.
This commit is contained in:
Родитель
f8afe489b4
Коммит
20e16dcc60
|
@ -41,10 +41,6 @@
|
||||||
#include "nsRegionPool.h"
|
#include "nsRegionPool.h"
|
||||||
#include "prmem.h"
|
#include "prmem.h"
|
||||||
|
|
||||||
// NOTE: Define this to premultiply the alpha info into the image. May result
|
|
||||||
// in a performance boost.
|
|
||||||
#define PERF_PREMULT_ALPHA
|
|
||||||
|
|
||||||
// Number of bits for each component in a pixel.
|
// Number of bits for each component in a pixel.
|
||||||
#define BITS_PER_COMPONENT 8
|
#define BITS_PER_COMPONENT 8
|
||||||
// Number of components per pixel (i.e. as in ARGB).
|
// Number of components per pixel (i.e. as in ARGB).
|
||||||
|
@ -159,11 +155,18 @@ nsImageMac::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth,
|
||||||
// 24-bit images are 8 bits per component; the alpha component is ignored
|
// 24-bit images are 8 bits per component; the alpha component is ignored
|
||||||
mRowBytes = CalculateRowBytes(aWidth, aDepth == 24 ? 32 : aDepth);
|
mRowBytes = CalculateRowBytes(aWidth, aDepth == 24 ? 32 : aDepth);
|
||||||
mImageBits = (PRUint8*) PR_Malloc(mHeight * mRowBytes * sizeof(PRUint8));
|
mImageBits = (PRUint8*) PR_Malloc(mHeight * mRowBytes * sizeof(PRUint8));
|
||||||
|
if (!mImageBits)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
if (mAlphaDepth)
|
if (mAlphaDepth)
|
||||||
{
|
{
|
||||||
mAlphaRowBytes = CalculateRowBytes(aWidth, mAlphaDepth);
|
mAlphaRowBytes = CalculateRowBytes(aWidth, mAlphaDepth);
|
||||||
mAlphaBits = (PRUint8*) PR_Malloc(mHeight * mAlphaRowBytes * sizeof(PRUint8));
|
mAlphaBits = (PRUint8*) PR_Malloc(mHeight * mAlphaRowBytes * sizeof(PRUint8));
|
||||||
|
if (!mAlphaBits) {
|
||||||
|
PR_Free(mImageBits);
|
||||||
|
mImageBits = nsnull;
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -191,45 +194,49 @@ nsImageMac::ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef PERF_PREMULT_ALPHA
|
|
||||||
void DataProviderReleaseFunc(void *info, const void *data, size_t size)
|
void DataProviderReleaseFunc(void *info, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
PR_Free(NS_CONST_CAST(void*, data));
|
PR_Free(NS_CONST_CAST(void*, data));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Create CGImageRef from image bits. Merge alpha bit into mImageBits, which
|
// Create CGImageRef from image bits. Merge alpha bit into mImageBits, which
|
||||||
// contains "place holder" for the alpha information. Then, create the
|
// contains "place holder" for the alpha information. Then, create the
|
||||||
// CGImageRef for use in drawing.
|
// CGImageRef for use in drawing.
|
||||||
void nsImageMac::EnsureCachedImage()
|
nsresult
|
||||||
|
nsImageMac::EnsureCachedImage()
|
||||||
{
|
{
|
||||||
// Only create cached image if mPendingUpdate is set.
|
// Only create cached image if mPendingUpdate is set.
|
||||||
if (!mPendingUpdate)
|
if (!mPendingUpdate)
|
||||||
return;
|
return NS_OK;
|
||||||
|
|
||||||
if (mImage) {
|
if (mImage) {
|
||||||
::CGImageRelease(mImage);
|
::CGImageRelease(mImage);
|
||||||
mImage = NULL;
|
mImage = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PERF_PREMULT_ALPHA
|
PRUint8* imageData = NULL; // data from which to create CGImage
|
||||||
PRUint8* imgPremultARGBData = NULL;
|
CGImageAlphaInfo alphaInfo; // alpha info for CGImage
|
||||||
if (mAlphaDepth == 8)
|
void (*releaseFunc)(void *info, const void *data, size_t size) = NULL;
|
||||||
imgPremultARGBData = (PRUint8*) PR_Malloc(mWidth * mHeight * COMPS_PER_PIXEL);
|
|
||||||
PRUint8* tmp = imgPremultARGBData;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (mAlphaDepth)
|
switch (mAlphaDepth)
|
||||||
{
|
{
|
||||||
case 8:
|
case 8:
|
||||||
|
{
|
||||||
|
// For 8-bit alpha, we create our own storage, since we premultiply the
|
||||||
|
// alpha info into the image bits, but we still want to keep the original
|
||||||
|
// image bits (mImageBits).
|
||||||
|
imageData = (PRUint8*) PR_Malloc(mWidth * mHeight * COMPS_PER_PIXEL);
|
||||||
|
if (!imageData)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
PRUint8* tmp = imageData;
|
||||||
|
|
||||||
for (PRInt32 y = 0; y < mHeight; y++)
|
for (PRInt32 y = 0; y < mHeight; y++)
|
||||||
{
|
{
|
||||||
PRInt32 rowStart = mRowBytes * y;
|
PRInt32 rowStart = mRowBytes * y;
|
||||||
PRInt32 alphaRowStart = mAlphaRowBytes * y;
|
PRInt32 alphaRowStart = mAlphaRowBytes * y;
|
||||||
for (PRInt32 x = 0; x < mWidth; x++)
|
for (PRInt32 x = 0; x < mWidth; x++)
|
||||||
{
|
{
|
||||||
#ifdef PERF_PREMULT_ALPHA
|
|
||||||
// Here we combine the alpha information with each pixel component,
|
// Here we combine the alpha information with each pixel component,
|
||||||
// creating an image with 'premultiplied alpha'.
|
// creating an image with 'premultiplied alpha'.
|
||||||
PRUint8 alpha = mAlphaBits[alphaRowStart + x];
|
PRUint8 alpha = mAlphaBits[alphaRowStart + x];
|
||||||
|
@ -238,16 +245,20 @@ void nsImageMac::EnsureCachedImage()
|
||||||
FAST_DIVIDE_BY_255(*tmp++, mImageBits[offset + 1] * alpha);
|
FAST_DIVIDE_BY_255(*tmp++, mImageBits[offset + 1] * alpha);
|
||||||
FAST_DIVIDE_BY_255(*tmp++, mImageBits[offset + 2] * alpha);
|
FAST_DIVIDE_BY_255(*tmp++, mImageBits[offset + 2] * alpha);
|
||||||
FAST_DIVIDE_BY_255(*tmp++, mImageBits[offset + 3] * alpha);
|
FAST_DIVIDE_BY_255(*tmp++, mImageBits[offset + 3] * alpha);
|
||||||
#else
|
|
||||||
// Copy the alpha information into the place holder in the image data.
|
|
||||||
mImageBits[rowStart + COMPS_PER_PIXEL * x] =
|
|
||||||
mAlphaBits[alphaRowStart + x];
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The memory that we pass to the CGDataProvider needs to stick around as
|
||||||
|
// long as the provider does, and the provider doesn't get destroyed until
|
||||||
|
// the CGImage is destroyed. So we have this small function which is
|
||||||
|
// called when the provider is destroyed.
|
||||||
|
releaseFunc = DataProviderReleaseFunc;
|
||||||
|
alphaInfo = kCGImageAlphaPremultipliedFirst;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
{
|
||||||
for (PRInt32 y = 0; y < mHeight; y++)
|
for (PRInt32 y = 0; y < mHeight; y++)
|
||||||
{
|
{
|
||||||
PRInt32 rowStart = mRowBytes * y;
|
PRInt32 rowStart = mRowBytes * y;
|
||||||
|
@ -256,42 +267,24 @@ void nsImageMac::EnsureCachedImage()
|
||||||
{
|
{
|
||||||
// Copy the alpha information into the place holder in the image data.
|
// Copy the alpha information into the place holder in the image data.
|
||||||
mImageBits[rowStart + COMPS_PER_PIXEL * x] =
|
mImageBits[rowStart + COMPS_PER_PIXEL * x] =
|
||||||
GetBit(alphaRow, x) ? 255 : 0;
|
GetAlphaBit(alphaRow, x) ? 255 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alphaInfo = kCGImageAlphaPremultipliedFirst;
|
||||||
|
imageData = mImageBits;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
for (PRInt32 y = 0; y < mHeight; y++)
|
{
|
||||||
{
|
alphaInfo = kCGImageAlphaNoneSkipFirst;
|
||||||
PRInt32 rowStart = mRowBytes * y;
|
imageData = mImageBits;
|
||||||
for (PRInt32 x = 0; x < mWidth; x++)
|
|
||||||
{
|
|
||||||
// No alpha information
|
|
||||||
mImageBits[rowStart + COMPS_PER_PIXEL * x] = 255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint8* imageData = mImageBits;
|
|
||||||
CGImageAlphaInfo alphaInfo = kCGImageAlphaFirst;
|
|
||||||
void (*releaseFunc)(void *info, const void *data, size_t size) = NULL;
|
|
||||||
#ifdef PERF_PREMULT_ALPHA
|
|
||||||
if (mAlphaDepth == 8)
|
|
||||||
{
|
|
||||||
imageData = imgPremultARGBData;
|
|
||||||
alphaInfo = kCGImageAlphaPremultipliedFirst;
|
|
||||||
|
|
||||||
// The memory that we pass to the CGDataProvider needs to stick around as
|
|
||||||
// long as the provider does, and the provider doesn't get destroyed until
|
|
||||||
// the CGImage is destroyed. So we have this small function which is called
|
|
||||||
// when the provider is destroyed.
|
|
||||||
releaseFunc = DataProviderReleaseFunc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CGColorSpaceRef cs = ::CGColorSpaceCreateDeviceRGB();
|
CGColorSpaceRef cs = ::CGColorSpaceCreateDeviceRGB();
|
||||||
StColorSpaceReleaser csReleaser(cs);
|
StColorSpaceReleaser csReleaser(cs);
|
||||||
CGDataProviderRef prov = ::CGDataProviderCreateWithData(NULL, imageData,
|
CGDataProviderRef prov = ::CGDataProviderCreateWithData(NULL, imageData,
|
||||||
|
@ -303,6 +296,7 @@ void nsImageMac::EnsureCachedImage()
|
||||||
::CGDataProviderRelease(prov);
|
::CGDataProviderRelease(prov);
|
||||||
|
|
||||||
mPendingUpdate = PR_FALSE;
|
mPendingUpdate = PR_FALSE;
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -314,7 +308,8 @@ nsImageMac::Draw(nsIRenderingContext &aContext, nsIDrawingSurface* aSurface,
|
||||||
if (mDecodedX2 < mDecodedX1 || mDecodedY2 < mDecodedY1)
|
if (mDecodedX2 < mDecodedX1 || mDecodedY2 < mDecodedY1)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
EnsureCachedImage();
|
nsresult rv = EnsureCachedImage();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
PRInt32 srcWidth = aSWidth;
|
PRInt32 srcWidth = aSWidth;
|
||||||
PRInt32 srcHeight = aSHeight;
|
PRInt32 srcHeight = aSHeight;
|
||||||
|
@ -391,11 +386,14 @@ NS_IMETHODIMP
|
||||||
nsImageMac::DrawToImage(nsIImage* aDstImage, PRInt32 aDX, PRInt32 aDY,
|
nsImageMac::DrawToImage(nsIImage* aDstImage, PRInt32 aDX, PRInt32 aDY,
|
||||||
PRInt32 aDWidth, PRInt32 aDHeight)
|
PRInt32 aDWidth, PRInt32 aDHeight)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
|
||||||
nsImageMac* dest = NS_STATIC_CAST(nsImageMac*, aDstImage);
|
nsImageMac* dest = NS_STATIC_CAST(nsImageMac*, aDstImage);
|
||||||
|
|
||||||
EnsureCachedImage();
|
nsresult rv = EnsureCachedImage();
|
||||||
dest->EnsureCachedImage();
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
rv = dest->EnsureCachedImage();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = NS_ERROR_FAILURE;
|
||||||
|
|
||||||
// Create image storage. The storage is 'owned' by the CGImageRef created
|
// Create image storage. The storage is 'owned' by the CGImageRef created
|
||||||
// below as 'newImageRef'; that is, the storage cannot be deleted until the
|
// below as 'newImageRef'; that is, the storage cannot be deleted until the
|
||||||
|
@ -405,6 +403,8 @@ nsImageMac::DrawToImage(nsIImage* aDstImage, PRInt32 aDX, PRInt32 aDY,
|
||||||
PRInt32 bytesPerRow = dest->GetLineStride();
|
PRInt32 bytesPerRow = dest->GetLineStride();
|
||||||
PRInt32 totalBytes = height * bytesPerRow;
|
PRInt32 totalBytes = height * bytesPerRow;
|
||||||
PRUint8* bitmap = (PRUint8*) PR_Malloc(totalBytes);
|
PRUint8* bitmap = (PRUint8*) PR_Malloc(totalBytes);
|
||||||
|
if (!bitmap)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
CGColorSpaceRef cs = ::CGColorSpaceCreateDeviceRGB();
|
CGColorSpaceRef cs = ::CGColorSpaceCreateDeviceRGB();
|
||||||
StColorSpaceReleaser csReleaser(cs);
|
StColorSpaceReleaser csReleaser(cs);
|
||||||
|
@ -427,11 +427,7 @@ nsImageMac::DrawToImage(nsIImage* aDstImage, PRInt32 aDX, PRInt32 aDY,
|
||||||
|
|
||||||
::CGContextRelease(bitmapContext);
|
::CGContextRelease(bitmapContext);
|
||||||
|
|
||||||
#ifdef PERF_PREMULT_ALPHA
|
|
||||||
CGImageAlphaInfo alphaInfo = ::CGImageGetAlphaInfo(dest->mImage);
|
CGImageAlphaInfo alphaInfo = ::CGImageGetAlphaInfo(dest->mImage);
|
||||||
#else
|
|
||||||
CGImageAlphaInfo alphaInfo = kCGImageAlphaFirst;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// create a new image from the combined bitmap
|
// create a new image from the combined bitmap
|
||||||
CGDataProviderRef prov = ::CGDataProviderCreateWithData(NULL, bitmap,
|
CGDataProviderRef prov = ::CGDataProviderCreateWithData(NULL, bitmap,
|
||||||
|
@ -480,9 +476,9 @@ nsImageMac::AdoptImage(CGImageRef aNewImage, PRUint8* aNewBitmap)
|
||||||
nsresult
|
nsresult
|
||||||
nsImageMac::Optimize(nsIDeviceContext* aContext)
|
nsImageMac::Optimize(nsIDeviceContext* aContext)
|
||||||
{
|
{
|
||||||
EnsureCachedImage();
|
nsresult rv = EnsureCachedImage();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
#ifdef PERF_PREMULT_ALPHA
|
|
||||||
// We cannot delete the bitmap data from which mImage was created; the data
|
// We cannot delete the bitmap data from which mImage was created; the data
|
||||||
// needs to stick around at least as long as the mImage is valid.
|
// needs to stick around at least as long as the mImage is valid.
|
||||||
// mImageBits is used by all images, except those that have mAlphaDepth == 8
|
// mImageBits is used by all images, except those that have mAlphaDepth == 8
|
||||||
|
@ -491,7 +487,6 @@ nsImageMac::Optimize(nsIDeviceContext* aContext)
|
||||||
PR_Free(mImageBits);
|
PR_Free(mImageBits);
|
||||||
mImageBits = NULL;
|
mImageBits = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// mAlphaBits is not really used any more after EnsureCachedImage is called,
|
// mAlphaBits is not really used any more after EnsureCachedImage is called,
|
||||||
// since it's data is merged into mImageBits.
|
// since it's data is merged into mImageBits.
|
||||||
|
@ -512,31 +507,101 @@ nsImageMac::LockImagePixels(PRBool aMaskPixels)
|
||||||
if (!mOptimized)
|
if (!mOptimized)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
// Regenerate mImageBits by drawing mImage into bitmap context.
|
// Need to recreate mAlphaBits and/or mImageBits. We do so by drawing the
|
||||||
// We only need do this if it was destroyed by Optimize().
|
// CGImage into a bitmap context. Afterwards, 'imageBits' contains the
|
||||||
if (!mImageBits)
|
// image data with premultiplied alpha (if applicable).
|
||||||
{
|
PRUint8* imageBits = (PRUint8*) PR_Malloc(mHeight * mRowBytes);
|
||||||
mImageBits = (PRUint8*) PR_Malloc(mHeight * mRowBytes);
|
if (!imageBits)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
CGColorSpaceRef cs = ::CGColorSpaceCreateDeviceRGB();
|
||||||
|
StColorSpaceReleaser csReleaser(cs);
|
||||||
|
CGContextRef bitmapContext =
|
||||||
|
::CGBitmapContextCreate(imageBits, mWidth, mHeight, BITS_PER_COMPONENT,
|
||||||
|
mRowBytes, cs, kCGImageAlphaPremultipliedFirst);
|
||||||
|
if (!bitmapContext) {
|
||||||
|
PR_Free(imageBits);
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
CGColorSpaceRef cs = ::CGColorSpaceCreateDeviceRGB();
|
// clear the bitmap context & draw mImage into it
|
||||||
StColorSpaceReleaser csReleaser(cs);
|
CGRect drawRect = ::CGRectMake(0, 0, mWidth, mHeight);
|
||||||
CGContextRef bitmapContext;
|
::CGContextClearRect(bitmapContext, drawRect);
|
||||||
bitmapContext = ::CGBitmapContextCreate(mImageBits, mWidth, mHeight,
|
::CGContextDrawImage(bitmapContext, drawRect, mImage);
|
||||||
BITS_PER_COMPONENT, mRowBytes, cs,
|
::CGContextRelease(bitmapContext);
|
||||||
kCGImageAlphaNoneSkipFirst);
|
|
||||||
|
|
||||||
if (bitmapContext != NULL)
|
// 'imageBits' now contains the image and (possibly) alpha bits for image.
|
||||||
{
|
// Now we need to separate them out.
|
||||||
CGRect drawRect = ::CGRectMake(0, 0, mWidth, mHeight);
|
|
||||||
|
|
||||||
// clear the bitmap context
|
if (mAlphaDepth) {
|
||||||
::CGContextClearRect(bitmapContext, drawRect);
|
// Only need to worry about alpha for mAlphaDepth == 1 or 8.
|
||||||
|
mAlphaBits = (PRUint8*) PR_Malloc(mHeight * mAlphaRowBytes *
|
||||||
::CGContextDrawImage(bitmapContext, drawRect, mImage);
|
sizeof(PRUint8));
|
||||||
::CGContextRelease(bitmapContext);
|
if (!mAlphaBits) {
|
||||||
|
PR_Free(imageBits);
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (mAlphaDepth)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
// Need to recreate mImageBits for mAlphaDepth == 8 only.
|
||||||
|
// See comments nsImageMac::Optimize().
|
||||||
|
PRUint8* tmp = imageBits;
|
||||||
|
mImageBits = (PRUint8*) PR_Malloc(mHeight * mRowBytes * sizeof(PRUint8));
|
||||||
|
if (!mImageBits) {
|
||||||
|
PR_Free(mAlphaBits);
|
||||||
|
mAlphaBits = nsnull;
|
||||||
|
PR_Free(imageBits);
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// split the alpha bits and image bits into their own structure
|
||||||
|
for (PRInt32 y = 0; y < mHeight; y++)
|
||||||
|
{
|
||||||
|
PRInt32 rowStart = mRowBytes * y;
|
||||||
|
PRInt32 alphaRowStart = mAlphaRowBytes * y;
|
||||||
|
for (PRInt32 x = 0; x < mWidth; x++)
|
||||||
|
{
|
||||||
|
PRUint8 alpha = *tmp++;
|
||||||
|
mAlphaBits[alphaRowStart + x] = alpha;
|
||||||
|
PRUint32 offset = rowStart + COMPS_PER_PIXEL * x;
|
||||||
|
mImageBits[offset + 1] = ((PRUint32) *tmp++) * 255 / alpha;
|
||||||
|
mImageBits[offset + 2] = ((PRUint32) *tmp++) * 255 / alpha;
|
||||||
|
mImageBits[offset + 3] = ((PRUint32) *tmp++) * 255 / alpha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mImageBits still exists for mAlphaDepth == 1 or mAlphaDepth == 0,
|
||||||
|
// since the bits are owned by the CGImageRef. So the only thing to
|
||||||
|
// do is to recreate the alpha bits for mAlphaDepth == 1.
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// recreate the alpha bits structure
|
||||||
|
for (PRInt32 y = 0; y < mHeight; y++)
|
||||||
|
{
|
||||||
|
PRInt32 rowStart = mRowBytes * y;
|
||||||
|
PRUint8* alphaRow = mAlphaBits + mAlphaRowBytes * y;
|
||||||
|
for (PRInt32 x = 0; x < mWidth; x++)
|
||||||
|
{
|
||||||
|
if (imageBits[rowStart + COMPS_PER_PIXEL * x])
|
||||||
|
SetAlphaBit(alphaRow, x);
|
||||||
|
else
|
||||||
|
ClearAlphaBit(alphaRow, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PR_Free(imageBits);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,6 +847,8 @@ nsImageMac::DrawTileQuickly(nsIRenderingContext &aContext,
|
||||||
PRUint32 bitmapRowBytes = tiledCols * mRowBytes;
|
PRUint32 bitmapRowBytes = tiledCols * mRowBytes;
|
||||||
PRUint32 totalBytes = bitmapHeight * bitmapRowBytes;
|
PRUint32 totalBytes = bitmapHeight * bitmapRowBytes;
|
||||||
PRUint8* bitmap = (PRUint8*) PR_Malloc(totalBytes);
|
PRUint8* bitmap = (PRUint8*) PR_Malloc(totalBytes);
|
||||||
|
if (!bitmap)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
CGContextRef bitmapContext;
|
CGContextRef bitmapContext;
|
||||||
bitmapContext = ::CGBitmapContextCreate(bitmap, bitmapWidth, bitmapHeight,
|
bitmapContext = ::CGBitmapContextCreate(bitmap, bitmapWidth, bitmapHeight,
|
||||||
|
@ -904,12 +971,12 @@ NS_IMETHODIMP nsImageMac::DrawTile(nsIRenderingContext &aContext,
|
||||||
PRInt32 aPadX, PRInt32 aPadY,
|
PRInt32 aPadX, PRInt32 aPadY,
|
||||||
const nsRect &aTileRect)
|
const nsRect &aTileRect)
|
||||||
{
|
{
|
||||||
EnsureCachedImage();
|
nsresult rv = EnsureCachedImage();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (mDecodedX2 < mDecodedX1 || mDecodedY2 < mDecodedY1)
|
if (mDecodedX2 < mDecodedX1 || mDecodedY2 < mDecodedY1)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
|
||||||
#ifdef USE_CGPATTERN_TILING
|
#ifdef USE_CGPATTERN_TILING
|
||||||
if (nsRenderingContextMac::OnJaguar())
|
if (nsRenderingContextMac::OnJaguar())
|
||||||
{
|
{
|
||||||
|
@ -947,20 +1014,16 @@ NS_IMETHODIMP nsImageMac::DrawTile(nsIRenderingContext &aContext,
|
||||||
::CGContextFillRect(context, tileRect);
|
::CGContextFillRect(context, tileRect);
|
||||||
surface->EndQuartzDrawing(context);
|
surface->EndQuartzDrawing(context);
|
||||||
|
|
||||||
rv = NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif /* USE_CGPATTERN_TILING */
|
#endif /* USE_CGPATTERN_TILING */
|
||||||
{
|
|
||||||
// use the manual methods of tiling
|
|
||||||
|
|
||||||
if (!aPadX && !aPadY)
|
// use the manual methods of tiling
|
||||||
rv = DrawTileQuickly(aContext, aSurface, aSXOffset, aSYOffset, aTileRect);
|
|
||||||
|
|
||||||
if (NS_FAILED(rv))
|
if (!aPadX && !aPadY) {
|
||||||
rv = SlowTile(aContext, aSurface, aSXOffset, aSYOffset, aPadX, aPadY,
|
return DrawTileQuickly(aContext, aSurface, aSXOffset, aSYOffset, aTileRect);
|
||||||
aTileRect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return SlowTile(aContext, aSurface, aSXOffset, aSYOffset, aPadX, aPadY,
|
||||||
|
aTileRect);
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,12 +134,18 @@ protected:
|
||||||
static PRBool RenderingToPrinter(nsIRenderingContext &aContext);
|
static PRBool RenderingToPrinter(nsIRenderingContext &aContext);
|
||||||
|
|
||||||
// Recreate internal image structure from updated image bits.
|
// Recreate internal image structure from updated image bits.
|
||||||
void EnsureCachedImage();
|
nsresult EnsureCachedImage();
|
||||||
|
|
||||||
// Return alpha bit at position 'x' in the row pointed to by 'rowptr'.
|
// Get/Set/Clear alpha bit at position 'x' in the row pointed to by 'rowptr'.
|
||||||
inline PRUint8 GetBit(PRUint8* rowptr, PRUint32 x) {
|
inline PRUint8 GetAlphaBit(PRUint8* rowptr, PRUint32 x) {
|
||||||
return (rowptr[x >> 3] & (1 << (7 - x & 0x7)));
|
return (rowptr[x >> 3] & (1 << (7 - x & 0x7)));
|
||||||
}
|
}
|
||||||
|
inline void SetAlphaBit(PRUint8* rowptr, PRUint32 x) {
|
||||||
|
rowptr[x >> 3] |= (1 << (7 - x & 0x7));
|
||||||
|
}
|
||||||
|
inline void ClearAlphaBit(PRUint8* rowptr, PRUint32 x) {
|
||||||
|
rowptr[x >> 3] &= ~(1 << (7 - x & 0x7));
|
||||||
|
}
|
||||||
|
|
||||||
// Takes ownership of the given image and bitmap. The CGImageRef is retained.
|
// Takes ownership of the given image and bitmap. The CGImageRef is retained.
|
||||||
void AdoptImage(CGImageRef aNewImage, PRUint8* aNewBitamp);
|
void AdoptImage(CGImageRef aNewImage, PRUint8* aNewBitamp);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче