зеркало из https://github.com/mozilla/gecko-dev.git
Bug 950647 - Make nsImageToPixbuf::ImgSurfaceToPixbuf act on a Moz2D SourceSurface instead of a Thebes gfxASurface. r=mattwoodrow
This commit is contained in:
Родитель
998668c1ff
Коммит
6b3eea9e92
|
@ -8,6 +8,9 @@
|
|||
#include "gfxASurface.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
#include "imgIContainer.h"
|
||||
|
||||
|
@ -15,6 +18,10 @@
|
|||
|
||||
#include "nsImageToPixbuf.h"
|
||||
|
||||
using mozilla::gfx::DataSourceSurface;
|
||||
using mozilla::gfx::SurfaceFormat;
|
||||
using mozilla::RefPtr;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsImageToPixbuf, nsIImageToPixbuf)
|
||||
|
||||
inline unsigned char
|
||||
|
@ -36,7 +43,7 @@ nsImageToPixbuf::ConvertImageToPixbuf(imgIContainer* aImage)
|
|||
GdkPixbuf*
|
||||
nsImageToPixbuf::ImageToPixbuf(imgIContainer* aImage)
|
||||
{
|
||||
nsRefPtr<gfxASurface> surface =
|
||||
nsRefPtr<gfxASurface> thebesSurface =
|
||||
aImage->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_SYNC_DECODE);
|
||||
|
||||
|
@ -44,66 +51,81 @@ nsImageToPixbuf::ImageToPixbuf(imgIContainer* aImage)
|
|||
// in an imgINotificationObserver event, meaning that we're not allowed request
|
||||
// a sync decode. Presumably the originating event is something sensible like
|
||||
// OnStopFrame(), so we can just retry the call without a sync decode.
|
||||
if (!surface)
|
||||
surface = aImage->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_NONE);
|
||||
if (!thebesSurface)
|
||||
thebesSurface = aImage->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_NONE);
|
||||
|
||||
NS_ENSURE_TRUE(thebesSurface, nullptr);
|
||||
|
||||
RefPtr<SourceSurface> surface =
|
||||
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
|
||||
thebesSurface);
|
||||
NS_ENSURE_TRUE(surface, nullptr);
|
||||
|
||||
nsRefPtr<gfxImageSurface> frame(surface->GetAsReadableARGB32ImageSurface());
|
||||
NS_ENSURE_TRUE(frame, nullptr);
|
||||
|
||||
return ImgSurfaceToPixbuf(frame, frame->Width(), frame->Height());
|
||||
return SourceSurfaceToPixbuf(surface,
|
||||
surface->GetSize().width,
|
||||
surface->GetSize().height);
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
nsImageToPixbuf::ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface, int32_t aWidth, int32_t aHeight)
|
||||
nsImageToPixbuf::SourceSurfaceToPixbuf(SourceSurface* aSurface,
|
||||
int32_t aWidth,
|
||||
int32_t aHeight)
|
||||
{
|
||||
MOZ_ASSERT(aWidth <= aSurface->GetSize().width &&
|
||||
aHeight <= aSurface->GetSize().height,
|
||||
"Requested rect is bigger than the supplied surface");
|
||||
|
||||
GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
|
||||
aWidth, aHeight);
|
||||
if (!pixbuf)
|
||||
return nullptr;
|
||||
|
||||
uint32_t rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
guchar* pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
uint32_t destStride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
guchar* destPixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
|
||||
long cairoStride = aImgSurface->Stride();
|
||||
unsigned char* cairoData = aImgSurface->Data();
|
||||
RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
|
||||
DataSourceSurface::MappedSurface map;
|
||||
dataSurface->Map(DataSourceSurface::MapType::READ, &map);
|
||||
uint8_t* srcData = map.mData;
|
||||
int32_t srcStride = map.mStride;
|
||||
|
||||
gfxImageFormat format = aImgSurface->Format();
|
||||
SurfaceFormat format = dataSurface->GetFormat();
|
||||
|
||||
for (int32_t row = 0; row < aHeight; ++row) {
|
||||
for (int32_t col = 0; col < aWidth; ++col) {
|
||||
guchar* pixel = pixels + row * rowstride + 4 * col;
|
||||
guchar* destPixel = destPixels + row * destStride + 4 * col;
|
||||
|
||||
uint32_t* cairoPixel = reinterpret_cast<uint32_t*>
|
||||
((cairoData + row * cairoStride + 4 * col));
|
||||
uint32_t* srcPixel =
|
||||
reinterpret_cast<uint32_t*>((srcData + row * srcStride + 4 * col));
|
||||
|
||||
if (format == gfxImageFormatARGB32) {
|
||||
const uint8_t a = (*cairoPixel >> 24) & 0xFF;
|
||||
const uint8_t r = unpremultiply((*cairoPixel >> 16) & 0xFF, a);
|
||||
const uint8_t g = unpremultiply((*cairoPixel >> 8) & 0xFF, a);
|
||||
const uint8_t b = unpremultiply((*cairoPixel >> 0) & 0xFF, a);
|
||||
if (format == SurfaceFormat::B8G8R8A8) {
|
||||
const uint8_t a = (*srcPixel >> 24) & 0xFF;
|
||||
const uint8_t r = unpremultiply((*srcPixel >> 16) & 0xFF, a);
|
||||
const uint8_t g = unpremultiply((*srcPixel >> 8) & 0xFF, a);
|
||||
const uint8_t b = unpremultiply((*srcPixel >> 0) & 0xFF, a);
|
||||
|
||||
*pixel++ = r;
|
||||
*pixel++ = g;
|
||||
*pixel++ = b;
|
||||
*pixel++ = a;
|
||||
*destPixel++ = r;
|
||||
*destPixel++ = g;
|
||||
*destPixel++ = b;
|
||||
*destPixel++ = a;
|
||||
} else {
|
||||
NS_ASSERTION(format == gfxImageFormatRGB24,
|
||||
"unexpected format");
|
||||
const uint8_t r = (*cairoPixel >> 16) & 0xFF;
|
||||
const uint8_t g = (*cairoPixel >> 8) & 0xFF;
|
||||
const uint8_t b = (*cairoPixel >> 0) & 0xFF;
|
||||
MOZ_ASSERT(format == SurfaceFormat::B8G8R8X8);
|
||||
|
||||
*pixel++ = r;
|
||||
*pixel++ = g;
|
||||
*pixel++ = b;
|
||||
*pixel++ = 0xFF; // A
|
||||
const uint8_t r = (*srcPixel >> 16) & 0xFF;
|
||||
const uint8_t g = (*srcPixel >> 8) & 0xFF;
|
||||
const uint8_t b = (*srcPixel >> 0) & 0xFF;
|
||||
|
||||
*destPixel++ = r;
|
||||
*destPixel++ = g;
|
||||
*destPixel++ = b;
|
||||
*destPixel++ = 0xFF; // A
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataSurface->Unmap();
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
|
@ -135,5 +157,9 @@ nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, int32_t aWidth, int32_t
|
|||
context->Paint();
|
||||
}
|
||||
|
||||
return ImgSurfaceToPixbuf(imgSurface, aWidth, aHeight);
|
||||
RefPtr<SourceSurface> surface =
|
||||
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
|
||||
imgSurface);
|
||||
|
||||
return SourceSurfaceToPixbuf(surface, aWidth, aHeight);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,15 @@ class gfxASurface;
|
|||
class gfxPattern;
|
||||
class gfxImageSurface;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class SourceSurface;
|
||||
}
|
||||
}
|
||||
|
||||
class nsImageToPixbuf MOZ_FINAL : public nsIImageToPixbuf {
|
||||
typedef mozilla::gfx::SourceSurface SourceSurface;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(imgIContainer* aImage);
|
||||
|
@ -27,9 +35,11 @@ class nsImageToPixbuf MOZ_FINAL : public nsIImageToPixbuf {
|
|||
static GdkPixbuf* ImageToPixbuf(imgIContainer * aImage);
|
||||
static GdkPixbuf* SurfaceToPixbuf(gfxASurface* aSurface,
|
||||
int32_t aWidth, int32_t aHeight);
|
||||
static GdkPixbuf* SourceSurfaceToPixbuf(SourceSurface* aSurface,
|
||||
int32_t aWidth,
|
||||
int32_t aHeight);
|
||||
|
||||
private:
|
||||
static GdkPixbuf* ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface,
|
||||
int32_t aWidth, int32_t aHeight);
|
||||
~nsImageToPixbuf() {}
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче