Bug 746896. Fix a bug with printing Azure canvas. r=joe

This commit is contained in:
Nicholas Cameron 2012-06-15 10:00:44 +12:00
parent 072a74616f
commit a5a0aba836
4 changed files with 106 additions and 32 deletions

View File

@ -2,6 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_2D_GLUE_H
#define GFX_2D_GLUE_H
#include "gfxPlatform.h"
#include "gfxRect.h"
@ -177,6 +180,22 @@ inline gfxMatrix ThebesMatrix(const Matrix &aMatrix)
aMatrix._22, aMatrix._31, aMatrix._32);
}
inline gfxASurface::gfxImageFormat SurfaceFormatToImageFormat(SurfaceFormat aFormat)
{
switch (aFormat) {
case FORMAT_B8G8R8A8:
return gfxASurface::ImageFormatARGB32;
case FORMAT_B8G8R8X8:
return gfxASurface::ImageFormatRGB24;
case FORMAT_R5G6B5:
return gfxASurface::ImageFormatRGB16_565;
case FORMAT_A8:
return gfxASurface::ImageFormatA8;
default:
return gfxASurface::ImageFormatUnknown;
}
}
inline gfxASurface::gfxContentType ContentForFormat(const SurfaceFormat &aFormat)
{
switch (aFormat) {
@ -245,3 +264,5 @@ inline gfxContext::GraphicsOperator ThebesOp(CompositionOp aOp)
}
}
#endif

View File

@ -9,6 +9,10 @@
#include "gfxImageSurface.h"
#include "cairo.h"
#include "mozilla/gfx/2D.h"
#include "gfx2DGlue.h"
using namespace mozilla::gfx;
gfxImageSurface::gfxImageSurface()
: mSize(0, 0),
@ -171,32 +175,75 @@ gfxImageSurface::ComputeStride(const gfxIntSize& aSize, gfxImageFormat aFormat)
return stride;
}
bool
gfxImageSurface::CopyFrom(gfxImageSurface *other)
// helper function for the CopyFrom methods
static void
CopyForStride(unsigned char* aDest, unsigned char* aSrc, const gfxIntSize& aSize, long aDestStride, long aSrcStride)
{
if (other->mSize != mSize)
{
return false;
}
if (other->mFormat != mFormat &&
!(other->mFormat == ImageFormatARGB32 && mFormat == ImageFormatRGB24) &&
!(other->mFormat == ImageFormatRGB24 && mFormat == ImageFormatARGB32))
{
return false;
}
if (other->mStride == mStride) {
memcpy (mData, other->mData, mStride * mSize.height);
if (aDestStride == aSrcStride) {
memcpy (aDest, aSrc, aSrcStride * aSize.height);
} else {
int lineSize = NS_MIN(other->mStride, mStride);
for (int i = 0; i < mSize.height; i++) {
unsigned char *src = other->mData + other->mStride * i;
unsigned char *dst = mData + mStride * i;
int lineSize = NS_MIN(aDestStride, aSrcStride);
for (int i = 0; i < aSize.height; i++) {
unsigned char* src = aSrc + aSrcStride * i;
unsigned char* dst = aDest + aDestStride * i;
memcpy (dst, src, lineSize);
}
}
}
// helper function for the CopyFrom methods
static bool
FormatsAreCompatible(gfxASurface::gfxImageFormat a1, gfxASurface::gfxImageFormat a2)
{
if (a1 != a2 &&
!(a1 == gfxASurface::ImageFormatARGB32 &&
a2 == gfxASurface::ImageFormatRGB24) &&
!(a1 == gfxASurface::ImageFormatRGB24 &&
a2 == gfxASurface::ImageFormatARGB32)) {
return false;
}
return true;
}
bool
gfxImageSurface::CopyFrom (SourceSurface *aSurface)
{
mozilla::RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
if (!data) {
return false;
}
gfxIntSize size(data->GetSize().width, data->GetSize().height);
if (size != mSize) {
return false;
}
if (!FormatsAreCompatible(SurfaceFormatToImageFormat(aSurface->GetFormat()),
mFormat)) {
return false;
}
CopyForStride(mData, data->GetData(), size, mStride, data->Stride());
return true;
}
bool
gfxImageSurface::CopyFrom(gfxImageSurface *other)
{
if (other->mSize != mSize) {
return false;
}
if (!FormatsAreCompatible(other->mFormat, mFormat)) {
return false;
}
CopyForStride(mData, other->mData, mSize, mStride, other->mStride);
return true;
}

View File

@ -13,6 +13,12 @@
class gfxSubimageSurface;
namespace mozilla {
namespace gfx {
class SourceSurface;
}
}
/**
* A raw image buffer. The format can be set in the constructor. Its main
* purpose is for storing read-only images and using it as a source surface,
@ -69,6 +75,12 @@ public:
/* Fast copy from another image surface; returns TRUE if successful, FALSE otherwise */
bool CopyFrom (gfxImageSurface *other);
/**
* Fast copy from a source surface; returns TRUE if successful, FALSE otherwise
* Assumes that the format of this surface is compatable with aSurface
*/
bool CopyFrom (mozilla::gfx::SourceSurface *aSurface);
/* return new Subimage with pointing to original image starting from aRect.pos
* and size of aRect.size. New subimage keeping current image reference
*/

View File

@ -559,13 +559,6 @@ gfxPlatform::GetScaledFontForFont(gfxFont *aFont)
return scaledFont;
}
cairo_user_data_key_t kDrawSourceSurface;
static void
DataSourceSurfaceDestroy(void *dataSourceSurface)
{
static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
}
UserDataKey kThebesSurfaceKey;
void
DestroyThebesSurface(void *data)
@ -605,11 +598,12 @@ gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
IntSize size = data->GetSize();
gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
surf =
new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
data->Stride(), format);
surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
// We need to make a copy here because data might change its data under us
nsRefPtr<gfxImageSurface> imageSurf = new gfxImageSurface(gfxIntSize(size.width, size.height), format, false);
bool resultOfCopy = imageSurf->CopyFrom(source);
NS_ASSERTION(resultOfCopy, "Failed to copy surface.");
surf = imageSurf;
}
// add a reference to be held by the drawTarget