Files
palemoon27/image/decoders/nsWEBPDecoder.cpp
T
roytam1 44d5f1a6a9 import change from rmottola/Arctic-Fox:
- initialize webp with different mode depending on endianness (c47ba6f6e)
- pointer style (09a5f12ee)
- Bug 1139983 - Fail the alloc if the nursery is full in NoGC (a85408eef)
- Bug 1135963. Allow JS_InitializePropertiesFromCompatibleNativeObject to deal with objects that have different prototypes. (ec8d1799b)
- Bug 1066233 - Part 1: Parser suppoert for ES6 ClassExpressions. (04e536bb6)
- Bug 1066233 - Part 2: Emitter support for ES6 ClassExpressions. (7e141d412)
- Bug 1066233 - Part 3: Reflect.parse support for ES6 ClassExpressions. (30595e6df)
- Bug 1066233 - Followup: Address a forgotten review comment. (836b26f59)
- Bug 1066233 - Tests. (5df23d2e6)
- Bug 1143106 - Fix construction of singleton objects during parsing when unboxed objects are in use (1749494c6)
2019-05-21 11:02:01 +08:00

161 lines
4.0 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ImageLogging.h"
#include "nsWEBPDecoder.h"
#include "gfxPlatform.h"
namespace mozilla {
namespace image {
#if defined(PR_LOGGING)
static PRLogModuleInfo *gWEBPLog = PR_NewLogModule("WEBPDecoder");
static PRLogModuleInfo *gWEBPDecoderAccountingLog =
PR_NewLogModule("WEBPDecoderAccounting");
#else
#define gWEBPlog
#define gWEBPDecoderAccountingLog
#endif
nsWEBPDecoder::nsWEBPDecoder(RasterImage* aImage)
: Decoder(aImage)
, mDecoder(nullptr)
, mData(nullptr)
, mPreviousLastLine(0)
{
PR_LOG(gWEBPDecoderAccountingLog, PR_LOG_DEBUG,
("nsWEBPDecoder::nsWEBPDecoder: Creating WEBP decoder %p",
this));
}
nsWEBPDecoder::~nsWEBPDecoder()
{
PR_LOG(gWEBPDecoderAccountingLog, PR_LOG_DEBUG,
("nsWEBPDecoder::~nsWEBPDecoder: Destroying WEBP decoder %p",
this));
// It is safe to pass nullptr to WebPIDelete().
WebPIDelete(mDecoder);
}
void
nsWEBPDecoder::InitInternal()
{
#if MOZ_BIG_ENDIAN
mDecoder = WebPINewRGB(MODE_Argb, nullptr, 0, 0);
#else
mDecoder = WebPINewRGB(MODE_rgbA, nullptr, 0, 0);
#endif
if (!mDecoder) {
PostDecoderError(NS_ERROR_FAILURE);
return;
}
}
void
nsWEBPDecoder::FinishInternal()
{
MOZ_ASSERT(!HasError(), "Shouldn't call FinishInternal after error!");
// We should never make multiple frames
MOZ_ASSERT(GetFrameCount() <= 1, "Multiple WebP frames?");
// Send notifications if appropriate
if (!IsSizeDecode() && (GetFrameCount() == 1)) {
PostFrameStop();
PostDecodeDone();
}
}
void
nsWEBPDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
{
MOZ_ASSERT(!HasError(), "Shouldn't call WriteInternal after error!");
const uint8_t* buf = (const uint8_t*)aBuffer;
VP8StatusCode rv = WebPIAppend(mDecoder, buf, aCount);
if (rv == VP8_STATUS_OUT_OF_MEMORY) {
PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
return;
} else if (rv == VP8_STATUS_INVALID_PARAM ||
rv == VP8_STATUS_BITSTREAM_ERROR) {
PostDataError();
return;
} else if (rv == VP8_STATUS_UNSUPPORTED_FEATURE ||
rv == VP8_STATUS_USER_ABORT) {
PostDecoderError(NS_ERROR_FAILURE);
return;
}
// Catch any remaining erroneous return value.
if (rv != VP8_STATUS_OK && rv != VP8_STATUS_SUSPENDED) {
PostDecoderError(NS_ERROR_FAILURE);
return;
}
int lastLineRead = -1;
int height = 0;
int width = 0;
int stride = 0;
mData = WebPIDecGetRGB(mDecoder, &lastLineRead, &width, &height, &stride);
if (lastLineRead == -1 || !mData)
return;
if (width <= 0 || height <= 0) {
PostDataError();
return;
}
if (!HasSize())
PostSize(width, height);
if (IsSizeDecode())
return;
// The only valid format for WebP decoding for both alpha and non-alpha
// images is BGRA, where Opaque images have an A of 255.
// Assume transparency for all images.
// XXX: This could be compositor-optimized by doing a one-time check for
// all-255 alpha pixels, but that might interfere with progressive
// decoding. Probably not worth it?
PostHasTransparency();
if (!mImageData) {
PostDecoderError(NS_ERROR_FAILURE);
return;
}
// Transfer from mData to mImageData
if (lastLineRead > mPreviousLastLine) {
for (int line = mPreviousLastLine; line < lastLineRead; line++) {
for (int pix = 0; pix < width; pix++) {
// RGBA -> BGRA
uint32_t DataOffset = 4 * (line * width + pix);
mImageData[DataOffset+0] = mData[DataOffset+2];
mImageData[DataOffset+1] = mData[DataOffset+1];
mImageData[DataOffset+2] = mData[DataOffset+0];
mImageData[DataOffset+3] = mData[DataOffset+3];
}
}
// Invalidate
nsIntRect r(0,
mPreviousLastLine,
width,
lastLineRead - mPreviousLastLine + 1);
PostInvalidation(r);
}
mPreviousLastLine = lastLineRead;
return;
}
} // namespace imagelib
} // namespace mozilla