Bug 775226 - Support CreateDrawTargetForData with Azure's CoreGraphics backend, r=jrmuizel

This commit is contained in:
Nicolas Silva 2012-07-26 14:06:23 -04:00
parent db4a8a6255
commit ac9c907a9b
3 changed files with 94 additions and 59 deletions

View File

@ -798,6 +798,77 @@ DrawTargetCG::DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest,
}
bool
DrawTargetCG::Init(unsigned char* aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat)
{
// XXX: we should come up with some consistent semantics for dealing
// with zero area drawtargets
if (aSize.width <= 0 || aSize.height <= 0 ||
// 32767 is the maximum size supported by cairo
// we clamp to that to make it easier to interoperate
aSize.width > 32767 || aSize.height > 32767) {
mColorSpace = NULL;
mCg = NULL;
mData = NULL;
return false;
}
//XXX: handle SurfaceFormat
//XXX: we'd be better off reusing the Colorspace across draw targets
mColorSpace = CGColorSpaceCreateDeviceRGB();
if (aData == NULL) {
// XXX: Currently, Init implicitly clears, that can often be a waste of time
mData = calloc(aSize.height * aStride, 1);
aData = static_cast<unsigned char*>(mData);
} else {
// mData == NULL means DrawTargetCG doesn't own the image data and will not
// delete it in the destructor
mData = NULL;
}
mSize = aSize;
int bitsPerComponent = 8;
CGBitmapInfo bitinfo;
bitinfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
// XXX: what should we do if this fails?
mCg = CGBitmapContextCreate (aData,
mSize.width,
mSize.height,
bitsPerComponent,
aStride,
mColorSpace,
bitinfo);
assert(mCg);
// CGContext's default to have the origin at the bottom left
// so flip it to the top left
CGContextTranslateCTM(mCg, 0, mSize.height);
CGContextScaleCTM(mCg, 1, -1);
// See Bug 722164 for performance details
// Medium or higher quality lead to expensive interpolation
// for canvas we want to use low quality interpolation
// to have competitive performance with other canvas
// implementation.
// XXX: Create input parameter to control interpolation and
// use the default for content.
CGContextSetInterpolationQuality(mCg, kCGInterpolationLow);
// XXX: set correct format
mFormat = FORMAT_B8G8R8A8;
return true;
}
bool
DrawTargetCG::Init(CGContextRef cgContext, const IntSize &aSize)
{
@ -834,66 +905,12 @@ DrawTargetCG::Init(CGContextRef cgContext, const IntSize &aSize)
}
bool
DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &)
DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &aFormat)
{
// XXX: we should come up with some consistent semantics for dealing
// with zero area drawtargets
if (aSize.width <= 0 || aSize.height <= 0 ||
// 32767 is the maximum size supported by cairo
// we clamp to that to make it easier to interoperate
aSize.width > 32767 || aSize.height > 32767) {
mColorSpace = NULL;
mCg = NULL;
mData = NULL;
return false;
}
//XXX: handle SurfaceFormat
//XXX: we'd be better off reusing the Colorspace across draw targets
mColorSpace = CGColorSpaceCreateDeviceRGB();
mSize = aSize;
int bitsPerComponent = 8;
int stride = mSize.width*4;
CGBitmapInfo bitinfo;
bitinfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
// XXX: currently we allocate ourselves so that we can easily return a gfxImageSurface
// we might not need to later if once we don't need to support gfxImageSurface
//XXX: currently Init implicitly clears, that can often be a waste of time
mData = calloc(mSize.height * stride, 1);
// XXX: what should we do if this fails?
mCg = CGBitmapContextCreate (mData,
mSize.width,
mSize.height,
bitsPerComponent,
stride,
mColorSpace,
bitinfo);
assert(mCg);
// CGContext's default to have the origin at the bottom left
// so flip it to the top left
CGContextTranslateCTM(mCg, 0, mSize.height);
CGContextScaleCTM(mCg, 1, -1);
// See Bug 722164 for performance details
// Medium or higher quality lead to expensive interpolation
// for canvas we want to use low quality interpolation
// to have competitive performance with other canvas
// implementation.
// XXX: Create input parameter to control interpolation and
// use the default for content.
CGContextSetInterpolationQuality(mCg, kCGInterpolationLow);
//XXX: set correct format
mFormat = FORMAT_B8G8R8A8;
return true;
int stride = aSize.width*4;
// Calling Init with aData == NULL will allocate.
return Init(NULL, aSize, stride, aFormat);
}
TemporaryRef<PathBuilder>

View File

@ -103,6 +103,7 @@ public:
//XXX: why do we take a reference to SurfaceFormat?
bool Init(const IntSize &aSize, SurfaceFormat&);
bool Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
bool Init(CGContextRef cgContext, const IntSize &aSize);
@ -149,6 +150,14 @@ private:
CGColorSpaceRef mColorSpace;
CGContextRef mCg;
/**
* A pointer to the image buffer if the buffer is owned by this class (set to
* NULL otherwise).
* The data is not considered owned by DrawTargetCG if the DrawTarget was
* created for a pre-existing buffer or if the buffer's lifetime is managed
* by CoreGraphics.
* Data owned by DrawTargetCG will be deallocated in the destructor.
*/
void *mData;
SurfaceFormat mFormat;

View File

@ -219,6 +219,15 @@ Factory::CreateDrawTargetForData(BackendType aBackend,
newTarget->Init(aData, aSize, aStride, aFormat);
return newTarget;
}
#endif
#ifdef XP_MACOSX
case BACKEND_COREGRAPHICS:
{
RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
if (newTarget->Init(aData, aSize, aStride, aFormat))
return newTarget;
break;
}
#endif
default:
gfxDebug() << "Invalid draw target type specified.";