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