diff --git a/image/decoders/nsIconDecoder.cpp b/image/decoders/nsIconDecoder.cpp index a574124b79f1..84c1b5c0ed85 100644 --- a/image/decoders/nsIconDecoder.cpp +++ b/image/decoders/nsIconDecoder.cpp @@ -5,17 +5,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIconDecoder.h" -#include "nsIInputStream.h" -#include "nspr.h" -#include "nsRect.h" -#include "nsError.h" #include "RasterImage.h" -#include +#include "SurfacePipeFactory.h" using namespace mozilla::gfx; -using std::min; - namespace mozilla { namespace image { @@ -24,10 +18,7 @@ static const uint32_t ICON_HEADER_SIZE = 2; nsIconDecoder::nsIconDecoder(RasterImage* aImage) : Decoder(aImage) , mLexer(Transition::To(State::HEADER, ICON_HEADER_SIZE)) - , mWidth() // set by ReadHeader() - , mHeight() // set by ReadHeader() , mBytesPerRow() // set by ReadHeader() - , mCurrentRow(0) { // Nothing to do } @@ -66,14 +57,14 @@ LexerTransition nsIconDecoder::ReadHeader(const char* aData) { // Grab the width and height. - mWidth = uint8_t(aData[0]); - mHeight = uint8_t(aData[1]); + uint8_t width = uint8_t(aData[0]); + uint8_t height = uint8_t(aData[1]); // The input is 32bpp, so we expect 4 bytes of data per pixel. - mBytesPerRow = mWidth * 4; + mBytesPerRow = width * 4; // Post our size to the superclass. - PostSize(mWidth, mHeight); + PostSize(width, height); // Icons have alpha. PostHasTransparency(); @@ -85,21 +76,19 @@ nsIconDecoder::ReadHeader(const char* aData) MOZ_ASSERT(!mImageData, "Already have a buffer allocated?"); IntSize targetSize = mDownscaler ? mDownscaler->TargetSize() : GetSize(); - nsresult rv = AllocateFrame(0, targetSize, - IntRect(IntPoint(), targetSize), - gfx::SurfaceFormat::B8G8R8A8); - if (NS_FAILED(rv)) { + IntRect targetFrameRect(IntPoint(0, 0), targetSize); + + Maybe pipe = + SurfacePipeFactory::CreateSurfacePipe(this, 0, GetSize(), targetSize, + targetFrameRect, SurfaceFormat::B8G8R8A8, + SurfacePipeFlags()); + if (!pipe) { return Transition::TerminateFailure(); } - MOZ_ASSERT(mImageData, "Should have a buffer now"); - if (mDownscaler) { - nsresult rv = mDownscaler->BeginFrame(GetSize(), Nothing(), - mImageData, /* aHasAlpha = */ true); - if (NS_FAILED(rv)) { - return Transition::TerminateFailure(); - } - } + mPipe = Move(*pipe); + + MOZ_ASSERT(mImageData, "Should have a buffer now"); return Transition::To(State::ROW_OF_PIXELS, mBytesPerRow); } @@ -107,25 +96,31 @@ nsIconDecoder::ReadHeader(const char* aData) LexerTransition nsIconDecoder::ReadRowOfPixels(const char* aData, size_t aLength) { - if (mDownscaler) { - memcpy(mDownscaler->RowBuffer(), aData, mBytesPerRow); - mDownscaler->CommitRow(); + MOZ_ASSERT(aLength % 4 == 0, "Rows should contain a multiple of four bytes"); - if (mDownscaler->HasInvalidation()) { - DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect(); - PostInvalidation(invalidRect.mOriginalSizeRect, - Some(invalidRect.mTargetSizeRect)); + auto result = mPipe.WritePixels([&]() -> NextPixel { + if (aLength == 0) { + return AsVariant(WriteState::NEED_MORE_DATA); // Done with this row. } - } else { - memcpy(mImageData + mCurrentRow * mBytesPerRow, aData, mBytesPerRow); - PostInvalidation(IntRect(0, mCurrentRow, mWidth, 1)); + uint32_t pixel = *reinterpret_cast(aData); + aData += 4; + aLength -= 4; + + return AsVariant(pixel); + }); + + MOZ_ASSERT(result != WriteState::FAILURE); + + Maybe invalidRect = mPipe.TakeInvalidRect(); + if (invalidRect) { + PostInvalidation(invalidRect->mInputSpaceRect, + Some(invalidRect->mOutputSpaceRect)); } - mCurrentRow++; - return (mCurrentRow < mHeight) - ? Transition::To(State::ROW_OF_PIXELS, mBytesPerRow) - : Transition::To(State::FINISH, 0); + return result == WriteState::FINISHED + ? Transition::To(State::FINISH, 0) + : Transition::To(State::ROW_OF_PIXELS, mBytesPerRow); } LexerTransition diff --git a/image/decoders/nsIconDecoder.h b/image/decoders/nsIconDecoder.h index b703837cd59a..e01ac593807e 100644 --- a/image/decoders/nsIconDecoder.h +++ b/image/decoders/nsIconDecoder.h @@ -9,10 +9,11 @@ #include "Decoder.h" #include "StreamingLexer.h" -#include "nsCOMPtr.h" +#include "SurfacePipe.h" namespace mozilla { namespace image { + class RasterImage; //////////////////////////////////////////////////////////////////////////////// @@ -21,16 +22,13 @@ class RasterImage; // and this decoder takes that format and converts it into 24-bit RGB with // alpha channel support. It was modeled a bit off the PPM decoder. // -// Assumptions about the decoder: -// (1) We receive ALL of the data from the icon channel in one OnDataAvailable -// call. We don't support multiple ODA calls yet. -// (2) the format of the incoming data is as follows: -// The first two bytes contain the width and the height of the icon. -// The remaining bytes contain the icon data, 4 bytes per pixel, in -// ARGB order (platform endianness, A in highest bits, B in lowest -// bits), row-primary, top-to-bottom, left-to-right, with -// premultiplied alpha. +// The format of the incoming data is as follows: // +// The first two bytes contain the width and the height of the icon. +// The remaining bytes contain the icon data, 4 bytes per pixel, in +// ARGB order (platform endianness, A in highest bits, B in lowest +// bits), row-primary, top-to-bottom, left-to-right, with +// premultiplied alpha. // //////////////////////////////////////////////////////////////////////////////// @@ -58,11 +56,8 @@ private: LexerTransition Finish(); StreamingLexer mLexer; - uint8_t mWidth; - uint8_t mHeight; + SurfacePipe mPipe; uint32_t mBytesPerRow; - uint32_t mBytesTotal; - uint32_t mCurrentRow; }; } // namespace image