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
Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
const Maybe<nsIntRect>& aFrameRect,
uint8_t* aOutputBuffer,
bool aHasAlpha,
bool aFlipVertically /* = false */)
@ -71,6 +72,17 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
MOZ_ASSERT(aOriginalSize.width > 0 && aOriginalSize.height > 0,
"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;
mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width,
double(mOriginalSize.height) / mTargetSize.height);
@ -78,7 +90,6 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
mHasAlpha = aHasAlpha;
mFlipVertically = aFlipVertically;
ResetForNextProgressivePass();
ReleaseWindow();
auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3;
@ -124,9 +135,22 @@ Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
return NS_ERROR_OUT_OF_MEMORY;
}
ResetForNextProgressivePass();
return NS_OK;
}
void
Downscaler::SkipToRow(int32_t aRow)
{
if (mCurrentInLine < aRow) {
ClearRow();
do {
CommitRow();
} while (mCurrentInLine < aRow);
}
}
void
Downscaler::ResetForNextProgressivePass()
{
@ -134,6 +158,9 @@ Downscaler::ResetForNextProgressivePass()
mCurrentOutLine = 0;
mCurrentInLine = 0;
mLinesInBuffer = 0;
// If we have a vertical offset, commit rows to shift us past it.
SkipToRow(mFrameRect.y);
}
static void
@ -193,6 +220,12 @@ Downscaler::CommitRow()
}
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

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

@ -12,10 +12,10 @@
#ifndef mozilla_image_Downscaler_h
#define mozilla_image_Downscaler_h
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include "nsRect.h"
namespace skia {
class ConvolutionFilter1D;
} // namespace skia
@ -64,6 +64,9 @@ public:
* Begins a new frame and reinitializes the Downscaler.
*
* @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
* output; this is the same buffer where the Decoder
* would write its output when not downscaling during
@ -75,12 +78,16 @@ public:
* the way they are stored in some image formats.
*/
nsresult BeginFrame(const nsIntSize& aOriginalSize,
const Maybe<nsIntRect>& aFrameRect,
uint8_t* aOutputBuffer,
bool aHasAlpha,
bool aFlipVertically = false);
/// 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).
void ClearRow(uint32_t aStartingAtCol = 0);
@ -104,9 +111,11 @@ public:
private:
void DownscaleInputLine();
void ReleaseWindow();
void SkipToRow(int32_t aRow);
nsIntSize mOriginalSize;
nsIntSize mTargetSize;
nsIntRect mFrameRect;
gfxSize mScale;
uint8_t* mOutputBuffer;

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

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

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

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

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

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

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

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

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

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

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

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