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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines