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