~ubuntu-branches/ubuntu/edgy/psi/edgy

« back to all changes in this revision

Viewing changes to libpsi/psipng/psimng.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2004-06-15 00:10:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040615001041-enywb6pcpe4sjsw6
Tags: 0.9.2-1
* New upstream release
* Set KDEDIR for ./configure so kde specific files get installed
* Don't install libpsiwidgets.so. It got installed in /usr/share
  where it doesn't belong. May be included (at a better location)
  later.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * psimng.cpp - QImageFormat for loading MNG animations at once
 
3
 * Copyright (C) 2003  Michail Pishchagin
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2.1 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 *
 
19
 */
 
20
 
 
21
#include "psimng.h"
 
22
 
 
23
#include <qdatetime.h>
 
24
 
 
25
#include <qimage.h>
 
26
#include <qasyncimageio.h>
 
27
#include <qiodevice.h>
 
28
 
 
29
// Define XMD_H prohibits the included headers of libmng.h to typedef INT32.
 
30
// This is needed for Borland with STL support, since in that case, INT32 is
 
31
// already defined by some Borland header.
 
32
#define XMD_H
 
33
#if defined(Q_OS_UNIXWARE)
 
34
#  define HAVE_BOOLEAN  // libjpeg under Unixware seems to need this
 
35
#endif
 
36
#include <libmng.h>
 
37
#include <stdlib.h>
 
38
 
 
39
class PsiMNGFormat : public QImageFormat {
 
40
public:
 
41
        PsiMNGFormat();
 
42
        ~PsiMNGFormat();
 
43
 
 
44
        int decode(QImage& img, QImageConsumer *cons, const uchar *buf, int length);
 
45
 
 
46
        bool       openstream();
 
47
        bool       closestream();
 
48
        bool       readdata(mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32p pRead);
 
49
        bool       errorproc(mng_int32 iErrorcode, mng_int8 /*iSeverity*/, mng_chunkid iChunkname, mng_uint32 /*iChunkseq*/, mng_int32 iExtra1, mng_int32 iExtra2, mng_pchar zErrortext);
 
50
        bool       processheader(mng_uint32 iWidth, mng_uint32 iHeight);
 
51
        mng_ptr    getcanvasline(mng_uint32 iLinenr);
 
52
        mng_bool   refresh(mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h);
 
53
        mng_uint32 gettickcount();
 
54
        bool       settimer(mng_uint32 iMsecs);
 
55
 
 
56
private:
 
57
        // Animation-level information
 
58
        enum {
 
59
                MovieStart,
 
60
                Data,
 
61
        } state;
 
62
 
 
63
        // Image-level information
 
64
        mng_handle handle;
 
65
 
 
66
        // Timing
 
67
        int time;
 
68
 
 
69
        // Temporary locals during single data-chunk processing
 
70
        const uchar *data;
 
71
        int dataSize, processedData;
 
72
 
 
73
        QImageConsumer *consumer;
 
74
        QImage *image;
 
75
};
 
76
 
 
77
//----------------------------------------------------------------------------
 
78
// C-callback to C++-member-function conversion
 
79
//----------------------------------------------------------------------------
 
80
 
 
81
static mng_bool openstream( mng_handle handle )
 
82
{
 
83
        return ((PsiMNGFormat*)mng_get_userdata(handle))->openstream();
 
84
}
 
85
static mng_bool closestream( mng_handle handle )
 
86
{
 
87
        return ((PsiMNGFormat*)mng_get_userdata(handle))->closestream();
 
88
}
 
89
static mng_bool readdata( mng_handle handle, mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32p pRead )
 
90
{
 
91
        return ((PsiMNGFormat*)mng_get_userdata(handle))->readdata(pBuf,iBuflen,pRead);
 
92
}
 
93
static mng_bool errorproc( mng_handle handle,
 
94
                           mng_int32   iErrorcode,
 
95
                           mng_int8    iSeverity,
 
96
                           mng_chunkid iChunkname,
 
97
                           mng_uint32  iChunkseq,
 
98
                           mng_int32   iExtra1,
 
99
                           mng_int32   iExtra2,
 
100
                           mng_pchar   zErrortext )
 
101
{
 
102
        return ((PsiMNGFormat*)mng_get_userdata(handle))->errorproc(iErrorcode,
 
103
                                                                    iSeverity,iChunkname,iChunkseq,iExtra1,iExtra2,zErrortext);
 
104
}
 
105
static mng_bool processheader( mng_handle handle,
 
106
                               mng_uint32 iWidth, mng_uint32 iHeight )
 
107
{
 
108
        return ((PsiMNGFormat*)mng_get_userdata(handle))->processheader(iWidth,iHeight);
 
109
}
 
110
static mng_ptr getcanvasline( mng_handle handle, mng_uint32 iLinenr )
 
111
{
 
112
        return ((PsiMNGFormat*)mng_get_userdata(handle))->getcanvasline(iLinenr);
 
113
}
 
114
static mng_bool refresh( mng_handle handle,
 
115
                         mng_uint32  iTop,
 
116
                         mng_uint32  iLeft,
 
117
                         mng_uint32  iBottom,
 
118
                         mng_uint32  iRight     )
 
119
{
 
120
        return ((PsiMNGFormat*)mng_get_userdata(handle))->refresh(iTop,iLeft,iBottom,iRight);
 
121
}
 
122
static mng_uint32 gettickcount( mng_handle handle )
 
123
{
 
124
        return ((PsiMNGFormat*)mng_get_userdata(handle))->gettickcount();
 
125
}
 
126
static mng_bool settimer( mng_handle handle, mng_uint32  iMsecs )
 
127
{
 
128
        return ((PsiMNGFormat*)mng_get_userdata(handle))->settimer(iMsecs);
 
129
}
 
130
 
 
131
static mng_ptr memalloc( mng_size_t iLen )
 
132
{
 
133
        return calloc(1,iLen);
 
134
}
 
135
static void memfree( mng_ptr iPtr, mng_size_t /*iLen*/ )
 
136
{
 
137
        free(iPtr);
 
138
}
 
139
 
 
140
//----------------------------------------------------------------------------
 
141
 
 
142
PsiMNGFormat::PsiMNGFormat()
 
143
{
 
144
        state = MovieStart;
 
145
        handle = 0;
 
146
        time = 0;
 
147
}
 
148
 
 
149
PsiMNGFormat::~PsiMNGFormat()
 
150
{
 
151
}
 
152
 
 
153
bool PsiMNGFormat::openstream()
 
154
{
 
155
        return true;
 
156
}
 
157
 
 
158
bool PsiMNGFormat::closestream()
 
159
{
 
160
        return true;
 
161
}
 
162
 
 
163
bool PsiMNGFormat::readdata(mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32p pRead)
 
164
{
 
165
        if ( iBuflen <= (uint)dataSize ) {
 
166
                memcpy(pBuf, data + processedData, iBuflen);
 
167
                *pRead = iBuflen;
 
168
        }
 
169
 
 
170
        processedData += iBuflen;
 
171
 
 
172
        return true;
 
173
}
 
174
 
 
175
bool PsiMNGFormat::errorproc( mng_int32 iErrorcode, mng_int8 /*iSeverity*/, mng_chunkid iChunkname, mng_uint32 /*iChunkseq*/, mng_int32 iExtra1, mng_int32 iExtra2, mng_pchar zErrortext )
 
176
{
 
177
        qWarning("MNG error %d: %s; chunk %c%c%c%c; subcode %d:%d",
 
178
                 iErrorcode,zErrortext,
 
179
                 (iChunkname>>24)&0xff,
 
180
                 (iChunkname>>16)&0xff,
 
181
                 (iChunkname>>8)&0xff,
 
182
                 (iChunkname>>0)&0xff,
 
183
                 iExtra1,iExtra2);
 
184
        return TRUE;
 
185
}
 
186
 
 
187
bool PsiMNGFormat::processheader(mng_uint32 iWidth, mng_uint32 iHeight)
 
188
{
 
189
        image->create(iWidth, iHeight, 32);
 
190
        image->setAlphaBuffer(TRUE);
 
191
        memset(image->bits(), 0, iWidth*iHeight*4);
 
192
        consumer->setSize(iWidth, iHeight);
 
193
        mng_set_canvasstyle(handle,
 
194
                            QImage::systemByteOrder() == QImage::LittleEndian
 
195
                            ? MNG_CANVAS_BGRA8 : MNG_CANVAS_ARGB8 );
 
196
        return TRUE;
 
197
}
 
198
 
 
199
mng_ptr PsiMNGFormat::getcanvasline(mng_uint32 iLinenr)
 
200
{
 
201
        return image->scanLine(iLinenr);
 
202
}
 
203
 
 
204
mng_bool PsiMNGFormat::refresh(mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
 
205
{
 
206
        QRect r(x,y,w,h);
 
207
        consumer->changed(r);
 
208
        consumer->setFramePeriod(0);
 
209
        consumer->frameDone();
 
210
        return TRUE;
 
211
}
 
212
 
 
213
mng_uint32 PsiMNGFormat::gettickcount()
 
214
{
 
215
        return time;
 
216
}
 
217
 
 
218
bool PsiMNGFormat::settimer(mng_uint32 iMsecs)
 
219
{
 
220
        consumer->setFramePeriod(iMsecs);
 
221
        consumer->frameDone();
 
222
        time += iMsecs;
 
223
        return TRUE;
 
224
}
 
225
 
 
226
int PsiMNGFormat::decode(QImage &img, QImageConsumer *cons, const uchar *buf, int length)
 
227
{
 
228
        //if ( !length ) // there's no more data then
 
229
        //      return 0;
 
230
 
 
231
        consumer = cons;
 
232
        image = &img;
 
233
 
 
234
        data = buf;
 
235
        dataSize = length;
 
236
        processedData = 0;
 
237
 
 
238
        if ( state == MovieStart ) {
 
239
                handle = mng_initialize( (mng_ptr)this, ::memalloc, ::memfree, 0 );
 
240
                //mng_set_suspensionmode( handle, MNG_FALSE );
 
241
                mng_setcb_openstream( handle, ::openstream );
 
242
                mng_setcb_closestream( handle, ::closestream );
 
243
                mng_setcb_readdata( handle, ::readdata );
 
244
                mng_setcb_errorproc( handle, ::errorproc );
 
245
                mng_setcb_processheader( handle, ::processheader );
 
246
                mng_setcb_getcanvasline( handle, ::getcanvasline );
 
247
                mng_setcb_refresh( handle, ::refresh );
 
248
                mng_setcb_gettickcount( handle, ::gettickcount );
 
249
                mng_setcb_settimer( handle, ::settimer );
 
250
                state = Data;
 
251
 
 
252
                mng_readdisplay(handle);
 
253
        }
 
254
        else
 
255
                mng_display_resume(handle);
 
256
 
 
257
        image = 0;
 
258
 
 
259
        return processedData;
 
260
}
 
261
 
 
262
//----------------------------------------------------------------------------
 
263
 
 
264
class PsiMNGFormatType : public QImageFormatType
 
265
{
 
266
        QImageFormat *decoderFor(const uchar *buffer, int length)
 
267
        {
 
268
                if (length < 8)
 
269
                        return 0;
 
270
 
 
271
                if (buffer[0]==138 // MNG signature
 
272
                 && buffer[1]=='M'
 
273
                 && buffer[2]=='N'
 
274
                 && buffer[3]=='G'
 
275
                 && buffer[4]==13
 
276
                 && buffer[5]==10
 
277
                 && buffer[6]==26
 
278
                 && buffer[7]==10) {
 
279
                        return new PsiMNGFormat;
 
280
                }
 
281
 
 
282
                return 0;
 
283
        }
 
284
 
 
285
        const char *formatName() const
 
286
        {
 
287
                return "PsiMNG";
 
288
        }
 
289
};
 
290
 
 
291
static PsiMNGFormatType *globalMngFormatTypeObject = 0;
 
292
 
 
293
void cleanupPsiMngIO()
 
294
{
 
295
        if ( globalMngFormatTypeObject ) {
 
296
                delete globalMngFormatTypeObject;
 
297
                globalMngFormatTypeObject = 0;
 
298
        }
 
299
}
 
300
 
 
301
void initPsiMngIO()
 
302
{
 
303
        static bool done = FALSE;
 
304
        if ( !done ) {
 
305
                done = TRUE;
 
306
                globalMngFormatTypeObject = new PsiMNGFormatType;
 
307
                qAddPostRoutine( cleanupPsiMngIO );
 
308
        }
 
309
}