1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "gfxQuartzSurface.h"
7 #include "gfxContext.h"
8 #include "gfxImageSurface.h"
9 #include "mozilla/gfx/2D.h"
10 #include "mozilla/gfx/HelpersCairo.h"
12 #include "cairo-quartz.h"
14 void gfxQuartzSurface::MakeInvalid() { mSize
= mozilla::gfx::IntSize(-1, -1); }
16 gfxQuartzSurface::gfxQuartzSurface(const mozilla::gfx::IntSize
& desiredSize
,
17 gfxImageFormat format
)
18 : mCGContext(nullptr), mSize(desiredSize
) {
19 if (!mozilla::gfx::Factory::CheckSurfaceSize(desiredSize
)) MakeInvalid();
21 unsigned int width
= static_cast<unsigned int>(mSize
.width
);
22 unsigned int height
= static_cast<unsigned int>(mSize
.height
);
24 cairo_format_t cformat
= GfxFormatToCairoFormat(format
);
25 cairo_surface_t
* surf
= cairo_quartz_surface_create(cformat
, width
, height
);
27 mCGContext
= cairo_quartz_surface_get_cg_context(surf
);
29 CGContextRetain(mCGContext
);
33 RecordMemoryUsed(mSize
.height
* 4 + sizeof(gfxQuartzSurface
));
37 gfxQuartzSurface::gfxQuartzSurface(CGContextRef context
,
38 const mozilla::gfx::IntSize
& size
)
39 : mCGContext(context
), mSize(size
) {
40 if (!mozilla::gfx::Factory::CheckSurfaceSize(size
)) MakeInvalid();
42 unsigned int width
= static_cast<unsigned int>(mSize
.width
);
43 unsigned int height
= static_cast<unsigned int>(mSize
.height
);
45 cairo_surface_t
* surf
=
46 cairo_quartz_surface_create_for_cg_context(context
, width
, height
);
48 CGContextRetain(mCGContext
);
52 RecordMemoryUsed(mSize
.height
* 4 + sizeof(gfxQuartzSurface
));
56 gfxQuartzSurface::gfxQuartzSurface(cairo_surface_t
* csurf
,
57 const mozilla::gfx::IntSize
& aSize
)
59 mCGContext
= cairo_quartz_surface_get_cg_context(csurf
);
60 CGContextRetain(mCGContext
);
65 gfxQuartzSurface::gfxQuartzSurface(unsigned char* data
,
66 const mozilla::gfx::IntSize
& aSize
,
67 long stride
, gfxImageFormat format
)
68 : mCGContext(nullptr), mSize(aSize
.width
, aSize
.height
) {
69 if (!mozilla::gfx::Factory::CheckSurfaceSize(aSize
)) MakeInvalid();
71 cairo_format_t cformat
= GfxFormatToCairoFormat(format
);
72 cairo_surface_t
* surf
= cairo_quartz_surface_create_for_data(
73 data
, cformat
, aSize
.width
, aSize
.height
, stride
);
75 mCGContext
= cairo_quartz_surface_get_cg_context(surf
);
77 CGContextRetain(mCGContext
);
81 RecordMemoryUsed(mSize
.height
* stride
+ sizeof(gfxQuartzSurface
));
85 already_AddRefed
<gfxASurface
> gfxQuartzSurface::CreateSimilarSurface(
86 gfxContentType aType
, const mozilla::gfx::IntSize
& aSize
) {
87 cairo_surface_t
* surface
= cairo_quartz_surface_create_cg_layer(
88 mSurface
, (cairo_content_t
)aType
, aSize
.width
, aSize
.height
);
89 if (cairo_surface_status(surface
)) {
90 cairo_surface_destroy(surface
);
94 RefPtr
<gfxASurface
> result
= Wrap(surface
, aSize
);
95 cairo_surface_destroy(surface
);
96 return result
.forget();
99 already_AddRefed
<gfxImageSurface
> gfxQuartzSurface::GetAsImageSurface() {
100 cairo_surface_t
* surface
= cairo_quartz_surface_get_image(mSurface
);
101 if (!surface
|| cairo_surface_status(surface
)) return nullptr;
103 RefPtr
<gfxASurface
> img
= Wrap(surface
);
105 // cairo_quartz_surface_get_image returns a referenced image, and thebes
106 // shares the refcounts of Cairo surfaces. However, Wrap also adds a
107 // reference to the image. We need to remove one of these references
108 // explicitly so we don't leak.
109 img
.get()->Release();
111 img
->SetOpaqueRect(GetOpaqueRect());
113 return img
.forget().downcast
<gfxImageSurface
>();
116 gfxQuartzSurface::~gfxQuartzSurface() { CGContextRelease(mCGContext
); }