]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/picomodel/lwo/clip.c
Merge branch 'fix-fast' into 'master'
[xonotic/netradiant.git] / libs / picomodel / lwo / clip.c
1 /*
2    ======================================================================
3    clip.c
4
5    Functions for LWO2 image references.
6
7    Ernie Wright  17 Sep 00
8    ====================================================================== */
9
10 #include "../picointernal.h"
11 #include "lwo2.h"
12
13
14 /*
15    ======================================================================
16    lwFreeClip()
17
18    Free memory used by an lwClip.
19    ====================================================================== */
20
21 void lwFreeClip( lwClip *clip ){
22         if ( clip ) {
23                 lwListFree(clip->ifilter, (void (*)(void *)) lwFreePlugin);
24                 lwListFree(clip->pfilter, (void (*)(void *)) lwFreePlugin);
25
26                 switch ( clip->type ) {
27                 case ID_STIL:
28                         _pico_free( clip->source.still.name );
29                         break;
30
31                 case ID_ISEQ:
32                         _pico_free( clip->source.seq.prefix );
33                         _pico_free( clip->source.seq.suffix );
34                         break;
35
36                 case ID_ANIM:
37                         _pico_free( clip->source.anim.name );
38                         _pico_free( clip->source.anim.server );
39                         _pico_free( clip->source.anim.data );
40                         break;
41
42                 case ID_XREF:
43                         _pico_free( clip->source.xref.string );
44                         break;
45
46                 case ID_STCC:
47                         _pico_free( clip->source.cycle.name );
48                         break;
49
50                 default:
51                         break;
52                 }
53
54                 _pico_free( clip );
55         }
56 }
57
58
59 /*
60    ======================================================================
61    lwGetClip()
62
63    Read image references from a CLIP chunk in an LWO2 file.
64    ====================================================================== */
65
66 lwClip *lwGetClip( picoMemStream_t *fp, int cksize ){
67         lwClip *clip;
68         lwPlugin *filt;
69         unsigned int id;
70         unsigned short sz;
71         int pos, rlen;
72
73
74         /* allocate the Clip structure */
75
76         clip = _pico_calloc( 1, sizeof( lwClip ) );
77         if ( !clip ) {
78                 goto Fail;
79         }
80
81         clip->contrast.val = 1.0f;
82         clip->brightness.val = 1.0f;
83         clip->saturation.val = 1.0f;
84         clip->gamma.val = 1.0f;
85
86         /* remember where we started */
87
88         set_flen( 0 );
89         pos = _pico_memstream_tell( fp );
90
91         /* index */
92
93         clip->index = getI4( fp );
94
95         /* first subchunk header */
96
97         clip->type = getU4( fp );
98         sz = getU2( fp );
99         if ( 0 > get_flen() ) {
100                 goto Fail;
101         }
102
103         sz += sz & 1;
104         set_flen( 0 );
105
106         switch ( clip->type ) {
107         case ID_STIL:
108                 clip->source.still.name = getS0( fp );
109                 break;
110
111         case ID_ISEQ:
112                 clip->source.seq.digits  = getU1( fp );
113                 clip->source.seq.flags   = getU1( fp );
114                 clip->source.seq.offset  = getI2( fp );
115                 getU2( fp );   /* not sure what this is yet */
116                 clip->source.seq.start   = getI2( fp );
117                 clip->source.seq.end     = getI2( fp );
118                 clip->source.seq.prefix  = getS0( fp );
119                 clip->source.seq.suffix  = getS0( fp );
120                 break;
121
122         case ID_ANIM:
123                 clip->source.anim.name   = getS0( fp );
124                 clip->source.anim.server = getS0( fp );
125                 rlen = get_flen();
126                 clip->source.anim.data   = getbytes( fp, sz - rlen );
127                 break;
128
129         case ID_XREF:
130                 clip->source.xref.index  = getI4( fp );
131                 clip->source.xref.string = getS0( fp );
132                 break;
133
134         case ID_STCC:
135                 clip->source.cycle.lo   = getI2( fp );
136                 clip->source.cycle.hi   = getI2( fp );
137                 clip->source.cycle.name = getS0( fp );
138                 break;
139
140         default:
141                 break;
142         }
143
144         /* error while reading current subchunk? */
145
146         rlen = get_flen();
147         if ( rlen < 0 || rlen > sz ) {
148                 goto Fail;
149         }
150
151         /* skip unread parts of the current subchunk */
152
153         if ( rlen < sz ) {
154                 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
155         }
156
157         /* end of the CLIP chunk? */
158
159         rlen = _pico_memstream_tell( fp ) - pos;
160         if ( cksize < rlen ) {
161                 goto Fail;
162         }
163         if ( cksize == rlen ) {
164                 return clip;
165         }
166
167         /* process subchunks as they're encountered */
168
169         id = getU4( fp );
170         sz = getU2( fp );
171         if ( 0 > get_flen() ) {
172                 goto Fail;
173         }
174
175         while ( 1 ) {
176                 sz += sz & 1;
177                 set_flen( 0 );
178
179                 switch ( id ) {
180                 case ID_TIME:
181                         clip->start_time = getF4( fp );
182                         clip->duration = getF4( fp );
183                         clip->frame_rate = getF4( fp );
184                         break;
185
186                 case ID_CONT:
187                         clip->contrast.val = getF4( fp );
188                         clip->contrast.eindex = getVX( fp );
189                         break;
190
191                 case ID_BRIT:
192                         clip->brightness.val = getF4( fp );
193                         clip->brightness.eindex = getVX( fp );
194                         break;
195
196                 case ID_SATR:
197                         clip->saturation.val = getF4( fp );
198                         clip->saturation.eindex = getVX( fp );
199                         break;
200
201                 case ID_HUE:
202                         clip->hue.val = getF4( fp );
203                         clip->hue.eindex = getVX( fp );
204                         break;
205
206                 case ID_GAMM:
207                         clip->gamma.val = getF4( fp );
208                         clip->gamma.eindex = getVX( fp );
209                         break;
210
211                 case ID_NEGA:
212                         clip->negative = getU2( fp );
213                         break;
214
215                 case ID_IFLT:
216                 case ID_PFLT:
217                         filt = _pico_calloc( 1, sizeof( lwPlugin ) );
218                         if ( !filt ) {
219                                 goto Fail;
220                         }
221
222                         filt->name = getS0( fp );
223                         filt->flags = getU2( fp );
224                         rlen = get_flen();
225                         filt->data = getbytes( fp, sz - rlen );
226
227                         if ( id == ID_IFLT ) {
228                                 lwListAdd( (void *) &clip->ifilter, filt );
229                                 clip->nifilters++;
230                         }
231                         else {
232                                 lwListAdd( (void *) &clip->pfilter, filt );
233                                 clip->npfilters++;
234                         }
235                         break;
236
237                 default:
238                         break;
239                 }
240
241                 /* error while reading current subchunk? */
242
243                 rlen = get_flen();
244                 if ( rlen < 0 || rlen > sz ) {
245                         goto Fail;
246                 }
247
248                 /* skip unread parts of the current subchunk */
249
250                 if ( rlen < sz ) {
251                         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
252                 }
253
254                 /* end of the CLIP chunk? */
255
256                 rlen = _pico_memstream_tell( fp ) - pos;
257                 if ( cksize < rlen ) {
258                         goto Fail;
259                 }
260                 if ( cksize == rlen ) {
261                         break;
262                 }
263
264                 /* get the next chunk header */
265
266                 set_flen( 0 );
267                 id = getU4( fp );
268                 sz = getU2( fp );
269                 if ( 6 != get_flen() ) {
270                         goto Fail;
271                 }
272         }
273
274         return clip;
275
276 Fail:
277         lwFreeClip( clip );
278         return NULL;
279 }
280
281
282 /*
283    ======================================================================
284    lwFindClip()
285
286    Returns an lwClip pointer, given a clip index.
287    ====================================================================== */
288
289 lwClip *lwFindClip( lwClip *list, int index ){
290         lwClip *clip;
291
292         clip = list;
293         while ( clip ) {
294                 if ( clip->index == index ) {
295                         break;
296                 }
297                 clip = clip->next;
298         }
299         return clip;
300 }