nsPNGDecoder.h (4788B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_image_decoders_nsPNGDecoder_h 8 #define mozilla_image_decoders_nsPNGDecoder_h 9 10 #include "Decoder.h" 11 #include "png.h" 12 #include "StreamingLexer.h" 13 #include "SurfacePipe.h" 14 #include "mozilla/gfx/Swizzle.h" 15 16 namespace mozilla { 17 namespace image { 18 class RasterImage; 19 20 class nsPNGDecoder : public Decoder { 21 public: 22 virtual ~nsPNGDecoder(); 23 24 /// @return true if this PNG is a valid ICO resource. 25 bool IsValidICOResource() const override; 26 27 DecoderType GetType() const override { return DecoderType::PNG; } 28 29 protected: 30 nsresult InitInternal() override; 31 nsresult FinishInternal() override; 32 LexerResult DoDecode(SourceBufferIterator& aIterator, 33 IResumable* aOnResume) override; 34 35 Maybe<glean::impl::MemoryDistributionMetric> SpeedMetric() const override; 36 37 private: 38 friend class DecoderFactory; 39 40 // Decoders should only be instantiated via DecoderFactory. 41 explicit nsPNGDecoder(RasterImage* aImage); 42 43 /// The information necessary to create a frame. 44 struct FrameInfo { 45 UnorientedIntRect mFrameRect; 46 bool mIsInterlaced; 47 }; 48 49 nsresult CreateFrame(const FrameInfo& aFrameInfo); 50 void EndImageFrame(); 51 52 uint32_t ReadColorProfile(png_structp png_ptr, png_infop info_ptr, 53 int color_type, bool* sRGBTag); 54 55 bool HasAlphaChannel() const { return mChannels == 2 || mChannels == 4; } 56 57 enum class TransparencyType { eNone, eAlpha, eFrameRect }; 58 59 TransparencyType GetTransparencyType(const UnorientedIntRect& aFrameRect); 60 void PostHasTransparencyIfNeeded(TransparencyType aTransparencyType); 61 62 void PostInvalidationIfNeeded(); 63 64 void WriteRow(uint8_t* aRow); 65 66 // Convenience methods to make interacting with StreamingLexer from inside 67 // a libpng callback easier. 68 void DoTerminate(png_structp aPNGStruct, TerminalState aState); 69 void DoYield(png_structp aPNGStruct); 70 71 enum class State { PNG_DATA, FINISHED_PNG_DATA }; 72 73 LexerTransition<State> ReadPNGData(const char* aData, size_t aLength); 74 LexerTransition<State> FinishedPNGData(); 75 76 StreamingLexer<State> mLexer; 77 78 // The next lexer state transition. We need to store it here because we can't 79 // directly return arbitrary values from libpng callbacks. 80 LexerTransition<State> mNextTransition; 81 82 // We yield to the caller every time we finish decoding a frame. When this 83 // happens, we need to allocate the next frame after returning from the yield. 84 // |mNextFrameInfo| is used to store the information needed to allocate the 85 // next frame. 86 Maybe<FrameInfo> mNextFrameInfo; 87 88 // The length of the last chunk of data passed to ReadPNGData(). We use this 89 // to arrange to arrive back at the correct spot in the data after yielding. 90 size_t mLastChunkLength; 91 92 public: 93 png_structp mPNG; 94 png_infop mInfo; 95 UnorientedIntRect mFrameRect; 96 uint8_t* mCMSLine; 97 uint8_t* interlacebuf; 98 gfx::SurfaceFormat mFormat; 99 100 uint8_t mChannels; 101 uint8_t mPass; 102 bool mFrameIsHidden; 103 bool mDisablePremultipliedAlpha; 104 bool mGotInfoCallback; 105 bool mUsePipeTransform; 106 bool mErrorIsRecoverable; 107 108 struct AnimFrameInfo { 109 AnimFrameInfo(); 110 #ifdef PNG_APNG_SUPPORTED 111 AnimFrameInfo(png_structp aPNG, png_infop aInfo); 112 #endif 113 114 DisposalMethod mDispose; 115 BlendMethod mBlend; 116 int32_t mTimeout; 117 }; 118 119 AnimFrameInfo mAnimInfo; 120 121 SurfacePipe mPipe; /// The SurfacePipe used to write to the output surface. 122 123 // The number of frames we've finished. 124 uint32_t mNumFrames; 125 126 // libpng callbacks 127 // We put these in the class so that they can access protected members. 128 static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr); 129 static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row, 130 png_uint_32 row_num, int pass); 131 #ifdef PNG_APNG_SUPPORTED 132 static void PNGAPI frame_info_callback(png_structp png_ptr, 133 png_uint_32 frame_num); 134 #endif 135 static void PNGAPI end_callback(png_structp png_ptr, png_infop info_ptr); 136 static void PNGAPI error_callback(png_structp png_ptr, 137 png_const_charp error_msg); 138 static void PNGAPI warning_callback(png_structp png_ptr, 139 png_const_charp warning_msg); 140 141 // This is defined in the PNG spec as an invariant. We use it to 142 // do manual validation without libpng. 143 static const uint8_t pngSignatureBytes[]; 144 }; 145 146 } // namespace image 147 } // namespace mozilla 148 149 #endif // mozilla_image_decoders_nsPNGDecoder_h