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 * 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/. */ * 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 "gfxPlatform.h"
#include "gfxRect.h" #include "gfxRect.h"
@ -177,6 +180,22 @@ inline gfxMatrix ThebesMatrix(const Matrix &aMatrix)
aMatrix._22, aMatrix._31, aMatrix._32); 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) inline gfxASurface::gfxContentType ContentForFormat(const SurfaceFormat &aFormat)
{ {
switch (aFormat) { switch (aFormat) {
@ -245,3 +264,5 @@ inline gfxContext::GraphicsOperator ThebesOp(CompositionOp aOp)
} }
} }
#endif

View File

@ -9,6 +9,10 @@
#include "gfxImageSurface.h" #include "gfxImageSurface.h"
#include "cairo.h" #include "cairo.h"
#include "mozilla/gfx/2D.h"
#include "gfx2DGlue.h"
using namespace mozilla::gfx;
gfxImageSurface::gfxImageSurface() gfxImageSurface::gfxImageSurface()
: mSize(0, 0), : mSize(0, 0),
@ -171,32 +175,75 @@ gfxImageSurface::ComputeStride(const gfxIntSize& aSize, gfxImageFormat aFormat)
return stride; return stride;
} }
bool // helper function for the CopyFrom methods
gfxImageSurface::CopyFrom(gfxImageSurface *other) static void
CopyForStride(unsigned char* aDest, unsigned char* aSrc, const gfxIntSize& aSize, long aDestStride, long aSrcStride)
{ {
if (other->mSize != mSize) if (aDestStride == aSrcStride) {
{ memcpy (aDest, aSrc, aSrcStride * aSize.height);
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);
} else { } else {
int lineSize = NS_MIN(other->mStride, mStride); int lineSize = NS_MIN(aDestStride, aSrcStride);
for (int i = 0; i < mSize.height; i++) { for (int i = 0; i < aSize.height; i++) {
unsigned char *src = other->mData + other->mStride * i; unsigned char* src = aSrc + aSrcStride * i;
unsigned char *dst = mData + mStride * i; unsigned char* dst = aDest + aDestStride * i;
memcpy (dst, src, lineSize); 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; return true;
} }

View File

@ -13,6 +13,12 @@
class gfxSubimageSurface; class gfxSubimageSurface;
namespace mozilla {
namespace gfx {
class SourceSurface;
}
}
/** /**
* A raw image buffer. The format can be set in the constructor. Its main * 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, * 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 */ /* Fast copy from another image surface; returns TRUE if successful, FALSE otherwise */
bool CopyFrom (gfxImageSurface *other); 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 /* return new Subimage with pointing to original image starting from aRect.pos
* and size of aRect.size. New subimage keeping current image reference * and size of aRect.size. New subimage keeping current image reference
*/ */

View File

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