mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 1191090 - Use the normal PNG decoder for PNG metadata decodes. r=tn
--HG-- extra : rebase_source : c0d1f9f8e376cbe4ebf1921d3e1edf85234e8f7b
This commit is contained in:
parent
3069169b59
commit
c0f83249c8
@ -47,11 +47,6 @@ GetPNGDecoderAccountingLog()
|
||||
# define MOZ_PNG_MAX_DIMENSION 32767
|
||||
#endif
|
||||
|
||||
// For metadata decodes.
|
||||
#define WIDTH_OFFSET 16
|
||||
#define HEIGHT_OFFSET (WIDTH_OFFSET + 4)
|
||||
#define BYTES_NEEDED_FOR_DIMENSIONS (HEIGHT_OFFSET + 4)
|
||||
|
||||
nsPNGDecoder::AnimFrameInfo::AnimFrameInfo()
|
||||
: mDispose(DisposalMethod::KEEP)
|
||||
, mBlend(BlendMethod::OVER)
|
||||
@ -148,6 +143,7 @@ nsPNGDecoder::CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
|
||||
gfx::SurfaceFormat aFormat)
|
||||
{
|
||||
MOZ_ASSERT(HasSize());
|
||||
MOZ_ASSERT(!IsMetadataDecode());
|
||||
|
||||
if (aFormat == gfx::SurfaceFormat::B8G8R8A8) {
|
||||
PostHasTransparency();
|
||||
@ -226,11 +222,6 @@ nsPNGDecoder::EndImageFrame()
|
||||
void
|
||||
nsPNGDecoder::InitInternal()
|
||||
{
|
||||
// For metadata decodes, we don't need to initialize the PNG decoder.
|
||||
if (IsMetadataDecode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCMSMode = gfxPlatform::GetCMSMode();
|
||||
if (GetDecodeFlags() & imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION) {
|
||||
mCMSMode = eCMSMode_Off;
|
||||
@ -257,8 +248,6 @@ nsPNGDecoder::InitInternal()
|
||||
122, 84, 88, 116, '\0'}; // zTXt
|
||||
#endif
|
||||
|
||||
// For full decodes, do png init stuff
|
||||
|
||||
// Initialize the container's source image header
|
||||
// Always decode to 24 bit pixdepth
|
||||
|
||||
@ -321,73 +310,24 @@ nsPNGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
|
||||
{
|
||||
MOZ_ASSERT(!HasError(), "Shouldn't call WriteInternal after error!");
|
||||
|
||||
// If we only want width/height, we don't need to go through libpng.
|
||||
if (IsMetadataDecode()) {
|
||||
// libpng uses setjmp/longjmp for error handling. Set it up.
|
||||
if (setjmp(png_jmpbuf(mPNG))) {
|
||||
|
||||
// Are we done?
|
||||
if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) {
|
||||
return;
|
||||
// We exited early. If mSuccessfulEarlyFinish isn't true, then we
|
||||
// encountered an error. We might not really know what caused it, but it
|
||||
// makes more sense to blame the data.
|
||||
if (!mSuccessfulEarlyFinish && !HasError()) {
|
||||
PostDataError();
|
||||
}
|
||||
|
||||
// Scan the header for the width and height bytes
|
||||
uint32_t pos = 0;
|
||||
const uint8_t* bptr = (uint8_t*)aBuffer;
|
||||
|
||||
while (pos < aCount && mHeaderBytesRead < BYTES_NEEDED_FOR_DIMENSIONS) {
|
||||
// Verify the signature bytes
|
||||
if (mHeaderBytesRead < sizeof(pngSignatureBytes)) {
|
||||
if (bptr[pos] != nsPNGDecoder::pngSignatureBytes[mHeaderBytesRead]) {
|
||||
PostDataError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get width and height bytes into the buffer
|
||||
if ((mHeaderBytesRead >= WIDTH_OFFSET) &&
|
||||
(mHeaderBytesRead < BYTES_NEEDED_FOR_DIMENSIONS)) {
|
||||
mSizeBytes[mHeaderBytesRead - WIDTH_OFFSET] = bptr[pos];
|
||||
}
|
||||
pos ++;
|
||||
mHeaderBytesRead ++;
|
||||
}
|
||||
|
||||
// If we're done now, verify the data and set up the container
|
||||
if (mHeaderBytesRead == BYTES_NEEDED_FOR_DIMENSIONS) {
|
||||
|
||||
// Grab the width and height, accounting for endianness (thanks libpng!)
|
||||
uint32_t width = png_get_uint_32(mSizeBytes);
|
||||
uint32_t height = png_get_uint_32(mSizeBytes + 4);
|
||||
|
||||
// Too big?
|
||||
if ((width > MOZ_PNG_MAX_DIMENSION) || (height > MOZ_PNG_MAX_DIMENSION)) {
|
||||
PostDataError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Post our size to the superclass
|
||||
PostSize(width, height);
|
||||
}
|
||||
|
||||
// Otherwise, we're doing a standard decode
|
||||
} else {
|
||||
|
||||
// libpng uses setjmp/longjmp for error handling - set the buffer
|
||||
if (setjmp(png_jmpbuf(mPNG))) {
|
||||
|
||||
// We might not really know what caused the error, but it makes more
|
||||
// sense to blame the data.
|
||||
if (!mSuccessfulEarlyFinish && !HasError()) {
|
||||
PostDataError();
|
||||
}
|
||||
|
||||
png_destroy_read_struct(&mPNG, &mInfo, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass the data off to libpng
|
||||
png_process_data(mPNG, mInfo, (unsigned char*)aBuffer, aCount);
|
||||
|
||||
png_destroy_read_struct(&mPNG, &mInfo, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass the data off to libpng.
|
||||
png_process_data(mPNG, mInfo,
|
||||
reinterpret_cast<unsigned char*>(const_cast<char*>((aBuffer))),
|
||||
aCount);
|
||||
}
|
||||
|
||||
// Sets up gamma pre-correction in libpng before our callback gets called.
|
||||
@ -546,6 +486,12 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
png_longjmp(decoder->mPNG, 1);
|
||||
}
|
||||
|
||||
if (decoder->IsMetadataDecode()) {
|
||||
// We have the size, so we don't need to decode any further.
|
||||
decoder->mSuccessfulEarlyFinish = true;
|
||||
png_longjmp(decoder->mPNG, 1);
|
||||
}
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_expand(png_ptr);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user