mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-03 23:30:46 +00:00
bug 93999: reduce number of image creations in gtk/xlib. Patch by imot
(Tomi.Leppikangas@oulu.fi). r=pavlov, sr=brendan, r=bbaetz on c++ issues, jst said "check it in" on c++ issues.
This commit is contained in:
parent
d0e2a62257
commit
58d0356b53
@ -87,8 +87,8 @@ CPPSRCS = \
|
||||
nsPrintOptionsImpl.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
|
||||
CPPSRCS += \
|
||||
ifneq (,$(filter gtk xlib os2,$(MOZ_WIDGET_TOOLKIT)))
|
||||
CPPSRCS += \
|
||||
nsRegion.cpp \
|
||||
nsRegionImpl.cpp \
|
||||
$(NULL)
|
||||
|
@ -73,6 +73,7 @@ nsImageGTK::nsImageGTK()
|
||||
mNaturalHeight = 0;
|
||||
mAlphaValid = PR_FALSE;
|
||||
mIsSpacer = PR_TRUE;
|
||||
mPendingUpdate = PR_FALSE;
|
||||
|
||||
#ifdef TRACE_IMAGE_ALLOCATION
|
||||
printf("nsImageGTK::nsImageGTK(this=%p)\n",
|
||||
@ -279,12 +280,15 @@ void nsImageGTK::MoveAlphaMask(PRInt32 aX, PRInt32 aY)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
// set up the palette to the passed in color array, RGB only in this array
|
||||
void nsImageGTK::ImageUpdated(nsIDeviceContext *aContext,
|
||||
PRUint8 aFlags,
|
||||
nsRect *aUpdateRect)
|
||||
{
|
||||
mPendingUpdate = PR_TRUE;
|
||||
mUpdateRegion.Or(mUpdateRegion, *aUpdateRect);
|
||||
}
|
||||
|
||||
void nsImageGTK::UpdateCachedImage()
|
||||
{
|
||||
#ifdef TRACE_IMAGE_ALLOCATION
|
||||
printf("nsImageGTK::ImageUpdated(this=%p,%d)\n",
|
||||
@ -292,105 +296,112 @@ void nsImageGTK::ImageUpdated(nsIDeviceContext *aContext,
|
||||
aFlags);
|
||||
#endif
|
||||
|
||||
nsRegionRectIterator ri(mUpdateRegion);
|
||||
const nsRect *rect;
|
||||
|
||||
while (rect = ri.Next()) {
|
||||
|
||||
// fprintf(stderr, "ImageUpdated %p x,y=(%d %d) width,height=(%d %d)\n",
|
||||
// this, aUpdateRect->x, aUpdateRect->y, aUpdateRect->width,
|
||||
// aUpdateRect->height);
|
||||
// this, rect->x, rect->y, rect->width, rect->height);
|
||||
|
||||
unsigned bottom, left, right;
|
||||
bottom = aUpdateRect->y + aUpdateRect->height;
|
||||
left = aUpdateRect->x;
|
||||
right = left + aUpdateRect->width;
|
||||
unsigned bottom, left, right;
|
||||
bottom = rect->y + rect->height;
|
||||
left = rect->x;
|
||||
right = left + rect->width;
|
||||
|
||||
// check if the image has an all-opaque 8-bit alpha mask
|
||||
if ((mAlphaDepth==8) && !mAlphaValid) {
|
||||
for (unsigned y=aUpdateRect->y; (y<bottom) && !mAlphaValid; y++) {
|
||||
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + left;
|
||||
for (unsigned x=left; x<right; x++) {
|
||||
if (*(alpha++)!=255) {
|
||||
mAlphaValid=PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if the image is a spacer
|
||||
if ((mAlphaDepth==1) && mIsSpacer) {
|
||||
// mask of the leading/trailing bits in the update region
|
||||
PRUint8 leftmask = 0xff >> (left & 0x7);
|
||||
PRUint8 rightmask = 0xff << (7 - ((right-1) & 0x7));
|
||||
|
||||
// byte where the first/last bits of the update region are located
|
||||
PRUint32 leftindex = left >> 3;
|
||||
PRUint32 rightindex = (right-1) >> 3;
|
||||
|
||||
// first/last bits in the same byte - combine mask into leftmask
|
||||
// and fill rightmask so we don't try using it
|
||||
if (leftindex == rightindex) {
|
||||
leftmask &= rightmask;
|
||||
rightmask = 0xff;
|
||||
}
|
||||
|
||||
// check the leading bits
|
||||
if (leftmask != 0xff) {
|
||||
PRUint8 *ptr = mAlphaBits + mAlphaRowBytes * aUpdateRect->y + leftindex;
|
||||
for (unsigned y=aUpdateRect->y; y<bottom; y++, ptr+=mAlphaRowBytes) {
|
||||
if (*ptr & leftmask) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move to first full byte
|
||||
leftindex++;
|
||||
}
|
||||
|
||||
// check the trailing bits
|
||||
if (mIsSpacer && (rightmask != 0xff)) {
|
||||
PRUint8 *ptr = mAlphaBits + mAlphaRowBytes * aUpdateRect->y + rightindex;
|
||||
for (unsigned y=aUpdateRect->y; y<bottom; y++, ptr+=mAlphaRowBytes) {
|
||||
if (*ptr & rightmask) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move to last full byte
|
||||
rightindex--;
|
||||
}
|
||||
|
||||
// check the middle bytes
|
||||
if (mIsSpacer && (leftindex <= rightindex)) {
|
||||
for (unsigned y=aUpdateRect->y; (y<bottom) && mIsSpacer; y++) {
|
||||
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + leftindex;
|
||||
// check if the image has an all-opaque 8-bit alpha mask
|
||||
if ((mAlphaDepth==8) && !mAlphaValid) {
|
||||
for (unsigned y=rect->y; (y<bottom) && !mAlphaValid; y++) {
|
||||
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + left;
|
||||
for (unsigned x=left; x<right; x++) {
|
||||
if (*(alpha++)!=0) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
if (*(alpha++)!=255) {
|
||||
mAlphaValid=PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if the image is a spacer
|
||||
if ((mAlphaDepth==1) && mIsSpacer) {
|
||||
// mask of the leading/trailing bits in the update region
|
||||
PRUint8 leftmask = 0xff >> (left & 0x7);
|
||||
PRUint8 rightmask = 0xff << (7 - ((right-1) & 0x7));
|
||||
|
||||
// byte where the first/last bits of the update region are located
|
||||
PRUint32 leftindex = left >> 3;
|
||||
PRUint32 rightindex = (right-1) >> 3;
|
||||
|
||||
// first/last bits in the same byte - combine mask into leftmask
|
||||
// and fill rightmask so we don't try using it
|
||||
if (leftindex == rightindex) {
|
||||
leftmask &= rightmask;
|
||||
rightmask = 0xff;
|
||||
}
|
||||
|
||||
// check the leading bits
|
||||
if (leftmask != 0xff) {
|
||||
PRUint8 *ptr = mAlphaBits + mAlphaRowBytes * rect->y + leftindex;
|
||||
for (unsigned y=rect->y; y<bottom; y++, ptr+=mAlphaRowBytes) {
|
||||
if (*ptr & leftmask) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move to first full byte
|
||||
leftindex++;
|
||||
}
|
||||
|
||||
// check the trailing bits
|
||||
if (mIsSpacer && (rightmask != 0xff)) {
|
||||
PRUint8 *ptr = mAlphaBits + mAlphaRowBytes * rect->y + rightindex;
|
||||
for (unsigned y=rect->y; y<bottom; y++, ptr+=mAlphaRowBytes) {
|
||||
if (*ptr & rightmask) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move to last full byte
|
||||
rightindex--;
|
||||
}
|
||||
|
||||
// check the middle bytes
|
||||
if (mIsSpacer && (leftindex <= rightindex)) {
|
||||
for (unsigned y=rect->y; (y<bottom) && mIsSpacer; y++) {
|
||||
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + leftindex;
|
||||
for (unsigned x=left; x<right; x++) {
|
||||
if (*(alpha++)!=0) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mAlphaValid && mImagePixmap) {
|
||||
gdk_pixmap_unref(mImagePixmap);
|
||||
mImagePixmap = 0;
|
||||
}
|
||||
|
||||
if (!mAlphaValid) {
|
||||
CreateOffscreenPixmap(mWidth, mHeight);
|
||||
if (!sXbitGC)
|
||||
sXbitGC = gdk_gc_new(mImagePixmap);
|
||||
|
||||
gdk_draw_rgb_image_dithalign(mImagePixmap, sXbitGC,
|
||||
rect->x, rect->y,
|
||||
rect->width, rect->height,
|
||||
GDK_RGB_DITHER_MAX,
|
||||
mImageBits + mRowBytes*rect->y + 3*rect->x,
|
||||
mRowBytes,
|
||||
rect->x, rect->y);
|
||||
}
|
||||
}
|
||||
|
||||
if (mAlphaValid && mImagePixmap) {
|
||||
gdk_pixmap_unref(mImagePixmap);
|
||||
mImagePixmap = 0;
|
||||
}
|
||||
|
||||
if (!mAlphaValid) {
|
||||
CreateOffscreenPixmap(mWidth, mHeight);
|
||||
if (!sXbitGC)
|
||||
sXbitGC = gdk_gc_new(mImagePixmap);
|
||||
|
||||
gdk_draw_rgb_image_dithalign(mImagePixmap, sXbitGC,
|
||||
aUpdateRect->x, aUpdateRect->y,
|
||||
aUpdateRect->width, aUpdateRect->height,
|
||||
GDK_RGB_DITHER_MAX,
|
||||
mImageBits + mRowBytes*aUpdateRect->y + 3*aUpdateRect->x,
|
||||
mRowBytes,
|
||||
aUpdateRect->x, aUpdateRect->y);
|
||||
}
|
||||
|
||||
mFlags = aFlags; // this should be 0'd out by Draw()
|
||||
mUpdateRegion.Empty();
|
||||
mPendingUpdate = PR_FALSE;
|
||||
mFlags = nsImageUpdateFlags_kBitsChanged; // this should be 0'd out by Draw()
|
||||
}
|
||||
|
||||
#ifdef CHEAP_PERFORMANCE_MEASURMENT
|
||||
@ -543,6 +554,9 @@ nsImageGTK::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
||||
{
|
||||
g_return_val_if_fail ((aSurface != nsnull), NS_ERROR_FAILURE);
|
||||
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if ((mAlphaDepth==1) && mIsSpacer)
|
||||
return NS_OK;
|
||||
|
||||
@ -1241,6 +1255,9 @@ nsImageGTK::Draw(nsIRenderingContext &aContext,
|
||||
{
|
||||
g_return_val_if_fail ((aSurface != nsnull), NS_ERROR_FAILURE);
|
||||
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if ((mAlphaDepth==1) && mIsSpacer)
|
||||
return NS_OK;
|
||||
|
||||
@ -1411,6 +1428,12 @@ NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext,
|
||||
aTileRect.width, aTileRect.height, this);
|
||||
#endif
|
||||
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if ((mAlphaDepth==1) && mIsSpacer)
|
||||
return NS_OK;
|
||||
|
||||
@ -1573,6 +1596,9 @@ NS_IMETHODIMP nsImageGTK::DrawToImage(nsIImage* aDstImage,
|
||||
|
||||
if (!dest)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if (!dest->mImagePixmap) {
|
||||
dest->CreateOffscreenPixmap(dest->mWidth, dest->mHeight);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "X11/Xlib.h"
|
||||
#include "X11/Xutil.h"
|
||||
#include <gdk/gdk.h>
|
||||
#include "nsRegion.h"
|
||||
|
||||
#undef Bool
|
||||
|
||||
@ -82,6 +83,7 @@ public:
|
||||
PRInt32 aSXOffset, PRInt32 aSYOffset,
|
||||
const nsRect &aTileRect);
|
||||
|
||||
void UpdateCachedImage();
|
||||
virtual void ImageUpdated(nsIDeviceContext *aContext,
|
||||
PRUint8 aFlags, nsRect *aUpdateRect);
|
||||
virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight,
|
||||
@ -187,6 +189,8 @@ private:
|
||||
PRInt32 mDecodedX2;
|
||||
PRInt32 mDecodedY2;
|
||||
|
||||
nsRegion mUpdateRegion;
|
||||
|
||||
// alpha layer members
|
||||
PRInt16 mAlphaRowBytes; // alpha bytes per row
|
||||
PRInt16 mAlphaWidth; // alpha layer width
|
||||
@ -194,6 +198,7 @@ private:
|
||||
PRInt8 mAlphaDepth; // alpha layer depth
|
||||
PRPackedBool mAlphaValid;
|
||||
PRPackedBool mIsSpacer;
|
||||
PRPackedBool mPendingUpdate;
|
||||
|
||||
PRPackedBool mIsTopToBottom;
|
||||
PRInt8 mNumBytesPixel;
|
||||
|
@ -59,9 +59,9 @@ class RgnRectMemoryAllocator
|
||||
}
|
||||
|
||||
void FreeChunk (void* aChunk) { delete [] aChunk; }
|
||||
void* NextChunk (const void* aThisChunk) const { return *NS_STATIC_CAST (void**, aThisChunk); }
|
||||
void* NextChunk (void* aThisChunk) const { return *NS_STATIC_CAST (void**, aThisChunk); }
|
||||
|
||||
nsRegion::RgnRect* ChunkHead (const void* aThisChunk) const
|
||||
nsRegion::RgnRect* ChunkHead (void* aThisChunk) const
|
||||
{ return NS_REINTERPRET_CAST (nsRegion::RgnRect*, NS_STATIC_CAST (PRUint8*, aThisChunk) + sizeof (void*)); }
|
||||
|
||||
public:
|
||||
|
@ -39,8 +39,6 @@ struct nsRectFast : public nsRect
|
||||
nsRectFast () {} // No need to call parent constructor to set default values
|
||||
nsRectFast (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) : nsRect (aX, aY, aWidth, aHeight) {}
|
||||
nsRectFast (const nsRect& aRect) : nsRect (aRect) {}
|
||||
operator nsRect () { return *NS_STATIC_CAST (nsRect*, this); }
|
||||
|
||||
|
||||
#if 1 // Override nsRect methods to make them inline. Do not check for emptiness.
|
||||
PRBool Contains (const nsRectFast &aRect) const
|
||||
@ -100,12 +98,13 @@ class nsRegion
|
||||
|
||||
inline void* operator new (size_t);
|
||||
inline void operator delete (void* aRect, size_t);
|
||||
operator = (const RgnRect& aRect) // Do not overwrite prev/next pointers
|
||||
RgnRect& operator = (const RgnRect& aRect) // Do not overwrite prev/next pointers
|
||||
{
|
||||
x = aRect.x;
|
||||
y = aRect.y;
|
||||
width = aRect.width;
|
||||
height = aRect.height;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
@ -234,7 +233,7 @@ private:
|
||||
{ MoveInto (aDestRegion, mRectListHead.next); }
|
||||
|
||||
nsRegion (const nsRegion& aRegion); // Prevent copying of regions
|
||||
operator = (const nsRegion& aRegion);
|
||||
nsRegion& operator = (const nsRegion& aRegion);
|
||||
};
|
||||
|
||||
|
||||
@ -272,4 +271,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -74,6 +74,8 @@ nsImageXlib::nsImageXlib()
|
||||
mGC = nsnull;
|
||||
mNaturalWidth = 0;
|
||||
mNaturalHeight = 0;
|
||||
mPendingUpdate = PR_FALSE;
|
||||
|
||||
if (!mXlibRgbHandle)
|
||||
mXlibRgbHandle = xxlib_find_handle(XXLIBRGB_DEFAULT_HANDLE);
|
||||
if (!mXlibRgbHandle)
|
||||
@ -299,106 +301,124 @@ void nsImageXlib::ImageUpdated(nsIDeviceContext *aContext,
|
||||
PRUint8 aFlags,
|
||||
nsRect *aUpdateRect)
|
||||
{
|
||||
unsigned bottom, left, right;
|
||||
bottom = aUpdateRect->y + aUpdateRect->height;
|
||||
left = aUpdateRect->x;
|
||||
right = left + aUpdateRect->width;
|
||||
|
||||
// check if the image has an all-opaque 8-bit alpha mask
|
||||
if ((mAlphaDepth == 8) && !mAlphaValid) {
|
||||
for (unsigned y = aUpdateRect->y; (y < bottom) && !mAlphaValid; y++) {
|
||||
unsigned char *alpha = mAlphaBits + mAlphaRowBytes * y + left;
|
||||
for (unsigned x = left; x < right; x++) {
|
||||
if (*(alpha++) != 255) {
|
||||
mAlphaValid = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mPendingUpdate = PR_TRUE;
|
||||
mUpdateRegion.Or(mUpdateRegion, *aUpdateRect);
|
||||
}
|
||||
|
||||
// check if the image is a spacer
|
||||
if ((mAlphaDepth==1) && mIsSpacer) {
|
||||
// mask of the leading/trailing bits in the update region
|
||||
PRUint8 leftmask = 0xff >> (left & 0x7);
|
||||
PRUint8 rightmask = 0xff << (7 - ((right-1) & 0x7));
|
||||
void nsImageXlib::UpdateCachedImage()
|
||||
{
|
||||
nsRegionRectIterator ri(mUpdateRegion);
|
||||
const nsRect *rect;
|
||||
|
||||
// byte where the first/last bits of the update region are located
|
||||
PRUint32 leftindex = left >> 3;
|
||||
PRUint32 rightindex = (right-1) >> 3;
|
||||
while (rect = ri.Next()) {
|
||||
|
||||
// first/last bits in the same byte - combine mask into leftmask
|
||||
// and fill rightmask so we don't try using it
|
||||
if (leftindex == rightindex) {
|
||||
leftmask &= rightmask;
|
||||
rightmask = 0xff;
|
||||
}
|
||||
// fprintf(stderr, "ImageUpdated %p x,y=(%d %d) width,height=(%d %d)\n",
|
||||
// this, rect->x, rect->y, rect->width, rect->height);
|
||||
|
||||
// check the leading bits
|
||||
if (leftmask != 0xff) {
|
||||
PRUint8 *ptr = mAlphaBits + mAlphaRowBytes * aUpdateRect->y + leftindex;
|
||||
for (unsigned y=aUpdateRect->y; y<bottom; y++, ptr+=mAlphaRowBytes) {
|
||||
if (*ptr & leftmask) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move to first full byte
|
||||
leftindex++;
|
||||
}
|
||||
unsigned bottom, left, right;
|
||||
bottom = rect->y + rect->height;
|
||||
left = rect->x;
|
||||
right = left + rect->width;
|
||||
|
||||
// check the trailing bits
|
||||
if (mIsSpacer && (rightmask != 0xff)) {
|
||||
PRUint8 *ptr = mAlphaBits + mAlphaRowBytes * aUpdateRect->y + rightindex;
|
||||
for (unsigned y=aUpdateRect->y; y<bottom; y++, ptr+=mAlphaRowBytes) {
|
||||
if (*ptr & rightmask) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move to last full byte
|
||||
rightindex--;
|
||||
}
|
||||
|
||||
// check the middle bytes
|
||||
if (mIsSpacer && (leftindex <= rightindex)) {
|
||||
for (unsigned y=aUpdateRect->y; (y<bottom) && mIsSpacer; y++) {
|
||||
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + leftindex;
|
||||
// check if the image has an all-opaque 8-bit alpha mask
|
||||
if ((mAlphaDepth==8) && !mAlphaValid) {
|
||||
for (unsigned y=rect->y; (y<bottom) && !mAlphaValid; y++) {
|
||||
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + left;
|
||||
for (unsigned x=left; x<right; x++) {
|
||||
if (*(alpha++)!=0) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
if (*(alpha++)!=255) {
|
||||
mAlphaValid=PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mAlphaValid && mImagePixmap) {
|
||||
XFreePixmap(mDisplay, mImagePixmap);
|
||||
mImagePixmap = 0;
|
||||
}
|
||||
|
||||
if (!mAlphaValid) {
|
||||
CreateOffscreenPixmap(mWidth, mHeight);
|
||||
// check if the image is a spacer
|
||||
if ((mAlphaDepth==1) && mIsSpacer) {
|
||||
// mask of the leading/trailing bits in the update region
|
||||
PRUint8 leftmask = 0xff >> (left & 0x7);
|
||||
PRUint8 rightmask = 0xff << (7 - ((right-1) & 0x7));
|
||||
|
||||
if (!sXbitGC) {
|
||||
XGCValues gcv;
|
||||
memset(&gcv, 0, sizeof(XGCValues));
|
||||
gcv.function = GXcopy;
|
||||
sXbitGC = XCreateGC(mDisplay, mImagePixmap, GCFunction, &gcv);
|
||||
// byte where the first/last bits of the update region are located
|
||||
PRUint32 leftindex = left >> 3;
|
||||
PRUint32 rightindex = (right-1) >> 3;
|
||||
|
||||
// first/last bits in the same byte - combine mask into leftmask
|
||||
// and fill rightmask so we don't try using it
|
||||
if (leftindex == rightindex) {
|
||||
leftmask &= rightmask;
|
||||
rightmask = 0xff;
|
||||
}
|
||||
|
||||
// check the leading bits
|
||||
if (leftmask != 0xff) {
|
||||
PRUint8 *ptr = mAlphaBits + mAlphaRowBytes * rect->y + leftindex;
|
||||
for (unsigned y=rect->y; y<bottom; y++, ptr+=mAlphaRowBytes) {
|
||||
if (*ptr & leftmask) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move to first full byte
|
||||
leftindex++;
|
||||
}
|
||||
|
||||
// check the trailing bits
|
||||
if (mIsSpacer && (rightmask != 0xff)) {
|
||||
PRUint8 *ptr = mAlphaBits + mAlphaRowBytes * rect->y + rightindex;
|
||||
for (unsigned y=rect->y; y<bottom; y++, ptr+=mAlphaRowBytes) {
|
||||
if (*ptr & rightmask) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// move to last full byte
|
||||
rightindex--;
|
||||
}
|
||||
|
||||
// check the middle bytes
|
||||
if (mIsSpacer && (leftindex <= rightindex)) {
|
||||
for (unsigned y=rect->y; (y<bottom) && mIsSpacer; y++) {
|
||||
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + leftindex;
|
||||
for (unsigned x=left; x<right; x++) {
|
||||
if (*(alpha++)!=0) {
|
||||
mIsSpacer = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xxlib_draw_rgb_image_dithalign(
|
||||
|
||||
if (mAlphaValid && mImagePixmap) {
|
||||
XFreePixmap(mDisplay, mImagePixmap);
|
||||
mImagePixmap = 0;
|
||||
}
|
||||
|
||||
if (!mAlphaValid) {
|
||||
CreateOffscreenPixmap(mWidth, mHeight);
|
||||
|
||||
if (!sXbitGC) {
|
||||
XGCValues gcv;
|
||||
memset(&gcv, 0, sizeof(XGCValues));
|
||||
gcv.function = GXcopy;
|
||||
sXbitGC = XCreateGC(mDisplay, mImagePixmap, GCFunction, &gcv);
|
||||
}
|
||||
xxlib_draw_rgb_image_dithalign(
|
||||
mXlibRgbHandle,
|
||||
mImagePixmap, sXbitGC,
|
||||
aUpdateRect->x, aUpdateRect->y,
|
||||
aUpdateRect->width, aUpdateRect->height,
|
||||
rect->x, rect->y,
|
||||
rect->width, rect->height,
|
||||
XLIB_RGB_DITHER_MAX,
|
||||
mImageBits + mRowBytes * aUpdateRect->y + 3 * aUpdateRect->x,
|
||||
mImageBits + mRowBytes * rect->y + 3 * rect->x,
|
||||
mRowBytes,
|
||||
aUpdateRect->x, aUpdateRect->y);
|
||||
}
|
||||
}
|
||||
mFlags = aFlags; // this should be 0'd out by Draw()
|
||||
|
||||
mUpdateRegion.Empty();
|
||||
mPendingUpdate = PR_FALSE;
|
||||
mFlags = nsImageUpdateFlags_kBitsChanged; // this should be 0'd out by Draw()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -580,6 +600,9 @@ nsImageXlib::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
|
||||
if (aSurface == nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if ((mAlphaDepth == 1) && mIsSpacer)
|
||||
return NS_OK;
|
||||
|
||||
@ -1225,6 +1248,9 @@ nsImageXlib::Draw(nsIRenderingContext &aContext,
|
||||
PRInt32 aX, PRInt32 aY,
|
||||
PRInt32 aWidth, PRInt32 aHeight)
|
||||
{
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if ((mAlphaDepth == 1) && mIsSpacer)
|
||||
return NS_OK;
|
||||
|
||||
@ -1342,6 +1368,9 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext,
|
||||
nsRect &aSrcRect,
|
||||
nsRect &aTileRect)
|
||||
{
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if ((mAlphaDepth == 1) && mIsSpacer)
|
||||
return NS_OK;
|
||||
|
||||
@ -1452,6 +1481,9 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext,
|
||||
PRInt32 aSXOffset, PRInt32 aSYOffset,
|
||||
const nsRect &aTileRect)
|
||||
{
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if ((mAlphaDepth == 1) && mIsSpacer)
|
||||
return NS_OK;
|
||||
|
||||
@ -1619,6 +1651,9 @@ NS_IMETHODIMP nsImageXlib::DrawToImage(nsIImage* aDstImage,
|
||||
if (!dest)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mPendingUpdate)
|
||||
UpdateCachedImage();
|
||||
|
||||
if (!dest->mImagePixmap)
|
||||
dest->CreateOffscreenPixmap(dest->mWidth, dest->mHeight);
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "nsIImage.h"
|
||||
#include "nsPoint.h"
|
||||
#include "nsGCCache.h"
|
||||
#include "nsRegion.h"
|
||||
#include "xlibrgb.h"
|
||||
|
||||
// class nsDrawingSurfaceXlib;
|
||||
@ -84,6 +85,7 @@ public:
|
||||
PRInt32 aSXOffset, PRInt32 aSYOffset,
|
||||
const nsRect &aTileRect);
|
||||
|
||||
void UpdateCachedImage();
|
||||
virtual void ImageUpdated(nsIDeviceContext *aContext,
|
||||
PRUint8 aFlags, nsRect *aUpdateRect);
|
||||
virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight,
|
||||
@ -195,6 +197,8 @@ private:
|
||||
PRInt32 mDecodedX2;
|
||||
PRInt32 mDecodedY2;
|
||||
|
||||
nsRegion mUpdateRegion;
|
||||
|
||||
static XlibRgbHandle *mXlibRgbHandle;
|
||||
Display *mDisplay;
|
||||
|
||||
@ -205,6 +209,7 @@ private:
|
||||
PRInt16 mAlphaHeight; // alpha layer height
|
||||
PRPackedBool mAlphaValid;
|
||||
PRPackedBool mIsSpacer;
|
||||
PRPackedBool mPendingUpdate;
|
||||
|
||||
PRUint8 mFlags; // flags set by ImageUpdated
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user