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