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 "qcms.h" 13 #include "StreamingLexer.h" 14 #include "SurfacePipe.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 GetType()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<Telemetry::HistogramID> SpeedHistogram() 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 gfx::IntRect mFrameRect; 46 bool mIsInterlaced; 47 }; 48 49 nsresult CreateFrame(const FrameInfo& aFrameInfo); 50 void EndImageFrame(); 51 HasAlphaChannel()52 bool HasAlphaChannel() const { return mChannels == 2 || mChannels == 4; } 53 54 enum class TransparencyType { eNone, eAlpha, eFrameRect }; 55 56 TransparencyType GetTransparencyType(const gfx::IntRect& aFrameRect); 57 void PostHasTransparencyIfNeeded(TransparencyType aTransparencyType); 58 59 void PostInvalidationIfNeeded(); 60 61 void WriteRow(uint8_t* aRow); 62 63 // Convenience methods to make interacting with StreamingLexer from inside 64 // a libpng callback easier. 65 void DoTerminate(png_structp aPNGStruct, TerminalState aState); 66 void DoYield(png_structp aPNGStruct); 67 68 enum class State { PNG_DATA, FINISHED_PNG_DATA }; 69 70 LexerTransition<State> ReadPNGData(const char* aData, size_t aLength); 71 LexerTransition<State> FinishedPNGData(); 72 73 StreamingLexer<State> mLexer; 74 75 // The next lexer state transition. We need to store it here because we can't 76 // directly return arbitrary values from libpng callbacks. 77 LexerTransition<State> mNextTransition; 78 79 // We yield to the caller every time we finish decoding a frame. When this 80 // happens, we need to allocate the next frame after returning from the yield. 81 // |mNextFrameInfo| is used to store the information needed to allocate the 82 // next frame. 83 Maybe<FrameInfo> mNextFrameInfo; 84 85 // The length of the last chunk of data passed to ReadPNGData(). We use this 86 // to arrange to arrive back at the correct spot in the data after yielding. 87 size_t mLastChunkLength; 88 89 public: 90 png_structp mPNG; 91 png_infop mInfo; 92 nsIntRect mFrameRect; 93 uint8_t* mCMSLine; 94 uint8_t* interlacebuf; 95 qcms_profile* mInProfile; 96 qcms_transform* mTransform; 97 gfx::SurfaceFormat mFormat; 98 99 // whether CMS or premultiplied alpha are forced off 100 uint32_t mCMSMode; 101 102 uint8_t mChannels; 103 uint8_t mPass; 104 bool mFrameIsHidden; 105 bool mDisablePremultipliedAlpha; 106 107 struct AnimFrameInfo { 108 AnimFrameInfo(); 109 #ifdef PNG_APNG_SUPPORTED 110 AnimFrameInfo(png_structp aPNG, png_infop aInfo); 111 #endif 112 113 DisposalMethod mDispose; 114 BlendMethod mBlend; 115 int32_t mTimeout; 116 }; 117 118 AnimFrameInfo mAnimInfo; 119 120 SurfacePipe mPipe; /// The SurfacePipe used to write to the output surface. 121 122 // The number of frames we've finished. 123 uint32_t mNumFrames; 124 125 // libpng callbacks 126 // We put these in the class so that they can access protected members. 127 static void PNGAPI info_callback(png_structp png_ptr, png_infop info_ptr); 128 static void PNGAPI row_callback(png_structp png_ptr, png_bytep new_row, 129 png_uint_32 row_num, int pass); 130 #ifdef PNG_APNG_SUPPORTED 131 static void PNGAPI frame_info_callback(png_structp png_ptr, 132 png_uint_32 frame_num); 133 #endif 134 static void PNGAPI end_callback(png_structp png_ptr, png_infop info_ptr); 135 static void PNGAPI error_callback(png_structp png_ptr, 136 png_const_charp error_msg); 137 static void PNGAPI warning_callback(png_structp png_ptr, 138 png_const_charp warning_msg); 139 140 // This is defined in the PNG spec as an invariant. We use it to 141 // do manual validation without libpng. 142 static const uint8_t pngSignatureBytes[]; 143 }; 144 145 } // namespace image 146 } // namespace mozilla 147 148 #endif // mozilla_image_decoders_nsPNGDecoder_h 149