ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/background.C
(Generate patch)

Comparing rxvt-unicode/src/background.C (file contents):
Revision 1.144 by sf-exg, Fri Jan 28 00:20:47 2011 UTC vs.
Revision 1.196 by sf-exg, Tue Jan 10 18:50:14 2012 UTC

1/*----------------------------------------------------------------------* 1/*----------------------------------------------------------------------*
2 * File: background.C - former xpm.C 2 * File: background.C - former xpm.C
3 *----------------------------------------------------------------------* 3 *----------------------------------------------------------------------*
4 * 4 *
5 * All portions of code are copyright by their respective author/s. 5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 2005-2008 Marc Lehmann <pcg@goof.com> 6 * Copyright (c) 2005-2008 Marc Lehmann <schmorp@schmorp.de>
7 * Copyright (c) 2007 Sasha Vasko <sasha@aftercode.net> 7 * Copyright (c) 2007 Sasha Vasko <sasha@aftercode.net>
8 * Copyright (c) 2010 Emanuele Giaquinta <e.giaquinta@glauco.it> 8 * Copyright (c) 2010 Emanuele Giaquinta <e.giaquinta@glauco.it>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
32 32
33#ifndef FilterConvolution 33#ifndef FilterConvolution
34#define FilterConvolution "convolution" 34#define FilterConvolution "convolution"
35#endif 35#endif
36 36
37/* 37#ifndef RepeatPad
38 * Pixmap geometry string interpretation : 38#define RepeatPad True
39 * Each geometry string contains zero or one scale/position 39#endif
40 * adjustment and may optionally be followed by a colon and one or more
41 * colon-delimited pixmap operations.
42 * The following table shows the valid geometry strings and their
43 * effects on the background image :
44 *
45 * WxH+X+Y Set scaling to W% by H%, and position to X% by Y%.
46 * W and H are percentages of the terminal window size.
47 * X and Y are also percentages; e.g., +50+50 centers
48 * the image in the window.
49 *
50 * Pixmap Operations : (should be prepended by a colon)
51 * tile Tile image. Scaling/position modifiers above will affect
52 * the tile size and origin.
53 * propscale When scaling, scale proportionally. That is, maintain the
54 * proper aspect ratio for the image. Any portion of the
55 * background not covered by the image is filled with the
56 * current background color.
57 * hscale Scale horizontally, tile vertically ?
58 * vscale Tile horizontally, scale vertically ?
59 * scale Scale both up and down
60 * auto Same as 100x100+50+50
61 */
62 40
63#ifdef HAVE_BG_PIXMAP 41#ifdef HAVE_BG_PIXMAP
42# if XRENDER
43static Picture
44create_xrender_mask (Display *dpy, Drawable drawable, Bool argb, Bool component_alpha)
45{
46 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8);
47
48 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8);
49 XRenderPictureAttributes pa;
50 pa.repeat = True;
51 pa.component_alpha = component_alpha;
52 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat | CPComponentAlpha, &pa);
53
54 XFreePixmap (dpy, pixmap);
55
56 return mask;
57}
58# endif
59
64void 60void
65rxvt_term::bg_destroy () 61rxvt_term::bg_destroy ()
66{ 62{
67#ifdef HAVE_AFTERIMAGE 63#ifdef HAVE_AFTERIMAGE
68 if (original_asim) 64 if (original_asim)
69 safe_asimage_destroy (original_asim); 65 safe_asimage_destroy (original_asim);
66 if (asv)
67 destroy_asvisual (asv, 0);
68 if (asimman)
69 destroy_image_manager (asimman, 0);
70#endif 70#endif
71 71
72#ifdef HAVE_PIXBUF 72#ifdef HAVE_PIXBUF
73 if (pixbuf) 73 if (pixbuf)
74 g_object_unref (pixbuf); 74 g_object_unref (pixbuf);
172 int smaller = min (image_size, window_size); 172 int smaller = min (image_size, window_size);
173 173
174 if (align >= 0 && align <= 100) 174 if (align >= 0 && align <= 100)
175 return diff * align / 100; 175 return diff * align / 100;
176 else if (align > 100 && align <= 200) 176 else if (align > 100 && align <= 200)
177 return ((align - 100) * smaller / 100) + window_size - smaller; 177 return (align - 100) * smaller / 100 + window_size - smaller;
178 else if (align >= -100 && align < 0) 178 else if (align >= -100 && align < 0)
179 return ((align + 100) * smaller / 100) - image_size; 179 return (align + 100) * smaller / 100 - image_size;
180 return 0; 180 return 0;
181} 181}
182 182
183static inline int 183static inline int
184make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_size) 184make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_size)
203{ 203{
204 bool changed = false; 204 bool changed = false;
205 int geom_flags = 0; 205 int geom_flags = 0;
206 int x = 0, y = 0; 206 int x = 0, y = 0;
207 unsigned int w = 0, h = 0; 207 unsigned int w = 0, h = 0;
208 unsigned int n; 208 unsigned long new_flags = 0;
209 unsigned long new_flags = (bg_flags & (~BG_GEOMETRY_FLAGS));
210 const char *ops;
211 209
212 if (geom == NULL) 210 if (geom == NULL)
213 return false; 211 return false;
214 212
215 char str[256]; 213 if (geom[0])
216
217 ops = strchr (geom, ':');
218 if (ops == NULL)
219 n = strlen (geom);
220 else
221 n = ops - geom;
222
223 if (n >= sizeof (str))
224 return false;
225
226 memcpy (str, geom, n);
227 str[n] = '\0';
228 rxvt_strtrim (str);
229
230 if (str[0])
231 { 214 {
232 /* we have geometry string - let's handle it prior to applying ops */ 215 char **arr = rxvt_strsplit (':', geom);
216
217 for (int i = 0; arr[i]; i++)
218 {
219 if (!strcasecmp (arr[i], "style=tiled"))
220 {
221 new_flags = BG_TILE;
222 w = h = noScale;
223 x = y = 0;
224 geom_flags = WidthValue|HeightValue|XValue|YValue;
225 }
226 else if (!strcasecmp (arr[i], "style=aspect-stretched"))
227 {
228 new_flags = BG_KEEP_ASPECT;
229 w = h = windowScale;
230 x = y = centerAlign;
231 geom_flags = WidthValue|HeightValue|XValue|YValue;
232 }
233 else if (!strcasecmp (arr[i], "style=stretched"))
234 {
235 new_flags = 0;
236 w = h = windowScale;
237 geom_flags = WidthValue|HeightValue;
238 }
239 else if (!strcasecmp (arr[i], "style=centered"))
240 {
241 new_flags = 0;
242 w = h = noScale;
243 x = y = centerAlign;
244 geom_flags = WidthValue|HeightValue|XValue|YValue;
245 }
246 else if (!strcasecmp (arr[i], "style=root-tiled"))
247 {
248 new_flags = BG_TILE|BG_ROOT_ALIGN;
249 w = h = noScale;
250 geom_flags = WidthValue|HeightValue;
251 }
252 else if (!strcasecmp (arr[i], "op=tile"))
253 new_flags |= BG_TILE;
254 else if (!strcasecmp (arr[i], "op=keep-aspect"))
255 new_flags |= BG_KEEP_ASPECT;
256 else if (!strcasecmp (arr[i], "op=root-align"))
257 new_flags |= BG_ROOT_ALIGN;
258
259 // deprecated
260 else if (!strcasecmp (arr[i], "tile"))
261 {
262 new_flags |= BG_TILE;
263 w = h = noScale;
264 geom_flags |= WidthValue|HeightValue;
265 }
266 else if (!strcasecmp (arr[i], "propscale"))
267 {
268 new_flags |= BG_KEEP_ASPECT;
269 w = h = windowScale;
270 geom_flags |= WidthValue|HeightValue;
271 }
272 else if (!strcasecmp (arr[i], "hscale"))
273 {
274 new_flags |= BG_TILE;
275 w = windowScale;
276 h = noScale;
277 geom_flags |= WidthValue|HeightValue;
278 }
279 else if (!strcasecmp (arr[i], "vscale"))
280 {
281 new_flags |= BG_TILE;
282 h = windowScale;
283 w = noScale;
284 geom_flags |= WidthValue|HeightValue;
285 }
286 else if (!strcasecmp (arr[i], "scale"))
287 {
288 w = h = windowScale;
289 geom_flags |= WidthValue|HeightValue;
290 }
291 else if (!strcasecmp (arr[i], "auto"))
292 {
293 w = h = windowScale;
294 x = y = centerAlign;
295 geom_flags |= WidthValue|HeightValue|XValue|YValue;
296 }
297 else if (!strcasecmp (arr[i], "root"))
298 {
299 new_flags |= BG_TILE|BG_ROOT_ALIGN;
300 w = h = noScale;
301 geom_flags |= WidthValue|HeightValue;
302 }
303
304 else
233 geom_flags = XParseGeometry (str, &x, &y, &w, &h); 305 geom_flags |= XParseGeometry (arr[i], &x, &y, &w, &h);
234 } /* done parsing geometry string */ 306 } /* done parsing ops */
307
308 rxvt_free_strsplit (arr);
309 }
310
311 new_flags |= bg_flags & ~BG_GEOMETRY_FLAGS;
235 312
236 if (!update) 313 if (!update)
237 { 314 {
238 if (!(geom_flags & XValue)) 315 if (!(geom_flags & XValue))
239 x = y = defaultAlign; 316 x = y = defaultAlign;
248 w = h; 325 w = h;
249 326
250 geom_flags |= WidthValue|HeightValue|XValue|YValue; 327 geom_flags |= WidthValue|HeightValue|XValue|YValue;
251 } 328 }
252 329
253 if (ops)
254 {
255 char **arr = rxvt_strsplit (':', ops + 1);
256
257 for (int i = 0; arr[i]; i++)
258 {
259 if (!strcasecmp (arr[i], "tile"))
260 {
261 w = h = noScale;
262 geom_flags |= WidthValue|HeightValue;
263 }
264 else if (!strcasecmp (arr[i], "propscale"))
265 {
266 new_flags |= BG_PROP_SCALE;
267 }
268 else if (!strcasecmp (arr[i], "hscale"))
269 {
270 if (w == 0) w = windowScale;
271
272 h = noScale;
273 geom_flags |= WidthValue|HeightValue;
274 }
275 else if (!strcasecmp (arr[i], "vscale"))
276 {
277 if (h == 0) h = windowScale;
278
279 w = noScale;
280 geom_flags |= WidthValue|HeightValue;
281 }
282 else if (!strcasecmp (arr[i], "scale"))
283 {
284 if (h == 0) h = windowScale;
285 if (w == 0) w = windowScale;
286
287 geom_flags |= WidthValue|HeightValue;
288 }
289 else if (!strcasecmp (arr[i], "auto"))
290 {
291 w = h = windowScale;
292 x = y = centerAlign;
293 geom_flags |= WidthValue|HeightValue|XValue|YValue;
294 }
295 else if (!strcasecmp (arr[i], "root"))
296 {
297 new_flags |= BG_ROOT_ALIGN;
298 w = h = noScale;
299 geom_flags |= WidthValue|HeightValue;
300 }
301 } /* done parsing ops */
302
303 rxvt_free_strsplit (arr);
304 }
305
306 if (check_set_scale_value (geom_flags, WidthValue, h_scale, w)) changed = true; 330 if (check_set_scale_value (geom_flags, WidthValue, h_scale, w)) changed = true;
307 if (check_set_scale_value (geom_flags, HeightValue, v_scale, h)) changed = true; 331 if (check_set_scale_value (geom_flags, HeightValue, v_scale, h)) changed = true;
308 if (check_set_align_value (geom_flags, XValue, h_align, x)) changed = true; 332 if (check_set_align_value (geom_flags, XValue, h_align, x)) changed = true;
309 if (check_set_align_value (geom_flags, YValue, v_align, y)) changed = true; 333 if (check_set_align_value (geom_flags, YValue, v_align, y)) changed = true;
310 334
321rxvt_term::get_image_geometry (int image_width, int image_height, int &w, int &h, int &x, int &y) 345rxvt_term::get_image_geometry (int image_width, int image_height, int &w, int &h, int &x, int &y)
322{ 346{
323 int target_width = szHint.width; 347 int target_width = szHint.width;
324 int target_height = szHint.height; 348 int target_height = szHint.height;
325 349
350 w = h_scale * target_width / 100;
351 h = v_scale * target_height / 100;
352
326 if (bg_flags & BG_PROP_SCALE) 353 if (bg_flags & BG_KEEP_ASPECT)
327 { 354 {
328 float scale = (float)target_width / image_width; 355 float scale = (float)w / image_width;
329 min_it (scale, (float)target_height / image_height); 356 min_it (scale, (float)h / image_height);
330 w = image_width * scale + 0.5; 357 w = image_width * scale + 0.5;
331 h = image_height * scale + 0.5; 358 h = image_height * scale + 0.5;
332 } 359 }
333 else
334 {
335 w = h_scale * target_width / 100;
336 h = v_scale * target_height / 100;
337 }
338 360
339 if (!w) w = image_width; 361 if (!w) w = image_width;
340 if (!h) h = image_height; 362 if (!h) h = image_height;
341 363
342 if (bg_flags & BG_ROOT_ALIGN) 364 if (bg_flags & BG_ROOT_ALIGN)
349 x = make_align_position (h_align, target_width, w); 371 x = make_align_position (h_align, target_width, w);
350 y = make_align_position (v_align, target_height, h); 372 y = make_align_position (v_align, target_height, h);
351 } 373 }
352 374
353 bg_flags &= ~BG_IS_SIZE_SENSITIVE; 375 bg_flags &= ~BG_IS_SIZE_SENSITIVE;
354 if ((bg_flags & BG_PROP_SCALE) || h_scale || v_scale 376 if (!(bg_flags & BG_TILE)
377 || h_scale || v_scale
355 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align)) 378 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align))
356 || w > target_width || h > target_height) 379 || w > target_width || h > target_height)
357 bg_flags |= BG_IS_SIZE_SENSITIVE; 380 bg_flags |= BG_IS_SIZE_SENSITIVE;
358} 381}
359 382
386 } 409 }
387 410
388 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL) 411 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL)
389 { 412 {
390 ASImage *tmp = blur_asimage_gauss (asv, background, h_blurRadius, v_blurRadius, 0xFFFFFFFF, 413 ASImage *tmp = blur_asimage_gauss (asv, background, h_blurRadius, v_blurRadius, 0xFFFFFFFF,
391 (original_asim == NULL || tint == TINT_LEAVE_SAME) ? ASA_XImage : ASA_ASImage, 414 ASA_XImage,
392 100, ASIMAGE_QUALITY_DEFAULT); 415 100, ASIMAGE_QUALITY_DEFAULT);
393 if (tmp) 416 if (tmp)
394 { 417 {
395 destroy_asimage (&background); 418 destroy_asimage (&background);
396 background = tmp; 419 background = tmp;
415 438
416 if (!original_asim 439 if (!original_asim
417 || (!(bg_flags & BG_ROOT_ALIGN) 440 || (!(bg_flags & BG_ROOT_ALIGN)
418 && (x >= target_width 441 && (x >= target_width
419 || y >= target_height 442 || y >= target_height
420 || (x + w <= 0) 443 || x + w <= 0
421 || (y + h <= 0)))) 444 || y + h <= 0)))
422 { 445 {
423 if (background) 446 if (background)
424 { 447 {
425 new_pmap_width = background->width; 448 new_pmap_width = background->width;
426 new_pmap_height = background->height; 449 new_pmap_height = background->height;
440 } 463 }
441 else 464 else
442 { 465 {
443 result = original_asim; 466 result = original_asim;
444 467
445 if ((w != original_asim->width) 468 if (w != original_asim->width
446 || (h != original_asim->height)) 469 || h != original_asim->height)
447 { 470 {
448 result = scale_asimage (asv, original_asim, 471 result = scale_asimage (asv, original_asim,
449 w, h, 472 w, h,
450 background ? ASA_ASImage : ASA_XImage, 473 ASA_XImage,
451 100, ASIMAGE_QUALITY_DEFAULT); 474 100, ASIMAGE_QUALITY_DEFAULT);
452 } 475 }
453 476
454 if (background == NULL) 477 if (background == NULL)
455 { 478 {
456 if (h_scale == 0 || v_scale == 0) 479 if (bg_flags & BG_TILE)
457 { 480 {
458 /* if tiling - pixmap has to be sized exactly as the image, 481 /* if tiling - pixmap has to be sized exactly as the image,
459 but there is no need to make it bigger than the window! */ 482 but there is no need to make it bigger than the window! */
460 new_pmap_width = min (result->width, target_width); 483 new_pmap_width = min (result->width, target_width);
461 new_pmap_height = min (result->height, target_height); 484 new_pmap_height = min (result->height, target_height);
486 layers[0].clip_width = target_width; 509 layers[0].clip_width = target_width;
487 layers[0].clip_height = target_height; 510 layers[0].clip_height = target_height;
488 layers[0].tint = background_tint; 511 layers[0].tint = background_tint;
489 layers[1].im = result; 512 layers[1].im = result;
490 513
491 if (h_scale == 0 || v_scale == 0) 514 if (bg_flags & BG_TILE)
492 { 515 {
493 /* tile horizontally */ 516 /* tile horizontally */
494 while (x > 0) x -= (int)result->width; 517 while (x > 0) x -= (int)result->width;
495 layers[1].dst_x = x; 518 layers[1].dst_x = x;
496 layers[1].clip_width = result->width+target_width; 519 layers[1].clip_width = result->width+target_width;
500 /* clip horizontally */ 523 /* clip horizontally */
501 layers[1].dst_x = x; 524 layers[1].dst_x = x;
502 layers[1].clip_width = result->width; 525 layers[1].clip_width = result->width;
503 } 526 }
504 527
505 if (h_scale == 0 || v_scale == 0) 528 if (bg_flags & BG_TILE)
506 { 529 {
507 while (y > 0) y -= (int)result->height; 530 while (y > 0) y -= (int)result->height;
508 layers[1].dst_y = y; 531 layers[1].dst_y = y;
509 layers[1].clip_height = result->height + target_height; 532 layers[1].clip_height = result->height + target_height;
510 } 533 }
560 583
561 int src_x = 0, src_y = 0, dst_x = 0, dst_y = 0; 584 int src_x = 0, src_y = 0, dst_x = 0, dst_y = 0;
562 int dst_width = result->width, dst_height = result->height; 585 int dst_width = result->width, dst_height = result->height;
563 if (background == NULL) 586 if (background == NULL)
564 { 587 {
565 if (!(h_scale == 0 || v_scale == 0)) 588 if (!(bg_flags & BG_TILE))
566 { 589 {
567 src_x = make_clip_rectangle (x, result->width , new_pmap_width , dst_x, dst_width ); 590 src_x = make_clip_rectangle (x, result->width , new_pmap_width , dst_x, dst_width );
568 src_y = make_clip_rectangle (y, result->height, new_pmap_height, dst_y, dst_height); 591 src_y = make_clip_rectangle (y, result->height, new_pmap_height, dst_y, dst_height);
569 } 592 }
570 593
616 else if (depth == 15 || depth == 16) 639 else if (depth == 15 || depth == 16)
617 bytes_per_pixel = 2; 640 bytes_per_pixel = 2;
618 else 641 else
619 return false; 642 return false;
620 643
621 width_r = rxvt_popcount (visual->red_mask); 644 width_r = ecb_popcount32 (visual->red_mask);
622 width_g = rxvt_popcount (visual->green_mask); 645 width_g = ecb_popcount32 (visual->green_mask);
623 width_b = rxvt_popcount (visual->blue_mask); 646 width_b = ecb_popcount32 (visual->blue_mask);
624 647
625 if (width_r > 8 || width_g > 8 || width_b > 8) 648 if (width_r > 8 || width_g > 8 || width_b > 8)
626 return false; 649 return false;
627 650
628 sh_r = rxvt_ctz (visual->red_mask); 651 sh_r = ecb_ctz32 (visual->red_mask);
629 sh_g = rxvt_ctz (visual->green_mask); 652 sh_g = ecb_ctz32 (visual->green_mask);
630 sh_b = rxvt_ctz (visual->blue_mask); 653 sh_b = ecb_ctz32 (visual->blue_mask);
631 654
632 if (width > INT_MAX / height / bytes_per_pixel) 655 if (width > INT_MAX / height / bytes_per_pixel)
633 return false; 656 return false;
634 657
635 data = (char *)malloc (width * height * bytes_per_pixel); 658 data = (char *)malloc (width * height * bytes_per_pixel);
642 { 665 {
643 free (data); 666 free (data);
644 return false; 667 return false;
645 } 668 }
646 669
647 ximage->byte_order = byteorder::big_endian () ? MSBFirst : LSBFirst; 670 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
648 671
649 rowstride = gdk_pixbuf_get_rowstride (pixbuf); 672 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
650 channels = gdk_pixbuf_get_n_channels (pixbuf); 673 channels = gdk_pixbuf_get_n_channels (pixbuf);
651 row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels; 674 row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels;
652 line = data; 675 line = data;
705 get_image_geometry (image_width, image_height, w, h, x, y); 728 get_image_geometry (image_width, image_height, w, h, x, y);
706 729
707 if (!(bg_flags & BG_ROOT_ALIGN) 730 if (!(bg_flags & BG_ROOT_ALIGN)
708 && (x >= target_width 731 && (x >= target_width
709 || y >= target_height 732 || y >= target_height
710 || (x + w <= 0) 733 || x + w <= 0
711 || (y + h <= 0))) 734 || y + h <= 0))
712 return false; 735 return false;
713 736
714 result = pixbuf; 737 result = pixbuf;
715 738
716 if ((w != image_width) 739 if (w != image_width
717 || (h != image_height)) 740 || h != image_height)
718 { 741 {
719 result = gdk_pixbuf_scale_simple (pixbuf, 742 result = gdk_pixbuf_scale_simple (pixbuf,
720 w, h, 743 w, h,
721 GDK_INTERP_BILINEAR); 744 GDK_INTERP_BILINEAR);
722 } 745 }
723 746
747 if (!result)
748 return false;
749
724 bool ret = false; 750 bool ret = false;
725 751
726 if (result)
727 {
728 XGCValues gcv; 752 XGCValues gcv;
729 GC gc; 753 GC gc;
730 Pixmap root_pmap; 754 Pixmap root_pmap;
731 755
732 image_width = gdk_pixbuf_get_width (result); 756 image_width = gdk_pixbuf_get_width (result);
733 image_height = gdk_pixbuf_get_height (result); 757 image_height = gdk_pixbuf_get_height (result);
734 758
735 if (tr_flags) 759 if (tr_flags)
736 { 760 {
737 root_pmap = bg_pixmap; 761 root_pmap = bg_pixmap;
738 bg_pixmap = None; 762 bg_pixmap = None;
763 }
764 else
765 {
766 if (bg_flags & BG_TILE)
739 } 767 {
740 else
741 {
742 if (h_scale == 0 || v_scale == 0)
743 {
744 new_pmap_width = min (image_width, target_width); 768 new_pmap_width = min (image_width, target_width);
745 new_pmap_height = min (image_height, target_height); 769 new_pmap_height = min (image_height, target_height);
746 } 770 }
747 } 771 }
748 772
749 if (bg_pixmap == None 773 if (bg_pixmap == None
750 || bg_pmap_width != new_pmap_width 774 || bg_pmap_width != new_pmap_width
751 || bg_pmap_height != new_pmap_height) 775 || bg_pmap_height != new_pmap_height)
752 { 776 {
753 if (bg_pixmap) 777 if (bg_pixmap)
754 XFreePixmap (dpy, bg_pixmap); 778 XFreePixmap (dpy, bg_pixmap);
755 bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth); 779 bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth);
756 bg_pmap_width = new_pmap_width; 780 bg_pmap_width = new_pmap_width;
757 bg_pmap_height = new_pmap_height; 781 bg_pmap_height = new_pmap_height;
758 } 782 }
759 783
760 gcv.foreground = pix_colors[Color_bg]; 784 gcv.foreground = pix_colors[Color_bg];
761 gc = XCreateGC (dpy, vt, GCForeground, &gcv); 785 gc = XCreateGC (dpy, vt, GCForeground, &gcv);
762 786
763 if (h_scale == 0 || v_scale == 0) 787 if (gc)
788 {
789 if (bg_flags & BG_TILE)
764 { 790 {
765 Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, depth); 791 Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, depth);
766 pixbuf_to_pixmap (result, tile, gc, 792 pixbuf_to_pixmap (result, tile, gc,
767 0, 0, 793 0, 0,
768 0, 0, 794 0, 0,
798 } 824 }
799 825
800#if XRENDER 826#if XRENDER
801 if (tr_flags) 827 if (tr_flags)
802 { 828 {
803 XRenderPictureAttributes pa;
804
805 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, visual); 829 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
830
806 Picture src = XRenderCreatePicture (dpy, root_pmap, src_format, 0, &pa); 831 Picture src = XRenderCreatePicture (dpy, root_pmap, format, 0, 0);
807 832
808 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
809 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, dst_format, 0, &pa); 833 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, format, 0, 0);
810 834
811 pa.repeat = True; 835 Picture mask = create_xrender_mask (dpy, vt, False, False);
812 Pixmap mask_pmap = XCreatePixmap (dpy, vt, 1, 1, 8);
813 XRenderPictFormat *mask_format = XRenderFindStandardFormat (dpy, PictStandardA8);
814 Picture mask = XRenderCreatePicture (dpy, mask_pmap, mask_format, CPRepeat, &pa);
815 XFreePixmap (dpy, mask_pmap);
816 836
817 if (src && dst && mask)
818 {
819 XRenderColor mask_c; 837 XRenderColor mask_c;
820 838
821 mask_c.alpha = 0x8000; 839 mask_c.alpha = 0x8000;
822 mask_c.red = 0; 840 mask_c.red =
823 mask_c.green = 0; 841 mask_c.green =
824 mask_c.blue = 0; 842 mask_c.blue = 0;
825 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); 843 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
844
826 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, target_width, target_height); 845 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, target_width, target_height);
827 }
828 846
829 XRenderFreePicture (dpy, src); 847 XRenderFreePicture (dpy, src);
830 XRenderFreePicture (dpy, dst); 848 XRenderFreePicture (dpy, dst);
831 XRenderFreePicture (dpy, mask); 849 XRenderFreePicture (dpy, mask);
832
833 XFreePixmap (dpy, root_pmap);
834 } 850 }
835#endif 851#endif
836 852
837 if (result != pixbuf)
838 g_object_unref (result);
839
840 XFreeGC (dpy, gc); 853 XFreeGC (dpy, gc);
841 854
842 ret = true; 855 ret = true;
843 } 856 }
857
858 if (result != pixbuf)
859 g_object_unref (result);
860
861 if (tr_flags)
862 XFreePixmap (dpy, root_pmap);
844 863
845 return ret; 864 return ret;
846} 865}
847# endif /* HAVE_PIXBUF */ 866# endif /* HAVE_PIXBUF */
848 867
850rxvt_term::bg_set_file (const char *file) 869rxvt_term::bg_set_file (const char *file)
851{ 870{
852 if (!file || !*file) 871 if (!file || !*file)
853 return false; 872 return false;
854 873
874 bool ret = false;
855 if (const char *p = strchr (file, ';')) 875 const char *p = strchr (file, ';');
876
877 if (p)
856 { 878 {
857 size_t len = p - file; 879 size_t len = p - file;
858 char *f = rxvt_temp_buf<char> (len + 1); 880 char *f = rxvt_temp_buf<char> (len + 1);
859 memcpy (f, file, len); 881 memcpy (f, file, len);
860 f[len] = '\0'; 882 f[len] = '\0';
869 { 891 {
870 if (original_asim) 892 if (original_asim)
871 safe_asimage_destroy (original_asim); 893 safe_asimage_destroy (original_asim);
872 original_asim = image; 894 original_asim = image;
873 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER; 895 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER;
874 return true; 896 ret = true;
875 } 897 }
876# endif 898# endif
877 899
878# ifdef HAVE_PIXBUF 900# ifdef HAVE_PIXBUF
879 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL); 901 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL);
881 { 903 {
882 if (pixbuf) 904 if (pixbuf)
883 g_object_unref (pixbuf); 905 g_object_unref (pixbuf);
884 pixbuf = image; 906 pixbuf = image;
885 bg_flags |= BG_IS_FROM_FILE; 907 bg_flags |= BG_IS_FROM_FILE;
886 return true; 908 ret = true;
887 } 909 }
888# endif 910# endif
889 911
912 if (ret)
913 {
914 if (p)
915 bg_set_geometry (p + 1);
916 else
917 bg_set_default_geometry ();
918 }
919
890 return false; 920 return ret;
891} 921}
892 922
893# endif /* BG_IMAGE_FROM_FILE */ 923# endif /* BG_IMAGE_FROM_FILE */
894 924
895# ifdef ENABLE_TRANSPARENCY 925# ifdef ENABLE_TRANSPARENCY
931 { 961 {
932 changed = true; 962 changed = true;
933 v_blurRadius = vr; 963 v_blurRadius = vr;
934 } 964 }
935 965
936 if (v_blurRadius == 0 && h_blurRadius == 0) 966 if (h_blurRadius == 0 || v_blurRadius == 0)
937 bg_flags &= ~BG_NEEDS_BLUR; 967 bg_flags &= ~BG_NEEDS_BLUR;
938 else 968 else
939 bg_flags |= BG_NEEDS_BLUR; 969 bg_flags |= BG_NEEDS_BLUR;
940 970
941 return changed; 971 return changed;
942} 972}
943 973
944static inline unsigned long 974void
945compute_tint_shade_flags (rxvt_color *tint, int shade) 975rxvt_term::set_tint_shade_flags ()
946{ 976{
947 unsigned long flags = 0; 977 rgba c;
948 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
949 bool has_shade = shade != 100; 978 bool has_shade = shade != 100;
950 979
951 if (tint) 980 bg_flags &= ~BG_TINT_FLAGS;
981
982 if (bg_flags & BG_TINT_SET)
952 { 983 {
953 tint->get (c); 984 tint.get (c);
954 if (!has_shade 985 if (!has_shade
955 && (c.r <= 0x00ff || c.r >= 0xff00) 986 && (c.r <= 0x00ff || c.r >= 0xff00)
956 && (c.g <= 0x00ff || c.g >= 0xff00) 987 && (c.g <= 0x00ff || c.g >= 0xff00)
957 && (c.b <= 0x00ff || c.b >= 0xff00)) 988 && (c.b <= 0x00ff || c.b >= 0xff00))
958 flags |= rxvt_term::BG_TINT_BITAND; 989 bg_flags |= BG_TINT_BITAND;
959 } 990 }
960 991
961 if (has_shade || tint) 992 if (has_shade || (bg_flags & BG_TINT_SET))
962 flags |= rxvt_term::BG_NEEDS_TINT; 993 bg_flags |= BG_NEEDS_TINT;
963
964 return flags;
965} 994}
966 995
967bool 996bool
968rxvt_term::bg_set_tint (rxvt_color &new_tint) 997rxvt_term::bg_set_tint (rxvt_color &new_tint)
969{ 998{
970 if (!(bg_flags & BG_TINT_SET) || tint != new_tint) 999 if (!(bg_flags & BG_TINT_SET) || tint != new_tint)
971 { 1000 {
972 unsigned long new_flags = compute_tint_shade_flags (&new_tint, shade);
973 tint = new_tint; 1001 tint = new_tint;
974 bg_flags = (bg_flags & ~BG_TINT_FLAGS) | new_flags | BG_TINT_SET; 1002 bg_flags |= BG_TINT_SET;
1003 set_tint_shade_flags ();
975 return true; 1004 return true;
976 } 1005 }
977 1006
978 return false; 1007 return false;
979} 1008}
980 1009
981bool 1010bool
982rxvt_term::bg_set_shade (const char *shade_str) 1011rxvt_term::bg_set_shade (const char *shade_str)
983{ 1012{
984 int new_shade = (shade_str) ? atoi (shade_str) : 100; 1013 int new_shade = atoi (shade_str);
985 1014
986 clamp_it (new_shade, -100, 200); 1015 clamp_it (new_shade, -100, 200);
987 if (new_shade < 0) 1016 if (new_shade < 0)
988 new_shade = 200 - (100 + new_shade); 1017 new_shade = 200 - (100 + new_shade);
989 1018
990 if (new_shade != shade) 1019 if (new_shade != shade)
991 { 1020 {
992 unsigned long new_flags = compute_tint_shade_flags ((bg_flags & BG_TINT_SET) ? &tint : NULL, new_shade);
993 shade = new_shade; 1021 shade = new_shade;
994 bg_flags = (bg_flags & ~BG_TINT_FLAGS) | new_flags; 1022 set_tint_shade_flags ();
995 return true; 1023 return true;
996 } 1024 }
997 1025
998 return false; 1026 return false;
999} 1027}
1020 params[i+2] = XDoubleToFixed (kernel[i] / sum); 1048 params[i+2] = XDoubleToFixed (kernel[i] / sum);
1021} 1049}
1022#endif 1050#endif
1023 1051
1024bool 1052bool
1025rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height) 1053rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height, int depth)
1026{ 1054{
1027 bool ret = false; 1055 bool ret = false;
1028#if XRENDER 1056#if XRENDER
1057 if (!(bg_flags & BG_HAS_RENDER_CONV))
1058 return false;
1059
1029 int size = max (h_blurRadius, v_blurRadius) * 2 + 1; 1060 int size = max (h_blurRadius, v_blurRadius) * 2 + 1;
1030 double *kernel = (double *)malloc (size * sizeof (double)); 1061 double *kernel = (double *)malloc (size * sizeof (double));
1031 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 1062 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
1032 1063
1033 XRenderPictureAttributes pa; 1064 XRenderPictureAttributes pa;
1034 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1065 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1035 1066
1067 pa.repeat = RepeatPad;
1036 Picture src = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1068 Picture src = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa);
1069 Pixmap tmp = XCreatePixmap (dpy, pixmap, width, height, depth);
1037 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1070 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa);
1071 XFreePixmap (dpy, tmp);
1038 1072
1039 if (kernel && params && src && dst) 1073 if (kernel && params)
1040 { 1074 {
1041 if (h_blurRadius)
1042 {
1043 size = h_blurRadius * 2 + 1; 1075 size = h_blurRadius * 2 + 1;
1044 get_gaussian_kernel (h_blurRadius, size, kernel, params); 1076 get_gaussian_kernel (h_blurRadius, size, kernel, params);
1045 1077
1046 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1078 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1047 XRenderComposite (dpy, 1079 XRenderComposite (dpy,
1048 PictOpSrc, 1080 PictOpSrc,
1049 src, 1081 src,
1050 None, 1082 None,
1051 dst, 1083 dst,
1052 0, 0, 1084 0, 0,
1053 0, 0, 1085 0, 0,
1054 0, 0, 1086 0, 0,
1055 width, height); 1087 width, height);
1056 }
1057 1088
1058 if (v_blurRadius) 1089 ::swap (src, dst);
1059 { 1090
1060 size = v_blurRadius * 2 + 1; 1091 size = v_blurRadius * 2 + 1;
1061 get_gaussian_kernel (v_blurRadius, size, kernel, params); 1092 get_gaussian_kernel (v_blurRadius, size, kernel, params);
1062 ::swap (params[0], params[1]); 1093 ::swap (params[0], params[1]);
1063 1094
1064 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1095 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1065 XRenderComposite (dpy, 1096 XRenderComposite (dpy,
1066 PictOpSrc, 1097 PictOpSrc,
1067 src, 1098 src,
1068 None, 1099 None,
1069 dst, 1100 dst,
1070 0, 0, 1101 0, 0,
1071 0, 0, 1102 0, 0,
1072 0, 0, 1103 0, 0,
1073 width, height); 1104 width, height);
1074 }
1075 1105
1076 ret = true; 1106 ret = true;
1077 } 1107 }
1078 1108
1079 free (kernel); 1109 free (kernel);
1106 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height); 1136 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height);
1107 ret = true; 1137 ret = true;
1108 XFreeGC (dpy, gc); 1138 XFreeGC (dpy, gc);
1109 } 1139 }
1110 } 1140 }
1111 else
1112 {
1113# if XRENDER 1141# if XRENDER
1142 else if (bg_flags & BG_HAS_RENDER)
1143 {
1114 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); 1144 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1115 1145
1116 if (bg_flags & BG_TINT_SET) 1146 if (bg_flags & BG_TINT_SET)
1117 tint.get (c); 1147 tint.get (c);
1118 1148
1119 if (shade <= 100) 1149 if (shade <= 100)
1120 { 1150 {
1121 c.r = (c.r * shade) / 100; 1151 c.r = c.r * shade / 100;
1122 c.g = (c.g * shade) / 100; 1152 c.g = c.g * shade / 100;
1123 c.b = (c.b * shade) / 100; 1153 c.b = c.b * shade / 100;
1124 } 1154 }
1125 else 1155 else
1126 { 1156 {
1127 c.r = (c.r * (200 - shade)) / 100; 1157 c.r = c.r * (200 - shade) / 100;
1128 c.g = (c.g * (200 - shade)) / 100; 1158 c.g = c.g * (200 - shade) / 100;
1129 c.b = (c.b * (200 - shade)) / 100; 1159 c.b = c.b * (200 - shade) / 100;
1130 } 1160 }
1131 1161
1132 XRenderPictFormat *solid_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
1133 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1162 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1134 XRenderPictureAttributes pa;
1135 1163
1136 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1164 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1137 1165
1138 pa.repeat = True; 1166 Picture overlay_pic = create_xrender_mask (dpy, pixmap, True, False);
1139 1167
1140 Pixmap overlay_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32); 1168 Picture mask_pic = create_xrender_mask (dpy, pixmap, True, True);
1141 Picture overlay_pic = XRenderCreatePicture (dpy, overlay_pmap, solid_format, CPRepeat, &pa);
1142 XFreePixmap (dpy, overlay_pmap);
1143 1169
1144 pa.component_alpha = True;
1145 Pixmap mask_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32);
1146 Picture mask_pic = XRenderCreatePicture (dpy, mask_pmap, solid_format, CPRepeat|CPComponentAlpha, &pa);
1147 XFreePixmap (dpy, mask_pmap);
1148
1149 if (mask_pic && overlay_pic && back_pic)
1150 {
1151 XRenderColor mask_c; 1170 XRenderColor mask_c;
1152 1171
1153 mask_c.red = mask_c.green = mask_c.blue = 0;
1154 mask_c.alpha = 0xffff; 1172 mask_c.alpha = 0xffff;
1173 mask_c.red =
1174 mask_c.green =
1175 mask_c.blue = 0;
1176 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1177
1178 mask_c.alpha = 0;
1179 mask_c.red = 0xffff - c.r;
1180 mask_c.green = 0xffff - c.g;
1181 mask_c.blue = 0xffff - c.b;
1182 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
1183
1184 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1185
1186 if (shade > 100)
1187 {
1188 mask_c.alpha = 0;
1189 mask_c.red =
1190 mask_c.green =
1191 mask_c.blue = 0xffff * (shade - 100) / 100;
1155 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); 1192 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1156 1193
1157 mask_c.alpha = 0;
1158 mask_c.red = 0xffff - c.r;
1159 mask_c.green = 0xffff - c.g;
1160 mask_c.blue = 0xffff - c.b;
1161 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
1162 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1163
1164 if (shade > 100)
1165 {
1166 mask_c.red = mask_c.green = mask_c.blue = 0xffff * (shade - 100) / 100;
1167 mask_c.alpha = 0;
1168 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1169
1170 XRenderComposite (dpy, PictOpOver, overlay_pic, None, back_pic, 0, 0, 0, 0, 0, 0, width, height); 1194 XRenderComposite (dpy, PictOpOver, overlay_pic, None, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1171 } 1195 }
1172 1196
1173 ret = true; 1197 ret = true;
1174 }
1175 1198
1176 XRenderFreePicture (dpy, mask_pic); 1199 XRenderFreePicture (dpy, mask_pic);
1177 XRenderFreePicture (dpy, overlay_pic); 1200 XRenderFreePicture (dpy, overlay_pic);
1178 XRenderFreePicture (dpy, back_pic); 1201 XRenderFreePicture (dpy, back_pic);
1202 }
1179# endif 1203# endif
1180 }
1181 1204
1182 return ret; 1205 return ret;
1183} 1206}
1184 1207
1185/* make_transparency_pixmap() 1208/*
1186 * Builds a pixmap of the same size as the terminal window that contains 1209 * Builds a pixmap of the same size as the terminal window that contains
1187 * the tiled portion of the root pixmap that is supposed to be covered by 1210 * the tiled portion of the root pixmap that is supposed to be covered by
1188 * our window. 1211 * our window.
1189 */ 1212 */
1190unsigned long 1213unsigned long
1234 if (root_pixmap != None && root_depth != depth) 1257 if (root_pixmap != None && root_depth != depth)
1235 { 1258 {
1236#if XRENDER 1259#if XRENDER
1237 if (bg_flags & BG_HAS_RENDER) 1260 if (bg_flags & BG_HAS_RENDER)
1238 { 1261 {
1239 XRenderPictureAttributes pa; 1262 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth);
1240 1263
1241 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen)); 1264 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
1242 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, &pa); 1265 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, 0);
1243 1266
1244 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth);
1245 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual); 1267 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
1246 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, &pa); 1268 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, 0);
1247 1269
1248 if (src && dst)
1249 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, root_pmap_width, root_pmap_height); 1270 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, root_pmap_width, root_pmap_height);
1250 else
1251 {
1252 XFreePixmap (dpy, recoded_root_pmap);
1253 root_pixmap = None;
1254 }
1255 1271
1256 XRenderFreePicture (dpy, src); 1272 XRenderFreePicture (dpy, src);
1257 XRenderFreePicture (dpy, dst); 1273 XRenderFreePicture (dpy, dst);
1258 } 1274 }
1259 else 1275 else
1260#endif 1276#endif
1261 root_pixmap = None; 1277 recoded_root_pmap = None;
1262 } 1278 }
1263 1279
1264 if (root_pixmap == None) 1280 if (recoded_root_pmap == None)
1265 return 0; 1281 return 0;
1266 1282
1267 if (bg_pixmap == None 1283 if (bg_pixmap == None
1268 || bg_pmap_width != window_width 1284 || bg_pmap_width != window_width
1269 || bg_pmap_height != window_height) 1285 || bg_pmap_height != window_height)
1273 bg_pixmap = XCreatePixmap (dpy, vt, window_width, window_height, depth); 1289 bg_pixmap = XCreatePixmap (dpy, vt, window_width, window_height, depth);
1274 bg_pmap_width = window_width; 1290 bg_pmap_width = window_width;
1275 bg_pmap_height = window_height; 1291 bg_pmap_height = window_height;
1276 } 1292 }
1277 1293
1278 if (bg_pixmap == None)
1279 return 0;
1280
1281 /* straightforward pixmap copy */ 1294 /* straightforward pixmap copy */
1282 while (sx < 0) sx += (int)root_width; 1295 while (sx < 0) sx += root_pmap_width;
1283 while (sy < 0) sy += (int)root_height; 1296 while (sy < 0) sy += root_pmap_height;
1284 1297
1285 gcv.tile = recoded_root_pmap; 1298 gcv.tile = recoded_root_pmap;
1286 gcv.fill_style = FillTiled; 1299 gcv.fill_style = FillTiled;
1287 gcv.ts_x_origin = -sx; 1300 gcv.ts_x_origin = -sx;
1288 gcv.ts_y_origin = -sy; 1301 gcv.ts_y_origin = -sy;
1290 1303
1291 if (gc) 1304 if (gc)
1292 { 1305 {
1293 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height); 1306 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height);
1294 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS); 1307 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS);
1295 XFreeGC (dpy, gc);
1296 1308
1297 if (!(bg_flags & BG_CLIENT_RENDER)) 1309 if (!(bg_flags & BG_CLIENT_RENDER))
1298 { 1310 {
1299 if ((bg_flags & BG_NEEDS_BLUR) 1311 if (bg_flags & BG_NEEDS_BLUR)
1300 && (bg_flags & BG_HAS_RENDER_CONV))
1301 { 1312 {
1302 if (blur_pixmap (bg_pixmap, visual, window_width, window_height)) 1313 if (blur_pixmap (bg_pixmap, visual, window_width, window_height, depth))
1303 result &= ~BG_NEEDS_BLUR; 1314 result &= ~BG_NEEDS_BLUR;
1304 } 1315 }
1305 if ((bg_flags & BG_NEEDS_TINT) 1316 if (bg_flags & BG_NEEDS_TINT)
1306 && (bg_flags & (BG_TINT_BITAND | BG_HAS_RENDER)))
1307 { 1317 {
1308 if (tint_pixmap (bg_pixmap, visual, window_width, window_height)) 1318 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1309 result &= ~BG_NEEDS_TINT; 1319 result &= ~BG_NEEDS_TINT;
1310 } 1320 }
1321# ifndef HAVE_AFTERIMAGE
1322 if (result & BG_NEEDS_TINT)
1323 {
1324 XImage *ximage = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1325 if (ximage)
1326 {
1327 /* our own client-side tinting */
1328 tint_ximage (DefaultVisual (dpy, display->screen), ximage);
1329
1330 XPutImage (dpy, bg_pixmap, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
1331 XDestroyImage (ximage);
1332 }
1333 }
1334# endif
1311 } /* server side rendering completed */ 1335 } /* server side rendering completed */
1336
1337 XFreeGC (dpy, gc);
1312 } 1338 }
1313 1339
1314 if (recoded_root_pmap != root_pixmap) 1340 if (recoded_root_pmap != root_pixmap)
1315 XFreePixmap (dpy, recoded_root_pmap); 1341 XFreePixmap (dpy, recoded_root_pmap);
1316 1342
1325 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]); 1351 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]);
1326 1352
1327 root_pixmap = new_root_pixmap; 1353 root_pixmap = new_root_pixmap;
1328} 1354}
1329# endif /* ENABLE_TRANSPARENCY */ 1355# endif /* ENABLE_TRANSPARENCY */
1330
1331#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1332static void shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c);
1333# endif
1334 1356
1335bool 1357bool
1336rxvt_term::bg_render () 1358rxvt_term::bg_render ()
1337{ 1359{
1338 unsigned long tr_flags = 0; 1360 unsigned long tr_flags = 0;
1343 { 1365 {
1344 /* we need to re-generate transparency pixmap in that case ! */ 1366 /* we need to re-generate transparency pixmap in that case ! */
1345 tr_flags = make_transparency_pixmap (); 1367 tr_flags = make_transparency_pixmap ();
1346 if (tr_flags == 0) 1368 if (tr_flags == 0)
1347 return false; 1369 return false;
1348 else if (!(tr_flags & BG_EFFECTS_FLAGS))
1349 bg_flags |= BG_IS_VALID; 1370 bg_flags |= BG_IS_VALID;
1350 } 1371 }
1351# endif 1372# endif
1352 1373
1353# ifdef BG_IMAGE_FROM_FILE 1374# ifdef BG_IMAGE_FROM_FILE
1354 if ((bg_flags & BG_IS_FROM_FILE) 1375 if ((bg_flags & BG_IS_FROM_FILE)
1355 || (tr_flags & BG_EFFECTS_FLAGS)) 1376 || (tr_flags & BG_EFFECTS_FLAGS))
1356 { 1377 {
1357 if (render_image (tr_flags)) 1378 if (render_image (tr_flags))
1358 bg_flags |= BG_IS_VALID; 1379 bg_flags |= BG_IS_VALID;
1359 }
1360# endif
1361
1362# if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1363 XImage *result = NULL;
1364
1365 if (tr_flags && !(bg_flags & BG_IS_VALID))
1366 {
1367 result = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1368 }
1369
1370 if (result)
1371 {
1372 /* our own client-side tinting */
1373 if (tr_flags & BG_NEEDS_TINT)
1374 {
1375 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
1376 if (bg_flags & BG_TINT_SET)
1377 tint.get (c);
1378 shade_ximage (DefaultVisual (dpy, display->screen), result, shade, c);
1379 }
1380
1381 GC gc = XCreateGC (dpy, vt, 0UL, NULL);
1382
1383 if (gc)
1384 {
1385 XPutImage (dpy, bg_pixmap, gc, result, 0, 0, 0, 0, result->width, result->height);
1386
1387 XFreeGC (dpy, gc);
1388 bg_flags |= BG_IS_VALID;
1389 }
1390
1391 XDestroyImage (result);
1392 } 1380 }
1393# endif 1381# endif
1394 1382
1395 if (!(bg_flags & BG_IS_VALID)) 1383 if (!(bg_flags & BG_IS_VALID))
1396 { 1384 {
1434} 1422}
1435 1423
1436#endif /* HAVE_BG_PIXMAP */ 1424#endif /* HAVE_BG_PIXMAP */
1437 1425
1438#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) 1426#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1439/* taken from aterm-0.4.2 */ 1427/* based on code from aterm-0.4.2 */
1440 1428
1441static void 1429static inline void
1442shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c) 1430fill_lut (uint32_t *lookup, uint32_t mask, int sh, unsigned short low, unsigned short high)
1431{
1432 for (int i = 0; i <= mask >> sh; i++)
1433 {
1434 uint32_t tmp;
1435 tmp = i * high;
1436 tmp += (mask >> sh) * low;
1437 lookup[i] = (tmp / 0xffff) << sh;
1438 }
1439}
1440
1441void
1442rxvt_term::tint_ximage (Visual *visual, XImage *ximage)
1443{ 1443{
1444 int sh_r, sh_g, sh_b; 1444 int sh_r, sh_g, sh_b;
1445 uint32_t mask_r, mask_g, mask_b; 1445 uint32_t mask_r, mask_g, mask_b;
1446 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; 1446 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b;
1447 rgba low; 1447 unsigned short low;
1448 rgba high;
1449 int i;
1450 int host_byte_order = byteorder::big_endian () ? MSBFirst : LSBFirst; 1448 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
1451 1449
1452 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return; 1450 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return;
1453 1451
1454 /* for convenience */ 1452 /* for convenience */
1455 mask_r = visual->red_mask; 1453 mask_r = visual->red_mask;
1513 break; 1511 break;
1514 default: 1512 default:
1515 return; /* we do not support this color depth */ 1513 return; /* we do not support this color depth */
1516 } 1514 }
1517 1515
1516 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1517
1518 if (bg_flags & BG_TINT_SET)
1519 tint.get (c);
1520
1518 /* prepare limits for color transformation (each channel is handled separately) */ 1521 /* prepare limits for color transformation (each channel is handled separately) */
1519 if (shade > 100) 1522 if (shade > 100)
1520 { 1523 {
1521 shade = 200 - shade;
1522
1523 high.r = c.r * shade / 100;
1524 high.g = c.g * shade / 100;
1525 high.b = c.b * shade / 100;
1526
1527 low.r = 65535 * (100 - shade) / 100; 1524 c.r = c.r * (200 - shade) / 100;
1528 low.g = 65535 * (100 - shade) / 100; 1525 c.g = c.g * (200 - shade) / 100;
1529 low.b = 65535 * (100 - shade) / 100; 1526 c.b = c.b * (200 - shade) / 100;
1527
1528 low = 0xffff * (shade - 100) / 100;
1530 } 1529 }
1531 else 1530 else
1532 { 1531 {
1533 high.r = c.r * shade / 100; 1532 c.r = c.r * shade / 100;
1534 high.g = c.g * shade / 100; 1533 c.g = c.g * shade / 100;
1535 high.b = c.b * shade / 100; 1534 c.b = c.b * shade / 100;
1536 1535
1537 low.r = low.g = low.b = 0; 1536 low = 0;
1538 } 1537 }
1539 1538
1540 /* fill our lookup tables */ 1539 /* fill our lookup tables */
1541 for (i = 0; i <= mask_r>>sh_r; i++) 1540 fill_lut (lookup_r, mask_r, sh_r, low, c.r);
1542 { 1541 fill_lut (lookup_g, mask_g, sh_g, low, c.g);
1543 uint32_t tmp; 1542 fill_lut (lookup_b, mask_b, sh_b, low, c.b);
1544 tmp = i * high.r;
1545 tmp += (mask_r>>sh_r) * low.r;
1546 lookup_r[i] = (tmp/65535)<<sh_r;
1547 }
1548 for (i = 0; i <= mask_g>>sh_g; i++)
1549 {
1550 uint32_t tmp;
1551 tmp = i * high.g;
1552 tmp += (mask_g>>sh_g) * low.g;
1553 lookup_g[i] = (tmp/65535)<<sh_g;
1554 }
1555 for (i = 0; i <= mask_b>>sh_b; i++)
1556 {
1557 uint32_t tmp;
1558 tmp = i * high.b;
1559 tmp += (mask_b>>sh_b) * low.b;
1560 lookup_b[i] = (tmp/65535)<<sh_b;
1561 }
1562 1543
1563 /* apply table to input image (replacing colors by newly calculated ones) */ 1544 /* apply table to input image (replacing colors by newly calculated ones) */
1564 if (ximage->bits_per_pixel == 32 1545 if (ximage->bits_per_pixel == 32
1565 && (ximage->depth == 24 || ximage->depth == 32) 1546 && (ximage->depth == 24 || ximage->depth == 32)
1566 && ximage->byte_order == host_byte_order) 1547 && ximage->byte_order == host_byte_order)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines