mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1062723 - Part 2: Implement source clipping for DrawTargetCairo. r=Bas
--HG-- extra : rebase_source : 9e02e1e91c3bcd455640a1f60e4da673302c5cf1
This commit is contained in:
parent
8fa1eb06cd
commit
db36f48ca5
@ -144,13 +144,13 @@ ReleaseData(void* aData)
|
||||
|
||||
cairo_surface_t*
|
||||
CopyToImageSurface(unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
const IntRect &aRect,
|
||||
int32_t aStride,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
cairo_surface_t* surf = cairo_image_surface_create(GfxFormatToCairoFormat(aFormat),
|
||||
aSize.width,
|
||||
aSize.height);
|
||||
aRect.width,
|
||||
aRect.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
|
||||
@ -163,15 +163,92 @@ CopyToImageSurface(unsigned char *aData,
|
||||
int surfStride = cairo_image_surface_get_stride(surf);
|
||||
int32_t pixelWidth = BytesPerPixel(aFormat);
|
||||
|
||||
for (int32_t y = 0; y < aSize.height; ++y) {
|
||||
unsigned char* source = aData +
|
||||
aRect.y * aStride +
|
||||
aRect.x * pixelWidth;
|
||||
|
||||
for (int32_t y = 0; y < aRect.height; ++y) {
|
||||
memcpy(surfData + y * surfStride,
|
||||
aData + y * aStride,
|
||||
aSize.width * pixelWidth);
|
||||
source + y * aStride,
|
||||
aRect.width * pixelWidth);
|
||||
}
|
||||
cairo_surface_mark_dirty(surf);
|
||||
return surf;
|
||||
}
|
||||
|
||||
/**
|
||||
* If aSurface can be represented as a surface of type
|
||||
* CAIRO_SURFACE_TYPE_IMAGE then returns that surface. Does
|
||||
* not add a reference.
|
||||
*/
|
||||
cairo_surface_t* GetAsImageSurface(cairo_surface_t* aSurface)
|
||||
{
|
||||
if (cairo_surface_get_type(aSurface) == CAIRO_SURFACE_TYPE_IMAGE) {
|
||||
return aSurface;
|
||||
#ifdef CAIRO_HAS_WIN32_SURFACE
|
||||
} else if (cairo_surface_get_type(aSurface) == CAIRO_SURFACE_TYPE_WIN32) {
|
||||
return cairo_win32_surface_get_image(aSurface);
|
||||
#endif
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cairo_surface_t* CreateSubImageForData(unsigned char* aData,
|
||||
const IntRect& aRect,
|
||||
int aStride,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
unsigned char *data = aData +
|
||||
aRect.y * aStride +
|
||||
aRect.x * BytesPerPixel(aFormat);
|
||||
|
||||
cairo_surface_t *image =
|
||||
cairo_image_surface_create_for_data(data,
|
||||
GfxFormatToCairoFormat(aFormat),
|
||||
aRect.width,
|
||||
aRect.height,
|
||||
aStride);
|
||||
cairo_surface_set_device_offset(image, -aRect.x, -aRect.y);
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a referenced cairo_surface_t representing the
|
||||
* sub-image specified by aSubImage.
|
||||
*/
|
||||
cairo_surface_t* ExtractSubImage(cairo_surface_t* aSurface,
|
||||
const IntRect& aSubImage,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
// No need to worry about retaining a reference to the original
|
||||
// surface since the only caller of this function guarantees
|
||||
// that aSurface will stay alive as long as the result
|
||||
|
||||
cairo_surface_t* image = GetAsImageSurface(aSurface);
|
||||
if (image) {
|
||||
image = CreateSubImageForData(cairo_image_surface_get_data(image),
|
||||
aSubImage,
|
||||
cairo_image_surface_get_stride(image),
|
||||
aFormat);
|
||||
return image;
|
||||
}
|
||||
|
||||
cairo_surface_t* similar =
|
||||
cairo_surface_create_similar(aSurface,
|
||||
cairo_surface_get_content(aSurface),
|
||||
aSubImage.width, aSubImage.height);
|
||||
|
||||
cairo_t* ctx = cairo_create(similar);
|
||||
cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_surface(ctx, aSurface, -aSubImage.x, -aSubImage.y);
|
||||
cairo_paint(ctx);
|
||||
cairo_destroy(ctx);
|
||||
|
||||
cairo_surface_set_device_offset(similar, -aSubImage.x, -aSubImage.y);
|
||||
return similar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cairo surface for the given SourceSurface.
|
||||
* If possible, it will use the cairo_surface associated with aSurface,
|
||||
@ -180,18 +257,35 @@ CopyToImageSurface(unsigned char *aData,
|
||||
* result when it is done with it.
|
||||
*/
|
||||
cairo_surface_t*
|
||||
GetCairoSurfaceForSourceSurface(SourceSurface *aSurface, bool aExistingOnly = false)
|
||||
GetCairoSurfaceForSourceSurface(SourceSurface *aSurface,
|
||||
bool aExistingOnly = false,
|
||||
const IntRect& aSubImage = IntRect())
|
||||
{
|
||||
IntRect subimage = IntRect(IntPoint(), aSurface->GetSize());
|
||||
if (!aSubImage.IsEmpty()) {
|
||||
MOZ_ASSERT(!aExistingOnly);
|
||||
MOZ_ASSERT(subimage.Contains(aSubImage));
|
||||
subimage = aSubImage;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() == SurfaceType::CAIRO) {
|
||||
cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
|
||||
cairo_surface_reference(surf);
|
||||
if (aSubImage.IsEmpty()) {
|
||||
cairo_surface_reference(surf);
|
||||
} else {
|
||||
surf = ExtractSubImage(surf, subimage, aSurface->GetFormat());
|
||||
}
|
||||
return surf;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() == SurfaceType::CAIRO_IMAGE) {
|
||||
cairo_surface_t* surf =
|
||||
static_cast<const DataSourceSurfaceCairo*>(aSurface)->GetSurface();
|
||||
cairo_surface_reference(surf);
|
||||
if (aSubImage.IsEmpty()) {
|
||||
cairo_surface_reference(surf);
|
||||
} else {
|
||||
surf = ExtractSubImage(surf, subimage, aSurface->GetFormat());
|
||||
}
|
||||
return surf;
|
||||
}
|
||||
|
||||
@ -210,11 +304,8 @@ GetCairoSurfaceForSourceSurface(SourceSurface *aSurface, bool aExistingOnly = fa
|
||||
}
|
||||
|
||||
cairo_surface_t* surf =
|
||||
cairo_image_surface_create_for_data(map.mData,
|
||||
GfxFormatToCairoFormat(data->GetFormat()),
|
||||
data->GetSize().width,
|
||||
data->GetSize().height,
|
||||
map.mStride);
|
||||
CreateSubImageForData(map.mData, subimage,
|
||||
map.mStride, data->GetFormat());
|
||||
|
||||
// In certain scenarios, requesting larger than 8k image fails. Bug 803568
|
||||
// covers the details of how to run into it, but the full detailed
|
||||
@ -228,7 +319,7 @@ GetCairoSurfaceForSourceSurface(SourceSurface *aSurface, bool aExistingOnly = fa
|
||||
// data.
|
||||
cairo_surface_t* result =
|
||||
CopyToImageSurface(map.mData,
|
||||
data->GetSize(),
|
||||
subimage,
|
||||
map.mStride,
|
||||
data->GetFormat());
|
||||
data->Unmap();
|
||||
@ -320,7 +411,9 @@ GfxPatternToCairoPattern(const Pattern& aPattern, Float aAlpha)
|
||||
case PatternType::SURFACE:
|
||||
{
|
||||
const SurfacePattern& pattern = static_cast<const SurfacePattern&>(aPattern);
|
||||
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(pattern.mSurface);
|
||||
cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(pattern.mSurface,
|
||||
false,
|
||||
pattern.mSamplingRect);
|
||||
if (!surf)
|
||||
return nullptr;
|
||||
|
||||
@ -1149,7 +1242,8 @@ DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
int32_t aStride,
|
||||
SurfaceFormat aFormat) const
|
||||
{
|
||||
cairo_surface_t* surf = CopyToImageSurface(aData, aSize, aStride, aFormat);
|
||||
cairo_surface_t* surf = CopyToImageSurface(aData, IntRect(IntPoint(), aSize),
|
||||
aStride, aFormat);
|
||||
|
||||
RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
|
||||
cairo_surface_destroy(surf);
|
||||
|
Loading…
Reference in New Issue
Block a user