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