gfx/thebes/gfxWindowsSurface.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "gfxWindowsSurface.h"
michael@0 7 #include "gfxContext.h"
michael@0 8 #include "gfxPlatform.h"
michael@0 9
michael@0 10 #include "cairo.h"
michael@0 11 #include "cairo-win32.h"
michael@0 12
michael@0 13 #include "nsString.h"
michael@0 14
michael@0 15 gfxWindowsSurface::gfxWindowsSurface(HWND wnd, uint32_t flags) :
michael@0 16 mOwnsDC(true), mForPrinting(false), mWnd(wnd)
michael@0 17 {
michael@0 18 mDC = ::GetDC(mWnd);
michael@0 19 InitWithDC(flags);
michael@0 20 }
michael@0 21
michael@0 22 gfxWindowsSurface::gfxWindowsSurface(HDC dc, uint32_t flags) :
michael@0 23 mOwnsDC(false), mForPrinting(false), mDC(dc), mWnd(nullptr)
michael@0 24 {
michael@0 25 if (flags & FLAG_TAKE_DC)
michael@0 26 mOwnsDC = true;
michael@0 27
michael@0 28 #ifdef NS_PRINTING
michael@0 29 if (flags & FLAG_FOR_PRINTING) {
michael@0 30 Init(cairo_win32_printing_surface_create(mDC));
michael@0 31 mForPrinting = true;
michael@0 32 } else
michael@0 33 #endif
michael@0 34 InitWithDC(flags);
michael@0 35 }
michael@0 36
michael@0 37 gfxWindowsSurface::gfxWindowsSurface(IDirect3DSurface9 *surface, uint32_t flags) :
michael@0 38 mOwnsDC(false), mForPrinting(false), mDC(0), mWnd(nullptr)
michael@0 39 {
michael@0 40 cairo_surface_t *surf = cairo_win32_surface_create_with_d3dsurface9(surface);
michael@0 41 Init(surf);
michael@0 42 }
michael@0 43
michael@0 44
michael@0 45 void
michael@0 46 gfxWindowsSurface::MakeInvalid(gfxIntSize& size)
michael@0 47 {
michael@0 48 size = gfxIntSize(-1, -1);
michael@0 49 }
michael@0 50
michael@0 51 gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& realSize, gfxImageFormat imageFormat) :
michael@0 52 mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
michael@0 53 {
michael@0 54 gfxIntSize size(realSize);
michael@0 55 if (!CheckSurfaceSize(size))
michael@0 56 MakeInvalid(size);
michael@0 57
michael@0 58 cairo_surface_t *surf = cairo_win32_surface_create_with_dib((cairo_format_t)(int)imageFormat,
michael@0 59 size.width, size.height);
michael@0 60
michael@0 61 Init(surf);
michael@0 62
michael@0 63 if (CairoStatus() == CAIRO_STATUS_SUCCESS) {
michael@0 64 mDC = cairo_win32_surface_get_dc(CairoSurface());
michael@0 65 RecordMemoryUsed(size.width * size.height * 4 + sizeof(gfxWindowsSurface));
michael@0 66 } else {
michael@0 67 mDC = nullptr;
michael@0 68 }
michael@0 69 }
michael@0 70
michael@0 71 gfxWindowsSurface::gfxWindowsSurface(HDC dc, const gfxIntSize& realSize, gfxImageFormat imageFormat) :
michael@0 72 mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
michael@0 73 {
michael@0 74 gfxIntSize size(realSize);
michael@0 75 if (!CheckSurfaceSize(size))
michael@0 76 MakeInvalid(size);
michael@0 77
michael@0 78 cairo_surface_t *surf = cairo_win32_surface_create_with_ddb(dc, (cairo_format_t)(int)imageFormat,
michael@0 79 size.width, size.height);
michael@0 80
michael@0 81 Init(surf);
michael@0 82
michael@0 83 if (mSurfaceValid) {
michael@0 84 // DDBs will generally only use 3 bytes per pixel when RGB24
michael@0 85 int bytesPerPixel = ((imageFormat == gfxImageFormat::RGB24) ? 3 : 4);
michael@0 86 RecordMemoryUsed(size.width * size.height * bytesPerPixel + sizeof(gfxWindowsSurface));
michael@0 87 }
michael@0 88
michael@0 89 if (CairoStatus() == 0)
michael@0 90 mDC = cairo_win32_surface_get_dc(CairoSurface());
michael@0 91 else
michael@0 92 mDC = nullptr;
michael@0 93 }
michael@0 94
michael@0 95 gfxWindowsSurface::gfxWindowsSurface(cairo_surface_t *csurf) :
michael@0 96 mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
michael@0 97 {
michael@0 98 if (cairo_surface_status(csurf) == 0)
michael@0 99 mDC = cairo_win32_surface_get_dc(csurf);
michael@0 100 else
michael@0 101 mDC = nullptr;
michael@0 102
michael@0 103 if (cairo_surface_get_type(csurf) == CAIRO_SURFACE_TYPE_WIN32_PRINTING)
michael@0 104 mForPrinting = true;
michael@0 105
michael@0 106 Init(csurf, true);
michael@0 107 }
michael@0 108
michael@0 109 void
michael@0 110 gfxWindowsSurface::InitWithDC(uint32_t flags)
michael@0 111 {
michael@0 112 if (flags & FLAG_IS_TRANSPARENT) {
michael@0 113 Init(cairo_win32_surface_create_with_alpha(mDC));
michael@0 114 } else {
michael@0 115 Init(cairo_win32_surface_create(mDC));
michael@0 116 }
michael@0 117 }
michael@0 118
michael@0 119 already_AddRefed<gfxASurface>
michael@0 120 gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent,
michael@0 121 const gfxIntSize& aSize)
michael@0 122 {
michael@0 123 if (!mSurface || !mSurfaceValid) {
michael@0 124 return nullptr;
michael@0 125 }
michael@0 126
michael@0 127 cairo_surface_t *surface;
michael@0 128 if (!mForPrinting && GetContentType() == gfxContentType::COLOR_ALPHA) {
michael@0 129 // When creating a similar surface to a transparent surface, ensure
michael@0 130 // the new surface uses a DIB. cairo_surface_create_similar won't
michael@0 131 // use a DIB for a gfxContentType::COLOR surface if this surface doesn't
michael@0 132 // have a DIB (e.g. if we're a transparent window surface). But
michael@0 133 // we need a DIB to perform well if the new surface is composited into
michael@0 134 // a surface that's the result of create_similar(gfxContentType::COLOR_ALPHA)
michael@0 135 // (e.g. a backbuffer for the window) --- that new surface *would*
michael@0 136 // have a DIB.
michael@0 137 surface =
michael@0 138 cairo_win32_surface_create_with_dib((cairo_format_t)(int)gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent),
michael@0 139 aSize.width, aSize.height);
michael@0 140 } else {
michael@0 141 surface =
michael@0 142 cairo_surface_create_similar(mSurface, (cairo_content_t)(int)aContent,
michael@0 143 aSize.width, aSize.height);
michael@0 144 }
michael@0 145
michael@0 146 if (cairo_surface_status(surface)) {
michael@0 147 cairo_surface_destroy(surface);
michael@0 148 return nullptr;
michael@0 149 }
michael@0 150
michael@0 151 nsRefPtr<gfxASurface> result = Wrap(surface, aSize);
michael@0 152 cairo_surface_destroy(surface);
michael@0 153 return result.forget();
michael@0 154 }
michael@0 155
michael@0 156 gfxWindowsSurface::~gfxWindowsSurface()
michael@0 157 {
michael@0 158 if (mOwnsDC) {
michael@0 159 if (mWnd)
michael@0 160 ::ReleaseDC(mWnd, mDC);
michael@0 161 else
michael@0 162 ::DeleteDC(mDC);
michael@0 163 }
michael@0 164 }
michael@0 165
michael@0 166 HDC
michael@0 167 gfxWindowsSurface::GetDCWithClip(gfxContext *ctx)
michael@0 168 {
michael@0 169 return cairo_win32_get_dc_with_clip (ctx->GetCairo());
michael@0 170 }
michael@0 171
michael@0 172 HDC
michael@0 173 gfxWindowsSurface::GetDC()
michael@0 174 {
michael@0 175 return cairo_win32_surface_get_dc (CairoSurface());
michael@0 176 }
michael@0 177
michael@0 178
michael@0 179 already_AddRefed<gfxImageSurface>
michael@0 180 gfxWindowsSurface::GetAsImageSurface()
michael@0 181 {
michael@0 182 if (!mSurfaceValid) {
michael@0 183 NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
michael@0 184 return nullptr;
michael@0 185 }
michael@0 186
michael@0 187 NS_ASSERTION(CairoSurface() != nullptr, "CairoSurface() shouldn't be nullptr when mSurfaceValid is TRUE!");
michael@0 188
michael@0 189 if (mForPrinting)
michael@0 190 return nullptr;
michael@0 191
michael@0 192 cairo_surface_t *isurf = cairo_win32_surface_get_image(CairoSurface());
michael@0 193 if (!isurf)
michael@0 194 return nullptr;
michael@0 195
michael@0 196 nsRefPtr<gfxImageSurface> result = gfxASurface::Wrap(isurf).downcast<gfxImageSurface>();
michael@0 197 result->SetOpaqueRect(GetOpaqueRect());
michael@0 198
michael@0 199 return result.forget();
michael@0 200 }
michael@0 201
michael@0 202 nsresult
michael@0 203 gfxWindowsSurface::BeginPrinting(const nsAString& aTitle,
michael@0 204 const nsAString& aPrintToFileName)
michael@0 205 {
michael@0 206 #ifdef NS_PRINTING
michael@0 207 #define DOC_TITLE_LENGTH (MAX_PATH-1)
michael@0 208 DOCINFOW docinfo;
michael@0 209
michael@0 210 nsString titleStr(aTitle);
michael@0 211 if (titleStr.Length() > DOC_TITLE_LENGTH) {
michael@0 212 titleStr.SetLength(DOC_TITLE_LENGTH-3);
michael@0 213 titleStr.AppendLiteral("...");
michael@0 214 }
michael@0 215
michael@0 216 nsString docName(aPrintToFileName);
michael@0 217 docinfo.cbSize = sizeof(docinfo);
michael@0 218 docinfo.lpszDocName = titleStr.Length() > 0 ? titleStr.get() : L"Mozilla Document";
michael@0 219 docinfo.lpszOutput = docName.Length() > 0 ? docName.get() : nullptr;
michael@0 220 docinfo.lpszDatatype = nullptr;
michael@0 221 docinfo.fwType = 0;
michael@0 222
michael@0 223 ::StartDocW(mDC, &docinfo);
michael@0 224
michael@0 225 return NS_OK;
michael@0 226 #else
michael@0 227 return NS_ERROR_FAILURE;
michael@0 228 #endif
michael@0 229 }
michael@0 230
michael@0 231 nsresult
michael@0 232 gfxWindowsSurface::EndPrinting()
michael@0 233 {
michael@0 234 #ifdef NS_PRINTING
michael@0 235 int result = ::EndDoc(mDC);
michael@0 236 if (result <= 0)
michael@0 237 return NS_ERROR_FAILURE;
michael@0 238
michael@0 239 return NS_OK;
michael@0 240 #else
michael@0 241 return NS_ERROR_FAILURE;
michael@0 242 #endif
michael@0 243 }
michael@0 244
michael@0 245 nsresult
michael@0 246 gfxWindowsSurface::AbortPrinting()
michael@0 247 {
michael@0 248 #ifdef NS_PRINTING
michael@0 249 int result = ::AbortDoc(mDC);
michael@0 250 if (result <= 0)
michael@0 251 return NS_ERROR_FAILURE;
michael@0 252 return NS_OK;
michael@0 253 #else
michael@0 254 return NS_ERROR_FAILURE;
michael@0 255 #endif
michael@0 256 }
michael@0 257
michael@0 258 nsresult
michael@0 259 gfxWindowsSurface::BeginPage()
michael@0 260 {
michael@0 261 #ifdef NS_PRINTING
michael@0 262 int result = ::StartPage(mDC);
michael@0 263 if (result <= 0)
michael@0 264 return NS_ERROR_FAILURE;
michael@0 265 return NS_OK;
michael@0 266 #else
michael@0 267 return NS_ERROR_FAILURE;
michael@0 268 #endif
michael@0 269 }
michael@0 270
michael@0 271 nsresult
michael@0 272 gfxWindowsSurface::EndPage()
michael@0 273 {
michael@0 274 #ifdef NS_PRINTING
michael@0 275 if (mForPrinting)
michael@0 276 cairo_surface_show_page(CairoSurface());
michael@0 277 int result = ::EndPage(mDC);
michael@0 278 if (result <= 0)
michael@0 279 return NS_ERROR_FAILURE;
michael@0 280 return NS_OK;
michael@0 281 #else
michael@0 282 return NS_ERROR_FAILURE;
michael@0 283 #endif
michael@0 284 }
michael@0 285
michael@0 286 int32_t
michael@0 287 gfxWindowsSurface::GetDefaultContextFlags() const
michael@0 288 {
michael@0 289 if (mForPrinting)
michael@0 290 return gfxContext::FLAG_SIMPLIFY_OPERATORS |
michael@0 291 gfxContext::FLAG_DISABLE_SNAPPING |
michael@0 292 gfxContext::FLAG_DISABLE_COPY_BACKGROUND;
michael@0 293
michael@0 294 return 0;
michael@0 295 }
michael@0 296
michael@0 297 const gfxIntSize
michael@0 298 gfxWindowsSurface::GetSize() const
michael@0 299 {
michael@0 300 if (!mSurfaceValid) {
michael@0 301 NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
michael@0 302 return gfxIntSize(-1, -1);
michael@0 303 }
michael@0 304
michael@0 305 NS_ASSERTION(mSurface != nullptr, "CairoSurface() shouldn't be nullptr when mSurfaceValid is TRUE!");
michael@0 306
michael@0 307 return gfxIntSize(cairo_win32_surface_get_width(mSurface),
michael@0 308 cairo_win32_surface_get_height(mSurface));
michael@0 309 }
michael@0 310
michael@0 311 gfxMemoryLocation
michael@0 312 gfxWindowsSurface::GetMemoryLocation() const
michael@0 313 {
michael@0 314 return gfxMemoryLocation::IN_PROCESS_NONHEAP;
michael@0 315 }

mercurial