gfx/thebes/gfxQuartzSurface.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 "gfxQuartzSurface.h"
michael@0 7 #include "gfxContext.h"
michael@0 8 #include "gfxImageSurface.h"
michael@0 9
michael@0 10 #include "cairo-quartz.h"
michael@0 11
michael@0 12 void
michael@0 13 gfxQuartzSurface::MakeInvalid()
michael@0 14 {
michael@0 15 mSize = gfxIntSize(-1, -1);
michael@0 16 }
michael@0 17
michael@0 18 gfxQuartzSurface::gfxQuartzSurface(const gfxSize& desiredSize, gfxImageFormat format,
michael@0 19 bool aForPrinting)
michael@0 20 : mCGContext(nullptr), mSize(desiredSize), mForPrinting(aForPrinting)
michael@0 21 {
michael@0 22 gfxIntSize size((unsigned int) floor(desiredSize.width),
michael@0 23 (unsigned int) floor(desiredSize.height));
michael@0 24 if (!CheckSurfaceSize(size))
michael@0 25 MakeInvalid();
michael@0 26
michael@0 27 unsigned int width = static_cast<unsigned int>(mSize.width);
michael@0 28 unsigned int height = static_cast<unsigned int>(mSize.height);
michael@0 29
michael@0 30 cairo_surface_t *surf = cairo_quartz_surface_create
michael@0 31 ((cairo_format_t) format, width, height);
michael@0 32
michael@0 33 mCGContext = cairo_quartz_surface_get_cg_context (surf);
michael@0 34
michael@0 35 CGContextRetain(mCGContext);
michael@0 36
michael@0 37 Init(surf);
michael@0 38 if (mSurfaceValid) {
michael@0 39 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
michael@0 40 }
michael@0 41 }
michael@0 42
michael@0 43 gfxQuartzSurface::gfxQuartzSurface(CGContextRef context,
michael@0 44 const gfxSize& desiredSize,
michael@0 45 bool aForPrinting)
michael@0 46 : mCGContext(context), mSize(desiredSize), mForPrinting(aForPrinting)
michael@0 47 {
michael@0 48 gfxIntSize size((unsigned int) floor(desiredSize.width),
michael@0 49 (unsigned int) floor(desiredSize.height));
michael@0 50 if (!CheckSurfaceSize(size))
michael@0 51 MakeInvalid();
michael@0 52
michael@0 53 unsigned int width = static_cast<unsigned int>(mSize.width);
michael@0 54 unsigned int height = static_cast<unsigned int>(mSize.height);
michael@0 55
michael@0 56 cairo_surface_t *surf =
michael@0 57 cairo_quartz_surface_create_for_cg_context(context,
michael@0 58 width, height);
michael@0 59
michael@0 60 CGContextRetain(mCGContext);
michael@0 61
michael@0 62 Init(surf);
michael@0 63 if (mSurfaceValid) {
michael@0 64 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
michael@0 65 }
michael@0 66 }
michael@0 67
michael@0 68 gfxQuartzSurface::gfxQuartzSurface(CGContextRef context,
michael@0 69 const gfxIntSize& size,
michael@0 70 bool aForPrinting)
michael@0 71 : mCGContext(context), mSize(size), mForPrinting(aForPrinting)
michael@0 72 {
michael@0 73 if (!CheckSurfaceSize(size))
michael@0 74 MakeInvalid();
michael@0 75
michael@0 76 unsigned int width = static_cast<unsigned int>(mSize.width);
michael@0 77 unsigned int height = static_cast<unsigned int>(mSize.height);
michael@0 78
michael@0 79 cairo_surface_t *surf =
michael@0 80 cairo_quartz_surface_create_for_cg_context(context,
michael@0 81 width, height);
michael@0 82
michael@0 83 CGContextRetain(mCGContext);
michael@0 84
michael@0 85 Init(surf);
michael@0 86 if (mSurfaceValid) {
michael@0 87 RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface));
michael@0 88 }
michael@0 89 }
michael@0 90
michael@0 91 gfxQuartzSurface::gfxQuartzSurface(cairo_surface_t *csurf,
michael@0 92 const gfxIntSize& aSize,
michael@0 93 bool aForPrinting) :
michael@0 94 mSize(aSize), mForPrinting(aForPrinting)
michael@0 95 {
michael@0 96 mCGContext = cairo_quartz_surface_get_cg_context (csurf);
michael@0 97 CGContextRetain (mCGContext);
michael@0 98
michael@0 99 Init(csurf, true);
michael@0 100 }
michael@0 101
michael@0 102 gfxQuartzSurface::gfxQuartzSurface(unsigned char *data,
michael@0 103 const gfxSize& desiredSize,
michael@0 104 long stride,
michael@0 105 gfxImageFormat format,
michael@0 106 bool aForPrinting)
michael@0 107 : mCGContext(nullptr), mSize(desiredSize), mForPrinting(aForPrinting)
michael@0 108 {
michael@0 109 gfxIntSize size((unsigned int) floor(desiredSize.width),
michael@0 110 (unsigned int) floor(desiredSize.height));
michael@0 111 if (!CheckSurfaceSize(size))
michael@0 112 MakeInvalid();
michael@0 113
michael@0 114 unsigned int width = static_cast<unsigned int>(mSize.width);
michael@0 115 unsigned int height = static_cast<unsigned int>(mSize.height);
michael@0 116
michael@0 117 cairo_surface_t *surf = cairo_quartz_surface_create_for_data
michael@0 118 (data, (cairo_format_t) format, width, height, stride);
michael@0 119
michael@0 120 mCGContext = cairo_quartz_surface_get_cg_context (surf);
michael@0 121
michael@0 122 CGContextRetain(mCGContext);
michael@0 123
michael@0 124 Init(surf);
michael@0 125 if (mSurfaceValid) {
michael@0 126 RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface));
michael@0 127 }
michael@0 128 }
michael@0 129
michael@0 130 gfxQuartzSurface::gfxQuartzSurface(unsigned char *data,
michael@0 131 const gfxIntSize& aSize,
michael@0 132 long stride,
michael@0 133 gfxImageFormat format,
michael@0 134 bool aForPrinting)
michael@0 135 : mCGContext(nullptr), mSize(aSize.width, aSize.height), mForPrinting(aForPrinting)
michael@0 136 {
michael@0 137 if (!CheckSurfaceSize(aSize))
michael@0 138 MakeInvalid();
michael@0 139
michael@0 140 cairo_surface_t *surf = cairo_quartz_surface_create_for_data
michael@0 141 (data, (cairo_format_t) format, aSize.width, aSize.height, stride);
michael@0 142
michael@0 143 mCGContext = cairo_quartz_surface_get_cg_context (surf);
michael@0 144
michael@0 145 CGContextRetain(mCGContext);
michael@0 146
michael@0 147 Init(surf);
michael@0 148 if (mSurfaceValid) {
michael@0 149 RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface));
michael@0 150 }
michael@0 151 }
michael@0 152
michael@0 153 already_AddRefed<gfxASurface>
michael@0 154 gfxQuartzSurface::CreateSimilarSurface(gfxContentType aType,
michael@0 155 const gfxIntSize& aSize)
michael@0 156 {
michael@0 157 cairo_surface_t *surface =
michael@0 158 cairo_quartz_surface_create_cg_layer(mSurface, (cairo_content_t)aType,
michael@0 159 aSize.width, aSize.height);
michael@0 160 if (cairo_surface_status(surface)) {
michael@0 161 cairo_surface_destroy(surface);
michael@0 162 return nullptr;
michael@0 163 }
michael@0 164
michael@0 165 nsRefPtr<gfxASurface> result = Wrap(surface, aSize);
michael@0 166 cairo_surface_destroy(surface);
michael@0 167 return result.forget();
michael@0 168 }
michael@0 169
michael@0 170 CGContextRef
michael@0 171 gfxQuartzSurface::GetCGContextWithClip(gfxContext *ctx)
michael@0 172 {
michael@0 173 return cairo_quartz_get_cg_context_with_clip(ctx->GetCairo());
michael@0 174 }
michael@0 175
michael@0 176 int32_t gfxQuartzSurface::GetDefaultContextFlags() const
michael@0 177 {
michael@0 178 if (mForPrinting)
michael@0 179 return gfxContext::FLAG_DISABLE_SNAPPING |
michael@0 180 gfxContext::FLAG_DISABLE_COPY_BACKGROUND;
michael@0 181
michael@0 182 return 0;
michael@0 183 }
michael@0 184
michael@0 185 already_AddRefed<gfxImageSurface> gfxQuartzSurface::GetAsImageSurface()
michael@0 186 {
michael@0 187 cairo_surface_t *surface = cairo_quartz_surface_get_image(mSurface);
michael@0 188 if (!surface || cairo_surface_status(surface))
michael@0 189 return nullptr;
michael@0 190
michael@0 191 nsRefPtr<gfxASurface> img = Wrap(surface);
michael@0 192
michael@0 193 // cairo_quartz_surface_get_image returns a referenced image, and thebes
michael@0 194 // shares the refcounts of Cairo surfaces. However, Wrap also adds a
michael@0 195 // reference to the image. We need to remove one of these references
michael@0 196 // explicitly so we don't leak.
michael@0 197 img->Release();
michael@0 198
michael@0 199 img->SetOpaqueRect(GetOpaqueRect());
michael@0 200
michael@0 201 return img.forget().downcast<gfxImageSurface>();
michael@0 202 }
michael@0 203
michael@0 204 gfxQuartzSurface::~gfxQuartzSurface()
michael@0 205 {
michael@0 206 CGContextRelease(mCGContext);
michael@0 207 }

mercurial