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.132 by sf-exg, Mon Jan 10 20:46:20 2011 UTC vs.
Revision 1.194 by sf-exg, Sun Jan 1 17:43:47 2012 UTC

1/*----------------------------------------------------------------------* 1/*----------------------------------------------------------------------*
2 * File: background.C - former xpm.C 2 * File: background.C - former xpm.C
3 *----------------------------------------------------------------------* 3 *----------------------------------------------------------------------*
4 * 4 *
5 * All portions of code are copyright by their respective author/s. 5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 2005-2008 Marc Lehmann <pcg@goof.com> 6 * Copyright (c) 2005-2008 Marc Lehmann <schmorp@schmorp.de>
7 * Copyright (c) 2007 Sasha Vasko <sasha@aftercode.net> 7 * Copyright (c) 2007 Sasha Vasko <sasha@aftercode.net>
8 * Copyright (c) 2010 Emanuele Giaquinta <e.giaquinta@glauco.it> 8 * Copyright (c) 2010 Emanuele Giaquinta <e.giaquinta@glauco.it>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
32 32
33#ifndef FilterConvolution 33#ifndef FilterConvolution
34#define FilterConvolution "convolution" 34#define FilterConvolution "convolution"
35#endif 35#endif
36 36
37#define DO_TIMING_TEST 0
38
39#if DO_TIMING_TEST
40# include <sys/time.h>
41#define TIMING_TEST_START(id) \
42 struct timeval timing_test_##id##_stv; \
43 gettimeofday (&timing_test_##id##_stv, NULL);
44
45#define TIMING_TEST_PRINT_RESULT(id) \
46 do { \
47 struct timeval tv; \
48 gettimeofday (&tv, NULL); \
49 tv.tv_sec -= (timing_test_##id##_stv).tv_sec; \
50 fprintf (stderr, "%s: %s: %d: elapsed %ld usec\n", #id, __FILE__, __LINE__, \
51 tv.tv_sec * 1000000 + tv.tv_usec - (timing_test_##id##_stv).tv_usec); \
52 } while (0)
53
54#else
55#define TIMING_TEST_START(id) do {} while (0)
56#define TIMING_TEST_PRINT_RESULT(id) do {} while (0)
57#endif
58
59/*
60 * Pixmap geometry string interpretation :
61 * Each geometry string contains zero or one scale/position
62 * adjustment and may optionally be followed by a colon and one or more
63 * colon-delimited pixmap operations.
64 * The following table shows the valid geometry strings and their
65 * effects on the background image :
66 *
67 * WxH+X+Y Set scaling to W% by H%, and position to X% by Y%.
68 * W and H are percentages of the terminal window size.
69 * X and Y are also percentages; e.g., +50+50 centers
70 * the image in the window.
71 *
72 * Pixmap Operations : (should be prepended by a colon)
73 * tile Tile image. Scaling/position modifiers above will affect
74 * the tile size and origin.
75 * propscale When scaling, scale proportionally. That is, maintain the
76 * proper aspect ratio for the image. Any portion of the
77 * background not covered by the image is filled with the
78 * current background color.
79 * hscale Scale horizontally, tile vertically ?
80 * vscale Tile horizontally, scale vertically ?
81 * scale Scale both up and down
82 * auto Same as 100x100+50+50
83 */
84
85#ifdef HAVE_BG_PIXMAP 37#ifdef HAVE_BG_PIXMAP
86bgPixmap_t::bgPixmap_t () 38# if XRENDER
39static Picture
40create_xrender_mask (Display *dpy, Drawable drawable, Bool argb, Bool component_alpha)
87{ 41{
88 // this is basically redundant as bgPixmap_t is only used in 42 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8);
89 // zero_initialised-derived structs 43
90#ifdef HAVE_AFTERIMAGE 44 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8);
91 original_asim = NULL; 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}
92#endif 54# endif
93#ifdef HAVE_PIXBUF
94 pixbuf = NULL;
95#endif
96#ifdef BG_IMAGE_FROM_FILE
97 have_image = false;
98 h_scale = v_scale = 0;
99 h_align = v_align = 0;
100#endif
101#ifdef ENABLE_TRANSPARENCY
102 shade = 100;
103#endif
104 flags = 0;
105 pixmap = None;
106 valid_since = invalid_since = 0;
107 target = 0;
108 target_x = target_y = 0;
109}
110 55
111void 56void
112bgPixmap_t::destroy () 57rxvt_term::bg_destroy ()
113{ 58{
114#ifdef HAVE_AFTERIMAGE 59#ifdef HAVE_AFTERIMAGE
115 if (original_asim) 60 if (original_asim)
116 safe_asimage_destroy (original_asim); 61 safe_asimage_destroy (original_asim);
62 if (asv)
63 destroy_asvisual (asv, 0);
64 if (asimman)
65 destroy_image_manager (asimman, 0);
117#endif 66#endif
118 67
119#ifdef HAVE_PIXBUF 68#ifdef HAVE_PIXBUF
120 if (pixbuf) 69 if (pixbuf)
121 g_object_unref (pixbuf); 70 g_object_unref (pixbuf);
122#endif 71#endif
123 72
124 if (pixmap && target) 73 if (bg_pixmap)
125 XFreePixmap (target->dpy, pixmap); 74 XFreePixmap (dpy, bg_pixmap);
126} 75}
127 76
128bool 77bool
129bgPixmap_t::set_position (int x, int y) 78rxvt_term::bg_set_position (int x, int y)
130{ 79{
131 80
132 if (target_x != x 81 if (target_x != x
133 || target_y != y) 82 || target_y != y)
134 { 83 {
138 } 87 }
139 return false; 88 return false;
140} 89}
141 90
142bool 91bool
143bgPixmap_t::window_size_sensitive () 92rxvt_term::bg_window_size_sensitive ()
144{ 93{
145# ifdef ENABLE_TRANSPARENCY 94# ifdef ENABLE_TRANSPARENCY
146 if (flags & isTransparent) 95 if (bg_flags & BG_IS_TRANSPARENT)
147 return true; 96 return true;
148# endif 97# endif
149 98
150# ifdef BG_IMAGE_FROM_FILE 99# ifdef BG_IMAGE_FROM_FILE
151 if (have_image) 100 if (bg_flags & BG_IS_FROM_FILE)
152 { 101 {
153 if (flags & sizeSensitive) 102 if (bg_flags & BG_IS_SIZE_SENSITIVE)
154 return true; 103 return true;
155 } 104 }
156# endif 105# endif
157 106
158 return false; 107 return false;
159} 108}
160 109
161bool 110bool
162bgPixmap_t::window_position_sensitive () 111rxvt_term::bg_window_position_sensitive ()
163{ 112{
164# ifdef ENABLE_TRANSPARENCY 113# ifdef ENABLE_TRANSPARENCY
165 if (flags & isTransparent) 114 if (bg_flags & BG_IS_TRANSPARENT)
166 return true; 115 return true;
167# endif 116# endif
168 117
169# ifdef BG_IMAGE_FROM_FILE 118# ifdef BG_IMAGE_FROM_FILE
170 if (have_image) 119 if (bg_flags & BG_IS_FROM_FILE)
171 { 120 {
172 if (flags & rootAlign) 121 if (bg_flags & BG_ROOT_ALIGN)
173 return true; 122 return true;
174 } 123 }
175# endif 124# endif
176 125
177 return false; 126 return false;
219 int smaller = min (image_size, window_size); 168 int smaller = min (image_size, window_size);
220 169
221 if (align >= 0 && align <= 100) 170 if (align >= 0 && align <= 100)
222 return diff * align / 100; 171 return diff * align / 100;
223 else if (align > 100 && align <= 200) 172 else if (align > 100 && align <= 200)
224 return ((align - 100) * smaller / 100) + window_size - smaller; 173 return (align - 100) * smaller / 100 + window_size - smaller;
225 else if (align >= -100 && align < 0) 174 else if (align >= -100 && align < 0)
226 return ((align + 100) * smaller / 100) - image_size; 175 return (align + 100) * smaller / 100 - image_size;
227 return 0; 176 return 0;
228} 177}
229 178
230static inline int 179static inline int
231make_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)
244 dst_size = target_size - dst_pos; 193 dst_size = target_size - dst_pos;
245 return src_pos; 194 return src_pos;
246} 195}
247 196
248bool 197bool
249bgPixmap_t::set_geometry (const char *geom, bool update) 198rxvt_term::bg_set_geometry (const char *geom, bool update)
250{ 199{
251 bool changed = false; 200 bool changed = false;
252 int geom_flags = 0; 201 int geom_flags = 0;
253 int x = 0, y = 0; 202 int x = 0, y = 0;
254 unsigned int w = 0, h = 0; 203 unsigned int w = 0, h = 0;
255 unsigned int n; 204 unsigned long new_flags = 0;
256 unsigned long new_flags = (flags & (~geometryFlags));
257 const char *ops;
258# define MAXLEN_GEOM 256 /* could be longer than regular geometry string */
259 205
260 if (geom == NULL) 206 if (geom == NULL)
261 return false; 207 return false;
262 208
263 char str[MAXLEN_GEOM]; 209 if (geom[0])
264
265 ops = strchr (geom, ':');
266 if (ops == NULL)
267 n = strlen (geom);
268 else
269 n = ops - geom;
270
271 if (n >= MAXLEN_GEOM)
272 return false;
273
274 memcpy (str, geom, n);
275 str[n] = '\0';
276 rxvt_strtrim (str);
277
278 if (str[0])
279 { 210 {
280 /* 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
281 geom_flags = XParseGeometry (str, &x, &y, &w, &h); 301 geom_flags |= XParseGeometry (arr[i], &x, &y, &w, &h);
282 } /* done parsing geometry string */ 302 } /* done parsing ops */
303
304 rxvt_free_strsplit (arr);
305 }
306
307 new_flags |= bg_flags & ~BG_GEOMETRY_FLAGS;
283 308
284 if (!update) 309 if (!update)
285 { 310 {
286 if (!(geom_flags & XValue)) 311 if (!(geom_flags & XValue))
287 x = y = defaultAlign; 312 x = y = defaultAlign;
296 w = h; 321 w = h;
297 322
298 geom_flags |= WidthValue|HeightValue|XValue|YValue; 323 geom_flags |= WidthValue|HeightValue|XValue|YValue;
299 } 324 }
300 325
301 if (ops)
302 {
303 char **arr = rxvt_strsplit (':', ops + 1);
304
305 for (int i = 0; arr[i]; i++)
306 {
307# define CHECK_GEOM_OPS(op_str) (strcasecmp (arr[i], (op_str)) == 0)
308 if (CHECK_GEOM_OPS ("tile"))
309 {
310 w = h = noScale;
311 geom_flags |= WidthValue|HeightValue;
312 }
313 else if (CHECK_GEOM_OPS ("propscale"))
314 {
315 new_flags |= propScale;
316 }
317 else if (CHECK_GEOM_OPS ("hscale"))
318 {
319 if (w == 0) w = windowScale;
320
321 h = noScale;
322 geom_flags |= WidthValue|HeightValue;
323 }
324 else if (CHECK_GEOM_OPS ("vscale"))
325 {
326 if (h == 0) h = windowScale;
327
328 w = noScale;
329 geom_flags |= WidthValue|HeightValue;
330 }
331 else if (CHECK_GEOM_OPS ("scale"))
332 {
333 if (h == 0) h = windowScale;
334 if (w == 0) w = windowScale;
335
336 geom_flags |= WidthValue|HeightValue;
337 }
338 else if (CHECK_GEOM_OPS ("auto"))
339 {
340 w = h = windowScale;
341 x = y = centerAlign;
342 geom_flags |= WidthValue|HeightValue|XValue|YValue;
343 }
344 else if (CHECK_GEOM_OPS ("root"))
345 {
346 new_flags |= rootAlign;
347 w = h = noScale;
348 geom_flags |= WidthValue|HeightValue;
349 }
350# undef CHECK_GEOM_OPS
351 } /* done parsing ops */
352
353 rxvt_free_strsplit (arr);
354 }
355
356 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;
357 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;
358 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;
359 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;
360 330
361 if (new_flags != flags) 331 if (new_flags != bg_flags)
362 { 332 {
363 flags = new_flags; 333 bg_flags = new_flags;
364 changed = true; 334 changed = true;
365 } 335 }
366 336
367 return changed; 337 return changed;
368} 338}
369 339
370void 340void
371bgPixmap_t::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)
372{ 342{
373 int target_width = target->szHint.width; 343 int target_width = szHint.width;
374 int target_height = target->szHint.height; 344 int target_height = szHint.height;
375 345
376 if (flags & propScale) 346 w = h_scale * target_width / 100;
347 h = v_scale * target_height / 100;
348
349 if (bg_flags & BG_KEEP_ASPECT)
377 { 350 {
378 float scale = (float)target_width / image_width; 351 float scale = (float)w / image_width;
379 min_it (scale, (float)target_height / image_height); 352 min_it (scale, (float)h / image_height);
380 w = image_width * scale + 0.5; 353 w = image_width * scale + 0.5;
381 h = image_height * scale + 0.5; 354 h = image_height * scale + 0.5;
382 } 355 }
383 else
384 {
385 w = h_scale * target_width / 100;
386 h = v_scale * target_height / 100;
387 }
388 356
389 if (!w) w = image_width; 357 if (!w) w = image_width;
390 if (!h) h = image_height; 358 if (!h) h = image_height;
391 359
392 if (flags & rootAlign) 360 if (bg_flags & BG_ROOT_ALIGN)
393 { 361 {
394 x = -target_x; 362 x = -target_x;
395 y = -target_y; 363 y = -target_y;
396 } 364 }
397 else 365 else
398 { 366 {
399 x = make_align_position (h_align, target_width, w); 367 x = make_align_position (h_align, target_width, w);
400 y = make_align_position (v_align, target_height, h); 368 y = make_align_position (v_align, target_height, h);
401 } 369 }
402 370
403 flags &= ~sizeSensitive; 371 bg_flags &= ~BG_IS_SIZE_SENSITIVE;
404 if ((flags & propScale) || h_scale || v_scale 372 if (!(bg_flags & BG_TILE)
373 || h_scale || v_scale
405 || (!(flags & rootAlign) && (h_align || v_align)) 374 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align))
406 || w > target_width || h > target_height) 375 || w > target_width || h > target_height)
407 flags |= sizeSensitive; 376 bg_flags |= BG_IS_SIZE_SENSITIVE;
408} 377}
409 378
410# ifdef HAVE_AFTERIMAGE 379# ifdef HAVE_AFTERIMAGE
411bool 380bool
412bgPixmap_t::render_image (unsigned long background_flags) 381rxvt_term::render_image (unsigned long tr_flags)
413{ 382{
414 if (target == NULL)
415 return false;
416
417 target->init_asv (); 383 init_asv ();
418 384
419 ASImage *background = NULL; 385 ASImage *background = NULL;
420 ARGB32 background_tint = TINT_LEAVE_SAME; 386 ARGB32 background_tint = TINT_LEAVE_SAME;
421 387
422# ifdef ENABLE_TRANSPARENCY 388# ifdef ENABLE_TRANSPARENCY
423 if (background_flags) 389 if (tr_flags)
424 background = pixmap2ximage (target->asv, pixmap, 0, 0, pmap_width, pmap_height, AllPlanes, 100); 390 background = pixmap2ximage (asv, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, 100);
425 391
426 if (!(background_flags & transpPmapTinted) && (flags & tintNeeded)) 392 if (tr_flags & BG_NEEDS_TINT)
427 { 393 {
428 ShadingInfo as_shade; 394 ShadingInfo as_shade;
429 as_shade.shading = shade; 395 as_shade.shading = shade;
430 396
431 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); 397 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
432 if (flags & tintSet) 398 if (bg_flags & BG_TINT_SET)
433 tint.get (c); 399 tint.get (c);
434 as_shade.tintColor.red = c.r; 400 as_shade.tintColor.red = c.r;
435 as_shade.tintColor.green = c.g; 401 as_shade.tintColor.green = c.g;
436 as_shade.tintColor.blue = c.b; 402 as_shade.tintColor.blue = c.b;
437 403
438 background_tint = shading2tint32 (&as_shade); 404 background_tint = shading2tint32 (&as_shade);
439 } 405 }
440 406
441 if (!(background_flags & transpPmapBlurred) && (flags & blurNeeded) && background != NULL) 407 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL)
442 { 408 {
443 ASImage *tmp = blur_asimage_gauss (target->asv, background, h_blurRadius, v_blurRadius, 0xFFFFFFFF, 409 ASImage *tmp = blur_asimage_gauss (asv, background, h_blurRadius, v_blurRadius, 0xFFFFFFFF,
444 (original_asim == NULL || tint == TINT_LEAVE_SAME) ? ASA_XImage : ASA_ASImage, 410 ASA_XImage,
445 100, ASIMAGE_QUALITY_DEFAULT); 411 100, ASIMAGE_QUALITY_DEFAULT);
446 if (tmp) 412 if (tmp)
447 { 413 {
448 destroy_asimage (&background); 414 destroy_asimage (&background);
449 background = tmp; 415 background = tmp;
451 } 417 }
452# endif 418# endif
453 419
454 ASImage *result = 0; 420 ASImage *result = 0;
455 421
456 int target_width = target->szHint.width; 422 int target_width = szHint.width;
457 int target_height = target->szHint.height; 423 int target_height = szHint.height;
458 int new_pmap_width = target_width; 424 int new_pmap_width = target_width;
459 int new_pmap_height = target_height; 425 int new_pmap_height = target_height;
460 426
461 int x = 0; 427 int x = 0;
462 int y = 0; 428 int y = 0;
465 431
466 if (original_asim) 432 if (original_asim)
467 get_image_geometry (original_asim->width, original_asim->height, w, h, x, y); 433 get_image_geometry (original_asim->width, original_asim->height, w, h, x, y);
468 434
469 if (!original_asim 435 if (!original_asim
470 || (!(flags & rootAlign) 436 || (!(bg_flags & BG_ROOT_ALIGN)
471 && (x >= target_width 437 && (x >= target_width
472 || y >= target_height 438 || y >= target_height
473 || (x + w <= 0) 439 || x + w <= 0
474 || (y + h <= 0)))) 440 || y + h <= 0)))
475 { 441 {
476 if (background) 442 if (background)
477 { 443 {
478 new_pmap_width = background->width; 444 new_pmap_width = background->width;
479 new_pmap_height = background->height; 445 new_pmap_height = background->height;
480 result = background; 446 result = background;
481 447
482 if (background_tint != TINT_LEAVE_SAME) 448 if (background_tint != TINT_LEAVE_SAME)
483 { 449 {
484 ASImage *tmp = tile_asimage (target->asv, background, 0, 0, 450 ASImage *tmp = tile_asimage (asv, background, 0, 0,
485 target_width, target_height, background_tint, 451 target_width, target_height, background_tint,
486 ASA_XImage, 100, ASIMAGE_QUALITY_DEFAULT); 452 ASA_XImage, 100, ASIMAGE_QUALITY_DEFAULT);
487 if (tmp) 453 if (tmp)
488 result = tmp; 454 result = tmp;
489 } 455 }
493 } 459 }
494 else 460 else
495 { 461 {
496 result = original_asim; 462 result = original_asim;
497 463
498 if ((w != original_asim->width) 464 if (w != original_asim->width
499 || (h != original_asim->height)) 465 || h != original_asim->height)
500 { 466 {
501 result = scale_asimage (target->asv, original_asim, 467 result = scale_asimage (asv, original_asim,
502 w, h, 468 w, h,
503 background ? ASA_ASImage : ASA_XImage, 469 ASA_XImage,
504 100, ASIMAGE_QUALITY_DEFAULT); 470 100, ASIMAGE_QUALITY_DEFAULT);
505 } 471 }
506 472
507 if (background == NULL) 473 if (background == NULL)
508 { 474 {
509 if (h_scale == 0 || v_scale == 0) 475 if (bg_flags & BG_TILE)
510 { 476 {
511 /* if tiling - pixmap has to be sized exactly as the image, 477 /* if tiling - pixmap has to be sized exactly as the image,
512 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! */
513 new_pmap_width = min (result->width, target_width); 479 new_pmap_width = min (result->width, target_width);
514 new_pmap_height = min (result->height, target_height); 480 new_pmap_height = min (result->height, target_height);
515 481
516 /* we also need to tile our image in both directions */ 482 /* we also need to tile our image in both directions */
517 ASImage *tmp = tile_asimage (target->asv, result, 483 ASImage *tmp = tile_asimage (asv, result,
518 (int)result->width - x, 484 (int)result->width - x,
519 (int)result->height - y, 485 (int)result->height - y,
520 new_pmap_width, 486 new_pmap_width,
521 new_pmap_height, 487 new_pmap_height,
522 TINT_LEAVE_SAME, ASA_XImage, 488 TINT_LEAVE_SAME, ASA_XImage,
539 layers[0].clip_width = target_width; 505 layers[0].clip_width = target_width;
540 layers[0].clip_height = target_height; 506 layers[0].clip_height = target_height;
541 layers[0].tint = background_tint; 507 layers[0].tint = background_tint;
542 layers[1].im = result; 508 layers[1].im = result;
543 509
544 if (h_scale == 0 || v_scale == 0) 510 if (bg_flags & BG_TILE)
545 { 511 {
546 /* tile horizontally */ 512 /* tile horizontally */
547 while (x > 0) x -= (int)result->width; 513 while (x > 0) x -= (int)result->width;
548 layers[1].dst_x = x; 514 layers[1].dst_x = x;
549 layers[1].clip_width = result->width+target_width; 515 layers[1].clip_width = result->width+target_width;
553 /* clip horizontally */ 519 /* clip horizontally */
554 layers[1].dst_x = x; 520 layers[1].dst_x = x;
555 layers[1].clip_width = result->width; 521 layers[1].clip_width = result->width;
556 } 522 }
557 523
558 if (h_scale == 0 || v_scale == 0) 524 if (bg_flags & BG_TILE)
559 { 525 {
560 while (y > 0) y -= (int)result->height; 526 while (y > 0) y -= (int)result->height;
561 layers[1].dst_y = y; 527 layers[1].dst_y = y;
562 layers[1].clip_height = result->height + target_height; 528 layers[1].clip_height = result->height + target_height;
563 } 529 }
565 { 531 {
566 layers[1].dst_y = y; 532 layers[1].dst_y = y;
567 layers[1].clip_height = result->height; 533 layers[1].clip_height = result->height;
568 } 534 }
569 535
570 if (target->rs[Rs_blendtype]) 536 if (rs[Rs_blendtype])
571 { 537 {
572 layers[1].merge_scanlines = blend_scanlines_name2func (target->rs[Rs_blendtype]); 538 layers[1].merge_scanlines = blend_scanlines_name2func (rs[Rs_blendtype]);
573 if (layers[1].merge_scanlines == NULL) 539 if (layers[1].merge_scanlines == NULL)
574 layers[1].merge_scanlines = alphablend_scanlines; 540 layers[1].merge_scanlines = alphablend_scanlines;
575 } 541 }
576 542
577 ASImage *tmp = merge_layers (target->asv, layers, 2, target_width, target_height, 543 ASImage *tmp = merge_layers (asv, layers, 2, target_width, target_height,
578 ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT); 544 ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
579 545
580 if (tmp) 546 if (tmp)
581 { 547 {
582 if (result != original_asim) 548 if (result != original_asim)
595 { 561 {
596 XGCValues gcv; 562 XGCValues gcv;
597 GC gc; 563 GC gc;
598 564
599 /* create Pixmap */ 565 /* create Pixmap */
600 if (pixmap == None 566 if (bg_pixmap == None
601 || pmap_width != new_pmap_width 567 || bg_pmap_width != new_pmap_width
602 || pmap_height != new_pmap_height 568 || bg_pmap_height != new_pmap_height)
603 || pmap_depth != target->depth)
604 { 569 {
605 if (pixmap) 570 if (bg_pixmap)
606 XFreePixmap (target->dpy, pixmap); 571 XFreePixmap (dpy, bg_pixmap);
607 pixmap = XCreatePixmap (target->dpy, target->vt, new_pmap_width, new_pmap_height, target->depth); 572 bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth);
608 pmap_width = new_pmap_width; 573 bg_pmap_width = new_pmap_width;
609 pmap_height = new_pmap_height; 574 bg_pmap_height = new_pmap_height;
610 pmap_depth = target->depth;
611 } 575 }
612 /* fill with background color (if result's not completely overlapping it) */ 576 /* fill with background color (if result's not completely overlapping it) */
613 gcv.foreground = target->pix_colors[Color_bg]; 577 gcv.foreground = pix_colors[Color_bg];
614 gc = XCreateGC (target->dpy, target->vt, GCForeground, &gcv); 578 gc = XCreateGC (dpy, vt, GCForeground, &gcv);
615 579
616 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;
617 int dst_width = result->width, dst_height = result->height; 581 int dst_width = result->width, dst_height = result->height;
618 if (background == NULL) 582 if (background == NULL)
619 { 583 {
620 if (!(h_scale == 0 || v_scale == 0)) 584 if (!(bg_flags & BG_TILE))
621 { 585 {
622 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 );
623 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);
624 } 588 }
625 589
626 if (dst_x > 0 || dst_y > 0 590 if (dst_x > 0 || dst_y > 0
627 || dst_x + dst_width < new_pmap_width 591 || dst_x + dst_width < new_pmap_width
628 || dst_y + dst_height < new_pmap_height) 592 || dst_y + dst_height < new_pmap_height)
629 XFillRectangle (target->dpy, pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); 593 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height);
630 } 594 }
631 595
632 /* put result on pixmap */ 596 /* put result on pixmap */
633 if (dst_x < new_pmap_width && dst_y < new_pmap_height) 597 if (dst_x < new_pmap_width && dst_y < new_pmap_height)
634 asimage2drawable (target->asv, pixmap, result, gc, src_x, src_y, dst_x, dst_y, dst_width, dst_height, True); 598 asimage2drawable (asv, bg_pixmap, result, gc, src_x, src_y, dst_x, dst_y, dst_width, dst_height, True);
635 599
636 if (result != background && result != original_asim) 600 if (result != background && result != original_asim)
637 destroy_asimage (&result); 601 destroy_asimage (&result);
638 602
639 XFreeGC (target->dpy, gc); 603 XFreeGC (dpy, gc);
640 604
641 ret = true; 605 ret = true;
642 } 606 }
643 607
644 if (background) 608 if (background)
648} 612}
649# endif /* HAVE_AFTERIMAGE */ 613# endif /* HAVE_AFTERIMAGE */
650 614
651# ifdef HAVE_PIXBUF 615# ifdef HAVE_PIXBUF
652bool 616bool
653bgPixmap_t::pixbuf_to_pixmap (GdkPixbuf *pixbuf, Pixmap pixmap, GC gc, 617rxvt_term::pixbuf_to_pixmap (GdkPixbuf *pixbuf, Pixmap pixmap, GC gc,
654 int src_x, int src_y, int dst_x, int dst_y, 618 int src_x, int src_y, int dst_x, int dst_y,
655 unsigned int width, unsigned int height) 619 unsigned int width, unsigned int height)
656{ 620{
657 XImage *ximage; 621 XImage *ximage;
658 char *data, *line; 622 char *data, *line;
659 int bytes_per_pixel; 623 int bytes_per_pixel;
660 int width_r, width_g, width_b; 624 int width_r, width_g, width_b;
661 int sh_r, sh_g, sh_b; 625 int sh_r, sh_g, sh_b;
662 int rowstride; 626 int rowstride;
663 int channels; 627 int channels;
664 unsigned char *row; 628 unsigned char *row;
665 Visual *visual = target->visual;
666 int depth = target->depth;
667 629
668 if (visual->c_class != TrueColor) 630 if (visual->c_class != TrueColor)
669 return false; 631 return false;
670 632
671 if (depth == 24 || depth == 32) 633 if (depth == 24 || depth == 32)
673 else if (depth == 15 || depth == 16) 635 else if (depth == 15 || depth == 16)
674 bytes_per_pixel = 2; 636 bytes_per_pixel = 2;
675 else 637 else
676 return false; 638 return false;
677 639
678 width_r = rxvt_popcount (visual->red_mask); 640 width_r = ecb_popcount32 (visual->red_mask);
679 width_g = rxvt_popcount (visual->green_mask); 641 width_g = ecb_popcount32 (visual->green_mask);
680 width_b = rxvt_popcount (visual->blue_mask); 642 width_b = ecb_popcount32 (visual->blue_mask);
681 643
682 if (width_r > 8 || width_g > 8 || width_b > 8) 644 if (width_r > 8 || width_g > 8 || width_b > 8)
683 return false; 645 return false;
684 646
685 sh_r = rxvt_ctz (visual->red_mask); 647 sh_r = ecb_ctz32 (visual->red_mask);
686 sh_g = rxvt_ctz (visual->green_mask); 648 sh_g = ecb_ctz32 (visual->green_mask);
687 sh_b = rxvt_ctz (visual->blue_mask); 649 sh_b = ecb_ctz32 (visual->blue_mask);
688 650
689 if (width > INT_MAX / height / bytes_per_pixel) 651 if (width > INT_MAX / height / bytes_per_pixel)
690 return false; 652 return false;
691 653
692 data = (char *)malloc (width * height * bytes_per_pixel); 654 data = (char *)malloc (width * height * bytes_per_pixel);
693 if (!data) 655 if (!data)
694 return false; 656 return false;
695 657
696 ximage = XCreateImage (target->dpy, visual, depth, ZPixmap, 0, data, 658 ximage = XCreateImage (dpy, visual, depth, ZPixmap, 0, data,
697 width, height, bytes_per_pixel * 8, 0); 659 width, height, bytes_per_pixel * 8, 0);
698 if (!ximage) 660 if (!ximage)
699 { 661 {
700 free (data); 662 free (data);
701 return false; 663 return false;
702 } 664 }
703 665
704 ximage->byte_order = byteorder::big_endian () ? MSBFirst : LSBFirst; 666 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
705 667
706 rowstride = gdk_pixbuf_get_rowstride (pixbuf); 668 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
707 channels = gdk_pixbuf_get_n_channels (pixbuf); 669 channels = gdk_pixbuf_get_n_channels (pixbuf);
708 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;
709 line = data; 671 line = data;
727 689
728 row += rowstride; 690 row += rowstride;
729 line += ximage->bytes_per_line; 691 line += ximage->bytes_per_line;
730 } 692 }
731 693
732 XPutImage (target->dpy, pixmap, gc, ximage, 0, 0, dst_x, dst_y, width, height); 694 XPutImage (dpy, pixmap, gc, ximage, 0, 0, dst_x, dst_y, width, height);
733 XDestroyImage (ximage); 695 XDestroyImage (ximage);
734 return true; 696 return true;
735} 697}
736 698
737bool 699bool
738bgPixmap_t::render_image (unsigned long background_flags) 700rxvt_term::render_image (unsigned long tr_flags)
739{ 701{
740 if (target == NULL)
741 return false;
742
743 if (!pixbuf) 702 if (!pixbuf)
744 return false; 703 return false;
745 704
746 if (background_flags 705 if (tr_flags
747 && !(flags & HAS_RENDER)) 706 && !(bg_flags & BG_HAS_RENDER))
748 return false; 707 return false;
749 708
750 GdkPixbuf *result; 709 GdkPixbuf *result;
751 710
752 int image_width = gdk_pixbuf_get_width (pixbuf); 711 int image_width = gdk_pixbuf_get_width (pixbuf);
753 int image_height = gdk_pixbuf_get_height (pixbuf); 712 int image_height = gdk_pixbuf_get_height (pixbuf);
754 713
755 int target_width = target->szHint.width; 714 int target_width = szHint.width;
756 int target_height = target->szHint.height; 715 int target_height = szHint.height;
757 int new_pmap_width = target_width; 716 int new_pmap_width = target_width;
758 int new_pmap_height = target_height; 717 int new_pmap_height = target_height;
759 718
760 int x = 0; 719 int x = 0;
761 int y = 0; 720 int y = 0;
762 int w = 0; 721 int w = 0;
763 int h = 0; 722 int h = 0;
764 723
765 get_image_geometry (image_width, image_height, w, h, x, y); 724 get_image_geometry (image_width, image_height, w, h, x, y);
766 725
767 if (!(flags & rootAlign) 726 if (!(bg_flags & BG_ROOT_ALIGN)
768 && (x >= target_width 727 && (x >= target_width
769 || y >= target_height 728 || y >= target_height
770 || (x + w <= 0) 729 || x + w <= 0
771 || (y + h <= 0))) 730 || y + h <= 0))
772 return false; 731 return false;
773 732
774 result = pixbuf; 733 result = pixbuf;
775 734
776 if ((w != image_width) 735 if (w != image_width
777 || (h != image_height)) 736 || h != image_height)
778 { 737 {
779 result = gdk_pixbuf_scale_simple (pixbuf, 738 result = gdk_pixbuf_scale_simple (pixbuf,
780 w, h, 739 w, h,
781 GDK_INTERP_BILINEAR); 740 GDK_INTERP_BILINEAR);
782 } 741 }
783 742
743 if (!result)
744 return false;
745
784 bool ret = false; 746 bool ret = false;
785 747
786 if (result)
787 {
788 XGCValues gcv; 748 XGCValues gcv;
789 GC gc; 749 GC gc;
790 Pixmap root_pmap; 750 Pixmap root_pmap;
791 751
792 image_width = gdk_pixbuf_get_width (result); 752 image_width = gdk_pixbuf_get_width (result);
793 image_height = gdk_pixbuf_get_height (result); 753 image_height = gdk_pixbuf_get_height (result);
794 754
795 if (background_flags) 755 if (tr_flags)
796 { 756 {
797 root_pmap = pixmap; 757 root_pmap = bg_pixmap;
798 pixmap = None; 758 bg_pixmap = None;
759 }
760 else
761 {
762 if (bg_flags & BG_TILE)
799 } 763 {
800 else
801 {
802 if (h_scale == 0 || v_scale == 0)
803 {
804 new_pmap_width = min (image_width, target_width); 764 new_pmap_width = min (image_width, target_width);
805 new_pmap_height = min (image_height, target_height); 765 new_pmap_height = min (image_height, target_height);
806 } 766 }
807 } 767 }
808 768
809 if (pixmap == None 769 if (bg_pixmap == None
810 || pmap_width != new_pmap_width 770 || bg_pmap_width != new_pmap_width
811 || pmap_height != new_pmap_height 771 || bg_pmap_height != new_pmap_height)
812 || pmap_depth != target->depth) 772 {
813 {
814 if (pixmap) 773 if (bg_pixmap)
815 XFreePixmap (target->dpy, pixmap); 774 XFreePixmap (dpy, bg_pixmap);
816 pixmap = XCreatePixmap (target->dpy, target->vt, new_pmap_width, new_pmap_height, target->depth); 775 bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth);
817 pmap_width = new_pmap_width; 776 bg_pmap_width = new_pmap_width;
818 pmap_height = new_pmap_height; 777 bg_pmap_height = new_pmap_height;
819 pmap_depth = target->depth; 778 }
779
780 gcv.foreground = pix_colors[Color_bg];
781 gc = XCreateGC (dpy, vt, GCForeground, &gcv);
782
783 if (gc)
784 {
785 if (bg_flags & BG_TILE)
820 } 786 {
821
822 gcv.foreground = target->pix_colors[Color_bg];
823 gc = XCreateGC (target->dpy, target->vt, GCForeground, &gcv);
824
825 if (h_scale == 0 || v_scale == 0)
826 {
827 Pixmap tile = XCreatePixmap (target->dpy, target->vt, image_width, image_height, target->depth); 787 Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, depth);
828 pixbuf_to_pixmap (result, tile, gc, 788 pixbuf_to_pixmap (result, tile, gc,
829 0, 0, 789 0, 0,
830 0, 0, 790 0, 0,
831 image_width, image_height); 791 image_width, image_height);
832 792
833 gcv.tile = tile; 793 gcv.tile = tile;
834 gcv.fill_style = FillTiled; 794 gcv.fill_style = FillTiled;
835 gcv.ts_x_origin = x; 795 gcv.ts_x_origin = x;
836 gcv.ts_y_origin = y; 796 gcv.ts_y_origin = y;
837 XChangeGC (target->dpy, gc, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv); 797 XChangeGC (dpy, gc, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv);
838 798
839 XFillRectangle (target->dpy, pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); 799 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height);
840 XFreePixmap (target->dpy, tile); 800 XFreePixmap (dpy, tile);
841 } 801 }
842 else 802 else
843 { 803 {
844 int src_x, src_y, dst_x, dst_y; 804 int src_x, src_y, dst_x, dst_y;
845 int dst_width, dst_height; 805 int dst_width, dst_height;
848 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);
849 809
850 if (dst_x > 0 || dst_y > 0 810 if (dst_x > 0 || dst_y > 0
851 || dst_x + dst_width < new_pmap_width 811 || dst_x + dst_width < new_pmap_width
852 || dst_y + dst_height < new_pmap_height) 812 || dst_y + dst_height < new_pmap_height)
853 XFillRectangle (target->dpy, pixmap, gc, 0, 0, new_pmap_width, new_pmap_height); 813 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height);
854 814
855 if (dst_x < new_pmap_width && dst_y < new_pmap_height) 815 if (dst_x < new_pmap_width && dst_y < new_pmap_height)
856 pixbuf_to_pixmap (result, pixmap, gc, 816 pixbuf_to_pixmap (result, bg_pixmap, gc,
857 src_x, src_y, 817 src_x, src_y,
858 dst_x, dst_y, 818 dst_x, dst_y,
859 dst_width, dst_height); 819 dst_width, dst_height);
860 } 820 }
861 821
862#if XRENDER 822#if XRENDER
863 if (background_flags) 823 if (tr_flags)
864 { 824 {
865 Display *dpy = target->dpy;
866 XRenderPictureAttributes pa;
867
868 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, target->visual); 825 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
826
869 Picture src = XRenderCreatePicture (dpy, root_pmap, src_format, 0, &pa); 827 Picture src = XRenderCreatePicture (dpy, root_pmap, format, 0, 0);
870 828
871 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, target->visual);
872 Picture dst = XRenderCreatePicture (dpy, pixmap, dst_format, 0, &pa); 829 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, format, 0, 0);
873 830
874 pa.repeat = True; 831 Picture mask = create_xrender_mask (dpy, vt, False, False);
875 Pixmap mask_pmap = XCreatePixmap (dpy, target->vt, 1, 1, 8);
876 XRenderPictFormat *mask_format = XRenderFindStandardFormat (dpy, PictStandardA8);
877 Picture mask = XRenderCreatePicture (dpy, mask_pmap, mask_format, CPRepeat, &pa);
878 XFreePixmap (dpy, mask_pmap);
879 832
880 if (src && dst && mask)
881 {
882 XRenderColor mask_c; 833 XRenderColor mask_c;
883 834
884 mask_c.alpha = 0x8000; 835 mask_c.alpha = 0x8000;
885 mask_c.red = 0; 836 mask_c.red =
886 mask_c.green = 0; 837 mask_c.green =
887 mask_c.blue = 0; 838 mask_c.blue = 0;
888 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); 839 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
840
889 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);
890 }
891 842
892 XRenderFreePicture (dpy, src); 843 XRenderFreePicture (dpy, src);
893 XRenderFreePicture (dpy, dst); 844 XRenderFreePicture (dpy, dst);
894 XRenderFreePicture (dpy, mask); 845 XRenderFreePicture (dpy, mask);
895
896 XFreePixmap (dpy, root_pmap);
897 } 846 }
898#endif 847#endif
899 848
900 if (result != pixbuf)
901 g_object_unref (result);
902
903 XFreeGC (target->dpy, gc); 849 XFreeGC (dpy, gc);
904 850
905 ret = true; 851 ret = true;
906 } 852 }
907 853
854 if (result != pixbuf)
855 g_object_unref (result);
856
857 if (tr_flags)
858 XFreePixmap (dpy, root_pmap);
859
908 return ret; 860 return ret;
909} 861}
910# endif /* HAVE_PIXBUF */ 862# endif /* HAVE_PIXBUF */
911 863
912bool 864bool
913bgPixmap_t::set_file (const char *file) 865rxvt_term::bg_set_file (const char *file)
914{ 866{
915 if (!file || !*file) 867 if (!file || !*file)
916 return false; 868 return false;
917 869
870 bool ret = false;
918 if (const char *p = strchr (file, ';')) 871 const char *p = strchr (file, ';');
872
873 if (p)
919 { 874 {
920 size_t len = p - file; 875 size_t len = p - file;
921 char *f = rxvt_temp_buf<char> (len + 1); 876 char *f = rxvt_temp_buf<char> (len + 1);
922 memcpy (f, file, len); 877 memcpy (f, file, len);
923 f[len] = '\0'; 878 f[len] = '\0';
924 file = f; 879 file = f;
925 } 880 }
926 881
927# ifdef HAVE_AFTERIMAGE 882# ifdef HAVE_AFTERIMAGE
928 if (!target->asimman) 883 if (!asimman)
929 target->asimman = create_generic_imageman (target->rs[Rs_path]); 884 asimman = create_generic_imageman (rs[Rs_path]);
930 ASImage *image = get_asimage (target->asimman, file, 0xFFFFFFFF, 100); 885 ASImage *image = get_asimage (asimman, file, 0xFFFFFFFF, 100);
931 if (image) 886 if (image)
932 { 887 {
933 if (original_asim) 888 if (original_asim)
934 safe_asimage_destroy (original_asim); 889 safe_asimage_destroy (original_asim);
935 original_asim = image; 890 original_asim = image;
936 flags |= CLIENT_RENDER; 891 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER;
937 have_image = true;
938 return true; 892 ret = true;
939 } 893 }
940# endif 894# endif
941 895
942# ifdef HAVE_PIXBUF 896# ifdef HAVE_PIXBUF
943 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL); 897 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL);
944 if (image) 898 if (image)
945 { 899 {
946 if (pixbuf) 900 if (pixbuf)
947 g_object_unref (pixbuf); 901 g_object_unref (pixbuf);
948 pixbuf = image; 902 pixbuf = image;
949 have_image = true; 903 bg_flags |= BG_IS_FROM_FILE;
950 return true; 904 ret = true;
951 } 905 }
952# endif 906# endif
953 907
908 if (ret)
909 {
910 if (p)
911 bg_set_geometry (p + 1);
912 else
913 bg_set_default_geometry ();
914 }
915
954 return false; 916 return ret;
955} 917}
956 918
957# endif /* BG_IMAGE_FROM_FILE */ 919# endif /* BG_IMAGE_FROM_FILE */
958 920
959# ifdef ENABLE_TRANSPARENCY 921# ifdef ENABLE_TRANSPARENCY
960bool 922bool
961bgPixmap_t::set_transparent () 923rxvt_term::bg_set_transparent ()
962{ 924{
963 if (!(flags & isTransparent)) 925 if (!(bg_flags & BG_IS_TRANSPARENT))
964 { 926 {
965 flags |= isTransparent; 927 bg_flags |= BG_IS_TRANSPARENT;
966 return true; 928 return true;
967 } 929 }
968 930
969 return false; 931 return false;
970} 932}
971 933
972bool 934bool
973bgPixmap_t::set_blur_radius (const char *geom) 935rxvt_term::bg_set_blur (const char *geom)
974{ 936{
975 bool changed = false; 937 bool changed = false;
976 unsigned int hr, vr; 938 unsigned int hr, vr;
977 int junk; 939 int junk;
978 int geom_flags = XParseGeometry (geom, &junk, &junk, &hr, &vr); 940 int geom_flags = XParseGeometry (geom, &junk, &junk, &hr, &vr);
995 { 957 {
996 changed = true; 958 changed = true;
997 v_blurRadius = vr; 959 v_blurRadius = vr;
998 } 960 }
999 961
1000 if (v_blurRadius == 0 && h_blurRadius == 0) 962 if (h_blurRadius == 0 || v_blurRadius == 0)
1001 flags &= ~blurNeeded; 963 bg_flags &= ~BG_NEEDS_BLUR;
1002 else 964 else
1003 flags |= blurNeeded; 965 bg_flags |= BG_NEEDS_BLUR;
1004 966
1005 return changed; 967 return changed;
1006} 968}
1007 969
1008static inline unsigned long 970void
1009compute_tint_shade_flags (rxvt_color *tint, int shade) 971rxvt_term::set_tint_shade_flags ()
1010{ 972{
1011 unsigned long flags = 0; 973 rgba c;
1012 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
1013 bool has_shade = shade != 100; 974 bool has_shade = shade != 100;
1014 975
1015 if (tint) 976 bg_flags &= ~BG_TINT_FLAGS;
977
978 if (bg_flags & BG_TINT_SET)
1016 { 979 {
1017 tint->get (c); 980 tint.get (c);
1018# define IS_COMPONENT_WHOLESOME(cmp) ((cmp) <= 0x00ff || (cmp) >= 0xff00)
1019 if (!has_shade 981 if (!has_shade
1020 && IS_COMPONENT_WHOLESOME (c.r) 982 && (c.r <= 0x00ff || c.r >= 0xff00)
1021 && IS_COMPONENT_WHOLESOME (c.g) 983 && (c.g <= 0x00ff || c.g >= 0xff00)
1022 && IS_COMPONENT_WHOLESOME (c.b)) 984 && (c.b <= 0x00ff || c.b >= 0xff00))
1023 flags |= bgPixmap_t::tintWholesome; 985 bg_flags |= BG_TINT_BITAND;
1024# undef IS_COMPONENT_WHOLESOME
1025 } 986 }
1026 987
1027 if (has_shade || tint) 988 if (has_shade || (bg_flags & BG_TINT_SET))
1028 flags |= bgPixmap_t::tintNeeded; 989 bg_flags |= BG_NEEDS_TINT;
1029
1030 return flags;
1031} 990}
1032 991
1033bool 992bool
1034bgPixmap_t::set_tint (rxvt_color &new_tint) 993rxvt_term::bg_set_tint (rxvt_color &new_tint)
1035{ 994{
1036 if (!(flags & tintSet) || tint != new_tint) 995 if (!(bg_flags & BG_TINT_SET) || tint != new_tint)
1037 { 996 {
1038 unsigned long new_flags = compute_tint_shade_flags (&new_tint, shade);
1039 tint = new_tint; 997 tint = new_tint;
1040 flags = (flags & ~tintFlags) | new_flags | tintSet; 998 bg_flags |= BG_TINT_SET;
999 set_tint_shade_flags ();
1041 return true; 1000 return true;
1042 } 1001 }
1043 1002
1044 return false; 1003 return false;
1045} 1004}
1046 1005
1047bool 1006bool
1048bgPixmap_t::set_shade (const char *shade_str) 1007rxvt_term::bg_set_shade (const char *shade_str)
1049{ 1008{
1050 int new_shade = (shade_str) ? atoi (shade_str) : 100; 1009 int new_shade = atoi (shade_str);
1051 1010
1052 clamp_it (new_shade, -100, 200); 1011 clamp_it (new_shade, -100, 200);
1053 if (new_shade < 0) 1012 if (new_shade < 0)
1054 new_shade = 200 - (100 + new_shade); 1013 new_shade = 200 - (100 + new_shade);
1055 1014
1056 if (new_shade != shade) 1015 if (new_shade != shade)
1057 { 1016 {
1058 unsigned long new_flags = compute_tint_shade_flags ((flags & tintSet) ? &tint : NULL, new_shade);
1059 shade = new_shade; 1017 shade = new_shade;
1060 flags = (flags & (~tintFlags | tintSet)) | new_flags; 1018 set_tint_shade_flags ();
1061 return true; 1019 return true;
1062 } 1020 }
1063 1021
1064 return false; 1022 return false;
1065} 1023}
1086 params[i+2] = XDoubleToFixed (kernel[i] / sum); 1044 params[i+2] = XDoubleToFixed (kernel[i] / sum);
1087} 1045}
1088#endif 1046#endif
1089 1047
1090bool 1048bool
1091bgPixmap_t::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height) 1049rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height)
1092{ 1050{
1093 bool ret = false; 1051 bool ret = false;
1094#if XRENDER 1052#if XRENDER
1053 if (!(bg_flags & BG_HAS_RENDER_CONV))
1054 return false;
1055
1095 int size = max (h_blurRadius, v_blurRadius) * 2 + 1; 1056 int size = max (h_blurRadius, v_blurRadius) * 2 + 1;
1096 double *kernel = (double *)malloc (size * sizeof (double)); 1057 double *kernel = (double *)malloc (size * sizeof (double));
1097 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 1058 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
1098 1059
1099 Display *dpy = target->dpy;
1100 XRenderPictureAttributes pa;
1101 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1060 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1102 1061
1103 Picture src = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1062 Picture src = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1104 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1063 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1105 1064
1106 if (kernel && params && src && dst) 1065 if (kernel && params)
1107 { 1066 {
1108 if (h_blurRadius)
1109 {
1110 size = h_blurRadius * 2 + 1; 1067 size = h_blurRadius * 2 + 1;
1111 get_gaussian_kernel (h_blurRadius, size, kernel, params); 1068 get_gaussian_kernel (h_blurRadius, size, kernel, params);
1112 1069
1113 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1070 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1114 XRenderComposite (dpy, 1071 XRenderComposite (dpy,
1115 PictOpSrc, 1072 PictOpSrc,
1116 src, 1073 src,
1117 None, 1074 None,
1118 dst, 1075 dst,
1119 0, 0, 1076 0, 0,
1120 0, 0, 1077 0, 0,
1121 0, 0, 1078 0, 0,
1122 width, height); 1079 width, height);
1123 }
1124 1080
1125 if (v_blurRadius)
1126 {
1127 size = v_blurRadius * 2 + 1; 1081 size = v_blurRadius * 2 + 1;
1128 get_gaussian_kernel (v_blurRadius, size, kernel, params); 1082 get_gaussian_kernel (v_blurRadius, size, kernel, params);
1129 swap (params[0], params[1]); 1083 ::swap (params[0], params[1]);
1130 1084
1131 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 1085 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1132 XRenderComposite (dpy, 1086 XRenderComposite (dpy,
1133 PictOpSrc, 1087 PictOpSrc,
1134 src, 1088 src,
1135 None, 1089 None,
1136 dst, 1090 dst,
1137 0, 0, 1091 0, 0,
1138 0, 0, 1092 0, 0,
1139 0, 0, 1093 0, 0,
1140 width, height); 1094 width, height);
1141 }
1142 1095
1143 ret = true; 1096 ret = true;
1144 } 1097 }
1145 1098
1146 free (kernel); 1099 free (kernel);
1150#endif 1103#endif
1151 return ret; 1104 return ret;
1152} 1105}
1153 1106
1154bool 1107bool
1155bgPixmap_t::tint_pixmap (Pixmap pixmap, Visual *visual, int width, int height) 1108rxvt_term::tint_pixmap (Pixmap pixmap, Visual *visual, int width, int height)
1156{ 1109{
1157 Display *dpy = target->dpy;
1158 bool ret = false; 1110 bool ret = false;
1159 1111
1160 if (flags & tintWholesome) 1112 if (bg_flags & BG_TINT_BITAND)
1161 { 1113 {
1162 XGCValues gcv; 1114 XGCValues gcv;
1163 GC gc; 1115 GC gc;
1164 1116
1165 /* In this case we can tint image server-side getting significant 1117 /* In this case we can tint image server-side getting significant
1174 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height); 1126 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height);
1175 ret = true; 1127 ret = true;
1176 XFreeGC (dpy, gc); 1128 XFreeGC (dpy, gc);
1177 } 1129 }
1178 } 1130 }
1179 else
1180 {
1181# if XRENDER 1131# if XRENDER
1132 else if (bg_flags & BG_HAS_RENDER)
1133 {
1182 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); 1134 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1183 1135
1184 if (flags & tintSet) 1136 if (bg_flags & BG_TINT_SET)
1185 tint.get (c); 1137 tint.get (c);
1186 1138
1187 if (shade <= 100) 1139 if (shade <= 100)
1188 { 1140 {
1189 c.r = (c.r * shade) / 100; 1141 c.r = c.r * shade / 100;
1190 c.g = (c.g * shade) / 100; 1142 c.g = c.g * shade / 100;
1191 c.b = (c.b * shade) / 100; 1143 c.b = c.b * shade / 100;
1192 } 1144 }
1193 else 1145 else
1194 { 1146 {
1195 c.r = (c.r * (200 - shade)) / 100; 1147 c.r = c.r * (200 - shade) / 100;
1196 c.g = (c.g * (200 - shade)) / 100; 1148 c.g = c.g * (200 - shade) / 100;
1197 c.b = (c.b * (200 - shade)) / 100; 1149 c.b = c.b * (200 - shade) / 100;
1198 } 1150 }
1199 1151
1200 XRenderPictFormat *solid_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
1201 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 1152 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1202 XRenderPictureAttributes pa;
1203 1153
1204 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 1154 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1205 1155
1206 pa.repeat = True; 1156 Picture overlay_pic = create_xrender_mask (dpy, pixmap, True, False);
1207 1157
1208 Pixmap overlay_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32); 1158 Picture mask_pic = create_xrender_mask (dpy, pixmap, True, True);
1209 Picture overlay_pic = XRenderCreatePicture (dpy, overlay_pmap, solid_format, CPRepeat, &pa);
1210 XFreePixmap (dpy, overlay_pmap);
1211 1159
1212 pa.component_alpha = True;
1213 Pixmap mask_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32);
1214 Picture mask_pic = XRenderCreatePicture (dpy, mask_pmap, solid_format, CPRepeat|CPComponentAlpha, &pa);
1215 XFreePixmap (dpy, mask_pmap);
1216
1217 if (mask_pic && overlay_pic && back_pic)
1218 {
1219 XRenderColor mask_c; 1160 XRenderColor mask_c;
1220 1161
1221 mask_c.red = mask_c.green = mask_c.blue = 0;
1222 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;
1179 mask_c.red =
1180 mask_c.green =
1181 mask_c.blue = 0xffff * (shade - 100) / 100;
1223 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); 1182 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1224 1183
1225 mask_c.alpha = 0;
1226 mask_c.red = 0xffff - c.r;
1227 mask_c.green = 0xffff - c.g;
1228 mask_c.blue = 0xffff - c.b;
1229 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
1230 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1231
1232 if (shade > 100)
1233 {
1234 mask_c.red = mask_c.green = mask_c.blue = 0xffff * (shade - 100) / 100;
1235 mask_c.alpha = 0;
1236 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1237
1238 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);
1239 } 1185 }
1240 1186
1241 ret = true; 1187 ret = true;
1242 }
1243 1188
1244 XRenderFreePicture (dpy, mask_pic); 1189 XRenderFreePicture (dpy, mask_pic);
1245 XRenderFreePicture (dpy, overlay_pic); 1190 XRenderFreePicture (dpy, overlay_pic);
1246 XRenderFreePicture (dpy, back_pic); 1191 XRenderFreePicture (dpy, back_pic);
1192 }
1247# endif 1193# endif
1248 }
1249 1194
1250 return ret; 1195 return ret;
1251} 1196}
1252 1197
1253/* make_transparency_pixmap() 1198/*
1254 * Builds a pixmap of the same size as the terminal window that contains 1199 * Builds a pixmap of the same size as the terminal window that contains
1255 * the tiled portion of the root pixmap that is supposed to be covered by 1200 * the tiled portion of the root pixmap that is supposed to be covered by
1256 * our window. 1201 * our window.
1257 */ 1202 */
1258unsigned long 1203unsigned long
1259bgPixmap_t::make_transparency_pixmap () 1204rxvt_term::make_transparency_pixmap ()
1260{ 1205{
1261 unsigned long result = 0; 1206 unsigned long result = 0;
1262
1263 if (target == NULL)
1264 return 0;
1265 1207
1266 /* root dimensions may change from call to call - but Display structure should 1208 /* root dimensions may change from call to call - but Display structure should
1267 * be always up-to-date, so let's use it : 1209 * be always up-to-date, so let's use it :
1268 */ 1210 */
1269 int screen = target->display->screen; 1211 int screen = display->screen;
1270 Display *dpy = target->dpy;
1271 int root_depth = DefaultDepth (dpy, screen); 1212 int root_depth = DefaultDepth (dpy, screen);
1272 int root_width = DisplayWidth (dpy, screen); 1213 int root_width = DisplayWidth (dpy, screen);
1273 int root_height = DisplayHeight (dpy, screen); 1214 int root_height = DisplayHeight (dpy, screen);
1274 unsigned int root_pmap_width, root_pmap_height; 1215 unsigned int root_pmap_width, root_pmap_height;
1275 int window_width = target->szHint.width; 1216 int window_width = szHint.width;
1276 int window_height = target->szHint.height; 1217 int window_height = szHint.height;
1277 int sx, sy; 1218 int sx, sy;
1278 XGCValues gcv; 1219 XGCValues gcv;
1279 GC gc; 1220 GC gc;
1280 1221
1281 sx = target_x; 1222 sx = target_x;
1291 { 1232 {
1292 Window wdummy; 1233 Window wdummy;
1293 int idummy; 1234 int idummy;
1294 unsigned int udummy; 1235 unsigned int udummy;
1295 1236
1296 target->allowedxerror = -1; 1237 allowedxerror = -1;
1297 1238
1298 if (!XGetGeometry (dpy, root_pixmap, &wdummy, &idummy, &idummy, &root_pmap_width, &root_pmap_height, &udummy, &udummy)) 1239 if (!XGetGeometry (dpy, root_pixmap, &wdummy, &idummy, &idummy, &root_pmap_width, &root_pmap_height, &udummy, &udummy))
1299 root_pixmap = None; 1240 root_pixmap = None;
1300 1241
1301 target->allowedxerror = 0; 1242 allowedxerror = 0;
1302 } 1243 }
1303 1244
1304 Pixmap recoded_root_pmap = root_pixmap; 1245 Pixmap recoded_root_pmap = root_pixmap;
1305 1246
1306 if (root_pixmap != None && root_depth != target->depth) 1247 if (root_pixmap != None && root_depth != depth)
1307 { 1248 {
1308#if XRENDER 1249#if XRENDER
1309 if (flags & HAS_RENDER) 1250 if (bg_flags & BG_HAS_RENDER)
1310 { 1251 {
1311 XRenderPictureAttributes pa; 1252 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth);
1312 1253
1313 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen)); 1254 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
1314 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, &pa); 1255 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, 0);
1315 1256
1316 recoded_root_pmap = XCreatePixmap (dpy, target->vt, root_pmap_width, root_pmap_height, target->depth);
1317 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, target->visual); 1257 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
1318 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, &pa); 1258 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, 0);
1319 1259
1320 if (src && dst)
1321 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);
1322 else
1323 {
1324 XFreePixmap (dpy, recoded_root_pmap);
1325 root_pixmap = None;
1326 }
1327 1261
1328 XRenderFreePicture (dpy, src); 1262 XRenderFreePicture (dpy, src);
1329 XRenderFreePicture (dpy, dst); 1263 XRenderFreePicture (dpy, dst);
1330 } 1264 }
1331 else 1265 else
1332#endif 1266#endif
1333 root_pixmap = None; 1267 recoded_root_pmap = None;
1334 } 1268 }
1335 1269
1336 if (root_pixmap == None) 1270 if (recoded_root_pmap == None)
1337 return 0; 1271 return 0;
1338 1272
1273 if (bg_pixmap == None
1274 || bg_pmap_width != window_width
1275 || bg_pmap_height != window_height)
1276 {
1277 if (bg_pixmap)
1278 XFreePixmap (dpy, bg_pixmap);
1339 Pixmap tiled_root_pmap = XCreatePixmap (dpy, target->vt, window_width, window_height, target->depth); 1279 bg_pixmap = XCreatePixmap (dpy, vt, window_width, window_height, depth);
1340 1280 bg_pmap_width = window_width;
1341 if (tiled_root_pmap == None) /* something really bad happened - abort */ 1281 bg_pmap_height = window_height;
1342 return 0; 1282 }
1343 1283
1344 /* straightforward pixmap copy */ 1284 /* straightforward pixmap copy */
1345 while (sx < 0) sx += (int)root_width; 1285 while (sx < 0) sx += root_pmap_width;
1346 while (sy < 0) sy += (int)root_height; 1286 while (sy < 0) sy += root_pmap_height;
1347 1287
1348 gcv.tile = recoded_root_pmap; 1288 gcv.tile = recoded_root_pmap;
1349 gcv.fill_style = FillTiled; 1289 gcv.fill_style = FillTiled;
1350 gcv.ts_x_origin = -sx; 1290 gcv.ts_x_origin = -sx;
1351 gcv.ts_y_origin = -sy; 1291 gcv.ts_y_origin = -sy;
1352 gc = XCreateGC (dpy, target->vt, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv); 1292 gc = XCreateGC (dpy, vt, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv);
1353 1293
1354 if (gc) 1294 if (gc)
1355 { 1295 {
1356 XFillRectangle (dpy, tiled_root_pmap, gc, 0, 0, window_width, window_height); 1296 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height);
1357 result |= transpPmapTiled; 1297 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS);
1298
1299 if (!(bg_flags & BG_CLIENT_RENDER))
1300 {
1301 if (bg_flags & BG_NEEDS_BLUR)
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)
1316 {
1317 /* our own client-side tinting */
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 }
1323 }
1324# endif
1325 } /* server side rendering completed */
1326
1358 XFreeGC (dpy, gc); 1327 XFreeGC (dpy, gc);
1359
1360 if (!(flags & CLIENT_RENDER))
1361 {
1362 if ((flags & blurNeeded)
1363 && (flags & HAS_RENDER_CONV))
1364 {
1365 if (blur_pixmap (tiled_root_pmap, target->visual, window_width, window_height))
1366 result |= transpPmapBlurred;
1367 }
1368 if ((flags & tintNeeded)
1369 && (flags & (tintWholesome | HAS_RENDER)))
1370 {
1371 if (tint_pixmap (tiled_root_pmap, target->visual, window_width, window_height))
1372 result |= transpPmapTinted;
1373 }
1374 } /* server side rendering completed */
1375
1376 if (pixmap)
1377 XFreePixmap (dpy, pixmap);
1378
1379 pixmap = tiled_root_pmap;
1380 pmap_width = window_width;
1381 pmap_height = window_height;
1382 pmap_depth = target->depth;
1383 } 1328 }
1384 else
1385 XFreePixmap (dpy, tiled_root_pmap);
1386 1329
1387 if (recoded_root_pmap != root_pixmap) 1330 if (recoded_root_pmap != root_pixmap)
1388 XFreePixmap (dpy, recoded_root_pmap); 1331 XFreePixmap (dpy, recoded_root_pmap);
1389 1332
1390 return result; 1333 return result;
1391} 1334}
1392 1335
1393void 1336void
1394bgPixmap_t::set_root_pixmap () 1337rxvt_term::bg_set_root_pixmap ()
1395{ 1338{
1396 Pixmap new_root_pixmap = target->get_pixmap_property (target->xa[XA_XROOTPMAP_ID]); 1339 Pixmap new_root_pixmap = get_pixmap_property (xa[XA_XROOTPMAP_ID]);
1397 if (new_root_pixmap == None) 1340 if (new_root_pixmap == None)
1398 new_root_pixmap = target->get_pixmap_property (target->xa[XA_ESETROOT_PMAP_ID]); 1341 new_root_pixmap = get_pixmap_property (xa[XA_ESETROOT_PMAP_ID]);
1399 1342
1400 root_pixmap = new_root_pixmap; 1343 root_pixmap = new_root_pixmap;
1401} 1344}
1402# endif /* ENABLE_TRANSPARENCY */ 1345# endif /* ENABLE_TRANSPARENCY */
1403 1346
1404#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) 1347bool
1405static void shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c); 1348rxvt_term::bg_render ()
1349{
1350 unsigned long tr_flags = 0;
1351
1352 bg_invalidate ();
1353# ifdef ENABLE_TRANSPARENCY
1354 if (bg_flags & BG_IS_TRANSPARENT)
1355 {
1356 /* we need to re-generate transparency pixmap in that case ! */
1357 tr_flags = make_transparency_pixmap ();
1358 if (tr_flags == 0)
1359 return false;
1360 bg_flags |= BG_IS_VALID;
1361 }
1406# endif 1362# endif
1407 1363
1408bool 1364# ifdef BG_IMAGE_FROM_FILE
1409bgPixmap_t::render () 1365 if ((bg_flags & BG_IS_FROM_FILE)
1410{ 1366 || (tr_flags & BG_EFFECTS_FLAGS))
1411 unsigned long background_flags = 0;
1412
1413 if (target == NULL)
1414 return false;
1415
1416 invalidate ();
1417# ifdef ENABLE_TRANSPARENCY
1418 if (flags & isTransparent)
1419 { 1367 {
1420 /* we need to re-generate transparency pixmap in that case ! */ 1368 if (render_image (tr_flags))
1421 background_flags = make_transparency_pixmap (); 1369 bg_flags |= BG_IS_VALID;
1422 if (background_flags == 0)
1423 return false;
1424 else if ((background_flags & transpTransformations) == (flags & transpTransformations))
1425 flags &= ~isInvalid;
1426 } 1370 }
1427# endif 1371# endif
1428 1372
1429# ifdef BG_IMAGE_FROM_FILE 1373 if (!(bg_flags & BG_IS_VALID))
1430 if (have_image
1431 || (background_flags & transpTransformations) != (flags & transpTransformations))
1432 {
1433 if (render_image (background_flags))
1434 flags &= ~isInvalid;
1435 } 1374 {
1436# endif
1437
1438# if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1439 XImage *result = NULL;
1440
1441 if (background_flags && (flags & isInvalid))
1442 {
1443 result = XGetImage (target->dpy, pixmap, 0, 0, pmap_width, pmap_height, AllPlanes, ZPixmap);
1444 }
1445
1446 if (result)
1447 {
1448 /* our own client-side tinting */
1449 if (!(background_flags & transpPmapTinted) && (flags & tintNeeded))
1450 {
1451 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
1452 if (flags & tintSet)
1453 tint.get (c);
1454 shade_ximage (DefaultVisual (target->dpy, target->display->screen), result, shade, c);
1455 }
1456
1457 GC gc = XCreateGC (target->dpy, target->vt, 0UL, NULL);
1458
1459 if (gc)
1460 {
1461 XPutImage (target->dpy, pixmap, gc, result, 0, 0, 0, 0, result->width, result->height);
1462
1463 XFreeGC (target->dpy, gc);
1464 flags &= ~isInvalid;
1465 }
1466
1467 XDestroyImage (result);
1468 }
1469# endif
1470
1471 if (flags & isInvalid)
1472 {
1473 if (pixmap != None) 1375 if (bg_pixmap != None)
1474 { 1376 {
1475 XFreePixmap (target->dpy, pixmap); 1377 XFreePixmap (dpy, bg_pixmap);
1476 pixmap = None; 1378 bg_pixmap = None;
1477 } 1379 }
1478 } 1380 }
1479 1381
1480 apply (); 1382 scr_recolour (false);
1383 bg_flags |= BG_NEEDS_REFRESH;
1481 1384
1482 valid_since = ev::now (); 1385 bg_valid_since = ev::now ();
1483 1386
1484 return true; 1387 return true;
1485} 1388}
1486 1389
1487void 1390void
1488bgPixmap_t::set_target (rxvt_term *new_target) 1391rxvt_term::bg_init ()
1489{ 1392{
1490 target = new_target; 1393#ifdef ENABLE_TRANSPARENCY
1394 shade = 100;
1395#endif
1491 1396
1492 flags &= ~(HAS_RENDER | HAS_RENDER_CONV); 1397 bg_flags &= ~(BG_HAS_RENDER | BG_HAS_RENDER_CONV);
1493#if XRENDER 1398#if XRENDER
1494 int major, minor; 1399 int major, minor;
1495 if (XRenderQueryVersion (target->dpy, &major, &minor)) 1400 if (XRenderQueryVersion (dpy, &major, &minor))
1496 flags |= HAS_RENDER; 1401 bg_flags |= BG_HAS_RENDER;
1497 XFilters *filters = XRenderQueryFilters (target->dpy, target->vt); 1402 XFilters *filters = XRenderQueryFilters (dpy, vt);
1498 if (filters) 1403 if (filters)
1499 { 1404 {
1500 for (int i = 0; i < filters->nfilter; i++) 1405 for (int i = 0; i < filters->nfilter; i++)
1501 if (!strcmp (filters->filter[i], FilterConvolution)) 1406 if (!strcmp (filters->filter[i], FilterConvolution))
1502 flags |= HAS_RENDER_CONV; 1407 bg_flags |= BG_HAS_RENDER_CONV;
1503 1408
1504 XFree (filters); 1409 XFree (filters);
1505 } 1410 }
1506#endif 1411#endif
1507} 1412}
1508 1413
1414#endif /* HAVE_BG_PIXMAP */
1415
1416#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1417/* based on code from aterm-0.4.2 */
1418
1419static inline void
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
1509void 1431void
1510bgPixmap_t::apply () 1432rxvt_term::tint_ximage (Visual *visual, XImage *ximage)
1511{
1512 if (target == NULL)
1513 return;
1514
1515 if (pixmap != None)
1516 {
1517 /* set target's background to pixmap */
1518# ifdef ENABLE_TRANSPARENCY
1519 if (flags & isTransparent)
1520 {
1521 XSetWindowBackgroundPixmap (target->dpy, target->parent[0], pixmap);
1522 XSetWindowBackgroundPixmap (target->dpy, target->vt, ParentRelative);
1523
1524 if (target->scrollBar.win)
1525 XSetWindowBackgroundPixmap (target->dpy, target->scrollBar.win, ParentRelative);
1526 }
1527 else
1528# endif
1529 {
1530 /* force old pixmap dereference in case it was transparent before :*/
1531 XSetWindowBackground (target->dpy, target->parent[0], target->pix_colors[Color_border]);
1532 XSetWindowBackgroundPixmap (target->dpy, target->vt, pixmap);
1533 /* do we also need to set scrollbar's background here ? */
1534
1535 if (target->scrollBar.win)
1536 XSetWindowBackground (target->dpy, target->scrollBar.win, target->pix_colors[Color_border]);
1537 }
1538 }
1539 else
1540 {
1541 /* set target background to a pixel */
1542 XSetWindowBackground (target->dpy, target->parent[0], target->pix_colors[Color_border]);
1543 XSetWindowBackground (target->dpy, target->vt, target->pix_colors[Color_bg]);
1544 /* do we also need to set scrollbar's background here ? */
1545 if (target->scrollBar.win)
1546 XSetWindowBackground (target->dpy, target->scrollBar.win, target->pix_colors[Color_border]);
1547 }
1548
1549 /* don't want Expose on the parent or vt. It is better to use
1550 scr_touch or we get a great deal of flicker otherwise: */
1551 XClearWindow (target->dpy, target->parent[0]);
1552
1553 if (target->scrollBar.state && target->scrollBar.win)
1554 {
1555 target->scrollBar.state = STATE_IDLE;
1556 target->scrollBar.show (0);
1557 }
1558
1559 target->want_refresh = 1;
1560 flags |= hasChanged;
1561}
1562
1563#endif /* HAVE_BG_PIXMAP */
1564
1565#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1566/* taken from aterm-0.4.2 */
1567
1568static void
1569shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c)
1570{ 1433{
1571 int sh_r, sh_g, sh_b; 1434 int sh_r, sh_g, sh_b;
1572 uint32_t mask_r, mask_g, mask_b; 1435 uint32_t mask_r, mask_g, mask_b;
1573 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; 1436 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b;
1574 rgba low; 1437 unsigned short low;
1575 rgba high;
1576 int i;
1577 int host_byte_order = byteorder::big_endian () ? MSBFirst : LSBFirst; 1438 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
1578 1439
1579 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return; 1440 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return;
1580 1441
1581 /* for convenience */ 1442 /* for convenience */
1582 mask_r = visual->red_mask; 1443 mask_r = visual->red_mask;
1640 break; 1501 break;
1641 default: 1502 default:
1642 return; /* we do not support this color depth */ 1503 return; /* we do not support this color depth */
1643 } 1504 }
1644 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
1645 /* prepare limits for color transformation (each channel is handled separately) */ 1511 /* prepare limits for color transformation (each channel is handled separately) */
1646 if (shade > 100) 1512 if (shade > 100)
1647 { 1513 {
1648 shade = 200 - shade;
1649
1650 high.r = c.r * shade / 100;
1651 high.g = c.g * shade / 100;
1652 high.b = c.b * shade / 100;
1653
1654 low.r = 65535 * (100 - shade) / 100; 1514 c.r = c.r * (200 - shade) / 100;
1655 low.g = 65535 * (100 - shade) / 100; 1515 c.g = c.g * (200 - shade) / 100;
1656 low.b = 65535 * (100 - shade) / 100; 1516 c.b = c.b * (200 - shade) / 100;
1517
1518 low = 0xffff * (shade - 100) / 100;
1657 } 1519 }
1658 else 1520 else
1659 { 1521 {
1660 high.r = c.r * shade / 100; 1522 c.r = c.r * shade / 100;
1661 high.g = c.g * shade / 100; 1523 c.g = c.g * shade / 100;
1662 high.b = c.b * shade / 100; 1524 c.b = c.b * shade / 100;
1663 1525
1664 low.r = low.g = low.b = 0; 1526 low = 0;
1665 } 1527 }
1666 1528
1667 /* fill our lookup tables */ 1529 /* fill our lookup tables */
1668 for (i = 0; i <= mask_r>>sh_r; i++) 1530 fill_lut (lookup_r, mask_r, sh_r, low, c.r);
1669 { 1531 fill_lut (lookup_g, mask_g, sh_g, low, c.g);
1670 uint32_t tmp; 1532 fill_lut (lookup_b, mask_b, sh_b, low, c.b);
1671 tmp = i * high.r;
1672 tmp += (mask_r>>sh_r) * low.r;
1673 lookup_r[i] = (tmp/65535)<<sh_r;
1674 }
1675 for (i = 0; i <= mask_g>>sh_g; i++)
1676 {
1677 uint32_t tmp;
1678 tmp = i * high.g;
1679 tmp += (mask_g>>sh_g) * low.g;
1680 lookup_g[i] = (tmp/65535)<<sh_g;
1681 }
1682 for (i = 0; i <= mask_b>>sh_b; i++)
1683 {
1684 uint32_t tmp;
1685 tmp = i * high.b;
1686 tmp += (mask_b>>sh_b) * low.b;
1687 lookup_b[i] = (tmp/65535)<<sh_b;
1688 }
1689 1533
1690 /* apply table to input image (replacing colors by newly calculated ones) */ 1534 /* apply table to input image (replacing colors by newly calculated ones) */
1691 if (ximage->bits_per_pixel == 32 1535 if (ximage->bits_per_pixel == 32
1692 && (ximage->depth == 24 || ximage->depth == 32) 1536 && (ximage->depth == 24 || ximage->depth == 32)
1693 && ximage->byte_order == host_byte_order) 1537 && ximage->byte_order == host_byte_order)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines