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.162 by sf-exg, Thu Aug 11 12:27:26 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], "hscale"))
304 {
305 new_flags |= BG_TILE;
306 w = windowScale;
307 h = noScale;
308 geom_flags |= WidthValue|HeightValue;
309 }
310 else if (!strcasecmp (arr[i], "vscale"))
311 {
312 new_flags |= BG_TILE;
313 h = windowScale;
314 w = noScale;
315 geom_flags |= WidthValue|HeightValue;
316 }
317 else if (!strcasecmp (arr[i], "scale"))
318 {
319 w = h = windowScale;
320 geom_flags |= WidthValue|HeightValue;
321 }
322 else if (!strcasecmp (arr[i], "auto"))
323 {
324 w = h = windowScale;
325 x = y = centerAlign;
326 geom_flags |= WidthValue|HeightValue|XValue|YValue;
327 }
328 else if (!strcasecmp (arr[i], "root"))
329 {
330 new_flags |= BG_TILE|BG_ROOT_ALIGN;
331 w = h = noScale;
332 geom_flags |= WidthValue|HeightValue;
333 }
334 } /* done parsing ops */
335
336 rxvt_free_strsplit (arr);
337 }
338
339 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;
340 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;
341 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;
342 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;
343 333
354rxvt_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)
355{ 345{
356 int target_width = szHint.width; 346 int target_width = szHint.width;
357 int target_height = szHint.height; 347 int target_height = szHint.height;
358 348
349 w = h_scale * target_width / 100;
350 h = v_scale * target_height / 100;
351
359 if (bg_flags & BG_PROP_SCALE) 352 if (bg_flags & BG_KEEP_ASPECT)
360 { 353 {
361 float scale = (float)target_width / image_width; 354 float scale = (float)w / image_width;
362 min_it (scale, (float)target_height / image_height); 355 min_it (scale, (float)h / image_height);
363 w = image_width * scale + 0.5; 356 w = image_width * scale + 0.5;
364 h = image_height * scale + 0.5; 357 h = image_height * scale + 0.5;
365 } 358 }
366 else
367 {
368 w = h_scale * target_width / 100;
369 h = v_scale * target_height / 100;
370 }
371 359
372 if (!w) w = image_width; 360 if (!w) w = image_width;
373 if (!h) h = image_height; 361 if (!h) h = image_height;
374 362
375 if (bg_flags & BG_ROOT_ALIGN) 363 if (bg_flags & BG_ROOT_ALIGN)
383 y = make_align_position (v_align, target_height, h); 371 y = make_align_position (v_align, target_height, h);
384 } 372 }
385 373
386 bg_flags &= ~BG_IS_SIZE_SENSITIVE; 374 bg_flags &= ~BG_IS_SIZE_SENSITIVE;
387 if (!(bg_flags & BG_TILE) 375 if (!(bg_flags & BG_TILE)
388 || (bg_flags & BG_PROP_SCALE) || h_scale || v_scale 376 || h_scale || v_scale
389 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align)) 377 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align))
390 || w > target_width || h > target_height) 378 || w > target_width || h > target_height)
391 bg_flags |= BG_IS_SIZE_SENSITIVE; 379 bg_flags |= BG_IS_SIZE_SENSITIVE;
392} 380}
393 381
420 } 408 }
421 409
422 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL) 410 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL)
423 { 411 {
424 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,
425 (original_asim == NULL || tint == TINT_LEAVE_SAME) ? ASA_XImage : ASA_ASImage, 413 ASA_XImage,
426 100, ASIMAGE_QUALITY_DEFAULT); 414 100, ASIMAGE_QUALITY_DEFAULT);
427 if (tmp) 415 if (tmp)
428 { 416 {
429 destroy_asimage (&background); 417 destroy_asimage (&background);
430 background = tmp; 418 background = tmp;
449 437
450 if (!original_asim 438 if (!original_asim
451 || (!(bg_flags & BG_ROOT_ALIGN) 439 || (!(bg_flags & BG_ROOT_ALIGN)
452 && (x >= target_width 440 && (x >= target_width
453 || y >= target_height 441 || y >= target_height
454 || (x + w <= 0) 442 || x + w <= 0
455 || (y + h <= 0)))) 443 || y + h <= 0)))
456 { 444 {
457 if (background) 445 if (background)
458 { 446 {
459 new_pmap_width = background->width; 447 new_pmap_width = background->width;
460 new_pmap_height = background->height; 448 new_pmap_height = background->height;
474 } 462 }
475 else 463 else
476 { 464 {
477 result = original_asim; 465 result = original_asim;
478 466
479 if ((w != original_asim->width) 467 if (w != original_asim->width
480 || (h != original_asim->height)) 468 || h != original_asim->height)
481 { 469 {
482 result = scale_asimage (asv, original_asim, 470 result = scale_asimage (asv, original_asim,
483 w, h, 471 w, h,
484 background ? ASA_ASImage : ASA_XImage, 472 ASA_XImage,
485 100, ASIMAGE_QUALITY_DEFAULT); 473 100, ASIMAGE_QUALITY_DEFAULT);
486 } 474 }
487 475
488 if (background == NULL) 476 if (background == NULL)
489 { 477 {
739 get_image_geometry (image_width, image_height, w, h, x, y); 727 get_image_geometry (image_width, image_height, w, h, x, y);
740 728
741 if (!(bg_flags & BG_ROOT_ALIGN) 729 if (!(bg_flags & BG_ROOT_ALIGN)
742 && (x >= target_width 730 && (x >= target_width
743 || y >= target_height 731 || y >= target_height
744 || (x + w <= 0) 732 || x + w <= 0
745 || (y + h <= 0))) 733 || y + h <= 0))
746 return false; 734 return false;
747 735
748 result = pixbuf; 736 result = pixbuf;
749 737
750 if ((w != image_width) 738 if (w != image_width
751 || (h != image_height)) 739 || h != image_height)
752 { 740 {
753 result = gdk_pixbuf_scale_simple (pixbuf, 741 result = gdk_pixbuf_scale_simple (pixbuf,
754 w, h, 742 w, h,
755 GDK_INTERP_BILINEAR); 743 GDK_INTERP_BILINEAR);
756 } 744 }
835 } 823 }
836 824
837#if XRENDER 825#if XRENDER
838 if (tr_flags) 826 if (tr_flags)
839 { 827 {
840 XRenderPictureAttributes pa;
841
842 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, visual); 828 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
829
843 Picture src = XRenderCreatePicture (dpy, root_pmap, src_format, 0, &pa); 830 Picture src = XRenderCreatePicture (dpy, root_pmap, format, 0, 0);
844 831
845 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
846 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, dst_format, 0, &pa); 832 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, format, 0, 0);
847 833
848 pa.repeat = True; 834 Picture mask = create_xrender_mask (dpy, vt, False, False);
849 Pixmap mask_pmap = XCreatePixmap (dpy, vt, 1, 1, 8);
850 XRenderPictFormat *mask_format = XRenderFindStandardFormat (dpy, PictStandardA8);
851 Picture mask = XRenderCreatePicture (dpy, mask_pmap, mask_format, CPRepeat, &pa);
852 XFreePixmap (dpy, mask_pmap);
853 835
854 XRenderColor mask_c; 836 XRenderColor mask_c;
855 837
856 mask_c.alpha = 0x8000; 838 mask_c.alpha = 0x8000;
857 mask_c.red = 0; 839 mask_c.red =
858 mask_c.green = 0; 840 mask_c.green =
859 mask_c.blue = 0; 841 mask_c.blue = 0;
860 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); 842 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
843
861 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);
862 845
863 XRenderFreePicture (dpy, src); 846 XRenderFreePicture (dpy, src);
864 XRenderFreePicture (dpy, dst); 847 XRenderFreePicture (dpy, dst);
865 XRenderFreePicture (dpy, mask); 848 XRenderFreePicture (dpy, mask);
885rxvt_term::bg_set_file (const char *file) 868rxvt_term::bg_set_file (const char *file)
886{ 869{
887 if (!file || !*file) 870 if (!file || !*file)
888 return false; 871 return false;
889 872
873 bool ret = false;
890 if (const char *p = strchr (file, ';')) 874 const char *p = strchr (file, ';');
875
876 if (p)
891 { 877 {
892 size_t len = p - file; 878 size_t len = p - file;
893 char *f = rxvt_temp_buf<char> (len + 1); 879 char *f = rxvt_temp_buf<char> (len + 1);
894 memcpy (f, file, len); 880 memcpy (f, file, len);
895 f[len] = '\0'; 881 f[len] = '\0';
904 { 890 {
905 if (original_asim) 891 if (original_asim)
906 safe_asimage_destroy (original_asim); 892 safe_asimage_destroy (original_asim);
907 original_asim = image; 893 original_asim = image;
908 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER; 894 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER;
909 return true; 895 ret = true;
910 } 896 }
911# endif 897# endif
912 898
913# ifdef HAVE_PIXBUF 899# ifdef HAVE_PIXBUF
914 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL); 900 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL);
916 { 902 {
917 if (pixbuf) 903 if (pixbuf)
918 g_object_unref (pixbuf); 904 g_object_unref (pixbuf);
919 pixbuf = image; 905 pixbuf = image;
920 bg_flags |= BG_IS_FROM_FILE; 906 bg_flags |= BG_IS_FROM_FILE;
921 return true; 907 ret = true;
922 } 908 }
923# endif 909# endif
924 910
911 if (ret)
912 {
913 if (p)
914 bg_set_geometry (p + 1);
915 else
916 bg_set_default_geometry ();
917 }
918
925 return false; 919 return ret;
926} 920}
927 921
928# endif /* BG_IMAGE_FROM_FILE */ 922# endif /* BG_IMAGE_FROM_FILE */
929 923
930# ifdef ENABLE_TRANSPARENCY 924# ifdef ENABLE_TRANSPARENCY
966 { 960 {
967 changed = true; 961 changed = true;
968 v_blurRadius = vr; 962 v_blurRadius = vr;
969 } 963 }
970 964
971 if (v_blurRadius == 0 && h_blurRadius == 0) 965 if (h_blurRadius == 0 || v_blurRadius == 0)
972 bg_flags &= ~BG_NEEDS_BLUR; 966 bg_flags &= ~BG_NEEDS_BLUR;
973 else 967 else
974 bg_flags |= BG_NEEDS_BLUR; 968 bg_flags |= BG_NEEDS_BLUR;
975 969
976 return changed; 970 return changed;
977} 971}
978 972
979void 973void
980rxvt_term::set_tint_shade_flags () 974rxvt_term::set_tint_shade_flags ()
981{ 975{
982 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); 976 rgba c;
983 bool has_shade = shade != 100; 977 bool has_shade = shade != 100;
984 978
985 bg_flags &= ~BG_TINT_FLAGS; 979 bg_flags &= ~BG_TINT_FLAGS;
986 980
987 if (bg_flags & BG_TINT_SET) 981 if (bg_flags & BG_TINT_SET)
1013} 1007}
1014 1008
1015bool 1009bool
1016rxvt_term::bg_set_shade (const char *shade_str) 1010rxvt_term::bg_set_shade (const char *shade_str)
1017{ 1011{
1018 int new_shade = (shade_str) ? atoi (shade_str) : 100; 1012 int new_shade = atoi (shade_str);
1019 1013
1020 clamp_it (new_shade, -100, 200); 1014 clamp_it (new_shade, -100, 200);
1021 if (new_shade < 0) 1015 if (new_shade < 0)
1022 new_shade = 200 - (100 + new_shade); 1016 new_shade = 200 - (100 + new_shade);
1023 1017
1053 params[i+2] = XDoubleToFixed (kernel[i] / sum); 1047 params[i+2] = XDoubleToFixed (kernel[i] / sum);
1054} 1048}
1055#endif 1049#endif
1056 1050
1057bool 1051bool
1058rxvt_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)
1059{ 1053{
1060 bool ret = false; 1054 bool ret = false;
1061#if XRENDER 1055#if XRENDER
1056 if (!(bg_flags & BG_HAS_RENDER_CONV))
1057 return false;
1058
1062 int size = max (h_blurRadius, v_blurRadius) * 2 + 1; 1059 int size = max (h_blurRadius, v_blurRadius) * 2 + 1;
1063 double *kernel = (double *)malloc (size * sizeof (double)); 1060 double *kernel = (double *)malloc (size * sizeof (double));
1064 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 1061 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
1065 1062
1066 XRenderPictureAttributes pa; 1063 XRenderPictureAttributes pa;
1067 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1064 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1068 1065
1066 pa.repeat = RepeatPad;
1069 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);
1070 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1069 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa);
1070 XFreePixmap (dpy, tmp);
1071 1071
1072 if (kernel && params) 1072 if (kernel && params)
1073 { 1073 {
1074 if (h_blurRadius)
1075 {
1076 size = h_blurRadius * 2 + 1; 1074 size = h_blurRadius * 2 + 1;
1077 get_gaussian_kernel (h_blurRadius, size, kernel, params); 1075 get_gaussian_kernel (h_blurRadius, size, kernel, params);
1078 1076
1079 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1077 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1080 XRenderComposite (dpy, 1078 XRenderComposite (dpy,
1081 PictOpSrc, 1079 PictOpSrc,
1082 src, 1080 src,
1083 None, 1081 None,
1084 dst, 1082 dst,
1085 0, 0, 1083 0, 0,
1086 0, 0, 1084 0, 0,
1087 0, 0, 1085 0, 0,
1088 width, height); 1086 width, height);
1089 }
1090 1087
1091 if (v_blurRadius) 1088 ::swap (src, dst);
1092 { 1089
1093 size = v_blurRadius * 2 + 1; 1090 size = v_blurRadius * 2 + 1;
1094 get_gaussian_kernel (v_blurRadius, size, kernel, params); 1091 get_gaussian_kernel (v_blurRadius, size, kernel, params);
1095 ::swap (params[0], params[1]); 1092 ::swap (params[0], params[1]);
1096 1093
1097 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1094 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1098 XRenderComposite (dpy, 1095 XRenderComposite (dpy,
1099 PictOpSrc, 1096 PictOpSrc,
1100 src, 1097 src,
1101 None, 1098 None,
1102 dst, 1099 dst,
1103 0, 0, 1100 0, 0,
1104 0, 0, 1101 0, 0,
1105 0, 0, 1102 0, 0,
1106 width, height); 1103 width, height);
1107 }
1108 1104
1109 ret = true; 1105 ret = true;
1110 } 1106 }
1111 1107
1112 free (kernel); 1108 free (kernel);
1139 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height); 1135 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height);
1140 ret = true; 1136 ret = true;
1141 XFreeGC (dpy, gc); 1137 XFreeGC (dpy, gc);
1142 } 1138 }
1143 } 1139 }
1144 else
1145 {
1146# if XRENDER 1140# if XRENDER
1141 else if (bg_flags & BG_HAS_RENDER)
1142 {
1147 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); 1143 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1148 1144
1149 if (bg_flags & BG_TINT_SET) 1145 if (bg_flags & BG_TINT_SET)
1150 tint.get (c); 1146 tint.get (c);
1151 1147
1160 c.r = c.r * (200 - shade) / 100; 1156 c.r = c.r * (200 - shade) / 100;
1161 c.g = c.g * (200 - shade) / 100; 1157 c.g = c.g * (200 - shade) / 100;
1162 c.b = c.b * (200 - shade) / 100; 1158 c.b = c.b * (200 - shade) / 100;
1163 } 1159 }
1164 1160
1165 XRenderPictFormat *solid_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
1166 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1161 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1167 XRenderPictureAttributes pa;
1168 1162
1169 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1163 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1170 1164
1171 pa.repeat = True; 1165 Picture overlay_pic = create_xrender_mask (dpy, pixmap, True, False);
1172 1166
1173 Pixmap overlay_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32); 1167 Picture mask_pic = create_xrender_mask (dpy, pixmap, True, True);
1174 Picture overlay_pic = XRenderCreatePicture (dpy, overlay_pmap, solid_format, CPRepeat, &pa);
1175 XFreePixmap (dpy, overlay_pmap);
1176
1177 pa.component_alpha = True;
1178 Pixmap mask_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32);
1179 Picture mask_pic = XRenderCreatePicture (dpy, mask_pmap, solid_format, CPRepeat | CPComponentAlpha, &pa);
1180 XFreePixmap (dpy, mask_pmap);
1181 1168
1182 XRenderColor mask_c; 1169 XRenderColor mask_c;
1183 1170
1184 mask_c.alpha = 0xffff; 1171 mask_c.alpha = 0xffff;
1185 mask_c.red = 1172 mask_c.red =
1190 mask_c.alpha = 0; 1177 mask_c.alpha = 0;
1191 mask_c.red = 0xffff - c.r; 1178 mask_c.red = 0xffff - c.r;
1192 mask_c.green = 0xffff - c.g; 1179 mask_c.green = 0xffff - c.g;
1193 mask_c.blue = 0xffff - c.b; 1180 mask_c.blue = 0xffff - c.b;
1194 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); 1181 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
1182
1195 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);
1196 1184
1197 if (shade > 100) 1185 if (shade > 100)
1198 { 1186 {
1199 mask_c.red = mask_c.green = mask_c.blue = 0xffff * (shade - 100) / 100;
1200 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;
1201 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); 1191 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1202 1192
1203 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);
1204 } 1194 }
1205 1195
1206 ret = true; 1196 ret = true;
1207 1197
1208 XRenderFreePicture (dpy, mask_pic); 1198 XRenderFreePicture (dpy, mask_pic);
1209 XRenderFreePicture (dpy, overlay_pic); 1199 XRenderFreePicture (dpy, overlay_pic);
1210 XRenderFreePicture (dpy, back_pic); 1200 XRenderFreePicture (dpy, back_pic);
1201 }
1211# endif 1202# endif
1212 }
1213 1203
1214 return ret; 1204 return ret;
1215} 1205}
1216 1206
1217/* 1207/*
1268#if XRENDER 1258#if XRENDER
1269 if (bg_flags & BG_HAS_RENDER) 1259 if (bg_flags & BG_HAS_RENDER)
1270 { 1260 {
1271 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);
1272 1262
1273 XRenderPictureAttributes pa;
1274
1275 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen)); 1263 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
1276 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, &pa); 1264 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, 0);
1277 1265
1278 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual); 1266 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
1279 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, &pa); 1267 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, 0);
1280 1268
1281 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);
1282 1270
1283 XRenderFreePicture (dpy, src); 1271 XRenderFreePicture (dpy, src);
1284 XRenderFreePicture (dpy, dst); 1272 XRenderFreePicture (dpy, dst);
1301 bg_pmap_width = window_width; 1289 bg_pmap_width = window_width;
1302 bg_pmap_height = window_height; 1290 bg_pmap_height = window_height;
1303 } 1291 }
1304 1292
1305 /* straightforward pixmap copy */ 1293 /* straightforward pixmap copy */
1306 while (sx < 0) sx += root_width; 1294 while (sx < 0) sx += root_pmap_width;
1307 while (sy < 0) sy += root_height; 1295 while (sy < 0) sy += root_pmap_height;
1308 1296
1309 gcv.tile = recoded_root_pmap; 1297 gcv.tile = recoded_root_pmap;
1310 gcv.fill_style = FillTiled; 1298 gcv.fill_style = FillTiled;
1311 gcv.ts_x_origin = -sx; 1299 gcv.ts_x_origin = -sx;
1312 gcv.ts_y_origin = -sy; 1300 gcv.ts_y_origin = -sy;
1314 1302
1315 if (gc) 1303 if (gc)
1316 { 1304 {
1317 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height); 1305 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height);
1318 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS); 1306 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS);
1319 XFreeGC (dpy, gc);
1320 1307
1321 if (!(bg_flags & BG_CLIENT_RENDER)) 1308 if (!(bg_flags & BG_CLIENT_RENDER))
1322 { 1309 {
1323 if ((bg_flags & BG_NEEDS_BLUR) 1310 if (bg_flags & BG_NEEDS_BLUR)
1324 && (bg_flags & BG_HAS_RENDER_CONV))
1325 { 1311 {
1326 if (blur_pixmap (bg_pixmap, visual, window_width, window_height)) 1312 if (blur_pixmap (bg_pixmap, visual, window_width, window_height, depth))
1327 result &= ~BG_NEEDS_BLUR; 1313 result &= ~BG_NEEDS_BLUR;
1328 } 1314 }
1329 if ((bg_flags & BG_NEEDS_TINT) 1315 if (bg_flags & BG_NEEDS_TINT)
1330 && (bg_flags & (BG_TINT_BITAND | BG_HAS_RENDER)))
1331 { 1316 {
1332 if (tint_pixmap (bg_pixmap, visual, window_width, window_height)) 1317 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1333 result &= ~BG_NEEDS_TINT; 1318 result &= ~BG_NEEDS_TINT;
1334 } 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
1335 } /* server side rendering completed */ 1334 } /* server side rendering completed */
1335
1336 XFreeGC (dpy, gc);
1336 } 1337 }
1337 1338
1338 if (recoded_root_pmap != root_pixmap) 1339 if (recoded_root_pmap != root_pixmap)
1339 XFreePixmap (dpy, recoded_root_pmap); 1340 XFreePixmap (dpy, recoded_root_pmap);
1340 1341
1349 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]); 1350 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]);
1350 1351
1351 root_pixmap = new_root_pixmap; 1352 root_pixmap = new_root_pixmap;
1352} 1353}
1353# endif /* ENABLE_TRANSPARENCY */ 1354# endif /* ENABLE_TRANSPARENCY */
1354
1355#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1356static void shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c);
1357# endif
1358 1355
1359bool 1356bool
1360rxvt_term::bg_render () 1357rxvt_term::bg_render ()
1361{ 1358{
1362 unsigned long tr_flags = 0; 1359 unsigned long tr_flags = 0;
1367 { 1364 {
1368 /* we need to re-generate transparency pixmap in that case ! */ 1365 /* we need to re-generate transparency pixmap in that case ! */
1369 tr_flags = make_transparency_pixmap (); 1366 tr_flags = make_transparency_pixmap ();
1370 if (tr_flags == 0) 1367 if (tr_flags == 0)
1371 return false; 1368 return false;
1372 else if (!(tr_flags & BG_EFFECTS_FLAGS))
1373 bg_flags |= BG_IS_VALID; 1369 bg_flags |= BG_IS_VALID;
1374 } 1370 }
1375# endif 1371# endif
1376 1372
1377# ifdef BG_IMAGE_FROM_FILE 1373# ifdef BG_IMAGE_FROM_FILE
1378 if ((bg_flags & BG_IS_FROM_FILE) 1374 if ((bg_flags & BG_IS_FROM_FILE)
1379 || (tr_flags & BG_EFFECTS_FLAGS)) 1375 || (tr_flags & BG_EFFECTS_FLAGS))
1380 { 1376 {
1381 if (render_image (tr_flags)) 1377 if (render_image (tr_flags))
1382 bg_flags |= BG_IS_VALID; 1378 bg_flags |= BG_IS_VALID;
1383 }
1384# endif
1385
1386# if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1387 XImage *result = NULL;
1388
1389 if (tr_flags && !(bg_flags & BG_IS_VALID))
1390 {
1391 result = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1392 }
1393
1394 if (result)
1395 {
1396 /* our own client-side tinting */
1397 if (tr_flags & BG_NEEDS_TINT)
1398 {
1399 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
1400 if (bg_flags & BG_TINT_SET)
1401 tint.get (c);
1402 shade_ximage (DefaultVisual (dpy, display->screen), result, shade, c);
1403 }
1404
1405 GC gc = XCreateGC (dpy, vt, 0UL, NULL);
1406
1407 if (gc)
1408 {
1409 XPutImage (dpy, bg_pixmap, gc, result, 0, 0, 0, 0, result->width, result->height);
1410
1411 XFreeGC (dpy, gc);
1412 bg_flags |= BG_IS_VALID;
1413 }
1414
1415 XDestroyImage (result);
1416 } 1379 }
1417# endif 1380# endif
1418 1381
1419 if (!(bg_flags & BG_IS_VALID)) 1382 if (!(bg_flags & BG_IS_VALID))
1420 { 1383 {
1458} 1421}
1459 1422
1460#endif /* HAVE_BG_PIXMAP */ 1423#endif /* HAVE_BG_PIXMAP */
1461 1424
1462#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) 1425#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1463/* taken from aterm-0.4.2 */ 1426/* based on code from aterm-0.4.2 */
1464 1427
1465static void 1428static inline void
1466shade_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)
1467{ 1442{
1468 int sh_r, sh_g, sh_b; 1443 int sh_r, sh_g, sh_b;
1469 uint32_t mask_r, mask_g, mask_b; 1444 uint32_t mask_r, mask_g, mask_b;
1470 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; 1445 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b;
1471 rgba low; 1446 unsigned short low;
1472 rgba high;
1473 int i;
1474 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst; 1447 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
1475 1448
1476 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return; 1449 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return;
1477 1450
1478 /* for convenience */ 1451 /* for convenience */
1537 break; 1510 break;
1538 default: 1511 default:
1539 return; /* we do not support this color depth */ 1512 return; /* we do not support this color depth */
1540 } 1513 }
1541 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
1542 /* prepare limits for color transformation (each channel is handled separately) */ 1520 /* prepare limits for color transformation (each channel is handled separately) */
1543 if (shade > 100) 1521 if (shade > 100)
1544 { 1522 {
1545 shade = 200 - shade;
1546
1547 high.r = c.r * shade / 100;
1548 high.g = c.g * shade / 100;
1549 high.b = c.b * shade / 100;
1550
1551 low.r = 65535 * (100 - shade) / 100; 1523 c.r = c.r * (200 - shade) / 100;
1552 low.g = 65535 * (100 - shade) / 100; 1524 c.g = c.g * (200 - shade) / 100;
1553 low.b = 65535 * (100 - shade) / 100; 1525 c.b = c.b * (200 - shade) / 100;
1526
1527 low = 0xffff * (shade - 100) / 100;
1554 } 1528 }
1555 else 1529 else
1556 { 1530 {
1557 high.r = c.r * shade / 100; 1531 c.r = c.r * shade / 100;
1558 high.g = c.g * shade / 100; 1532 c.g = c.g * shade / 100;
1559 high.b = c.b * shade / 100; 1533 c.b = c.b * shade / 100;
1560 1534
1561 low.r = low.g = low.b = 0; 1535 low = 0;
1562 } 1536 }
1563 1537
1564 /* fill our lookup tables */ 1538 /* fill our lookup tables */
1565 for (i = 0; i <= mask_r>>sh_r; i++) 1539 fill_lut (lookup_r, mask_r, sh_r, low, c.r);
1566 { 1540 fill_lut (lookup_g, mask_g, sh_g, low, c.g);
1567 uint32_t tmp; 1541 fill_lut (lookup_b, mask_b, sh_b, low, c.b);
1568 tmp = i * high.r;
1569 tmp += (mask_r>>sh_r) * low.r;
1570 lookup_r[i] = (tmp/65535)<<sh_r;
1571 }
1572 for (i = 0; i <= mask_g>>sh_g; i++)
1573 {
1574 uint32_t tmp;
1575 tmp = i * high.g;
1576 tmp += (mask_g>>sh_g) * low.g;
1577 lookup_g[i] = (tmp/65535)<<sh_g;
1578 }
1579 for (i = 0; i <= mask_b>>sh_b; i++)
1580 {
1581 uint32_t tmp;
1582 tmp = i * high.b;
1583 tmp += (mask_b>>sh_b) * low.b;
1584 lookup_b[i] = (tmp/65535)<<sh_b;
1585 }
1586 1542
1587 /* apply table to input image (replacing colors by newly calculated ones) */ 1543 /* apply table to input image (replacing colors by newly calculated ones) */
1588 if (ximage->bits_per_pixel == 32 1544 if (ximage->bits_per_pixel == 32
1589 && (ximage->depth == 24 || ximage->depth == 32) 1545 && (ximage->depth == 24 || ximage->depth == 32)
1590 && ximage->byte_order == host_byte_order) 1546 && ximage->byte_order == host_byte_order)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines