1 /* $Header: /home/yav/xpx/RCS/convert.c,v 1.40 1996/04/24 23:08:27 yav Exp $
2  * convert image data
3  * written by yav (UHD98984@pcvan.or.jp)
4  */
5 
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 
9 #include "headers.h"
10 #include "xpx.h"
11 #include "work.h"
12 #include "infodef.h"
13 #define PUBLIC_CONVERT_C
14 #include "extern.h"
15 
16 char rcsid_convert[] = "$Id: convert.c,v 1.40 1996/04/24 23:08:27 yav Exp $";
17 static unsigned char rbittbl[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
18 static char tilemask[8][8];
19 
init_tilemask()20 int init_tilemask()
21 {
22   return 0;
23 }
24 
set_tilemask(p)25 int set_tilemask(p)
26      char *p;
27 {
28   memcpy(tilemask, p, sizeof(tilemask));
29   return 0;
30 }
31 
imgupdate(w,h)32 void imgupdate(w, h)
33      int w;
34      int h;
35 {
36   set_image_size(w, h);
37   image_update_all();
38 }
39 
40 /* return pnm type number */
read_pnm_header(fp,data,colorhints,nhints)41 int read_pnm_header(fp, data, colorhints, nhints)
42      FILE *fp;
43      int *data;
44      COL *colorhints;
45      int *nhints;
46 {
47   int i, result, r, g, b;
48   int datan, maxcol, datan0;
49   char buf[256], *p;
50 
51   if (fgets(buf, sizeof(buf), fp) == NULL)
52     return 0;
53   if (buf[0] != 'P')
54     return 0;			/* Not pnm file */
55   switch (buf[1]) {
56   case '1':
57     result = 1;
58     datan0 = 2;
59     data[2] = 1;
60     break;
61   case '2':
62     result = 2;
63     datan0 = 3;
64     break;
65   case '3':
66     result = 3;
67     datan0 = 3;
68     break;
69   case '4':
70     result = 4;
71     datan0 = 2;
72     data[2] = 1;
73     break;
74   case '5':
75     result = 5;
76     datan0 = 3;
77     break;
78   case '6':
79     result = 6;
80     datan0 = 3;
81     break;
82   default:
83     return 0;			/* Not supported pnm file */
84   }
85   maxcol = -1;
86   datan = 0;
87   while (datan < datan0 && fgets(buf, sizeof(buf), fp) != NULL) {
88     if (buf[0] == '#') {
89       if (colorhints != NULL && nhints != NULL) {
90 	if (sscanf(buf, "# color:%d %d %d %d", &i, &r, &g, &b) == 4) {
91 	  if (i < *nhints) {
92 	    (colorhints+i)->rgb.red = r;
93 	    (colorhints+i)->rgb.green = g;
94 	    (colorhints+i)->rgb.blue = b;
95 	    if (maxcol < i)
96 	      maxcol = i;
97 	  }
98 	}
99       }
100     } else {
101       for (p = buf; (i = strtol(p, &p, 10)) != 0 && datan < 3; datan++)
102 	data[datan] = i;
103     }
104   }
105   if (colorhints != NULL && nhints != NULL)
106     *nhints = maxcol+1;
107   return result;
108 }
109 
110 static unsigned char bitpos;
111 static unsigned char rddata;
112 static int pnmmaxval;
113 
read_pnm_pixels(fp,t,cp,n)114 int read_pnm_pixels(fp, t, cp, n)
115      FILE *fp;
116      int t;
117      COL *cp;
118      int n;
119 {
120   int i, x, rgbsw;
121   int c;
122   unsigned char *p, buf[256];
123 
124   switch(t) {
125   case 1:			/* P1 pbm ascii */
126   case 2:			/* P2 pgm ascii */
127   case 3:			/* P3 ppm ascii */
128     x = rgbsw = 0;
129     while (x < n) {
130       i = 0;
131       p = buf;
132       for (;;) {
133 	c = fgetc(fp);
134 	if (c == EOF)
135 	  return x;
136 	else if (c == '\n')
137 	  break;
138 	else if (c == ' '||c == '\t') {
139 	  if (i)
140 	    break;
141 	} else {
142 	  *p++ = c;
143 	  i = 1;
144 	}
145       }
146       *p = '\0';
147       i = strtol((char *)buf, (char **)&p, 10);
148       if (p == buf)
149 	continue;
150       i = (i * 255) / pnmmaxval;
151       switch(t) {
152       case 3:
153 	switch(rgbsw) {
154 	case 0:
155 	  cp->rgb.red = i;
156 	  break;
157 	case 1:
158 	  cp->rgb.green = i;
159 	  break;
160 	case 2:
161 	  cp->rgb.blue = i;
162 	  break;
163 	}
164 	if (++rgbsw >= 3) {
165 	  cp->rgb.padding = 0;
166 	  cp++;
167 	  rgbsw = 0;
168 	  x++;
169 	}
170 	break;
171       case 1:
172       case 2:
173 	cp->rgb.red = cp->rgb.green = cp->rgb.blue = i;
174 	cp->rgb.padding = 0;
175 	cp++;
176 	x++;
177 	break;
178       }
179     }
180     return x;
181   case 4:			/* P4 pbm raw */
182     while (n--) {
183       if (bitpos == 0x01) {
184 	i = fgetc(fp);
185 	if (i == EOF)
186 	  return 0;
187 	rddata = i;
188 	bitpos = 0x80;
189       } else {
190 	bitpos >>= 1;
191       }
192       cp->rgb.red = cp->rgb.green = cp->rgb.blue = rddata & bitpos ? 0 : 255;
193       cp++;
194     }
195     return 1;
196   case 5:			/* P5 pgm raw */
197     while (n) {
198       i = sizeof(buf) > n ? n : sizeof(buf);
199       if (!fread(buf, i, 1, fp))
200 	return 0;
201       p = buf;
202       x = i;
203       while (x--) {
204 	cp->rgb.red = cp->rgb.green = cp->rgb.blue = (*p++ * 255) / pnmmaxval;
205 	cp->rgb.padding = 0;
206 	cp++;
207       }
208       n -= i;
209     }
210     return 1;
211   case 6:			/* P6 ppm raw */
212     while (n) {
213       i = sizeof(buf)/3 > n ? n : sizeof(buf)/3;
214       if (!fread(buf, i*3, 1, fp))
215 	return 0;
216       p = buf;
217       x = i;
218       while (x--) {
219 	cp->rgb.red = (*p++ * 255) / pnmmaxval;
220 	cp->rgb.green = (*p++ * 255) / pnmmaxval;
221 	cp->rgb.blue = (*p++ * 255) / pnmmaxval;
222 	cp->rgb.padding = 0;
223 	cp++;
224       }
225       n -= i;
226     }
227     return 1;
228   default:
229     /* unknown pnm type ??? */
230     return 0;
231   }
232   /* NOT REACHED */
233 }
234 
235 static COL lastcol;
236 static int lastcol_pixel;
237 
color_pixel(col)238 int color_pixel(col)
239      COL *col;
240 {
241   int i;
242   COL *tbl;
243 
244   if (lastcol_pixel >= 0) {
245     if (memcmp(&lastcol.rgb, &col->rgb, 3) == 0)
246       return lastcol_pixel;
247   }
248   tbl = color_buf;
249   for (i = 0; i < MAXCOLSET*MAXPALSET; i++) {
250     if (memcmp(&col->rgb, &tbl->rgb, 3) == 0 &&
251 	(coltbl[i] & (CM_ALLOCED|CM_REQUEST))) {
252       lastcol = *col;
253       return lastcol_pixel = i;
254     }
255     tbl++;
256   }
257   return -1;
258 }
259 
260 typedef struct {
261   int i;
262   int n;
263   int pn;
264 } CLN;
265 
colcnt(p,len,ctbl,ntbl,n,itbl)266 int colcnt(p, len, ctbl, ntbl, n, itbl)
267      COL *p;
268      int len;
269      COL *ctbl;
270      CLN *ntbl;
271      int n;
272      unsigned char *itbl;
273 {
274   int i, x, max;
275 
276   max = 0;
277   for (x = 0; x < len; x++) {
278     i = 0;
279     for (;;) {
280       if (i >= max) {
281 	if (++max > n)
282 	  return -1;
283 	*(ctbl+i) = *p;
284       }
285       if (memcmp(&(ctbl+i)->rgb, &p->rgb, 3) == 0)
286 	break;
287       i++;
288     }
289     *itbl++ = i;
290     ++((ntbl+i)->n);
291     p++;
292   }
293   return max;
294 }
295 
ncolcmp(p1,p2)296 int ncolcmp(p1, p2)
297      CLN *p1;
298      CLN *p2;
299 {
300   return p2->n - p1->n;
301 }
302 
icolcmp(p1,p2)303 int icolcmp(p1, p2)
304      CLN *p1;
305      CLN *p2;
306 {
307   return p1->i - p2->i;
308 }
309 
slow_convert(px,w,h)310 void slow_convert(px, w, h)
311      COL *px;
312      int w;
313      int h;
314 {
315   int i, n, len, x, y;
316   unsigned char *itbl, *ip;
317   COL ctbl[256];
318   CLN ntbl[256];
319 
320   if (debug_mode)
321     fprintf(stderr, "slow_convert %dx%d\n", w, h);
322   len = w*h;
323   itbl = (unsigned char *)malloc(len);
324   for (i = 256; i; --i) {
325     bzero(ctbl, sizeof(*ctbl)*i);
326     bzero(ntbl, sizeof(*ntbl)*i);
327     n = colcnt(px, len, ctbl, ntbl, i, itbl);
328     if (n >= 0)
329       break;
330   }
331   message("phase-1 %d colors.\n", n);
332   for (i = 0; i < 256; i++)
333     ntbl[i].i = i;
334   qsort(ntbl, n, sizeof(*ntbl), ncolcmp);
335   for (i = 0; i < n; i++)
336     ntbl[i].pn = i;
337   for (;;) {
338     free_color_all();
339     message("try %d colors.\n", n);
340     for (i = 0; i < n; i++)
341       request_color2(i, ctbl+ntbl[i].i);
342     i = get_requested_colors();
343     message("get %d/%d request colors.\n", i, n);
344     if (i == n)
345       break;
346     n -= 16;
347     if (n < 0) {
348       message("!too few color!\n");
349       free(itbl);
350       return;
351     }
352   }
353   qsort(ntbl, n, sizeof(*ntbl), icolcmp);
354   ip = itbl;
355   for (y = 0; y < h; y++) {
356     for (x = 0; x < w; x++) {
357       *(imgdata+y*imgmaxw+x) = ntbl[*ip++].pn;
358     }
359   }
360   free(itbl);
361 }
362 
363 /* read portable bitmap/graymap/pixmap */
rd_pnm(fp)364 int rd_pnm(fp)
365      FILE *fp;
366 {
367   int c, i, n, f, x, y, pnmtype;
368   int data[3], w, h;
369   int colcnt;
370   COL *px0, *px, *px1;
371 
372   colcnt = MAXPALSET*MAXCOLSET;
373   pnmtype = read_pnm_header(fp, data, color_buf, &colcnt);
374   if (pnmtype == 0)
375     return 1;
376   if (pnmtype == 1||pnmtype == 4)
377     imgfiledepth = 1;
378   if (debug_mode) {
379     fprintf(stderr, "rd_pnm: width %d, height %d max %d\n",
380 	    data[0], data[1], data[2]);
381     fprintf(stderr, "rd_pnm: %d color hints\n", colcnt);
382   }
383 
384   free_color_all();
385   /* magtoppm commented color information set */
386   get_color(color_buf, colcnt);
387 
388   w = data[0];
389   h = data[1];
390   pnmmaxval = data[2];
391   if (w > imgmaxw) {
392     w = imgmaxw;
393     message("!\nwidth %d trancate to %d.\n", data[0], w);
394   }
395   if (h > imgmaxh) {
396     h = imgmaxh;
397     message("!\nheight %d trancate to %d.\n", data[1], h);
398   }
399   px = (COL *)malloc(sizeof(*px)*w);
400   if (!quick_convert)
401     px1 = px0 = (COL *)malloc(sizeof(*px0)*w*h);
402   lastcol_pixel = -1;
403   for (y = 0; y < h; y++) {
404     f = 1;
405     bitpos = 0x01;
406     for (n = data[0]; n; n -= i) {
407       i = n > w ? w : n;
408       read_pnm_pixels(fp, pnmtype, px, i);
409       if (!f)
410 	continue;		/* skip x over pixels */
411       if (quick_convert) {
412 	if (colcnt && pnmtype == 5) {
413 	  /* color infomation contained portable graymap */
414 	  for (x = 0; x < i; x++)
415 	    *(imgdata+y*imgmaxw+x) = (px+x)->rgb.red;
416 	} else {
417 	  for (x = 0; x < i; x++) {
418 	    c = color_pixel(px+x);
419 	    if (c < 0)
420 	      c = request_color(px+x);
421 	    *(imgdata+y*imgmaxw+x) = c;
422 	  }
423 	}
424       } else {
425 	memcpy(px1, px, sizeof(*px)*i);
426 	px1 += i;
427       }
428       f = 0;
429     }
430   }
431   if (!quick_convert) {
432     slow_convert(px0, w, h);
433     free(px0);
434   } else {
435     get_requested_colors();
436   }
437   free(px);
438   imgupdate(w, h);
439   return 0;
440 }
441 
442 static char kiss_magic_number[] = "KiSS";
443 
444 /* read KISS kcf */
rd_kcf(fp)445 int rd_kcf(fp)
446      FILE *fp;
447 {
448   int i, s, bpc, cc, col, set, preload;
449   COL *cp;
450   unsigned char *p, buf[4096];
451 
452   preload = strlen(kiss_magic_number);
453   if (!fread(buf, preload, 1, fp))
454     return 1;
455   if (strncmp(buf, kiss_magic_number, preload) == 0) {
456     /* read new style kcf header section */
457     if (!fread(buf+preload, 32-preload, 1, fp))
458       return 1;
459     /* check color file mark */
460     if (buf[4] != 0x10)
461       return 1;
462     bpc = buf[5];
463     col = buf[8]|(buf[9]<<8);
464     set = buf[10]|(buf[11]<<8);
465     preload = 0;
466     infomenu[INFOMENU_GSKCF].mode |= MenuModeMaskOn;
467   } else {
468     /* old style kcf */
469     bpc = 12;
470     col = 16;
471     set = 10;
472     infomenu[INFOMENU_GSKCF].mode &= ~MenuModeMaskOn;
473   }
474   redraw_window(infomenu[INFOMENU_GSKCF].win);
475   cp = color_buf;
476   cc = ((bpc+7)>>3)*col;
477   for (s = 0; s < set; s++) {
478     if (!fread(buf+preload, cc-preload, 1, fp))
479       return 1;
480     p = buf;
481     for (i = 0; i < col; i++) {
482       if (bpc == 12) {
483 	cp->rgb.red = (*p&0xf0)|(*p>>4);
484 	cp->rgb.blue = (*p&0x0f)|((*p&0x0f)<<4);
485 	p++;
486 	cp->rgb.green = (*p&0x0f)|((*p&0x0f)<<4);
487 	p++;
488       } else {
489 	cp->rgb.red = *p++;
490 	cp->rgb.green = *p++;
491 	cp->rgb.blue = *p++;
492       }
493       cp++;
494     }
495     preload = 0;
496   }
497   free_color();
498   get_color(color_buf+16*current_pal, col);
499   image_update_col();
500   return 0;
501 }
502 
503 /* write KISS kcf */
wr_kcf(fp)504 int wr_kcf(fp)
505      FILE *fp;
506 {
507   int i, s, bpc, col, set, cc;
508   COL *cp;
509   unsigned char *p, buf[4096];
510 
511   /* old style kcf spec set */
512   bpc = 12;			/* red:4 blue:4 green:4 = 12bits/color */
513   col = 16;
514   set = 10;
515   if (infomenu[INFOMENU_GSKCF].mode & MenuModeMaskOn) {
516     bpc = 24;			/* red:8 green:8 blue:8 = 24bits/color */
517     bzero(buf, 32);
518     memcpy(buf, kiss_magic_number, strlen(kiss_magic_number));
519     buf[4] = 0x10;		/* color file mark */
520     buf[5] = bpc;
521     buf[8] = col;
522     buf[9] = col>>8;
523     buf[10] = set;
524     buf[11] = set>>8;
525     if (!fwrite(buf, 32, 1, fp))
526       return 1;
527   }
528   cp = color_buf;
529   cc = ((bpc+7)>>3)*col;
530   for (s = 0; s < set; s++) {
531     p = buf;
532     for (i = 0; i < col; i++) {
533       if (bpc == 12) {
534 	*p++ = (cp->rgb.red & 0xf0)|(cp->rgb.blue >> 4);
535 	*p++ = cp->rgb.green >> 4;
536       } else {
537 	*p++ = cp->rgb.red;
538 	*p++ = cp->rgb.green;
539 	*p++ = cp->rgb.blue;
540       }
541       cp++;
542     }
543     if (!fwrite(buf, cc, 1, fp))
544       return 1;
545   }
546   return 0;
547 }
548 
549 /* read KISS cel */
rd_cel(fp)550 int rd_cel(fp)
551      FILE *fp;
552 {
553   int c, x, y, w, h, preload, bpp;
554   int dataw, datah;
555   int ofsx, ofsy;
556   unsigned char buf[4096];
557 
558   preload = strlen(kiss_magic_number);
559   if (!fread(buf, preload, 1, fp))
560     return 1;
561   if (strncmp(buf, kiss_magic_number, preload) == 0) {
562     /* read new style cel file header section */
563     if (!fread(buf+preload, 32-preload, 1, fp))
564       return 1;
565     /* check cel file mark */
566     if (buf[4] != 0x20)
567       return 1;
568     bpp = buf[5];
569     w = buf[8]|(buf[9]<<8);
570     h = buf[10]|(buf[11]<<8);
571     ofsx = buf[12]|(buf[13]<<8);
572     ofsy = buf[14]|(buf[15]<<8);
573     infomenu[INFOMENU_GSCEL].mode |= MenuModeMaskOn;
574   } else {
575     bpp = 4;
576     w = buf[0]|(buf[1]<<8);
577     h = buf[2]|(buf[3]<<8);
578     ofsx = ofsy = 0;
579     infomenu[INFOMENU_GSCEL].mode &= ~MenuModeMaskOn;
580   }
581   redraw_window(infomenu[INFOMENU_GSCEL].win);
582   imgfiledepth = bpp;
583   dataw = w;
584   datah = h;
585   if (ofsx+w > imgmaxw) {
586     w = imgmaxw-ofsx;
587     message("!\nwidth %d trancate to %d.\n", dataw+ofsx, w+ofsx);
588   }
589   if (ofsy+h > imgmaxh) {
590     h = imgmaxh-ofsy;
591     message("!\nheight %d trancate to %d.\n", datah+ofsy, h+ofsy);
592   }
593   for (y = 0; y < ofsy; y++) {
594     for (x = 0; x < ofsx+w; x++) {
595       *(imgdata+y*imgmaxw+x) = 0;
596     }
597   }
598   for (y = ofsy; y < ofsy+h; y++) {
599     if (!fread(buf, bpp==4?((dataw+1)>>1):dataw, 1, fp))
600       return 1;
601     for (x = 0; x < ofsx; x++)
602       *(imgdata+y*imgmaxw+x) = 0;
603     for (x = 0; x < w; x++) {
604       if (bpp == 4) {
605 	c = buf[x>>1];
606 	if ((x & 1) == 0)
607 	  c >>= 4;
608 	else
609 	  c &= 0x0f;
610       } else {
611 	c = buf[x];
612       }
613       *(imgdata+y*imgmaxw+ofsx+x) = c;
614     }
615   }
616   hotspotx = ofsx;
617   hotspoty = ofsy;
618   imgupdate(ofsx+w, ofsy+h);
619   return 0;
620 }
621 
get_celofs_y()622 int get_celofs_y()
623 {
624   int x, y;
625 
626   for (y = 0; y < imgfileh; y++) {
627     for (x = 0; x < imgfilew; x++) {
628       if (*(imgdata+y*imgmaxw+x) != 0)
629 	return y;
630     }
631   }
632   return 0;
633 }
634 
get_celofs_x()635 int get_celofs_x()
636 {
637   int x, y;
638 
639   for (x = 0; x < imgfilew; x++) {
640     for (y = 0; y < imgfileh; y++) {
641       if (*(imgdata+y*imgmaxw+x) != 0)
642 	return x;
643     }
644   }
645   return 0;
646 }
647 
648 /* write KISS cel */
wr_cel(fp)649 int wr_cel(fp)
650      FILE *fp;
651 {
652   int c, x, y, w, h, bpp, headersize;
653   unsigned char buf[4096];
654 
655   w = imgfilew;
656   h = imgfileh;
657   bpp = 4;			/* 4bits/pixel */
658   if (infomenu[INFOMENU_GSCEL].mode & MenuModeMaskOn) {
659     headersize = 32;
660     bzero(buf, headersize);
661     memcpy(buf, kiss_magic_number, strlen(kiss_magic_number));
662     hotspotx = get_celofs_x();
663     hotspoty = get_celofs_y();
664     w -= hotspotx;
665     h -= hotspoty;
666     buf[4] = 0x20;		/* cel file mark */
667     buf[5] = bpp;
668     buf[8] = w;
669     buf[9] = w >> 8;
670     buf[10] = h;
671     buf[11] = h >> 8;
672     buf[12] = hotspotx;
673     buf[13] = hotspotx >> 8;
674     buf[14] = hotspoty;
675     buf[15] = hotspoty >> 8;
676   } else {
677     headersize = 4;
678     hotspotx = hotspoty = 0;
679     buf[0] = w;
680     buf[1] = w >> 8;
681     buf[2] = h;
682     buf[3] = h >> 8;
683   }
684   if (!fwrite(buf, headersize, 1, fp))
685     return 1;
686   for (y = hotspoty; y < hotspoty+h; y++) {
687     for (x = 0; x < w; x++) {
688       c = *(imgdata+y*imgmaxw+hotspotx+x);
689       if (bpp == 4) {
690 	if ((x & 1) == 0)
691 	  buf[x>>1] = c<<4;
692 	else
693 	  buf[x>>1] |= c;
694       } else {
695 	buf[x] = c;
696       }
697     }
698     if (!fwrite(buf, bpp==4?((w+1)>>1):w, 1, fp))
699       return 1;
700   }
701   return 0;
702 }
703 
704 /* write portable pixmap */
wr_ppm(fp)705 int wr_ppm(fp)
706      FILE *fp;
707 {
708   int i, x, y;
709   COL *cp;
710   unsigned char c, buf[3];
711 
712   fprintf(fp, "P6\n");
713   fprintf(fp, "#Saved by %s %s\n", myname, xpx_version);
714   /* color information */
715   cp = color_buf;
716   for (i = 0; i < alloced_color; i++) {
717     fprintf(fp, "# color:%3d %3d %3d %3d\n", i,
718 	    cp->rgb.red, cp->rgb.green, cp->rgb.blue);
719     cp++;
720   }
721   fprintf(fp, "%d %d\n", imgfilew, imgfileh);
722   fprintf(fp, "255\n");
723 
724   for (y = 0; y < imgfileh; y++) {
725     for (x = 0; x < imgfilew; x++) {
726       c = *(imgdata+y*imgmaxw+x);
727       buf[0] = color_buf[c].rgb.red;
728       buf[1] = color_buf[c].rgb.green;
729       buf[2] = color_buf[c].rgb.blue;
730       if (!fwrite(buf, 3, 1, fp))
731 	return 1;
732     }
733   }
734   return 0;
735 }
736 
write_xbm_out(fp,data,datalen,end)737 int write_xbm_out(fp, data, datalen, end)
738      FILE *fp;
739      unsigned char *data;
740      int datalen;
741      int end;
742 {
743   int i;
744   char *p;
745   char buf[256];
746 
747   strcpy(buf, "  ");
748   p = buf+2;
749   for (i = 0; i < datalen; i++) {
750     sprintf(p, " 0x%02x,", *data++);
751     p += strlen(p);
752   }
753   if (end)
754     strcpy(p-1, "};");
755   strcat(buf, "\n");
756   return fputs(buf, fp);
757 }
758 
759 /* write X11 bitmap */
wr_xbm(fp,name)760 int wr_xbm(fp, name)
761      FILE *fp;
762      char *name;
763 {
764   int i, x, y, w, h;
765   int outcount;
766   unsigned char c;
767   unsigned char outbuf[12];
768   char namebuf[MAXPATH], *p;
769 
770   strcpy(namebuf, name);
771   p = basefilename(namebuf);
772   w = imgfilew;
773   h = imgfileh;
774   fprintf(fp, "#define %s_width %d\n", p, w);
775   fprintf(fp, "#define %s_height %d\n", p, h);
776   if (hotspotx >= 0 && hotspoty >= 0) {
777     fprintf(fp, "#define %s_x_hot %d\n", p, hotspotx);
778     fprintf(fp, "#define %s_y_hot %d\n", p, hotspoty);
779   }
780   fprintf(fp, "static unsigned char %s_bits[] = {\n", p);
781   outcount = 0;
782   for (y = 0; y < h; y++) {
783     for (x = 0; x < w; x += 8) {
784       c = 0;
785       for (i = 0; i < 8; i++) {
786 	if ((x + i < w)&& *(imgdata+y*imgmaxw+x+i))
787 	  c |= rbittbl[i];
788       }
789       if (outcount >= sizeof(outbuf)) {
790 	write_xbm_out(fp, outbuf, outcount, 0);
791 	outcount = 0;
792       }
793       outbuf[outcount++] = c;
794     }
795   }
796   write_xbm_out(fp, outbuf, outcount, 1);
797   return 0;
798 }
799 
strcmp_tail(p,tail)800 int strcmp_tail(p, tail)
801      char *p;
802      char *tail;
803 {
804   int pl, tl;
805 
806   tl = strlen(tail);
807   pl = strlen(p);
808   if (pl < tl)
809     return 1;
810   return strcmp(p+pl-tl, tail);
811 }
812 
813 /* read X11 bitmap */
rd_xbm(fp)814 int rd_xbm(fp)
815      FILE *fp;
816 {
817   int i, x, y, w, h, c, hotx, hoty;
818   char buf[1024], *p;
819   char namebuf[MAXPATH];
820 
821   w = h = 0;
822   hotx = hoty = -1;
823   while (fgets(buf, sizeof(buf), fp) != NULL) {
824     if (strncmp(buf, "static", 6) == 0||
825 	strncmp(buf, "unsigned", 8) == 0||
826 	strncmp(buf, "char", 4) == 0)
827       break;
828     if (sscanf(buf, "#define %s %d", namebuf, &c) == 2) {
829       if (strcmp_tail(namebuf, "width") == 0)
830 	w = c;
831       else if (strcmp_tail(namebuf, "height") == 0)
832 	h = c;
833       else if (strcmp_tail(namebuf, "x_hot") == 0)
834 	hotx = c;
835       else if (strcmp_tail(namebuf, "y_hot") == 0)
836 	hoty = c;
837     }
838   }
839   if (!w || !h)
840     return 1;
841   y = x = 0;
842   p = buf;
843   *p = '\0';
844   for (;;) {
845     while (*p && (*p == ' ' || *p == '\t' || *p == ','))
846       p++;
847     if (*p == '\0' || *p == '\n') {
848       if (fgets(buf, sizeof(buf), fp) == NULL)
849 	break;
850       p = buf;
851     }
852     if (sscanf(p, "0x%02x", &c)) {
853       p += 4;
854       for (i = 0; i < 8; i++) {
855 	if (x+i < w)
856 	  *(imgdata+y*imgmaxw+x+i) = ((c & rbittbl[i]) ? 1 : 0);
857       }
858       x += 8;
859       if (x >= w) {
860 	if (++y >= h)
861 	  break;
862 	x = 0;
863       }
864     } else {
865       p++;
866     }
867   }
868   imgfiledepth = 1;
869   hotspotx = hotx;
870   hotspoty = hoty;
871   imgupdate(w, h);
872   return 0;
873 }
874 
875 /* set XImage from imgdata */
setpixel_sub2(x0,y0,pixel)876 void setpixel_sub2(x0, y0, pixel)
877      int x0;
878      int y0;
879      unsigned long pixel;
880 {
881   int x, y, x1, y1;
882 
883   x0 *= zoomfactor;
884   y0 *= zoomfactor;
885   x1 = x0+zoomfactor;
886   y1 = y0+zoomfactor;
887   for (y = y0; y < y1; y++)
888     for (x = x0; x < x1; x++)
889       XPutPixel(img, x, y, pixel);
890 }
891 
892 /* set XImage from imgdata */
setpixel_sub(x0,y0,pixel)893 void setpixel_sub(x0, y0, pixel)
894      int x0;
895      int y0;
896      unsigned long pixel;
897 {
898   int x, y, x1, y1;
899 
900   if (vimg != NULL)
901     XPutPixel(vimg, x0, y0,  pixel);
902   x0 *= zoomfactor;
903   y0 *= zoomfactor;
904   x1 = x0+zoomfactor;
905   y1 = y0+zoomfactor;
906   for (y = y0; y < y1; y++)
907     for (x = x0; x < x1; x++)
908       XPutPixel(img, x, y, pixel);
909 }
910 
911 /* set view image */
912 #define setpixel_subv(x0,y0,px) XPutPixel(vimg,(x0),(y0),(px))
913 
setpixelcolor(x,y,col)914 void setpixelcolor(x, y, col)
915      int x;
916      int y;
917      int col;
918 {
919   unsigned char *p;
920 
921   /* check masked color */
922   p = imgdata+y*imgmaxw+x;
923   if (!*(colmask + current_pal*MAXCOLSET + *p) && tilemask[y&7][x&7]) {
924     *p = col;
925     setpixel_sub2(x, y, pixtbl[col]);
926     if (vimg != NULL)
927       setpixel_subv(x, y, pixtbl[col]);
928   }
929 }
930 
gen_image_subv(x0,y0,w,h)931 void gen_image_subv(x0, y0, w, h)
932      int x0;
933      int y0;
934      int w;
935      int h;
936 {
937   int x, y;
938   unsigned char *ip;
939 
940   for (y = y0; y < y0+h; y++) {
941     ip = imgdata+y*imgmaxw+x0;
942     for (x = x0; x < x0+w; x++) {
943       setpixel_subv(x, y, pixtbl[*ip++]);
944     }
945   }
946 }
947 
948 /* set XImage from imgdata */
gen_image_sub(x0,y0,w,h)949 void gen_image_sub(x0, y0, w, h)
950      int x0;
951      int y0;
952      int w;
953      int h;
954 {
955   int x, y, xs, ys, xe, ye, zx, zy;
956   unsigned char *ip;
957   unsigned char pix;
958 
959   xs = x0 * zoomfactor;
960   ys = y0 * zoomfactor;
961   xe = xs + w * zoomfactor;
962   ye = ys + h * zoomfactor;
963   for (y = ys; y < ye; y += zoomfactor) {
964     ip = imgdata+(y/zoomfactor)*imgmaxw+x0;
965     for (x = xs; x < xe; x += zoomfactor) {
966       pix = pixtbl[*ip++];
967       for (zy = 0; zy < zoomfactor; zy++)
968 	for (zx = 0; zx < zoomfactor; zx++)
969 	  XPutPixel(img, x+zx, y+zy, pix);
970     }
971   }
972 }
973 
update_area(x,y,w,h)974 void update_area(x, y, w, h)
975      int x;
976      int y;
977      int w;
978      int h;
979 {
980   gen_image_sub(x, y, w, h);
981   if (vimg != NULL)
982     gen_image_subv(x, y, w, h);
983 }
984 
fill_area2(dstx,dsty,w,h,c)985 void fill_area2(dstx, dsty, w, h, c)
986      int dstx;
987      int dsty;
988      int w;
989      int h;
990      int c;
991 {
992   int x, y, xe, ye;
993   unsigned char *p;
994   char *mp;
995 
996   mp = colmask + current_pal*MAXCOLSET;
997   xe = dstx + w;
998   ye = dsty + h;
999   for (y = dsty; y < ye; y++) {
1000     p = imgdata+y*imgmaxw+dstx;
1001     for (x = dstx; x < xe; x++) {
1002       if (!*(mp+*p))
1003 	*p = c;
1004       p++;
1005     }
1006   }
1007   update_area(dstx, dsty, w, h);
1008 }
1009 
fill_area(dstx,dsty,w,h,c)1010 void fill_area(dstx, dsty, w, h, c)
1011      int dstx;
1012      int dsty;
1013      int w;
1014      int h;
1015      int c;
1016 {
1017   int x, y, xe, ye;
1018   unsigned char *p;
1019   char *mp;
1020 
1021   mp = colmask + current_pal*MAXCOLSET;
1022   xe = dstx + w;
1023   ye = dsty + h;
1024   for (y = dsty; y < ye; y++) {
1025     p = imgdata+y*imgmaxw+dstx;
1026     for (x = dstx; x < xe; x++) {
1027       if (!*(mp+*p) && tilemask[y&7][x&7])
1028 	*p = c;
1029       p++;
1030     }
1031   }
1032   update_area(dstx, dsty, w, h);
1033 }
1034 
copy_area(dstx,dsty,srcx,srcy,w,h)1035 void copy_area(dstx, dsty, srcx, srcy, w, h)
1036      int dstx;
1037      int dsty;
1038      int srcx;
1039      int srcy;
1040      int w;
1041      int h;
1042 {
1043   int x, y;
1044   int lastnocopypixel;
1045   unsigned char *srcp, *dstp;
1046   char *mp;
1047 
1048   lastnocopypixel = nocopypixel;
1049   if (!nocopypixel_mode)
1050     nocopypixel = -1;
1051   mp = colmask+current_pal*MAXPALSET;
1052   if (dsty*imgmaxw+dstx > srcy*imgmaxw+srcx) {
1053     for (y = h-1; y >= 0; y--) {
1054       dstp = imgdata+(dsty+y)*imgmaxw+dstx;
1055       srcp = imgdata+(srcy+y)*imgmaxw+srcx;
1056       for (x = w-1; x >= 0; x--) {
1057 	if (!*(mp+*(dstp+x)) && *(srcp+x) != nocopypixel)
1058 	  *(dstp+x) = *(srcp+x);
1059       }
1060     }
1061   } else {
1062     for (y = 0; y < h; y++) {
1063       dstp = imgdata+(dsty+y)*imgmaxw+dstx;
1064       srcp = imgdata+(srcy+y)*imgmaxw+srcx;
1065       for (x = 0; x < w; x++) {
1066 	if (!*(mp+*(dstp+x)) && *(srcp+x) != nocopypixel)
1067 	  *(dstp+x) = *(srcp+x);
1068       }
1069     }
1070   }
1071   update_area(dstx, dsty, w, h);
1072   nocopypixel = lastnocopypixel;
1073 }
1074 
1075 
gen_image_col(x0,y0,w,h)1076 void gen_image_col(x0, y0, w, h)
1077      int x0;
1078      int y0;
1079      int w;
1080      int h;
1081 {
1082   int x, y;
1083   unsigned char *ip;
1084 
1085   for (y = y0; y < y0+h; y++) {
1086     ip = imgdata+y*imgmaxw+x0;
1087     for (x = x0; x < x0+w; x++) {
1088       if (coltbl[*ip] & CM_UPDATING) {
1089 	coltbl[*ip] |= CM_UPDATED;
1090 	setpixel_sub2(x, y, pixtbl[*ip++]);
1091       }
1092     }
1093   }
1094   if (vimg != NULL) {
1095     for (y = y0; y < y0+h; y++) {
1096       ip = imgdata+y*imgmaxw+x0;
1097       for (x = x0; x < x0+w; x++) {
1098 	if (coltbl[*ip] & CM_UPDATING) {
1099 	  coltbl[*ip] |= CM_UPDATED;
1100 	  setpixel_subv(x, y, pixtbl[*ip++]);
1101 	}
1102       }
1103     }
1104   }
1105   for (x = 0; x < MAXPALSET*MAXCOLSET; x++) {
1106     if (coltbl[x] & CM_UPDATED)
1107       coltbl[x] &= ~(CM_UPDATED|CM_UPDATING);
1108   }
1109 }
1110 
1111 /* End of file */
1112