Bug 276692 move image->GdkPixbuf conversion code to nsImageGTK

r=bryner sr=roc
This commit is contained in:
cbiesinger%web.de 2005-01-24 18:10:06 +00:00
Родитель 7ed1238419
Коммит 32fd7394ff
5 изменённых файлов: 117 добавлений и 107 удалений

Просмотреть файл

@ -54,6 +54,8 @@
#include "nsIImageLoadingContent.h"
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "nsIImage.h"
#include "nsIGdkPixbufImage.h"
#include "nsColor.h"
#include <glib.h>
@ -342,113 +344,15 @@ nsGNOMEShellService::SetShouldCheckDefaultBrowser(PRBool aShouldCheck)
static nsresult
WriteImage(const nsCString& aPath, gfxIImageFrame* aImage)
{
PRInt32 width, height;
aImage->GetWidth(&width);
aImage->GetHeight(&height);
nsCOMPtr<nsIGdkPixbufImage> pixImg(do_GetInterface(aImage));
if (!pixImg)
return NS_ERROR_NOT_AVAILABLE;
PRInt32 format;
aImage->GetFormat(&format);
GdkPixbuf* pixbuf = pixImg->GetGdkPixbuf();
if (!pixbuf)
return NS_ERROR_NOT_AVAILABLE;
aImage->LockImageData();
PRUint32 bytesPerRow;
aImage->GetImageBytesPerRow(&bytesPerRow);
PRUint32 bpp = bytesPerRow / width * 8;
// XXX If bpp is not 24, we will need to do something else, like
// allocate a new pixbuf and copy the data in ourselves.
if (bpp != 24)
return NS_ERROR_FAILURE;
PRUint8 *bits;
PRUint32 length;
aImage->GetImageData(&bits, &length);
if (!bits) return NS_ERROR_FAILURE;
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(bits,
GDK_COLORSPACE_RGB,
PR_FALSE,
8,
width,
height,
bytesPerRow,
NULL,
NULL);
GdkPixbuf *alphaPixbuf = nsnull;
if (format == gfxIFormats::RGB_A1 || format == gfxIFormats::RGB_A8) {
aImage->LockAlphaData();
PRUint32 alphaBytesPerRow, alphaDepth, alphaLength;
aImage->GetAlphaBytesPerRow(&alphaBytesPerRow);
#if 0
if (format == gfxIFormats::RGB_A1)
alphaDepth = 1;
else
alphaDepth = 8;
#endif
switch (format) {
case gfxIFormats::RGB_A1:
alphaDepth = 1;
break;
case gfxIFormats::RGB_A8:
alphaDepth = 8;
break;
default:
// not reached
return NS_ERROR_UNEXPECTED;
}
PRUint8 *alphaBits;
aImage->GetAlphaData(&alphaBits, &alphaLength);
alphaPixbuf = gdk_pixbuf_add_alpha(pixbuf, FALSE, 0, 0, 0);
// Run through alphaBits and copy the alpha mask into the pixbuf's
// alpha channel.
PRUint8 *maskRow = alphaBits;
PRUint8 *pixbufRow = gdk_pixbuf_get_pixels(alphaPixbuf);
gint pixbufRowStride = gdk_pixbuf_get_rowstride(alphaPixbuf);
gint pixbufChannels = gdk_pixbuf_get_n_channels(alphaPixbuf);
for (PRInt32 y = 0; y < height; ++y) {
PRUint8 *pixbufPixel = pixbufRow;
PRUint8 *maskPixel = maskRow;
// If using 1-bit alpha, we must expand it to 8-bit
PRUint32 bitPos = 7;
for (PRInt32 x = 0; x < width; ++x) {
if (alphaDepth == 1) {
pixbufPixel[pixbufChannels - 1] = ((*maskPixel >> bitPos) & 1) ? 255 : 0;
if (bitPos-- == 0) { // wrapped around, move forward a byte
++maskPixel;
bitPos = 7;
}
} else {
pixbufPixel[pixbufChannels - 1] = *maskPixel++;
}
pixbufPixel += pixbufChannels;
}
pixbufRow += pixbufRowStride;
maskRow += alphaBytesPerRow;
}
}
gboolean res = gdk_pixbuf_save(alphaPixbuf ? alphaPixbuf : pixbuf,
aPath.get(), "png", NULL, NULL);
if (alphaPixbuf) {
aImage->UnlockAlphaData();
g_object_unref(alphaPixbuf);
}
gboolean res = gdk_pixbuf_save(pixbuf, aPath.get(), "png", NULL, NULL);
aImage->UnlockImageData();
g_object_unref(pixbuf);

Просмотреть файл

@ -145,6 +145,10 @@ endif
endif
ifdef MOZ_ENABLE_GTK2
EXPORTS = \
nsIGdkPixbufImage.h \
$(NULL)
CPPSRCS += \
nsRegionGTK2.cpp \
$(NULL)

Просмотреть файл

Просмотреть файл

@ -47,6 +47,8 @@
#include "nspr.h"
#include "nsIGdkPixbufImage.h"
#define IsFlagSet(a,b) ((a) & (b))
#define NS_GET_BIT(rowptr, x) (rowptr[(x)>>3] & (1<<(7-(x)&0x7)))
@ -74,7 +76,11 @@ static GdkGC *sXbitGC = nsnull;
prevents us from doing fast tiling. */
static PRBool sNeedSlowTile = PR_FALSE;
#ifdef MOZ_WIDGET_GTK2
NS_IMPL_ISUPPORTS2(nsImageGTK, nsIImage, nsIGdkPixbufImage)
#else
NS_IMPL_ISUPPORTS1(nsImageGTK, nsIImage)
#endif
//------------------------------------------------------------
@ -2163,3 +2169,90 @@ NS_IMETHODIMP nsImageGTK::DrawToImage(nsIImage* aDstImage,
return NS_OK;
}
#ifdef MOZ_WIDGET_GTK2
static void pixbuf_free(guchar* data, gpointer) {
nsMemory::Free(data);
}
NS_IMETHODIMP_(GdkPixbuf*)
nsImageGTK::GetGdkPixbuf() {
// Init ensures that we only have 24bpp images
NS_ASSERTION(mNumBytesPixel == 3, "Unexpected color depth");
nsresult rv = LockImagePixels(PR_FALSE);
NS_ENSURE_SUCCESS(rv, nsnull);
// Since UnlockImagePixels potentially frees the image data (and since the
// buffer might outlive this object anyway), we have to copy the data.
guchar* pixels = NS_STATIC_CAST(guchar*,
nsMemory::Clone(mImageBits, mRowBytes * mHeight));
UnlockImagePixels(PR_FALSE);
if (!pixels)
return nsnull;
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(pixels,
GDK_COLORSPACE_RGB,
PR_FALSE,
8,
mWidth,
mHeight,
mRowBytes,
pixbuf_free,
nsnull);
if (!pixbuf)
return nsnull;
if (!GetHasAlphaMask()) {
// No alpha channel -> we are done
return pixbuf;
}
GdkPixbuf *alphaPixbuf = gdk_pixbuf_add_alpha(pixbuf, FALSE, 0, 0, 0);
g_object_unref(pixbuf);
if (!alphaPixbuf)
return nsnull;
LockImagePixels(PR_TRUE);
PRInt32 alphaBytesPerRow = GetAlphaLineStride();
PRUint8 *alphaBits = GetAlphaBits();
// Run through alphaBits and copy the alpha mask into the pixbuf's
// alpha channel.
PRUint8 *maskRow = alphaBits;
PRUint8 *pixbufRow = gdk_pixbuf_get_pixels(alphaPixbuf);
gint pixbufRowStride = gdk_pixbuf_get_rowstride(alphaPixbuf);
gint pixbufChannels = gdk_pixbuf_get_n_channels(alphaPixbuf);
for (PRInt32 y = 0; y < mHeight; ++y) {
PRUint8 *pixbufPixel = pixbufRow;
PRUint8 *maskPixel = maskRow;
// If using 1-bit alpha, we must expand it to 8-bit
PRUint32 bitPos = 7;
for (PRInt32 x = 0; x < mWidth; ++x) {
if (mAlphaDepth == 1) {
pixbufPixel[pixbufChannels - 1] = ((*maskPixel >> bitPos) & 1) ? 255 : 0;
if (bitPos-- == 0) { // wrapped around, move forward a byte
++maskPixel;
bitPos = 7;
}
} else {
pixbufPixel[pixbufChannels - 1] = *maskPixel++;
}
pixbufPixel += pixbufChannels;
}
pixbufRow += pixbufRowStride;
maskRow += alphaBytesPerRow;
}
UnlockImagePixels(PR_TRUE);
return alphaPixbuf;
}
#endif

Просмотреть файл

@ -44,10 +44,16 @@
#include <X11/Xutil.h>
#include <gdk/gdk.h>
#include "nsRegion.h"
#include "nsIGdkPixbufImage.h"
class nsDrawingSurfaceGTK;
class nsImageGTK : public nsIImage
class nsImageGTK :
#ifdef MOZ_WIDGET_GTK2
public nsIGdkPixbufImage
#else
public nsIImage
#endif
{
public:
nsImageGTK();
@ -98,7 +104,7 @@ public:
virtual nsresult Optimize(nsIDeviceContext* aContext);
virtual PRBool GetHasAlphaMask() { return mAlphaBits != nsnull; }
virtual PRBool GetHasAlphaMask() { return mAlphaBits != nsnull || mAlphaPixmap != nsnull; }
virtual PRUint8* GetAlphaBits();
virtual PRInt32 GetAlphaLineStride();
@ -117,6 +123,9 @@ public:
NS_IMETHOD LockImagePixels(PRBool aMaskPixels);
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels);
#ifdef MOZ_WIDGET_GTK2
NS_IMETHOD_(GdkPixbuf*) GetGdkPixbuf();
#endif
private:
/**