1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxQuartzSurface.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,207 @@ 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 "gfxQuartzSurface.h" 1.10 +#include "gfxContext.h" 1.11 +#include "gfxImageSurface.h" 1.12 + 1.13 +#include "cairo-quartz.h" 1.14 + 1.15 +void 1.16 +gfxQuartzSurface::MakeInvalid() 1.17 +{ 1.18 + mSize = gfxIntSize(-1, -1); 1.19 +} 1.20 + 1.21 +gfxQuartzSurface::gfxQuartzSurface(const gfxSize& desiredSize, gfxImageFormat format, 1.22 + bool aForPrinting) 1.23 + : mCGContext(nullptr), mSize(desiredSize), mForPrinting(aForPrinting) 1.24 +{ 1.25 + gfxIntSize size((unsigned int) floor(desiredSize.width), 1.26 + (unsigned int) floor(desiredSize.height)); 1.27 + if (!CheckSurfaceSize(size)) 1.28 + MakeInvalid(); 1.29 + 1.30 + unsigned int width = static_cast<unsigned int>(mSize.width); 1.31 + unsigned int height = static_cast<unsigned int>(mSize.height); 1.32 + 1.33 + cairo_surface_t *surf = cairo_quartz_surface_create 1.34 + ((cairo_format_t) format, width, height); 1.35 + 1.36 + mCGContext = cairo_quartz_surface_get_cg_context (surf); 1.37 + 1.38 + CGContextRetain(mCGContext); 1.39 + 1.40 + Init(surf); 1.41 + if (mSurfaceValid) { 1.42 + RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); 1.43 + } 1.44 +} 1.45 + 1.46 +gfxQuartzSurface::gfxQuartzSurface(CGContextRef context, 1.47 + const gfxSize& desiredSize, 1.48 + bool aForPrinting) 1.49 + : mCGContext(context), mSize(desiredSize), mForPrinting(aForPrinting) 1.50 +{ 1.51 + gfxIntSize size((unsigned int) floor(desiredSize.width), 1.52 + (unsigned int) floor(desiredSize.height)); 1.53 + if (!CheckSurfaceSize(size)) 1.54 + MakeInvalid(); 1.55 + 1.56 + unsigned int width = static_cast<unsigned int>(mSize.width); 1.57 + unsigned int height = static_cast<unsigned int>(mSize.height); 1.58 + 1.59 + cairo_surface_t *surf = 1.60 + cairo_quartz_surface_create_for_cg_context(context, 1.61 + width, height); 1.62 + 1.63 + CGContextRetain(mCGContext); 1.64 + 1.65 + Init(surf); 1.66 + if (mSurfaceValid) { 1.67 + RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); 1.68 + } 1.69 +} 1.70 + 1.71 +gfxQuartzSurface::gfxQuartzSurface(CGContextRef context, 1.72 + const gfxIntSize& size, 1.73 + bool aForPrinting) 1.74 + : mCGContext(context), mSize(size), mForPrinting(aForPrinting) 1.75 +{ 1.76 + if (!CheckSurfaceSize(size)) 1.77 + MakeInvalid(); 1.78 + 1.79 + unsigned int width = static_cast<unsigned int>(mSize.width); 1.80 + unsigned int height = static_cast<unsigned int>(mSize.height); 1.81 + 1.82 + cairo_surface_t *surf = 1.83 + cairo_quartz_surface_create_for_cg_context(context, 1.84 + width, height); 1.85 + 1.86 + CGContextRetain(mCGContext); 1.87 + 1.88 + Init(surf); 1.89 + if (mSurfaceValid) { 1.90 + RecordMemoryUsed(mSize.height * 4 + sizeof(gfxQuartzSurface)); 1.91 + } 1.92 +} 1.93 + 1.94 +gfxQuartzSurface::gfxQuartzSurface(cairo_surface_t *csurf, 1.95 + const gfxIntSize& aSize, 1.96 + bool aForPrinting) : 1.97 + mSize(aSize), mForPrinting(aForPrinting) 1.98 +{ 1.99 + mCGContext = cairo_quartz_surface_get_cg_context (csurf); 1.100 + CGContextRetain (mCGContext); 1.101 + 1.102 + Init(csurf, true); 1.103 +} 1.104 + 1.105 +gfxQuartzSurface::gfxQuartzSurface(unsigned char *data, 1.106 + const gfxSize& desiredSize, 1.107 + long stride, 1.108 + gfxImageFormat format, 1.109 + bool aForPrinting) 1.110 + : mCGContext(nullptr), mSize(desiredSize), mForPrinting(aForPrinting) 1.111 +{ 1.112 + gfxIntSize size((unsigned int) floor(desiredSize.width), 1.113 + (unsigned int) floor(desiredSize.height)); 1.114 + if (!CheckSurfaceSize(size)) 1.115 + MakeInvalid(); 1.116 + 1.117 + unsigned int width = static_cast<unsigned int>(mSize.width); 1.118 + unsigned int height = static_cast<unsigned int>(mSize.height); 1.119 + 1.120 + cairo_surface_t *surf = cairo_quartz_surface_create_for_data 1.121 + (data, (cairo_format_t) format, width, height, stride); 1.122 + 1.123 + mCGContext = cairo_quartz_surface_get_cg_context (surf); 1.124 + 1.125 + CGContextRetain(mCGContext); 1.126 + 1.127 + Init(surf); 1.128 + if (mSurfaceValid) { 1.129 + RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface)); 1.130 + } 1.131 +} 1.132 + 1.133 +gfxQuartzSurface::gfxQuartzSurface(unsigned char *data, 1.134 + const gfxIntSize& aSize, 1.135 + long stride, 1.136 + gfxImageFormat format, 1.137 + bool aForPrinting) 1.138 + : mCGContext(nullptr), mSize(aSize.width, aSize.height), mForPrinting(aForPrinting) 1.139 +{ 1.140 + if (!CheckSurfaceSize(aSize)) 1.141 + MakeInvalid(); 1.142 + 1.143 + cairo_surface_t *surf = cairo_quartz_surface_create_for_data 1.144 + (data, (cairo_format_t) format, aSize.width, aSize.height, stride); 1.145 + 1.146 + mCGContext = cairo_quartz_surface_get_cg_context (surf); 1.147 + 1.148 + CGContextRetain(mCGContext); 1.149 + 1.150 + Init(surf); 1.151 + if (mSurfaceValid) { 1.152 + RecordMemoryUsed(mSize.height * stride + sizeof(gfxQuartzSurface)); 1.153 + } 1.154 +} 1.155 + 1.156 +already_AddRefed<gfxASurface> 1.157 +gfxQuartzSurface::CreateSimilarSurface(gfxContentType aType, 1.158 + const gfxIntSize& aSize) 1.159 +{ 1.160 + cairo_surface_t *surface = 1.161 + cairo_quartz_surface_create_cg_layer(mSurface, (cairo_content_t)aType, 1.162 + aSize.width, aSize.height); 1.163 + if (cairo_surface_status(surface)) { 1.164 + cairo_surface_destroy(surface); 1.165 + return nullptr; 1.166 + } 1.167 + 1.168 + nsRefPtr<gfxASurface> result = Wrap(surface, aSize); 1.169 + cairo_surface_destroy(surface); 1.170 + return result.forget(); 1.171 +} 1.172 + 1.173 +CGContextRef 1.174 +gfxQuartzSurface::GetCGContextWithClip(gfxContext *ctx) 1.175 +{ 1.176 + return cairo_quartz_get_cg_context_with_clip(ctx->GetCairo()); 1.177 +} 1.178 + 1.179 +int32_t gfxQuartzSurface::GetDefaultContextFlags() const 1.180 +{ 1.181 + if (mForPrinting) 1.182 + return gfxContext::FLAG_DISABLE_SNAPPING | 1.183 + gfxContext::FLAG_DISABLE_COPY_BACKGROUND; 1.184 + 1.185 + return 0; 1.186 +} 1.187 + 1.188 +already_AddRefed<gfxImageSurface> gfxQuartzSurface::GetAsImageSurface() 1.189 +{ 1.190 + cairo_surface_t *surface = cairo_quartz_surface_get_image(mSurface); 1.191 + if (!surface || cairo_surface_status(surface)) 1.192 + return nullptr; 1.193 + 1.194 + nsRefPtr<gfxASurface> img = Wrap(surface); 1.195 + 1.196 + // cairo_quartz_surface_get_image returns a referenced image, and thebes 1.197 + // shares the refcounts of Cairo surfaces. However, Wrap also adds a 1.198 + // reference to the image. We need to remove one of these references 1.199 + // explicitly so we don't leak. 1.200 + img->Release(); 1.201 + 1.202 + img->SetOpaqueRect(GetOpaqueRect()); 1.203 + 1.204 + return img.forget().downcast<gfxImageSurface>(); 1.205 +} 1.206 + 1.207 +gfxQuartzSurface::~gfxQuartzSurface() 1.208 +{ 1.209 + CGContextRelease(mCGContext); 1.210 +}