ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.39
Committed: Mon Jun 11 17:40:15 2007 UTC (16 years, 11 months ago) by ayin
Content type: text/plain
Branch: MAIN
Changes since 1.38: +616 -0 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 ayin 1.36 #ifdef TRANSPARENT
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     #ifdef TRANSPARENT
241     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 ayin 1.36 #ifdef TRANSPARENT
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     f = strndup( file, f - file );
416     original_asim = get_asimage( asimman, f, 0xFFFFFFFF, 100 );
417     free( f );
418     }
419     if (original_asim)
420     {
421     bgPixmap.pixmap = asimage2pixmap( display->asv, display->root, original_asim, NULL, True );
422     xpmAttr.width = original_asim->width ;
423     xpmAttr.height = original_asim->height ;
424     }
425     #else /* HAVE_AFTERIMAGE */
426 pcg 1.7 xpmAttr.closeness = 30000;
427 root 1.29 xpmAttr.colormap = cmap;
428     xpmAttr.visual = visual;
429     xpmAttr.depth = depth;
430     xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual
431     | XpmDepth | XpmSize | XpmReturnPixels);
432 pcg 1.7
433     /* search environment variables here too */
434 pcg 1.9 f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]);
435 pcg 1.7 if (f == NULL
436 root 1.31 || XpmReadFileToPixmap (dpy, display->root, f,
437 root 1.29 &bgPixmap.pixmap, NULL,
438     &xpmAttr))
439 pcg 1.7 {
440 pcg 1.10 char *p;
441 pcg 1.7
442     /* semi-colon delimited */
443 root 1.17 if ((p = strchr (file, ';')) == NULL)
444     p = strchr (file, '\0');
445 pcg 1.7
446 root 1.19 rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file);
447 pcg 1.7 }
448 pcg 1.9 free (f);
449 sasha 1.38 #endif /* HAVE_AFTERIMAGE */
450 pcg 1.1 }
451 pcg 1.10
452 pcg 1.7 resize_pixmap ();
453     return bgPixmap.pixmap;
454 pcg 1.1 }
455    
456     #endif /* XPM_BACKGROUND */
457 ayin 1.39
458     #ifdef TRANSPARENT
459     #if TINTING && !defined(HAVE_AFTERIMAGE)
460     /* taken from aterm-0.4.2 */
461    
462     typedef uint32_t RUINT32T;
463    
464     void ShadeXImage(rxvt_term *term, XImage* srcImage, int shade, int rm, int gm, int bm)
465     {
466     int sh_r, sh_g, sh_b;
467     RUINT32T mask_r, mask_g, mask_b;
468     RUINT32T *lookup, *lookup_r, *lookup_g, *lookup_b;
469     unsigned int lower_lim_r, lower_lim_g, lower_lim_b;
470     unsigned int upper_lim_r, upper_lim_g, upper_lim_b;
471     int i;
472    
473     Visual *visual = term->visual;
474    
475     if( visual->c_class != TrueColor || srcImage->format != ZPixmap ) return ;
476    
477     /* for convenience */
478     mask_r = visual->red_mask;
479     mask_g = visual->green_mask;
480     mask_b = visual->blue_mask;
481    
482     /* boring lookup table pre-initialization */
483     switch (srcImage->bits_per_pixel) {
484     case 15:
485     if ((mask_r != 0x7c00) ||
486     (mask_g != 0x03e0) ||
487     (mask_b != 0x001f))
488     return;
489     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+32+32));
490     lookup_r = lookup;
491     lookup_g = lookup+32;
492     lookup_b = lookup+32+32;
493     sh_r = 10;
494     sh_g = 5;
495     sh_b = 0;
496     break;
497     case 16:
498     if ((mask_r != 0xf800) ||
499     (mask_g != 0x07e0) ||
500     (mask_b != 0x001f))
501     return;
502     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+64+32));
503     lookup_r = lookup;
504     lookup_g = lookup+32;
505     lookup_b = lookup+32+64;
506     sh_r = 11;
507     sh_g = 5;
508     sh_b = 0;
509     break;
510     case 24:
511     if ((mask_r != 0xff0000) ||
512     (mask_g != 0x00ff00) ||
513     (mask_b != 0x0000ff))
514     return;
515     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
516     lookup_r = lookup;
517     lookup_g = lookup+256;
518     lookup_b = lookup+256+256;
519     sh_r = 16;
520     sh_g = 8;
521     sh_b = 0;
522     break;
523     case 32:
524     if ((mask_r != 0xff0000) ||
525     (mask_g != 0x00ff00) ||
526     (mask_b != 0x0000ff))
527     return;
528     lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
529     lookup_r = lookup;
530     lookup_g = lookup+256;
531     lookup_b = lookup+256+256;
532     sh_r = 16;
533     sh_g = 8;
534     sh_b = 0;
535     break;
536     default:
537     return; /* we do not support this color depth */
538     }
539    
540     /* prepare limits for color transformation (each channel is handled separately) */
541     if (shade < 0) {
542     shade = -shade;
543     if (shade < 0) shade = 0;
544     if (shade > 100) shade = 100;
545    
546     lower_lim_r = 65535-rm;
547     lower_lim_g = 65535-gm;
548     lower_lim_b = 65535-bm;
549    
550     lower_lim_r = 65535-(unsigned int)(((RUINT32T)lower_lim_r)*((RUINT32T)shade)/100);
551     lower_lim_g = 65535-(unsigned int)(((RUINT32T)lower_lim_g)*((RUINT32T)shade)/100);
552     lower_lim_b = 65535-(unsigned int)(((RUINT32T)lower_lim_b)*((RUINT32T)shade)/100);
553    
554     upper_lim_r = upper_lim_g = upper_lim_b = 65535;
555     } else {
556     if (shade < 0) shade = 0;
557     if (shade > 100) shade = 100;
558    
559     lower_lim_r = lower_lim_g = lower_lim_b = 0;
560    
561     upper_lim_r = (unsigned int)((((RUINT32T)rm)*((RUINT32T)shade))/100);
562     upper_lim_g = (unsigned int)((((RUINT32T)gm)*((RUINT32T)shade))/100);
563     upper_lim_b = (unsigned int)((((RUINT32T)bm)*((RUINT32T)shade))/100);
564     }
565    
566     /* switch red and blue bytes if necessary, we need it for some weird XServers like XFree86 3.3.3.1 */
567     if ((srcImage->bits_per_pixel == 24) && (mask_r >= 0xFF0000 ))
568     {
569     unsigned int tmp;
570    
571     tmp = lower_lim_r;
572     lower_lim_r = lower_lim_b;
573     lower_lim_b = tmp;
574    
575     tmp = upper_lim_r;
576     upper_lim_r = upper_lim_b;
577     upper_lim_b = tmp;
578     }
579    
580     /* fill our lookup tables */
581     for (i = 0; i <= mask_r>>sh_r; i++)
582     {
583     RUINT32T tmp;
584     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_r-lower_lim_r));
585     tmp += ((RUINT32T)(mask_r>>sh_r))*((RUINT32T)lower_lim_r);
586     lookup_r[i] = (tmp/65535)<<sh_r;
587     }
588     for (i = 0; i <= mask_g>>sh_g; i++)
589     {
590     RUINT32T tmp;
591     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_g-lower_lim_g));
592     tmp += ((RUINT32T)(mask_g>>sh_g))*((RUINT32T)lower_lim_g);
593     lookup_g[i] = (tmp/65535)<<sh_g;
594     }
595     for (i = 0; i <= mask_b>>sh_b; i++)
596     {
597     RUINT32T tmp;
598     tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_b-lower_lim_b));
599     tmp += ((RUINT32T)(mask_b>>sh_b))*((RUINT32T)lower_lim_b);
600     lookup_b[i] = (tmp/65535)<<sh_b;
601     }
602    
603     /* apply table to input image (replacing colors by newly calculated ones) */
604     switch (srcImage->bits_per_pixel)
605     {
606     case 15:
607     {
608     unsigned short *p1, *pf, *p, *pl;
609     p1 = (unsigned short *) srcImage->data;
610     pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
611     while (p1 < pf)
612     {
613     p = p1;
614     pl = p1 + srcImage->width;
615     for (; p < pl; p++)
616     {
617     *p = lookup_r[(*p & 0x7c00)>>10] |
618     lookup_g[(*p & 0x03e0)>> 5] |
619     lookup_b[(*p & 0x001f)];
620     }
621     p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
622     }
623     break;
624     }
625     case 16:
626     {
627     unsigned short *p1, *pf, *p, *pl;
628     p1 = (unsigned short *) srcImage->data;
629     pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
630     while (p1 < pf)
631     {
632     p = p1;
633     pl = p1 + srcImage->width;
634     for (; p < pl; p++)
635     {
636     *p = lookup_r[(*p & 0xf800)>>11] |
637     lookup_g[(*p & 0x07e0)>> 5] |
638     lookup_b[(*p & 0x001f)];
639     }
640     p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
641     }
642     break;
643     }
644     case 24:
645     {
646     unsigned char *p1, *pf, *p, *pl;
647     p1 = (unsigned char *) srcImage->data;
648     pf = (unsigned char *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
649     while (p1 < pf)
650     {
651     p = p1;
652     pl = p1 + srcImage->width * 3;
653     for (; p < pl; p += 3)
654     {
655     p[0] = lookup_r[(p[0] & 0xff0000)>>16];
656     p[1] = lookup_r[(p[1] & 0x00ff00)>> 8];
657     p[2] = lookup_r[(p[2] & 0x0000ff)];
658     }
659     p1 = (unsigned char *) ((char *) p1 + srcImage->bytes_per_line);
660     }
661     break;
662     }
663     case 32:
664     {
665     RUINT32T *p1, *pf, *p, *pl;
666     p1 = (RUINT32T *) srcImage->data;
667     pf = (RUINT32T *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
668    
669     while (p1 < pf)
670     {
671     p = p1;
672     pl = p1 + srcImage->width;
673     for (; p < pl; p++)
674     {
675     *p = lookup_r[(*p & 0xff0000)>>16] |
676     lookup_g[(*p & 0x00ff00)>> 8] |
677     lookup_b[(*p & 0x0000ff)] |
678     (*p & ~0xffffff);
679     }
680     p1 = (RUINT32T *) ((char *) p1 + srcImage->bytes_per_line);
681     }
682     break;
683     }
684     }
685    
686     free (lookup);
687     }
688     #endif
689    
690     /*
691     * Check our parents are still who we think they are.
692     * Do transparency updates if required
693     */
694     int
695     rxvt_term::check_our_parents ()
696     {
697     check_our_parents_ev.stop ();
698     check_our_parents_ev.start (NOW + .1);
699     return 0;
700     }
701    
702     void
703     rxvt_term::check_our_parents_cb (time_watcher &w)
704     {
705     int i, pchanged, aformat, have_pixmap, rootdepth;
706     unsigned long nitems, bytes_after;
707     Atom atype;
708     unsigned char *prop = NULL;
709     Window root, oldp, *list;
710     Pixmap rootpixmap = None;
711     XWindowAttributes wattr, wrootattr;
712     int sx, sy;
713     Window cr;
714    
715     pchanged = 0;
716    
717     if (!option (Opt_transparent))
718     return /*pchanged*/; /* Don't try any more */
719    
720     XGetWindowAttributes (dpy, display->root, &wrootattr);
721     rootdepth = wrootattr.depth;
722    
723     XGetWindowAttributes (dpy, parent[0], &wattr);
724    
725     if (rootdepth != wattr.depth)
726     {
727     if (am_transparent)
728     {
729     pchanged = 1;
730     XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
731     am_transparent = am_pixmap_trans = 0;
732     }
733    
734     return /*pchanged*/; /* Don't try any more */
735     }
736    
737     /* Get all X ops out of the queue so that our information is up-to-date. */
738     XSync (dpy, False);
739    
740     XTranslateCoordinates (dpy, parent[0], display->root,
741     0, 0, &sx, &sy, &cr);
742    
743     /* check if we are outside of the visible part of the virtual screen : */
744     if( sx + (int)szHint.width <= 0 || sy + (int)szHint.height <= 0
745     || sx >= wrootattr.width || sy >= wrootattr.height )
746     return /* 0 */ ;
747     /*
748     * Make the frame window set by the window manager have
749     * the root background. Some window managers put multiple nested frame
750     * windows for each client, so we have to take care about that.
751     */
752     i = (xa[XA_XROOTPMAP_ID]
753     && XGetWindowProperty (dpy, display->root, xa[XA_XROOTPMAP_ID],
754     0L, 1L, False, XA_PIXMAP, &atype, &aformat,
755     &nitems, &bytes_after, &prop) == Success);
756    
757     if (!i || prop == NULL)
758     i = (xa[XA_ESETROOT_PMAP_ID]
759     && XGetWindowProperty (dpy, display->root, xa[XA_ESETROOT_PMAP_ID],
760     0L, 1L, False, XA_PIXMAP, &atype, &aformat,
761     &nitems, &bytes_after, &prop) == Success);
762    
763     if (!i || prop == NULL
764     #if TINTING
765     || (!ISSET_PIXCOLOR (Color_tint) && rs[Rs_shade] == NULL
766     #ifdef HAVE_AFTERIMAGE
767     && original_asim == NULL && rs[Rs_blurradius] == NULL
768     #endif
769     )
770     #endif
771     )
772     have_pixmap = 0;
773     else
774     {
775     have_pixmap = 1;
776     rootpixmap = *(Pixmap *)prop;
777     XFree (prop);
778     }
779    
780     if (have_pixmap)
781     {
782     Bool success = False ;
783     GC gc;
784     XGCValues gcvalue;
785     #ifdef HAVE_AFTERIMAGE
786     {
787     Pixmap tmp_pmap = None ;
788     ShadingInfo shade;
789     ARGB32 tint ;
790     unsigned int pmap_w = 0, pmap_h = 0;
791    
792     if (get_drawable_size( rootpixmap, &pmap_w, &pmap_h ))
793     {
794     int root_x = 0, root_y = 0;
795    
796     shade.shading = rs[Rs_shade] ? atoi (rs[Rs_shade]) : 100;
797     if (ISSET_PIXCOLOR (Color_tint))
798     {
799     rgba c;
800     pix_colors_focused [Color_tint].get (c);
801     shade.tintColor.red = c.r;
802     shade.tintColor.green = c.g;
803     shade.tintColor.blue = c.b;
804     }
805     else
806     shade.tintColor.red = shade.tintColor.green = shade.tintColor.blue = 0xFFFF;
807     tint = shading2tint32( &shade );
808     gc = XCreateGC (dpy, vt, 0UL, &gcvalue);
809     if (GetWinPosition (parent[0], &root_x, &root_y) )
810     {
811     ASImageLayer *layers = create_image_layers( 2 );
812     ASImage *merged_im = NULL;
813     int back_x, back_y, back_w, back_h;
814     /* merge_layers does good job at tiling background appropriately,
815     so all we need is to cut out smallest possible piece : */
816     #define MAKE_ROOTPMAP_GEOM(xy,wh,widthheight) \
817     do{ while( root_##xy < 0 ) root_##xy += (int)wrootattr.widthheight; \
818     back_##xy = root_##xy % pmap_##wh; /* that gives us left side of the closest tile : */ \
819     if( pmap_##wh >= back_##xy + szHint.widthheight ) \
820     back_##wh = szHint.widthheight;/* background is large - limit it by our size */ \
821     else \
822     { /* small background - need the whole of it for successfull tiling :*/ \
823     back_##xy = 0; \
824     back_##wh = pmap_##wh; \
825     }}while(0)
826    
827     MAKE_ROOTPMAP_GEOM(x,w,width);
828     MAKE_ROOTPMAP_GEOM(y,h,height);
829    
830     layers[0].im = pixmap2asimage (display->asv, rootpixmap, back_x, back_y, back_w, back_h, AllPlanes, ASA_ASImage, 100);
831     layers[0].clip_x = (back_w == pmap_w)?root_x:0;
832     layers[0].clip_y = (back_h == pmap_h)?root_y:0;
833     layers[0].clip_width = szHint.width;
834     layers[0].clip_height = szHint.height;
835     layers[0].tint = tint;
836     if (rs[Rs_blurradius] && layers[0].im)
837     {
838     double r = atof(rs[Rs_blurradius]);
839     ASImage* tmp = blur_asimage_gauss(display->asv, layers[0].im, r, r, 0xFFFFFFFF, ASA_ASImage, 100, ASIMAGE_QUALITY_DEFAULT );
840     if( tmp )
841     {
842     destroy_asimage( &layers[0].im );
843     layers[0].im = tmp;
844     }
845     }
846     if (original_asim != NULL)
847     {
848     int fore_w, fore_h;
849     layers[1].im = original_asim;
850     if( bgPixmap.auto_resize )
851     {
852     fore_w = szHint.width;
853     fore_h = szHint.height;
854     }
855     else
856     {
857     fore_w = bgPixmap.w;
858     fore_h = bgPixmap.h;
859     }
860     if (fore_w != original_asim->width
861     || fore_h != original_asim->height)
862     {
863     layers[1].im = scale_asimage( display->asv,
864     original_asim,
865     fore_w, fore_h,
866     ASA_ASImage, 100,
867     ASIMAGE_QUALITY_DEFAULT );
868     }
869    
870     layers[1].clip_width = szHint.width;
871     layers[1].clip_height = szHint.height;
872    
873     if (rs[Rs_blendtype])
874     {
875     layers[1].merge_scanlines = blend_scanlines_name2func(rs[Rs_blendtype]);
876     if( layers[1].merge_scanlines == NULL )
877     layers[1].merge_scanlines = alphablend_scanlines;
878     }
879     }
880     merged_im = merge_layers( display->asv, layers, layers[1].im?2:1,
881     szHint.width, szHint.height,
882     ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT );
883     if (layers[1].im != original_asim)
884     destroy_asimage( &(layers[1].im) );
885     destroy_asimage( &(layers[0].im) );
886     if (merged_im != NULL)
887     {
888     tmp_pmap = asimage2pixmap( display->asv, DefaultRootWindow(dpy), merged_im, gc, True );
889     destroy_asimage( &merged_im );
890     }
891     free( layers );
892     }
893     }
894     if (tmp_pmap != None)
895     {
896     success = True;
897     if (pixmap != None)
898     XFreePixmap (dpy, pixmap);
899     pixmap = tmp_pmap;
900     }
901     }
902     #else /* HAVE_AFTERIMAGE */
903     {
904     /*
905     * Copy display->root pixmap transparency
906     */
907     int nx, ny;
908     unsigned int nw, nh;
909     XImage *image;
910    
911     nw = (unsigned int)szHint.width;
912     nh = (unsigned int)szHint.height;
913     nx = ny = 0;
914    
915     if (sx < 0)
916     {
917     nw += sx;
918     nx = -sx;
919     sx = 0;
920     }
921    
922     if (sy < 0)
923     {
924     nh += sy;
925     ny = -sy;
926     sy = 0;
927     }
928    
929     min_it (nw, (unsigned int) (wrootattr.width - sx));
930     min_it (nh, (unsigned int) (wrootattr.height - sy));
931    
932     XSync (dpy, False);
933     allowedxerror = -1;
934     image = XGetImage (dpy, rootpixmap, sx, sy, nw, nh, AllPlanes, ZPixmap);
935    
936     /* XXX: handle BadMatch - usually because we're outside the pixmap */
937     /* XXX: may need a delay here? */
938     allowedxerror = 0;
939     if (image != NULL)
940     {
941     if (pixmap != None)
942     XFreePixmap (dpy, pixmap);
943    
944     #if TINTING
945     if (ISSET_PIXCOLOR (Color_tint))
946     {
947     int shade = rs[Rs_shade] ? atoi (rs[Rs_shade]) : 100;
948    
949     rgba c;
950     pix_colors_focused [Color_tint].get (c);
951     ShadeXImage (this, image, shade, c.r, c.g, c.b);
952     }
953     #endif
954    
955     pixmap = XCreatePixmap (dpy, vt, szHint.width, szHint.height, image->depth);
956     gc = XCreateGC (dpy, vt, 0UL, &gcvalue);
957     XPutImage (dpy, pixmap, gc, image, 0, 0,
958     nx, ny, image->width, image->height);
959     XDestroyImage (image);
960     success = True ;
961     }
962     }
963     #endif /* HAVE_AFTERIMAGE */
964     if (gc != NULL)
965     XFreeGC (dpy, gc);
966    
967     if (!success)
968     {
969     if (am_transparent && am_pixmap_trans)
970     {
971     pchanged = 1;
972     if (pixmap != None)
973     {
974     XFreePixmap (dpy, pixmap);
975     pixmap = None;
976     }
977     }
978    
979     am_pixmap_trans = 0;
980     }
981     else
982     {
983     XSetWindowBackgroundPixmap (dpy, parent[0], pixmap);
984     XClearWindow (dpy, parent[0]);
985    
986     if (!am_transparent || !am_pixmap_trans)
987     pchanged = 1;
988    
989     am_transparent = am_pixmap_trans = 1;
990     }
991     }
992    
993     if (am_pixmap_trans)
994     XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
995     else
996     {
997     unsigned int n;
998     /*
999     * InheritPixmap transparency
1000     */
1001     for (i = 1; i < (int) (sizeof (parent) / sizeof (Window)); i++)
1002     {
1003     oldp = parent[i];
1004     XQueryTree (dpy, parent[i - 1], &root, &parent[i], &list, &n);
1005     XFree (list);
1006    
1007     if (parent[i] == display->root)
1008     {
1009     if (oldp != None)
1010     pchanged = 1;
1011    
1012     break;
1013     }
1014    
1015     if (oldp != parent[i])
1016     pchanged = 1;
1017     }
1018    
1019     n = 0;
1020    
1021     if (pchanged)
1022     for (; n < (unsigned int)i; n++)
1023     {
1024     XGetWindowAttributes (dpy, parent[n], &wattr);
1025    
1026     if (wattr.depth != rootdepth || wattr.c_class == InputOnly)
1027     {
1028     n = (int) (sizeof (parent) / sizeof (Window)) + 1;
1029     break;
1030     }
1031     }
1032    
1033     if (n > (sizeof (parent) / sizeof (parent[0])))
1034     {
1035     XSetWindowBackground (dpy, parent[0], pix_colors_focused[Color_border]);
1036     XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
1037     am_transparent = 0;
1038     /* XXX: also turn off Opt_transparent? */
1039     }
1040     else
1041     {
1042     for (n = 0; n < (unsigned int)i; n++)
1043     {
1044     XSetWindowBackgroundPixmap (dpy, parent[n], ParentRelative);
1045     XClearWindow (dpy, parent[n]);
1046     }
1047    
1048     XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
1049     am_transparent = 1;
1050     }
1051    
1052     for (; i < (int) (sizeof (parent) / sizeof (Window)); i++)
1053     parent[i] = None;
1054     }
1055    
1056     if (scrollBar.win)
1057     {
1058     XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative);
1059     scrollBar.setIdle ();
1060     scrollbar_show (0);
1061     }
1062    
1063     if (am_transparent)
1064     {
1065     want_refresh = want_full_refresh = 1;
1066     if (am_pixmap_trans)
1067     flush ();
1068     }
1069    
1070     // return pchanged;
1071     }
1072     #endif