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.

     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)
    17 {
    18     mDC = ::GetDC(mWnd);
    19     InitWithDC(flags);
    20 }
    22 gfxWindowsSurface::gfxWindowsSurface(HDC dc, uint32_t flags) :
    23     mOwnsDC(false), mForPrinting(false), mDC(dc), mWnd(nullptr)
    24 {
    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);
    35 }
    37 gfxWindowsSurface::gfxWindowsSurface(IDirect3DSurface9 *surface, uint32_t flags) :
    38     mOwnsDC(false), mForPrinting(false), mDC(0), mWnd(nullptr)
    39 {
    40     cairo_surface_t *surf = cairo_win32_surface_create_with_d3dsurface9(surface);
    41     Init(surf);
    42 }
    45 void
    46 gfxWindowsSurface::MakeInvalid(gfxIntSize& size)
    47 {
    48     size = gfxIntSize(-1, -1);
    49 }
    51 gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& realSize, gfxImageFormat imageFormat) :
    52     mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
    53 {
    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;
    68     }
    69 }
    71 gfxWindowsSurface::gfxWindowsSurface(HDC dc, const gfxIntSize& realSize, gfxImageFormat imageFormat) :
    72     mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
    73 {
    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));
    87     }
    89     if (CairoStatus() == 0)
    90         mDC = cairo_win32_surface_get_dc(CairoSurface());
    91     else
    92         mDC = nullptr;
    93 }
    95 gfxWindowsSurface::gfxWindowsSurface(cairo_surface_t *csurf) :
    96     mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
    97 {
    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);
   107 }
   109 void
   110 gfxWindowsSurface::InitWithDC(uint32_t flags)
   111 {
   112     if (flags & FLAG_IS_TRANSPARENT) {
   113         Init(cairo_win32_surface_create_with_alpha(mDC));
   114     } else {
   115         Init(cairo_win32_surface_create(mDC));
   116     }
   117 }
   119 already_AddRefed<gfxASurface>
   120 gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent,
   121                                         const gfxIntSize& aSize)
   122 {
   123     if (!mSurface || !mSurfaceValid) {
   124         return nullptr;
   125     }
   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);
   144     }
   146     if (cairo_surface_status(surface)) {
   147         cairo_surface_destroy(surface);
   148         return nullptr;
   149     }
   151     nsRefPtr<gfxASurface> result = Wrap(surface, aSize);
   152     cairo_surface_destroy(surface);
   153     return result.forget();
   154 }
   156 gfxWindowsSurface::~gfxWindowsSurface()
   157 {
   158     if (mOwnsDC) {
   159         if (mWnd)
   160             ::ReleaseDC(mWnd, mDC);
   161         else
   162             ::DeleteDC(mDC);
   163     }
   164 }
   166 HDC
   167 gfxWindowsSurface::GetDCWithClip(gfxContext *ctx)
   168 {
   169     return cairo_win32_get_dc_with_clip (ctx->GetCairo());
   170 }
   172 HDC
   173 gfxWindowsSurface::GetDC()
   174 {
   175     return cairo_win32_surface_get_dc (CairoSurface());
   176 }
   179 already_AddRefed<gfxImageSurface>
   180 gfxWindowsSurface::GetAsImageSurface()
   181 {
   182     if (!mSurfaceValid) {
   183         NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
   184         return nullptr;
   185     }
   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();
   200 }
   202 nsresult
   203 gfxWindowsSurface::BeginPrinting(const nsAString& aTitle,
   204                                  const nsAString& aPrintToFileName)
   205 {
   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("...");
   214     }
   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
   229 }
   231 nsresult
   232 gfxWindowsSurface::EndPrinting()
   233 {
   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
   243 }
   245 nsresult
   246 gfxWindowsSurface::AbortPrinting()
   247 {
   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
   256 }
   258 nsresult
   259 gfxWindowsSurface::BeginPage()
   260 {
   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
   269 }
   271 nsresult
   272 gfxWindowsSurface::EndPage()
   273 {
   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
   284 }
   286 int32_t
   287 gfxWindowsSurface::GetDefaultContextFlags() const
   288 {
   289     if (mForPrinting)
   290         return gfxContext::FLAG_SIMPLIFY_OPERATORS |
   291                gfxContext::FLAG_DISABLE_SNAPPING |
   292                gfxContext::FLAG_DISABLE_COPY_BACKGROUND;
   294     return 0;
   295 }
   297 const gfxIntSize 
   298 gfxWindowsSurface::GetSize() const
   299 {
   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);
   303     }
   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));
   309 }
   311 gfxMemoryLocation
   312 gfxWindowsSurface::GetMemoryLocation() const
   313 {
   314     return gfxMemoryLocation::IN_PROCESS_NONHEAP;
   315 }

mercurial