RdBitF.c revision 61b2299d
1/* $Xorg: RdBitF.c,v 1.5 2001/02/09 02:03:35 xorgcvs Exp $ */
2/*
3
4Copyright 1987, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included
13in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall
24not be used in advertising or otherwise to promote the sale, use or
25other dealings in this Software without prior written authorization
26from The Open Group.
27
28*/
29/* $XFree86: xc/lib/X11/RdBitF.c,v 3.6 2003/04/13 19:22:17 dawes Exp $ */
30
31/*
32 *	Code to read bitmaps from disk files. Interprets
33 *	data from X10 and X11 bitmap files and creates
34 *	Pixmap representations of files. Returns Pixmap
35 *	ID and specifics about image.
36 *
37 *	Modified for speedup by Jim Becker, changed image
38 *	data parsing logic (removed some fscanf()s).
39 *	Aug 5, 1988
40 *
41 * Note that this file and ../Xmu/RdBitF.c look very similar....  Keep them
42 * that way (but don't use common source code so that people can have one
43 * without the other).
44 */
45
46#ifdef HAVE_CONFIG_H
47#include <config.h>
48#endif
49#include "Xlibint.h"
50#include <X11/Xos.h>
51#include "Xutil.h"
52#include <stdio.h>
53#include <ctype.h>
54
55
56#define MAX_SIZE 255
57
58/* shared data for the image read/parse logic */
59static const short hexTable[256] = {
60    ['0'] = 0,  ['1'] = 1,
61    ['2'] = 2,  ['3'] = 3,
62    ['4'] = 4,  ['5'] = 5,
63    ['6'] = 6,  ['7'] = 7,
64    ['8'] = 8,  ['9'] = 9,
65    ['A'] = 10, ['B'] = 11,
66    ['C'] = 12, ['D'] = 13,
67    ['E'] = 14, ['F'] = 15,
68    ['a'] = 10, ['b'] = 11,
69    ['c'] = 12, ['d'] = 13,
70    ['e'] = 14, ['f'] = 15,
71
72    [' '] = -1, [','] = -1,
73    ['}'] = -1, ['\n'] = -1,
74    ['\t'] = -1
75};
76
77/*
78 *	read next hex value in the input stream, return -1 if EOF
79 */
80static int
81NextInt (
82    FILE *fstream)
83{
84    int	ch;
85    int	value = 0;
86    int gotone = 0;
87    int done = 0;
88
89    /* loop, accumulate hex value until find delimiter  */
90    /* skip any initial delimiters found in read stream */
91
92    while (!done) {
93	ch = getc(fstream);
94	if (ch == EOF) {
95	    value	= -1;
96	    done++;
97	} else {
98	    /* trim high bits, check type and accumulate */
99	    ch &= 0xff;
100	    if (isascii(ch) && isxdigit(ch)) {
101		value = (value << 4) + hexTable[ch];
102		gotone++;
103	    } else if ((hexTable[ch]) < 0 && gotone)
104	      done++;
105	}
106    }
107    return value;
108}
109
110int
111XReadBitmapFileData (
112    _Xconst char *filename,
113    unsigned int *width,                /* RETURNED */
114    unsigned int *height,               /* RETURNED */
115    unsigned char **data,               /* RETURNED */
116    int *x_hot,                         /* RETURNED */
117    int *y_hot)                         /* RETURNED */
118{
119    FILE *fstream;			/* handle on file  */
120    unsigned char *bits = NULL;		/* working variable */
121    char line[MAX_SIZE];		/* input line from file */
122    int size;				/* number of bytes of data */
123    char name_and_type[MAX_SIZE];	/* an input line */
124    char *type;				/* for parsing */
125    int value;				/* from an input line */
126    int version10p;			/* boolean, old format */
127    int padding;			/* to handle alignment */
128    int bytes_per_line;			/* per scanline of data */
129    unsigned int ww = 0;		/* width */
130    unsigned int hh = 0;		/* height */
131    int hx = -1;			/* x hotspot */
132    int hy = -1;			/* y hotspot */
133
134#ifdef __UNIXOS2__
135    filename = __XOS2RedirRoot(filename);
136#endif
137    if (!(fstream = fopen(filename, "r")))
138	return BitmapOpenFailed;
139
140    /* error cleanup and return macro	*/
141#define	RETURN(code) \
142{ if (bits) Xfree ((char *)bits); fclose (fstream); return code; }
143
144    while (fgets(line, MAX_SIZE, fstream)) {
145	if (strlen(line) == MAX_SIZE-1)
146	    RETURN (BitmapFileInvalid);
147	if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
148	    if (!(type = strrchr(name_and_type, '_')))
149	      type = name_and_type;
150	    else
151	      type++;
152
153	    if (!strcmp("width", type))
154	      ww = (unsigned int) value;
155	    if (!strcmp("height", type))
156	      hh = (unsigned int) value;
157	    if (!strcmp("hot", type)) {
158		if (type-- == name_and_type || type-- == name_and_type)
159		  continue;
160		if (!strcmp("x_hot", type))
161		  hx = value;
162		if (!strcmp("y_hot", type))
163		  hy = value;
164	    }
165	    continue;
166	}
167
168	if (sscanf(line, "static short %s = {", name_and_type) == 1)
169	  version10p = 1;
170	else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
171	  version10p = 0;
172	else if (sscanf(line, "static char %s = {", name_and_type) == 1)
173	  version10p = 0;
174	else
175	  continue;
176
177	if (!(type = strrchr(name_and_type, '_')))
178	  type = name_and_type;
179	else
180	  type++;
181
182	if (strcmp("bits[]", type))
183	  continue;
184
185	if (!ww || !hh)
186	  RETURN (BitmapFileInvalid);
187
188	if ((ww % 16) && ((ww % 16) < 9) && version10p)
189	  padding = 1;
190	else
191	  padding = 0;
192
193	bytes_per_line = (ww+7)/8 + padding;
194
195	size = bytes_per_line * hh;
196	bits = (unsigned char *) Xmalloc ((unsigned int) size);
197	if (!bits)
198	  RETURN (BitmapNoMemory);
199
200	if (version10p) {
201	    unsigned char *ptr;
202	    int bytes;
203
204	    for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
205		if ((value = NextInt(fstream)) < 0)
206		  RETURN (BitmapFileInvalid);
207		*(ptr++) = value;
208		if (!padding || ((bytes+2) % bytes_per_line))
209		  *(ptr++) = value >> 8;
210	    }
211	} else {
212	    unsigned char *ptr;
213	    int bytes;
214
215	    for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
216		if ((value = NextInt(fstream)) < 0)
217		  RETURN (BitmapFileInvalid);
218		*ptr=value;
219	    }
220	}
221    }					/* end while */
222
223    fclose(fstream);
224    if (!bits)
225	return (BitmapFileInvalid);
226
227    *data = bits;
228    *width = ww;
229    *height = hh;
230    if (x_hot) *x_hot = hx;
231    if (y_hot) *y_hot = hy;
232
233    return (BitmapSuccess);
234}
235
236int
237XReadBitmapFile (
238    Display *display,
239    Drawable d,
240    _Xconst char *filename,
241    unsigned int *width,                /* RETURNED */
242    unsigned int *height,               /* RETURNED */
243    Pixmap *pixmap,                     /* RETURNED */
244    int *x_hot,                         /* RETURNED */
245    int *y_hot)                         /* RETURNED */
246{
247    unsigned char *data;
248    int res;
249
250    res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot);
251    if (res != BitmapSuccess)
252	return res;
253    *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height);
254    Xfree((char *)data);
255    if (*pixmap == None)
256	return (BitmapNoMemory);
257    return (BitmapSuccess);
258}
259