зеркало из https://github.com/mozilla/pjs.git
Bug 635035, part 4: Implement MovePixels() for image surfaces. r=roc
This commit is contained in:
Родитель
f447d99153
Коммит
bf8aedccf6
|
@ -254,3 +254,70 @@ gfxImageSurface::GetAsImageSurface()
|
|||
nsRefPtr<gfxImageSurface> surface = this;
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
void
|
||||
gfxImageSurface::MovePixels(const nsIntRect& aSourceRect,
|
||||
const nsIntPoint& aDestTopLeft)
|
||||
{
|
||||
const nsIntRect bounds(0, 0, mSize.width, mSize.height);
|
||||
nsIntPoint offset = aDestTopLeft - aSourceRect.TopLeft();
|
||||
nsIntRect clippedSource = aSourceRect;
|
||||
clippedSource.IntersectRect(clippedSource, bounds);
|
||||
nsIntRect clippedDest = clippedSource + offset;
|
||||
clippedDest.IntersectRect(clippedDest, bounds);
|
||||
const nsIntRect dest = clippedDest;
|
||||
const nsIntRect source = dest - offset;
|
||||
// NB: this relies on IntersectRect() and operator+/- preserving
|
||||
// x/y for empty rectangles
|
||||
NS_ABORT_IF_FALSE(bounds.Contains(dest) && bounds.Contains(source) &&
|
||||
aSourceRect.Contains(source) &&
|
||||
nsIntRect(aDestTopLeft, aSourceRect.Size()).Contains(dest) &&
|
||||
source.Size() == dest.Size() &&
|
||||
offset == (dest.TopLeft() - source.TopLeft()),
|
||||
"Messed up clipping, crash or corruption will follow");
|
||||
if (source.IsEmpty() || source == dest) {
|
||||
return;
|
||||
}
|
||||
|
||||
long naturalStride = ComputeStride(mSize, mFormat);
|
||||
if (mStride == naturalStride && dest.width == bounds.width) {
|
||||
// Fast path: this is a vertical shift of some rows in a
|
||||
// "normal" image surface. We can directly memmove and
|
||||
// hopefully stay in SIMD land.
|
||||
unsigned char* dst = mData + dest.y * mStride;
|
||||
const unsigned char* src = mData + source.y * mStride;
|
||||
size_t nBytes = dest.height * mStride;
|
||||
memmove(dst, src, nBytes);
|
||||
return;
|
||||
}
|
||||
|
||||
// Slow(er) path: have to move row-by-row.
|
||||
const PRInt32 bpp = BytePerPixelFromFormat(mFormat);
|
||||
const size_t nRowBytes = dest.width * bpp;
|
||||
// dstRow points at the first pixel within the current destination
|
||||
// row, and similarly for srcRow. endSrcRow is one row beyond the
|
||||
// last row we need to copy. stride is either +mStride or
|
||||
// -mStride, depending on which direction we're copying.
|
||||
unsigned char* dstRow;
|
||||
unsigned char* srcRow;
|
||||
unsigned char* endSrcRow; // NB: this may point outside the image
|
||||
long stride;
|
||||
if (dest.y > source.y) {
|
||||
// We're copying down from source to dest, so walk backwards
|
||||
// starting from the last rows to avoid stomping pixels we
|
||||
// need.
|
||||
stride = -mStride;
|
||||
dstRow = mData + dest.x * bpp + (dest.YMost() - 1) * mStride;
|
||||
srcRow = mData + source.x * bpp + (source.YMost() - 1) * mStride;
|
||||
endSrcRow = mData + source.x * bpp + (source.y - 1) * mStride;
|
||||
} else {
|
||||
stride = mStride;
|
||||
dstRow = mData + dest.x * bpp + dest.y * mStride;
|
||||
srcRow = mData + source.x * bpp + source.y * mStride;
|
||||
endSrcRow = mData + source.x * bpp + source.YMost() * mStride;
|
||||
}
|
||||
|
||||
for (; srcRow != endSrcRow; dstRow += stride, srcRow += stride) {
|
||||
memmove(dstRow, srcRow, nRowBytes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,11 @@ public:
|
|||
|
||||
virtual PRBool SupportsSelfCopy() { return PR_FALSE; }
|
||||
|
||||
/** See gfxASurface.h. */
|
||||
NS_OVERRIDE
|
||||
virtual void MovePixels(const nsIntRect& aSourceRect,
|
||||
const nsIntPoint& aDestTopLeft);
|
||||
|
||||
protected:
|
||||
gfxImageSurface();
|
||||
void InitWithData(unsigned char *aData, const gfxIntSize& aSize,
|
||||
|
|
Загрузка…
Ссылка в новой задаче