source: trunk/JPGPROC/source/gbmsrc/gbmxbm.c@ 2

Last change on this file since 2 was 2, checked in by stevenhl, 8 years ago

Import sources from cwmm-full.zip dated 2005-03-21

File size: 13.8 KB
Line 
1/*
2
3gbmxbm.c - X Windows Bitmap support
4
5Reads and writes most X bitmaps
6
7*/
8
9/*...sincludes:0:*/
10#include <stdio.h>
11#include <ctype.h>
12#include <stddef.h>
13#include <stdlib.h>
14#include <string.h>
15#include "gbm.h"
16#include "gbmhelp.h"
17
18/*...vgbm\46\h:0:*/
19/*...vgbmhelp\46\h:0:*/
20/*...e*/
21/*...sisalnum fix:0:*/
22#ifdef LINUX
23/* On Slackware 3.4 /lib/libc.so.5 -> libc.5.4.33
24 isalnum(c) is implemented as (__ctype_b(c)&_ISalnum)
25 Programs compiled on Slackware therefore look for this bit
26 On RedHat 6.0, /usr/i486-linux-libc5/lib/libc.so.5 -> libc.so.5.3.12
27 isalnum(c) is probably done as (__ctype_b(c)&(_ISalnum|_ISdigit))
28 So the __ctype_b array doesn't have this bit.
29 So programs compiled, using isalnum on Slackware 3.4, don't work
30 when run on RedHat 6.0. Best to avoid it. */
31#undef isalnum
32#define isalnum(c) (isalpha(c)||isdigit(c))
33#endif
34/*...e*/
35
36static GBMFT xbm_gbmft =
37 {
38 "XBitmap",
39 "X Windows Bitmap",
40 "XBM",
41 GBM_FT_R1|
42 GBM_FT_W1,
43 };
44
45#define GBM_ERR_XBM_EXP_ID ((GBM_ERR) 1300)
46#define GBM_ERR_XBM_UNEXP_EOF ((GBM_ERR) 1301)
47#define GBM_ERR_XBM_EXP_CHAR ((GBM_ERR) 1302)
48#define GBM_ERR_XBM_EXP_LSQR ((GBM_ERR) 1303)
49#define GBM_ERR_XBM_EXP_RSQR ((GBM_ERR) 1304)
50#define GBM_ERR_XBM_EXP_EQUALS ((GBM_ERR) 1305)
51#define GBM_ERR_XBM_EXP_LCUR ((GBM_ERR) 1306)
52#define GBM_ERR_XBM_EXP_RCUR ((GBM_ERR) 1307)
53#define GBM_ERR_XBM_EXP_COMMA ((GBM_ERR) 1308)
54#define GBM_ERR_XBM_EXP_NUMBER ((GBM_ERR) 1309)
55#define GBM_ERR_XBM_EXP_SEMI ((GBM_ERR) 1310)
56
57#define MAX_BUF 1024
58#define MAX_ID 100
59
60typedef struct
61 {
62 int fd;
63 int inx, cnt;
64 byte buf[MAX_BUF];
65 char id[MAX_ID+1];
66 int number;
67 int size;
68 } XBM_PRIV;
69
70/*...srev:0:*/
71static byte rev[0x100] =
72 {
73 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
74 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
75 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
76 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
77 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
78 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
79 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
80 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
81 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
82 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
83 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
84 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
85 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
86 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
87 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
88 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
89 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
90 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
91 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
92 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
93 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
94 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
95 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
96 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
97 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
98 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
99 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
100 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
101 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
102 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
103 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
104 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
105 };
106/*...e*/
107/*...sbuffered text read:0:*/
108static int nextbuf(XBM_PRIV *xbm_priv)
109 {
110 int cnt;
111 if ( (cnt = gbm_file_read(xbm_priv->fd, xbm_priv->buf, MAX_BUF)) <= 0 )
112 return -1;
113 xbm_priv->cnt = cnt;
114 xbm_priv->inx = 1;
115 return xbm_priv->buf[0];
116 }
117
118#define nextchar(x) ( ((x)->inx<(x)->cnt) ? \
119 (int) (unsigned int) (unsigned char) ((x)->buf[((x)->inx)++]) : nextbuf(x) )
120 /* This is worded to char (char)255 does not become (int)-1 */
121
122static void pushchar(XBM_PRIV *xbm_priv, int c)
123 {
124 if ( c != -1 )
125 xbm_priv->buf[--(xbm_priv->inx)] = (byte) c;
126 }
127
128typedef byte SYM;
129#define S_DEFINE ((SYM) 1)
130#define S_ID ((SYM) 2)
131#define S_NUMBER ((SYM) 3)
132#define S_STATIC ((SYM) 4)
133#define S_CHAR ((SYM) 5)
134#define S_SHORT ((SYM) 6)
135#define S_LSQR ((SYM) 7)
136#define S_RSQR ((SYM) 8)
137#define S_LCUR ((SYM) 9)
138#define S_RCUR ((SYM) 10)
139#define S_COMMA ((SYM) 11)
140#define S_SEMI ((SYM) 12)
141#define S_EQUALS ((SYM) 13)
142#define S_EOF ((SYM) 14)
143#define S_ERROR_ID ((SYM) 15)
144#define S_ERROR_MINUS ((SYM) 16)
145#define S_ERROR_PLUS ((SYM) 17)
146#define S_ERROR_NUMBER ((SYM) 18)
147#define S_UNSIGNED ((SYM) 19)
148#define S_SIGNED ((SYM) 20)
149
150/*...svalof:0:*/
151static int valof(char c)
152 {
153 if ( c >= 'a' && c <= 'f' )
154 return c - 'a' + 10;
155 if ( c >= 'A' && c <= 'F' )
156 return c - 'A' + 10;
157 return c - '0';
158 }
159/*...e*/
160/*...sskipit:0:*/
161/* Skip whitespace and comments,
162 returning -1 or the first interesting character. */
163
164static int skipit(XBM_PRIV *xbm_priv)
165 {
166 int c;
167 for ( ;; )
168 {
169 while ( (c = nextchar(xbm_priv)) != -1 && isspace(c) )
170 ;
171 if ( c == -1 )
172 return -1;
173
174 if ( c != '/' )
175 break;
176
177 if ( (c = nextchar(xbm_priv)) != '*' )
178 return -1;
179
180 if ( (c = nextchar(xbm_priv)) == -1 )
181 return -1;
182
183 do
184 while ( c != '*' )
185 if ( (c = nextchar(xbm_priv)) == -1 )
186 return S_EOF;
187 while ( (c = nextchar(xbm_priv)) != -1 && c != '/' );
188 if ( c == -1 )
189 return -1;
190 }
191 return c;
192 }
193/*...e*/
194
195static SYM nextsym(XBM_PRIV *xbm_priv)
196 {
197 int c, i, sign = 1;
198
199 if ( (c = skipit(xbm_priv)) == -1 )
200 return S_EOF;
201
202 switch ( c )
203 {
204 case '[': return S_LSQR ;
205 case ']': return S_RSQR ;
206 case '{': return S_LCUR ;
207 case '}': return S_RCUR ;
208 case ',': return S_COMMA ;
209 case ';': return S_SEMI ;
210 case '=': return S_EQUALS;
211 }
212
213 if ( isdigit(c) || c == '-' || c == '+' )
214 {
215 if ( c == '-' )
216 {
217 sign = -1;
218 if ( (c = nextchar(xbm_priv)) == -1 )
219 return S_ERROR_MINUS;
220 if ( !isdigit(c) )
221 return S_ERROR_NUMBER;
222 }
223 else if ( c == '+' )
224 {
225 if ( (c = nextchar(xbm_priv)) == -1 )
226 return S_ERROR_PLUS;
227 if ( !isdigit(c) )
228 return S_ERROR_NUMBER;
229 }
230 if ( c == '0' )
231 {
232 xbm_priv->number = 0;
233 if ( (c = nextchar(xbm_priv)) == 'x' || c == 'X' )
234 /* Hex number */
235 {
236 while ( (c = nextchar(xbm_priv)) != -1 && isxdigit(c) )
237 {
238 xbm_priv->number <<= 4;
239 xbm_priv->number += valof((char) c);
240 }
241 }
242 else
243 /* Octal number */
244 while ( c != -1 && c >= '0' && c <= '7' )
245 {
246 xbm_priv->number <<= 3;
247 xbm_priv->number += ( c - '0' );
248 c = nextchar(xbm_priv);
249 }
250 }
251 else
252 {
253 xbm_priv->number = ( c - '0' );
254 while ( (c = nextchar(xbm_priv)) != -1 && isdigit(c) )
255 {
256 xbm_priv->number *= 10;
257 xbm_priv->number += ( c - '0' );
258 }
259 }
260
261 xbm_priv->number *= sign;
262
263 pushchar(xbm_priv, c);
264 return S_NUMBER;
265 }
266
267 i = 0;
268 do
269 xbm_priv->id[i++] = c;
270 while ( (c = nextchar(xbm_priv)) != -1 && (isalnum(c) || c == '_') && i < MAX_ID );
271 xbm_priv->id[i] = '\0';
272
273 pushchar(xbm_priv, c);
274
275 if ( !strcmp(xbm_priv->id, "#define" ) ) return S_DEFINE ;
276 if ( !strcmp(xbm_priv->id, "static" ) ) return S_STATIC ;
277 if ( !strcmp(xbm_priv->id, "char" ) ) return S_CHAR ;
278 if ( !strcmp(xbm_priv->id, "short" ) ) return S_SHORT ;
279 if ( !strcmp(xbm_priv->id, "unsigned") ) return S_UNSIGNED;
280 if ( !strcmp(xbm_priv->id, "signed" ) ) return S_SIGNED ;
281
282 if ( !isalnum(xbm_priv->id[0]) )
283 return S_ERROR_ID;
284
285 return S_ID;
286 }
287
288static SYM nextid(XBM_PRIV *xbm_priv)
289 {
290 int c, i;
291
292 if ( (c = skipit(xbm_priv)) == -1 )
293 return S_EOF;
294
295 i = 0;
296 do
297 xbm_priv->id[i++] = c;
298 while ( (c = nextchar(xbm_priv)) != -1 && !isspace(c) && c != '[' && i < MAX_ID );
299
300 xbm_priv->id[i] = '\0';
301
302 pushchar(xbm_priv, c);
303
304 return S_ID;
305 }
306/*...e*/
307
308/*...sxbm_qft:0:*/
309GBM_ERR xbm_qft(GBMFT *gbmft)
310 {
311 *gbmft = xbm_gbmft;
312 return GBM_ERR_OK;
313 }
314/*...e*/
315/*...sxbm_rhdr:0:*/
316GBM_ERR xbm_rhdr(char *fn, int fd, GBM *gbm, char *opt)
317 {
318 XBM_PRIV *xbm_priv = (XBM_PRIV *) gbm->priv;
319 SYM sym;
320
321 fn=fn; opt=opt; /* Suppress 'unref arg' compiler warnings */
322
323 xbm_priv->fd = fd;
324 xbm_priv->inx = 0;
325 xbm_priv->cnt = 0;
326
327 gbm->w = -1;
328 gbm->h = -1;
329 gbm->bpp = 1;
330
331 while ( (sym = nextsym(xbm_priv)) == S_DEFINE )
332 {
333 char *p;
334
335 if ( (sym = nextid(xbm_priv)) != S_ID )
336 return GBM_ERR_XBM_EXP_ID;
337 if ( (p = strrchr(xbm_priv->id, '_')) != NULL )
338 p++;
339 else
340 p = (char *) (xbm_priv->id);
341
342 if ( !strcmp(p, "width") )
343 {
344 if ( (sym = nextsym(xbm_priv)) != S_NUMBER )
345 return GBM_ERR_XBM_EXP_NUMBER;
346 gbm->w = xbm_priv->number;
347 }
348 else if ( !strcmp(p, "height") )
349 {
350 if ( (sym = nextsym(xbm_priv)) != S_NUMBER )
351 return GBM_ERR_XBM_EXP_NUMBER;
352 gbm->h = xbm_priv->number;
353 }
354 else
355 {
356 if ( (sym = nextsym(xbm_priv)) != S_NUMBER )
357 return GBM_ERR_XBM_EXP_NUMBER;
358 }
359
360 }
361
362 if ( gbm->w == -1 || gbm->h == -1 )
363 return GBM_ERR_BAD_SIZE;
364
365 if ( sym == S_STATIC )
366 sym = nextsym(xbm_priv);
367
368 if ( sym == S_EOF )
369 return GBM_ERR_XBM_UNEXP_EOF;
370
371 if ( sym == S_UNSIGNED )
372 sym = nextsym(xbm_priv);
373
374 if ( sym == S_SIGNED )
375 sym = nextsym(xbm_priv);
376
377 if ( sym == S_EOF )
378 return GBM_ERR_XBM_UNEXP_EOF;
379
380 switch ( sym )
381 {
382 case S_CHAR:
383 xbm_priv->size = 8;
384 break;
385 case S_SHORT:
386 xbm_priv->size = 16;
387 break;
388 default:
389 return GBM_ERR_XBM_EXP_CHAR;
390 }
391
392 if ( nextid(xbm_priv) != S_ID )
393 return GBM_ERR_XBM_EXP_ID;
394
395 if ( nextsym(xbm_priv) != S_LSQR )
396 return GBM_ERR_XBM_EXP_LSQR;
397
398 if ( nextsym(xbm_priv) != S_RSQR )
399 return GBM_ERR_XBM_EXP_RSQR;
400
401 if ( nextsym(xbm_priv) != S_EQUALS )
402 return GBM_ERR_XBM_EXP_EQUALS;
403
404 if ( nextsym(xbm_priv) != S_LCUR )
405 return GBM_ERR_XBM_EXP_LCUR;
406
407 return GBM_ERR_OK;
408 }
409/*...e*/
410/*...sxbm_rpal:0:*/
411GBM_ERR xbm_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
412 {
413 fd=fd; gbm=gbm; /* Suppress 'unref arg' compiler warnings */
414
415 gbmrgb[0].r = 0xff;
416 gbmrgb[0].g = 0xff;
417 gbmrgb[0].b = 0xff; /* White background */
418 gbmrgb[1].r = 0x00;
419 gbmrgb[1].g = 0x00;
420 gbmrgb[1].b = 0x00; /* Black background */
421 return GBM_ERR_OK;
422 }
423/*...e*/
424/*...sxbm_rdata:0:*/
425GBM_ERR xbm_rdata(int fd, GBM *gbm, byte *data)
426 {
427 XBM_PRIV *xbm_priv = (XBM_PRIV *) gbm->priv;
428 int stride = ( ( gbm->w * gbm->bpp + 31 ) / 32 ) * 4;
429 int x, y;
430 SYM sym;
431 BOOLEAN keep_going = TRUE;
432
433 fd=fd; /* Suppres 'unref arg' compiler warning */
434
435 memset(data, 0, gbm->h * stride);
436 data += ( (gbm->h - 1) * stride );
437
438 switch ( xbm_priv->size )
439 {
440/*...s8:16:*/
441case 8:
442 for ( y = gbm->h - 1; keep_going && y >= 0; y--, data -= stride )
443 for ( x = 0; keep_going && x < (int) ((unsigned)(gbm->w + 7) >> 3); x++ )
444 if ( (sym = nextsym(xbm_priv)) == S_RCUR )
445 keep_going = FALSE;
446 else if ( sym != S_NUMBER )
447 return GBM_ERR_XBM_EXP_NUMBER;
448 else
449 {
450 data[x] = rev[xbm_priv->number];
451
452 sym = nextsym(xbm_priv);
453 if ( sym == S_RCUR )
454 keep_going = FALSE;
455 else if ( sym != S_COMMA )
456 return GBM_ERR_XBM_EXP_COMMA;
457 }
458 break;
459/*...e*/
460/*...s16:16:*/
461case 16:
462 for ( y = gbm->h - 1; keep_going && y >= 0; y--, data -= stride )
463 for ( x = 0; keep_going && x < (int) ((unsigned)(gbm->w + 15) >> 4); x++ )
464 if ( (sym = nextsym(xbm_priv)) == S_RCUR )
465 keep_going = FALSE;
466 else if ( sym != S_NUMBER )
467 return GBM_ERR_XBM_EXP_NUMBER;
468 else
469 {
470 data[x * 2 ] = rev[ xbm_priv->number & 0xffU];
471 data[x * 2 + 1] = rev[(unsigned)xbm_priv->number >> 8 ];
472
473 sym = nextsym(xbm_priv);
474 if ( sym == S_RCUR )
475 keep_going = FALSE;
476 else if ( sym != S_COMMA )
477 return GBM_ERR_XBM_EXP_COMMA;
478 }
479 break;
480/*...e*/
481 }
482
483 if ( keep_going )
484 if ( nextsym(xbm_priv) != S_RCUR )
485 return GBM_ERR_XBM_EXP_RCUR;
486
487 if ( nextsym(xbm_priv) != S_SEMI )
488 return GBM_ERR_XBM_EXP_SEMI;
489
490 return GBM_ERR_OK;
491 }
492/*...e*/
493/*...sxbm_w:0:*/
494/*
495Write darkest colour as 1s, lightest colour with 0s.
496*/
497
498GBM_ERR xbm_w(char *fn, int fd, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, char *opt)
499 {
500 int stride = ((gbm->w * gbm->bpp + 31) / 32) * 4;
501 int x, y, col = 0;
502 char s[100+1], name[100+1], *dot, *p;
503 int k0, k1, xor;
504
505 opt=opt; /* Suppress 'unref arg' compiler warning */
506
507 /* Normally palette entry 0 brightest is usual */
508 /* If not reverse all the bits */
509
510 k0 = gbmrgb[0].r * 77 + gbmrgb[0].g * 150 + gbmrgb[0].b * 29;
511 k1 = gbmrgb[1].r * 77 + gbmrgb[1].g * 150 + gbmrgb[1].b * 29;
512
513 xor = ( k0 > k1 ) ? 0 : 0xff;
514
515 /* Make the name from the filename, without the extension */
516
517 strncpy(name, fn, 100);
518 if ( (dot = strrchr(name, '.')) != NULL )
519 *dot = '\0';
520
521 /* Nobble any potentially nasty characters */
522
523 if ( !isalpha(*name) )
524 *name = '_';
525 for ( p = name + 1; *p; p++ )
526 if ( !isalnum(*p) )
527 *p = '_';
528
529 sprintf(s, "#define %s_width %d\r\n" , name, gbm->w);
530 if ( (size_t) gbm_file_write(fd, s, strlen(s)) != strlen(s) )
531 return GBM_ERR_WRITE;
532 sprintf(s, "#define %s_height %d\r\n", name, gbm->h);
533 if ( (size_t) gbm_file_write(fd, s, strlen(s)) != strlen(s) )
534 return GBM_ERR_WRITE;
535 sprintf(s, "static char %s_bits[] = {\r\n", name);
536 if ( (size_t) gbm_file_write(fd, s, strlen(s)) != strlen(s) )
537 return GBM_ERR_WRITE;
538
539 data += (gbm->h - 1) * stride;
540 for ( y = gbm->h - 1; y >= 0; y--, data -= stride )
541 for ( x = 0; x < (int) ((unsigned)(gbm->w + 7) >> 3); x++ )
542 {
543 sprintf(s, "0x%02x,", rev[data[x]] ^ xor);
544 col += 5;
545 if ( col > 70 )
546 {
547 strcat(s, "\r\n");
548 col = 0;
549 }
550 if ( (size_t) gbm_file_write(fd, s, strlen(s)) != strlen(s) )
551 return GBM_ERR_WRITE;
552 }
553
554 if ( col )
555 {
556 if ( gbm_file_write(fd, "\r\n", 2) != 2 )
557 return GBM_ERR_WRITE;
558 }
559
560 if ( gbm_file_write(fd, "};\r\n", 4) != 4 )
561 return GBM_ERR_WRITE;
562
563 return GBM_ERR_OK;
564 }
565/*...e*/
566/*...sxbm_err:0:*/
567const char *xbm_err(GBM_ERR rc)
568 {
569 switch ( (int) rc )
570 {
571 case GBM_ERR_XBM_EXP_ID:
572 return "expected identifier";
573 case GBM_ERR_XBM_UNEXP_EOF:
574 return "unexpected end of file";
575 case GBM_ERR_XBM_EXP_CHAR:
576 return "expected char or short";
577 case GBM_ERR_XBM_EXP_LSQR:
578 return "expected[";
579 case GBM_ERR_XBM_EXP_RSQR:
580 return "expected ]";
581 case GBM_ERR_XBM_EXP_EQUALS:
582 return "expected =";
583 case GBM_ERR_XBM_EXP_LCUR:
584 return "expected {";
585 case GBM_ERR_XBM_EXP_RCUR:
586 return "expected }";
587 case GBM_ERR_XBM_EXP_COMMA:
588 return "expected ,";
589 case GBM_ERR_XBM_EXP_NUMBER:
590 return "expected number";
591 case GBM_ERR_XBM_EXP_SEMI:
592 return "expected ;";
593 }
594 return NULL;
595 }
596/*...e*/
Note: See TracBrowser for help on using the repository browser.