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