michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "SourceSurfaceCairo.h" michael@0: #include "DrawTargetCairo.h" michael@0: #include "HelpersCairo.h" michael@0: #include "DataSourceSurfaceWrapper.h" michael@0: michael@0: #include "cairo.h" michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: static SurfaceFormat michael@0: CairoFormatToSurfaceFormat(cairo_format_t format) michael@0: { michael@0: switch (format) michael@0: { michael@0: case CAIRO_FORMAT_ARGB32: michael@0: return SurfaceFormat::B8G8R8A8; michael@0: case CAIRO_FORMAT_RGB24: michael@0: return SurfaceFormat::B8G8R8X8; michael@0: case CAIRO_FORMAT_A8: michael@0: return SurfaceFormat::A8; michael@0: default: michael@0: return SurfaceFormat::B8G8R8A8; michael@0: } michael@0: } michael@0: michael@0: SourceSurfaceCairo::SourceSurfaceCairo(cairo_surface_t* aSurface, michael@0: const IntSize& aSize, michael@0: const SurfaceFormat& aFormat, michael@0: DrawTargetCairo* aDrawTarget /* = nullptr */) michael@0: : mSize(aSize) michael@0: , mFormat(aFormat) michael@0: , mSurface(aSurface) michael@0: , mDrawTarget(aDrawTarget) michael@0: { michael@0: cairo_surface_reference(mSurface); michael@0: } michael@0: michael@0: SourceSurfaceCairo::~SourceSurfaceCairo() michael@0: { michael@0: cairo_surface_destroy(mSurface); michael@0: } michael@0: michael@0: IntSize michael@0: SourceSurfaceCairo::GetSize() const michael@0: { michael@0: return mSize; michael@0: } michael@0: michael@0: SurfaceFormat michael@0: SourceSurfaceCairo::GetFormat() const michael@0: { michael@0: return mFormat; michael@0: } michael@0: michael@0: TemporaryRef michael@0: SourceSurfaceCairo::GetDataSurface() michael@0: { michael@0: RefPtr dataSurf; michael@0: michael@0: if (cairo_surface_get_type(mSurface) == CAIRO_SURFACE_TYPE_IMAGE) { michael@0: dataSurf = new DataSourceSurfaceCairo(mSurface); michael@0: } else { michael@0: cairo_surface_t* imageSurf = cairo_image_surface_create(GfxFormatToCairoFormat(mFormat), michael@0: mSize.width, mSize.height); michael@0: michael@0: // Fill the new image surface with the contents of our surface. michael@0: cairo_t* ctx = cairo_create(imageSurf); michael@0: cairo_set_source_surface(ctx, mSurface, 0, 0); michael@0: cairo_paint(ctx); michael@0: cairo_destroy(ctx); michael@0: michael@0: dataSurf = new DataSourceSurfaceCairo(imageSurf); michael@0: cairo_surface_destroy(imageSurf); michael@0: } michael@0: michael@0: // We also need to make sure that the returned surface has michael@0: // surface->GetType() == SurfaceType::DATA. michael@0: dataSurf = new DataSourceSurfaceWrapper(dataSurf); michael@0: michael@0: return dataSurf; michael@0: } michael@0: michael@0: cairo_surface_t* michael@0: SourceSurfaceCairo::GetSurface() const michael@0: { michael@0: return mSurface; michael@0: } michael@0: michael@0: void michael@0: SourceSurfaceCairo::DrawTargetWillChange() michael@0: { michael@0: if (mDrawTarget) { michael@0: mDrawTarget = nullptr; michael@0: michael@0: // We're about to lose our version of the surface, so make a copy of it. michael@0: cairo_surface_t* surface = cairo_surface_create_similar(mSurface, michael@0: GfxFormatToCairoContent(mFormat), michael@0: mSize.width, mSize.height); michael@0: cairo_t* ctx = cairo_create(surface); michael@0: cairo_pattern_t* pat = cairo_pattern_create_for_surface(mSurface); michael@0: cairo_set_source(ctx, pat); michael@0: cairo_paint(ctx); michael@0: cairo_destroy(ctx); michael@0: cairo_pattern_destroy(pat); michael@0: michael@0: // Swap in this new surface. michael@0: cairo_surface_destroy(mSurface); michael@0: mSurface = surface; michael@0: } michael@0: } michael@0: michael@0: DataSourceSurfaceCairo::DataSourceSurfaceCairo(cairo_surface_t* imageSurf) michael@0: : mImageSurface(imageSurf) michael@0: { michael@0: cairo_surface_reference(mImageSurface); michael@0: } michael@0: michael@0: DataSourceSurfaceCairo::~DataSourceSurfaceCairo() michael@0: { michael@0: cairo_surface_destroy(mImageSurface); michael@0: } michael@0: michael@0: unsigned char * michael@0: DataSourceSurfaceCairo::GetData() michael@0: { michael@0: return cairo_image_surface_get_data(mImageSurface); michael@0: } michael@0: michael@0: int32_t michael@0: DataSourceSurfaceCairo::Stride() michael@0: { michael@0: return cairo_image_surface_get_stride(mImageSurface); michael@0: } michael@0: michael@0: IntSize michael@0: DataSourceSurfaceCairo::GetSize() const michael@0: { michael@0: IntSize size; michael@0: size.width = cairo_image_surface_get_width(mImageSurface); michael@0: size.height = cairo_image_surface_get_height(mImageSurface); michael@0: michael@0: return size; michael@0: } michael@0: michael@0: SurfaceFormat michael@0: DataSourceSurfaceCairo::GetFormat() const michael@0: { michael@0: return CairoFormatToSurfaceFormat(cairo_image_surface_get_format(mImageSurface)); michael@0: } michael@0: michael@0: cairo_surface_t* michael@0: DataSourceSurfaceCairo::GetSurface() const michael@0: { michael@0: return mImageSurface; michael@0: } michael@0: michael@0: } michael@0: }