ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.57
Committed: Fri Aug 3 23:32:14 2007 UTC (16 years, 9 months ago) by ayin
Content type: text/plain
Branch: MAIN
Changes since 1.56: +1 -9 lines
Log Message:
Remove --enable-tinting and make --enable-transparency enable also the tinting
code.

File Contents

# Content
1 /*----------------------------------------------------------------------*
2 * File: xpm.C
3 *----------------------------------------------------------------------*
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 * Copyright (c) 2005-2006 Marc Lehmann <pcg@goof.com>
10 *
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 /*
30 * Pixmap geometry string interpretation :
31 * Each geometry string contains zero or one scale/position
32 * adjustment and may optionally be followed by a colon and one or more
33 * colon-delimited pixmap operations.
34 * The following table shows the valid geometry strings and their
35 * affects on the background image :
36 *
37 * WxH+X+Y Set scaling to W% by H%, and position to X% by Y%.
38 * W and H are percentages of the terminal window size.
39 * X and Y are also percentages; e.g., +50+50 centers
40 * the image in the window.
41 * WxH+X Assumes Y == X
42 * WxH Assumes Y == X == 50 (centers the image)
43 * W+X+Y Assumes H == W
44 * W+X Assumes H == W and Y == X
45 * W Assumes H == W and Y == X == 50
46 *
47 * Adjusting position only :
48 * =+X+Y Set position to X% by Y% (absolute).
49 * =+X Set position to X% by X%.
50 * +X+Y Adjust position horizontally X% and vertically Y%
51 * from current position (relative).
52 * +X+X Adjust position horizontally X% and vertically X%
53 * from current position.
54 *
55 * Adjusting scale only :
56 * Wx0 Multiply horizontal scaling factor by W%
57 * 0xH Multiply vertical scaling factor by H%
58 * 0x0 No scaling (show image at normal size).
59 *
60 * Pixmap Operations : (should be prepended by a colon)
61 * tile Tile image. Scaling/position modifiers above will affect
62 * the tile size and origin.
63 * propscale When scaling, scale proportionally. That is, maintain the
64 * proper aspect ratio for the image. Any portion of the
65 * background not covered by the image is filled with the
66 * current background color.
67 * hscale Scale horizontally, tile vertically ?
68 * vscale Tile horizontally, scale vertically ?
69 * scale Scale both up and down
70 * auto Same as 100x100+50+50
71 */
72
73 #ifdef HAVE_BG_PIXMAP
74 bool
75 bgPixmap_t::window_size_sensitive ()
76 {
77 return (flags&(bgPmap_Scale|bgPmap_Transparent));
78 }
79
80 #ifdef XPM_BACKGROUND
81 bool
82 bgPixmap_t::handle_geometry (const char *geom)
83 {
84 int geom_flags, changed = 0;
85 int x = 0, y = 0;
86 unsigned int w = 0, h = 0;
87 unsigned int n;
88 unsigned long new_flags = (flags&(~bgPmap_geometryFlags)) ;
89 char *p;
90 #define MAXLEN_GEOM sizeof("[10000x10000+10000+10000]")
91
92 if (geom == NULL)
93 return false;
94
95 char str[MAXLEN_GEOM];
96
97 if (!strcmp (geom, "?"))
98 {
99 #if 0 /* TODO: */
100 sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
101 min (h_scale, 32767), min (v_scale, 32767),
102 min (h_align, 32767), min (v_align, 32767));
103 process_xterm_seq (XTerm_title, str, CHAR_ST);
104 #endif
105 return false;
106 }
107
108 if ((p = strchr (geom, ';')) == NULL)
109 p = strchr (geom, '\0');
110
111 n = (p - geom);
112 if (n < MAXLEN_GEOM)
113 {
114 new_flags |= bgPmap_geometrySet;
115
116 strncpy (str, geom, n);
117 str[n] = '\0';
118
119 if (strcmp(str, "auto") == 0)
120 {
121 w = h = 100;
122 geom_flags = WidthValue|HeightValue ;
123 }
124 else
125 {
126 geom_flags = XParseGeometry (str, &x, &y, &w, &h);
127 }
128 /* code below is garbage and needs to be rewritten */
129 if (!geom_flags)
130 {
131 geom_flags |= WidthValue;
132 w = 0;
133 } /* default is tile */
134
135 if (geom_flags & WidthValue)
136 {
137 if (!(geom_flags & XValue))
138 x = 50;
139
140 if (!(geom_flags & HeightValue))
141 h = w;
142
143 if (w && !h)
144 {
145 w = (h_scale * w) / 100;
146 h = v_scale;
147 }
148 else if (h && !w)
149 {
150 w = h_scale;
151 h = (v_scale * h) / 100;
152 }
153
154 min_it (w, 32767);
155 min_it (h, 32767);
156
157 if (h_scale != w)
158 {
159 h_scale = w;
160 changed++;
161 }
162
163 if (v_scale != h)
164 {
165 v_scale = h;
166 changed++;
167 }
168 }
169 if (!(geom_flags & YValue))
170 {
171 if (geom_flags & XNegative)
172 geom_flags |= YNegative;
173
174 y = x;
175 }
176
177 if (!(geom_flags & WidthValue) && geom[0] != '=')
178 {
179 x += h_align;
180 y += v_align;
181 }
182
183 if (h_align != x)
184 {
185 h_align = x;
186 changed++;
187 }
188
189 if (v_align != y)
190 {
191 v_align = y;
192 changed++;
193 }
194
195 if (h_scale != 0)
196 new_flags |= bgPmap_hScale;
197 if (v_scale != 0)
198 new_flags |= bgPmap_vScale;
199 }
200
201 if (new_flags != flags)
202 {
203 flags = new_flags;
204 changed++;
205 }
206 return (changed > 0);
207 }
208
209 void
210 rxvt_term::resize_pixmap ()
211 {
212 XGCValues gcvalue;
213 GC gc;
214 unsigned int w = bgPixmap.h_scale*szHint.width/100;
215 unsigned int h = bgPixmap.v_scale*szHint.height/100;
216 int x = bgPixmap.h_align*szHint.width/100;
217 int y = bgPixmap.v_align*szHint.height/100;
218 #ifdef HAVE_AFTERIMAGE
219 ASImage *im = bgPixmap.original_asim;
220 #else
221 void *im = NULL;
222 #endif
223 /* preliminary cleanup - this needs to be integrated with check_our_parents() code */
224 if (bgPixmap.pixmap != None)
225 {
226 XFreePixmap (dpy, bgPixmap.pixmap);
227 bgPixmap.pixmap = None ;
228 }
229 #ifdef ENABLE_TRANSPARENCY
230 if (option(Opt_transparent) && am_transparent)
231 {
232 /* we need to re-generate transparency pixmap in that case ! */
233 check_our_parents ();
234 return;
235 }
236 #endif
237
238 if (im == NULL)
239 { /* So be it: I'm not using pixmaps */
240 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
241 return;
242 }
243
244 gcvalue.foreground = pix_colors[Color_bg];
245 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
246
247 /* don't zoom pixmap too much nor expand really small pixmaps */
248 if (w > 16000)
249 w = 1;
250 if (h > 16000)
251 h = 1;
252
253 #ifdef HAVE_AFTERIMAGE
254 if (w == 0)
255 w = im->width;
256 if (h == 0)
257 h = im->height;
258
259 if (w != im->width || h != im->height)
260 {
261 ASImage *tmp = scale_asimage (asv, im, w, h, (x == 0 && y == 0)?ASA_XImage:ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
262 if (tmp != NULL)
263 im = tmp;
264 }
265 bgPixmap.pmap_width = MIN(w,szHint.width);
266 bgPixmap.pmap_height = MIN(h,szHint.height);
267 #if 0 /* TODO: fix that! */
268 if (x != 0 || y != 0)
269 {
270 ASImage *tmp = tile_asimage (asv, im, x, y, w, h, TINT_LEAVE_SAME, ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
271 if (tmp != NULL)
272 {
273 if (im != bgPixmap.original_asim)
274 destroy_asimage (&im);
275 im = tmp;
276 }
277 }
278 #endif
279 bgPixmap.pixmap = XCreatePixmap (dpy, vt, bgPixmap.pmap_width, bgPixmap.pmap_height, depth);
280 bgPixmap.pmap_depth = depth;
281
282 asimage2drawable (asv, bgPixmap.pixmap, im, gc, 0, 0, 0, 0, bgPixmap.pmap_width, bgPixmap.pmap_height, True);
283
284 if (im != bgPixmap.original_asim)
285 destroy_asimage (&im);
286 #endif
287 if( bgPixmap.pixmap )
288 XSetWindowBackgroundPixmap (dpy, vt, bgPixmap.pixmap);
289
290 XFreeGC (dpy, gc);
291 }
292
293 void
294 rxvt_term::set_bgPixmap (const char *file)
295 {
296 char *f;
297
298 assert (file != NULL);
299
300 if (bgPixmap.pixmap != None)
301 {
302 XFreePixmap (dpy, bgPixmap.pixmap);
303 bgPixmap.pixmap = None;
304 }
305
306 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
307 if (*file != '\0')
308 {
309 #ifdef HAVE_AFTERIMAGE
310 if (asimman == NULL)
311 asimman = create_generic_imageman(rs[Rs_path]);
312 if ((f = strchr (file, ';')) == NULL)
313 bgPixmap.original_asim = get_asimage( asimman, file, 0xFFFFFFFF, 100 );
314 else
315 {
316 size_t len = f - file;
317 f = (char *)malloc (len + 1);
318 strncpy (f, file, len);
319 f[len] = '\0';
320 bgPixmap.original_asim = get_asimage( asimman, f, 0xFFFFFFFF, 100 );
321 free( f );
322 }
323 #endif
324 }
325
326 resize_pixmap ();
327 }
328
329 #endif /* XPM_BACKGROUND */
330 #endif /* HAVE_BG_PIXMAP */
331
332 #ifdef ENABLE_TRANSPARENCY
333 #ifndef HAVE_AFTERIMAGE
334 /* taken from aterm-0.4.2 */
335
336 typedef uint32_t RUINT32T;
337
338 static void
339 ShadeXImage(rxvt_term *term, XImage* srcImage, int shade, int rm, int gm, int bm)
340 {
341 int sh_r, sh_g, sh_b;
342 RUINT32T mask_r, mask_g, mask_b;
343 RUINT32T *lookup, *lookup_r, *lookup_g, *lookup_b;
344 unsigned int lower_lim_r, lower_lim_g, lower_lim_b;
345 unsigned int upper_lim_r, upper_lim_g, upper_lim_b;
346 int i;
347
348 Visual *visual = term->visual;
349
350 if( visual->c_class != TrueColor || srcImage->format != ZPixmap ) return ;
351
352 /* for convenience */
353 mask_r = visual->red_mask;
354 mask_g = visual->green_mask;
355 mask_b = visual->blue_mask;
356
357 /* boring lookup table pre-initialization */
358 switch (srcImage->bits_per_pixel) {
359 case 15:
360 if ((mask_r != 0x7c00) ||
361 (mask_g != 0x03e0) ||
362 (mask_b != 0x001f))
363 return;
364 lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+32+32));
365 lookup_r = lookup;
366 lookup_g = lookup+32;
367 lookup_b = lookup+32+32;
368 sh_r = 10;
369 sh_g = 5;
370 sh_b = 0;
371 break;
372 case 16:
373 if ((mask_r != 0xf800) ||
374 (mask_g != 0x07e0) ||
375 (mask_b != 0x001f))
376 return;
377 lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+64+32));
378 lookup_r = lookup;
379 lookup_g = lookup+32;
380 lookup_b = lookup+32+64;
381 sh_r = 11;
382 sh_g = 5;
383 sh_b = 0;
384 break;
385 case 24:
386 if ((mask_r != 0xff0000) ||
387 (mask_g != 0x00ff00) ||
388 (mask_b != 0x0000ff))
389 return;
390 lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
391 lookup_r = lookup;
392 lookup_g = lookup+256;
393 lookup_b = lookup+256+256;
394 sh_r = 16;
395 sh_g = 8;
396 sh_b = 0;
397 break;
398 case 32:
399 if ((mask_r != 0xff0000) ||
400 (mask_g != 0x00ff00) ||
401 (mask_b != 0x0000ff))
402 return;
403 lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
404 lookup_r = lookup;
405 lookup_g = lookup+256;
406 lookup_b = lookup+256+256;
407 sh_r = 16;
408 sh_g = 8;
409 sh_b = 0;
410 break;
411 default:
412 return; /* we do not support this color depth */
413 }
414
415 /* prepare limits for color transformation (each channel is handled separately) */
416 if (shade < 0) {
417 shade = -shade;
418 if (shade < 0) shade = 0;
419 if (shade > 100) shade = 100;
420
421 lower_lim_r = 65535-rm;
422 lower_lim_g = 65535-gm;
423 lower_lim_b = 65535-bm;
424
425 lower_lim_r = 65535-(unsigned int)(((RUINT32T)lower_lim_r)*((RUINT32T)shade)/100);
426 lower_lim_g = 65535-(unsigned int)(((RUINT32T)lower_lim_g)*((RUINT32T)shade)/100);
427 lower_lim_b = 65535-(unsigned int)(((RUINT32T)lower_lim_b)*((RUINT32T)shade)/100);
428
429 upper_lim_r = upper_lim_g = upper_lim_b = 65535;
430 } else {
431 if (shade < 0) shade = 0;
432 if (shade > 100) shade = 100;
433
434 lower_lim_r = lower_lim_g = lower_lim_b = 0;
435
436 upper_lim_r = (unsigned int)((((RUINT32T)rm)*((RUINT32T)shade))/100);
437 upper_lim_g = (unsigned int)((((RUINT32T)gm)*((RUINT32T)shade))/100);
438 upper_lim_b = (unsigned int)((((RUINT32T)bm)*((RUINT32T)shade))/100);
439 }
440
441 /* switch red and blue bytes if necessary, we need it for some weird XServers like XFree86 3.3.3.1 */
442 if ((srcImage->bits_per_pixel == 24) && (mask_r >= 0xFF0000 ))
443 {
444 unsigned int tmp;
445
446 tmp = lower_lim_r;
447 lower_lim_r = lower_lim_b;
448 lower_lim_b = tmp;
449
450 tmp = upper_lim_r;
451 upper_lim_r = upper_lim_b;
452 upper_lim_b = tmp;
453 }
454
455 /* fill our lookup tables */
456 for (i = 0; i <= mask_r>>sh_r; i++)
457 {
458 RUINT32T tmp;
459 tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_r-lower_lim_r));
460 tmp += ((RUINT32T)(mask_r>>sh_r))*((RUINT32T)lower_lim_r);
461 lookup_r[i] = (tmp/65535)<<sh_r;
462 }
463 for (i = 0; i <= mask_g>>sh_g; i++)
464 {
465 RUINT32T tmp;
466 tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_g-lower_lim_g));
467 tmp += ((RUINT32T)(mask_g>>sh_g))*((RUINT32T)lower_lim_g);
468 lookup_g[i] = (tmp/65535)<<sh_g;
469 }
470 for (i = 0; i <= mask_b>>sh_b; i++)
471 {
472 RUINT32T tmp;
473 tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_b-lower_lim_b));
474 tmp += ((RUINT32T)(mask_b>>sh_b))*((RUINT32T)lower_lim_b);
475 lookup_b[i] = (tmp/65535)<<sh_b;
476 }
477
478 /* apply table to input image (replacing colors by newly calculated ones) */
479 switch (srcImage->bits_per_pixel)
480 {
481 case 15:
482 {
483 unsigned short *p1, *pf, *p, *pl;
484 p1 = (unsigned short *) srcImage->data;
485 pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
486 while (p1 < pf)
487 {
488 p = p1;
489 pl = p1 + srcImage->width;
490 for (; p < pl; p++)
491 {
492 *p = lookup_r[(*p & 0x7c00)>>10] |
493 lookup_g[(*p & 0x03e0)>> 5] |
494 lookup_b[(*p & 0x001f)];
495 }
496 p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
497 }
498 break;
499 }
500 case 16:
501 {
502 unsigned short *p1, *pf, *p, *pl;
503 p1 = (unsigned short *) srcImage->data;
504 pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
505 while (p1 < pf)
506 {
507 p = p1;
508 pl = p1 + srcImage->width;
509 for (; p < pl; p++)
510 {
511 *p = lookup_r[(*p & 0xf800)>>11] |
512 lookup_g[(*p & 0x07e0)>> 5] |
513 lookup_b[(*p & 0x001f)];
514 }
515 p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
516 }
517 break;
518 }
519 case 24:
520 {
521 unsigned char *p1, *pf, *p, *pl;
522 p1 = (unsigned char *) srcImage->data;
523 pf = (unsigned char *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
524 while (p1 < pf)
525 {
526 p = p1;
527 pl = p1 + srcImage->width * 3;
528 for (; p < pl; p += 3)
529 {
530 p[0] = lookup_r[(p[0] & 0xff0000)>>16];
531 p[1] = lookup_r[(p[1] & 0x00ff00)>> 8];
532 p[2] = lookup_r[(p[2] & 0x0000ff)];
533 }
534 p1 = (unsigned char *) ((char *) p1 + srcImage->bytes_per_line);
535 }
536 break;
537 }
538 case 32:
539 {
540 RUINT32T *p1, *pf, *p, *pl;
541 p1 = (RUINT32T *) srcImage->data;
542 pf = (RUINT32T *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
543
544 while (p1 < pf)
545 {
546 p = p1;
547 pl = p1 + srcImage->width;
548 for (; p < pl; p++)
549 {
550 *p = lookup_r[(*p & 0xff0000)>>16] |
551 lookup_g[(*p & 0x00ff00)>> 8] |
552 lookup_b[(*p & 0x0000ff)] |
553 (*p & ~0xffffff);
554 }
555 p1 = (RUINT32T *) ((char *) p1 + srcImage->bytes_per_line);
556 }
557 break;
558 }
559 }
560
561 free (lookup);
562 }
563 #endif
564
565 /*
566 * Check our parents are still who we think they are.
567 * Do transparency updates if required
568 */
569 int
570 rxvt_term::check_our_parents ()
571 {
572 check_our_parents_ev.stop ();
573 check_our_parents_ev.start (NOW + .1);
574 return 0;
575 }
576
577 void
578 rxvt_term::check_our_parents_cb (time_watcher &w)
579 {
580 int i, pchanged, aformat, rootdepth;
581 unsigned long nitems, bytes_after;
582 Atom atype;
583 unsigned char *prop = NULL;
584 Window root, oldp, *list;
585 Pixmap rootpixmap = None;
586 XWindowAttributes wattr, wrootattr;
587 int sx, sy;
588 Window cr;
589 unsigned int rootpixmap_w = 0, rootpixmap_h = 0;
590
591 pchanged = 0;
592
593 if (!option (Opt_transparent))
594 return /*pchanged*/; /* Don't try any more */
595
596 #if 0
597 struct timeval stv;
598 gettimeofday (&stv,NULL);
599 #define PRINT_BACKGROUND_OP_TIME do{ struct timeval tv;gettimeofday (&tv,NULL); tv.tv_sec-= stv.tv_sec;\
600 fprintf (stderr,"%d: elapsed %ld usec\n",__LINE__,\
601 tv.tv_sec*1000000+tv.tv_usec-stv.tv_usec );}while(0)
602 #else
603 #define PRINT_BACKGROUND_OP_TIME do{}while(0)
604 #endif
605
606
607 XGetWindowAttributes (dpy, display->root, &wrootattr);
608 rootdepth = wrootattr.depth;
609
610 XGetWindowAttributes (dpy, parent[0], &wattr);
611
612 if (rootdepth != wattr.depth)
613 {
614 if (am_transparent)
615 {
616 pchanged = 1;
617 XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
618 am_transparent = am_pixmap_trans = 0;
619 }
620
621 return /*pchanged*/; /* Don't try any more */
622 }
623
624 /* Get all X ops out of the queue so that our information is up-to-date. */
625 XSync (dpy, False);
626
627 XTranslateCoordinates (dpy, parent[0], display->root,
628 0, 0, &sx, &sy, &cr);
629 /* check if we are outside of the visible part of the virtual screen : */
630 if( sx + (int)szHint.width <= 0 || sy + (int)szHint.height <= 0
631 || sx >= wrootattr.width || sy >= wrootattr.height )
632 return /* 0 */ ;
633 /*
634 * Make the frame window set by the window manager have
635 * the root background. Some window managers put multiple nested frame
636 * windows for each client, so we have to take care about that.
637 */
638 i = (xa[XA_XROOTPMAP_ID]
639 && XGetWindowProperty (dpy, display->root, xa[XA_XROOTPMAP_ID],
640 0L, 1L, False, XA_PIXMAP, &atype, &aformat,
641 &nitems, &bytes_after, &prop) == Success);
642
643 if (!i || prop == NULL)
644 i = (xa[XA_ESETROOT_PMAP_ID]
645 && XGetWindowProperty (dpy, display->root, xa[XA_ESETROOT_PMAP_ID],
646 0L, 1L, False, XA_PIXMAP, &atype, &aformat,
647 &nitems, &bytes_after, &prop) == Success);
648
649 /* TODO: the below logic needs to be cleaned up */
650 if (!i || prop == NULL
651 || (!ISSET_PIXCOLOR (Color_tint) && rs[Rs_shade] == NULL
652 #ifdef HAVE_AFTERIMAGE
653 && bgPixmap.original_asim == NULL && rs[Rs_blurradius] == NULL
654 #endif
655 )
656 )
657 rootpixmap = None;
658 else
659 {
660 int junk;
661 unsigned int ujunk;
662 /* root pixmap may be bad - allow a error */
663 allowedxerror = -1;
664 if ((rootpixmap = *(Pixmap *)prop) != None)
665 if (!XGetGeometry (dpy, rootpixmap, &root, &junk, &junk, &rootpixmap_w, &rootpixmap_h, &ujunk, &ujunk))
666 rootpixmap = None;
667 allowedxerror = 0;
668 }
669
670 if (prop != NULL)
671 XFree (prop);
672
673 if (rootpixmap != None)
674 {
675 Bool success = False;
676 GC gc = NULL;
677 XGCValues gcvalue;
678 int shade = 100;
679 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
680 Bool whole_tint = False, no_tint = True;
681
682 while (sx < 0) sx += (int)wrootattr.width;
683 while (sy < 0) sy += (int)wrootattr.height;
684
685 if (rs[Rs_shade])
686 shade = atoi (rs[Rs_shade]);
687 if (ISSET_PIXCOLOR (Color_tint))
688 pix_colors_focused [Color_tint].get (c);
689 #define IS_COMPONENT_WHOLESOME(c) ((c) <=0x000700 || (c)>=0x00f700)
690 if (shade >= 100)
691 whole_tint = (IS_COMPONENT_WHOLESOME(c.r)
692 && IS_COMPONENT_WHOLESOME(c.g)
693 && IS_COMPONENT_WHOLESOME(c.b));
694 no_tint = (c.r >= 0x00f700 && c.g >= 0x00f700 && c.b >= 0x00f700);
695 #undef IS_COMPONENT_WHOLESOME
696 /* theer are no performance advantages to reusing same pixmap */
697 if (bgPixmap.pixmap != None)
698 XFreePixmap (dpy, bgPixmap.pixmap);
699 bgPixmap.pixmap = XCreatePixmap (dpy, vt, szHint.width, szHint.height, rootdepth);
700 bgPixmap.pmap_width = szHint.width;
701 bgPixmap.pmap_height = szHint.height;
702 bgPixmap.pmap_depth = rootdepth;
703
704 #if 0 /* TODO : identify cases where this will be detrimental to performance : */
705 /* we want to tile root pixmap into our own pixmap in this cases :
706 * 1) rootpixmap does not cover our window entirely
707 * 2) whole_tint - we can use server-side tinting or tinting disabled
708 */
709 if ( whole_tint || no_tint || pmap_w < sx + szHint.width || pmap_h < sy + szHint.height)
710 {
711 }
712 #endif
713 gcvalue.tile = rootpixmap;
714 gcvalue.fill_style = FillTiled;
715 gcvalue.ts_x_origin = -sx;
716 gcvalue.ts_y_origin = -sy;
717 gc = XCreateGC (dpy, rootpixmap, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcvalue);
718 XFillRectangle (dpy, bgPixmap.pixmap, gc, 0, 0, szHint.width, szHint.height);
719
720 if (whole_tint && !no_tint)
721 {
722 /* In this case we can tint image server-side getting significant
723 * performance improvements, as we eliminate XImage transfer
724 */
725 gcvalue.foreground = Pixel (pix_colors_focused [Color_tint]);
726 gcvalue.function = GXand;
727 gcvalue.fill_style = FillSolid;
728 XChangeGC (dpy, gc, GCFillStyle | GCForeground | GCFunction, &gcvalue);
729 XFillRectangle (dpy, bgPixmap.pixmap, gc, 0, 0, szHint.width, szHint.height);
730 }
731 success = True;
732 #ifdef HAVE_AFTERIMAGE
733 if (rs[Rs_blurradius] || bgPixmap.original_asim != NULL || (!whole_tint && (!no_tint || shade !=100)))
734 {
735 ARGB32 tint = TINT_LEAVE_SAME;
736 ASImage *back_im = NULL;
737
738 back_im = pixmap2ximage (asv, bgPixmap.pixmap, 0, 0, szHint.width, szHint.height, AllPlanes, 100);
739 if (back_im != NULL)
740 {
741 if (!whole_tint && (!no_tint || shade !=100))
742 {
743 ShadingInfo as_shade;
744 as_shade.shading = shade;
745 as_shade.tintColor.red = c.r;
746 as_shade.tintColor.green = c.g;
747 as_shade.tintColor.blue = c.b;
748 tint = shading2tint32 (&as_shade);
749 }
750
751 if (rs[Rs_blurradius] && back_im)
752 {
753 ASImage* tmp;
754 int junk;
755 unsigned int hr = 1, vr = 1;
756 int flags = XParseGeometry (rs[Rs_blurradius], &junk, &junk, &hr, &vr);
757 if (!(flags&WidthValue))
758 hr = 1;
759 if (!(flags&HeightValue))
760 vr = hr;
761 tmp = blur_asimage_gauss (asv, back_im, hr, vr, 0xFFFFFFFF,
762 (bgPixmap.original_asim == NULL || tint == TINT_LEAVE_SAME)?ASA_XImage:ASA_ASImage,
763 100, ASIMAGE_QUALITY_DEFAULT);
764 if (tmp)
765 {
766 destroy_asimage (&back_im);
767 back_im = tmp;
768 }
769 }
770
771 if (bgPixmap.original_asim != NULL)
772 {
773 ASImageLayer *layers = create_image_layers (2);
774 ASImage *merged_im = NULL;
775 int fore_w, fore_h;
776
777 layers[0].im = back_im;
778 layers[0].clip_width = szHint.width;
779 layers[0].clip_height = szHint.height;
780 layers[0].tint = tint;
781 layers[1].im = bgPixmap.original_asim;
782
783 fore_w = (bgPixmap.h_scale == 0) ? bgPixmap.original_asim->width : bgPixmap.h_scale*szHint.width/100;
784 fore_h = (bgPixmap.v_scale == 0) ? bgPixmap.original_asim->height : bgPixmap.v_scale*szHint.height/100;
785
786 if (fore_w != bgPixmap.original_asim->width
787 || fore_h != bgPixmap.original_asim->height)
788 {
789 layers[1].im = scale_asimage (asv,
790 bgPixmap.original_asim,
791 fore_w, fore_h,
792 ASA_ASImage, 100,
793 ASIMAGE_QUALITY_DEFAULT);
794 }
795 layers[1].clip_width = szHint.width;
796 layers[1].clip_height = szHint.height;
797
798 if (rs[Rs_blendtype])
799 {
800 layers[1].merge_scanlines = blend_scanlines_name2func (rs[Rs_blendtype]);
801 if (layers[1].merge_scanlines == NULL)
802 layers[1].merge_scanlines = alphablend_scanlines;
803 }
804 PRINT_BACKGROUND_OP_TIME;
805 merged_im = merge_layers (asv, layers, 2, szHint.width, szHint.height,
806 ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
807 if (layers[1].im != bgPixmap.original_asim)
808 destroy_asimage (&(layers[1].im));
809 free (layers);
810
811 if (merged_im != NULL)
812 {
813 destroy_asimage (&back_im);
814 back_im = merged_im;
815 }
816 PRINT_BACKGROUND_OP_TIME;
817 }
818 else if (tint != TINT_LEAVE_SAME)
819 {
820 ASImage* tmp = tile_asimage (asv, back_im, 0, 0, szHint.width, szHint.height, tint, ASA_XImage, 100, ASIMAGE_QUALITY_DEFAULT);
821 if (tmp)
822 {
823 destroy_asimage (&back_im);
824 back_im = tmp;
825 }
826 PRINT_BACKGROUND_OP_TIME;
827 }
828 asimage2drawable (asv, bgPixmap.pixmap, back_im, gc, 0, 0, 0, 0, szHint.width, szHint.height, True);
829 destroy_asimage (&back_im);
830 } /* back_im != NULL */
831 else
832 success = False;
833 }
834 #else /* HAVE_AFTERIMAGE */
835 if (!whole_tint && (!no_tint || shade !=100))
836 {
837 XImage *image = XGetImage (dpy, bgPixmap.pixmap, 0, 0, szHint.width, szHint.height, AllPlanes, ZPixmap);
838 success = False;
839 if (image != NULL)
840 {
841 PRINT_BACKGROUND_OP_TIME;
842 if (gc == NULL)
843 gc = XCreateGC (dpy, vt, 0UL, &gcvalue);
844 if (ISSET_PIXCOLOR (Color_tint) || shade != 100)
845 ShadeXImage (this, image, shade, c.r, c.g, c.b);
846 XPutImage (dpy, bgPixmap.pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
847 XDestroyImage (image);
848 success = True;
849 }
850 }
851 #endif /* HAVE_AFTERIMAGE */
852 PRINT_BACKGROUND_OP_TIME;
853
854 if (gc != NULL)
855 XFreeGC (dpy, gc);
856
857 if (!success)
858 {
859 if (am_transparent && am_pixmap_trans)
860 {
861 pchanged = 1;
862 if (bgPixmap.pixmap != None)
863 {
864 XFreePixmap (dpy, bgPixmap.pixmap);
865 bgPixmap.pixmap = None;
866 }
867 }
868
869 am_pixmap_trans = 0;
870 }
871 else
872 {
873 XSetWindowBackgroundPixmap (dpy, parent[0], bgPixmap.pixmap);
874 XClearWindow (dpy, parent[0]);
875
876 if (!am_transparent || !am_pixmap_trans)
877 pchanged = 1;
878
879 am_transparent = am_pixmap_trans = 1;
880 }
881 } /* rootpixmap != None */
882
883 if (am_pixmap_trans)
884 XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
885 else
886 {
887 unsigned int n;
888 /*
889 * InheritPixmap transparency
890 */
891 for (i = 1; i < (int) (sizeof (parent) / sizeof (Window)); i++)
892 {
893 oldp = parent[i];
894 XQueryTree (dpy, parent[i - 1], &root, &parent[i], &list, &n);
895 XFree (list);
896
897 if (parent[i] == display->root)
898 {
899 if (oldp != None)
900 pchanged = 1;
901
902 break;
903 }
904
905 if (oldp != parent[i])
906 pchanged = 1;
907 }
908
909 n = 0;
910
911 if (pchanged)
912 for (; n < (unsigned int)i; n++)
913 {
914 XGetWindowAttributes (dpy, parent[n], &wattr);
915
916 if (wattr.depth != rootdepth || wattr.c_class == InputOnly)
917 {
918 n = (int) (sizeof (parent) / sizeof (Window)) + 1;
919 break;
920 }
921 }
922
923 if (n > (sizeof (parent) / sizeof (parent[0])))
924 {
925 XSetWindowBackground (dpy, parent[0], pix_colors_focused[Color_border]);
926 XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
927 am_transparent = 0;
928 /* XXX: also turn off Opt_transparent? */
929 }
930 else
931 {
932 for (n = 0; n < (unsigned int)i; n++)
933 {
934 XSetWindowBackgroundPixmap (dpy, parent[n], ParentRelative);
935 XClearWindow (dpy, parent[n]);
936 }
937
938 XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
939 am_transparent = 1;
940 }
941
942 for (; i < (int) (sizeof (parent) / sizeof (Window)); i++)
943 parent[i] = None;
944 }
945
946 if (scrollBar.win)
947 {
948 XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative);
949 scrollBar.setIdle ();
950 scrollbar_show (0);
951 }
952
953 if (am_transparent)
954 {
955 want_refresh = want_full_refresh = 1;
956 if (am_pixmap_trans)
957 flush ();
958 }
959
960 // return pchanged;
961 }
962 #endif