Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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"
10 #include "cairo-quartz.h"
12 void
13 gfxQuartzSurface::MakeInvalid()
14 {
15 mSize = gfxIntSize(-1, -1);
16 }
18 gfxQuartzSurface::gfxQuartzSurface(const gfxSize& desiredSize, gfxImageFormat format,
19 bool aForPrinting)
20 : mCGContext(nullptr), mSize(desiredSize), mForPrinting(aForPrinting)
21 {
22 gfxIntSize size((unsigned int) floor(desiredSize.width),
23 (unsigned int) floor(desiredSize.height));
24 if (!CheckSurfaceSize(size))
25 MakeInvalid();
27 unsigned int width = static_cast<unsigned int>(mSize.width);
28 unsigned int height = static_cast<unsigned int>(mSize.height);
30 cairo_surface_t *surf = cairo_quartz_surface_create
31 ((cairo_format_t) format, width, height);
33 mCGContext = cairo_quartz_surface_get_cg_context (surf);
35 CGContextRetain(mCGContext);
37 Init(surf);
38 if (mSurfaceValid) {
39 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
40 }
41 }
43 gfxQuartzSurface::gfxQuartzSurface(CGContextRef context,
44 const gfxSize& desiredSize,
45 bool aForPrinting)
46 : mCGContext(context), mSize(desiredSize), mForPrinting(aForPrinting)
47 {
48 gfxIntSize size((unsigned int) floor(desiredSize.width),
49 (unsigned int) floor(desiredSize.height));
50 if (!CheckSurfaceSize(size))
51 MakeInvalid();
53 unsigned int width = static_cast<unsigned int>(mSize.width);
54 unsigned int height = static_cast<unsigned int>(mSize.height);
56 cairo_surface_t *surf =
57 cairo_quartz_surface_create_for_cg_context(context,
58 width, height);
60 CGContextRetain(mCGContext);
62 Init(surf);
63 if (mSurfaceValid) {
64 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
65 }
66 }
68 gfxQuartzSurface::gfxQuartzSurface(CGContextRef context,
69 const gfxIntSize& size,
70 bool aForPrinting)
71 : mCGContext(context), mSize(size), mForPrinting(aForPrinting)
72 {
73 if (!CheckSurfaceSize(size))
74 MakeInvalid();
76 unsigned int width = static_cast<unsigned int>(mSize.width);
77 unsigned int height = static_cast<unsigned int>(mSize.height);
79 cairo_surface_t *surf =
80 cairo_quartz_surface_create_for_cg_context(context,
81 width, height);
83 CGContextRetain(mCGContext);
85 Init(surf);
86 if (mSurfaceValid) {
87 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
88 }
89 }
91 gfxQuartzSurface::gfxQuartzSurface(cairo_surface_t *csurf,
92 const gfxIntSize& aSize,
93 bool aForPrinting) :
94 mSize(aSize), mForPrinting(aForPrinting)
95 {
96 mCGContext = cairo_quartz_surface_get_cg_context (csurf);
97 CGContextRetain (mCGContext);
99 Init(csurf, true);
100 }
102 gfxQuartzSurface::gfxQuartzSurface(unsigned char *data,
103 const gfxSize& desiredSize,
104 long stride,
105 gfxImageFormat format,
106 bool aForPrinting)
107 : mCGContext(nullptr), mSize(desiredSize), mForPrinting(aForPrinting)
108 {
109 gfxIntSize size((unsigned int) floor(desiredSize.width),
110 (unsigned int) floor(desiredSize.height));
111 if (!CheckSurfaceSize(size))
112 MakeInvalid();
114 unsigned int width = static_cast<unsigned int>(mSize.width);
115 unsigned int height = static_cast<unsigned int>(mSize.height);
117 cairo_surface_t *surf = cairo_quartz_surface_create_for_data
118 (data, (cairo_format_t) format, width, height, stride);
120 mCGContext = cairo_quartz_surface_get_cg_context (surf);
122 CGContextRetain(mCGContext);
124 Init(surf);
125 if (mSurfaceValid) {
126 RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface));
127 }
128 }
130 gfxQuartzSurface::gfxQuartzSurface(unsigned char *data,
131 const gfxIntSize& aSize,
132 long stride,
133 gfxImageFormat format,
134 bool aForPrinting)
135 : mCGContext(nullptr), mSize(aSize.width, aSize.height), mForPrinting(aForPrinting)
136 {
137 if (!CheckSurfaceSize(aSize))
138 MakeInvalid();
140 cairo_surface_t *surf = cairo_quartz_surface_create_for_data
141 (data, (cairo_format_t) format, aSize.width, aSize.height, stride);
143 mCGContext = cairo_quartz_surface_get_cg_context (surf);
145 CGContextRetain(mCGContext);
147 Init(surf);
148 if (mSurfaceValid) {
149 RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface));
150 }
151 }
153 already_AddRefed<gfxASurface>
154 gfxQuartzSurface::CreateSimilarSurface(gfxContentType aType,
155 const gfxIntSize& aSize)
156 {
157 cairo_surface_t *surface =
158 cairo_quartz_surface_create_cg_layer(mSurface, (cairo_content_t)aType,
159 aSize.width, aSize.height);
160 if (cairo_surface_status(surface)) {
161 cairo_surface_destroy(surface);
162 return nullptr;
163 }
165 nsRefPtr<gfxASurface> result = Wrap(surface, aSize);
166 cairo_surface_destroy(surface);
167 return result.forget();
168 }
170 CGContextRef
171 gfxQuartzSurface::GetCGContextWithClip(gfxContext *ctx)
172 {
173 return cairo_quartz_get_cg_context_with_clip(ctx->GetCairo());
174 }
176 int32_t gfxQuartzSurface::GetDefaultContextFlags() const
177 {
178 if (mForPrinting)
179 return gfxContext::FLAG_DISABLE_SNAPPING |
180 gfxContext::FLAG_DISABLE_COPY_BACKGROUND;
182 return 0;
183 }
185 already_AddRefed<gfxImageSurface> gfxQuartzSurface::GetAsImageSurface()
186 {
187 cairo_surface_t *surface = cairo_quartz_surface_get_image(mSurface);
188 if (!surface || cairo_surface_status(surface))
189 return nullptr;
191 nsRefPtr<gfxASurface> img = Wrap(surface);
193 // cairo_quartz_surface_get_image returns a referenced image, and thebes
194 // shares the refcounts of Cairo surfaces. However, Wrap also adds a
195 // reference to the image. We need to remove one of these references
196 // explicitly so we don't leak.
197 img->Release();
199 img->SetOpaqueRect(GetOpaqueRect());
201 return img.forget().downcast<gfxImageSurface>();
202 }
204 gfxQuartzSurface::~gfxQuartzSurface()
205 {
206 CGContextRelease(mCGContext);
207 }