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"
11 #include "cairo-win32.h"
15 gfxWindowsSurface::gfxWindowsSurface(HWND wnd
, uint32_t flags
) :
16 mOwnsDC(true), mForPrinting(false), mWnd(wnd
)
22 gfxWindowsSurface::gfxWindowsSurface(HDC dc
, uint32_t flags
) :
23 mOwnsDC(false), mForPrinting(false), mDC(dc
), mWnd(nullptr)
25 if (flags
& FLAG_TAKE_DC
)
29 if (flags
& FLAG_FOR_PRINTING
) {
30 Init(cairo_win32_printing_surface_create(mDC
));
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
);
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
))
58 cairo_surface_t
*surf
= cairo_win32_surface_create_with_dib((cairo_format_t
)(int)imageFormat
,
59 size
.width
, size
.height
);
63 if (CairoStatus() == CAIRO_STATUS_SUCCESS
) {
64 mDC
= cairo_win32_surface_get_dc(CairoSurface());
65 RecordMemoryUsed(size
.width
* size
.height
* 4 + sizeof(gfxWindowsSurface
));
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
))
78 cairo_surface_t
*surf
= cairo_win32_surface_create_with_ddb(dc
, (cairo_format_t
)(int)imageFormat
,
79 size
.width
, size
.height
);
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());
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
);
103 if (cairo_surface_get_type(csurf
) == CAIRO_SURFACE_TYPE_WIN32_PRINTING
)
110 gfxWindowsSurface::InitWithDC(uint32_t flags
)
112 if (flags
& FLAG_IS_TRANSPARENT
) {
113 Init(cairo_win32_surface_create_with_alpha(mDC
));
115 Init(cairo_win32_surface_create(mDC
));
119 already_AddRefed
<gfxASurface
>
120 gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent
,
121 const gfxIntSize
& aSize
)
123 if (!mSurface
|| !mSurfaceValid
) {
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*
138 cairo_win32_surface_create_with_dib((cairo_format_t
)(int)gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent
),
139 aSize
.width
, aSize
.height
);
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
);
151 nsRefPtr
<gfxASurface
> result
= Wrap(surface
, aSize
);
152 cairo_surface_destroy(surface
);
153 return result
.forget();
156 gfxWindowsSurface::~gfxWindowsSurface()
160 ::ReleaseDC(mWnd
, 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?");
187 NS_ASSERTION(CairoSurface() != nullptr, "CairoSurface() shouldn't be nullptr when mSurfaceValid is TRUE!");
192 cairo_surface_t
*isurf
= cairo_win32_surface_get_image(CairoSurface());
196 nsRefPtr
<gfxImageSurface
> result
= gfxASurface::Wrap(isurf
).downcast
<gfxImageSurface
>();
197 result
->SetOpaqueRect(GetOpaqueRect());
199 return result
.forget();
203 gfxWindowsSurface::BeginPrinting(const nsAString
& aTitle
,
204 const nsAString
& aPrintToFileName
)
207 #define DOC_TITLE_LENGTH (MAX_PATH-1)
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;
223 ::StartDocW(mDC
, &docinfo
);
227 return NS_ERROR_FAILURE
;
232 gfxWindowsSurface::EndPrinting()
235 int result
= ::EndDoc(mDC
);
237 return NS_ERROR_FAILURE
;
241 return NS_ERROR_FAILURE
;
246 gfxWindowsSurface::AbortPrinting()
249 int result
= ::AbortDoc(mDC
);
251 return NS_ERROR_FAILURE
;
254 return NS_ERROR_FAILURE
;
259 gfxWindowsSurface::BeginPage()
262 int result
= ::StartPage(mDC
);
264 return NS_ERROR_FAILURE
;
267 return NS_ERROR_FAILURE
;
272 gfxWindowsSurface::EndPage()
276 cairo_surface_show_page(CairoSurface());
277 int result
= ::EndPage(mDC
);
279 return NS_ERROR_FAILURE
;
282 return NS_ERROR_FAILURE
;
287 gfxWindowsSurface::GetDefaultContextFlags() const
290 return gfxContext::FLAG_SIMPLIFY_OPERATORS
|
291 gfxContext::FLAG_DISABLE_SNAPPING
|
292 gfxContext::FLAG_DISABLE_COPY_BACKGROUND
;
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
));
312 gfxWindowsSurface::GetMemoryLocation() const
314 return gfxMemoryLocation::IN_PROCESS_NONHEAP
;