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.152 by sf-exg, Sun May 8 21:03:03 2011 UTC vs.
Revision 1.194 by sf-exg, Sun Jan 1 17:43:47 2012 UTC

32 32
33#ifndef FilterConvolution 33#ifndef FilterConvolution
34#define FilterConvolution "convolution" 34#define FilterConvolution "convolution"
35#endif 35#endif
36 36
37/*
38 * Pixmap geometry string interpretation :
39 * Each geometry string contains zero or one scale/position
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
63#ifdef HAVE_BG_PIXMAP 37#ifdef HAVE_BG_PIXMAP
38# if XRENDER
39static Picture
40create_xrender_mask (Display *dpy, Drawable drawable, Bool argb, Bool component_alpha)
41{
42 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8);
43
44 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8);
45 XRenderPictureAttributes pa;
46 pa.repeat = True;
47 pa.component_alpha = component_alpha;
48 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat | CPComponentAlpha, &pa);
49
50 XFreePixmap (dpy, pixmap);
51
52 return mask;
53}
54# endif
55
64void 56void
65rxvt_term::bg_destroy () 57rxvt_term::bg_destroy ()
66{ 58{
67#ifdef HAVE_AFTERIMAGE 59#ifdef HAVE_AFTERIMAGE
68 if (original_asim) 60 if (original_asim)
176 int smaller = min (image_size, window_size); 168 int smaller = min (image_size, window_size);
177 169
178 if (align >= 0 && align <= 100) 170 if (align >= 0 && align <= 100)
179 return diff * align / 100; 171 return diff * align / 100;
180 else if (align > 100 && align <= 200) 172 else if (align > 100 && align <= 200)
181 return ((align - 100) * smaller / 100) + window_size - smaller; 173 return (align - 100) * smaller / 100 + window_size - smaller;
182 else if (align >= -100 && align < 0) 174 else if (align >= -100 && align < 0)
183 return ((align + 100) * smaller / 100) - image_size; 175 return (align + 100) * smaller / 100 - image_size;
184 return 0; 176 return 0;
185} 177}
186 178
187static inline int 179static inline int
188make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_size) 180make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_size)
207{ 199{
208 bool changed = false; 200 bool changed = false;
209 int geom_flags = 0; 201 int geom_flags = 0;
210 int x = 0, y = 0; 202 int x = 0, y = 0;
211 unsigned int w = 0, h = 0; 203 unsigned int w = 0, h = 0;
212 unsigned int n; 204 unsigned long new_flags = 0;
213 unsigned long new_flags = (bg_flags & (~BG_GEOMETRY_FLAGS));
214 const char *ops;
215 205
216 if (geom == NULL) 206 if (geom == NULL)
217 return false; 207 return false;
218 208
219 char str[256]; 209 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 { 210 {
236 /* we have geometry string - let's handle it prior to applying ops */ 211 char **arr = rxvt_strsplit (':', geom);
212
213 for (int i = 0; arr[i]; i++)
214 {
215 if (!strcasecmp (arr[i], "style=tiled"))
216 {
217 new_flags = BG_TILE;
218 w = h = noScale;
219 x = y = 0;
220 geom_flags = WidthValue|HeightValue|XValue|YValue;
221 }
222 else if (!strcasecmp (arr[i], "style=aspect-stretched"))
223 {
224 new_flags = BG_KEEP_ASPECT;
225 w = h = windowScale;
226 x = y = centerAlign;
227 geom_flags = WidthValue|HeightValue|XValue|YValue;
228 }
229 else if (!strcasecmp (arr[i], "style=stretched"))
230 {
231 new_flags = 0;
232 w = h = windowScale;
233 geom_flags = WidthValue|HeightValue;
234 }
235 else if (!strcasecmp (arr[i], "style=centered"))
236 {
237 new_flags = 0;
238 w = h = noScale;
239 x = y = centerAlign;
240 geom_flags = WidthValue|HeightValue|XValue|YValue;
241 }
242 else if (!strcasecmp (arr[i], "style=root-tiled"))
243 {
244 new_flags = BG_TILE|BG_ROOT_ALIGN;
245 w = h = noScale;
246 geom_flags = WidthValue|HeightValue;
247 }
248 else if (!strcasecmp (arr[i], "op=tile"))
249 new_flags |= BG_TILE;
250 else if (!strcasecmp (arr[i], "op=keep-aspect"))
251 new_flags |= BG_KEEP_ASPECT;
252 else if (!strcasecmp (arr[i], "op=root-align"))
253 new_flags |= BG_ROOT_ALIGN;
254
255 // deprecated
256 else if (!strcasecmp (arr[i], "tile"))
257 {
258 new_flags |= BG_TILE;
259 w = h = noScale;
260 geom_flags |= WidthValue|HeightValue;
261 }
262 else if (!strcasecmp (arr[i], "propscale"))
263 {
264 new_flags |= BG_KEEP_ASPECT;
265 w = h = windowScale;
266 geom_flags |= WidthValue|HeightValue;
267 }
268 else if (!strcasecmp (arr[i], "hscale"))
269 {
270 new_flags |= BG_TILE;
271 w = windowScale;
272 h = noScale;
273 geom_flags |= WidthValue|HeightValue;
274 }
275 else if (!strcasecmp (arr[i], "vscale"))
276 {
277 new_flags |= BG_TILE;
278 h = windowScale;
279 w = noScale;
280 geom_flags |= WidthValue|HeightValue;
281 }
282 else if (!strcasecmp (arr[i], "scale"))
283 {
284 w = h = windowScale;
285 geom_flags |= WidthValue|HeightValue;
286 }
287 else if (!strcasecmp (arr[i], "auto"))
288 {
289 w = h = windowScale;
290 x = y = centerAlign;
291 geom_flags |= WidthValue|HeightValue|XValue|YValue;
292 }
293 else if (!strcasecmp (arr[i], "root"))
294 {
295 new_flags |= BG_TILE|BG_ROOT_ALIGN;
296 w = h = noScale;
297 geom_flags |= WidthValue|HeightValue;
298 }
299
300 else
237 geom_flags = XParseGeometry (str, &x, &y, &w, &h); 301 geom_flags |= XParseGeometry (arr[i], &x, &y, &w, &h);
238 } /* done parsing geometry string */ 302 } /* done parsing ops */
303
304 rxvt_free_strsplit (arr);
305 }
306
307 new_flags |= bg_flags & ~BG_GEOMETRY_FLAGS;
239 308
240 if (!update) 309 if (!update)
241 { 310 {
242 if (!(geom_flags & XValue)) 311 if (!(geom_flags & XValue))
243 x = y = defaultAlign; 312 x = y = defaultAlign;
252 w = h; 321 w = h;
253 322
254 geom_flags |= WidthValue|HeightValue|XValue|YValue; 323 geom_flags |= WidthValue|HeightValue|XValue|YValue;
255 } 324 }
256 325
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; 326 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; 327 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; 328 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; 329 if (check_set_align_value (geom_flags, YValue, v_align, y)) changed = true;
314 330
325rxvt_term::get_image_geometry (int image_width, int image_height, int &w, int &h, int &x, int &y) 341rxvt_term::get_image_geometry (int image_width, int image_height, int &w, int &h, int &x, int &y)
326{ 342{
327 int target_width = szHint.width; 343 int target_width = szHint.width;
328 int target_height = szHint.height; 344 int target_height = szHint.height;
329 345
346 w = h_scale * target_width / 100;
347 h = v_scale * target_height / 100;
348
330 if (bg_flags & BG_PROP_SCALE) 349 if (bg_flags & BG_KEEP_ASPECT)
331 { 350 {
332 float scale = (float)target_width / image_width; 351 float scale = (float)w / image_width;
333 min_it (scale, (float)target_height / image_height); 352 min_it (scale, (float)h / image_height);
334 w = image_width * scale + 0.5; 353 w = image_width * scale + 0.5;
335 h = image_height * scale + 0.5; 354 h = image_height * scale + 0.5;
336 } 355 }
337 else
338 {
339 w = h_scale * target_width / 100;
340 h = v_scale * target_height / 100;
341 }
342 356
343 if (!w) w = image_width; 357 if (!w) w = image_width;
344 if (!h) h = image_height; 358 if (!h) h = image_height;
345 359
346 if (bg_flags & BG_ROOT_ALIGN) 360 if (bg_flags & BG_ROOT_ALIGN)
353 x = make_align_position (h_align, target_width, w); 367 x = make_align_position (h_align, target_width, w);
354 y = make_align_position (v_align, target_height, h); 368 y = make_align_position (v_align, target_height, h);
355 } 369 }
356 370
357 bg_flags &= ~BG_IS_SIZE_SENSITIVE; 371 bg_flags &= ~BG_IS_SIZE_SENSITIVE;
358 if ((bg_flags & BG_PROP_SCALE) || h_scale || v_scale 372 if (!(bg_flags & BG_TILE)
373 || h_scale || v_scale
359 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align)) 374 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align))
360 || w > target_width || h > target_height) 375 || w > target_width || h > target_height)
361 bg_flags |= BG_IS_SIZE_SENSITIVE; 376 bg_flags |= BG_IS_SIZE_SENSITIVE;
362} 377}
363 378
390 } 405 }
391 406
392 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL) 407 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL)
393 { 408 {
394 ASImage *tmp = blur_asimage_gauss (asv, background, h_blurRadius, v_blurRadius, 0xFFFFFFFF, 409 ASImage *tmp = blur_asimage_gauss (asv, background, h_blurRadius, v_blurRadius, 0xFFFFFFFF,
395 (original_asim == NULL || tint == TINT_LEAVE_SAME) ? ASA_XImage : ASA_ASImage, 410 ASA_XImage,
396 100, ASIMAGE_QUALITY_DEFAULT); 411 100, ASIMAGE_QUALITY_DEFAULT);
397 if (tmp) 412 if (tmp)
398 { 413 {
399 destroy_asimage (&background); 414 destroy_asimage (&background);
400 background = tmp; 415 background = tmp;
419 434
420 if (!original_asim 435 if (!original_asim
421 || (!(bg_flags & BG_ROOT_ALIGN) 436 || (!(bg_flags & BG_ROOT_ALIGN)
422 && (x >= target_width 437 && (x >= target_width
423 || y >= target_height 438 || y >= target_height
424 || (x + w <= 0) 439 || x + w <= 0
425 || (y + h <= 0)))) 440 || y + h <= 0)))
426 { 441 {
427 if (background) 442 if (background)
428 { 443 {
429 new_pmap_width = background->width; 444 new_pmap_width = background->width;
430 new_pmap_height = background->height; 445 new_pmap_height = background->height;
444 } 459 }
445 else 460 else
446 { 461 {
447 result = original_asim; 462 result = original_asim;
448 463
449 if ((w != original_asim->width) 464 if (w != original_asim->width
450 || (h != original_asim->height)) 465 || h != original_asim->height)
451 { 466 {
452 result = scale_asimage (asv, original_asim, 467 result = scale_asimage (asv, original_asim,
453 w, h, 468 w, h,
454 background ? ASA_ASImage : ASA_XImage, 469 ASA_XImage,
455 100, ASIMAGE_QUALITY_DEFAULT); 470 100, ASIMAGE_QUALITY_DEFAULT);
456 } 471 }
457 472
458 if (background == NULL) 473 if (background == NULL)
459 { 474 {
460 if (h_scale == 0 || v_scale == 0) 475 if (bg_flags & BG_TILE)
461 { 476 {
462 /* if tiling - pixmap has to be sized exactly as the image, 477 /* if tiling - pixmap has to be sized exactly as the image,
463 but there is no need to make it bigger than the window! */ 478 but there is no need to make it bigger than the window! */
464 new_pmap_width = min (result->width, target_width); 479 new_pmap_width = min (result->width, target_width);
465 new_pmap_height = min (result->height, target_height); 480 new_pmap_height = min (result->height, target_height);
490 layers[0].clip_width = target_width; 505 layers[0].clip_width = target_width;
491 layers[0].clip_height = target_height; 506 layers[0].clip_height = target_height;
492 layers[0].tint = background_tint; 507 layers[0].tint = background_tint;
493 layers[1].im = result; 508 layers[1].im = result;
494 509
495 if (h_scale == 0 || v_scale == 0) 510 if (bg_flags & BG_TILE)
496 { 511 {
497 /* tile horizontally */ 512 /* tile horizontally */
498 while (x > 0) x -= (int)result->width; 513 while (x > 0) x -= (int)result->width;
499 layers[1].dst_x = x; 514 layers[1].dst_x = x;
500 layers[1].clip_width = result->width+target_width; 515 layers[1].clip_width = result->width+target_width;
504 /* clip horizontally */ 519 /* clip horizontally */
505 layers[1].dst_x = x; 520 layers[1].dst_x = x;
506 layers[1].clip_width = result->width; 521 layers[1].clip_width = result->width;
507 } 522 }
508 523
509 if (h_scale == 0 || v_scale == 0) 524 if (bg_flags & BG_TILE)
510 { 525 {
511 while (y > 0) y -= (int)result->height; 526 while (y > 0) y -= (int)result->height;
512 layers[1].dst_y = y; 527 layers[1].dst_y = y;
513 layers[1].clip_height = result->height + target_height; 528 layers[1].clip_height = result->height + target_height;
514 } 529 }
564 579
565 int src_x = 0, src_y = 0, dst_x = 0, dst_y = 0; 580 int src_x = 0, src_y = 0, dst_x = 0, dst_y = 0;
566 int dst_width = result->width, dst_height = result->height; 581 int dst_width = result->width, dst_height = result->height;
567 if (background == NULL) 582 if (background == NULL)
568 { 583 {
569 if (!(h_scale == 0 || v_scale == 0)) 584 if (!(bg_flags & BG_TILE))
570 { 585 {
571 src_x = make_clip_rectangle (x, result->width , new_pmap_width , dst_x, dst_width ); 586 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); 587 src_y = make_clip_rectangle (y, result->height, new_pmap_height, dst_y, dst_height);
573 } 588 }
574 589
620 else if (depth == 15 || depth == 16) 635 else if (depth == 15 || depth == 16)
621 bytes_per_pixel = 2; 636 bytes_per_pixel = 2;
622 else 637 else
623 return false; 638 return false;
624 639
625 width_r = rxvt_popcount (visual->red_mask); 640 width_r = ecb_popcount32 (visual->red_mask);
626 width_g = rxvt_popcount (visual->green_mask); 641 width_g = ecb_popcount32 (visual->green_mask);
627 width_b = rxvt_popcount (visual->blue_mask); 642 width_b = ecb_popcount32 (visual->blue_mask);
628 643
629 if (width_r > 8 || width_g > 8 || width_b > 8) 644 if (width_r > 8 || width_g > 8 || width_b > 8)
630 return false; 645 return false;
631 646
632 sh_r = rxvt_ctz (visual->red_mask); 647 sh_r = ecb_ctz32 (visual->red_mask);
633 sh_g = rxvt_ctz (visual->green_mask); 648 sh_g = ecb_ctz32 (visual->green_mask);
634 sh_b = rxvt_ctz (visual->blue_mask); 649 sh_b = ecb_ctz32 (visual->blue_mask);
635 650
636 if (width > INT_MAX / height / bytes_per_pixel) 651 if (width > INT_MAX / height / bytes_per_pixel)
637 return false; 652 return false;
638 653
639 data = (char *)malloc (width * height * bytes_per_pixel); 654 data = (char *)malloc (width * height * bytes_per_pixel);
646 { 661 {
647 free (data); 662 free (data);
648 return false; 663 return false;
649 } 664 }
650 665
651 ximage->byte_order = byteorder::big_endian () ? MSBFirst : LSBFirst; 666 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
652 667
653 rowstride = gdk_pixbuf_get_rowstride (pixbuf); 668 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
654 channels = gdk_pixbuf_get_n_channels (pixbuf); 669 channels = gdk_pixbuf_get_n_channels (pixbuf);
655 row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels; 670 row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels;
656 line = data; 671 line = data;
709 get_image_geometry (image_width, image_height, w, h, x, y); 724 get_image_geometry (image_width, image_height, w, h, x, y);
710 725
711 if (!(bg_flags & BG_ROOT_ALIGN) 726 if (!(bg_flags & BG_ROOT_ALIGN)
712 && (x >= target_width 727 && (x >= target_width
713 || y >= target_height 728 || y >= target_height
714 || (x + w <= 0) 729 || x + w <= 0
715 || (y + h <= 0))) 730 || y + h <= 0))
716 return false; 731 return false;
717 732
718 result = pixbuf; 733 result = pixbuf;
719 734
720 if ((w != image_width) 735 if (w != image_width
721 || (h != image_height)) 736 || h != image_height)
722 { 737 {
723 result = gdk_pixbuf_scale_simple (pixbuf, 738 result = gdk_pixbuf_scale_simple (pixbuf,
724 w, h, 739 w, h,
725 GDK_INTERP_BILINEAR); 740 GDK_INTERP_BILINEAR);
726 } 741 }
742 root_pmap = bg_pixmap; 757 root_pmap = bg_pixmap;
743 bg_pixmap = None; 758 bg_pixmap = None;
744 } 759 }
745 else 760 else
746 { 761 {
747 if (h_scale == 0 || v_scale == 0) 762 if (bg_flags & BG_TILE)
748 { 763 {
749 new_pmap_width = min (image_width, target_width); 764 new_pmap_width = min (image_width, target_width);
750 new_pmap_height = min (image_height, target_height); 765 new_pmap_height = min (image_height, target_height);
751 } 766 }
752 } 767 }
760 bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth); 775 bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth);
761 bg_pmap_width = new_pmap_width; 776 bg_pmap_width = new_pmap_width;
762 bg_pmap_height = new_pmap_height; 777 bg_pmap_height = new_pmap_height;
763 } 778 }
764 779
765 if (bg_pixmap != None)
766 {
767 gcv.foreground = pix_colors[Color_bg]; 780 gcv.foreground = pix_colors[Color_bg];
768 gc = XCreateGC (dpy, vt, GCForeground, &gcv); 781 gc = XCreateGC (dpy, vt, GCForeground, &gcv);
769 782
770 if (gc) 783 if (gc)
771 { 784 {
772 if (h_scale == 0 || v_scale == 0) 785 if (bg_flags & BG_TILE)
773 { 786 {
774 Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, depth); 787 Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, depth);
775
776 if (tile != None)
777 {
778 pixbuf_to_pixmap (result, tile, gc, 788 pixbuf_to_pixmap (result, tile, gc,
779 0, 0, 789 0, 0,
780 0, 0, 790 0, 0,
781 image_width, image_height); 791 image_width, image_height);
782 792
783 gcv.tile = tile; 793 gcv.tile = tile;
784 gcv.fill_style = FillTiled; 794 gcv.fill_style = FillTiled;
785 gcv.ts_x_origin = x; 795 gcv.ts_x_origin = x;
786 gcv.ts_y_origin = y; 796 gcv.ts_y_origin = y;
787 XChangeGC (dpy, gc, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv); 797 XChangeGC (dpy, gc, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv);
788 798
789 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); 799 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height);
790 XFreePixmap (dpy, tile); 800 XFreePixmap (dpy, tile);
791 }
792 } 801 }
793 else 802 else
794 { 803 {
795 int src_x, src_y, dst_x, dst_y; 804 int src_x, src_y, dst_x, dst_y;
796 int dst_width, dst_height; 805 int dst_width, dst_height;
797 806
798 src_x = make_clip_rectangle (x, image_width , new_pmap_width , dst_x, dst_width ); 807 src_x = make_clip_rectangle (x, image_width , new_pmap_width , dst_x, dst_width );
799 src_y = make_clip_rectangle (y, image_height, new_pmap_height, dst_y, dst_height); 808 src_y = make_clip_rectangle (y, image_height, new_pmap_height, dst_y, dst_height);
800 809
801 if (dst_x > 0 || dst_y > 0 810 if (dst_x > 0 || dst_y > 0
802 || dst_x + dst_width < new_pmap_width 811 || dst_x + dst_width < new_pmap_width
803 || dst_y + dst_height < new_pmap_height) 812 || dst_y + dst_height < new_pmap_height)
804 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); 813 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height);
805 814
806 if (dst_x < new_pmap_width && dst_y < new_pmap_height) 815 if (dst_x < new_pmap_width && dst_y < new_pmap_height)
807 pixbuf_to_pixmap (result, bg_pixmap, gc, 816 pixbuf_to_pixmap (result, bg_pixmap, gc,
808 src_x, src_y, 817 src_x, src_y,
809 dst_x, dst_y, 818 dst_x, dst_y,
810 dst_width, dst_height); 819 dst_width, dst_height);
811 } 820 }
812 821
813#if XRENDER 822#if XRENDER
814 if (tr_flags) 823 if (tr_flags)
815 { 824 {
816 XRenderPictureAttributes pa;
817
818 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, visual); 825 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
826
819 Picture src = XRenderCreatePicture (dpy, root_pmap, src_format, 0, &pa); 827 Picture src = XRenderCreatePicture (dpy, root_pmap, format, 0, 0);
820 828
821 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
822 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, dst_format, 0, &pa); 829 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, format, 0, 0);
823 830
824 pa.repeat = True; 831 Picture mask = create_xrender_mask (dpy, vt, False, False);
825 Pixmap mask_pmap = XCreatePixmap (dpy, vt, 1, 1, 8);
826 XRenderPictFormat *mask_format = XRenderFindStandardFormat (dpy, PictStandardA8);
827 Picture mask = XRenderCreatePicture (dpy, mask_pmap, mask_format, CPRepeat, &pa);
828 XFreePixmap (dpy, mask_pmap);
829 832
830 if (src && dst && mask)
831 {
832 XRenderColor mask_c; 833 XRenderColor mask_c;
833 834
834 mask_c.alpha = 0x8000; 835 mask_c.alpha = 0x8000;
835 mask_c.red = 0; 836 mask_c.red =
836 mask_c.green = 0; 837 mask_c.green =
837 mask_c.blue = 0; 838 mask_c.blue = 0;
838 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); 839 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
840
839 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, target_width, target_height); 841 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, target_width, target_height);
840 }
841 842
842 XRenderFreePicture (dpy, src); 843 XRenderFreePicture (dpy, src);
843 XRenderFreePicture (dpy, dst); 844 XRenderFreePicture (dpy, dst);
844 XRenderFreePicture (dpy, mask); 845 XRenderFreePicture (dpy, mask);
845 } 846 }
846#endif 847#endif
847 848
848 XFreeGC (dpy, gc); 849 XFreeGC (dpy, gc);
849 850
850 ret = true; 851 ret = true;
851 }
852 } 852 }
853 853
854 if (result != pixbuf) 854 if (result != pixbuf)
855 g_object_unref (result); 855 g_object_unref (result);
856 856
865rxvt_term::bg_set_file (const char *file) 865rxvt_term::bg_set_file (const char *file)
866{ 866{
867 if (!file || !*file) 867 if (!file || !*file)
868 return false; 868 return false;
869 869
870 bool ret = false;
870 if (const char *p = strchr (file, ';')) 871 const char *p = strchr (file, ';');
872
873 if (p)
871 { 874 {
872 size_t len = p - file; 875 size_t len = p - file;
873 char *f = rxvt_temp_buf<char> (len + 1); 876 char *f = rxvt_temp_buf<char> (len + 1);
874 memcpy (f, file, len); 877 memcpy (f, file, len);
875 f[len] = '\0'; 878 f[len] = '\0';
884 { 887 {
885 if (original_asim) 888 if (original_asim)
886 safe_asimage_destroy (original_asim); 889 safe_asimage_destroy (original_asim);
887 original_asim = image; 890 original_asim = image;
888 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER; 891 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER;
889 return true; 892 ret = true;
890 } 893 }
891# endif 894# endif
892 895
893# ifdef HAVE_PIXBUF 896# ifdef HAVE_PIXBUF
894 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL); 897 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL);
896 { 899 {
897 if (pixbuf) 900 if (pixbuf)
898 g_object_unref (pixbuf); 901 g_object_unref (pixbuf);
899 pixbuf = image; 902 pixbuf = image;
900 bg_flags |= BG_IS_FROM_FILE; 903 bg_flags |= BG_IS_FROM_FILE;
901 return true; 904 ret = true;
902 } 905 }
903# endif 906# endif
904 907
908 if (ret)
909 {
910 if (p)
911 bg_set_geometry (p + 1);
912 else
913 bg_set_default_geometry ();
914 }
915
905 return false; 916 return ret;
906} 917}
907 918
908# endif /* BG_IMAGE_FROM_FILE */ 919# endif /* BG_IMAGE_FROM_FILE */
909 920
910# ifdef ENABLE_TRANSPARENCY 921# ifdef ENABLE_TRANSPARENCY
946 { 957 {
947 changed = true; 958 changed = true;
948 v_blurRadius = vr; 959 v_blurRadius = vr;
949 } 960 }
950 961
951 if (v_blurRadius == 0 && h_blurRadius == 0) 962 if (h_blurRadius == 0 || v_blurRadius == 0)
952 bg_flags &= ~BG_NEEDS_BLUR; 963 bg_flags &= ~BG_NEEDS_BLUR;
953 else 964 else
954 bg_flags |= BG_NEEDS_BLUR; 965 bg_flags |= BG_NEEDS_BLUR;
955 966
956 return changed; 967 return changed;
957} 968}
958 969
959void 970void
960rxvt_term::set_tint_shade_flags () 971rxvt_term::set_tint_shade_flags ()
961{ 972{
962 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); 973 rgba c;
963 bool has_shade = shade != 100; 974 bool has_shade = shade != 100;
964 975
965 bg_flags &= ~BG_TINT_FLAGS; 976 bg_flags &= ~BG_TINT_FLAGS;
966 977
967 if (bg_flags & BG_TINT_SET) 978 if (bg_flags & BG_TINT_SET)
993} 1004}
994 1005
995bool 1006bool
996rxvt_term::bg_set_shade (const char *shade_str) 1007rxvt_term::bg_set_shade (const char *shade_str)
997{ 1008{
998 int new_shade = (shade_str) ? atoi (shade_str) : 100; 1009 int new_shade = atoi (shade_str);
999 1010
1000 clamp_it (new_shade, -100, 200); 1011 clamp_it (new_shade, -100, 200);
1001 if (new_shade < 0) 1012 if (new_shade < 0)
1002 new_shade = 200 - (100 + new_shade); 1013 new_shade = 200 - (100 + new_shade);
1003 1014
1037bool 1048bool
1038rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height) 1049rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height)
1039{ 1050{
1040 bool ret = false; 1051 bool ret = false;
1041#if XRENDER 1052#if XRENDER
1053 if (!(bg_flags & BG_HAS_RENDER_CONV))
1054 return false;
1055
1042 int size = max (h_blurRadius, v_blurRadius) * 2 + 1; 1056 int size = max (h_blurRadius, v_blurRadius) * 2 + 1;
1043 double *kernel = (double *)malloc (size * sizeof (double)); 1057 double *kernel = (double *)malloc (size * sizeof (double));
1044 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 1058 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
1045 1059
1046 XRenderPictureAttributes pa;
1047 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1060 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1048 1061
1049 Picture src = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1062 Picture src = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1050 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1063 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1051 1064
1052 if (kernel && params && src && dst) 1065 if (kernel && params)
1053 { 1066 {
1054 if (h_blurRadius)
1055 {
1056 size = h_blurRadius * 2 + 1; 1067 size = h_blurRadius * 2 + 1;
1057 get_gaussian_kernel (h_blurRadius, size, kernel, params); 1068 get_gaussian_kernel (h_blurRadius, size, kernel, params);
1058 1069
1059 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1070 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1060 XRenderComposite (dpy, 1071 XRenderComposite (dpy,
1061 PictOpSrc, 1072 PictOpSrc,
1062 src, 1073 src,
1063 None, 1074 None,
1064 dst, 1075 dst,
1065 0, 0, 1076 0, 0,
1066 0, 0, 1077 0, 0,
1067 0, 0, 1078 0, 0,
1068 width, height); 1079 width, height);
1069 }
1070 1080
1071 if (v_blurRadius)
1072 {
1073 size = v_blurRadius * 2 + 1; 1081 size = v_blurRadius * 2 + 1;
1074 get_gaussian_kernel (v_blurRadius, size, kernel, params); 1082 get_gaussian_kernel (v_blurRadius, size, kernel, params);
1075 ::swap (params[0], params[1]); 1083 ::swap (params[0], params[1]);
1076 1084
1077 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1085 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1078 XRenderComposite (dpy, 1086 XRenderComposite (dpy,
1079 PictOpSrc, 1087 PictOpSrc,
1080 src, 1088 src,
1081 None, 1089 None,
1082 dst, 1090 dst,
1083 0, 0, 1091 0, 0,
1084 0, 0, 1092 0, 0,
1085 0, 0, 1093 0, 0,
1086 width, height); 1094 width, height);
1087 }
1088 1095
1089 ret = true; 1096 ret = true;
1090 } 1097 }
1091 1098
1092 free (kernel); 1099 free (kernel);
1119 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height); 1126 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height);
1120 ret = true; 1127 ret = true;
1121 XFreeGC (dpy, gc); 1128 XFreeGC (dpy, gc);
1122 } 1129 }
1123 } 1130 }
1124 else
1125 {
1126# if XRENDER 1131# if XRENDER
1132 else if (bg_flags & BG_HAS_RENDER)
1133 {
1127 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); 1134 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1128 1135
1129 if (bg_flags & BG_TINT_SET) 1136 if (bg_flags & BG_TINT_SET)
1130 tint.get (c); 1137 tint.get (c);
1131 1138
1140 c.r = c.r * (200 - shade) / 100; 1147 c.r = c.r * (200 - shade) / 100;
1141 c.g = c.g * (200 - shade) / 100; 1148 c.g = c.g * (200 - shade) / 100;
1142 c.b = c.b * (200 - shade) / 100; 1149 c.b = c.b * (200 - shade) / 100;
1143 } 1150 }
1144 1151
1145 XRenderPictFormat *solid_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
1146 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1152 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1147 XRenderPictureAttributes pa;
1148 1153
1149 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1154 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1150 1155
1151 pa.repeat = True; 1156 Picture overlay_pic = create_xrender_mask (dpy, pixmap, True, False);
1152 1157
1153 Pixmap overlay_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32); 1158 Picture mask_pic = create_xrender_mask (dpy, pixmap, True, True);
1154 Picture overlay_pic = XRenderCreatePicture (dpy, overlay_pmap, solid_format, CPRepeat, &pa);
1155 XFreePixmap (dpy, overlay_pmap);
1156 1159
1157 pa.component_alpha = True;
1158 Pixmap mask_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32);
1159 Picture mask_pic = XRenderCreatePicture (dpy, mask_pmap, solid_format, CPRepeat | CPComponentAlpha, &pa);
1160 XFreePixmap (dpy, mask_pmap);
1161
1162 if (mask_pic && overlay_pic && back_pic)
1163 {
1164 XRenderColor mask_c; 1160 XRenderColor mask_c;
1165 1161
1166 mask_c.alpha = 0xffff; 1162 mask_c.alpha = 0xffff;
1163 mask_c.red =
1164 mask_c.green =
1165 mask_c.blue = 0;
1166 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1167
1168 mask_c.alpha = 0;
1169 mask_c.red = 0xffff - c.r;
1170 mask_c.green = 0xffff - c.g;
1171 mask_c.blue = 0xffff - c.b;
1172 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
1173
1174 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1175
1176 if (shade > 100)
1177 {
1178 mask_c.alpha = 0;
1167 mask_c.red = 1179 mask_c.red =
1168 mask_c.green = 1180 mask_c.green =
1169 mask_c.blue = 0; 1181 mask_c.blue = 0xffff * (shade - 100) / 100;
1170 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); 1182 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1171 1183
1172 mask_c.alpha = 0;
1173 mask_c.red = 0xffff - c.r;
1174 mask_c.green = 0xffff - c.g;
1175 mask_c.blue = 0xffff - c.b;
1176 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
1177 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1178
1179 if (shade > 100)
1180 {
1181 mask_c.red = mask_c.green = mask_c.blue = 0xffff * (shade - 100) / 100;
1182 mask_c.alpha = 0;
1183 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1184
1185 XRenderComposite (dpy, PictOpOver, overlay_pic, None, back_pic, 0, 0, 0, 0, 0, 0, width, height); 1184 XRenderComposite (dpy, PictOpOver, overlay_pic, None, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1186 } 1185 }
1187 1186
1188 ret = true; 1187 ret = true;
1189 }
1190 1188
1191 XRenderFreePicture (dpy, mask_pic); 1189 XRenderFreePicture (dpy, mask_pic);
1192 XRenderFreePicture (dpy, overlay_pic); 1190 XRenderFreePicture (dpy, overlay_pic);
1193 XRenderFreePicture (dpy, back_pic); 1191 XRenderFreePicture (dpy, back_pic);
1192 }
1194# endif 1193# endif
1195 }
1196 1194
1197 return ret; 1195 return ret;
1198} 1196}
1199 1197
1200/* 1198/*
1251#if XRENDER 1249#if XRENDER
1252 if (bg_flags & BG_HAS_RENDER) 1250 if (bg_flags & BG_HAS_RENDER)
1253 { 1251 {
1254 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth); 1252 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth);
1255 1253
1256 if (recoded_root_pmap != None)
1257 {
1258 XRenderPictureAttributes pa;
1259
1260 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen)); 1254 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
1261 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, &pa); 1255 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, 0);
1262 1256
1263 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual); 1257 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
1264 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, &pa); 1258 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, 0);
1265 1259
1266 if (src && dst)
1267 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, root_pmap_width, root_pmap_height); 1260 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, root_pmap_width, root_pmap_height);
1268 else
1269 {
1270 XFreePixmap (dpy, recoded_root_pmap);
1271 recoded_root_pmap = None;
1272 }
1273 1261
1274 XRenderFreePicture (dpy, src); 1262 XRenderFreePicture (dpy, src);
1275 XRenderFreePicture (dpy, dst); 1263 XRenderFreePicture (dpy, dst);
1276 }
1277 } 1264 }
1278 else 1265 else
1279#endif 1266#endif
1280 recoded_root_pmap = None; 1267 recoded_root_pmap = None;
1281 } 1268 }
1292 bg_pixmap = XCreatePixmap (dpy, vt, window_width, window_height, depth); 1279 bg_pixmap = XCreatePixmap (dpy, vt, window_width, window_height, depth);
1293 bg_pmap_width = window_width; 1280 bg_pmap_width = window_width;
1294 bg_pmap_height = window_height; 1281 bg_pmap_height = window_height;
1295 } 1282 }
1296 1283
1297 if (bg_pixmap != None)
1298 {
1299 /* straightforward pixmap copy */ 1284 /* straightforward pixmap copy */
1300 while (sx < 0) sx += (int)root_width; 1285 while (sx < 0) sx += root_pmap_width;
1301 while (sy < 0) sy += (int)root_height; 1286 while (sy < 0) sy += root_pmap_height;
1302 1287
1303 gcv.tile = recoded_root_pmap; 1288 gcv.tile = recoded_root_pmap;
1304 gcv.fill_style = FillTiled; 1289 gcv.fill_style = FillTiled;
1305 gcv.ts_x_origin = -sx; 1290 gcv.ts_x_origin = -sx;
1306 gcv.ts_y_origin = -sy; 1291 gcv.ts_y_origin = -sy;
1307 gc = XCreateGC (dpy, vt, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv); 1292 gc = XCreateGC (dpy, vt, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv);
1308 1293
1309 if (gc) 1294 if (gc)
1310 { 1295 {
1311 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height); 1296 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height);
1312 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS); 1297 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS);
1313 XFreeGC (dpy, gc);
1314 1298
1315 if (!(bg_flags & BG_CLIENT_RENDER)) 1299 if (!(bg_flags & BG_CLIENT_RENDER))
1316 { 1300 {
1317 if ((bg_flags & BG_NEEDS_BLUR) 1301 if (bg_flags & BG_NEEDS_BLUR)
1318 && (bg_flags & BG_HAS_RENDER_CONV)) 1302 {
1303 if (blur_pixmap (bg_pixmap, visual, window_width, window_height))
1304 result &= ~BG_NEEDS_BLUR;
1305 }
1306 if (bg_flags & BG_NEEDS_TINT)
1307 {
1308 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1309 result &= ~BG_NEEDS_TINT;
1310 }
1311# ifndef HAVE_AFTERIMAGE
1312 if (result & BG_NEEDS_TINT)
1313 {
1314 XImage *ximage = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1315 if (ximage)
1319 { 1316 {
1320 if (blur_pixmap (bg_pixmap, visual, window_width, window_height)) 1317 /* our own client-side tinting */
1321 result &= ~BG_NEEDS_BLUR; 1318 tint_ximage (DefaultVisual (dpy, display->screen), ximage);
1319
1320 XPutImage (dpy, bg_pixmap, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
1321 XDestroyImage (ximage);
1322 } 1322 }
1323 if ((bg_flags & BG_NEEDS_TINT)
1324 && (bg_flags & (BG_TINT_BITAND | BG_HAS_RENDER)))
1325 {
1326 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1327 result &= ~BG_NEEDS_TINT;
1328 } 1323 }
1324# endif
1329 } /* server side rendering completed */ 1325 } /* server side rendering completed */
1330 } 1326
1327 XFreeGC (dpy, gc);
1331 } 1328 }
1332 1329
1333 if (recoded_root_pmap != root_pixmap) 1330 if (recoded_root_pmap != root_pixmap)
1334 XFreePixmap (dpy, recoded_root_pmap); 1331 XFreePixmap (dpy, recoded_root_pmap);
1335 1332
1344 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]); 1341 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]);
1345 1342
1346 root_pixmap = new_root_pixmap; 1343 root_pixmap = new_root_pixmap;
1347} 1344}
1348# endif /* ENABLE_TRANSPARENCY */ 1345# endif /* ENABLE_TRANSPARENCY */
1349
1350#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1351static void shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c);
1352# endif
1353 1346
1354bool 1347bool
1355rxvt_term::bg_render () 1348rxvt_term::bg_render ()
1356{ 1349{
1357 unsigned long tr_flags = 0; 1350 unsigned long tr_flags = 0;
1362 { 1355 {
1363 /* we need to re-generate transparency pixmap in that case ! */ 1356 /* we need to re-generate transparency pixmap in that case ! */
1364 tr_flags = make_transparency_pixmap (); 1357 tr_flags = make_transparency_pixmap ();
1365 if (tr_flags == 0) 1358 if (tr_flags == 0)
1366 return false; 1359 return false;
1367 else if (!(tr_flags & BG_EFFECTS_FLAGS))
1368 bg_flags |= BG_IS_VALID; 1360 bg_flags |= BG_IS_VALID;
1369 } 1361 }
1370# endif 1362# endif
1371 1363
1372# ifdef BG_IMAGE_FROM_FILE 1364# ifdef BG_IMAGE_FROM_FILE
1373 if ((bg_flags & BG_IS_FROM_FILE) 1365 if ((bg_flags & BG_IS_FROM_FILE)
1374 || (tr_flags & BG_EFFECTS_FLAGS)) 1366 || (tr_flags & BG_EFFECTS_FLAGS))
1375 { 1367 {
1376 if (render_image (tr_flags)) 1368 if (render_image (tr_flags))
1377 bg_flags |= BG_IS_VALID; 1369 bg_flags |= BG_IS_VALID;
1378 }
1379# endif
1380
1381# if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1382 XImage *result = NULL;
1383
1384 if (tr_flags && !(bg_flags & BG_IS_VALID))
1385 {
1386 result = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1387 }
1388
1389 if (result)
1390 {
1391 /* our own client-side tinting */
1392 if (tr_flags & BG_NEEDS_TINT)
1393 {
1394 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
1395 if (bg_flags & BG_TINT_SET)
1396 tint.get (c);
1397 shade_ximage (DefaultVisual (dpy, display->screen), result, shade, c);
1398 }
1399
1400 GC gc = XCreateGC (dpy, vt, 0UL, NULL);
1401
1402 if (gc)
1403 {
1404 XPutImage (dpy, bg_pixmap, gc, result, 0, 0, 0, 0, result->width, result->height);
1405
1406 XFreeGC (dpy, gc);
1407 bg_flags |= BG_IS_VALID;
1408 }
1409
1410 XDestroyImage (result);
1411 } 1370 }
1412# endif 1371# endif
1413 1372
1414 if (!(bg_flags & BG_IS_VALID)) 1373 if (!(bg_flags & BG_IS_VALID))
1415 { 1374 {
1453} 1412}
1454 1413
1455#endif /* HAVE_BG_PIXMAP */ 1414#endif /* HAVE_BG_PIXMAP */
1456 1415
1457#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) 1416#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1458/* taken from aterm-0.4.2 */ 1417/* based on code from aterm-0.4.2 */
1459 1418
1460static void 1419static inline void
1461shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c) 1420fill_lut (uint32_t *lookup, uint32_t mask, int sh, unsigned short low, unsigned short high)
1421{
1422 for (int i = 0; i <= mask >> sh; i++)
1423 {
1424 uint32_t tmp;
1425 tmp = i * high;
1426 tmp += (mask >> sh) * low;
1427 lookup[i] = (tmp / 0xffff) << sh;
1428 }
1429}
1430
1431void
1432rxvt_term::tint_ximage (Visual *visual, XImage *ximage)
1462{ 1433{
1463 int sh_r, sh_g, sh_b; 1434 int sh_r, sh_g, sh_b;
1464 uint32_t mask_r, mask_g, mask_b; 1435 uint32_t mask_r, mask_g, mask_b;
1465 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; 1436 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b;
1466 rgba low; 1437 unsigned short low;
1467 rgba high;
1468 int i;
1469 int host_byte_order = byteorder::big_endian () ? MSBFirst : LSBFirst; 1438 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
1470 1439
1471 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return; 1440 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return;
1472 1441
1473 /* for convenience */ 1442 /* for convenience */
1474 mask_r = visual->red_mask; 1443 mask_r = visual->red_mask;
1532 break; 1501 break;
1533 default: 1502 default:
1534 return; /* we do not support this color depth */ 1503 return; /* we do not support this color depth */
1535 } 1504 }
1536 1505
1506 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1507
1508 if (bg_flags & BG_TINT_SET)
1509 tint.get (c);
1510
1537 /* prepare limits for color transformation (each channel is handled separately) */ 1511 /* prepare limits for color transformation (each channel is handled separately) */
1538 if (shade > 100) 1512 if (shade > 100)
1539 { 1513 {
1540 shade = 200 - shade;
1541
1542 high.r = c.r * shade / 100;
1543 high.g = c.g * shade / 100;
1544 high.b = c.b * shade / 100;
1545
1546 low.r = 65535 * (100 - shade) / 100; 1514 c.r = c.r * (200 - shade) / 100;
1547 low.g = 65535 * (100 - shade) / 100; 1515 c.g = c.g * (200 - shade) / 100;
1548 low.b = 65535 * (100 - shade) / 100; 1516 c.b = c.b * (200 - shade) / 100;
1517
1518 low = 0xffff * (shade - 100) / 100;
1549 } 1519 }
1550 else 1520 else
1551 { 1521 {
1552 high.r = c.r * shade / 100; 1522 c.r = c.r * shade / 100;
1553 high.g = c.g * shade / 100; 1523 c.g = c.g * shade / 100;
1554 high.b = c.b * shade / 100; 1524 c.b = c.b * shade / 100;
1555 1525
1556 low.r = low.g = low.b = 0; 1526 low = 0;
1557 } 1527 }
1558 1528
1559 /* fill our lookup tables */ 1529 /* fill our lookup tables */
1560 for (i = 0; i <= mask_r>>sh_r; i++) 1530 fill_lut (lookup_r, mask_r, sh_r, low, c.r);
1561 { 1531 fill_lut (lookup_g, mask_g, sh_g, low, c.g);
1562 uint32_t tmp; 1532 fill_lut (lookup_b, mask_b, sh_b, low, c.b);
1563 tmp = i * high.r;
1564 tmp += (mask_r>>sh_r) * low.r;
1565 lookup_r[i] = (tmp/65535)<<sh_r;
1566 }
1567 for (i = 0; i <= mask_g>>sh_g; i++)
1568 {
1569 uint32_t tmp;
1570 tmp = i * high.g;
1571 tmp += (mask_g>>sh_g) * low.g;
1572 lookup_g[i] = (tmp/65535)<<sh_g;
1573 }
1574 for (i = 0; i <= mask_b>>sh_b; i++)
1575 {
1576 uint32_t tmp;
1577 tmp = i * high.b;
1578 tmp += (mask_b>>sh_b) * low.b;
1579 lookup_b[i] = (tmp/65535)<<sh_b;
1580 }
1581 1533
1582 /* apply table to input image (replacing colors by newly calculated ones) */ 1534 /* apply table to input image (replacing colors by newly calculated ones) */
1583 if (ximage->bits_per_pixel == 32 1535 if (ximage->bits_per_pixel == 32
1584 && (ximage->depth == 24 || ximage->depth == 32) 1536 && (ximage->depth == 24 || ximage->depth == 32)
1585 && ximage->byte_order == host_byte_order) 1537 && ximage->byte_order == host_byte_order)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines