Skip to content

Commit

Permalink
Bug 1207378 (Part 1) - Add support for a frame rect to Downscaler. r=tn
Browse files Browse the repository at this point in the history
  • Loading branch information
sethfowler committed Sep 26, 2015
1 parent 4ed8cbe commit c2e7886
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 9 deletions.
35 changes: 34 additions & 1 deletion image/Downscaler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Downscaler::ReleaseWindow()

nsresult
Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
const Maybe<nsIntRect>& aFrameRect,
uint8_t* aOutputBuffer,
bool aHasAlpha,
bool aFlipVertically /* = false */)
Expand All @@ -71,14 +72,24 @@ 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);
mOutputBuffer = aOutputBuffer;
mHasAlpha = aHasAlpha;
mFlipVertically = aFlipVertically;

ResetForNextProgressivePass();
ReleaseWindow();

auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3;
Expand Down Expand Up @@ -124,16 +135,32 @@ 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()
{
mPrevInvalidatedLine = 0;
mCurrentOutLine = 0;
mCurrentInLine = 0;
mLinesInBuffer = 0;

// If we have a vertical offset, commit rows to shift us past it.
SkipToRow(mFrameRect.y);
}

static void
Expand Down Expand Up @@ -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
Expand Down
13 changes: 11 additions & 2 deletions image/Downscaler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -64,6 +64,9 @@ class Downscaler
* 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
Expand All @@ -75,12 +78,16 @@ class Downscaler
* 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);
Expand All @@ -104,9 +111,11 @@ class Downscaler
private:
void DownscaleInputLine();
void ReleaseWindow();
void SkipToRow(int32_t aRow);

nsIntSize mOriginalSize;
nsIntSize mTargetSize;
nsIntRect mFrameRect;
gfxSize mScale;

uint8_t* mOutputBuffer;
Expand Down
3 changes: 2 additions & 1 deletion image/decoders/nsBMPDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion image/decoders/nsGIFDecoder2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion image/decoders/nsICODecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion image/decoders/nsIconDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
2 changes: 1 addition & 1 deletion image/decoders/nsJPEGDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
3 changes: 2 additions & 1 deletion image/decoders/nsPNGDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit c2e7886

Please sign in to comment.