ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.43
Committed: Sat Jun 30 23:31:29 2007 UTC (16 years, 10 months ago) by ayin
Content type: text/plain
Branch: MAIN
Changes since 1.42: +2 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.34 /*----------------------------------------------------------------------*
2 pcg 1.12 * File: xpm.C
3 pcg 1.1 *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1997 Carsten Haitzler <raster@zip.com.au>
7     * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
8     * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
9 root 1.33 * Copyright (c) 2005-2006 Marc Lehmann <pcg@goof.com>
10 pcg 1.1 *
11     * This program is free software; you can redistribute it and/or modify
12     * it under the terms of the GNU General Public License as published by
13     * the Free Software Foundation; either version 2 of the License, or
14     * (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU General Public License
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24     *---------------------------------------------------------------------*/
25    
26     #include "../config.h" /* NECESSARY */
27     #include "rxvt.h" /* NECESSARY */
28    
29     #ifdef XPM_BACKGROUND
30    
31 root 1.22 static void rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight);
32    
33 pcg 1.1 /*
34     * These GEOM strings indicate absolute size/position:
35     * @ `WxH+X+Y'
36     * @ `WxH+X' -> Y = X
37     * @ `WxH' -> Y = X = 50
38     * @ `W+X+Y' -> H = W
39     * @ `W+X' -> H = W, Y = X
40     * @ `W' -> H = W, X = Y = 50
41     * @ `0xH' -> H *= H/100, X = Y = 50 (W unchanged)
42     * @ `Wx0' -> W *= W/100, X = Y = 50 (H unchanged)
43     * @ `=+X+Y' -> (H, W unchanged)
44     * @ `=+X' -> Y = X (H, W unchanged)
45     *
46     * These GEOM strings adjust position relative to current position:
47     * @ `+X+Y'
48     * @ `+X' -> Y = X
49     *
50     * And this GEOM string is for querying current scale/position:
51     * @ `?'
52     */
53     int
54 pcg 1.5 rxvt_term::scale_pixmap (const char *geom)
55 pcg 1.1 {
56 root 1.28 int flags, changed = 0;
57     int x = 0, y = 0;
58     unsigned int w = 0, h = 0;
59     unsigned int n;
60     char *p;
61 root 1.35 bgPixmap_t *bgpixmap = &bgPixmap;
62 pcg 1.1
63 root 1.28 #define MAXLEN_GEOM sizeof("[10000x10000+10000+10000]")
64 pcg 1.1
65 pcg 1.7 if (geom == NULL)
66     return 0;
67 root 1.28
68     char str[MAXLEN_GEOM];
69    
70 root 1.17 if (!strcmp (geom, "?"))
71 pcg 1.7 {
72 pcg 1.9 sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
73 root 1.28 min (bgpixmap->w, 32767), min (bgpixmap->h, 32767),
74     min (bgpixmap->x, 32767), min (bgpixmap->y, 32767));
75 pcg 1.11 process_xterm_seq (XTerm_title, str, CHAR_ST);
76 pcg 1.7 return 0;
77 pcg 1.1 }
78    
79 root 1.17 if ((p = strchr (geom, ';')) == NULL)
80     p = strchr (geom, '\0');
81 root 1.28
82 pcg 1.7 n = (p - geom);
83 root 1.35 if (n < MAXLEN_GEOM)
84 pcg 1.7 {
85 root 1.17 strncpy (str, geom, n);
86 pcg 1.7 str[n] = '\0';
87    
88 sasha 1.38 if (strcmp(str, "auto") == 0)
89     {
90     if (!bgpixmap->auto_resize)
91     changed++;
92     bgpixmap->auto_resize = True ;
93     w = szHint.width ;
94     h = szHint.height ;
95     flags = WidthValue|HeightValue ;
96     }
97     else
98     {
99     bgpixmap->auto_resize = False ;
100     flags = XParseGeometry (str, &x, &y, &w, &h);
101     }
102 root 1.28
103 pcg 1.7 if (!flags)
104     {
105     flags |= WidthValue;
106     w = 0;
107     } /* default is tile */
108 root 1.28
109 pcg 1.7 if (flags & WidthValue)
110     {
111 root 1.28 if (!(flags & XValue))
112 pcg 1.7 x = 50;
113 root 1.28
114     if (!(flags & HeightValue))
115 pcg 1.7 h = w;
116 root 1.28
117 pcg 1.7 if (w && !h)
118     {
119     w = (bgpixmap->w * w) / 100;
120     h = bgpixmap->h;
121     }
122     else if (h && !w)
123     {
124     w = bgpixmap->w;
125     h = (bgpixmap->h * h) / 100;
126     }
127 root 1.28
128     min_it (w, 32767);
129     min_it (h, 32767);
130    
131 pcg 1.7 if (bgpixmap->w != (short)w)
132     {
133     bgpixmap->w = (short)w;
134     changed++;
135     }
136 root 1.28
137 pcg 1.7 if (bgpixmap->h != (short)h)
138     {
139     bgpixmap->h = (short)h;
140     changed++;
141     }
142     }
143 root 1.28
144     if (!(flags & YValue))
145 pcg 1.7 {
146     if (flags & XNegative)
147     flags |= YNegative;
148 root 1.28
149 pcg 1.7 y = x;
150     }
151    
152 root 1.28 if (!(flags & WidthValue) && geom[0] != '=')
153 pcg 1.7 {
154     x += bgpixmap->x;
155     y += bgpixmap->y;
156     }
157 root 1.28
158     if (xpmAttr.width && xpmAttr.height)
159 pcg 1.7 {
160 root 1.28 x = MOD(x, xpmAttr.width);
161     y = MOD(y, xpmAttr.height);
162     }
163    
164 pcg 1.7 if (bgpixmap->x != x)
165     {
166     bgpixmap->x = x;
167     changed++;
168     }
169 root 1.28
170 pcg 1.7 if (bgpixmap->y != y)
171     {
172     bgpixmap->y = y;
173     changed++;
174     }
175 pcg 1.1 }
176 root 1.28
177 pcg 1.7 return changed;
178 pcg 1.1 }
179    
180     void
181 pcg 1.5 rxvt_term::resize_pixmap ()
182 pcg 1.1 {
183 root 1.27 XGCValues gcvalue;
184     GC gc;
185 pcg 1.7
186 root 1.24 if (pixmap != None)
187 sasha 1.38 {
188     XFreePixmap (dpy, pixmap);
189     pixmap = None ;
190     }
191 pcg 1.7
192     if (bgPixmap.pixmap == None)
193     { /* So be it: I'm not using pixmaps */
194 root 1.24 pixmap = None;
195 root 1.20
196 root 1.41 #ifdef ENABLE_TRANSPARENCY
197 root 1.37 if (!option (Opt_transparent) || !am_transparent)
198 ayin 1.36 #endif
199 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
200 root 1.20
201 pcg 1.7 return;
202 pcg 1.1 }
203    
204 root 1.17 gcvalue.foreground = pix_colors[Color_bg];
205 root 1.31 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
206 pcg 1.1
207 pcg 1.7 if (bgPixmap.pixmap != None)
208     { /* we have a specified pixmap */
209 root 1.28 unsigned int w = bgPixmap.w, h = bgPixmap.h,
210     x = bgPixmap.x, y = bgPixmap.y;
211     unsigned int xpmh = xpmAttr.height,
212     xpmw = xpmAttr.width;
213 pcg 1.7
214 sasha 1.38 if (bgPixmap.auto_resize)
215     {
216     w = szHint.width ;
217     h = szHint.height ;
218     }
219 pcg 1.7 /*
220     * don't zoom pixmap too much nor expand really small pixmaps
221     */
222 root 1.28 if (w > 32767 || h > 32767)
223 pcg 1.7 w = 1;
224     else if (width > (10 * xpmw)
225     || height > (10 * xpmh))
226     w = 0; /* tile */
227    
228 root 1.28 if (!w)
229 pcg 1.7 {
230     /* basic X tiling - let the X server do it */
231 root 1.31 pixmap = XCreatePixmap (dpy, vt, xpmw, xpmh, depth);
232 root 1.28
233 root 1.31 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, y, xpmw - x, xpmh - y, 0, 0);
234     XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, 0, xpmw - x, y, 0, xpmh - y);
235     XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, y, x, xpmh - y, xpmw - x, 0);
236     XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, 0, x, y, xpmw - x, xpmh - y);
237 pcg 1.7 }
238     else
239 sasha 1.38 #ifdef HAVE_AFTERIMAGE
240 root 1.41 #ifdef ENABLE_TRANSPARENCY
241 sasha 1.38 if (!option(Opt_transparent) || !am_transparent)
242     /* will do that in check_our_parents otherwise */
243     #endif
244     {
245     ASImage *scaled_im = scale_asimage( display->asv, original_asim, w, h, ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT );
246     if (scaled_im)
247     {
248     pixmap = asimage2pixmap( display->asv, display->root, scaled_im, gc, True );
249     destroy_asimage( &scaled_im );
250     }
251     }
252     #else /* HAVE_AFTERIMAGE */
253 pcg 1.7 {
254 root 1.27 float incr, p;
255     Pixmap tmp;
256 pcg 1.7
257 root 1.31 pixmap = XCreatePixmap (dpy, vt, width, height, depth);
258 pcg 1.7 /*
259     * horizontal scaling
260     */
261 pcg 1.9 rxvt_pixmap_incr (&w, &x, &incr, &p, width, xpmw);
262 pcg 1.7
263 root 1.31 tmp = XCreatePixmap (dpy, vt, width, xpmh, depth);
264     XFillRectangle (dpy, tmp, gc, 0, 0, width, xpmh);
265 pcg 1.7
266     for ( /*nil */ ; x < w; x++, p += incr)
267     {
268     if (p >= xpmw)
269     p = 0;
270 root 1.28
271 pcg 1.7 /* copy one column from the original pixmap to the tmp pixmap */
272 root 1.31 XCopyArea (dpy, bgPixmap.pixmap, tmp, gc, (int)p, 0, 1, xpmh, (int)x, 0);
273 pcg 1.7 }
274    
275     /*
276     * vertical scaling
277     */
278 pcg 1.9 rxvt_pixmap_incr (&h, &y, &incr, &p, height, xpmh);
279 pcg 1.7
280     if (y > 0)
281 root 1.31 XFillRectangle (dpy, pixmap, gc, 0, 0, width, y);
282 root 1.20
283 pcg 1.7 if (h < height)
284 root 1.31 XFillRectangle (dpy, pixmap, gc, 0, (int)h, width, height - h + 1);
285 root 1.20
286 pcg 1.7 for ( /*nil */ ; y < h; y++, p += incr)
287     {
288     if (p >= xpmh)
289     p = 0;
290 root 1.20
291 pcg 1.7 /* copy one row from the tmp pixmap to the main pixmap */
292 root 1.31 XCopyArea (dpy, tmp, pixmap, gc, 0, (int)p, width, 1, 0, (int)y);
293 pcg 1.7 }
294 root 1.20
295 root 1.31 XFreePixmap (dpy, tmp);
296 pcg 1.7 }
297 sasha 1.38 #endif /* HAVE_AFTERIMAGE */
298 pcg 1.1 }
299 root 1.14
300 root 1.31 XSetWindowBackgroundPixmap (dpy, vt, pixmap);
301 root 1.28
302 root 1.31 XFreeGC (dpy, gc);
303 root 1.41 #ifdef ENABLE_TRANSPARENCY
304 pcg 1.7 am_transparent = 0;
305 ayin 1.36 #endif
306 pcg 1.1 }
307    
308     /*
309     * Calculate tiling sizes and increments
310     * At start, p == 0, incr == xpmwidthheight
311     */
312 pcg 1.6 static void
313 pcg 1.9 rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
314 pcg 1.1 {
315 pcg 1.7 unsigned int cwh, cxy;
316     float cincr, cp;
317 pcg 1.1
318 pcg 1.7 cp = 0;
319     cincr = (float)xpmwidthheight;
320     cxy = *xy;
321     cwh = *wh;
322     if (cwh == 1)
323     { /* display one image, no horizontal/vertical scaling */
324     cincr = (float)widthheight;
325     if (xpmwidthheight <= widthheight)
326     {
327     cwh = xpmwidthheight;
328     cxy = (cxy * (widthheight - cwh)) / 100; /* beware! order */
329     cwh += cxy;
330     }
331     else
332     {
333     cxy = 0;
334     cwh = widthheight;
335     }
336 pcg 1.1 }
337 pcg 1.7 else if (cwh < 10)
338     { /* fit WH images across/down screen */
339     cincr *= cwh;
340     cxy = 0;
341     cwh = widthheight;
342     }
343     else
344     {
345     cincr *= 100.0 / cwh;
346     if (cwh < 100)
347     { /* contract */
348     float pos;
349    
350     cwh = (cwh * widthheight) / 100;
351     pos = (float)cxy / 100 * widthheight - (cwh / 2);
352    
353     cxy = (widthheight - cwh);
354     if (pos <= 0)
355     cxy = 0;
356     else if (pos < cxy)
357     cxy = (int) pos;
358     cwh += cxy;
359     }
360     else
361     { /* expand */
362     if (cxy > 0)
363     { /* position */
364     float pos;
365    
366     pos = (float)cxy / 100 * xpmwidthheight - (cincr / 2);
367     cp = xpmwidthheight - cincr;
368     if (pos <= 0)
369     cp = 0;
370     else if (pos < cp)
371     cp = pos;
372     }
373     cxy = 0;
374     cwh = widthheight;
375     }
376     }
377     cincr /= widthheight;
378     *wh = cwh;
379     *xy = cxy;
380     *incr = cincr;
381     *p = cp;
382 pcg 1.1 }
383    
384     Pixmap
385 pcg 1.5 rxvt_term::set_bgPixmap (const char *file)
386 pcg 1.1 {
387 root 1.21 char *f;
388 pcg 1.1
389 pcg 1.9 assert (file != NULL);
390 pcg 1.1
391 pcg 1.7 if (bgPixmap.pixmap != None)
392     {
393 root 1.31 XFreePixmap (dpy, bgPixmap.pixmap);
394 pcg 1.7 bgPixmap.pixmap = None;
395 pcg 1.1 }
396 root 1.19
397 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
398 pcg 1.1
399 pcg 1.7 if (*file != '\0')
400     {
401     /* XWindowAttributes attr; */
402    
403     /*
404     * we already have the required attributes
405     */
406 root 1.31 /* XGetWindowAttributes (dpy, vt, &attr); */
407 pcg 1.7
408 sasha 1.38 #ifdef HAVE_AFTERIMAGE
409     if (asimman == NULL)
410     asimman = create_generic_imageman(rs[Rs_path]);
411     if ((f = strchr (file, ';')) == NULL)
412     original_asim = get_asimage( asimman, file, 0xFFFFFFFF, 100 );
413     else
414     {
415 ayin 1.42 size_t len = f - file;
416     f = (char *)malloc (len + 1);
417     strncpy (f, file, len);
418     f[len] = '\0';
419 sasha 1.38 original_asim = get_asimage( asimman, f, 0xFFFFFFFF, 100 );
420     free( f );
421     }
422     if (original_asim)
423     {
424     bgPixmap.pixmap = asimage2pixmap( display->asv, display->root, original_asim, NULL, True );
425     xpmAttr.width = original_asim->width ;
426     xpmAttr.height = original_asim->height ;
427     }
428     #else /* HAVE_AFTERIMAGE */
429 pcg 1.7 xpmAttr.closeness = 30000;
430 root 1.29 xpmAttr.colormap = cmap;
431     xpmAttr.visual = visual;
432     xpmAttr.depth = depth;
433     xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual
434     | XpmDepth | XpmSize | XpmReturnPixels);
435 pcg 1.7
436     /* search environment variables here too */
437 pcg 1.9 f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]);
438 pcg 1.7 if (f == NULL
439 root 1.31 || XpmReadFileToPixmap (dpy, display->root, f,
440 root 1.29 &bgPixmap.pixmap, NULL,
441     &xpmAttr))
442 pcg 1.7 {
443 pcg 1.10 char *p;
444 pcg 1.7
445     /* semi-colon delimited */
446 root 1.17 if ((p = strchr (file, ';')) == NULL)
447     p = strchr (file, '\0');
448 pcg 1.7
449 root 1.19 rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file);
450 pcg 1.7 }
451 pcg 1.9 free (f);
452 sasha 1.38 #endif /* HAVE_AFTERIMAGE */
453 pcg 1.1 }
454 pcg 1.10
455 pcg 1.7 resize_pixmap ();
456     return bgPixmap.pixmap;
457 pcg 1.1 }
458    
459     #endif /* XPM_BACKGROUND */
460 ayin 1.39
461 root 1.41 #ifdef ENABLE_TRANSPARENCY
462 ayin 1.39 #if TINTING && !defined(HAVE_AFTERIMAGE)
463     /* taken from aterm-0.4.2 */
464    
465     typedef uint32_t RUINT32T;
466    
467 ayin 1.43 static void
468     ShadeXImage(rxvt_term *term, XImage* srcImage, int shade, int rm, int gm, int bm)
469 ayin 1.39 {
470     int sh_r, sh_g, sh_b;
471     RUINT32T mask_r, mask_g, mask_b;
472     RUINT32T *lookup, *lookup_r, *lookup_g, *lookup_b;
473     unsigned int lower_lim_r, lower_lim_g, lower_lim_b;
474     unsigned int upper_lim_r, upper_lim_g, upper_lim_b;
475     int i;
476    
477     Visual *visual = term->visual;
478    
479     if( visual->c_class != TrueColor || srcImage->format != ZPixmap ) return ;
480    
481     /* for convenience */
482     mask_r = visual->red_mask;
483     mask_g = visual->green_mask;
484     mask_b = visual->blue_mask;
485    
486     /* boring lookup table pre-initialization */
487     switch (srcImage->bits_per_pixel) {
488     case 15:
489     if ((mask_r != 0x7c00) ||
490     (mask_g != 0x03e0) ||
491     (mask_b != 0x001f))
492     return;
493     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+32+32));
494     lookup_r = lookup;
495     lookup_g = lookup+32;
496     lookup_b = lookup+32+32;
497     sh_r = 10;
498     sh_g = 5;
499     sh_b = 0;
500     break;
501     case 16:
502     if ((mask_r != 0xf800) ||
503     (mask_g != 0x07e0) ||
504     (mask_b != 0x001f))
505     return;
506     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+64+32));
507     lookup_r = lookup;
508     lookup_g = lookup+32;
509     lookup_b = lookup+32+64;
510     sh_r = 11;
511     sh_g = 5;
512     sh_b = 0;
513     break;
514     case 24:
515     if ((mask_r != 0xff0000) ||
516     (mask_g != 0x00ff00) ||
517     (mask_b != 0x0000ff))
518     return;
519     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
520     lookup_r = lookup;
521     lookup_g = lookup+256;
522     lookup_b = lookup+256+256;
523     sh_r = 16;
524     sh_g = 8;
525     sh_b = 0;
526     break;
527     case 32:
528     if ((mask_r != 0xff0000) ||
529     (mask_g != 0x00ff00) ||
530     (mask_b != 0x0000ff))
531     return;
532     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
533     lookup_r = lookup;
534     lookup_g = lookup+256;
535     lookup_b = lookup+256+256;
536     sh_r = 16;
537     sh_g = 8;
538     sh_b = 0;
539     break;
540     default:
541     return; /* we do not support this color depth */
542     }
543    
544     /* prepare limits for color transformation (each channel is handled separately) */
545     if (shade < 0) {
546     shade = -shade;
547     if (shade < 0) shade = 0;
548     if (shade > 100) shade = 100;
549    
550     lower_lim_r = 65535-rm;
551     lower_lim_g = 65535-gm;
552     lower_lim_b = 65535-bm;
553    
554     lower_lim_r = 65535-(unsigned int)(((RUINT32T)lower_lim_r)*((RUINT32T)shade)/100);
555     lower_lim_g = 65535-(unsigned int)(((RUINT32T)lower_lim_g)*((RUINT32T)shade)/100);
556     lower_lim_b = 65535-(unsigned int)(((RUINT32T)lower_lim_b)*((RUINT32T)shade)/100);
557    
558     upper_lim_r = upper_lim_g = upper_lim_b = 65535;
559     } else {
560     if (shade < 0) shade = 0;
561     if (shade > 100) shade = 100;
562    
563     lower_lim_r = lower_lim_g = lower_lim_b = 0;
564    
565     upper_lim_r = (unsigned int)((((RUINT32T)rm)*((RUINT32T)shade))/100);
566     upper_lim_g = (unsigned int)((((RUINT32T)gm)*((RUINT32T)shade))/100);
567     upper_lim_b = (unsigned int)((((RUINT32T)bm)*((RUINT32T)shade))/100);
568     }
569    
570     /* switch red and blue bytes if necessary, we need it for some weird XServers like XFree86 3.3.3.1 */
571     if ((srcImage->bits_per_pixel == 24) && (mask_r >= 0xFF0000 ))
572     {
573     unsigned int tmp;
574    
575     tmp = lower_lim_r;
576     lower_lim_r = lower_lim_b;
577     lower_lim_b = tmp;
578    
579     tmp = upper_lim_r;
580     upper_lim_r = upper_lim_b;
581     upper_lim_b = tmp;
582     }
583    
584     /* fill our lookup tables */
585     for (i = 0; i <= mask_r>>sh_r; i++)
586     {
587     RUINT32T tmp;
588     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_r-lower_lim_r));
589     tmp += ((RUINT32T)(mask_r>>sh_r))*((RUINT32T)lower_lim_r);
590     lookup_r[i] = (tmp/65535)<<sh_r;
591     }
592     for (i = 0; i <= mask_g>>sh_g; i++)
593     {
594     RUINT32T tmp;
595     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_g-lower_lim_g));
596     tmp += ((RUINT32T)(mask_g>>sh_g))*((RUINT32T)lower_lim_g);
597     lookup_g[i] = (tmp/65535)<<sh_g;
598     }
599     for (i = 0; i <= mask_b>>sh_b; i++)
600     {
601     RUINT32T tmp;
602     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_b-lower_lim_b));
603     tmp += ((RUINT32T)(mask_b>>sh_b))*((RUINT32T)lower_lim_b);
604     lookup_b[i] = (tmp/65535)<<sh_b;
605     }
606    
607     /* apply table to input image (replacing colors by newly calculated ones) */
608     switch (srcImage->bits_per_pixel)
609     {
610     case 15:
611     {
612     unsigned short *p1, *pf, *p, *pl;
613     p1 = (unsigned short *) srcImage->data;
614     pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
615     while (p1 < pf)
616     {
617     p = p1;
618     pl = p1 + srcImage->width;
619     for (; p < pl; p++)
620     {
621     *p = lookup_r[(*p & 0x7c00)>>10] |
622     lookup_g[(*p & 0x03e0)>> 5] |
623     lookup_b[(*p & 0x001f)];
624     }
625     p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
626     }
627     break;
628     }
629     case 16:
630     {
631     unsigned short *p1, *pf, *p, *pl;
632     p1 = (unsigned short *) srcImage->data;
633     pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
634     while (p1 < pf)
635     {
636     p = p1;
637     pl = p1 + srcImage->width;
638     for (; p < pl; p++)
639     {
640     *p = lookup_r[(*p & 0xf800)>>11] |
641     lookup_g[(*p & 0x07e0)>> 5] |
642     lookup_b[(*p & 0x001f)];
643     }
644     p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
645     }
646     break;
647     }
648     case 24:
649     {
650     unsigned char *p1, *pf, *p, *pl;
651     p1 = (unsigned char *) srcImage->data;
652     pf = (unsigned char *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
653     while (p1 < pf)
654     {
655     p = p1;
656     pl = p1 + srcImage->width * 3;
657     for (; p < pl; p += 3)
658     {
659     p[0] = lookup_r[(p[0] & 0xff0000)>>16];
660     p[1] = lookup_r[(p[1] & 0x00ff00)>> 8];
661     p[2] = lookup_r[(p[2] & 0x0000ff)];
662     }
663     p1 = (unsigned char *) ((char *) p1 + srcImage->bytes_per_line);
664     }
665     break;
666     }
667     case 32:
668     {
669     RUINT32T *p1, *pf, *p, *pl;
670     p1 = (RUINT32T *) srcImage->data;
671     pf = (RUINT32T *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
672    
673     while (p1 < pf)
674     {
675     p = p1;
676     pl = p1 + srcImage->width;
677     for (; p < pl; p++)
678     {
679     *p = lookup_r[(*p & 0xff0000)>>16] |
680     lookup_g[(*p & 0x00ff00)>> 8] |
681     lookup_b[(*p & 0x0000ff)] |
682     (*p & ~0xffffff);
683     }
684     p1 = (RUINT32T *) ((char *) p1 + srcImage->bytes_per_line);
685     }
686     break;
687     }
688     }
689    
690     free (lookup);
691     }
692     #endif
693    
694     /*
695     * Check our parents are still who we think they are.
696     * Do transparency updates if required
697     */
698     int
699     rxvt_term::check_our_parents ()
700     {
701     check_our_parents_ev.stop ();
702     check_our_parents_ev.start (NOW + .1);
703     return 0;
704     }
705    
706     void
707     rxvt_term::check_our_parents_cb (time_watcher &w)
708     {
709     int i, pchanged, aformat, have_pixmap, rootdepth;
710     unsigned long nitems, bytes_after;
711     Atom atype;
712     unsigned char *prop = NULL;
713     Window root, oldp, *list;
714     Pixmap rootpixmap = None;
715     XWindowAttributes wattr, wrootattr;
716     int sx, sy;
717     Window cr;
718    
719     pchanged = 0;
720    
721     if (!option (Opt_transparent))
722     return /*pchanged*/; /* Don't try any more */
723    
724     XGetWindowAttributes (dpy, display->root, &wrootattr);
725     rootdepth = wrootattr.depth;
726    
727     XGetWindowAttributes (dpy, parent[0], &wattr);
728    
729     if (rootdepth != wattr.depth)
730     {
731     if (am_transparent)
732     {
733     pchanged = 1;
734     XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
735     am_transparent = am_pixmap_trans = 0;
736     }
737    
738     return /*pchanged*/; /* Don't try any more */
739     }
740    
741     /* Get all X ops out of the queue so that our information is up-to-date. */
742     XSync (dpy, False);
743    
744     XTranslateCoordinates (dpy, parent[0], display->root,
745     0, 0, &sx, &sy, &cr);
746    
747     /* check if we are outside of the visible part of the virtual screen : */
748     if( sx + (int)szHint.width <= 0 || sy + (int)szHint.height <= 0
749     || sx >= wrootattr.width || sy >= wrootattr.height )
750     return /* 0 */ ;
751     /*
752     * Make the frame window set by the window manager have
753     * the root background. Some window managers put multiple nested frame
754     * windows for each client, so we have to take care about that.
755     */
756     i = (xa[XA_XROOTPMAP_ID]
757     && XGetWindowProperty (dpy, display->root, xa[XA_XROOTPMAP_ID],
758     0L, 1L, False, XA_PIXMAP, &atype, &aformat,
759     &nitems, &bytes_after, &prop) == Success);
760    
761     if (!i || prop == NULL)
762     i = (xa[XA_ESETROOT_PMAP_ID]
763     && XGetWindowProperty (dpy, display->root, xa[XA_ESETROOT_PMAP_ID],
764     0L, 1L, False, XA_PIXMAP, &atype, &aformat,
765     &nitems, &bytes_after, &prop) == Success);
766    
767     if (!i || prop == NULL
768     #if TINTING
769     || (!ISSET_PIXCOLOR (Color_tint) && rs[Rs_shade] == NULL
770     #ifdef HAVE_AFTERIMAGE
771     && original_asim == NULL && rs[Rs_blurradius] == NULL
772     #endif
773     )
774     #endif
775     )
776     have_pixmap = 0;
777     else
778     {
779     have_pixmap = 1;
780     rootpixmap = *(Pixmap *)prop;
781     XFree (prop);
782     }
783    
784     if (have_pixmap)
785     {
786     Bool success = False ;
787 ayin 1.40 GC gc = NULL;
788 ayin 1.39 XGCValues gcvalue;
789     #ifdef HAVE_AFTERIMAGE
790     {
791     Pixmap tmp_pmap = None ;
792     ShadingInfo shade;
793     ARGB32 tint ;
794     unsigned int pmap_w = 0, pmap_h = 0;
795    
796     if (get_drawable_size( rootpixmap, &pmap_w, &pmap_h ))
797     {
798     int root_x = 0, root_y = 0;
799    
800     shade.shading = rs[Rs_shade] ? atoi (rs[Rs_shade]) : 100;
801     if (ISSET_PIXCOLOR (Color_tint))
802     {
803     rgba c;
804     pix_colors_focused [Color_tint].get (c);
805     shade.tintColor.red = c.r;
806     shade.tintColor.green = c.g;
807     shade.tintColor.blue = c.b;
808     }
809     else
810     shade.tintColor.red = shade.tintColor.green = shade.tintColor.blue = 0xFFFF;
811     tint = shading2tint32( &shade );
812     gc = XCreateGC (dpy, vt, 0UL, &gcvalue);
813     if (GetWinPosition (parent[0], &root_x, &root_y) )
814     {
815     ASImageLayer *layers = create_image_layers( 2 );
816     ASImage *merged_im = NULL;
817     int back_x, back_y, back_w, back_h;
818     /* merge_layers does good job at tiling background appropriately,
819     so all we need is to cut out smallest possible piece : */
820     #define MAKE_ROOTPMAP_GEOM(xy,wh,widthheight) \
821     do{ while( root_##xy < 0 ) root_##xy += (int)wrootattr.widthheight; \
822     back_##xy = root_##xy % pmap_##wh; /* that gives us left side of the closest tile : */ \
823     if( pmap_##wh >= back_##xy + szHint.widthheight ) \
824     back_##wh = szHint.widthheight;/* background is large - limit it by our size */ \
825     else \
826     { /* small background - need the whole of it for successfull tiling :*/ \
827     back_##xy = 0; \
828     back_##wh = pmap_##wh; \
829     }}while(0)
830    
831     MAKE_ROOTPMAP_GEOM(x,w,width);
832     MAKE_ROOTPMAP_GEOM(y,h,height);
833    
834     layers[0].im = pixmap2asimage (display->asv, rootpixmap, back_x, back_y, back_w, back_h, AllPlanes, ASA_ASImage, 100);
835     layers[0].clip_x = (back_w == pmap_w)?root_x:0;
836     layers[0].clip_y = (back_h == pmap_h)?root_y:0;
837     layers[0].clip_width = szHint.width;
838     layers[0].clip_height = szHint.height;
839     layers[0].tint = tint;
840     if (rs[Rs_blurradius] && layers[0].im)
841     {
842     double r = atof(rs[Rs_blurradius]);
843     ASImage* tmp = blur_asimage_gauss(display->asv, layers[0].im, r, r, 0xFFFFFFFF, ASA_ASImage, 100, ASIMAGE_QUALITY_DEFAULT );
844     if( tmp )
845     {
846     destroy_asimage( &layers[0].im );
847     layers[0].im = tmp;
848     }
849     }
850     if (original_asim != NULL)
851     {
852     int fore_w, fore_h;
853     layers[1].im = original_asim;
854     if( bgPixmap.auto_resize )
855     {
856     fore_w = szHint.width;
857     fore_h = szHint.height;
858     }
859     else
860     {
861     fore_w = bgPixmap.w;
862     fore_h = bgPixmap.h;
863     }
864     if (fore_w != original_asim->width
865     || fore_h != original_asim->height)
866     {
867     layers[1].im = scale_asimage( display->asv,
868     original_asim,
869     fore_w, fore_h,
870     ASA_ASImage, 100,
871     ASIMAGE_QUALITY_DEFAULT );
872     }
873    
874     layers[1].clip_width = szHint.width;
875     layers[1].clip_height = szHint.height;
876    
877     if (rs[Rs_blendtype])
878     {
879     layers[1].merge_scanlines = blend_scanlines_name2func(rs[Rs_blendtype]);
880     if( layers[1].merge_scanlines == NULL )
881     layers[1].merge_scanlines = alphablend_scanlines;
882     }
883     }
884     merged_im = merge_layers( display->asv, layers, layers[1].im?2:1,
885     szHint.width, szHint.height,
886     ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT );
887     if (layers[1].im != original_asim)
888     destroy_asimage( &(layers[1].im) );
889     destroy_asimage( &(layers[0].im) );
890     if (merged_im != NULL)
891     {
892     tmp_pmap = asimage2pixmap( display->asv, DefaultRootWindow(dpy), merged_im, gc, True );
893     destroy_asimage( &merged_im );
894     }
895     free( layers );
896     }
897     }
898     if (tmp_pmap != None)
899     {
900     success = True;
901     if (pixmap != None)
902     XFreePixmap (dpy, pixmap);
903     pixmap = tmp_pmap;
904     }
905     }
906     #else /* HAVE_AFTERIMAGE */
907     {
908     /*
909     * Copy display->root pixmap transparency
910     */
911     int nx, ny;
912     unsigned int nw, nh;
913     XImage *image;
914    
915     nw = (unsigned int)szHint.width;
916     nh = (unsigned int)szHint.height;
917     nx = ny = 0;
918    
919     if (sx < 0)
920     {
921     nw += sx;
922     nx = -sx;
923     sx = 0;
924     }
925    
926     if (sy < 0)
927     {
928     nh += sy;
929     ny = -sy;
930     sy = 0;
931     }
932    
933     min_it (nw, (unsigned int) (wrootattr.width - sx));
934     min_it (nh, (unsigned int) (wrootattr.height - sy));
935    
936     XSync (dpy, False);
937     allowedxerror = -1;
938     image = XGetImage (dpy, rootpixmap, sx, sy, nw, nh, AllPlanes, ZPixmap);
939    
940     /* XXX: handle BadMatch - usually because we're outside the pixmap */
941     /* XXX: may need a delay here? */
942     allowedxerror = 0;
943     if (image != NULL)
944     {
945     if (pixmap != None)
946     XFreePixmap (dpy, pixmap);
947    
948     #if TINTING
949     if (ISSET_PIXCOLOR (Color_tint))
950     {
951     int shade = rs[Rs_shade] ? atoi (rs[Rs_shade]) : 100;
952    
953     rgba c;
954     pix_colors_focused [Color_tint].get (c);
955     ShadeXImage (this, image, shade, c.r, c.g, c.b);
956     }
957     #endif
958    
959     pixmap = XCreatePixmap (dpy, vt, szHint.width, szHint.height, image->depth);
960     gc = XCreateGC (dpy, vt, 0UL, &gcvalue);
961     XPutImage (dpy, pixmap, gc, image, 0, 0,
962     nx, ny, image->width, image->height);
963     XDestroyImage (image);
964     success = True ;
965     }
966     }
967     #endif /* HAVE_AFTERIMAGE */
968     if (gc != NULL)
969     XFreeGC (dpy, gc);
970    
971     if (!success)
972     {
973     if (am_transparent && am_pixmap_trans)
974     {
975     pchanged = 1;
976     if (pixmap != None)
977     {
978     XFreePixmap (dpy, pixmap);
979     pixmap = None;
980     }
981     }
982    
983     am_pixmap_trans = 0;
984     }
985     else
986     {
987     XSetWindowBackgroundPixmap (dpy, parent[0], pixmap);
988     XClearWindow (dpy, parent[0]);
989    
990     if (!am_transparent || !am_pixmap_trans)
991     pchanged = 1;
992    
993     am_transparent = am_pixmap_trans = 1;
994     }
995     }
996    
997     if (am_pixmap_trans)
998     XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
999     else
1000     {
1001     unsigned int n;
1002     /*
1003     * InheritPixmap transparency
1004     */
1005     for (i = 1; i < (int) (sizeof (parent) / sizeof (Window)); i++)
1006     {
1007     oldp = parent[i];
1008     XQueryTree (dpy, parent[i - 1], &root, &parent[i], &list, &n);
1009     XFree (list);
1010    
1011     if (parent[i] == display->root)
1012     {
1013     if (oldp != None)
1014     pchanged = 1;
1015    
1016     break;
1017     }
1018    
1019     if (oldp != parent[i])
1020     pchanged = 1;
1021     }
1022    
1023     n = 0;
1024    
1025     if (pchanged)
1026     for (; n < (unsigned int)i; n++)
1027     {
1028     XGetWindowAttributes (dpy, parent[n], &wattr);
1029    
1030     if (wattr.depth != rootdepth || wattr.c_class == InputOnly)
1031     {
1032     n = (int) (sizeof (parent) / sizeof (Window)) + 1;
1033     break;
1034     }
1035     }
1036    
1037     if (n > (sizeof (parent) / sizeof (parent[0])))
1038     {
1039     XSetWindowBackground (dpy, parent[0], pix_colors_focused[Color_border]);
1040     XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
1041     am_transparent = 0;
1042     /* XXX: also turn off Opt_transparent? */
1043     }
1044     else
1045     {
1046     for (n = 0; n < (unsigned int)i; n++)
1047     {
1048     XSetWindowBackgroundPixmap (dpy, parent[n], ParentRelative);
1049     XClearWindow (dpy, parent[n]);
1050     }
1051    
1052     XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
1053     am_transparent = 1;
1054     }
1055    
1056     for (; i < (int) (sizeof (parent) / sizeof (Window)); i++)
1057     parent[i] = None;
1058     }
1059    
1060     if (scrollBar.win)
1061     {
1062     XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative);
1063     scrollBar.setIdle ();
1064     scrollbar_show (0);
1065     }
1066    
1067     if (am_transparent)
1068     {
1069     want_refresh = want_full_refresh = 1;
1070     if (am_pixmap_trans)
1071     flush ();
1072     }
1073    
1074     // return pchanged;
1075     }
1076     #endif