1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2001
21 * the Initial Developer. All Rights Reserved.
24 * Stuart Parmenter <pavlov@netscape.com>
25 * Chris Saari <saari@netscape.com>
26 * Federico Mena-Quintero <federico@novell.com>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
43 * This file declares the imgContainer class, which
44 * handles static and animated image containers.
46 * @author Stuart Parmenter <pavlov@netscape.com>
47 * @author Chris Saari <saari@netscape.com>
48 * @author Arron Mogge <paper@animecity.nu>
49 * @author Andrew Smith <asmith15@learn.senecac.on.ca>
52 #ifndef __imgContainer_h__
53 #define __imgContainer_h__
55 #include "nsCOMArray.h"
57 #include "imgIContainer.h"
58 #include "gfxIImageFrame.h"
59 #include "nsIProperties.h"
61 #include "nsWeakReference.h"
64 #define NS_IMGCONTAINER_CID \
65 { /* 27f0682c-ff64-4dd2-ae7a-668e59f2fd38 */ \
69 {0xae, 0x7a, 0x66, 0x8e, 0x59, 0xf2, 0xfd, 0x38} \
73 * Handles static and animated image containers.
76 * @par A Quick Walk Through
77 * The decoder initializes this class and calls AppendFrame() to add a frame.
78 * Once imgContainer detects more than one frame, it starts the animation
79 * with StartAnimation().
82 * StartAnimation() checks if animating is allowed, and creates a timer. The
83 * timer calls Notify when the specified frame delay time is up.
86 * Notify() moves on to the next frame, sets up the new timer delay, destroys
87 * the old frame, and forces a redraw via observer->FrameChanged().
90 * Each frame can have a different method of removing itself. These are
91 * listed as imgIContainer::cDispose... constants. Notify() calls
92 * DoComposite() to handle any special frame destruction.
95 * The basic path through DoComposite() is:
96 * 1) Calculate Area that needs updating, which is at least the area of
98 * 2) Dispose of previous frame.
99 * 3) Draw new image onto compositingFrame.
100 * See comments in DoComposite() for more information and optimizations.
103 * The rest of the imgContainer specific functions are used by DoComposite to
104 * destroy the old frame and build the new one.
107 * <li> "Mask", "Alpha", and "Alpha Level" are interchangable phrases in
108 * respects to imgContainer.
111 * <li> GIFs never have more than a 1 bit alpha.
112 * <li> APNGs may have a full alpha channel.
115 * <li> Background color specified in GIF is ignored by web browsers.
118 * <li> If Frame 3 wants to dispose by restoring previous, what it wants is to
119 * restore the composition up to and including Frame 2, as well as Frame 2s
120 * disposal. So, in the middle of DoComposite when composing Frame 3, right
121 * after destroying Frame 2's area, we copy compositingFrame to
122 * prevCompositingFrame. When DoComposite gets called to do Frame 4, we
123 * copy prevCompositingFrame back, and then draw Frame 4 on top.
126 * The mAnim structure has members only needed for animated images, so
127 * it's not allocated until the second frame is added.
130 * mAnimationMode, mLoopCount and mObserver are not in the mAnim structure
131 * because the first two have public setters and the observer we only get
134 class imgContainer
: public imgIContainer
,
135 public nsITimerCallback
,
140 NS_DECL_IMGICONTAINER
141 NS_DECL_NSITIMERCALLBACK
142 NS_DECL_NSIPROPERTIES
145 virtual ~imgContainer();
150 //! Area of the first frame that needs to be redrawn on subsequent loops.
151 nsIntRect firstFrameRefreshArea
;
152 // Note this doesn't hold a proper value until frame 2 finished decoding.
153 PRInt32 currentDecodingFrameIndex
; // 0 to numFrames-1
154 PRInt32 currentAnimationFrameIndex
; // 0 to numFrames-1
155 //! Track the last composited frame for Optimizations (See DoComposite code)
156 PRInt32 lastCompositedFrameIndex
;
157 //! Whether we can assume there will be no more frames
158 //! (and thus loop the animation)
160 //! Are we currently animating the image?
162 /** For managing blending of frames
164 * Some animations will use the compositingFrame to composite images
165 * and just hand this back to the caller when it is time to draw the frame.
166 * NOTE: When clearing compositingFrame, remember to set
167 * lastCompositedFrameIndex to -1. Code assume that if
168 * lastCompositedFrameIndex >= 0 then compositingFrame exists.
170 nsCOMPtr
<gfxIImageFrame
> compositingFrame
;
171 /** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS
173 * The Previous Frame (all frames composited up to the current) needs to be
174 * stored in cases where the image specifies it wants the last frame back
175 * when it's done with the current frame.
177 nsCOMPtr
<gfxIImageFrame
> compositingPrevFrame
;
178 //! Timer to animate multiframed images
179 nsCOMPtr
<nsITimer
> timer
;
182 firstFrameRefreshArea(),
183 currentDecodingFrameIndex(0),
184 currentAnimationFrameIndex(0),
185 lastCompositedFrameIndex(-1),
186 doneDecoding(PR_FALSE
),
198 gfxIImageFrame
* GetCurrentFrameNoRef();
200 inline Anim
* ensureAnimExists() {
206 /** Function for doing the frame compositing of animations
208 * @param aFrameToUse Set by DoComposite
209 * (aNextFrame, compositingFrame, or compositingPrevFrame)
210 * @param aDirtyRect Area that the display will need to update
211 * @param aPrevFrame Last Frame seen/processed
212 * @param aNextFrame Frame we need to incorperate/display
213 * @param aNextFrameIndex Position of aNextFrame in mFrames list
215 nsresult
DoComposite(gfxIImageFrame
** aFrameToUse
, nsIntRect
* aDirtyRect
,
216 gfxIImageFrame
* aPrevFrame
,
217 gfxIImageFrame
* aNextFrame
,
218 PRInt32 aNextFrameIndex
);
221 * Combine aOverlayFrame's mask into aCompositingFrame's mask.
223 * This takes the mask information from the passed in aOverlayFrame and
224 * inserts that information into the aCompositingFrame's mask at the proper
225 * offsets. It does *not* rebuild the entire mask.
227 * @param aCompositingFrame Target frame
228 * @param aOverlayFrame This frame's mask is being copied
230 void BuildCompositeMask(gfxIImageFrame
* aCompositingFrame
,
231 gfxIImageFrame
* aOverlayFrame
);
233 /** Sets an area of the frame's mask.
235 * @param aFrame Target Frame
236 * @param aVisible Turn on (PR_TRUE) or off (PR_FALSE) visibility
238 * @note Invisible area of frame's image will need to be set to 0
240 void SetMaskVisibility(gfxIImageFrame
*aFrame
, PRBool aVisible
);
242 void SetMaskVisibility(gfxIImageFrame
*aFrame
,
243 PRInt32 aX
, PRInt32 aY
,
244 PRInt32 aWidth
, PRInt32 aHeight
,
247 void SetMaskVisibility(gfxIImageFrame
*aFrame
,
248 nsIntRect
&aRect
, PRBool aVisible
) {
249 SetMaskVisibility(aFrame
, aRect
.x
, aRect
.y
,
250 aRect
.width
, aRect
.height
, aVisible
);
253 /** Clears an area of <aFrame> with transparent black.
255 * @param aFrame Target Frame
257 * @note Does also clears the transparancy mask
259 static void ClearFrame(gfxIImageFrame
* aFrame
);
262 static void ClearFrame(gfxIImageFrame
* aFrame
, nsIntRect
&aRect
);
264 //! Copy one gfxIImageFrame's image and mask into another
265 static PRBool
CopyFrameImage(gfxIImageFrame
*aSrcFrame
,
266 gfxIImageFrame
*aDstFrame
);
268 /** Draws one gfxIImageFrame's image to into another,
269 * at the position specified by aRect
271 * @param aSrcFrame Frame providing the source image
272 * @param aDstFrame Frame where the image is drawn into
273 * @param aRect The position and size to draw the image
275 static nsresult
DrawFrameTo(gfxIImageFrame
*aSrcFrame
,
276 gfxIImageFrame
*aDstFrame
,
281 //! All the <gfxIImageFrame>s of the PNG
282 // *** IMPORTANT: if you use mFrames in a method, call RestoreDiscardedData() first to ensure
283 // that the frames actually exist (they may have been discarded to save memory).
284 nsCOMArray
<gfxIImageFrame
> mFrames
;
285 int mNumFrames
; /* stored separately from mFrames.Count() to support discarded images */
287 nsCOMPtr
<nsIProperties
> mProperties
;
289 // *** IMPORTANT: if you use mAnim in a method, call RestoreDiscardedData() first to ensure
290 // that the frames actually exist (they may have been discarded to save memory).
291 imgContainer::Anim
* mAnim
;
293 //! See imgIContainer for mode constants
294 PRUint16 mAnimationMode
;
296 //! # loops remaining before animation stops (-1 no stop)
299 //! imgIContainerObserver
304 nsCString mDiscardableMimeType
;
306 nsTArray
<char> mRestoreData
;
307 PRBool mRestoreDataDone
;
308 nsCOMPtr
<nsITimer
> mDiscardTimer
;
310 nsresult
ResetDiscardTimer (void);
311 nsresult
RestoreDiscardedData (void);
312 nsresult
ReloadImages (void);
313 static void sDiscardTimerCallback (nsITimer
*aTimer
, void *aClosure
);
316 #endif /* __imgContainer_h__ */