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