1 # include "bitmapConfig.h"
2
3 # include "bmintern.h"
4 # include <stdio.h>
5 # include <ctype.h>
6 # include <string.h>
7 # include <stdlib.h>
8 # include <sioFileio.h>
9
10 # include <appDebugon.h>
11
12 static unsigned char BMXBMflip[256];
13
bmXbmSetFlip(void)14 static void bmXbmSetFlip( void )
15 {
16 int i;
17
18 for ( i= 0; i < 256; i++ )
19 {
20 BMXBMflip[i]= ( ( i & 0x80 ) >> 7 ) |
21 ( ( i & 0x40 ) >> 5 ) |
22 ( ( i & 0x20 ) >> 3 ) |
23 ( ( i & 0x10 ) >> 1 ) |
24 ( ( i & 0x08 ) << 1 ) |
25 ( ( i & 0x04 ) << 3 ) |
26 ( ( i & 0x02 ) << 5 ) |
27 ( ( i & 0x01 ) << 7 ) ;
28 }
29 }
30
31 /************************************************************************/
32 /* Read an X bitmap file. */
33 /* Routine stolen from the X11R6 file 'lib/X11/RdBitF.c' */
34 /************************************************************************/
35
36 /* Fake X headers */
37 #define Bool unsigned char
38 #define False 0
39 #define True 1
40 #define BitmapOpenFailed -1
41 #define BitmapFileInvalid -1
42 #define BitmapNoMemory -1
43 #define BitmapSuccess 0
44 #define Xfree(p) free(p)
45 #define Xmalloc(n) malloc(n)
46
47 #define MAX_SIZE 255
48
49 /* shared data for the image read/parse logic */
50 static short hexTable[256]; /* conversion value */
51 static Bool initialized = False; /* easier to fill in at run time */
52
53
54 /*
55 * Table index for the hex values. Initialized once, first time.
56 * Used for translation value or delimiter significance lookup.
57 */
initHexTable(void)58 static void initHexTable( void )
59 {
60 /*
61 * We build the table at run time for several reasons:
62 *
63 * 1. portable to non-ASCII machines.
64 * 2. still reentrant since we set the init flag after setting table.
65 * 3. easier to extend.
66 * 4. less prone to bugs.
67 */
68 hexTable['0'] = 0; hexTable['1'] = 1;
69 hexTable['2'] = 2; hexTable['3'] = 3;
70 hexTable['4'] = 4; hexTable['5'] = 5;
71 hexTable['6'] = 6; hexTable['7'] = 7;
72 hexTable['8'] = 8; hexTable['9'] = 9;
73 hexTable['A'] = 10; hexTable['B'] = 11;
74 hexTable['C'] = 12; hexTable['D'] = 13;
75 hexTable['E'] = 14; hexTable['F'] = 15;
76 hexTable['a'] = 10; hexTable['b'] = 11;
77 hexTable['c'] = 12; hexTable['d'] = 13;
78 hexTable['e'] = 14; hexTable['f'] = 15;
79
80 /* delimiters of significance are flagged w/ negative value */
81 hexTable[' '] = -1; hexTable[','] = -1;
82 hexTable['}'] = -1; hexTable['\n'] = -1;
83 hexTable['\t'] = -1;
84
85 initialized = True;
86 }
87
88 /*
89 * read next hex value in the input stream, return -1 if EOF
90 */
NextInt(FILE * fstream)91 static int NextInt ( FILE *fstream )
92 {
93 int ch;
94 int value = 0;
95 int gotone = 0;
96 int done = 0;
97
98 /* loop, accumulate hex value until find delimiter */
99 /* skip any initial delimiters found in read stream */
100
101 while (!done) {
102 ch = getc(fstream);
103 if (ch == EOF) {
104 value = -1;
105 done++;
106 } else {
107 /* trim high bits, check type and accumulate */
108 ch &= 0xff;
109 if (isascii(ch) && isxdigit(ch)) {
110 value = (value << 4) + hexTable[ch];
111 gotone++;
112 } else if ((hexTable[ch]) < 0 && gotone)
113 done++;
114 }
115 }
116 return value;
117 }
118
XReadBitmapFileData(const char * filename,unsigned int * width,unsigned int * height,unsigned char ** data,int * x_hot,int * y_hot)119 static int XReadBitmapFileData (
120 const char *filename,
121 unsigned int *width, /* RETURNED */
122 unsigned int *height, /* RETURNED */
123 unsigned char **data, /* RETURNED */
124 int *x_hot, /* RETURNED */
125 int *y_hot) /* RETURNED */
126 {
127 FILE *fstream; /* handle on file */
128 unsigned char *bits = NULL; /* working variable */
129 char line[MAX_SIZE]; /* input line from file */
130 int size; /* number of bytes of data */
131 char name_and_type[MAX_SIZE]; /* an input line */
132 char *type; /* for parsing */
133 int value; /* from an input line */
134 int version10p; /* boolean, old format */
135 int padding; /* to handle alignment */
136 int bytes_per_line; /* per scanline of data */
137 unsigned int ww = 0; /* width */
138 unsigned int hh = 0; /* height */
139 int hx = -1; /* x hotspot */
140 int hy = -1; /* y hotspot */
141
142 /* first time initialization */
143 if (initialized == False) initHexTable();
144
145 if (!(fstream = fopen(filename, "r")))
146 { SDEB(filename); return BitmapOpenFailed; }
147
148 /* error cleanup and return macro */
149 #define RETURN(code) \
150 { if (bits) Xfree ((char *)bits); fclose (fstream); LDEB(1); return code; }
151
152 while (fgets(line, MAX_SIZE, fstream)) {
153 if (strlen(line) == MAX_SIZE-1)
154 RETURN (BitmapFileInvalid);
155 if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
156 if (!(type = strrchr(name_and_type, '_')))
157 type = name_and_type;
158 else
159 type++;
160
161 if (!strcmp("width", type))
162 ww = (unsigned int) value;
163 if (!strcmp("height", type))
164 hh = (unsigned int) value;
165 if (!strcmp("hot", type)) {
166 if (type-- == name_and_type || type-- == name_and_type)
167 continue;
168 if (!strcmp("x_hot", type))
169 hx = value;
170 if (!strcmp("y_hot", type))
171 hy = value;
172 }
173 continue;
174 }
175
176 if (sscanf(line, "static short %s = {", name_and_type) == 1)
177 /*}*/
178 version10p = 1;
179 else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
180 /*}*/
181 version10p = 0;
182 else if (sscanf(line, "static char %s = {", name_and_type) == 1)
183 /*}*/
184 version10p = 0;
185 else
186 continue;
187
188 if (!(type = strrchr(name_and_type, '_')))
189 type = name_and_type;
190 else
191 type++;
192
193 if (strcmp("bits[]", type))
194 continue;
195
196 if (!ww || !hh)
197 { LLDEB(ww,hh); RETURN (BitmapFileInvalid); }
198
199 if ((ww % 16) && ((ww % 16) < 9) && version10p)
200 padding = 1;
201 else
202 padding = 0;
203
204 bytes_per_line = (ww+7)/8 + padding;
205
206 size = bytes_per_line * hh;
207 bits = (unsigned char *) Xmalloc ((unsigned int) size);
208 if (!bits)
209 { LDEB(bits); RETURN (BitmapNoMemory); }
210
211 if (version10p) {
212 unsigned char *ptr;
213 int bytes;
214
215 for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
216 if ((value = NextInt(fstream)) < 0)
217 { LDEB(value); RETURN (BitmapFileInvalid); }
218 *(ptr++) = value;
219 if (!padding || ((bytes+2) % bytes_per_line))
220 *(ptr++) = value >> 8;
221 }
222 } else {
223 unsigned char *ptr;
224 int bytes;
225
226 for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
227 if ((value = NextInt(fstream)) < 0)
228 { LDEB(value); RETURN (BitmapFileInvalid); }
229 *ptr=value;
230 }
231 }
232 } /* end while */
233
234 fclose(fstream);
235 if (!bits)
236 { XDEB(bits); return (BitmapFileInvalid); }
237
238 *data = bits;
239 *width = ww;
240 *height = hh;
241 if (x_hot) *x_hot = hx;
242 if (y_hot) *y_hot = hy;
243
244 return (BitmapSuccess);
245 }
246
247 /************************************************************************/
248 /* Write an X bitmap file. */
249 /* Part of this routine is stolen from: the X11R6 file */
250 /* 'lib/X11/WrBitF.c */
251 /************************************************************************/
252
253 #define BYTES_PER_OUTPUT_LINE 12
254
bmWriteXbmFile(const MemoryBuffer * filename,const unsigned char * buffer,const BitmapDescription * bd,int privateFormat)255 int bmWriteXbmFile( const MemoryBuffer * filename,
256 const unsigned char * buffer,
257 const BitmapDescription * bd,
258 int privateFormat )
259 {
260 SimpleOutputStream * sos;
261 int x_hot= -1;
262 int y_hot= -1;
263 const char * name= "IMAGE";
264 const unsigned char * data= buffer;
265 int width= bd->bdPixelsWide;
266 int height= bd->bdPixelsHigh;
267 int size= bd->bdBufferLength;
268
269 int byte;
270 int c;
271 const unsigned char * ptr;
272
273 sos= sioOutFileioOpen( filename );
274 if ( ! sos )
275 { XDEB(sos); return -1; }
276
277 bmXbmSetFlip();
278
279 /* #>>>>>>>>>>>>>>>>>>> begin FROM X*/
280
281 /* Write out standard header */
282 sioOutPrintf(sos, "#define %s_width %d\n", name, width);
283 sioOutPrintf(sos, "#define %s_height %d\n", name, height);
284 if (x_hot != -1) {
285 sioOutPrintf(sos, "#define %s_x_hot %d\n", name, x_hot);
286 sioOutPrintf(sos, "#define %s_y_hot %d\n", name, y_hot);
287 }
288
289 /* Print out the data itself */
290 sioOutPrintf(sos, "static unsigned char %s_bits[] = {", name);
291 for (byte=0, ptr=data; byte<size; byte++, ptr++) {
292 if (!byte)
293 sioOutPrintf(sos, "\n ");
294 else if (!(byte % BYTES_PER_OUTPUT_LINE))
295 sioOutPrintf(sos, ",\n ");
296 else
297 sioOutPrintf(sos, ", ");
298 c = *ptr;
299 if (c<0)
300 c += 256;
301 sioOutPrintf(sos, "0x%02x", BMXBMflip[c]);
302 }
303 sioOutPrintf(sos, "};\n");
304
305 sioOutClose(sos);
306 return(BitmapSuccess);
307 }
308 /* #<<<<<<<<<<<<<<<<<<< end FROM X*/
309
bmCanWriteXbmFile(const BitmapDescription * bd,int privateFormat)310 int bmCanWriteXbmFile( const BitmapDescription * bd,
311 int privateFormat )
312 {
313 if ( privateFormat != 11 )
314 { return -1; }
315
316 if ( bd->bdBitsPerPixel != 1 )
317 { return -1; }
318
319 return 0;
320 }
321
322 /************************************************************************/
323 /* */
324 /* Read an XBM bitmap file. */
325 /* */
326 /************************************************************************/
327
bmReadXbmFile(const MemoryBuffer * filename,unsigned char ** pBuffer,BitmapDescription * bd,int * pPrivateFormat)328 int bmReadXbmFile( const MemoryBuffer * filename,
329 unsigned char ** pBuffer,
330 BitmapDescription * bd,
331 int * pPrivateFormat )
332 {
333 unsigned int width;
334 unsigned int height;
335 int x_hot;
336 int y_hot;
337 unsigned char * s;
338
339 if ( XReadBitmapFileData ( utilMemoryBufferGetString( filename ),
340 &width,
341 &height,
342 pBuffer,
343 &x_hot, &y_hot ) )
344 { LDEB(1); return -1; }
345
346 bd->bdBytesPerRow= ( width+ 7 )/8;
347 bd->bdBufferLength= height* bd->bdBytesPerRow;
348 bd->bdPixelsWide= width;
349 bd->bdPixelsHigh= height;
350 bd->bdBitsPerSample= 1;
351 bd->bdSamplesPerPixel= 1;
352 bd->bdBitsPerPixel= 1;
353 bd->bdXResolution= 1;
354 bd->bdYResolution= 1;
355 bd->bdUnit= BMunPIXEL;
356 bd->bdColorEncoding= BMcoBLACKWHITE;
357 bd->bdHasAlpha= 0;
358 utilInitColorPalette( &(bd->bdPalette) );
359
360 *pPrivateFormat= 11;
361
362 bmXbmSetFlip();
363 s= *pBuffer;
364 for ( width = 0; width < bd->bdBufferLength; width++ )
365 { *s= BMXBMflip[*s]; s++; }
366
367 return 0;
368 }
369