michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "gfxQuartzSurface.h" michael@0: #include "gfxContext.h" michael@0: #include "gfxImageSurface.h" michael@0: michael@0: #include "cairo-quartz.h" michael@0: michael@0: void michael@0: gfxQuartzSurface::MakeInvalid() michael@0: { michael@0: mSize = gfxIntSize(-1, -1); michael@0: } michael@0: michael@0: gfxQuartzSurface::gfxQuartzSurface(const gfxSize& desiredSize, gfxImageFormat format, michael@0: bool aForPrinting) michael@0: : mCGContext(nullptr), mSize(desiredSize), mForPrinting(aForPrinting) michael@0: { michael@0: gfxIntSize size((unsigned int) floor(desiredSize.width), michael@0: (unsigned int) floor(desiredSize.height)); michael@0: if (!CheckSurfaceSize(size)) michael@0: MakeInvalid(); michael@0: michael@0: unsigned int width = static_cast(mSize.width); michael@0: unsigned int height = static_cast(mSize.height); michael@0: michael@0: cairo_surface_t *surf = cairo_quartz_surface_create michael@0: ((cairo_format_t) format, width, height); michael@0: michael@0: mCGContext = cairo_quartz_surface_get_cg_context (surf); michael@0: michael@0: CGContextRetain(mCGContext); michael@0: michael@0: Init(surf); michael@0: if (mSurfaceValid) { michael@0: RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); michael@0: } michael@0: } michael@0: michael@0: gfxQuartzSurface::gfxQuartzSurface(CGContextRef context, michael@0: const gfxSize& desiredSize, michael@0: bool aForPrinting) michael@0: : mCGContext(context), mSize(desiredSize), mForPrinting(aForPrinting) michael@0: { michael@0: gfxIntSize size((unsigned int) floor(desiredSize.width), michael@0: (unsigned int) floor(desiredSize.height)); michael@0: if (!CheckSurfaceSize(size)) michael@0: MakeInvalid(); michael@0: michael@0: unsigned int width = static_cast(mSize.width); michael@0: unsigned int height = static_cast(mSize.height); michael@0: michael@0: cairo_surface_t *surf = michael@0: cairo_quartz_surface_create_for_cg_context(context, michael@0: width, height); michael@0: michael@0: CGContextRetain(mCGContext); michael@0: michael@0: Init(surf); michael@0: if (mSurfaceValid) { michael@0: RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); michael@0: } michael@0: } michael@0: michael@0: gfxQuartzSurface::gfxQuartzSurface(CGContextRef context, michael@0: const gfxIntSize& size, michael@0: bool aForPrinting) michael@0: : mCGContext(context), mSize(size), mForPrinting(aForPrinting) michael@0: { michael@0: if (!CheckSurfaceSize(size)) michael@0: MakeInvalid(); michael@0: michael@0: unsigned int width = static_cast(mSize.width); michael@0: unsigned int height = static_cast(mSize.height); michael@0: michael@0: cairo_surface_t *surf = michael@0: cairo_quartz_surface_create_for_cg_context(context, michael@0: width, height); michael@0: michael@0: CGContextRetain(mCGContext); michael@0: michael@0: Init(surf); michael@0: if (mSurfaceValid) { michael@0: RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); michael@0: } michael@0: } michael@0: michael@0: gfxQuartzSurface::gfxQuartzSurface(cairo_surface_t *csurf, michael@0: const gfxIntSize& aSize, michael@0: bool aForPrinting) : michael@0: mSize(aSize), mForPrinting(aForPrinting) michael@0: { michael@0: mCGContext = cairo_quartz_surface_get_cg_context (csurf); michael@0: CGContextRetain (mCGContext); michael@0: michael@0: Init(csurf, true); michael@0: } michael@0: michael@0: gfxQuartzSurface::gfxQuartzSurface(unsigned char *data, michael@0: const gfxSize& desiredSize, michael@0: long stride, michael@0: gfxImageFormat format, michael@0: bool aForPrinting) michael@0: : mCGContext(nullptr), mSize(desiredSize), mForPrinting(aForPrinting) michael@0: { michael@0: gfxIntSize size((unsigned int) floor(desiredSize.width), michael@0: (unsigned int) floor(desiredSize.height)); michael@0: if (!CheckSurfaceSize(size)) michael@0: MakeInvalid(); michael@0: michael@0: unsigned int width = static_cast(mSize.width); michael@0: unsigned int height = static_cast(mSize.height); michael@0: michael@0: cairo_surface_t *surf = cairo_quartz_surface_create_for_data michael@0: (data, (cairo_format_t) format, width, height, stride); michael@0: michael@0: mCGContext = cairo_quartz_surface_get_cg_context (surf); michael@0: michael@0: CGContextRetain(mCGContext); michael@0: michael@0: Init(surf); michael@0: if (mSurfaceValid) { michael@0: RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface)); michael@0: } michael@0: } michael@0: michael@0: gfxQuartzSurface::gfxQuartzSurface(unsigned char *data, michael@0: const gfxIntSize& aSize, michael@0: long stride, michael@0: gfxImageFormat format, michael@0: bool aForPrinting) michael@0: : mCGContext(nullptr), mSize(aSize.width, aSize.height), mForPrinting(aForPrinting) michael@0: { michael@0: if (!CheckSurfaceSize(aSize)) michael@0: MakeInvalid(); michael@0: michael@0: cairo_surface_t *surf = cairo_quartz_surface_create_for_data michael@0: (data, (cairo_format_t) format, aSize.width, aSize.height, stride); michael@0: michael@0: mCGContext = cairo_quartz_surface_get_cg_context (surf); michael@0: michael@0: CGContextRetain(mCGContext); michael@0: michael@0: Init(surf); michael@0: if (mSurfaceValid) { michael@0: RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface)); michael@0: } michael@0: } michael@0: michael@0: already_AddRefed michael@0: gfxQuartzSurface::CreateSimilarSurface(gfxContentType aType, michael@0: const gfxIntSize& aSize) michael@0: { michael@0: cairo_surface_t *surface = michael@0: cairo_quartz_surface_create_cg_layer(mSurface, (cairo_content_t)aType, michael@0: aSize.width, aSize.height); michael@0: if (cairo_surface_status(surface)) { michael@0: cairo_surface_destroy(surface); michael@0: return nullptr; michael@0: } michael@0: michael@0: nsRefPtr result = Wrap(surface, aSize); michael@0: cairo_surface_destroy(surface); michael@0: return result.forget(); michael@0: } michael@0: michael@0: CGContextRef michael@0: gfxQuartzSurface::GetCGContextWithClip(gfxContext *ctx) michael@0: { michael@0: return cairo_quartz_get_cg_context_with_clip(ctx->GetCairo()); michael@0: } michael@0: michael@0: int32_t gfxQuartzSurface::GetDefaultContextFlags() const michael@0: { michael@0: if (mForPrinting) michael@0: return gfxContext::FLAG_DISABLE_SNAPPING | michael@0: gfxContext::FLAG_DISABLE_COPY_BACKGROUND; michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: already_AddRefed gfxQuartzSurface::GetAsImageSurface() michael@0: { michael@0: cairo_surface_t *surface = cairo_quartz_surface_get_image(mSurface); michael@0: if (!surface || cairo_surface_status(surface)) michael@0: return nullptr; michael@0: michael@0: nsRefPtr img = Wrap(surface); michael@0: michael@0: // cairo_quartz_surface_get_image returns a referenced image, and thebes michael@0: // shares the refcounts of Cairo surfaces. However, Wrap also adds a michael@0: // reference to the image. We need to remove one of these references michael@0: // explicitly so we don't leak. michael@0: img->Release(); michael@0: michael@0: img->SetOpaqueRect(GetOpaqueRect()); michael@0: michael@0: return img.forget().downcast(); michael@0: } michael@0: michael@0: gfxQuartzSurface::~gfxQuartzSurface() michael@0: { michael@0: CGContextRelease(mCGContext); michael@0: }