|
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/. */ |
|
5 |
|
6 #include "gfxQuartzSurface.h" |
|
7 #include "gfxContext.h" |
|
8 #include "gfxImageSurface.h" |
|
9 |
|
10 #include "cairo-quartz.h" |
|
11 |
|
12 void |
|
13 gfxQuartzSurface::MakeInvalid() |
|
14 { |
|
15 mSize = gfxIntSize(-1, -1); |
|
16 } |
|
17 |
|
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(); |
|
26 |
|
27 unsigned int width = static_cast<unsigned int>(mSize.width); |
|
28 unsigned int height = static_cast<unsigned int>(mSize.height); |
|
29 |
|
30 cairo_surface_t *surf = cairo_quartz_surface_create |
|
31 ((cairo_format_t) format, width, height); |
|
32 |
|
33 mCGContext = cairo_quartz_surface_get_cg_context (surf); |
|
34 |
|
35 CGContextRetain(mCGContext); |
|
36 |
|
37 Init(surf); |
|
38 if (mSurfaceValid) { |
|
39 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); |
|
40 } |
|
41 } |
|
42 |
|
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(); |
|
52 |
|
53 unsigned int width = static_cast<unsigned int>(mSize.width); |
|
54 unsigned int height = static_cast<unsigned int>(mSize.height); |
|
55 |
|
56 cairo_surface_t *surf = |
|
57 cairo_quartz_surface_create_for_cg_context(context, |
|
58 width, height); |
|
59 |
|
60 CGContextRetain(mCGContext); |
|
61 |
|
62 Init(surf); |
|
63 if (mSurfaceValid) { |
|
64 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); |
|
65 } |
|
66 } |
|
67 |
|
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(); |
|
75 |
|
76 unsigned int width = static_cast<unsigned int>(mSize.width); |
|
77 unsigned int height = static_cast<unsigned int>(mSize.height); |
|
78 |
|
79 cairo_surface_t *surf = |
|
80 cairo_quartz_surface_create_for_cg_context(context, |
|
81 width, height); |
|
82 |
|
83 CGContextRetain(mCGContext); |
|
84 |
|
85 Init(surf); |
|
86 if (mSurfaceValid) { |
|
87 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); |
|
88 } |
|
89 } |
|
90 |
|
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); |
|
98 |
|
99 Init(csurf, true); |
|
100 } |
|
101 |
|
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(); |
|
113 |
|
114 unsigned int width = static_cast<unsigned int>(mSize.width); |
|
115 unsigned int height = static_cast<unsigned int>(mSize.height); |
|
116 |
|
117 cairo_surface_t *surf = cairo_quartz_surface_create_for_data |
|
118 (data, (cairo_format_t) format, width, height, stride); |
|
119 |
|
120 mCGContext = cairo_quartz_surface_get_cg_context (surf); |
|
121 |
|
122 CGContextRetain(mCGContext); |
|
123 |
|
124 Init(surf); |
|
125 if (mSurfaceValid) { |
|
126 RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface)); |
|
127 } |
|
128 } |
|
129 |
|
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(); |
|
139 |
|
140 cairo_surface_t *surf = cairo_quartz_surface_create_for_data |
|
141 (data, (cairo_format_t) format, aSize.width, aSize.height, stride); |
|
142 |
|
143 mCGContext = cairo_quartz_surface_get_cg_context (surf); |
|
144 |
|
145 CGContextRetain(mCGContext); |
|
146 |
|
147 Init(surf); |
|
148 if (mSurfaceValid) { |
|
149 RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface)); |
|
150 } |
|
151 } |
|
152 |
|
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 } |
|
164 |
|
165 nsRefPtr<gfxASurface> result = Wrap(surface, aSize); |
|
166 cairo_surface_destroy(surface); |
|
167 return result.forget(); |
|
168 } |
|
169 |
|
170 CGContextRef |
|
171 gfxQuartzSurface::GetCGContextWithClip(gfxContext *ctx) |
|
172 { |
|
173 return cairo_quartz_get_cg_context_with_clip(ctx->GetCairo()); |
|
174 } |
|
175 |
|
176 int32_t gfxQuartzSurface::GetDefaultContextFlags() const |
|
177 { |
|
178 if (mForPrinting) |
|
179 return gfxContext::FLAG_DISABLE_SNAPPING | |
|
180 gfxContext::FLAG_DISABLE_COPY_BACKGROUND; |
|
181 |
|
182 return 0; |
|
183 } |
|
184 |
|
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; |
|
190 |
|
191 nsRefPtr<gfxASurface> img = Wrap(surface); |
|
192 |
|
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(); |
|
198 |
|
199 img->SetOpaqueRect(GetOpaqueRect()); |
|
200 |
|
201 return img.forget().downcast<gfxImageSurface>(); |
|
202 } |
|
203 |
|
204 gfxQuartzSurface::~gfxQuartzSurface() |
|
205 { |
|
206 CGContextRelease(mCGContext); |
|
207 } |