michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsPNGDecoder_h__ michael@0: #define nsPNGDecoder_h__ michael@0: michael@0: #include "Decoder.h" michael@0: michael@0: #include "gfxTypes.h" michael@0: michael@0: #include "nsCOMPtr.h" michael@0: michael@0: #include "png.h" michael@0: michael@0: #include "qcms.h" michael@0: michael@0: namespace mozilla { michael@0: namespace image { michael@0: class RasterImage; michael@0: michael@0: class nsPNGDecoder : public Decoder michael@0: { michael@0: public: michael@0: nsPNGDecoder(RasterImage &aImage); michael@0: virtual ~nsPNGDecoder(); michael@0: michael@0: virtual void InitInternal(); michael@0: virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy); michael@0: virtual Telemetry::ID SpeedHistogram(); michael@0: michael@0: void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset, michael@0: int32_t width, int32_t height, michael@0: gfxImageFormat format); michael@0: void EndImageFrame(); michael@0: michael@0: // Check if PNG is valid ICO (32bpp RGBA) michael@0: // http://blogs.msdn.com/b/oldnewthing/archive/2010/10/22/10079192.aspx michael@0: bool IsValidICO() const michael@0: { michael@0: // If there are errors in the call to png_get_IHDR, the error_callback in michael@0: // nsPNGDecoder.cpp is called. In this error callback we do a longjmp, so michael@0: // we need to save the jump buffer here. Oterwise we'll end up without a michael@0: // proper callstack. michael@0: if (setjmp(png_jmpbuf(mPNG))) { michael@0: // We got here from a longjmp call indirectly from png_get_IHDR michael@0: return false; michael@0: } michael@0: michael@0: png_uint_32 michael@0: png_width, // Unused michael@0: png_height; // Unused michael@0: michael@0: int png_bit_depth, michael@0: png_color_type; michael@0: michael@0: if (png_get_IHDR(mPNG, mInfo, &png_width, &png_height, &png_bit_depth, michael@0: &png_color_type, nullptr, nullptr, nullptr)) { michael@0: michael@0: return ((png_color_type == PNG_COLOR_TYPE_RGB_ALPHA || michael@0: png_color_type == PNG_COLOR_TYPE_RGB) && michael@0: png_bit_depth == 8); michael@0: } else { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: public: michael@0: png_structp mPNG; michael@0: png_infop mInfo; michael@0: nsIntRect mFrameRect; michael@0: uint8_t *mCMSLine; michael@0: uint8_t *interlacebuf; michael@0: qcms_profile *mInProfile; michael@0: qcms_transform *mTransform; michael@0: michael@0: gfxImageFormat format; michael@0: michael@0: // For size decodes michael@0: uint8_t mSizeBytes[8]; // Space for width and height, both 4 bytes michael@0: uint32_t mHeaderBytesRead; michael@0: michael@0: // whether CMS or premultiplied alpha are forced off michael@0: uint32_t mCMSMode; michael@0: michael@0: uint8_t mChannels; michael@0: bool mFrameHasNoAlpha; michael@0: bool mFrameIsHidden; michael@0: bool mDisablePremultipliedAlpha; michael@0: michael@0: struct AnimFrameInfo michael@0: { michael@0: AnimFrameInfo(); michael@0: #ifdef PNG_APNG_SUPPORTED michael@0: AnimFrameInfo(png_structp aPNG, png_infop aInfo); michael@0: #endif michael@0: michael@0: FrameBlender::FrameDisposalMethod mDispose; michael@0: FrameBlender::FrameBlendMethod mBlend; michael@0: int32_t mTimeout; michael@0: }; michael@0: michael@0: AnimFrameInfo mAnimInfo; michael@0: michael@0: // The number of frames we've finished. michael@0: uint32_t mNumFrames; michael@0: michael@0: /* michael@0: * libpng callbacks michael@0: * michael@0: * We put these in the class so that they can access protected members. michael@0: */ michael@0: static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr); michael@0: static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row, michael@0: png_uint_32 row_num, int pass); michael@0: #ifdef PNG_APNG_SUPPORTED michael@0: static void PNGAPI frame_info_callback(png_structp png_ptr, michael@0: png_uint_32 frame_num); michael@0: #endif michael@0: static void PNGAPI end_callback(png_structp png_ptr, png_infop info_ptr); michael@0: static void PNGAPI error_callback(png_structp png_ptr, michael@0: png_const_charp error_msg); michael@0: static void PNGAPI warning_callback(png_structp png_ptr, michael@0: png_const_charp warning_msg); michael@0: michael@0: // This is defined in the PNG spec as an invariant. We use it to michael@0: // do manual validation without libpng. michael@0: static const uint8_t pngSignatureBytes[]; michael@0: }; michael@0: michael@0: } // namespace image michael@0: } // namespace mozilla michael@0: michael@0: #endif // nsPNGDecoder_h__