Bug 756767 - Part 2: Deal with CreateSourceSurfaceFromData failing. r=jrmuizel

This commit is contained in:
Bas Schouten 2012-05-21 17:27:32 +02:00
Родитель 5981f7c8a2
Коммит bd74709f48
5 изменённых файлов: 47 добавлений и 5 удалений

Просмотреть файл

@ -532,6 +532,7 @@ gfxContext::DrawSurface(gfxASurface *surface, const gfxSize& size)
cairo_fill(mCairo);
cairo_restore(mCairo);
} else {
// Lifetime needs to be limited here since we may wrap surface's data.
RefPtr<SourceSurface> surf =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface);
@ -1293,6 +1294,7 @@ gfxContext::SetColor(const gfxRGBA& c)
cairo_set_source_rgba(mCairo, c.r, c.g, c.b, c.a);
} else {
CurrentState().pattern = NULL;
CurrentState().sourceSurfCairo = NULL;
CurrentState().sourceSurface = NULL;
if (gfxPlatform::GetCMSMode() == eCMSMode_All) {
@ -1316,6 +1318,7 @@ gfxContext::SetDeviceColor(const gfxRGBA& c)
cairo_set_source_rgba(mCairo, c.r, c.g, c.b, c.a);
} else {
CurrentState().pattern = NULL;
CurrentState().sourceSurfCairo = NULL;
CurrentState().sourceSurface = NULL;
CurrentState().color = ToColor(c);
}
@ -1354,6 +1357,9 @@ gfxContext::SetSource(gfxASurface *surface, const gfxPoint& offset)
CurrentState().surfTransform = Matrix(1.0f, 0, 0, 1.0f, Float(offset.x), Float(offset.y));
CurrentState().pattern = NULL;
CurrentState().patternTransformChanged = false;
// Keep the underlying cairo surface around while we keep the
// sourceSurface.
CurrentState().sourceSurfCairo = surface;
CurrentState().sourceSurface =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface);
}
@ -1365,6 +1371,7 @@ gfxContext::SetPattern(gfxPattern *pattern)
if (mCairo) {
cairo_set_source(mCairo, pattern->CairoPattern());
} else {
CurrentState().sourceSurfCairo = NULL;
CurrentState().sourceSurface = NULL;
CurrentState().patternTransformChanged = false;
CurrentState().pattern = pattern;
@ -1421,6 +1428,7 @@ gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset)
if (mCairo) {
cairo_mask_surface(mCairo, surface->CairoSurface(), offset.x, offset.y);
} else {
// Lifetime needs to be limited here as we may simply wrap surface's data.
RefPtr<SourceSurface> sourceSurf =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface);
@ -1582,6 +1590,7 @@ gfxContext::PopGroupToSource()
} else {
RefPtr<SourceSurface> src = mDT->Snapshot();
Restore();
CurrentState().sourceSurfCairo = NULL;
CurrentState().sourceSurface = src;
CurrentState().pattern = NULL;
CurrentState().patternTransformChanged = false;

Просмотреть файл

@ -713,6 +713,7 @@ private:
bool opIsClear;
Color color;
nsRefPtr<gfxPattern> pattern;
nsRefPtr<gfxASurface> sourceSurfCairo;
mozilla::RefPtr<SourceSurface> sourceSurface;
Matrix surfTransform;
Matrix transform;

Просмотреть файл

@ -151,6 +151,8 @@ gfxPattern::GetPattern(DrawTarget *aTarget, Matrix *aPatternTransform)
if (!mSourceSurface) {
nsRefPtr<gfxASurface> gfxSurf = gfxASurface::Wrap(surf);
// The underlying surface here will be kept around by the gfxPattern.
// This function is intended to be used right away.
mSourceSurface =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTarget, gfxSurf);
}

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -472,6 +472,12 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
if (!srcBuffer) {
nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
bool isWin32ImageSurf = false;
if (imgSurface && aSurface->GetType() != gfxASurface::SurfaceTypeWin32) {
isWin32ImageSurf = true;
}
if (!imgSurface) {
imgSurface = new gfxImageSurface(aSurface->GetSize(), gfxASurface::FormatFromContent(aSurface->GetContentType()));
nsRefPtr<gfxContext> ctx = new gfxContext(imgSurface);
@ -498,17 +504,36 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa
NS_RUNTIMEABORT("Invalid surface format!");
}
IntSize size = IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height);
srcBuffer = aTarget->CreateSourceSurfaceFromData(imgSurface->Data(),
IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height),
size,
imgSurface->Stride(),
format);
if (!srcBuffer) {
// We need to check if our gfxASurface will keep the underlying data
// alive! This is true if gfxASurface actually -is- an ImageSurface or
// if it is a gfxWindowsSurface which supportes GetAsImageSurface.
if (imgSurface != aSurface && !isWin32ImageSurf) {
// This shouldn't happen for now, it can be easily supported by making
// a copy. For now let's just abort.
NS_RUNTIMEABORT("Attempt to create unsupported SourceSurface from"
"non-image surface.");
return nsnull;
}
srcBuffer = Factory::CreateWrappingDataSourceSurface(imgSurface->Data(),
imgSurface->Stride(),
size, format);
}
cairo_surface_t *nullSurf =
cairo_null_surface_create(CAIRO_CONTENT_COLOR_ALPHA);
cairo_surface_set_user_data(nullSurf,
&kSourceSurface,
imgSurface,
NULL);
&kSourceSurface,
imgSurface,
NULL);
cairo_surface_attach_snapshot(imgSurface->CairoSurface(), nullSurf, SourceSnapshotDetached);
cairo_surface_destroy(nullSurf);
}

Просмотреть файл

@ -163,6 +163,11 @@ public:
virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
CreateDrawTargetForSurface(gfxASurface *aSurface);
/*
* Creates a SourceSurface for a gfxASurface. This surface should -not- be
* held around by the user after the underlying gfxASurface has been
* destroyed as a copy of the data is not guaranteed.
*/
virtual mozilla::RefPtr<mozilla::gfx::SourceSurface>
GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);