1 /* Tk-specific functions for image families in Xconq.
2    Copyright (C) 1998, 1999 Stanley T. Shebs.
3 
4 Xconq is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.  See the file COPYING.  */
8 
9 #include "config.h"
10 #include "misc.h"
11 #include "lisp.h"
12 #include "module.h"
13 #include "system.h"
14 #include "imf.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #ifdef MAC
21 #include <tclMacCommonPch.h>
22 #include <tclMac.h>			/* Includes tcl.h. */
23 #include <tkMac.h>			/* Includes tk.h. */
24 #else
25 #include <tcl.h>
26 #include <tk.h>
27 #endif /* MAC */
28 
29 /* These must be included AFTER tcl.h and tk.h. */
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32 
33 #ifdef __cplusplus
34 }
35 #endif
36 
37 #include "tkimf.h"
38 
39 /* Lifted from tk sources - XPutImage is not available to Windows port. */
40 #ifdef UNIX
41 #define TkPutImage(colors, ncolors, display, pixels, gc, image, destx, desty, srcx, srcy, width, height) \
42 	XPutImage(display, pixels, gc, image, destx, desty, srcx, \
43 	srcy, width, height);
44 #else
45 extern void TkPutImage(unsigned long *colors, int ncolors,
46 		       Display* display, Drawable d, GC gc, XImage* image,
47 		       int src_x, int src_y, int dest_x, int dest_y,
48 		       unsigned int width, unsigned int height);
49 #endif
50 
51 extern Tcl_Interp *interp;
52 
53 int tmp_valid;
54 
55 Tk_Window tmp_root_window;
56 
57 static Pixmap tk_load_bitmap(Tk_Window rootwin, char *name, char *ext,
58 			     int *w, int *h);
59 static void tk_interp_image(ImageFamily *imf, Image *img, int force);
60 static void tk_interp_image_1(ImageFamily *imf, Image *img, Image *subimg,
61 			      int subi, int force);
62 static void tk_make_color_pixmap(Tk_Window rootwin, ImageFamily *imf,
63 				 Image *img);
64 static void tk_make_mono_pixmap(Tk_Window rootwin, ImageFamily *imf,
65 				Image *img);
66 static void tk_make_mask_pixmap(Tk_Window rootwin, ImageFamily *imf,
67 				Image *img);
68 
69 /* Stash for cloned image families. */
70 
71 static ImageFamily *tkimages[MAXIMAGEFAMILIES];
72 
73 int numtkimages = 0;
74 
75 TkImage *
init_tk_image(Image * img)76 init_tk_image(Image *img)
77 {
78     TkImage *tkimg;
79 
80     tkimg = (TkImage *) xmalloc(sizeof(TkImage));
81     /* Point to the generic image. */
82     tkimg->generic = img;
83     tkimg->mono = None;
84     tkimg->mask = None;
85     tkimg->colr = None;
86     tkimg->solid = NULL;
87     return tkimg;
88 }
89 
90 TkImage *
get_tk_image(Image * img)91 get_tk_image(Image *img)
92 {
93     TkImage *tkimg;
94 
95     if (img->hook)
96       return (TkImage *) img->hook;
97     tkimg = init_tk_image(img);
98     img->hook = (char *) tkimg;
99     return tkimg;
100 }
101 
102 /* This tries to fill in the given image family by looking for and loading
103    standard X11 bitmap files. */
104 
105 ImageFamily *
tk_load_imf(ImageFamily * imf)106 tk_load_imf(ImageFamily *imf)
107 {
108     int w, h;
109     Pixmap pic;
110     Image *img;
111     Tk_Window rootwin = None;
112     TkImageFamily *tkimf;
113     TkImage *tkimg;
114 
115     /* If no imf or no name, don't even try. */
116     if (imf == NULL || imf->name == NULL)
117       return NULL;
118     if (strcmp(imf->name, "none") == 0)
119       return imf;
120     if (tmp_valid) {
121 	if (imf->hook == NULL) {
122 	    imf->hook = (char *)xmalloc(sizeof(TkImageFamily));
123 	    tkimf = (TkImageFamily *) imf->hook;
124 	    tkimf->rootwin = tmp_root_window;
125 	    /* Record the cloned family for later lookup. */
126 	    tkimages[numtkimages++] = imf;
127 	}
128     }
129     tkimf = (TkImageFamily *) imf->hook;
130     if (tkimf) {
131 	rootwin = tkimf->rootwin;
132     }
133     /* Grab at plausibly-named bitmaps. */
134     pic = tk_load_bitmap(rootwin, imf->name, "b", &w, &h);
135     if (pic != None) {
136 	img = get_img(imf, w, h);
137 	tkimg = get_tk_image(img);
138 	tkimg->mono = pic;
139     }
140     pic = tk_load_bitmap(rootwin, imf->name, "m", &w, &h);
141     if (pic != None) {
142 	img = get_img(imf, w, h);
143 	tkimg = get_tk_image(img);
144 	tkimg->mask = pic;
145     }
146     pic = tk_load_bitmap(rootwin, imf->name, "8.b", &w, &h);
147     if (pic != None) {
148 	img = get_img(imf, w, h);
149 	tkimg = get_tk_image(img);
150 	tkimg->mono = pic;
151     }
152     pic = tk_load_bitmap(rootwin, imf->name, "8.m", &w, &h);
153     if (pic != None) {
154 	img = get_img(imf, w, h);
155 	tkimg = get_tk_image(img);
156 	tkimg->mask = pic;
157     }
158     pic = tk_load_bitmap(rootwin, imf->name, "32.b", &w, &h);
159     if (pic != None) {
160 	img = get_img(imf, w, h);
161 	tkimg = get_tk_image(img);
162 	tkimg->mono = pic;
163     }
164     pic = tk_load_bitmap(rootwin, imf->name, "32.m", &w, &h);
165     if (pic != None) {
166 	img = get_img(imf, w, h);
167 	tkimg = get_tk_image(img);
168 	tkimg->mask = pic;
169     }
170     return imf;
171 }
172 
173 /* Try to load a bitmap of the given name, looking in both the current dir
174    and the library dir. */
175 
176 static Pixmap
tk_load_bitmap(Tk_Window rootwin,char * name,char * ext,int * wp,int * hp)177 tk_load_bitmap(Tk_Window rootwin, char *name, char *ext, int *wp, int *hp)
178 {
179 #if 0
180     int hotx, hoty;
181     unsigned int w, h;
182     Pixmap rslt;
183     static char sbuf[BUFSIZE];
184 
185     if (ext != NULL) {
186 	make_pathname(NULL, name, ext, sbuf);
187 	if (XReadBitmapFile(dpy, rootwin, sbuf,
188 			    &w, &h, &rslt, &hotx, &hoty) == BitmapSuccess) {
189 	    DGprintf("Loaded bitmap \"%s\"\n", sbuf);
190 	    *wp = w;  *hp = h;
191 	    return rslt;
192 	}
193     }
194 #endif
195     return None;
196 }
197 
198 /* if (force): prefer data over rawdata; always re-create pixmaps */
199 
200 ImageFamily *
tk_interp_imf(ImageFamily * imf,Image * img,int force)201 tk_interp_imf(ImageFamily *imf, Image *img, int force)
202 {
203     TkImageFamily *tkimf;
204 
205     if (tmp_valid) {
206 	if (imf->hook == NULL) {
207 	    imf->hook = (char *)xmalloc(sizeof(TkImageFamily));
208 	    tkimf = (TkImageFamily *) imf->hook;
209 	    tkimf->rootwin = tmp_root_window;
210 	    /* Record the cloned family for later lookup. */
211 	    tkimages[numtkimages++] = imf;
212 	}
213     }
214     if (img == NULL) {
215 	for_all_images(imf, img) {
216 	    tk_interp_image(imf, img, force);
217 	}
218     } else {
219 	tk_interp_image(imf, img, force);
220     }
221     return imf;
222 }
223 
224 /* Interpret an image and any possible subimages. */
225 
226 static void
tk_interp_image(ImageFamily * imf,Image * img,int force)227 tk_interp_image(ImageFamily *imf, Image *img, int force)
228 {
229     int subi;
230 
231     /* Skip all basic terrain images except power 4 and 5
232     if we are low on memory. */
233     if (poor_memory
234         && img->isterrain
235         && img->w != 24
236         && img->w != 44) {
237     	return;
238     }
239     /* Terrain patterns are not supported yet on Windows,
240     so no need to load them there. */
241     if (!use_clip_mask
242     	&& img->istile
243     	&& img->w > 1) {
244     	return;
245     }
246     /* Iterate through any subimages. */
247     if (img->isborder && img->subimages != NULL) {
248 	for (subi = 0; subi < 16; ++subi) {
249 	    tk_interp_image_1(imf, img, img->subimages[subi], subi, force);
250 	}
251     } else if (img->isconnection && img->subimages != NULL) {
252 	for (subi = 0; subi < 64; ++subi) {
253 	    tk_interp_image_1(imf, img, img->subimages[subi], subi, force);
254 	}
255     } else if (img->istransition && img->subimages != NULL) {
256 	for (subi = 0; subi < 4 * 4; ++subi) {
257 	    tk_interp_image_1(imf, img, img->subimages[subi], subi, force);
258 	}
259     } else if (img->numsubimages > 0 && img->subimages != NULL) {
260 	for (subi = 0; subi < img->numsubimages; ++subi) {
261 	    tk_interp_image_1(imf, img, img->subimages[subi], subi, force);
262 	}
263     } else {
264 	tk_interp_image_1(imf, img, img, 0, force);
265     }
266 }
267 
268 /* Interpret a single image/subimage. */
269 
270 static void
tk_interp_image_1(ImageFamily * imf,Image * img,Image * subimg,int subi,int force)271 tk_interp_image_1(ImageFamily *imf, Image *img, Image *subimg, int subi,
272 		  int force)
273 {
274     char namebuf[BUFSIZE];
275     int w, h, numbytes;
276     int dummy, red, grn, blu;
277     TkImageFamily *tkimf;
278     TkImage *tkimg;
279     Tk_Window rootwin;
280     Tk_Uid bitmapid;
281     XColor col;
282 
283     w = img->w;  h = img->h;
284     tkimg = get_tk_image(subimg);
285     /* Collect the root window, failing if none exists. */
286     tkimf = (TkImageFamily *) imf->hook;
287     if (tkimf == NULL)
288       return;
289     rootwin = tkimf->rootwin;
290 
291     /* A 1x1 image is just a color - make it into a solid color. */
292     if (w == 1 && h == 1 && img->palette != lispnil) {
293 	/* (should do generic work in generic code) */
294 	/* force this? */
295 	img->numcolors = 1;
296 	parse_lisp_palette_entry(car(img->palette), &dummy, &red, &grn, &blu);
297 	img->r = red;  img->g = grn;  img->b = blu;
298 	col.red = red;  col.green = grn;  col.blue = blu;
299 	tkimg->solid = Tk_GetColorByValue(rootwin, &col);
300 	if (tkimg->solid == NULL)
301 	  init_warning("Cannot get color #%2.2x%2.2x%2.2x for %s",
302 		       col.red, col.green, col.blue, imf->name);
303 	return;
304     }
305     if (subimg->colrdata != lispnil
306 	&& (subimg->rawcolrdata == NULL || force)) {
307 	numbytes = h * computed_rowbytes(w, subimg->pixelsize);
308 	subimg->rawcolrdata = (char *)xmalloc(numbytes);
309 	interp_bytes(subimg->colrdata, numbytes, subimg->rawcolrdata, 0);
310     }
311     if (subimg->rawcolrdata == NULL && img->filedata != lispnil) {
312 	make_image_from_file_image(imf, img, subimg, subi);
313     }
314     make_raw_mono_data(subimg, force);
315     if (subimg->maskdata != lispnil
316 	&& (subimg->rawmaskdata == NULL || force)) {
317 	numbytes = h * computed_rowbytes(w, 1);
318 	subimg->rawmaskdata = (char *)xmalloc(numbytes);
319 	interp_bytes(subimg->maskdata, numbytes, subimg->rawmaskdata, 0);
320     }
321     /* At this point our data is known to be in "raw" form, ready to
322        turn into Tk-specific objects. */
323     if (use_clip_mask) {
324 	/* If clip masks work (real X11), then we can create bitmaps for
325 	   the mono and mask data. */
326 	if (subimg->rawmonodata != NULL && (tkimg->mono == None || force)) {
327 	    numbytes = h * computed_rowbytes(w, 1);
328 	    reverse_bit_endianness(subimg->rawmonodata, numbytes);
329 	    sprintf(namebuf, "%s.%d.%d.%d.mono", imf->name, w, h, subi);
330 	    bitmapid = Tk_GetUid(namebuf);
331 	    Tk_DefineBitmap(interp, bitmapid, subimg->rawmonodata, w, h);
332 	    tkimg->mono = Tk_GetBitmap(interp, rootwin, bitmapid);
333 	    reverse_bit_endianness(subimg->rawmonodata, numbytes);
334 	}
335 	if (subimg->rawmaskdata != NULL	&& (tkimg->mask == None || force)) {
336 	    numbytes = h * computed_rowbytes(w, 1);
337 	    reverse_bit_endianness(subimg->rawmaskdata, numbytes);
338 	    sprintf(namebuf, "%s.%d.%d.%d.mask", imf->name, w, h, subi);
339 	    bitmapid = Tk_GetUid(namebuf);
340 	    Tk_DefineBitmap(interp, bitmapid, subimg->rawmaskdata, w, h);
341 	    tkimg->mask = Tk_GetBitmap(interp, rootwin, bitmapid);
342 	    reverse_bit_endianness(subimg->rawmaskdata, numbytes);
343 	}
344     } else {
345 	/* Logical operations depend on the to-be-masked areas of images
346 	   being all black. */
347 	if (subimg->rawmaskdata != NULL) {
348 	    if (subimg->rawcolrdata != NULL)
349 	      blacken_masked_area(imf, subimg, 0, 0, 0);
350 	    if (subimg->rawmonodata != NULL)
351 	      blacken_mono_masked_area(imf, subimg, 0, 0, 0);
352 	}
353 	/* Make mono and mask data into b/w pixmaps of full depth, to
354 	   use with AND/OR operations. */
355 	if (subimg->rawmonodata	&& (tkimg->mono == None || force)) {
356 	    tk_make_mono_pixmap(rootwin, imf, subimg);
357 	}
358 	if (subimg->rawmaskdata	&& (tkimg->mask == None || force)) {
359 	    tk_make_mask_pixmap(rootwin, imf, subimg);
360 	}
361     }
362     /* Whether using clip masks or logical ops, color pixmap creation
363        works the same. */
364     if (subimg->rawcolrdata && (tkimg->colr == None || force)) {
365 	tk_make_color_pixmap(rootwin, imf, subimg);
366     }
367 }
368 
369 /* TK bitmaps are always in little-endian bit order, while IMF images
370    are always big-endian in bit order, so we must reverse the bits
371    in each byte individually. */
372 
373 void
reverse_bit_endianness(char * rawdata,int numbytes)374 reverse_bit_endianness(char *rawdata, int numbytes)
375 {
376     int i, j, byte, byte2;
377 
378     for (i = 0; i < numbytes; ++i) {
379 	byte = rawdata[i];
380 	byte2 = 0;
381 	for (j = 0; j < 8; ++j) {
382 	    byte2 = (byte2 << 1) | (byte & 1);
383 	    byte >>= 1;
384 	}
385 	rawdata[i] = byte2;
386     }
387 }
388 
389 static int try_images = 1;
390 
391 static int use_images;
392 
393 #if ( defined(UNIX) || defined(MAC) )
394 static XImage *test_image;
395 #endif
396 static int imdepth;
397 
398 static char *ximbuf;
399 static XImage *xim;
400 
401 static void
tk_make_color_pixmap(Tk_Window rootwin,ImageFamily * imf,Image * img)402 tk_make_color_pixmap(Tk_Window rootwin, ImageFamily *imf, Image *img)
403 {
404     int r, ri, rc, depth, c, rmask, pix, use_images_here;
405     XColor col, *color;
406     char *rp;
407     GC gc;
408     TkImage *tkimg = (TkImage *) img->hook;
409     Display *dpy = Tk_Display(rootwin);
410 
411     if (tkimg == NULL || img->rawcolrdata == NULL)
412       return;
413     /* Can't make color pixmaps if we don't have any colors. */
414     if (img->palette == lispnil && img->rawpalette == NULL)
415       return;
416     DGprintf("Starting %dx%d colr pixmap for %s\n", img->w, img->h, imf->name);
417     if (img->rawpalette == NULL)
418       make_raw_palette(img);
419     Tk_MakeWindowExist(rootwin);
420     depth = DefaultDepthOfScreen(Tk_Screen(rootwin));
421     if (img->numcolors <= 0) {
422 	run_warning("No colors?");
423 	return;
424     }
425     /* Allocate colors. */
426     tkimg->cmap =
427 	(XColor **) xmalloc(256 /*img->numcolors*/ * sizeof(XColor *));
428     for (c = 0; c < img->numcolors; c++) {
429 	col.red   = img->rawpalette[4 * c + 1];
430 	col.green = img->rawpalette[4 * c + 2];
431 	col.blue  = img->rawpalette[4 * c + 3];
432 	color = Tk_GetColorByValue(rootwin, &col);
433 	if (color == NULL)
434 	  init_warning("Cannot get color #%2.2x%2.2x%2.2x for %s",
435 		       col.red, col.green, col.blue, imf->name);
436 	tkimg->cmap[img->rawpalette[4 * c + 0]] = color;
437     }
438     tkimg->colr = Tk_GetPixmap(dpy, Tk_WindowId(rootwin), img->w, img->h,
439 			       depth);
440     if (tkimg->colr == None) {
441 	init_warning("color pixmap creation failed");
442 	return;
443     }
444     /* Draw the image by plotting each point separately. */
445     rmask = (1 << img->pixelsize) - 1;
446     rp = img->rawcolrdata;
447     gc = Tk_GetGC(rootwin, None, NULL);
448     XSetClipMask(dpy, gc, None);
449     XSetFillStyle(dpy, gc, FillSolid);
450     if (try_images) {
451 	/* (no XGetImage for color images on Windows) */
452 #if ( defined(UNIX) || defined(MAC) )
453 	if (test_image == NULL) {
454 	    test_image = XGetImage(dpy, tkimg->colr, 0, 0, img->w, img->h,
455 				   AllPlanes, ZPixmap);
456 	    /* Only use images with 16-bit color for now. */
457 	    if (test_image->depth == 16) {
458 		use_images = TRUE;
459 		imdepth = 16;
460 	    }
461 	}
462 #else
463 	/* On Windows, we always seem to have 32-bit images. */
464 	use_images = TRUE;
465 	imdepth = 32;
466 #endif
467     }
468     use_images_here = use_images;
469     if ((img->w & 1) == 1 || (img->h & 1) == 1)
470       use_images_here = FALSE;
471     if (use_images_here) {
472 #if ( defined(UNIX) || defined(MAC) )
473 	ximbuf = (char *) xmalloc(img->w * img->h * (imdepth / 8));
474 #else
475 	/* (should do this for both Unix and Windows...) */
476 	Visual *vis;
477 	vis = Tk_Visual(rootwin);
478 	ximbuf = (char *) xmalloc(img->w * img->h * (imdepth / 8));
479 	xim = XCreateImage(dpy, vis, imdepth, ZPixmap, 0, ximbuf,
480 			   img->w, img->h, 32, 0);
481 #endif
482     }
483     for (r = 0; r < img->h; r++) {
484 	ri = 8 - img->pixelsize;
485 	for (c = 0; c < img->w; c++) {
486 	    /* imf decoding stuff */
487 	    rc = ((int) (*rp >> ri)) & rmask;
488 	    if (ri) {
489 		ri -= img->pixelsize;
490 	    } else {
491 		ri = 8 - img->pixelsize;
492 		rp++;
493 	    }
494 	    pix = 0;
495 	    if (tkimg->cmap[rc] && rc < 256)
496 	      pix = tkimg->cmap[rc]->pixel;
497 	    if (use_images_here) {
498 		if (imdepth == 16) {
499 #if 1
500 		    *(((short *) ximbuf) + (img->w * r + c)) = pix;
501 #endif
502 #if 0
503 		    ximbuf[(img->w * r + c) * 2 + 1] = pix & 0xff;
504 		    ximbuf[(img->w * r + c) * 2 + 0] = pix >> 8;
505 #endif
506 		} else {
507 		    XPutPixel(xim, c, r, pix);
508 		}
509 	    } else {
510 		XSetForeground(dpy, gc, pix);
511 		XFillRectangle(dpy, tkimg->colr, gc, c, r, 1, 1);
512 	    }
513 	}
514 	if ((img->pixelsize * img->w) % 8) {
515 	    rp++;
516 	}
517     }
518     if (use_images_here) {
519 #if 0 /* this is probably the right approach to use someday */
520 	int numvisuals;
521 	XVisualInfo visinfo, *visinfoptr;
522 
523 	visinfo.screen = Tk_ScreenNumber(rootwin);
524 	visinfo.visualid = XVisualIDFromVisual(Tk_Visual(rootwin));
525 	visinfoptr = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
526 				    &visinfo, &numvisuals);
527 #endif
528 #if ( defined(UNIX) || defined(MAC) )
529 	Visual *vis;
530 	vis = Tk_Visual(rootwin);
531 	xim = XCreateImage(dpy, vis, imdepth, ZPixmap, 0, ximbuf,
532 			   img->w, img->h, 32, 0);
533 #endif
534 	/* Move the image's bits into the pixmap. */
535 	TkPutImage(NULL, 0, dpy, tkimg->colr, gc, xim, 0, 0, 0, 0,
536 		   img->w, img->h);
537 	/* Destroy XImage once it is no longer needed. */
538 	XDestroyImage(xim);
539     }
540     Tk_FreeGC(dpy, gc);
541     DGprintf("   Finished\n");
542 }
543 
544 static void
tk_make_mono_pixmap(Tk_Window rootwin,ImageFamily * imf,Image * img)545 tk_make_mono_pixmap(Tk_Window rootwin, ImageFamily *imf, Image *img)
546 {
547     int r, ri, rc, depth, c, rmask, pix, use_images_here;
548     XColor col;
549     char *rp;
550     GC gc;
551     TkImage *tkimg = (TkImage *) img->hook;
552     Display *dpy = Tk_Display(rootwin);
553     XColor *whitecolor, *blackcolor;
554 
555     if (tkimg == NULL || img->rawmonodata == NULL)
556       return;
557     DGprintf("Starting %dx%d mono pixmap for %s\n", img->w, img->h, imf->name);
558     Tk_MakeWindowExist(rootwin);
559     depth = DefaultDepthOfScreen(Tk_Screen(rootwin));
560     /* Note that depth is expected to be > 1 - we're going to paint black
561        and white into a color image. */
562     col.red = col.green = col.blue = 65535;
563     whitecolor = Tk_GetColorByValue(rootwin, &col);
564     col.red = col.green = col.blue = 0;
565     blackcolor = Tk_GetColorByValue(rootwin, &col);
566     tkimg->mono = Tk_GetPixmap(dpy, Tk_WindowId(rootwin), img->w, img->h,
567 			       depth);
568     if (tkimg->mono == None) {
569 	init_warning("mono pixmap creation failed");
570 	return;
571     }
572     rmask = 1;
573     rp = img->rawmonodata;
574     gc = Tk_GetGC(rootwin, None, NULL);
575     XSetClipMask(dpy, gc, None);
576     XSetFillStyle(dpy, gc, FillSolid);
577     if (try_images) {
578 #if ( defined(UNIX) || defined(MAC) )
579 	if (test_image == NULL) {
580 	    test_image = XGetImage(dpy, tkimg->mono, 0, 0, img->w, img->h,
581 				   AllPlanes, ZPixmap);
582 	    /* Only use images with 16-bit color for now. */
583 	    if (test_image->depth == 16) {
584 		use_images = TRUE;
585 	    }
586 	}
587 #else
588 	/* (should create b/w image) */
589 	use_images = TRUE;
590 #endif
591     }
592     use_images_here = use_images;
593     if ((img->w & 1) == 1 || (img->h & 1) == 1)
594       use_images_here = FALSE;
595     if (use_images_here) {
596 	ximbuf = (char *) xmalloc(img->w * img->h * 2 * sizeof(char));
597     }
598     for (r = 0; r < img->h; r++) {
599 	ri = 7;
600 	for (c = 0; c < img->w; c++) {
601 	    /* imf decoding stuff */
602 	    rc = ((int) (*rp >> ri)) & rmask;
603 	    if (ri) {
604 		ri -= 1;
605 	    } else {
606 		ri = 7;
607 		rp++;
608 	    }
609 	    pix = (rc ? blackcolor : whitecolor)->pixel;
610 	    if (use_images_here) {
611 		ximbuf[(img->w * r + c) * 2 + 0] = pix & 0xff;
612 		ximbuf[(img->w * r + c) * 2 + 1] = pix >> 8;
613 	    } else {
614 		XSetForeground(dpy, gc, pix);
615 		XFillRectangle(dpy, tkimg->mono, gc, c, r, 1, 1);
616 	    }
617 	}
618 	if (img->w % 8) {
619 	    rp++;
620 	}
621     }
622     if (use_images_here) {
623 	Visual *vis;
624 
625 	vis = Tk_Visual(rootwin);
626 	xim = XCreateImage(dpy, vis, 16, ZPixmap, 0, ximbuf, img->w, img->h,
627 			   32, 0);
628 
629 	/* Move the image's bits into the pixmap. */
630 	TkPutImage(NULL, 0, dpy, tkimg->mono, gc, xim, 0, 0, 0, 0,
631 		   img->w, img->h);
632 	XDestroyImage(xim);
633     }
634     Tk_FreeGC(dpy, gc);
635     DGprintf("    Finished\n");
636 }
637 
638 static void
tk_make_mask_pixmap(Tk_Window rootwin,ImageFamily * imf,Image * img)639 tk_make_mask_pixmap(Tk_Window rootwin, ImageFamily *imf, Image *img)
640 {
641     int r, ri, rc, depth, c, rmask, pix, use_images_here;
642     XColor col;
643     char *rp;
644     GC gc;
645     TkImage *tkimg = (TkImage *) img->hook;
646     Display *dpy = Tk_Display(rootwin);
647     XColor *whitecolor, *blackcolor;
648 
649     if (tkimg == NULL || img->rawmaskdata == NULL)
650       return;
651     DGprintf("Starting %dx%d mask pixmap for %s\n", img->w, img->h, imf->name);
652     Tk_MakeWindowExist(rootwin);
653     depth = DefaultDepthOfScreen(Tk_Screen(rootwin));
654     col.red = col.green = col.blue = 65535;
655     whitecolor = Tk_GetColorByValue(rootwin, &col);
656     col.red = col.green = col.blue = 0;
657     blackcolor = Tk_GetColorByValue(rootwin, &col);
658     tkimg->mask = Tk_GetPixmap(dpy, Tk_WindowId(rootwin), img->w, img->h,
659 			       depth);
660     if (tkimg->mask == None) {
661 	init_warning("mask pixmap creation failed");
662 	return;
663     }
664     rmask = 1;
665     rp = img->rawmaskdata;
666     gc = Tk_GetGC(rootwin, None, NULL);
667     XSetClipMask(dpy, gc, None);
668     XSetFillStyle(dpy, gc, FillSolid);
669     if (try_images) {
670 #if ( defined(UNIX) || defined(MAC) )
671 	if (test_image == NULL) {
672 	    test_image = XGetImage(dpy, tkimg->mask, 0, 0, img->w, img->h,
673 				   AllPlanes, ZPixmap);
674 	    /* Only use images with 16-bit color for now. */
675 	    if (test_image->depth == 16) {
676 		use_images = TRUE;
677 	    }
678 	}
679 #else
680 	use_images = TRUE;
681 #endif
682     }
683     use_images_here = use_images;
684     if ((img->w & 1) == 1 || (img->h & 1) == 1)
685       use_images_here = FALSE;
686     if (use_images_here) {
687 	ximbuf = (char *) xmalloc(img->w * img->h * 2 * sizeof(char));
688     }
689     for (r = 0; r < img->h; r++) {
690 	ri = 7;
691 	for (c = 0; c < img->w; c++) {
692 	    /* imf decoding stuff */
693 	    rc = ((int) (*rp >> ri)) & rmask;
694 	    if (ri) {
695 		ri -= 1;
696 	    } else {
697 		ri = 7;
698 		rp++;
699 	    }
700 	    pix = (rc ? blackcolor : whitecolor)->pixel;
701 	    if (use_images_here) {
702 		ximbuf[(img->w * r + c) * 2 + 0] = pix & 0xff;
703 		ximbuf[(img->w * r + c) * 2 + 1] = pix >> 8;
704 	    } else {
705 		XSetForeground(dpy, gc, pix);
706 		XFillRectangle(dpy, tkimg->mask, gc, c, r, 1, 1);
707 	    }
708 	}
709 	if (img->w % 8) {
710 	    rp++;
711 	}
712     }
713     if (use_images_here) {
714 	Visual *vis;
715 
716 	/* Create XImage to put IMF pixels into. */
717 	vis = Tk_Visual(rootwin);
718 	xim = XCreateImage(dpy, vis, 16, ZPixmap, 0, ximbuf, img->w, img->h,
719 			   32, 0);
720 	/* Move XImage's bits into the pixmap. */
721 	TkPutImage(NULL, 0, dpy, tkimg->mask, gc, xim, 0, 0, 0, 0,
722 		   img->w, img->h);
723 	/* Free up XImage once it has been transferred to the pixmap. */
724 	XDestroyImage(xim);
725     }
726     Tk_FreeGC(dpy, gc);
727     DGprintf("    Finished\n");
728 }
729 
730 void
make_generic_image_data(ImageFamily * imf)731 make_generic_image_data(ImageFamily *imf)
732 {
733     /* (should write impl?) */
734 }
735 
736 ImageFamily *
tk_find_imf(char * name)737 tk_find_imf(char *name)
738 {
739     int i;
740     ImageFamily *imf;
741     Tk_Window tkwin;
742 
743     for (i = 0; i < numtkimages; ++i)
744       if (strcmp(tkimages[i]->name, name) == 0)
745 	return tkimages[i];
746     tkwin = Tk_MainWindow(interp);
747     tmp_root_window = tkwin;
748     tmp_valid = TRUE;
749     imf = get_generic_images(name);
750     tmp_valid = FALSE;
751     return imf;
752 }
753