mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 997304 - Copy the image data if it's not a suitable size for cairo. r=Bas
This commit is contained in:
parent
59213f7de9
commit
8955c86721
@ -133,6 +133,36 @@ ReleaseData(void* aData)
|
|||||||
static_cast<DataSourceSurface*>(aData)->Release();
|
static_cast<DataSourceSurface*>(aData)->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cairo_surface_t*
|
||||||
|
CopyToImageSurface(unsigned char *aData,
|
||||||
|
const IntSize &aSize,
|
||||||
|
int32_t aStride,
|
||||||
|
SurfaceFormat aFormat)
|
||||||
|
{
|
||||||
|
cairo_surface_t* surf = cairo_image_surface_create(GfxFormatToCairoFormat(aFormat),
|
||||||
|
aSize.width,
|
||||||
|
aSize.height);
|
||||||
|
// In certain scenarios, requesting larger than 8k image fails. Bug 803568
|
||||||
|
// covers the details of how to run into it, but the full detailed
|
||||||
|
// investigation hasn't been done to determine the underlying cause. We
|
||||||
|
// will just handle the failure to allocate the surface to avoid a crash.
|
||||||
|
if (cairo_surface_status(surf)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* surfData = cairo_image_surface_get_data(surf);
|
||||||
|
int surfStride = cairo_image_surface_get_stride(surf);
|
||||||
|
int32_t pixelWidth = BytesPerPixel(aFormat);
|
||||||
|
|
||||||
|
for (int32_t y = 0; y < aSize.height; ++y) {
|
||||||
|
memcpy(surfData + y * surfStride,
|
||||||
|
aData + y * aStride,
|
||||||
|
aSize.width * pixelWidth);
|
||||||
|
}
|
||||||
|
cairo_surface_mark_dirty(surf);
|
||||||
|
return surf;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns cairo surface for the given SourceSurface.
|
* Returns cairo surface for the given SourceSurface.
|
||||||
* If possible, it will use the cairo_surface associated with aSurface,
|
* If possible, it will use the cairo_surface associated with aSurface,
|
||||||
@ -177,7 +207,16 @@ GetCairoSurfaceForSourceSurface(SourceSurface *aSurface, bool aExistingOnly = fa
|
|||||||
// investigation hasn't been done to determine the underlying cause. We
|
// investigation hasn't been done to determine the underlying cause. We
|
||||||
// will just handle the failure to allocate the surface to avoid a crash.
|
// will just handle the failure to allocate the surface to avoid a crash.
|
||||||
if (cairo_surface_status(surf)) {
|
if (cairo_surface_status(surf)) {
|
||||||
cairo_surface_destroy(surf);
|
if (cairo_surface_status(surf) == CAIRO_STATUS_INVALID_STRIDE) {
|
||||||
|
// If we failed because of an invalid stride then copy into
|
||||||
|
// a new surface with a stride that cairo chooses. No need to
|
||||||
|
// set user data since we're not dependent on the original
|
||||||
|
// data.
|
||||||
|
return CopyToImageSurface(data->GetData(),
|
||||||
|
data->GetSize(),
|
||||||
|
data->Stride(),
|
||||||
|
data->GetFormat());
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1056,52 +1095,13 @@ DrawTargetCairo::CreateFilter(FilterType aType)
|
|||||||
return FilterNodeSoftware::Create(aType);
|
return FilterNodeSoftware::Create(aType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies pixel data from aData into aSurface; aData must have the dimensions
|
|
||||||
* given in aSize, with a stride of aStride bytes and aPixelWidth bytes per pixel
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
CopyDataToCairoSurface(cairo_surface_t* aSurface,
|
|
||||||
unsigned char *aData,
|
|
||||||
const IntSize &aSize,
|
|
||||||
int32_t aStride,
|
|
||||||
int32_t aPixelWidth)
|
|
||||||
{
|
|
||||||
unsigned char* surfData = cairo_image_surface_get_data(aSurface);
|
|
||||||
int surfStride = cairo_image_surface_get_stride(aSurface);
|
|
||||||
// In certain scenarios, requesting larger than 8k image fails. Bug 803568
|
|
||||||
// covers the details of how to run into it, but the full detailed
|
|
||||||
// investigation hasn't been done to determine the underlying cause. We
|
|
||||||
// will just handle the failure to allocate the surface to avoid a crash.
|
|
||||||
if (!surfData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (int32_t y = 0; y < aSize.height; ++y) {
|
|
||||||
memcpy(surfData + y * surfStride,
|
|
||||||
aData + y * aStride,
|
|
||||||
aSize.width * aPixelWidth);
|
|
||||||
}
|
|
||||||
cairo_surface_mark_dirty(aSurface);
|
|
||||||
}
|
|
||||||
|
|
||||||
TemporaryRef<SourceSurface>
|
TemporaryRef<SourceSurface>
|
||||||
DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
|
DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
|
||||||
const IntSize &aSize,
|
const IntSize &aSize,
|
||||||
int32_t aStride,
|
int32_t aStride,
|
||||||
SurfaceFormat aFormat) const
|
SurfaceFormat aFormat) const
|
||||||
{
|
{
|
||||||
cairo_surface_t* surf = cairo_image_surface_create(GfxFormatToCairoFormat(aFormat),
|
cairo_surface_t* surf = CopyToImageSurface(aData, aSize, aStride, aFormat);
|
||||||
aSize.width,
|
|
||||||
aSize.height);
|
|
||||||
// In certain scenarios, requesting larger than 8k image fails. Bug 803568
|
|
||||||
// covers the details of how to run into it, but the full detailed
|
|
||||||
// investigation hasn't been done to determine the underlying cause. We
|
|
||||||
// will just handle the failure to allocate the surface to avoid a crash.
|
|
||||||
if (cairo_surface_status(surf)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CopyDataToCairoSurface(surf, aData, aSize, aStride, BytesPerPixel(aFormat));
|
|
||||||
|
|
||||||
RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
|
RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
|
||||||
cairo_surface_destroy(surf);
|
cairo_surface_destroy(surf);
|
||||||
|
@ -198,6 +198,7 @@ private: // methods
|
|||||||
// If the current operator is "source" then clear the destination before we
|
// If the current operator is "source" then clear the destination before we
|
||||||
// draw into it, to simulate the effect of an unbounded source operator.
|
// draw into it, to simulate the effect of an unbounded source operator.
|
||||||
void ClearSurfaceForUnboundedSource(const CompositionOp &aOperator);
|
void ClearSurfaceForUnboundedSource(const CompositionOp &aOperator);
|
||||||
|
|
||||||
private: // data
|
private: // data
|
||||||
cairo_t* mContext;
|
cairo_t* mContext;
|
||||||
cairo_surface_t* mSurface;
|
cairo_surface_t* mSurface;
|
||||||
|
Loading…
Reference in New Issue
Block a user