Bug 1255104 - Use SurfacePipe in nsIconDecoder. r=njn

This commit is contained in:
Seth Fowler 2016-03-10 18:45:29 -08:00
Родитель b47c0eea98
Коммит c987885db6
2 изменённых файлов: 44 добавлений и 54 удалений

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

@ -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 <algorithm>
#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::State>
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<SurfacePipe> 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::State>
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<uint32_t>([&]() -> NextPixel<uint32_t> {
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<const uint32_t*>(aData);
aData += 4;
aLength -= 4;
return AsVariant(pixel);
});
MOZ_ASSERT(result != WriteState::FAILURE);
Maybe<SurfaceInvalidRect> 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<nsIconDecoder::State>

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

@ -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<State> Finish();
StreamingLexer<State> mLexer;
uint8_t mWidth;
uint8_t mHeight;
SurfacePipe mPipe;
uint32_t mBytesPerRow;
uint32_t mBytesTotal;
uint32_t mCurrentRow;
};
} // namespace image