Bumping manifests a=b2g-bump
[gecko.git] / gfx / thebes / gfxWindowsSurface.cpp
blob58c9100520f2a359b1b97e86cd51a3a2ae6d7d6c
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 "gfxWindowsSurface.h"
7 #include "gfxContext.h"
8 #include "gfxPlatform.h"
10 #include "cairo.h"
11 #include "cairo-win32.h"
13 #include "nsString.h"
15 gfxWindowsSurface::gfxWindowsSurface(HWND wnd, uint32_t flags) :
16 mOwnsDC(true), mForPrinting(false), mWnd(wnd)
18 mDC = ::GetDC(mWnd);
19 InitWithDC(flags);
22 gfxWindowsSurface::gfxWindowsSurface(HDC dc, uint32_t flags) :
23 mOwnsDC(false), mForPrinting(false), mDC(dc), mWnd(nullptr)
25 if (flags & FLAG_TAKE_DC)
26 mOwnsDC = true;
28 #ifdef NS_PRINTING
29 if (flags & FLAG_FOR_PRINTING) {
30 Init(cairo_win32_printing_surface_create(mDC));
31 mForPrinting = true;
32 } else
33 #endif
34 InitWithDC(flags);
37 gfxWindowsSurface::gfxWindowsSurface(IDirect3DSurface9 *surface, uint32_t flags) :
38 mOwnsDC(false), mForPrinting(false), mDC(0), mWnd(nullptr)
40 cairo_surface_t *surf = cairo_win32_surface_create_with_d3dsurface9(surface);
41 Init(surf);
45 void
46 gfxWindowsSurface::MakeInvalid(gfxIntSize& size)
48 size = gfxIntSize(-1, -1);
51 gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& realSize, gfxImageFormat imageFormat) :
52 mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
54 gfxIntSize size(realSize);
55 if (!CheckSurfaceSize(size))
56 MakeInvalid(size);
58 cairo_surface_t *surf = cairo_win32_surface_create_with_dib((cairo_format_t)(int)imageFormat,
59 size.width, size.height);
61 Init(surf);
63 if (CairoStatus() == CAIRO_STATUS_SUCCESS) {
64 mDC = cairo_win32_surface_get_dc(CairoSurface());
65 RecordMemoryUsed(size.width * size.height * 4 + sizeof(gfxWindowsSurface));
66 } else {
67 mDC = nullptr;
71 gfxWindowsSurface::gfxWindowsSurface(HDC dc, const gfxIntSize& realSize, gfxImageFormat imageFormat) :
72 mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
74 gfxIntSize size(realSize);
75 if (!CheckSurfaceSize(size))
76 MakeInvalid(size);
78 cairo_surface_t *surf = cairo_win32_surface_create_with_ddb(dc, (cairo_format_t)(int)imageFormat,
79 size.width, size.height);
81 Init(surf);
83 if (mSurfaceValid) {
84 // DDBs will generally only use 3 bytes per pixel when RGB24
85 int bytesPerPixel = ((imageFormat == gfxImageFormat::RGB24) ? 3 : 4);
86 RecordMemoryUsed(size.width * size.height * bytesPerPixel + sizeof(gfxWindowsSurface));
89 if (CairoStatus() == 0)
90 mDC = cairo_win32_surface_get_dc(CairoSurface());
91 else
92 mDC = nullptr;
95 gfxWindowsSurface::gfxWindowsSurface(cairo_surface_t *csurf) :
96 mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
98 if (cairo_surface_status(csurf) == 0)
99 mDC = cairo_win32_surface_get_dc(csurf);
100 else
101 mDC = nullptr;
103 if (cairo_surface_get_type(csurf) == CAIRO_SURFACE_TYPE_WIN32_PRINTING)
104 mForPrinting = true;
106 Init(csurf, true);
109 void
110 gfxWindowsSurface::InitWithDC(uint32_t flags)
112 if (flags & FLAG_IS_TRANSPARENT) {
113 Init(cairo_win32_surface_create_with_alpha(mDC));
114 } else {
115 Init(cairo_win32_surface_create(mDC));
119 already_AddRefed<gfxASurface>
120 gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent,
121 const gfxIntSize& aSize)
123 if (!mSurface || !mSurfaceValid) {
124 return nullptr;
127 cairo_surface_t *surface;
128 if (!mForPrinting && GetContentType() == gfxContentType::COLOR_ALPHA) {
129 // When creating a similar surface to a transparent surface, ensure
130 // the new surface uses a DIB. cairo_surface_create_similar won't
131 // use a DIB for a gfxContentType::COLOR surface if this surface doesn't
132 // have a DIB (e.g. if we're a transparent window surface). But
133 // we need a DIB to perform well if the new surface is composited into
134 // a surface that's the result of create_similar(gfxContentType::COLOR_ALPHA)
135 // (e.g. a backbuffer for the window) --- that new surface *would*
136 // have a DIB.
137 surface =
138 cairo_win32_surface_create_with_dib((cairo_format_t)(int)gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent),
139 aSize.width, aSize.height);
140 } else {
141 surface =
142 cairo_surface_create_similar(mSurface, (cairo_content_t)(int)aContent,
143 aSize.width, aSize.height);
146 if (cairo_surface_status(surface)) {
147 cairo_surface_destroy(surface);
148 return nullptr;
151 nsRefPtr<gfxASurface> result = Wrap(surface, aSize);
152 cairo_surface_destroy(surface);
153 return result.forget();
156 gfxWindowsSurface::~gfxWindowsSurface()
158 if (mOwnsDC) {
159 if (mWnd)
160 ::ReleaseDC(mWnd, mDC);
161 else
162 ::DeleteDC(mDC);
167 gfxWindowsSurface::GetDCWithClip(gfxContext *ctx)
169 return cairo_win32_get_dc_with_clip (ctx->GetCairo());
173 gfxWindowsSurface::GetDC()
175 return cairo_win32_surface_get_dc (CairoSurface());
179 already_AddRefed<gfxImageSurface>
180 gfxWindowsSurface::GetAsImageSurface()
182 if (!mSurfaceValid) {
183 NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
184 return nullptr;
187 NS_ASSERTION(CairoSurface() != nullptr, "CairoSurface() shouldn't be nullptr when mSurfaceValid is TRUE!");
189 if (mForPrinting)
190 return nullptr;
192 cairo_surface_t *isurf = cairo_win32_surface_get_image(CairoSurface());
193 if (!isurf)
194 return nullptr;
196 nsRefPtr<gfxImageSurface> result = gfxASurface::Wrap(isurf).downcast<gfxImageSurface>();
197 result->SetOpaqueRect(GetOpaqueRect());
199 return result.forget();
202 nsresult
203 gfxWindowsSurface::BeginPrinting(const nsAString& aTitle,
204 const nsAString& aPrintToFileName)
206 #ifdef NS_PRINTING
207 #define DOC_TITLE_LENGTH (MAX_PATH-1)
208 DOCINFOW docinfo;
210 nsString titleStr(aTitle);
211 if (titleStr.Length() > DOC_TITLE_LENGTH) {
212 titleStr.SetLength(DOC_TITLE_LENGTH-3);
213 titleStr.AppendLiteral("...");
216 nsString docName(aPrintToFileName);
217 docinfo.cbSize = sizeof(docinfo);
218 docinfo.lpszDocName = titleStr.Length() > 0 ? titleStr.get() : L"Mozilla Document";
219 docinfo.lpszOutput = docName.Length() > 0 ? docName.get() : nullptr;
220 docinfo.lpszDatatype = nullptr;
221 docinfo.fwType = 0;
223 ::StartDocW(mDC, &docinfo);
225 return NS_OK;
226 #else
227 return NS_ERROR_FAILURE;
228 #endif
231 nsresult
232 gfxWindowsSurface::EndPrinting()
234 #ifdef NS_PRINTING
235 int result = ::EndDoc(mDC);
236 if (result <= 0)
237 return NS_ERROR_FAILURE;
239 return NS_OK;
240 #else
241 return NS_ERROR_FAILURE;
242 #endif
245 nsresult
246 gfxWindowsSurface::AbortPrinting()
248 #ifdef NS_PRINTING
249 int result = ::AbortDoc(mDC);
250 if (result <= 0)
251 return NS_ERROR_FAILURE;
252 return NS_OK;
253 #else
254 return NS_ERROR_FAILURE;
255 #endif
258 nsresult
259 gfxWindowsSurface::BeginPage()
261 #ifdef NS_PRINTING
262 int result = ::StartPage(mDC);
263 if (result <= 0)
264 return NS_ERROR_FAILURE;
265 return NS_OK;
266 #else
267 return NS_ERROR_FAILURE;
268 #endif
271 nsresult
272 gfxWindowsSurface::EndPage()
274 #ifdef NS_PRINTING
275 if (mForPrinting)
276 cairo_surface_show_page(CairoSurface());
277 int result = ::EndPage(mDC);
278 if (result <= 0)
279 return NS_ERROR_FAILURE;
280 return NS_OK;
281 #else
282 return NS_ERROR_FAILURE;
283 #endif
286 int32_t
287 gfxWindowsSurface::GetDefaultContextFlags() const
289 if (mForPrinting)
290 return gfxContext::FLAG_SIMPLIFY_OPERATORS |
291 gfxContext::FLAG_DISABLE_SNAPPING |
292 gfxContext::FLAG_DISABLE_COPY_BACKGROUND;
294 return 0;
297 const gfxIntSize
298 gfxWindowsSurface::GetSize() const
300 if (!mSurfaceValid) {
301 NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
302 return gfxIntSize(-1, -1);
305 NS_ASSERTION(mSurface != nullptr, "CairoSurface() shouldn't be nullptr when mSurfaceValid is TRUE!");
307 return gfxIntSize(cairo_win32_surface_get_width(mSurface),
308 cairo_win32_surface_get_height(mSurface));
311 gfxMemoryLocation
312 gfxWindowsSurface::GetMemoryLocation() const
314 return gfxMemoryLocation::IN_PROCESS_NONHEAP;