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.160 by sf-exg, Thu Aug 11 08:37:17 2011 UTC vs.
Revision 1.197 by sf-exg, Wed Jan 11 13:22:01 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/* 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 */
52 40
53#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
54void 60void
55rxvt_term::bg_destroy () 61rxvt_term::bg_destroy ()
56{ 62{
57#ifdef HAVE_AFTERIMAGE 63#ifdef HAVE_AFTERIMAGE
58 if (original_asim) 64 if (original_asim)
166 int smaller = min (image_size, window_size); 172 int smaller = min (image_size, window_size);
167 173
168 if (align >= 0 && align <= 100) 174 if (align >= 0 && align <= 100)
169 return diff * align / 100; 175 return diff * align / 100;
170 else if (align > 100 && align <= 200) 176 else if (align > 100 && align <= 200)
171 return ((align - 100) * smaller / 100) + window_size - smaller; 177 return (align - 100) * smaller / 100 + window_size - smaller;
172 else if (align >= -100 && align < 0) 178 else if (align >= -100 && align < 0)
173 return ((align + 100) * smaller / 100) - image_size; 179 return (align + 100) * smaller / 100 - image_size;
174 return 0; 180 return 0;
175} 181}
176 182
177static inline int 183static inline int
178make_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)
185 src_pos = -pos; 191 src_pos = -pos;
186 dst_pos = 0; 192 dst_pos = 0;
187 dst_size += pos; 193 dst_size += pos;
188 } 194 }
189 195
190 if (dst_pos + dst_size > target_size)
191 dst_size = target_size - dst_pos; 196 min_it (dst_size, target_size - dst_pos);
192 return src_pos; 197 return src_pos;
193} 198}
194 199
195bool 200bool
196rxvt_term::bg_set_geometry (const char *geom, bool update) 201rxvt_term::bg_set_geometry (const char *geom, bool update)
197{ 202{
198 bool changed = false; 203 bool changed = false;
199 int geom_flags = 0; 204 int geom_flags = 0;
200 int x = 0, y = 0; 205 int x = 0, y = 0;
201 unsigned int w = 0, h = 0; 206 unsigned int w = 0, h = 0;
202 unsigned int n; 207 unsigned long new_flags = 0;
203 unsigned long new_flags = (bg_flags & (~BG_GEOMETRY_FLAGS));
204 const char *ops;
205 208
206 if (geom == NULL) 209 if (geom == NULL)
207 return false; 210 return false;
208 211
209 char str[256]; 212 if (geom[0])
210
211 ops = strchr (geom, ':');
212 if (ops == NULL)
213 n = strlen (geom);
214 else
215 n = ops - geom;
216
217 if (n >= sizeof (str))
218 return false;
219
220 memcpy (str, geom, n);
221 str[n] = '\0';
222 rxvt_strtrim (str);
223
224 if (str[0])
225 { 213 {
226 /* 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
227 geom_flags = XParseGeometry (str, &x, &y, &w, &h); 304 geom_flags |= XParseGeometry (arr[i], &x, &y, &w, &h);
228 } /* done parsing geometry string */ 305 } /* done parsing ops */
306
307 rxvt_free_strsplit (arr);
308 }
309
310 new_flags |= bg_flags & ~BG_GEOMETRY_FLAGS;
229 311
230 if (!update) 312 if (!update)
231 { 313 {
232 if (!(geom_flags & XValue)) 314 if (!(geom_flags & XValue))
233 x = y = defaultAlign; 315 x = y = defaultAlign;
242 w = h; 324 w = h;
243 325
244 geom_flags |= WidthValue|HeightValue|XValue|YValue; 326 geom_flags |= WidthValue|HeightValue|XValue|YValue;
245 } 327 }
246 328
247 if (ops)
248 {
249 char **arr = rxvt_strsplit (':', ops + 1);
250
251 for (int i = 0; arr[i]; i++)
252 {
253 if (!strcasecmp (arr[i], "style=tiled"))
254 {
255 new_flags = BG_TILE;
256 w = h = noScale;
257 x = y = 0;
258 geom_flags = WidthValue|HeightValue|XValue|YValue;
259 }
260 else if (!strcasecmp (arr[i], "style=aspect-stretched"))
261 {
262 new_flags = BG_PROP_SCALE;
263 x = y = centerAlign;
264 geom_flags = XValue|YValue;
265 }
266 else if (!strcasecmp (arr[i], "style=stretched"))
267 {
268 new_flags = 0;
269 w = h = windowScale;
270 geom_flags = WidthValue|HeightValue;
271 }
272 else if (!strcasecmp (arr[i], "style=centered"))
273 {
274 new_flags = 0;
275 w = h = noScale;
276 x = y = centerAlign;
277 geom_flags = WidthValue|HeightValue|XValue|YValue;
278 }
279 else if (!strcasecmp (arr[i], "style=root-tiled"))
280 {
281 new_flags = BG_TILE|BG_ROOT_ALIGN;
282 w = h = noScale;
283 geom_flags = WidthValue|HeightValue;
284 }
285 else if (!strcasecmp (arr[i], "op=tile"))
286 new_flags |= BG_TILE;
287 else if (!strcasecmp (arr[i], "op=pscale"))
288 new_flags |= BG_PROP_SCALE;
289 else if (!strcasecmp (arr[i], "op=root"))
290 new_flags |= BG_ROOT_ALIGN;
291
292 // deprecated
293 else if (!strcasecmp (arr[i], "tile"))
294 {
295 new_flags |= BG_TILE;
296 w = h = noScale;
297 geom_flags |= WidthValue|HeightValue;
298 }
299 else if (!strcasecmp (arr[i], "propscale"))
300 {
301 new_flags |= BG_PROP_SCALE;
302 }
303 else if (!strcasecmp (arr[i], "scale"))
304 {
305 if (h == 0) h = windowScale;
306 if (w == 0) w = windowScale;
307
308 geom_flags |= WidthValue|HeightValue;
309 }
310 else if (!strcasecmp (arr[i], "root"))
311 {
312 new_flags |= BG_TILE|BG_ROOT_ALIGN;
313 w = h = noScale;
314 geom_flags |= WidthValue|HeightValue;
315 }
316 } /* done parsing ops */
317
318 rxvt_free_strsplit (arr);
319 }
320
321 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;
322 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;
323 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;
324 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;
325 333
336rxvt_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)
337{ 345{
338 int target_width = szHint.width; 346 int target_width = szHint.width;
339 int target_height = szHint.height; 347 int target_height = szHint.height;
340 348
349 w = h_scale * target_width / 100;
350 h = v_scale * target_height / 100;
351
341 if (bg_flags & BG_PROP_SCALE) 352 if (bg_flags & BG_KEEP_ASPECT)
342 { 353 {
343 float scale = (float)target_width / image_width; 354 float scale = (float)w / image_width;
344 min_it (scale, (float)target_height / image_height); 355 min_it (scale, (float)h / image_height);
345 w = image_width * scale + 0.5; 356 w = image_width * scale + 0.5;
346 h = image_height * scale + 0.5; 357 h = image_height * scale + 0.5;
347 } 358 }
348 else
349 {
350 w = h_scale * target_width / 100;
351 h = v_scale * target_height / 100;
352 }
353 359
354 if (!w) w = image_width; 360 if (!w) w = image_width;
355 if (!h) h = image_height; 361 if (!h) h = image_height;
356 362
357 if (bg_flags & BG_ROOT_ALIGN) 363 if (bg_flags & BG_ROOT_ALIGN)
365 y = make_align_position (v_align, target_height, h); 371 y = make_align_position (v_align, target_height, h);
366 } 372 }
367 373
368 bg_flags &= ~BG_IS_SIZE_SENSITIVE; 374 bg_flags &= ~BG_IS_SIZE_SENSITIVE;
369 if (!(bg_flags & BG_TILE) 375 if (!(bg_flags & BG_TILE)
370 || (bg_flags & BG_PROP_SCALE) || h_scale || v_scale 376 || h_scale || v_scale
371 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align)) 377 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align))
372 || w > target_width || h > target_height) 378 || w > target_width || h > target_height)
373 bg_flags |= BG_IS_SIZE_SENSITIVE; 379 bg_flags |= BG_IS_SIZE_SENSITIVE;
374} 380}
375 381
402 } 408 }
403 409
404 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL) 410 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL)
405 { 411 {
406 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,
407 (original_asim == NULL || tint == TINT_LEAVE_SAME) ? ASA_XImage : ASA_ASImage, 413 ASA_XImage,
408 100, ASIMAGE_QUALITY_DEFAULT); 414 100, ASIMAGE_QUALITY_DEFAULT);
409 if (tmp) 415 if (tmp)
410 { 416 {
411 destroy_asimage (&background); 417 destroy_asimage (&background);
412 background = tmp; 418 background = tmp;
431 437
432 if (!original_asim 438 if (!original_asim
433 || (!(bg_flags & BG_ROOT_ALIGN) 439 || (!(bg_flags & BG_ROOT_ALIGN)
434 && (x >= target_width 440 && (x >= target_width
435 || y >= target_height 441 || y >= target_height
436 || (x + w <= 0) 442 || x + w <= 0
437 || (y + h <= 0)))) 443 || y + h <= 0)))
438 { 444 {
439 if (background) 445 if (background)
440 { 446 {
441 new_pmap_width = background->width; 447 new_pmap_width = background->width;
442 new_pmap_height = background->height; 448 new_pmap_height = background->height;
456 } 462 }
457 else 463 else
458 { 464 {
459 result = original_asim; 465 result = original_asim;
460 466
461 if ((w != original_asim->width) 467 if (w != original_asim->width
462 || (h != original_asim->height)) 468 || h != original_asim->height)
463 { 469 {
464 result = scale_asimage (asv, original_asim, 470 result = scale_asimage (asv, original_asim,
465 w, h, 471 w, h,
466 background ? ASA_ASImage : ASA_XImage, 472 ASA_XImage,
467 100, ASIMAGE_QUALITY_DEFAULT); 473 100, ASIMAGE_QUALITY_DEFAULT);
468 } 474 }
469 475
470 if (background == NULL) 476 if (background == NULL)
471 { 477 {
721 get_image_geometry (image_width, image_height, w, h, x, y); 727 get_image_geometry (image_width, image_height, w, h, x, y);
722 728
723 if (!(bg_flags & BG_ROOT_ALIGN) 729 if (!(bg_flags & BG_ROOT_ALIGN)
724 && (x >= target_width 730 && (x >= target_width
725 || y >= target_height 731 || y >= target_height
726 || (x + w <= 0) 732 || x + w <= 0
727 || (y + h <= 0))) 733 || y + h <= 0))
728 return false; 734 return false;
729 735
730 result = pixbuf; 736 result = pixbuf;
731 737
732 if ((w != image_width) 738 if (w != image_width
733 || (h != image_height)) 739 || h != image_height)
734 { 740 {
735 result = gdk_pixbuf_scale_simple (pixbuf, 741 result = gdk_pixbuf_scale_simple (pixbuf,
736 w, h, 742 w, h,
737 GDK_INTERP_BILINEAR); 743 GDK_INTERP_BILINEAR);
738 } 744 }
817 } 823 }
818 824
819#if XRENDER 825#if XRENDER
820 if (tr_flags) 826 if (tr_flags)
821 { 827 {
822 XRenderPictureAttributes pa;
823
824 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, visual); 828 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
829
825 Picture src = XRenderCreatePicture (dpy, root_pmap, src_format, 0, &pa); 830 Picture src = XRenderCreatePicture (dpy, root_pmap, format, 0, 0);
826 831
827 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
828 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, dst_format, 0, &pa); 832 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, format, 0, 0);
829 833
830 pa.repeat = True; 834 Picture mask = create_xrender_mask (dpy, vt, False, False);
831 Pixmap mask_pmap = XCreatePixmap (dpy, vt, 1, 1, 8);
832 XRenderPictFormat *mask_format = XRenderFindStandardFormat (dpy, PictStandardA8);
833 Picture mask = XRenderCreatePicture (dpy, mask_pmap, mask_format, CPRepeat, &pa);
834 XFreePixmap (dpy, mask_pmap);
835 835
836 XRenderColor mask_c; 836 XRenderColor mask_c;
837 837
838 mask_c.alpha = 0x8000; 838 mask_c.alpha = 0x8000;
839 mask_c.red = 0; 839 mask_c.red =
840 mask_c.green = 0; 840 mask_c.green =
841 mask_c.blue = 0; 841 mask_c.blue = 0;
842 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); 842 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
843
843 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);
844 845
845 XRenderFreePicture (dpy, src); 846 XRenderFreePicture (dpy, src);
846 XRenderFreePicture (dpy, dst); 847 XRenderFreePicture (dpy, dst);
847 XRenderFreePicture (dpy, mask); 848 XRenderFreePicture (dpy, mask);
867rxvt_term::bg_set_file (const char *file) 868rxvt_term::bg_set_file (const char *file)
868{ 869{
869 if (!file || !*file) 870 if (!file || !*file)
870 return false; 871 return false;
871 872
873 bool ret = false;
872 if (const char *p = strchr (file, ';')) 874 const char *p = strchr (file, ';');
875
876 if (p)
873 { 877 {
874 size_t len = p - file; 878 size_t len = p - file;
875 char *f = rxvt_temp_buf<char> (len + 1); 879 char *f = rxvt_temp_buf<char> (len + 1);
876 memcpy (f, file, len); 880 memcpy (f, file, len);
877 f[len] = '\0'; 881 f[len] = '\0';
886 { 890 {
887 if (original_asim) 891 if (original_asim)
888 safe_asimage_destroy (original_asim); 892 safe_asimage_destroy (original_asim);
889 original_asim = image; 893 original_asim = image;
890 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER; 894 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER;
891 return true; 895 ret = true;
892 } 896 }
893# endif 897# endif
894 898
895# ifdef HAVE_PIXBUF 899# ifdef HAVE_PIXBUF
896 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL); 900 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL);
898 { 902 {
899 if (pixbuf) 903 if (pixbuf)
900 g_object_unref (pixbuf); 904 g_object_unref (pixbuf);
901 pixbuf = image; 905 pixbuf = image;
902 bg_flags |= BG_IS_FROM_FILE; 906 bg_flags |= BG_IS_FROM_FILE;
903 return true; 907 ret = true;
904 } 908 }
905# endif 909# endif
906 910
911 if (ret)
912 {
913 if (p)
914 bg_set_geometry (p + 1);
915 else
916 bg_set_default_geometry ();
917 }
918
907 return false; 919 return ret;
908} 920}
909 921
910# endif /* BG_IMAGE_FROM_FILE */ 922# endif /* BG_IMAGE_FROM_FILE */
911 923
912# ifdef ENABLE_TRANSPARENCY 924# ifdef ENABLE_TRANSPARENCY
948 { 960 {
949 changed = true; 961 changed = true;
950 v_blurRadius = vr; 962 v_blurRadius = vr;
951 } 963 }
952 964
953 if (v_blurRadius == 0 && h_blurRadius == 0) 965 if (h_blurRadius == 0 || v_blurRadius == 0)
954 bg_flags &= ~BG_NEEDS_BLUR; 966 bg_flags &= ~BG_NEEDS_BLUR;
955 else 967 else
956 bg_flags |= BG_NEEDS_BLUR; 968 bg_flags |= BG_NEEDS_BLUR;
957 969
958 return changed; 970 return changed;
959} 971}
960 972
961void 973void
962rxvt_term::set_tint_shade_flags () 974rxvt_term::set_tint_shade_flags ()
963{ 975{
964 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); 976 rgba c;
965 bool has_shade = shade != 100; 977 bool has_shade = shade != 100;
966 978
967 bg_flags &= ~BG_TINT_FLAGS; 979 bg_flags &= ~BG_TINT_FLAGS;
968 980
969 if (bg_flags & BG_TINT_SET) 981 if (bg_flags & BG_TINT_SET)
995} 1007}
996 1008
997bool 1009bool
998rxvt_term::bg_set_shade (const char *shade_str) 1010rxvt_term::bg_set_shade (const char *shade_str)
999{ 1011{
1000 int new_shade = (shade_str) ? atoi (shade_str) : 100; 1012 int new_shade = atoi (shade_str);
1001 1013
1002 clamp_it (new_shade, -100, 200); 1014 clamp_it (new_shade, -100, 200);
1003 if (new_shade < 0) 1015 if (new_shade < 0)
1004 new_shade = 200 - (100 + new_shade); 1016 new_shade = 200 - (100 + new_shade);
1005 1017
1035 params[i+2] = XDoubleToFixed (kernel[i] / sum); 1047 params[i+2] = XDoubleToFixed (kernel[i] / sum);
1036} 1048}
1037#endif 1049#endif
1038 1050
1039bool 1051bool
1040rxvt_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)
1041{ 1053{
1042 bool ret = false; 1054 bool ret = false;
1043#if XRENDER 1055#if XRENDER
1056 if (!(bg_flags & BG_HAS_RENDER_CONV))
1057 return false;
1058
1044 int size = max (h_blurRadius, v_blurRadius) * 2 + 1; 1059 int size = max (h_blurRadius, v_blurRadius) * 2 + 1;
1045 double *kernel = (double *)malloc (size * sizeof (double)); 1060 double *kernel = (double *)malloc (size * sizeof (double));
1046 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 1061 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
1047 1062
1048 XRenderPictureAttributes pa; 1063 XRenderPictureAttributes pa;
1049 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1064 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1050 1065
1066 pa.repeat = RepeatPad;
1051 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);
1052 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1069 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa);
1070 XFreePixmap (dpy, tmp);
1053 1071
1054 if (kernel && params) 1072 if (kernel && params)
1055 { 1073 {
1056 if (h_blurRadius)
1057 {
1058 size = h_blurRadius * 2 + 1; 1074 size = h_blurRadius * 2 + 1;
1059 get_gaussian_kernel (h_blurRadius, size, kernel, params); 1075 get_gaussian_kernel (h_blurRadius, size, kernel, params);
1060 1076
1061 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1077 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1062 XRenderComposite (dpy, 1078 XRenderComposite (dpy,
1063 PictOpSrc, 1079 PictOpSrc,
1064 src, 1080 src,
1065 None, 1081 None,
1066 dst, 1082 dst,
1067 0, 0, 1083 0, 0,
1068 0, 0, 1084 0, 0,
1069 0, 0, 1085 0, 0,
1070 width, height); 1086 width, height);
1071 }
1072 1087
1073 if (v_blurRadius) 1088 ::swap (src, dst);
1074 { 1089
1075 size = v_blurRadius * 2 + 1; 1090 size = v_blurRadius * 2 + 1;
1076 get_gaussian_kernel (v_blurRadius, size, kernel, params); 1091 get_gaussian_kernel (v_blurRadius, size, kernel, params);
1077 ::swap (params[0], params[1]); 1092 ::swap (params[0], params[1]);
1078 1093
1079 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1094 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1080 XRenderComposite (dpy, 1095 XRenderComposite (dpy,
1081 PictOpSrc, 1096 PictOpSrc,
1082 src, 1097 src,
1083 None, 1098 None,
1084 dst, 1099 dst,
1085 0, 0, 1100 0, 0,
1086 0, 0, 1101 0, 0,
1087 0, 0, 1102 0, 0,
1088 width, height); 1103 width, height);
1089 }
1090 1104
1091 ret = true; 1105 ret = true;
1092 } 1106 }
1093 1107
1094 free (kernel); 1108 free (kernel);
1121 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height); 1135 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height);
1122 ret = true; 1136 ret = true;
1123 XFreeGC (dpy, gc); 1137 XFreeGC (dpy, gc);
1124 } 1138 }
1125 } 1139 }
1126 else
1127 {
1128# if XRENDER 1140# if XRENDER
1141 else if (bg_flags & BG_HAS_RENDER)
1142 {
1129 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); 1143 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1130 1144
1131 if (bg_flags & BG_TINT_SET) 1145 if (bg_flags & BG_TINT_SET)
1132 tint.get (c); 1146 tint.get (c);
1133 1147
1142 c.r = c.r * (200 - shade) / 100; 1156 c.r = c.r * (200 - shade) / 100;
1143 c.g = c.g * (200 - shade) / 100; 1157 c.g = c.g * (200 - shade) / 100;
1144 c.b = c.b * (200 - shade) / 100; 1158 c.b = c.b * (200 - shade) / 100;
1145 } 1159 }
1146 1160
1147 XRenderPictFormat *solid_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
1148 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1161 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1149 XRenderPictureAttributes pa;
1150 1162
1151 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1163 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1152 1164
1153 pa.repeat = True; 1165 Picture overlay_pic = create_xrender_mask (dpy, pixmap, True, False);
1154 1166
1155 Pixmap overlay_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32); 1167 Picture mask_pic = create_xrender_mask (dpy, pixmap, True, True);
1156 Picture overlay_pic = XRenderCreatePicture (dpy, overlay_pmap, solid_format, CPRepeat, &pa);
1157 XFreePixmap (dpy, overlay_pmap);
1158
1159 pa.component_alpha = True;
1160 Pixmap mask_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32);
1161 Picture mask_pic = XRenderCreatePicture (dpy, mask_pmap, solid_format, CPRepeat | CPComponentAlpha, &pa);
1162 XFreePixmap (dpy, mask_pmap);
1163 1168
1164 XRenderColor mask_c; 1169 XRenderColor mask_c;
1165 1170
1166 mask_c.alpha = 0xffff; 1171 mask_c.alpha = 0xffff;
1167 mask_c.red = 1172 mask_c.red =
1172 mask_c.alpha = 0; 1177 mask_c.alpha = 0;
1173 mask_c.red = 0xffff - c.r; 1178 mask_c.red = 0xffff - c.r;
1174 mask_c.green = 0xffff - c.g; 1179 mask_c.green = 0xffff - c.g;
1175 mask_c.blue = 0xffff - c.b; 1180 mask_c.blue = 0xffff - c.b;
1176 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); 1181 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
1182
1177 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height); 1183 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1178 1184
1179 if (shade > 100) 1185 if (shade > 100)
1180 { 1186 {
1181 mask_c.red = mask_c.green = mask_c.blue = 0xffff * (shade - 100) / 100;
1182 mask_c.alpha = 0; 1187 mask_c.alpha = 0;
1188 mask_c.red =
1189 mask_c.green =
1190 mask_c.blue = 0xffff * (shade - 100) / 100;
1183 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); 1191 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1184 1192
1185 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);
1186 } 1194 }
1187 1195
1188 ret = true; 1196 ret = true;
1189 1197
1190 XRenderFreePicture (dpy, mask_pic); 1198 XRenderFreePicture (dpy, mask_pic);
1191 XRenderFreePicture (dpy, overlay_pic); 1199 XRenderFreePicture (dpy, overlay_pic);
1192 XRenderFreePicture (dpy, back_pic); 1200 XRenderFreePicture (dpy, back_pic);
1201 }
1193# endif 1202# endif
1194 }
1195 1203
1196 return ret; 1204 return ret;
1197} 1205}
1198 1206
1199/* 1207/*
1250#if XRENDER 1258#if XRENDER
1251 if (bg_flags & BG_HAS_RENDER) 1259 if (bg_flags & BG_HAS_RENDER)
1252 { 1260 {
1253 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth); 1261 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth);
1254 1262
1255 XRenderPictureAttributes pa;
1256
1257 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen)); 1263 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
1258 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, &pa); 1264 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, 0);
1259 1265
1260 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual); 1266 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
1261 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, &pa); 1267 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, 0);
1262 1268
1263 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);
1264 1270
1265 XRenderFreePicture (dpy, src); 1271 XRenderFreePicture (dpy, src);
1266 XRenderFreePicture (dpy, dst); 1272 XRenderFreePicture (dpy, dst);
1283 bg_pmap_width = window_width; 1289 bg_pmap_width = window_width;
1284 bg_pmap_height = window_height; 1290 bg_pmap_height = window_height;
1285 } 1291 }
1286 1292
1287 /* straightforward pixmap copy */ 1293 /* straightforward pixmap copy */
1288 while (sx < 0) sx += root_width; 1294 while (sx < 0) sx += root_pmap_width;
1289 while (sy < 0) sy += root_height; 1295 while (sy < 0) sy += root_pmap_height;
1290 1296
1291 gcv.tile = recoded_root_pmap; 1297 gcv.tile = recoded_root_pmap;
1292 gcv.fill_style = FillTiled; 1298 gcv.fill_style = FillTiled;
1293 gcv.ts_x_origin = -sx; 1299 gcv.ts_x_origin = -sx;
1294 gcv.ts_y_origin = -sy; 1300 gcv.ts_y_origin = -sy;
1296 1302
1297 if (gc) 1303 if (gc)
1298 { 1304 {
1299 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height); 1305 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height);
1300 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS); 1306 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS);
1301 XFreeGC (dpy, gc);
1302 1307
1303 if (!(bg_flags & BG_CLIENT_RENDER)) 1308 if (!(bg_flags & BG_CLIENT_RENDER))
1304 { 1309 {
1305 if ((bg_flags & BG_NEEDS_BLUR) 1310 if (bg_flags & BG_NEEDS_BLUR)
1306 && (bg_flags & BG_HAS_RENDER_CONV))
1307 { 1311 {
1308 if (blur_pixmap (bg_pixmap, visual, window_width, window_height)) 1312 if (blur_pixmap (bg_pixmap, visual, window_width, window_height, depth))
1309 result &= ~BG_NEEDS_BLUR; 1313 result &= ~BG_NEEDS_BLUR;
1310 } 1314 }
1311 if ((bg_flags & BG_NEEDS_TINT) 1315 if (bg_flags & BG_NEEDS_TINT)
1312 && (bg_flags & (BG_TINT_BITAND | BG_HAS_RENDER)))
1313 { 1316 {
1314 if (tint_pixmap (bg_pixmap, visual, window_width, window_height)) 1317 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1315 result &= ~BG_NEEDS_TINT; 1318 result &= ~BG_NEEDS_TINT;
1316 } 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
1317 } /* server side rendering completed */ 1334 } /* server side rendering completed */
1335
1336 XFreeGC (dpy, gc);
1318 } 1337 }
1319 1338
1320 if (recoded_root_pmap != root_pixmap) 1339 if (recoded_root_pmap != root_pixmap)
1321 XFreePixmap (dpy, recoded_root_pmap); 1340 XFreePixmap (dpy, recoded_root_pmap);
1322 1341
1331 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]); 1350 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]);
1332 1351
1333 root_pixmap = new_root_pixmap; 1352 root_pixmap = new_root_pixmap;
1334} 1353}
1335# endif /* ENABLE_TRANSPARENCY */ 1354# endif /* ENABLE_TRANSPARENCY */
1336
1337#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1338static void shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c);
1339# endif
1340 1355
1341bool 1356bool
1342rxvt_term::bg_render () 1357rxvt_term::bg_render ()
1343{ 1358{
1344 unsigned long tr_flags = 0; 1359 unsigned long tr_flags = 0;
1349 { 1364 {
1350 /* we need to re-generate transparency pixmap in that case ! */ 1365 /* we need to re-generate transparency pixmap in that case ! */
1351 tr_flags = make_transparency_pixmap (); 1366 tr_flags = make_transparency_pixmap ();
1352 if (tr_flags == 0) 1367 if (tr_flags == 0)
1353 return false; 1368 return false;
1354 else if (!(tr_flags & BG_EFFECTS_FLAGS))
1355 bg_flags |= BG_IS_VALID; 1369 bg_flags |= BG_IS_VALID;
1356 } 1370 }
1357# endif 1371# endif
1358 1372
1359# ifdef BG_IMAGE_FROM_FILE 1373# ifdef BG_IMAGE_FROM_FILE
1360 if ((bg_flags & BG_IS_FROM_FILE) 1374 if ((bg_flags & BG_IS_FROM_FILE)
1361 || (tr_flags & BG_EFFECTS_FLAGS)) 1375 || (tr_flags & BG_EFFECTS_FLAGS))
1362 { 1376 {
1363 if (render_image (tr_flags)) 1377 if (render_image (tr_flags))
1364 bg_flags |= BG_IS_VALID; 1378 bg_flags |= BG_IS_VALID;
1365 }
1366# endif
1367
1368# if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1369 XImage *result = NULL;
1370
1371 if (tr_flags && !(bg_flags & BG_IS_VALID))
1372 {
1373 result = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1374 }
1375
1376 if (result)
1377 {
1378 /* our own client-side tinting */
1379 if (tr_flags & BG_NEEDS_TINT)
1380 {
1381 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
1382 if (bg_flags & BG_TINT_SET)
1383 tint.get (c);
1384 shade_ximage (DefaultVisual (dpy, display->screen), result, shade, c);
1385 }
1386
1387 GC gc = XCreateGC (dpy, vt, 0UL, NULL);
1388
1389 if (gc)
1390 {
1391 XPutImage (dpy, bg_pixmap, gc, result, 0, 0, 0, 0, result->width, result->height);
1392
1393 XFreeGC (dpy, gc);
1394 bg_flags |= BG_IS_VALID;
1395 }
1396
1397 XDestroyImage (result);
1398 } 1379 }
1399# endif 1380# endif
1400 1381
1401 if (!(bg_flags & BG_IS_VALID)) 1382 if (!(bg_flags & BG_IS_VALID))
1402 { 1383 {
1440} 1421}
1441 1422
1442#endif /* HAVE_BG_PIXMAP */ 1423#endif /* HAVE_BG_PIXMAP */
1443 1424
1444#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) 1425#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1445/* taken from aterm-0.4.2 */ 1426/* based on code from aterm-0.4.2 */
1446 1427
1447static void 1428static inline void
1448shade_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)
1449{ 1442{
1450 int sh_r, sh_g, sh_b; 1443 int sh_r, sh_g, sh_b;
1451 uint32_t mask_r, mask_g, mask_b; 1444 uint32_t mask_r, mask_g, mask_b;
1452 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; 1445 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b;
1453 rgba low; 1446 unsigned short low;
1454 rgba high;
1455 int i;
1456 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst; 1447 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
1457 1448
1458 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return; 1449 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return;
1459 1450
1460 /* for convenience */ 1451 /* for convenience */
1519 break; 1510 break;
1520 default: 1511 default:
1521 return; /* we do not support this color depth */ 1512 return; /* we do not support this color depth */
1522 } 1513 }
1523 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
1524 /* prepare limits for color transformation (each channel is handled separately) */ 1520 /* prepare limits for color transformation (each channel is handled separately) */
1525 if (shade > 100) 1521 if (shade > 100)
1526 { 1522 {
1527 shade = 200 - shade;
1528
1529 high.r = c.r * shade / 100;
1530 high.g = c.g * shade / 100;
1531 high.b = c.b * shade / 100;
1532
1533 low.r = 65535 * (100 - shade) / 100; 1523 c.r = c.r * (200 - shade) / 100;
1534 low.g = 65535 * (100 - shade) / 100; 1524 c.g = c.g * (200 - shade) / 100;
1535 low.b = 65535 * (100 - shade) / 100; 1525 c.b = c.b * (200 - shade) / 100;
1526
1527 low = 0xffff * (shade - 100) / 100;
1536 } 1528 }
1537 else 1529 else
1538 { 1530 {
1539 high.r = c.r * shade / 100; 1531 c.r = c.r * shade / 100;
1540 high.g = c.g * shade / 100; 1532 c.g = c.g * shade / 100;
1541 high.b = c.b * shade / 100; 1533 c.b = c.b * shade / 100;
1542 1534
1543 low.r = low.g = low.b = 0; 1535 low = 0;
1544 } 1536 }
1545 1537
1546 /* fill our lookup tables */ 1538 /* fill our lookup tables */
1547 for (i = 0; i <= mask_r>>sh_r; i++) 1539 fill_lut (lookup_r, mask_r, sh_r, low, c.r);
1548 { 1540 fill_lut (lookup_g, mask_g, sh_g, low, c.g);
1549 uint32_t tmp; 1541 fill_lut (lookup_b, mask_b, sh_b, low, c.b);
1550 tmp = i * high.r;
1551 tmp += (mask_r>>sh_r) * low.r;
1552 lookup_r[i] = (tmp/65535)<<sh_r;
1553 }
1554 for (i = 0; i <= mask_g>>sh_g; i++)
1555 {
1556 uint32_t tmp;
1557 tmp = i * high.g;
1558 tmp += (mask_g>>sh_g) * low.g;
1559 lookup_g[i] = (tmp/65535)<<sh_g;
1560 }
1561 for (i = 0; i <= mask_b>>sh_b; i++)
1562 {
1563 uint32_t tmp;
1564 tmp = i * high.b;
1565 tmp += (mask_b>>sh_b) * low.b;
1566 lookup_b[i] = (tmp/65535)<<sh_b;
1567 }
1568 1542
1569 /* apply table to input image (replacing colors by newly calculated ones) */ 1543 /* apply table to input image (replacing colors by newly calculated ones) */
1570 if (ximage->bits_per_pixel == 32 1544 if (ximage->bits_per_pixel == 32
1571 && (ximage->depth == 24 || ximage->depth == 32) 1545 && (ximage->depth == 24 || ximage->depth == 32)
1572 && ximage->byte_order == host_byte_order) 1546 && ximage->byte_order == host_byte_order)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines