ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.42
Committed: Wed Jun 27 20:26:15 2007 UTC (16 years, 11 months ago) by ayin
Content type: text/plain
Branch: MAIN
Changes since 1.41: +4 -1 lines
Log Message:
strndup is not portable.

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