1 /*****
2 * readFLG.c : XmHTML Fast Loadable Graphics reader.
3 *
4 * This file Version $Revision: 1.3 $
5 *
6 * Creation date: Sun Sep 28 14:11:03 GMT+0100 1997
7 * Last modification: $Date: 1998/04/27 07:02:52 $
8 * By: $Author: newt $
9 * Current State: $State: Exp $
10 *
11 * Author: newt
12 *
13 * Copyright (C) 1994-1997 by Ripley Software Development
14 * All Rights Reserved
15 *
16 * This file is part of the XmHTML Widget Library.
17 *
18 * This library is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU [Library] General Public
20 * License as published by the Free Software Foundation; either
21 * version 2 of the License, or (at your option) any later version.
22 *
23 * This library is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * Library General Public License for more details.
27 *
28 * You should have received a copy of the GNU [Library] General Public
29 * License along with this library; if not, write to the Free
30 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 *
32 *****/
33 /*****
34 * ChangeLog
35 * $Log: readFLG.c,v $
36 * Revision 1.3 1998/04/27 07:02:52 newt
37 * tka stuff
38 *
39 * Revision 1.2 1998/04/04 06:28:30 newt
40 * XmHTML Beta 1.1.3
41 *
42 * Revision 1.1 1997/10/23 00:23:22 newt
43 * Initial Revision
44 *
45 *****/
46 #ifdef HAVE_CONFIG_H
47 #include "config.h"
48 #endif
49
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53
54 #if defined(HAVE_LIBPNG) || defined(HAVE_LIBZ)
55 #include <zlib.h>
56 #endif
57
58 #include "toolkit.h"
59 #include XmHTMLPrivateHeader
60
61 /*** External Function Prototype Declarations ***/
62
63 /*** Public Variable Declarations ***/
64
65 /*** Private Datatype Declarations ****/
66
67 /*** Private Function Prototype Declarations ****/
68
69 /*** Private Variable Declarations ***/
70
71 #define _readByte(VAL) do{ \
72 VAL = (*ib->curr_pos++ & 0xff); \
73 ib->next++; \
74 }while(0)
75
76 #define _readDimension(VAL) do{ \
77 VAL = (*ib->curr_pos++ & 0xff); \
78 VAL |= ((*ib->curr_pos++ & 0xff) << 8); \
79 ib->next += 2; \
80 }while(0)
81
82 #define _readCardinal(VAL) do{ \
83 VAL = (*ib->curr_pos++ & 0xff); \
84 VAL |= ((*ib->curr_pos++ & 0xff) << 8); \
85 VAL |= ((*ib->curr_pos++ & 0xff) << 16); \
86 VAL |= ((*ib->curr_pos++ & 0xff) << 24); \
87 ib->next += 4; \
88 }while(0)
89
90 #define _readInt(VAL) do{ \
91 VAL = (*ib->curr_pos++ & 0xff); \
92 VAL |= ((*ib->curr_pos++ & 0xff) << 8); \
93 VAL |= ((*ib->curr_pos++ & 0xff) << 16); \
94 VAL |= ((*ib->curr_pos++ & 0xff) << 24); \
95 ib->next += 4; \
96 }while(0)
97
98 static XmImageInfo*
readFLG(ImageBuffer * ib)99 readFLG(ImageBuffer *ib)
100 {
101 XmImageInfo *all_frames, *frame, *current;
102 int frameCount, i;
103 Byte c, *data;
104 Dimension *color;
105 Cardinal nframes, loop_count;
106
107 /* bogus frame leader */
108 all_frames = (XmImageInfo*)malloc(sizeof(XmImageInfo));
109 all_frames->frame = NULL;
110 current = all_frames;
111
112 /* skip magic */
113 ib->next += 6;
114 ib->curr_pos += 6;
115
116 /* FLG revision */
117 _readByte(c);
118
119 /* compress byte */
120 _readByte(c);
121
122 /* original image type */
123 _readByte(c);
124
125 /* no of frames in this file */
126 _readCardinal(nframes);
127
128 /* no of times to repeat animation */
129 _readCardinal(loop_count);
130
131 /* read all frames */
132 frameCount = 0;
133
134 do{
135 frame = (XmImageInfo*)calloc(1, sizeof(XmImageInfo));
136
137 /* default options */
138 frame->options = XmIMAGE_DEFERRED_FREE | XmIMAGE_RGB_SINGLE |
139 XmIMAGE_ALLOW_SCALE;
140
141 frame->type = IMAGE_FLG;
142
143 /* frames remaining */
144 frame->nframes = nframes - frameCount;
145 frame->loop_count = loop_count;
146
147 _readDimension(frame->width);
148 _readDimension(frame->height);
149 frame->swidth = frame->width;
150 frame->sheight = frame->height;
151
152 /* logical screen offsets (these can be negative) */
153 _readInt(frame->x);
154 _readInt(frame->y);
155
156 /* frame timeout */
157 _readCardinal(frame->timeout);
158
159 /* frame disposal method */
160 _readByte(frame->dispose);
161
162 /* frame depth (original bits per pixel) */
163 _readByte(frame->depth);
164
165 /* transparent pixel index */
166 _readInt(frame->bg);
167
168 /* transparency type */
169 _readByte(frame->transparency);
170
171 /* colorspace */
172 _readByte(frame->colorspace);
173
174 /* size of colormap */
175 _readCardinal(frame->ncolors);
176
177 if(frame->ncolors)
178 {
179 /* add one, it's zero based */
180 frame->ncolors++;
181 frame->scolors = frame->ncolors;
182
183 /* alloc colormap */
184 frame->reds = (Dimension*)calloc(3*frame->ncolors,
185 sizeof(Dimension));
186
187 /* read it */
188 color = frame->reds;
189
190 /* red color components */
191 for(i = 0; i < frame->ncolors; i++, color++)
192 _readDimension(*color);
193
194 /* green color components */
195 frame->greens = color;
196 for(i = 0; i < frame->ncolors; i++, color++)
197 _readDimension(*color);
198
199 /* blue color components */
200 frame->blues = color;
201 for(i = 0; i < frame->ncolors; i++, color++)
202 _readDimension(*color);
203 }
204
205 /* frame data */
206 frame->data = (Byte*)malloc(frame->width * frame->height);
207 data = frame->data;
208 for(i = 0; i < frame->width * frame->height; i++)
209 _readByte(*data++);
210
211 /* clipmask data (if we have got one) */
212 if(frame->bg != -1 && frame->transparency == XmIMAGE_TRANSPARENCY_BG)
213 {
214 int wd;
215 Byte *clip;
216
217 wd = frame->width;
218 /* pad so it will be a multiple of 8 */
219 while((wd % 8))
220 wd++;
221
222 /* this many bytes on a row */
223 wd /= 8;
224 /* this many bytes in the clipmask */
225 wd *= frame->height;
226
227 frame->clip = (Byte*)malloc(wd);
228 clip = frame->clip;
229 for(i = 0; i < wd; i++)
230 _readByte(*clip++);
231
232 /* we have a clipmask */
233 frame->options |= XmIMAGE_CLIPMASK;
234 }
235
236 /* alpha channel (if any) */
237 if(frame->transparency == XmIMAGE_TRANSPARENCY_ALPHA)
238 {
239 Cardinal gamma;
240 Byte *alpha;
241
242 /* frame gamma */
243 _readCardinal(gamma);
244 frame->fg_gamma = (float)gamma/100000.0;
245
246 /* write out alpha channel */
247 frame->alpha = (Byte*)malloc(frame->width * frame->height);
248 alpha = frame->alpha;
249 for(i = 0; i < frame->width * frame->height; i++)
250 _readByte(*alpha++);
251 }
252 /* terminator */
253 _readByte(c);
254
255 if(c != 0)
256 fprintf(stderr, "readFLG: missing separator bit on frame %i!\n",
257 frameCount);
258
259 current->frame = frame;
260 current = current->frame;
261
262 frameCount++; /* done with this frame */
263 }while(frameCount < nframes);
264
265 current = all_frames->frame;
266 free(all_frames);
267 return(current);
268 }
269
270
271 /*****
272 * Name: _XmHTMLReadFLG
273 * Return Type: XmImage*
274 * Description: reads a Fast Loadable Graphic directly into an XmImage.
275 * In:
276 * ib: raw image data;
277 * Returns:
278 * an allocated XmImage or NULL on failure.
279 *****/
280 XmImageInfo*
_XmHTMLReadFLG(XmHTMLWidget html,ImageBuffer * ib)281 _XmHTMLReadFLG(XmHTMLWidget html, ImageBuffer *ib)
282 {
283 XmImageInfo *image = NULL;
284 Byte *buffer = NULL, c = 0;
285 Boolean err = False;
286 ImageBuffer *dp;
287
288 #if defined(HAVE_LIBPNG) || defined(HAVE_LIBZ)
289 ImageBuffer data;
290 int zlib_err;
291 #endif
292
293 image = NULL;
294
295 /* sanity */
296 RewindImageBuffer(ib);
297
298 /* skip magic & version number */
299 ib->curr_pos += 7;
300 ib->next += 7;
301
302 /* check if data is compressed */
303 _readByte(c);
304
305 if(c == 1)
306 {
307 #if !defined(HAVE_LIBPNG) && !defined(HAVE_LIBZ)
308 /* compressed FLG requires zlib support to be present */
309 _XmHTMLWarning(__WFUNC__(html, "_XmHTMLReadFLG"),
310 XMHTML_MSG_103, ib->file, "zlib support not compiled in");
311 return(image);
312 #else
313 Cardinal tmp = 0;
314 unsigned long dsize, csize;
315
316 /* get size of uncompressed data */
317 _readCardinal(tmp);
318 dsize = (unsigned long)tmp;
319
320 /* size of compressed data */
321 csize = (unsigned long)(ib->size - ib->next);
322
323 /* allocate uncompress buffer */
324 buffer = (Byte*)malloc(dsize+1);
325
326 if((zlib_err = uncompress(buffer, &dsize, ib->curr_pos, csize)) != Z_OK)
327 {
328 _XmHTMLWarning(__WFUNC__(html, "_XmHTMLReadFLG"),
329 XMHTML_MSG_103, ib->file,
330 zlib_err == Z_MEM_ERROR ? "out of memory" :
331 zlib_err == Z_BUF_ERROR ? "not enough output room" :
332 "data corrupted");
333 err = True;
334 }
335 else if(dsize != (unsigned long)tmp)
336 {
337 _XmHTMLWarning(__WFUNC__(html, "_XmHTMLReadFLG"),
338 XMHTML_MSG_104, ib->file, dsize, tmp);
339 err = True;
340 }
341 /* compose local image buffer */
342 data.buffer = buffer;
343 data.curr_pos = data.buffer;
344 data.size = (size_t)dsize;
345 data.next = 0;
346 data.may_free = False;
347 dp = &data;
348 #endif
349 }
350 else
351 dp = ib;
352
353 if(err)
354 {
355 /* free up compressed buffer */
356 if(c == 1)
357 free(buffer);
358 return(image);
359 }
360
361 /* now go and process the actual image */
362 RewindImageBuffer(dp);
363
364 image = readFLG(dp);
365
366 /* store name of image */
367 image->url = strdup(ib->file); /* image location */
368
369 /* free up compressed buffer */
370 if(c == 1)
371 free(buffer);
372
373 return(image);
374 }
375