зеркало из https://github.com/mozilla/pjs.git
Bug 276692 move image->GdkPixbuf conversion code to nsImageGTK
r=bryner sr=roc
This commit is contained in:
Родитель
7ed1238419
Коммит
32fd7394ff
|
@ -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:
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче