зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1105834 - Part 1: Add CreateDataSourceSurfaceByCloning to moz2d. r=mstange,bas
This commit is contained in:
Родитель
c94b2e2945
Коммит
700fbb43f7
|
@ -9,11 +9,41 @@
|
|||
#include "DataSurfaceHelpers.h"
|
||||
#include "Logging.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "Tools.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
uint8_t*
|
||||
DataAtOffset(DataSourceSurface* aSurface, IntPoint aPoint)
|
||||
{
|
||||
if (!SurfaceContainsPoint(aSurface, aPoint)) {
|
||||
MOZ_CRASH("sample position needs to be inside surface!");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(Factory::CheckSurfaceSize(aSurface->GetSize()),
|
||||
"surface size overflows - this should have been prevented when the surface was created");
|
||||
|
||||
uint8_t* data = aSurface->GetData() + aPoint.y * aSurface->Stride() +
|
||||
aPoint.x * BytesPerPixel(aSurface->GetFormat());
|
||||
|
||||
if (data < aSurface->GetData()) {
|
||||
MOZ_CRASH("out-of-range data access");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// This check is safe against integer overflow.
|
||||
bool
|
||||
SurfaceContainsPoint(SourceSurface* aSurface, const IntPoint& aPoint)
|
||||
{
|
||||
IntSize size = aSurface->GetSize();
|
||||
return aPoint.x >= 0 && aPoint.x < size.width &&
|
||||
aPoint.y >= 0 && aPoint.y < size.height;
|
||||
}
|
||||
|
||||
void
|
||||
ConvertBGRXToBGRA(uint8_t* aData, const IntSize &aSize, int32_t aStride)
|
||||
{
|
||||
|
@ -196,5 +226,57 @@ BufferSizeFromStrideAndHeight(int32_t aStride,
|
|||
return requiredBytes.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* aSrcRect: Rect relative to the aSrc surface
|
||||
* aDestPoint: Point inside aDest surface
|
||||
*/
|
||||
void
|
||||
CopyRect(DataSourceSurface* aSrc, DataSourceSurface* aDest,
|
||||
IntRect aSrcRect, IntPoint aDestPoint)
|
||||
{
|
||||
if (aSrcRect.Overflows() ||
|
||||
IntRect(aDestPoint, aSrcRect.Size()).Overflows()) {
|
||||
MOZ_CRASH("we should never be getting invalid rects at this point");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aSrc->GetFormat() == aDest->GetFormat(), "different surface formats");
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aSrc->GetSize()).Contains(aSrcRect), "source rect too big for source surface");
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aDest->GetSize()).Contains(aSrcRect - aSrcRect.TopLeft() + aDestPoint), "dest surface too small");
|
||||
|
||||
if (aSrcRect.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t* sourceData = DataAtOffset(aSrc, aSrcRect.TopLeft());
|
||||
uint32_t sourceStride = aSrc->Stride();
|
||||
uint8_t* destData = DataAtOffset(aDest, aDestPoint);
|
||||
uint32_t destStride = aDest->Stride();
|
||||
|
||||
if (BytesPerPixel(aSrc->GetFormat()) == 4) {
|
||||
for (int32_t y = 0; y < aSrcRect.height; y++) {
|
||||
PodCopy((int32_t*)destData, (int32_t*)sourceData, aSrcRect.width);
|
||||
sourceData += sourceStride;
|
||||
destData += destStride;
|
||||
}
|
||||
} else if (BytesPerPixel(aSrc->GetFormat()) == 1) {
|
||||
for (int32_t y = 0; y < aSrcRect.height; y++) {
|
||||
PodCopy(destData, sourceData, aSrcRect.width);
|
||||
sourceData += sourceStride;
|
||||
destData += destStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TemporaryRef<DataSourceSurface>
|
||||
CreateDataSourceSurfaceByCloning(DataSourceSurface* aSource)
|
||||
{
|
||||
RefPtr<DataSourceSurface> copy =
|
||||
Factory::CreateDataSourceSurface(aSource->GetSize(), aSource->GetFormat(), true);
|
||||
if (copy) {
|
||||
CopyRect(aSource, copy, IntRect(IntPoint(), aSource->GetSize()), IntPoint());
|
||||
}
|
||||
return copy.forget();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,36 @@ BufferSizeFromStrideAndHeight(int32_t aStride,
|
|||
int32_t aHeight,
|
||||
int32_t aExtraBytes = 0);
|
||||
|
||||
/**
|
||||
* Copy aSrcRect from aSrc to aDest starting at aDestPoint.
|
||||
*/
|
||||
void
|
||||
CopyRect(DataSourceSurface* aSrc, DataSourceSurface* aDest,
|
||||
IntRect aSrcRect, IntPoint aDestPoint);
|
||||
|
||||
/**
|
||||
* Create a non aliasing copy of aSource. This creates a new DataSourceSurface
|
||||
* using the factory and copies the bits.
|
||||
*
|
||||
* @return a dss allocated by Factory that contains a copy a aSource.
|
||||
*/
|
||||
TemporaryRef<DataSourceSurface>
|
||||
CreateDataSourceSurfaceByCloning(DataSourceSurface* aSource);
|
||||
|
||||
/**
|
||||
* Return the byte at aPoint.
|
||||
*/
|
||||
uint8_t*
|
||||
DataAtOffset(DataSourceSurface* aSurface, IntPoint aPoint);
|
||||
|
||||
/**
|
||||
* Check if aPoint is contained by the surface.
|
||||
*
|
||||
* @returns true if and only if aPoint is inside the surface.
|
||||
*/
|
||||
bool
|
||||
SurfaceContainsPoint(SourceSurface* aSurface, const IntPoint& aPoint);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,101 +180,16 @@ NS_lround(double x)
|
|||
return x >= 0.0 ? int32_t(x + 0.5) : int32_t(x - 0.5);
|
||||
}
|
||||
|
||||
// This check is safe against integer overflow.
|
||||
static bool
|
||||
SurfaceContainsPoint(SourceSurface* aSurface, const IntPoint& aPoint)
|
||||
{
|
||||
IntSize size = aSurface->GetSize();
|
||||
return aPoint.x >= 0 && aPoint.x < size.width &&
|
||||
aPoint.y >= 0 && aPoint.y < size.height;
|
||||
}
|
||||
|
||||
static uint8_t*
|
||||
DataAtOffset(DataSourceSurface* aSurface, IntPoint aPoint)
|
||||
{
|
||||
if (!SurfaceContainsPoint(aSurface, aPoint)) {
|
||||
MOZ_CRASH("sample position needs to be inside surface!");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(Factory::CheckSurfaceSize(aSurface->GetSize()),
|
||||
"surface size overflows - this should have been prevented when the surface was created");
|
||||
|
||||
uint8_t* data = aSurface->GetData() + aPoint.y * aSurface->Stride() +
|
||||
aPoint.x * BytesPerPixel(aSurface->GetFormat());
|
||||
|
||||
if (data < aSurface->GetData()) {
|
||||
MOZ_CRASH("out-of-range data access");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static bool
|
||||
IntRectOverflows(const IntRect& aRect)
|
||||
{
|
||||
CheckedInt<int32_t> xMost = aRect.x;
|
||||
xMost += aRect.width;
|
||||
CheckedInt<int32_t> yMost = aRect.y;
|
||||
yMost += aRect.height;
|
||||
return !xMost.isValid() || !yMost.isValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* aSrcRect: Rect relative to the aSrc surface
|
||||
* aDestPoint: Point inside aDest surface
|
||||
*/
|
||||
static void
|
||||
CopyRect(DataSourceSurface* aSrc, DataSourceSurface* aDest,
|
||||
IntRect aSrcRect, IntPoint aDestPoint)
|
||||
{
|
||||
if (IntRectOverflows(aSrcRect) ||
|
||||
IntRectOverflows(IntRect(aDestPoint, aSrcRect.Size()))) {
|
||||
MOZ_CRASH("we should never be getting invalid rects at this point");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aSrc->GetFormat() == aDest->GetFormat(), "different surface formats");
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aSrc->GetSize()).Contains(aSrcRect), "source rect too big for source surface");
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aDest->GetSize()).Contains(aSrcRect - aSrcRect.TopLeft() + aDestPoint), "dest surface too small");
|
||||
|
||||
if (aSrcRect.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t* sourceData = DataAtOffset(aSrc, aSrcRect.TopLeft());
|
||||
uint32_t sourceStride = aSrc->Stride();
|
||||
uint8_t* destData = DataAtOffset(aDest, aDestPoint);
|
||||
uint32_t destStride = aDest->Stride();
|
||||
|
||||
if (BytesPerPixel(aSrc->GetFormat()) == 4) {
|
||||
for (int32_t y = 0; y < aSrcRect.height; y++) {
|
||||
PodCopy((int32_t*)destData, (int32_t*)sourceData, aSrcRect.width);
|
||||
sourceData += sourceStride;
|
||||
destData += destStride;
|
||||
}
|
||||
} else if (BytesPerPixel(aSrc->GetFormat()) == 1) {
|
||||
for (int32_t y = 0; y < aSrcRect.height; y++) {
|
||||
PodCopy(destData, sourceData, aSrcRect.width);
|
||||
sourceData += sourceStride;
|
||||
destData += destStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TemporaryRef<DataSourceSurface>
|
||||
CloneAligned(DataSourceSurface* aSource)
|
||||
{
|
||||
RefPtr<DataSourceSurface> copy =
|
||||
Factory::CreateDataSourceSurface(aSource->GetSize(), aSource->GetFormat(), true);
|
||||
if (copy) {
|
||||
CopyRect(aSource, copy, IntRect(IntPoint(), aSource->GetSize()), IntPoint());
|
||||
}
|
||||
return copy.forget();
|
||||
return CreateDataSourceSurfaceByCloning(aSource);
|
||||
}
|
||||
|
||||
static void
|
||||
FillRectWithPixel(DataSourceSurface *aSurface, const IntRect &aFillRect, IntPoint aPixelPos)
|
||||
{
|
||||
MOZ_ASSERT(!IntRectOverflows(aFillRect));
|
||||
MOZ_ASSERT(!aFillRect.Overflows());
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aFillRect),
|
||||
"aFillRect needs to be completely inside the surface");
|
||||
MOZ_ASSERT(SurfaceContainsPoint(aSurface, aPixelPos),
|
||||
|
@ -307,8 +222,8 @@ FillRectWithVerticallyRepeatingHorizontalStrip(DataSourceSurface *aSurface,
|
|||
const IntRect &aFillRect,
|
||||
const IntRect &aSampleRect)
|
||||
{
|
||||
MOZ_ASSERT(!IntRectOverflows(aFillRect));
|
||||
MOZ_ASSERT(!IntRectOverflows(aSampleRect));
|
||||
MOZ_ASSERT(!aFillRect.Overflows());
|
||||
MOZ_ASSERT(!aSampleRect.Overflows());
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aFillRect),
|
||||
"aFillRect needs to be completely inside the surface");
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aSampleRect),
|
||||
|
@ -335,8 +250,8 @@ FillRectWithHorizontallyRepeatingVerticalStrip(DataSourceSurface *aSurface,
|
|||
const IntRect &aFillRect,
|
||||
const IntRect &aSampleRect)
|
||||
{
|
||||
MOZ_ASSERT(!IntRectOverflows(aFillRect));
|
||||
MOZ_ASSERT(!IntRectOverflows(aSampleRect));
|
||||
MOZ_ASSERT(!aFillRect.Overflows());
|
||||
MOZ_ASSERT(!aSampleRect.Overflows());
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aFillRect),
|
||||
"aFillRect needs to be completely inside the surface");
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aSampleRect),
|
||||
|
@ -367,7 +282,7 @@ FillRectWithHorizontallyRepeatingVerticalStrip(DataSourceSurface *aSurface,
|
|||
static void
|
||||
DuplicateEdges(DataSourceSurface* aSurface, const IntRect &aFromRect)
|
||||
{
|
||||
MOZ_ASSERT(!IntRectOverflows(aFromRect));
|
||||
MOZ_ASSERT(!aFromRect.Overflows());
|
||||
MOZ_ASSERT(IntRect(IntPoint(), aSurface->GetSize()).Contains(aFromRect),
|
||||
"aFromRect needs to be completely inside the surface");
|
||||
|
||||
|
@ -475,7 +390,7 @@ GetDataSurfaceInRect(SourceSurface *aSurface,
|
|||
{
|
||||
MOZ_ASSERT(aSurface ? aSurfaceRect.Size() == aSurface->GetSize() : aSurfaceRect.IsEmpty());
|
||||
|
||||
if (IntRectOverflows(aSurfaceRect) || IntRectOverflows(aDestRect)) {
|
||||
if (aSurfaceRect.Overflows() || aDestRect.Overflows()) {
|
||||
// We can't rely on the intersection calculations below to make sense when
|
||||
// XMost() or YMost() overflow. Bail out.
|
||||
return nullptr;
|
||||
|
@ -629,7 +544,7 @@ FilterNodeSoftware::Draw(DrawTarget* aDrawTarget,
|
|||
}
|
||||
|
||||
IntRect outputRect = GetOutputRectInRect(renderIntRect);
|
||||
if (IntRectOverflows(outputRect)) {
|
||||
if (outputRect.Overflows()) {
|
||||
#ifdef DEBUG_DUMP_SURFACES
|
||||
printf("output rect overflowed, not painting anything\n");
|
||||
printf("</pre>\n");
|
||||
|
@ -680,7 +595,7 @@ FilterNodeSoftware::GetOutput(const IntRect &aRect)
|
|||
{
|
||||
MOZ_ASSERT(GetOutputRectInRect(aRect).Contains(aRect));
|
||||
|
||||
if (IntRectOverflows(aRect)) {
|
||||
if (aRect.Overflows()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -710,7 +625,7 @@ FilterNodeSoftware::RequestRect(const IntRect &aRect)
|
|||
void
|
||||
FilterNodeSoftware::RequestInputRect(uint32_t aInputEnumIndex, const IntRect &aRect)
|
||||
{
|
||||
if (IntRectOverflows(aRect)) {
|
||||
if (aRect.Overflows()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -743,7 +658,7 @@ FilterNodeSoftware::GetInputDataSourceSurface(uint32_t aInputEnumIndex,
|
|||
ConvolveMatrixEdgeMode aEdgeMode,
|
||||
const IntRect *aTransparencyPaddedSourceRect)
|
||||
{
|
||||
if (IntRectOverflows(aRect)) {
|
||||
if (aRect.Overflows()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -858,7 +773,7 @@ IntRect
|
|||
FilterNodeSoftware::GetInputRectInRect(uint32_t aInputEnumIndex,
|
||||
const IntRect &aInRect)
|
||||
{
|
||||
if (IntRectOverflows(aInRect)) {
|
||||
if (aInRect.Overflows()) {
|
||||
return IntRect();
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,14 @@ struct IntRectTyped :
|
|||
IntRectTyped<UnknownUnits> ToUnknownRect() const {
|
||||
return IntRectTyped<UnknownUnits>(this->x, this->y, this->width, this->height);
|
||||
}
|
||||
|
||||
bool Overflows() const {
|
||||
CheckedInt<int32_t> xMost = this->x;
|
||||
xMost += this->width;
|
||||
CheckedInt<int32_t> yMost = this->y;
|
||||
yMost += this->height;
|
||||
return !xMost.isValid() || !yMost.isValid();
|
||||
}
|
||||
};
|
||||
typedef IntRectTyped<UnknownUnits> IntRect;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче