/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/anidecod.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/common/anidecod.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 4 months ago) by william
File size: 9858 byte(s)
committing r3113 initial commit again...
1 william 31 /////////////////////////////////////////////////////////////////////////////
2     // Name: src/common/anidecod.cpp
3     // Purpose: wxANIDecoder, ANI reader for wxImage and wxAnimation
4     // Author: Francesco Montorsi
5     // RCS-ID: $Id: anidecod.cpp 43898 2006-12-10 14:18:37Z VZ $
6     // Copyright: (c) Francesco Montorsi
7     // Licence: wxWindows licence
8     /////////////////////////////////////////////////////////////////////////////
9    
10     // For compilers that support precompilation, includes "wx.h".
11     #include "wx/wxprec.h"
12    
13     #ifdef __BORLANDC__
14     #pragma hdrstop
15     #endif
16    
17     #if wxUSE_STREAMS && wxUSE_ICO_CUR
18    
19     #include "wx/anidecod.h"
20    
21     #ifndef WX_PRECOMP
22     #include "wx/palette.h"
23     #endif
24    
25     #include <stdlib.h>
26     #include <string.h>
27    
28     // static
29     wxCURHandler wxANIDecoder::sm_handler;
30    
31     //---------------------------------------------------------------------------
32     // wxANIFrameInfo
33     //---------------------------------------------------------------------------
34    
35     class wxANIFrameInfo
36     {
37     public:
38     wxANIFrameInfo(unsigned int delay = 0, int idx = -1)
39     { m_delay=delay; m_imageIndex=idx; }
40    
41     unsigned int m_delay;
42     int m_imageIndex;
43     };
44    
45     #include "wx/arrimpl.cpp" // this is a magic incantation which must be done!
46     WX_DEFINE_OBJARRAY(wxImageArray)
47    
48     #include "wx/arrimpl.cpp" // this is a magic incantation which must be done!
49     WX_DEFINE_OBJARRAY(wxANIFrameInfoArray)
50    
51    
52     //---------------------------------------------------------------------------
53     // wxANIDecoder
54     //---------------------------------------------------------------------------
55    
56     wxANIDecoder::wxANIDecoder()
57     {
58     }
59    
60     wxANIDecoder::~wxANIDecoder()
61     {
62     }
63    
64     bool wxANIDecoder::ConvertToImage(unsigned int frame, wxImage *image) const
65     {
66     unsigned int idx = m_info[frame].m_imageIndex;
67     *image = m_images[idx]; // copy
68     return image->IsOk();
69     }
70    
71    
72     //---------------------------------------------------------------------------
73     // Data accessors
74     //---------------------------------------------------------------------------
75    
76     wxSize wxANIDecoder::GetFrameSize(unsigned int WXUNUSED(frame)) const
77     {
78     // all frames are of the same size...
79     return m_szAnimation;
80     }
81    
82     wxPoint wxANIDecoder::GetFramePosition(unsigned int WXUNUSED(frame)) const
83     {
84     // all frames are of the same size...
85     return wxPoint(0,0);
86     }
87    
88     wxAnimationDisposal wxANIDecoder::GetDisposalMethod(unsigned int WXUNUSED(frame)) const
89     {
90     // this disposal is implicit for all frames inside an ANI file
91     return wxANIM_TOBACKGROUND;
92     }
93    
94     long wxANIDecoder::GetDelay(unsigned int frame) const
95     {
96     return m_info[frame].m_delay;
97     }
98    
99     wxColour wxANIDecoder::GetTransparentColour(unsigned int frame) const
100     {
101     unsigned int idx = m_info[frame].m_imageIndex;
102    
103     if (!m_images[idx].HasMask())
104     return wxNullColour;
105    
106     return wxColour(m_images[idx].GetMaskRed(),
107     m_images[idx].GetMaskGreen(),
108     m_images[idx].GetMaskBlue());
109     }
110    
111    
112     //---------------------------------------------------------------------------
113     // ANI reading and decoding
114     //---------------------------------------------------------------------------
115    
116     bool wxANIDecoder::CanRead(wxInputStream& stream) const
117     {
118     wxInt32 FCC1, FCC2;
119     wxUint32 datalen ;
120    
121     wxInt32 riff32;
122     memcpy( &riff32, "RIFF", 4 );
123     wxInt32 list32;
124     memcpy( &list32, "LIST", 4 );
125     wxInt32 ico32;
126     memcpy( &ico32, "icon", 4 );
127     wxInt32 anih32;
128     memcpy( &anih32, "anih", 4 );
129    
130     stream.SeekI(0);
131     if ( !stream.Read(&FCC1, 4) )
132     return false;
133    
134     if ( FCC1 != riff32 )
135     return false;
136    
137     // we have a riff file:
138     while ( stream.IsOk() )
139     {
140     if ( FCC1 == anih32 )
141     return true; // found the ANIH chunk - this should be an ANI file
142    
143     // we always have a data size:
144     stream.Read(&datalen, 4);
145     datalen = wxINT32_SWAP_ON_BE(datalen) ;
146    
147     // data should be padded to make even number of bytes
148     if (datalen % 2 == 1) datalen ++ ;
149    
150     // now either data or a FCC:
151     if ( (FCC1 == riff32) || (FCC1 == list32) )
152     {
153     stream.Read(&FCC2, 4);
154     }
155     else
156     {
157     stream.SeekI(stream.TellI() + datalen);
158     }
159    
160     // try to read next data chunk:
161     if ( !stream.Read(&FCC1, 4) )
162     {
163     // reading failed -- either EOF or IO error, bail out anyhow
164     return false;
165     }
166     }
167    
168     return false;
169     }
170    
171     // the "anih" RIFF chunk
172     struct wxANIHeader
173     {
174     wxInt32 cbSizeOf; // Num bytes in AniHeader (36 bytes)
175     wxInt32 cFrames; // Number of unique Icons in this cursor
176     wxInt32 cSteps; // Number of Blits before the animation cycles
177     wxInt32 cx; // width of the frames
178     wxInt32 cy; // height of the frames
179     wxInt32 cBitCount; // bit depth
180     wxInt32 cPlanes; // 1
181     wxInt32 JifRate; // Default Jiffies (1/60th of a second) if rate chunk not present.
182     wxInt32 flags; // Animation Flag (see AF_ constants)
183    
184     // ANI files are always little endian so we need to swap bytes on big
185     // endian architectures
186     #ifdef WORDS_BIGENDIAN
187     void AdjustEndianness()
188     {
189     // this works because all our fields are wxInt32 and they must be
190     // packed without holes between them (if they're not, they wouldn't map
191     // to the file header!)
192     wxInt32 * const start = (wxInt32 *)this;
193     wxInt32 * const end = start + sizeof(wxANIHeader)/sizeof(wxInt32);
194     for ( wxInt32 *p = start; p != end; p++ )
195     {
196     *p = wxINT32_SWAP_ALWAYS(*p);
197     }
198     }
199     #else
200     void AdjustEndianness() { }
201     #endif
202     };
203    
204     bool wxANIDecoder::Load( wxInputStream& stream )
205     {
206     wxInt32 FCC1, FCC2;
207     wxUint32 datalen;
208     unsigned int globaldelay=0;
209    
210     wxInt32 riff32;
211     memcpy( &riff32, "RIFF", 4 );
212     wxInt32 list32;
213     memcpy( &list32, "LIST", 4 );
214     wxInt32 ico32;
215     memcpy( &ico32, "icon", 4 );
216     wxInt32 anih32;
217     memcpy( &anih32, "anih", 4 );
218     wxInt32 rate32;
219     memcpy( &rate32, "rate", 4 );
220     wxInt32 seq32;
221     memcpy( &seq32, "seq ", 4 );
222    
223     stream.SeekI(0);
224     stream.Read(&FCC1, 4);
225     if ( FCC1 != riff32 )
226     return false;
227    
228     m_nFrames = 0;
229     m_szAnimation = wxDefaultSize;
230    
231     m_images.Clear();
232     m_info.Clear();
233    
234     // we have a riff file:
235     while ( stream.IsOk() )
236     {
237     // we always have a data size:
238     stream.Read(&datalen, 4);
239     datalen = wxINT32_SWAP_ON_BE(datalen);
240    
241     //data should be padded to make even number of bytes
242     if (datalen % 2 == 1) datalen++;
243    
244     // now either data or a FCC:
245     if ( (FCC1 == riff32) || (FCC1 == list32) )
246     {
247     stream.Read(&FCC2, 4);
248     }
249     else if ( FCC1 == anih32 )
250     {
251     if ( datalen != sizeof(wxANIHeader) )
252     return false;
253    
254     if (m_nFrames > 0)
255     return false; // already parsed an ani header?
256    
257     struct wxANIHeader header;
258     stream.Read(&header, sizeof(wxANIHeader));
259     header.AdjustEndianness();
260    
261     // we should have a global frame size
262     m_szAnimation = wxSize(header.cx, header.cy);
263    
264     // save interesting info from the header
265     m_nFrames = header.cSteps; // NB: not cFrames!!
266     if ( m_nFrames == 0 )
267     return false;
268    
269     globaldelay = header.JifRate * 1000 / 60;
270    
271     m_images.Alloc(header.cFrames);
272     m_info.Add(wxANIFrameInfo(), m_nFrames);
273     }
274     else if ( FCC1 == rate32 )
275     {
276     // did we already process the anih32 chunk?
277     if (m_nFrames == 0)
278     return false; // rate chunks should always be placed after anih chunk
279    
280     wxASSERT(m_info.GetCount() == m_nFrames);
281     for (unsigned int i=0; i<m_nFrames; i++)
282     {
283     stream.Read(&FCC2, 4);
284     m_info[i].m_delay = wxINT32_SWAP_ON_BE(FCC2) * 1000 / 60;
285     }
286     }
287     else if ( FCC1 == seq32 )
288     {
289     // did we already process the anih32 chunk?
290     if (m_nFrames == 0)
291     return false; // seq chunks should always be placed after anih chunk
292    
293     wxASSERT(m_info.GetCount() == m_nFrames);
294     for (unsigned int i=0; i<m_nFrames; i++)
295     {
296     stream.Read(&FCC2, 4);
297     m_info[i].m_imageIndex = wxINT32_SWAP_ON_BE(FCC2);
298     }
299     }
300     else if ( FCC1 == ico32 )
301     {
302     // use DoLoadFile() and not LoadFile()!
303     wxImage image;
304     if (!sm_handler.DoLoadFile(&image, stream, false /* verbose */, -1))
305     return false;
306    
307     m_images.Add(image);
308     }
309     else
310     {
311     stream.SeekI(stream.TellI() + datalen);
312     }
313    
314     // try to read next data chunk:
315     stream.Read(&FCC1, 4);
316     }
317    
318     if (m_nFrames==0)
319     return false;
320    
321     if (m_nFrames==m_images.GetCount())
322     {
323     // if no SEQ chunk is available, display the frames in the order
324     // they were loaded
325     for (unsigned int i=0; i<m_nFrames; i++)
326     if (m_info[i].m_imageIndex == -1)
327     m_info[i].m_imageIndex = i;
328     }
329    
330     // if some frame has an invalid delay, use the global delay given in the
331     // ANI header
332     for (unsigned int i=0; i<m_nFrames; i++)
333     if (m_info[i].m_delay == 0)
334     m_info[i].m_delay = globaldelay;
335    
336     // if the header did not contain a valid frame size, try to grab
337     // it from the size of the first frame (all frames are of the same size)
338     if (m_szAnimation.GetWidth() == 0 ||
339     m_szAnimation.GetHeight() == 0)
340     m_szAnimation = wxSize(m_images[0].GetWidth(), m_images[0].GetHeight());
341    
342     return m_szAnimation != wxDefaultSize;
343     }
344    
345     #endif // wxUSE_STREAMS && wxUSE_ICO_CUR

  ViewVC Help
Powered by ViewVC 1.1.22