1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxWindowsSurface.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,315 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "gfxWindowsSurface.h" 1.10 +#include "gfxContext.h" 1.11 +#include "gfxPlatform.h" 1.12 + 1.13 +#include "cairo.h" 1.14 +#include "cairo-win32.h" 1.15 + 1.16 +#include "nsString.h" 1.17 + 1.18 +gfxWindowsSurface::gfxWindowsSurface(HWND wnd, uint32_t flags) : 1.19 + mOwnsDC(true), mForPrinting(false), mWnd(wnd) 1.20 +{ 1.21 + mDC = ::GetDC(mWnd); 1.22 + InitWithDC(flags); 1.23 +} 1.24 + 1.25 +gfxWindowsSurface::gfxWindowsSurface(HDC dc, uint32_t flags) : 1.26 + mOwnsDC(false), mForPrinting(false), mDC(dc), mWnd(nullptr) 1.27 +{ 1.28 + if (flags & FLAG_TAKE_DC) 1.29 + mOwnsDC = true; 1.30 + 1.31 +#ifdef NS_PRINTING 1.32 + if (flags & FLAG_FOR_PRINTING) { 1.33 + Init(cairo_win32_printing_surface_create(mDC)); 1.34 + mForPrinting = true; 1.35 + } else 1.36 +#endif 1.37 + InitWithDC(flags); 1.38 +} 1.39 + 1.40 +gfxWindowsSurface::gfxWindowsSurface(IDirect3DSurface9 *surface, uint32_t flags) : 1.41 + mOwnsDC(false), mForPrinting(false), mDC(0), mWnd(nullptr) 1.42 +{ 1.43 + cairo_surface_t *surf = cairo_win32_surface_create_with_d3dsurface9(surface); 1.44 + Init(surf); 1.45 +} 1.46 + 1.47 + 1.48 +void 1.49 +gfxWindowsSurface::MakeInvalid(gfxIntSize& size) 1.50 +{ 1.51 + size = gfxIntSize(-1, -1); 1.52 +} 1.53 + 1.54 +gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& realSize, gfxImageFormat imageFormat) : 1.55 + mOwnsDC(false), mForPrinting(false), mWnd(nullptr) 1.56 +{ 1.57 + gfxIntSize size(realSize); 1.58 + if (!CheckSurfaceSize(size)) 1.59 + MakeInvalid(size); 1.60 + 1.61 + cairo_surface_t *surf = cairo_win32_surface_create_with_dib((cairo_format_t)(int)imageFormat, 1.62 + size.width, size.height); 1.63 + 1.64 + Init(surf); 1.65 + 1.66 + if (CairoStatus() == CAIRO_STATUS_SUCCESS) { 1.67 + mDC = cairo_win32_surface_get_dc(CairoSurface()); 1.68 + RecordMemoryUsed(size.width * size.height * 4 + sizeof(gfxWindowsSurface)); 1.69 + } else { 1.70 + mDC = nullptr; 1.71 + } 1.72 +} 1.73 + 1.74 +gfxWindowsSurface::gfxWindowsSurface(HDC dc, const gfxIntSize& realSize, gfxImageFormat imageFormat) : 1.75 + mOwnsDC(false), mForPrinting(false), mWnd(nullptr) 1.76 +{ 1.77 + gfxIntSize size(realSize); 1.78 + if (!CheckSurfaceSize(size)) 1.79 + MakeInvalid(size); 1.80 + 1.81 + cairo_surface_t *surf = cairo_win32_surface_create_with_ddb(dc, (cairo_format_t)(int)imageFormat, 1.82 + size.width, size.height); 1.83 + 1.84 + Init(surf); 1.85 + 1.86 + if (mSurfaceValid) { 1.87 + // DDBs will generally only use 3 bytes per pixel when RGB24 1.88 + int bytesPerPixel = ((imageFormat == gfxImageFormat::RGB24) ? 3 : 4); 1.89 + RecordMemoryUsed(size.width * size.height * bytesPerPixel + sizeof(gfxWindowsSurface)); 1.90 + } 1.91 + 1.92 + if (CairoStatus() == 0) 1.93 + mDC = cairo_win32_surface_get_dc(CairoSurface()); 1.94 + else 1.95 + mDC = nullptr; 1.96 +} 1.97 + 1.98 +gfxWindowsSurface::gfxWindowsSurface(cairo_surface_t *csurf) : 1.99 + mOwnsDC(false), mForPrinting(false), mWnd(nullptr) 1.100 +{ 1.101 + if (cairo_surface_status(csurf) == 0) 1.102 + mDC = cairo_win32_surface_get_dc(csurf); 1.103 + else 1.104 + mDC = nullptr; 1.105 + 1.106 + if (cairo_surface_get_type(csurf) == CAIRO_SURFACE_TYPE_WIN32_PRINTING) 1.107 + mForPrinting = true; 1.108 + 1.109 + Init(csurf, true); 1.110 +} 1.111 + 1.112 +void 1.113 +gfxWindowsSurface::InitWithDC(uint32_t flags) 1.114 +{ 1.115 + if (flags & FLAG_IS_TRANSPARENT) { 1.116 + Init(cairo_win32_surface_create_with_alpha(mDC)); 1.117 + } else { 1.118 + Init(cairo_win32_surface_create(mDC)); 1.119 + } 1.120 +} 1.121 + 1.122 +already_AddRefed<gfxASurface> 1.123 +gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent, 1.124 + const gfxIntSize& aSize) 1.125 +{ 1.126 + if (!mSurface || !mSurfaceValid) { 1.127 + return nullptr; 1.128 + } 1.129 + 1.130 + cairo_surface_t *surface; 1.131 + if (!mForPrinting && GetContentType() == gfxContentType::COLOR_ALPHA) { 1.132 + // When creating a similar surface to a transparent surface, ensure 1.133 + // the new surface uses a DIB. cairo_surface_create_similar won't 1.134 + // use a DIB for a gfxContentType::COLOR surface if this surface doesn't 1.135 + // have a DIB (e.g. if we're a transparent window surface). But 1.136 + // we need a DIB to perform well if the new surface is composited into 1.137 + // a surface that's the result of create_similar(gfxContentType::COLOR_ALPHA) 1.138 + // (e.g. a backbuffer for the window) --- that new surface *would* 1.139 + // have a DIB. 1.140 + surface = 1.141 + cairo_win32_surface_create_with_dib((cairo_format_t)(int)gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent), 1.142 + aSize.width, aSize.height); 1.143 + } else { 1.144 + surface = 1.145 + cairo_surface_create_similar(mSurface, (cairo_content_t)(int)aContent, 1.146 + aSize.width, aSize.height); 1.147 + } 1.148 + 1.149 + if (cairo_surface_status(surface)) { 1.150 + cairo_surface_destroy(surface); 1.151 + return nullptr; 1.152 + } 1.153 + 1.154 + nsRefPtr<gfxASurface> result = Wrap(surface, aSize); 1.155 + cairo_surface_destroy(surface); 1.156 + return result.forget(); 1.157 +} 1.158 + 1.159 +gfxWindowsSurface::~gfxWindowsSurface() 1.160 +{ 1.161 + if (mOwnsDC) { 1.162 + if (mWnd) 1.163 + ::ReleaseDC(mWnd, mDC); 1.164 + else 1.165 + ::DeleteDC(mDC); 1.166 + } 1.167 +} 1.168 + 1.169 +HDC 1.170 +gfxWindowsSurface::GetDCWithClip(gfxContext *ctx) 1.171 +{ 1.172 + return cairo_win32_get_dc_with_clip (ctx->GetCairo()); 1.173 +} 1.174 + 1.175 +HDC 1.176 +gfxWindowsSurface::GetDC() 1.177 +{ 1.178 + return cairo_win32_surface_get_dc (CairoSurface()); 1.179 +} 1.180 + 1.181 + 1.182 +already_AddRefed<gfxImageSurface> 1.183 +gfxWindowsSurface::GetAsImageSurface() 1.184 +{ 1.185 + if (!mSurfaceValid) { 1.186 + NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?"); 1.187 + return nullptr; 1.188 + } 1.189 + 1.190 + NS_ASSERTION(CairoSurface() != nullptr, "CairoSurface() shouldn't be nullptr when mSurfaceValid is TRUE!"); 1.191 + 1.192 + if (mForPrinting) 1.193 + return nullptr; 1.194 + 1.195 + cairo_surface_t *isurf = cairo_win32_surface_get_image(CairoSurface()); 1.196 + if (!isurf) 1.197 + return nullptr; 1.198 + 1.199 + nsRefPtr<gfxImageSurface> result = gfxASurface::Wrap(isurf).downcast<gfxImageSurface>(); 1.200 + result->SetOpaqueRect(GetOpaqueRect()); 1.201 + 1.202 + return result.forget(); 1.203 +} 1.204 + 1.205 +nsresult 1.206 +gfxWindowsSurface::BeginPrinting(const nsAString& aTitle, 1.207 + const nsAString& aPrintToFileName) 1.208 +{ 1.209 +#ifdef NS_PRINTING 1.210 +#define DOC_TITLE_LENGTH (MAX_PATH-1) 1.211 + DOCINFOW docinfo; 1.212 + 1.213 + nsString titleStr(aTitle); 1.214 + if (titleStr.Length() > DOC_TITLE_LENGTH) { 1.215 + titleStr.SetLength(DOC_TITLE_LENGTH-3); 1.216 + titleStr.AppendLiteral("..."); 1.217 + } 1.218 + 1.219 + nsString docName(aPrintToFileName); 1.220 + docinfo.cbSize = sizeof(docinfo); 1.221 + docinfo.lpszDocName = titleStr.Length() > 0 ? titleStr.get() : L"Mozilla Document"; 1.222 + docinfo.lpszOutput = docName.Length() > 0 ? docName.get() : nullptr; 1.223 + docinfo.lpszDatatype = nullptr; 1.224 + docinfo.fwType = 0; 1.225 + 1.226 + ::StartDocW(mDC, &docinfo); 1.227 + 1.228 + return NS_OK; 1.229 +#else 1.230 + return NS_ERROR_FAILURE; 1.231 +#endif 1.232 +} 1.233 + 1.234 +nsresult 1.235 +gfxWindowsSurface::EndPrinting() 1.236 +{ 1.237 +#ifdef NS_PRINTING 1.238 + int result = ::EndDoc(mDC); 1.239 + if (result <= 0) 1.240 + return NS_ERROR_FAILURE; 1.241 + 1.242 + return NS_OK; 1.243 +#else 1.244 + return NS_ERROR_FAILURE; 1.245 +#endif 1.246 +} 1.247 + 1.248 +nsresult 1.249 +gfxWindowsSurface::AbortPrinting() 1.250 +{ 1.251 +#ifdef NS_PRINTING 1.252 + int result = ::AbortDoc(mDC); 1.253 + if (result <= 0) 1.254 + return NS_ERROR_FAILURE; 1.255 + return NS_OK; 1.256 +#else 1.257 + return NS_ERROR_FAILURE; 1.258 +#endif 1.259 +} 1.260 + 1.261 +nsresult 1.262 +gfxWindowsSurface::BeginPage() 1.263 +{ 1.264 +#ifdef NS_PRINTING 1.265 + int result = ::StartPage(mDC); 1.266 + if (result <= 0) 1.267 + return NS_ERROR_FAILURE; 1.268 + return NS_OK; 1.269 +#else 1.270 + return NS_ERROR_FAILURE; 1.271 +#endif 1.272 +} 1.273 + 1.274 +nsresult 1.275 +gfxWindowsSurface::EndPage() 1.276 +{ 1.277 +#ifdef NS_PRINTING 1.278 + if (mForPrinting) 1.279 + cairo_surface_show_page(CairoSurface()); 1.280 + int result = ::EndPage(mDC); 1.281 + if (result <= 0) 1.282 + return NS_ERROR_FAILURE; 1.283 + return NS_OK; 1.284 +#else 1.285 + return NS_ERROR_FAILURE; 1.286 +#endif 1.287 +} 1.288 + 1.289 +int32_t 1.290 +gfxWindowsSurface::GetDefaultContextFlags() const 1.291 +{ 1.292 + if (mForPrinting) 1.293 + return gfxContext::FLAG_SIMPLIFY_OPERATORS | 1.294 + gfxContext::FLAG_DISABLE_SNAPPING | 1.295 + gfxContext::FLAG_DISABLE_COPY_BACKGROUND; 1.296 + 1.297 + return 0; 1.298 +} 1.299 + 1.300 +const gfxIntSize 1.301 +gfxWindowsSurface::GetSize() const 1.302 +{ 1.303 + if (!mSurfaceValid) { 1.304 + NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?"); 1.305 + return gfxIntSize(-1, -1); 1.306 + } 1.307 + 1.308 + NS_ASSERTION(mSurface != nullptr, "CairoSurface() shouldn't be nullptr when mSurfaceValid is TRUE!"); 1.309 + 1.310 + return gfxIntSize(cairo_win32_surface_get_width(mSurface), 1.311 + cairo_win32_surface_get_height(mSurface)); 1.312 +} 1.313 + 1.314 +gfxMemoryLocation 1.315 +gfxWindowsSurface::GetMemoryLocation() const 1.316 +{ 1.317 + return gfxMemoryLocation::IN_PROCESS_NONHEAP; 1.318 +}