Bug 1207378 (Part 1) - Add support for a frame rect to Downscaler. r=tn

This commit is contained in:
Seth Fowler 2015-09-26 01:36:19 -07:00
Родитель 2648aa6251
Коммит ba99adc235
8 изменённых файлов: 53 добавлений и 9 удалений

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

@ -57,6 +57,7 @@ Downscaler::ReleaseWindow()
nsresult nsresult
Downscaler::BeginFrame(const nsIntSize& aOriginalSize, Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
const Maybe<nsIntRect>& aFrameRect,
uint8_t* aOutputBuffer, uint8_t* aOutputBuffer,
bool aHasAlpha, bool aHasAlpha,
bool aFlipVertically /* = false */) bool aFlipVertically /* = false */)
@ -71,6 +72,17 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
MOZ_ASSERT(aOriginalSize.width > 0 && aOriginalSize.height > 0, MOZ_ASSERT(aOriginalSize.width > 0 && aOriginalSize.height > 0,
"Invalid original size"); "Invalid original size");
mFrameRect = aFrameRect.valueOr(nsIntRect(nsIntPoint(), aOriginalSize));
MOZ_ASSERT(mFrameRect.x >= 0 && mFrameRect.y >= 0 &&
mFrameRect.width > 0 && mFrameRect.height > 0,
"Frame rect must have positive components");
MOZ_ASSERT(nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
.Contains(mFrameRect),
"Frame rect must fit inside image");
MOZ_ASSERT_IF(!nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
.IsEqualEdges(mFrameRect),
aHasAlpha);
mOriginalSize = aOriginalSize; mOriginalSize = aOriginalSize;
mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width, mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width,
double(mOriginalSize.height) / mTargetSize.height); double(mOriginalSize.height) / mTargetSize.height);
@ -78,7 +90,6 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
mHasAlpha = aHasAlpha; mHasAlpha = aHasAlpha;
mFlipVertically = aFlipVertically; mFlipVertically = aFlipVertically;
ResetForNextProgressivePass();
ReleaseWindow(); ReleaseWindow();
auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3; auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3;
@ -124,9 +135,22 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
ResetForNextProgressivePass();
return NS_OK; return NS_OK;
} }
void
Downscaler::SkipToRow(int32_t aRow)
{
if (mCurrentInLine < aRow) {
ClearRow();
do {
CommitRow();
} while (mCurrentInLine < aRow);
}
}
void void
Downscaler::ResetForNextProgressivePass() Downscaler::ResetForNextProgressivePass()
{ {
@ -134,6 +158,9 @@ Downscaler::ResetForNextProgressivePass()
mCurrentOutLine = 0; mCurrentOutLine = 0;
mCurrentInLine = 0; mCurrentInLine = 0;
mLinesInBuffer = 0; mLinesInBuffer = 0;
// If we have a vertical offset, commit rows to shift us past it.
SkipToRow(mFrameRect.y);
} }
static void static void
@ -193,6 +220,12 @@ Downscaler::CommitRow()
} }
mCurrentInLine += 1; mCurrentInLine += 1;
// If we're at the end of the part of the original image that has data, commit
// rows to shift us to the end.
if (mCurrentInLine == (mFrameRect.y + mFrameRect.height)) {
SkipToRow(mOriginalSize.height - 1);
}
} }
bool bool

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

@ -12,10 +12,10 @@
#ifndef mozilla_image_Downscaler_h #ifndef mozilla_image_Downscaler_h
#define mozilla_image_Downscaler_h #define mozilla_image_Downscaler_h
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "nsRect.h" #include "nsRect.h"
namespace skia { namespace skia {
class ConvolutionFilter1D; class ConvolutionFilter1D;
} // namespace skia } // namespace skia
@ -64,6 +64,9 @@ public:
* Begins a new frame and reinitializes the Downscaler. * Begins a new frame and reinitializes the Downscaler.
* *
* @param aOriginalSize The original size of this frame, before scaling. * @param aOriginalSize The original size of this frame, before scaling.
* @param aFrameRect The region of the original image which has data.
* Every pixel outside @aFrameRect is considered blank and
* has zero alpha.
* @param aOutputBuffer The buffer to which the Downscaler should write its * @param aOutputBuffer The buffer to which the Downscaler should write its
* output; this is the same buffer where the Decoder * output; this is the same buffer where the Decoder
* would write its output when not downscaling during * would write its output when not downscaling during
@ -75,12 +78,16 @@ public:
* the way they are stored in some image formats. * the way they are stored in some image formats.
*/ */
nsresult BeginFrame(const nsIntSize& aOriginalSize, nsresult BeginFrame(const nsIntSize& aOriginalSize,
const Maybe<nsIntRect>& aFrameRect,
uint8_t* aOutputBuffer, uint8_t* aOutputBuffer,
bool aHasAlpha, bool aHasAlpha,
bool aFlipVertically = false); bool aFlipVertically = false);
/// Retrieves the buffer into which the Decoder should write each row. /// Retrieves the buffer into which the Decoder should write each row.
uint8_t* RowBuffer() { return mRowBuffer.get(); } uint8_t* RowBuffer()
{
return mRowBuffer.get() + mFrameRect.x * sizeof(uint32_t);
}
/// Clears the current row buffer (optionally starting at @aStartingAtCol). /// Clears the current row buffer (optionally starting at @aStartingAtCol).
void ClearRow(uint32_t aStartingAtCol = 0); void ClearRow(uint32_t aStartingAtCol = 0);
@ -104,9 +111,11 @@ public:
private: private:
void DownscaleInputLine(); void DownscaleInputLine();
void ReleaseWindow(); void ReleaseWindow();
void SkipToRow(int32_t aRow);
nsIntSize mOriginalSize; nsIntSize mOriginalSize;
nsIntSize mTargetSize; nsIntSize mTargetSize;
nsIntRect mFrameRect;
gfxSize mScale; gfxSize mScale;
uint8_t* mOutputBuffer; uint8_t* mOutputBuffer;

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

@ -461,7 +461,8 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
if (mDownscaler) { if (mDownscaler) {
// BMPs store their rows in reverse order, so the downscaler needs to // BMPs store their rows in reverse order, so the downscaler needs to
// reverse them again when writing its output. // reverse them again when writing its output.
rv = mDownscaler->BeginFrame(GetSize(), mImageData, hasTransparency, rv = mDownscaler->BeginFrame(GetSize(), Nothing(),
mImageData, hasTransparency,
/* aFlipVertically = */ true); /* aFlipVertically = */ true);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return; return;

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

@ -279,7 +279,7 @@ nsGIFDecoder2::BeginImageFrame(uint16_t aDepth)
} }
if (mDownscaler) { if (mDownscaler) {
rv = mDownscaler->BeginFrame(frameRect.Size(), mImageData, rv = mDownscaler->BeginFrame(frameRect.Size(), Nothing(), mImageData,
mGIFStruct.is_transparent); mGIFStruct.is_transparent);
} }

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

@ -553,7 +553,7 @@ nsICODecoder::PrepareForMask()
mDownscaler->TargetSize().height * mDownscaler->TargetSize().height *
sizeof(uint32_t)); sizeof(uint32_t));
mMaskBuffer = MakeUnique<uint8_t[]>(bmpDecoder->GetImageDataLength()); mMaskBuffer = MakeUnique<uint8_t[]>(bmpDecoder->GetImageDataLength());
nsresult rv = mDownscaler->BeginFrame(GetRealSize(), nsresult rv = mDownscaler->BeginFrame(GetRealSize(), Nothing(),
mMaskBuffer.get(), mMaskBuffer.get(),
/* aHasAlpha = */ true, /* aHasAlpha = */ true,
/* aFlipVertically = */ true); /* aFlipVertically = */ true);

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

@ -93,7 +93,7 @@ nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
MOZ_ASSERT(mImageData, "Should have a buffer now"); MOZ_ASSERT(mImageData, "Should have a buffer now");
if (mDownscaler) { if (mDownscaler) {
nsresult rv = mDownscaler->BeginFrame(GetSize(), nsresult rv = mDownscaler->BeginFrame(GetSize(), Nothing(),
mImageData, mImageData,
/* aHasAlpha = */ true); /* aHasAlpha = */ true);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

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

@ -398,7 +398,7 @@ nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
MOZ_ASSERT(mImageData, "Should have a buffer now"); MOZ_ASSERT(mImageData, "Should have a buffer now");
if (mDownscaler) { if (mDownscaler) {
nsresult rv = mDownscaler->BeginFrame(GetSize(), nsresult rv = mDownscaler->BeginFrame(GetSize(), Nothing(),
mImageData, mImageData,
/* aHasAlpha = */ false); /* aHasAlpha = */ false);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

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

@ -209,7 +209,8 @@ nsPNGDecoder::CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
if (mDownscaler) { if (mDownscaler) {
bool hasAlpha = aFormat != SurfaceFormat::B8G8R8X8; bool hasAlpha = aFormat != SurfaceFormat::B8G8R8X8;
rv = mDownscaler->BeginFrame(frameRect.Size(), mImageData, hasAlpha); rv = mDownscaler->BeginFrame(frameRect.Size(), Nothing(),
mImageData, hasAlpha);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
} }