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