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.156 by sf-exg, Tue Aug 9 18:41:31 2011 UTC vs.
Revision 1.206 by sf-exg, Thu Apr 12 10:22:50 2012 UTC

20 * You should have received a copy of the GNU General Public License 20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *---------------------------------------------------------------------*/ 23 *---------------------------------------------------------------------*/
24 24
25#include <cmath> 25#include <math.h>
26#include "../config.h" /* NECESSARY */ 26#include "../config.h" /* NECESSARY */
27#include "rxvt.h" /* NECESSARY */ 27#include "rxvt.h" /* NECESSARY */
28 28
29#if XRENDER 29#if XRENDER
30# include <X11/extensions/Xrender.h> 30# include <X11/extensions/Xrender.h>
32 32
33#ifndef FilterConvolution 33#ifndef FilterConvolution
34#define FilterConvolution "convolution" 34#define FilterConvolution "convolution"
35#endif 35#endif
36 36
37/* 37#ifndef RepeatPad
38 * Pixmap geometry string interpretation : 38#define RepeatPad True
39 * Each geometry string contains zero or one scale/position 39#endif
40 * adjustment and may optionally be followed by a colon and one or more
41 * colon-delimited pixmap operations.
42 * The following table shows the valid geometry strings and their
43 * effects on the background image :
44 *
45 * WxH+X+Y Set scaling to W% by H%, and position to X% by Y%.
46 * W and H are percentages of the terminal window size.
47 * X and Y are also percentages; e.g., +50+50 centers
48 * the image in the window.
49 *
50 * Pixmap Operations : (should be prepended by a colon)
51 * tile Tile image. Scaling/position modifiers above will affect
52 * the tile size and origin.
53 * propscale When scaling, scale proportionally. That is, maintain the
54 * proper aspect ratio for the image. Any portion of the
55 * background not covered by the image is filled with the
56 * current background color.
57 * hscale Scale horizontally, tile vertically ?
58 * vscale Tile horizontally, scale vertically ?
59 * scale Scale both up and down
60 * auto Same as 100x100+50+50
61 */
62 40
63#ifdef HAVE_BG_PIXMAP 41#ifdef HAVE_BG_PIXMAP
42# if XRENDER
43static Picture
44create_xrender_mask (Display *dpy, Drawable drawable, Bool argb, Bool component_alpha)
45{
46 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8);
47
48 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8);
49 XRenderPictureAttributes pa;
50 pa.repeat = True;
51 pa.component_alpha = component_alpha;
52 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat | CPComponentAlpha, &pa);
53
54 XFreePixmap (dpy, pixmap);
55
56 return mask;
57}
58# endif
59
64void 60void
65rxvt_term::bg_destroy () 61rxvt_term::bg_destroy ()
66{ 62{
67#ifdef HAVE_AFTERIMAGE
68 if (original_asim)
69 safe_asimage_destroy (original_asim);
70 if (asv)
71 destroy_asvisual (asv, 0);
72 if (asimman)
73 destroy_image_manager (asimman, 0);
74#endif
75
76#ifdef HAVE_PIXBUF 63#ifdef HAVE_PIXBUF
77 if (pixbuf) 64 if (pixbuf)
78 g_object_unref (pixbuf); 65 g_object_unref (pixbuf);
79#endif 66#endif
80 67
133 120
134 return false; 121 return false;
135} 122}
136 123
137# ifdef BG_IMAGE_FROM_FILE 124# ifdef BG_IMAGE_FROM_FILE
138static inline bool
139check_set_scale_value (int geom_flags, int flag, unsigned int &scale, unsigned int new_value)
140{
141 if (geom_flags & flag)
142 {
143 if (new_value > 1000)
144 new_value = 1000;
145 if (new_value != scale)
146 {
147 scale = new_value;
148 return true;
149 }
150 }
151 return false;
152}
153
154static inline bool
155check_set_align_value (int geom_flags, int flag, int &align, int new_value)
156{
157 if (geom_flags & flag)
158 {
159 if (new_value < -100)
160 new_value = -100;
161 else if (new_value > 200)
162 new_value = 200;
163 if (new_value != align)
164 {
165 align = new_value;
166 return true;
167 }
168 }
169 return false;
170}
171
172static inline int 125static inline int
173make_align_position (int align, int window_size, int image_size) 126make_align_position (int align, int window_size, int image_size)
174{ 127{
175 int diff = window_size - image_size;
176 int smaller = min (image_size, window_size);
177
178 if (align >= 0 && align <= 100) 128 if (align >= 0 && align <= 100)
179 return diff * align / 100; 129 return lerp (0, window_size - image_size, align);
180 else if (align > 100 && align <= 200) 130 else if (align > 100)
181 return ((align - 100) * smaller / 100) + window_size - smaller; 131 return lerp (window_size - image_size, window_size, align - 100);
182 else if (align >= -100 && align < 0) 132 else
183 return ((align + 100) * smaller / 100) - image_size; 133 return lerp (-image_size, 0, align + 100);
184 return 0;
185} 134}
186 135
187static inline int 136static inline int
188make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_size) 137make_clip_rectangle (int pos, int size, int target_size, int &dst_pos, int &dst_size)
189{ 138{
195 src_pos = -pos; 144 src_pos = -pos;
196 dst_pos = 0; 145 dst_pos = 0;
197 dst_size += pos; 146 dst_size += pos;
198 } 147 }
199 148
200 if (dst_pos + dst_size > target_size)
201 dst_size = target_size - dst_pos; 149 min_it (dst_size, target_size - dst_pos);
202 return src_pos; 150 return src_pos;
203} 151}
204 152
205bool 153bool
206rxvt_term::bg_set_geometry (const char *geom, bool update) 154rxvt_term::bg_set_geometry (const char *geom, bool update)
207{ 155{
208 bool changed = false; 156 bool changed = false;
209 int geom_flags = 0; 157 int geom_flags = 0;
210 int x = 0, y = 0; 158 int x = h_align;
159 int y = v_align;
211 unsigned int w = 0, h = 0; 160 unsigned int w = h_scale;
212 unsigned int n; 161 unsigned int h = v_scale;
213 unsigned long new_flags = (bg_flags & (~BG_GEOMETRY_FLAGS)); 162 unsigned long new_flags = 0;
214 const char *ops;
215 163
216 if (geom == NULL) 164 if (geom == NULL)
217 return false; 165 return false;
218 166
219 char str[256]; 167 if (geom[0])
220
221 ops = strchr (geom, ':');
222 if (ops == NULL)
223 n = strlen (geom);
224 else
225 n = ops - geom;
226
227 if (n >= sizeof (str))
228 return false;
229
230 memcpy (str, geom, n);
231 str[n] = '\0';
232 rxvt_strtrim (str);
233
234 if (str[0])
235 { 168 {
236 /* we have geometry string - let's handle it prior to applying ops */ 169 char **arr = rxvt_strsplit (':', geom);
170
171 for (int i = 0; arr[i]; i++)
172 {
173 if (!strcasecmp (arr[i], "style=tiled"))
174 {
175 new_flags = BG_TILE;
176 w = h = noScale;
177 x = y = 0;
178 geom_flags = WidthValue|HeightValue|XValue|YValue;
179 }
180 else if (!strcasecmp (arr[i], "style=aspect-stretched"))
181 {
182 new_flags = BG_KEEP_ASPECT;
183 w = h = windowScale;
184 x = y = centerAlign;
185 geom_flags = WidthValue|HeightValue|XValue|YValue;
186 }
187 else if (!strcasecmp (arr[i], "style=stretched"))
188 {
189 new_flags = 0;
190 w = h = windowScale;
191 geom_flags = WidthValue|HeightValue;
192 }
193 else if (!strcasecmp (arr[i], "style=centered"))
194 {
195 new_flags = 0;
196 w = h = noScale;
197 x = y = centerAlign;
198 geom_flags = WidthValue|HeightValue|XValue|YValue;
199 }
200 else if (!strcasecmp (arr[i], "style=root-tiled"))
201 {
202 new_flags = BG_TILE|BG_ROOT_ALIGN;
203 w = h = noScale;
204 geom_flags = WidthValue|HeightValue;
205 }
206 else if (!strcasecmp (arr[i], "op=tile"))
207 new_flags |= BG_TILE;
208 else if (!strcasecmp (arr[i], "op=keep-aspect"))
209 new_flags |= BG_KEEP_ASPECT;
210 else if (!strcasecmp (arr[i], "op=root-align"))
211 new_flags |= BG_ROOT_ALIGN;
212
213 // deprecated
214 else if (!strcasecmp (arr[i], "tile"))
215 {
216 new_flags |= BG_TILE;
217 w = h = noScale;
218 geom_flags |= WidthValue|HeightValue;
219 }
220 else if (!strcasecmp (arr[i], "propscale"))
221 {
222 new_flags |= BG_KEEP_ASPECT;
223 w = h = windowScale;
224 geom_flags |= WidthValue|HeightValue;
225 }
226 else if (!strcasecmp (arr[i], "hscale"))
227 {
228 new_flags |= BG_TILE;
229 w = windowScale;
230 h = noScale;
231 geom_flags |= WidthValue|HeightValue;
232 }
233 else if (!strcasecmp (arr[i], "vscale"))
234 {
235 new_flags |= BG_TILE;
236 h = windowScale;
237 w = noScale;
238 geom_flags |= WidthValue|HeightValue;
239 }
240 else if (!strcasecmp (arr[i], "scale"))
241 {
242 w = h = windowScale;
243 geom_flags |= WidthValue|HeightValue;
244 }
245 else if (!strcasecmp (arr[i], "auto"))
246 {
247 w = h = windowScale;
248 x = y = centerAlign;
249 geom_flags |= WidthValue|HeightValue|XValue|YValue;
250 }
251 else if (!strcasecmp (arr[i], "root"))
252 {
253 new_flags |= BG_TILE|BG_ROOT_ALIGN;
254 w = h = noScale;
255 geom_flags |= WidthValue|HeightValue;
256 }
257
258 else
237 geom_flags = XParseGeometry (str, &x, &y, &w, &h); 259 geom_flags |= XParseGeometry (arr[i], &x, &y, &w, &h);
238 } /* done parsing geometry string */ 260 } /* done parsing ops */
261
262 rxvt_free_strsplit (arr);
263 }
264
265 new_flags |= bg_flags & ~BG_GEOMETRY_FLAGS;
239 266
240 if (!update) 267 if (!update)
241 { 268 {
242 if (!(geom_flags & XValue)) 269 if (!(geom_flags & XValue))
243 x = y = defaultAlign; 270 x = y = defaultAlign;
248 w = h = defaultScale; 275 w = h = defaultScale;
249 else if (!(geom_flags & HeightValue)) 276 else if (!(geom_flags & HeightValue))
250 h = w; 277 h = w;
251 else if (!(geom_flags & WidthValue)) 278 else if (!(geom_flags & WidthValue))
252 w = h; 279 w = h;
253
254 geom_flags |= WidthValue|HeightValue|XValue|YValue;
255 }
256
257 if (ops)
258 { 280 }
259 char **arr = rxvt_strsplit (':', ops + 1);
260 281
261 for (int i = 0; arr[i]; i++) 282 min_it (w, 1000);
262 { 283 min_it (h, 1000);
263 if (!strcasecmp (arr[i], "tile")) 284 clamp_it (x, -100, 200);
264 { 285 clamp_it (y, -100, 200);
265 new_flags |= BG_TILE;
266 w = h = noScale;
267 geom_flags |= WidthValue|HeightValue;
268 }
269 else if (!strcasecmp (arr[i], "propscale"))
270 {
271 new_flags |= BG_PROP_SCALE;
272 }
273 else if (!strcasecmp (arr[i], "hscale"))
274 {
275 if (w == 0) w = windowScale;
276 286
277 h = noScale; 287 if (bg_flags != new_flags
278 geom_flags |= WidthValue|HeightValue; 288 || h_scale != w
279 } 289 || v_scale != h
280 else if (!strcasecmp (arr[i], "vscale")) 290 || h_align != x
281 { 291 || v_align != y)
282 if (h == 0) h = windowScale;
283
284 w = noScale;
285 geom_flags |= WidthValue|HeightValue;
286 }
287 else if (!strcasecmp (arr[i], "scale"))
288 {
289 if (h == 0) h = windowScale;
290 if (w == 0) w = windowScale;
291
292 geom_flags |= WidthValue|HeightValue;
293 }
294 else if (!strcasecmp (arr[i], "auto"))
295 {
296 w = h = windowScale;
297 x = y = centerAlign;
298 geom_flags |= WidthValue|HeightValue|XValue|YValue;
299 }
300 else if (!strcasecmp (arr[i], "root"))
301 {
302 new_flags |= BG_TILE|BG_ROOT_ALIGN;
303 w = h = noScale;
304 geom_flags |= WidthValue|HeightValue;
305 }
306 } /* done parsing ops */
307
308 rxvt_free_strsplit (arr);
309 }
310
311 if (check_set_scale_value (geom_flags, WidthValue, h_scale, w)) changed = true;
312 if (check_set_scale_value (geom_flags, HeightValue, v_scale, h)) changed = true;
313 if (check_set_align_value (geom_flags, XValue, h_align, x)) changed = true;
314 if (check_set_align_value (geom_flags, YValue, v_align, y)) changed = true;
315
316 if (new_flags != bg_flags)
317 { 292 {
318 bg_flags = new_flags; 293 bg_flags = new_flags;
294 h_scale = w;
295 v_scale = h;
296 h_align = x;
297 v_align = y;
319 changed = true; 298 changed = true;
320 } 299 }
321 300
322 return changed; 301 return changed;
323} 302}
326rxvt_term::get_image_geometry (int image_width, int image_height, int &w, int &h, int &x, int &y) 305rxvt_term::get_image_geometry (int image_width, int image_height, int &w, int &h, int &x, int &y)
327{ 306{
328 int target_width = szHint.width; 307 int target_width = szHint.width;
329 int target_height = szHint.height; 308 int target_height = szHint.height;
330 309
310 w = h_scale * target_width / 100;
311 h = v_scale * target_height / 100;
312
331 if (bg_flags & BG_PROP_SCALE) 313 if (bg_flags & BG_KEEP_ASPECT)
332 { 314 {
333 float scale = (float)target_width / image_width; 315 float scale = (float)w / image_width;
334 min_it (scale, (float)target_height / image_height); 316 min_it (scale, (float)h / image_height);
335 w = image_width * scale + 0.5; 317 w = image_width * scale + 0.5;
336 h = image_height * scale + 0.5; 318 h = image_height * scale + 0.5;
337 } 319 }
338 else
339 {
340 w = h_scale * target_width / 100;
341 h = v_scale * target_height / 100;
342 }
343 320
344 if (!w) w = image_width; 321 if (!w) w = image_width;
345 if (!h) h = image_height; 322 if (!h) h = image_height;
346 323
347 if (bg_flags & BG_ROOT_ALIGN) 324 if (bg_flags & BG_ROOT_ALIGN)
353 { 330 {
354 x = make_align_position (h_align, target_width, w); 331 x = make_align_position (h_align, target_width, w);
355 y = make_align_position (v_align, target_height, h); 332 y = make_align_position (v_align, target_height, h);
356 } 333 }
357 334
358 bg_flags &= ~BG_IS_SIZE_SENSITIVE;
359 if (!(bg_flags & BG_TILE) 335 if (!(bg_flags & BG_TILE)
360 || (bg_flags & BG_PROP_SCALE) || h_scale || v_scale 336 || h_scale || v_scale
361 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align)) 337 || (!(bg_flags & BG_ROOT_ALIGN) && (h_align || v_align))
362 || w > target_width || h > target_height) 338 || image_width > target_width || image_height > target_height)
363 bg_flags |= BG_IS_SIZE_SENSITIVE; 339 bg_flags |= BG_IS_SIZE_SENSITIVE;
364}
365
366# ifdef HAVE_AFTERIMAGE
367bool
368rxvt_term::render_image (unsigned long tr_flags)
369{
370 init_asv ();
371
372 ASImage *background = NULL;
373 ARGB32 background_tint = TINT_LEAVE_SAME;
374
375# ifdef ENABLE_TRANSPARENCY
376 if (tr_flags)
377 background = pixmap2ximage (asv, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, 100);
378
379 if (tr_flags & BG_NEEDS_TINT)
380 {
381 ShadingInfo as_shade;
382 as_shade.shading = shade;
383
384 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
385 if (bg_flags & BG_TINT_SET)
386 tint.get (c);
387 as_shade.tintColor.red = c.r;
388 as_shade.tintColor.green = c.g;
389 as_shade.tintColor.blue = c.b;
390
391 background_tint = shading2tint32 (&as_shade);
392 }
393
394 if ((tr_flags & BG_NEEDS_BLUR) && background != NULL)
395 {
396 ASImage *tmp = blur_asimage_gauss (asv, background, h_blurRadius, v_blurRadius, 0xFFFFFFFF,
397 (original_asim == NULL || tint == TINT_LEAVE_SAME) ? ASA_XImage : ASA_ASImage,
398 100, ASIMAGE_QUALITY_DEFAULT);
399 if (tmp)
400 {
401 destroy_asimage (&background);
402 background = tmp;
403 }
404 }
405# endif
406
407 ASImage *result = 0;
408
409 int target_width = szHint.width;
410 int target_height = szHint.height;
411 int new_pmap_width = target_width;
412 int new_pmap_height = target_height;
413
414 int x = 0;
415 int y = 0;
416 int w = 0;
417 int h = 0;
418
419 if (original_asim)
420 get_image_geometry (original_asim->width, original_asim->height, w, h, x, y);
421
422 if (!original_asim
423 || (!(bg_flags & BG_ROOT_ALIGN)
424 && (x >= target_width
425 || y >= target_height
426 || (x + w <= 0)
427 || (y + h <= 0))))
428 {
429 if (background)
430 {
431 new_pmap_width = background->width;
432 new_pmap_height = background->height;
433 result = background;
434
435 if (background_tint != TINT_LEAVE_SAME)
436 {
437 ASImage *tmp = tile_asimage (asv, background, 0, 0,
438 target_width, target_height, background_tint,
439 ASA_XImage, 100, ASIMAGE_QUALITY_DEFAULT);
440 if (tmp)
441 result = tmp;
442 }
443 }
444 else
445 new_pmap_width = new_pmap_height = 0;
446 }
447 else 340 else
448 { 341 bg_flags &= ~BG_IS_SIZE_SENSITIVE;
449 result = original_asim;
450
451 if ((w != original_asim->width)
452 || (h != original_asim->height))
453 {
454 result = scale_asimage (asv, original_asim,
455 w, h,
456 background ? ASA_ASImage : ASA_XImage,
457 100, ASIMAGE_QUALITY_DEFAULT);
458 }
459
460 if (background == NULL)
461 {
462 if (bg_flags & BG_TILE)
463 {
464 /* if tiling - pixmap has to be sized exactly as the image,
465 but there is no need to make it bigger than the window! */
466 new_pmap_width = min (result->width, target_width);
467 new_pmap_height = min (result->height, target_height);
468
469 /* we also need to tile our image in both directions */
470 ASImage *tmp = tile_asimage (asv, result,
471 (int)result->width - x,
472 (int)result->height - y,
473 new_pmap_width,
474 new_pmap_height,
475 TINT_LEAVE_SAME, ASA_XImage,
476 100, ASIMAGE_QUALITY_DEFAULT);
477 if (tmp)
478 {
479 if (result != original_asim)
480 destroy_asimage (&result);
481
482 result = tmp;
483 }
484 }
485 }
486 else
487 {
488 /* if blending background and image - pixmap has to be sized same as target window */
489 ASImageLayer *layers = create_image_layers (2);
490
491 layers[0].im = background;
492 layers[0].clip_width = target_width;
493 layers[0].clip_height = target_height;
494 layers[0].tint = background_tint;
495 layers[1].im = result;
496
497 if (bg_flags & BG_TILE)
498 {
499 /* tile horizontally */
500 while (x > 0) x -= (int)result->width;
501 layers[1].dst_x = x;
502 layers[1].clip_width = result->width+target_width;
503 }
504 else
505 {
506 /* clip horizontally */
507 layers[1].dst_x = x;
508 layers[1].clip_width = result->width;
509 }
510
511 if (bg_flags & BG_TILE)
512 {
513 while (y > 0) y -= (int)result->height;
514 layers[1].dst_y = y;
515 layers[1].clip_height = result->height + target_height;
516 }
517 else
518 {
519 layers[1].dst_y = y;
520 layers[1].clip_height = result->height;
521 }
522
523 if (rs[Rs_blendtype])
524 {
525 layers[1].merge_scanlines = blend_scanlines_name2func (rs[Rs_blendtype]);
526 if (layers[1].merge_scanlines == NULL)
527 layers[1].merge_scanlines = alphablend_scanlines;
528 }
529
530 ASImage *tmp = merge_layers (asv, layers, 2, target_width, target_height,
531 ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
532
533 if (tmp)
534 {
535 if (result != original_asim)
536 destroy_asimage (&result);
537
538 result = tmp;
539 }
540
541 free (layers);
542 }
543 }
544
545 bool ret = false;
546
547 if (result)
548 {
549 XGCValues gcv;
550 GC gc;
551
552 /* create Pixmap */
553 if (bg_pixmap == None
554 || bg_pmap_width != new_pmap_width
555 || bg_pmap_height != new_pmap_height)
556 {
557 if (bg_pixmap)
558 XFreePixmap (dpy, bg_pixmap);
559 bg_pixmap = XCreatePixmap (dpy, vt, new_pmap_width, new_pmap_height, depth);
560 bg_pmap_width = new_pmap_width;
561 bg_pmap_height = new_pmap_height;
562 }
563 /* fill with background color (if result's not completely overlapping it) */
564 gcv.foreground = pix_colors[Color_bg];
565 gc = XCreateGC (dpy, vt, GCForeground, &gcv);
566
567 int src_x = 0, src_y = 0, dst_x = 0, dst_y = 0;
568 int dst_width = result->width, dst_height = result->height;
569 if (background == NULL)
570 {
571 if (!(bg_flags & BG_TILE))
572 {
573 src_x = make_clip_rectangle (x, result->width , new_pmap_width , dst_x, dst_width );
574 src_y = make_clip_rectangle (y, result->height, new_pmap_height, dst_y, dst_height);
575 }
576
577 if (dst_x > 0 || dst_y > 0
578 || dst_x + dst_width < new_pmap_width
579 || dst_y + dst_height < new_pmap_height)
580 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, new_pmap_width, new_pmap_height);
581 }
582
583 /* put result on pixmap */
584 if (dst_x < new_pmap_width && dst_y < new_pmap_height)
585 asimage2drawable (asv, bg_pixmap, result, gc, src_x, src_y, dst_x, dst_y, dst_width, dst_height, True);
586
587 if (result != background && result != original_asim)
588 destroy_asimage (&result);
589
590 XFreeGC (dpy, gc);
591
592 ret = true;
593 }
594
595 if (background)
596 destroy_asimage (&background);
597
598 return ret;
599} 342}
600# endif /* HAVE_AFTERIMAGE */
601 343
602# ifdef HAVE_PIXBUF 344# ifdef HAVE_PIXBUF
603bool 345bool
604rxvt_term::pixbuf_to_pixmap (GdkPixbuf *pixbuf, Pixmap pixmap, GC gc, 346rxvt_term::pixbuf_to_pixmap (GdkPixbuf *pixbuf, Pixmap pixmap, GC gc,
605 int src_x, int src_y, int dst_x, int dst_y, 347 int src_x, int src_y, int dst_x, int dst_y,
682 XDestroyImage (ximage); 424 XDestroyImage (ximage);
683 return true; 425 return true;
684} 426}
685 427
686bool 428bool
687rxvt_term::render_image (unsigned long tr_flags) 429rxvt_term::render_image (bool transparent)
688{ 430{
689 if (!pixbuf) 431 if (!pixbuf)
690 return false; 432 return false;
691 433
692 if (tr_flags 434 if (transparent
693 && !(bg_flags & BG_HAS_RENDER)) 435 && !(bg_flags & BG_HAS_RENDER))
694 return false; 436 return false;
695 437
696 GdkPixbuf *result; 438 GdkPixbuf *result;
697 439
711 get_image_geometry (image_width, image_height, w, h, x, y); 453 get_image_geometry (image_width, image_height, w, h, x, y);
712 454
713 if (!(bg_flags & BG_ROOT_ALIGN) 455 if (!(bg_flags & BG_ROOT_ALIGN)
714 && (x >= target_width 456 && (x >= target_width
715 || y >= target_height 457 || y >= target_height
716 || (x + w <= 0) 458 || x + w <= 0
717 || (y + h <= 0))) 459 || y + h <= 0))
718 return false; 460 return false;
719 461
720 result = pixbuf; 462 result = pixbuf;
721 463
722 if ((w != image_width) 464 if (w != image_width
723 || (h != image_height)) 465 || h != image_height)
724 { 466 {
725 result = gdk_pixbuf_scale_simple (pixbuf, 467 result = gdk_pixbuf_scale_simple (pixbuf,
726 w, h, 468 w, h,
727 GDK_INTERP_BILINEAR); 469 GDK_INTERP_BILINEAR);
728 } 470 }
737 Pixmap root_pmap; 479 Pixmap root_pmap;
738 480
739 image_width = gdk_pixbuf_get_width (result); 481 image_width = gdk_pixbuf_get_width (result);
740 image_height = gdk_pixbuf_get_height (result); 482 image_height = gdk_pixbuf_get_height (result);
741 483
742 if (tr_flags) 484 if (transparent)
743 { 485 {
744 root_pmap = bg_pixmap; 486 root_pmap = bg_pixmap;
745 bg_pixmap = None; 487 bg_pixmap = None;
746 } 488 }
747 else 489 else
805 dst_x, dst_y, 547 dst_x, dst_y,
806 dst_width, dst_height); 548 dst_width, dst_height);
807 } 549 }
808 550
809#if XRENDER 551#if XRENDER
810 if (tr_flags) 552 if (transparent)
811 { 553 {
812 XRenderPictureAttributes pa;
813
814 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, visual); 554 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
555
815 Picture src = XRenderCreatePicture (dpy, root_pmap, src_format, 0, &pa); 556 Picture src = XRenderCreatePicture (dpy, root_pmap, format, 0, 0);
816 557
817 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
818 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, dst_format, 0, &pa); 558 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, format, 0, 0);
819 559
820 pa.repeat = True; 560 Picture mask = create_xrender_mask (dpy, vt, False, False);
821 Pixmap mask_pmap = XCreatePixmap (dpy, vt, 1, 1, 8);
822 XRenderPictFormat *mask_format = XRenderFindStandardFormat (dpy, PictStandardA8);
823 Picture mask = XRenderCreatePicture (dpy, mask_pmap, mask_format, CPRepeat, &pa);
824 XFreePixmap (dpy, mask_pmap);
825 561
826 XRenderColor mask_c; 562 XRenderColor mask_c;
827 563
828 mask_c.alpha = 0x8000; 564 mask_c.alpha = 0x8000;
829 mask_c.red = 0; 565 mask_c.red =
830 mask_c.green = 0; 566 mask_c.green =
831 mask_c.blue = 0; 567 mask_c.blue = 0;
832 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); 568 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
569
833 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, target_width, target_height); 570 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, target_width, target_height);
834 571
835 XRenderFreePicture (dpy, src); 572 XRenderFreePicture (dpy, src);
836 XRenderFreePicture (dpy, dst); 573 XRenderFreePicture (dpy, dst);
837 XRenderFreePicture (dpy, mask); 574 XRenderFreePicture (dpy, mask);
844 } 581 }
845 582
846 if (result != pixbuf) 583 if (result != pixbuf)
847 g_object_unref (result); 584 g_object_unref (result);
848 585
849 if (tr_flags) 586 if (transparent)
850 XFreePixmap (dpy, root_pmap); 587 XFreePixmap (dpy, root_pmap);
851 588
852 return ret; 589 return ret;
853} 590}
854# endif /* HAVE_PIXBUF */ 591# endif /* HAVE_PIXBUF */
857rxvt_term::bg_set_file (const char *file) 594rxvt_term::bg_set_file (const char *file)
858{ 595{
859 if (!file || !*file) 596 if (!file || !*file)
860 return false; 597 return false;
861 598
599 bool ret = false;
862 if (const char *p = strchr (file, ';')) 600 const char *p = strchr (file, ';');
601
602 if (p)
863 { 603 {
864 size_t len = p - file; 604 size_t len = p - file;
865 char *f = rxvt_temp_buf<char> (len + 1); 605 char *f = rxvt_temp_buf<char> (len + 1);
866 memcpy (f, file, len); 606 memcpy (f, file, len);
867 f[len] = '\0'; 607 f[len] = '\0';
868 file = f; 608 file = f;
869 } 609 }
870 610
871# ifdef HAVE_AFTERIMAGE
872 if (!asimman)
873 asimman = create_generic_imageman (rs[Rs_path]);
874 ASImage *image = get_asimage (asimman, file, 0xFFFFFFFF, 100);
875 if (image)
876 {
877 if (original_asim)
878 safe_asimage_destroy (original_asim);
879 original_asim = image;
880 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER;
881 return true;
882 }
883# endif
884
885# ifdef HAVE_PIXBUF 611# ifdef HAVE_PIXBUF
886 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL); 612 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL);
887 if (image) 613 if (image)
888 { 614 {
889 if (pixbuf) 615 if (pixbuf)
890 g_object_unref (pixbuf); 616 g_object_unref (pixbuf);
891 pixbuf = image; 617 pixbuf = image;
892 bg_flags |= BG_IS_FROM_FILE; 618 bg_flags |= BG_IS_FROM_FILE;
893 return true; 619 ret = true;
894 } 620 }
895# endif 621# endif
896 622
623 if (ret)
624 {
625 if (p)
626 bg_set_geometry (p + 1);
627 else
628 bg_set_default_geometry ();
629 }
630
897 return false; 631 return ret;
898} 632}
899 633
900# endif /* BG_IMAGE_FROM_FILE */ 634# endif /* BG_IMAGE_FROM_FILE */
901 635
902# ifdef ENABLE_TRANSPARENCY 636# ifdef ENABLE_TRANSPARENCY
938 { 672 {
939 changed = true; 673 changed = true;
940 v_blurRadius = vr; 674 v_blurRadius = vr;
941 } 675 }
942 676
943 if (v_blurRadius == 0 && h_blurRadius == 0) 677 if (h_blurRadius && v_blurRadius)
678 bg_flags |= BG_NEEDS_BLUR;
679 else
944 bg_flags &= ~BG_NEEDS_BLUR; 680 bg_flags &= ~BG_NEEDS_BLUR;
945 else
946 bg_flags |= BG_NEEDS_BLUR;
947 681
948 return changed; 682 return changed;
949} 683}
950 684
951void 685void
952rxvt_term::set_tint_shade_flags () 686rxvt_term::set_tint_shade_flags ()
953{ 687{
954 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); 688 if (shade != 100 || (bg_flags & BG_TINT_SET))
955 bool has_shade = shade != 100; 689 bg_flags |= BG_NEEDS_TINT;
690 else
691 bg_flags &= ~BG_NEEDS_TINT;
692}
956 693
694bool
695rxvt_term::bg_set_tint (rxvt_color &new_tint)
696{
697 if (!(bg_flags & BG_TINT_SET) || tint != new_tint)
698 {
699 tint = new_tint;
957 bg_flags &= ~BG_TINT_FLAGS; 700 bg_flags |= BG_TINT_SET;
958 701
959 if (bg_flags & BG_TINT_SET) 702 rgba c;
960 {
961 tint.get (c); 703 tint.get (c);
962 if (!has_shade
963 && (c.r <= 0x00ff || c.r >= 0xff00) 704 if ((c.r <= 0x00ff || c.r >= 0xff00)
964 && (c.g <= 0x00ff || c.g >= 0xff00) 705 && (c.g <= 0x00ff || c.g >= 0xff00)
965 && (c.b <= 0x00ff || c.b >= 0xff00)) 706 && (c.b <= 0x00ff || c.b >= 0xff00))
966 bg_flags |= BG_TINT_BITAND; 707 bg_flags |= BG_TINT_BITAND;
967 } 708 else
968
969 if (has_shade || (bg_flags & BG_TINT_SET))
970 bg_flags |= BG_NEEDS_TINT;
971}
972
973bool
974rxvt_term::bg_set_tint (rxvt_color &new_tint)
975{
976 if (!(bg_flags & BG_TINT_SET) || tint != new_tint)
977 {
978 tint = new_tint;
979 bg_flags |= BG_TINT_SET; 709 bg_flags &= ~BG_TINT_BITAND;
710
980 set_tint_shade_flags (); 711 set_tint_shade_flags ();
981 return true; 712 return true;
982 } 713 }
983 714
984 return false; 715 return false;
985} 716}
986 717
987bool 718bool
988rxvt_term::bg_set_shade (const char *shade_str) 719rxvt_term::bg_set_shade (const char *shade_str)
989{ 720{
990 int new_shade = (shade_str) ? atoi (shade_str) : 100; 721 int new_shade = atoi (shade_str);
991 722
992 clamp_it (new_shade, -100, 200); 723 clamp_it (new_shade, -100, 200);
993 if (new_shade < 0) 724 if (new_shade < 0)
994 new_shade = 200 - (100 + new_shade); 725 new_shade = 200 - (100 + new_shade);
995 726
1025 params[i+2] = XDoubleToFixed (kernel[i] / sum); 756 params[i+2] = XDoubleToFixed (kernel[i] / sum);
1026} 757}
1027#endif 758#endif
1028 759
1029bool 760bool
1030rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height) 761rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height, int depth)
1031{ 762{
1032 bool ret = false; 763 bool ret = false;
1033#if XRENDER 764#if XRENDER
765 if (!(bg_flags & BG_HAS_RENDER_CONV))
766 return false;
767
1034 int size = max (h_blurRadius, v_blurRadius) * 2 + 1; 768 int size = max (h_blurRadius, v_blurRadius) * 2 + 1;
1035 double *kernel = (double *)malloc (size * sizeof (double)); 769 double *kernel = (double *)malloc (size * sizeof (double));
1036 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 770 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
1037 771
1038 XRenderPictureAttributes pa; 772 XRenderPictureAttributes pa;
1039 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 773 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1040 774
775 pa.repeat = RepeatPad;
1041 Picture src = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 776 Picture src = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa);
777 Pixmap tmp = XCreatePixmap (dpy, pixmap, width, height, depth);
1042 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 778 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa);
779 XFreePixmap (dpy, tmp);
1043 780
1044 if (kernel && params) 781 if (kernel && params)
1045 { 782 {
1046 if (h_blurRadius)
1047 {
1048 size = h_blurRadius * 2 + 1; 783 size = h_blurRadius * 2 + 1;
1049 get_gaussian_kernel (h_blurRadius, size, kernel, params); 784 get_gaussian_kernel (h_blurRadius, size, kernel, params);
1050 785
1051 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 786 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1052 XRenderComposite (dpy, 787 XRenderComposite (dpy,
1053 PictOpSrc, 788 PictOpSrc,
1054 src, 789 src,
1055 None, 790 None,
1056 dst, 791 dst,
1057 0, 0, 792 0, 0,
1058 0, 0, 793 0, 0,
1059 0, 0, 794 0, 0,
1060 width, height); 795 width, height);
1061 }
1062 796
1063 if (v_blurRadius) 797 ::swap (src, dst);
1064 { 798
1065 size = v_blurRadius * 2 + 1; 799 size = v_blurRadius * 2 + 1;
1066 get_gaussian_kernel (v_blurRadius, size, kernel, params); 800 get_gaussian_kernel (v_blurRadius, size, kernel, params);
1067 ::swap (params[0], params[1]); 801 ::swap (params[0], params[1]);
1068 802
1069 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 803 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1070 XRenderComposite (dpy, 804 XRenderComposite (dpy,
1071 PictOpSrc, 805 PictOpSrc,
1072 src, 806 src,
1073 None, 807 None,
1074 dst, 808 dst,
1075 0, 0, 809 0, 0,
1076 0, 0, 810 0, 0,
1077 0, 0, 811 0, 0,
1078 width, height); 812 width, height);
1079 }
1080 813
1081 ret = true; 814 ret = true;
1082 } 815 }
1083 816
1084 free (kernel); 817 free (kernel);
1092bool 825bool
1093rxvt_term::tint_pixmap (Pixmap pixmap, Visual *visual, int width, int height) 826rxvt_term::tint_pixmap (Pixmap pixmap, Visual *visual, int width, int height)
1094{ 827{
1095 bool ret = false; 828 bool ret = false;
1096 829
1097 if (bg_flags & BG_TINT_BITAND) 830 if (shade == 100 && (bg_flags & BG_TINT_BITAND))
1098 { 831 {
1099 XGCValues gcv; 832 XGCValues gcv;
1100 GC gc; 833 GC gc;
1101 834
1102 /* In this case we can tint image server-side getting significant 835 /* In this case we can tint image server-side getting significant
1111 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height); 844 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height);
1112 ret = true; 845 ret = true;
1113 XFreeGC (dpy, gc); 846 XFreeGC (dpy, gc);
1114 } 847 }
1115 } 848 }
1116 else
1117 {
1118# if XRENDER 849# if XRENDER
850 else if (bg_flags & BG_HAS_RENDER)
851 {
1119 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); 852 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1120 853
1121 if (bg_flags & BG_TINT_SET) 854 if (bg_flags & BG_TINT_SET)
1122 tint.get (c); 855 tint.get (c);
1123 856
1132 c.r = c.r * (200 - shade) / 100; 865 c.r = c.r * (200 - shade) / 100;
1133 c.g = c.g * (200 - shade) / 100; 866 c.g = c.g * (200 - shade) / 100;
1134 c.b = c.b * (200 - shade) / 100; 867 c.b = c.b * (200 - shade) / 100;
1135 } 868 }
1136 869
1137 XRenderPictFormat *solid_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
1138 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 870 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1139 XRenderPictureAttributes pa;
1140 871
1141 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 872 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1142 873
1143 pa.repeat = True; 874 Picture overlay_pic = create_xrender_mask (dpy, pixmap, True, False);
1144 875
1145 Pixmap overlay_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32); 876 Picture mask_pic = create_xrender_mask (dpy, pixmap, True, True);
1146 Picture overlay_pic = XRenderCreatePicture (dpy, overlay_pmap, solid_format, CPRepeat, &pa);
1147 XFreePixmap (dpy, overlay_pmap);
1148
1149 pa.component_alpha = True;
1150 Pixmap mask_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32);
1151 Picture mask_pic = XRenderCreatePicture (dpy, mask_pmap, solid_format, CPRepeat | CPComponentAlpha, &pa);
1152 XFreePixmap (dpy, mask_pmap);
1153 877
1154 XRenderColor mask_c; 878 XRenderColor mask_c;
1155 879
1156 mask_c.alpha = 0xffff; 880 mask_c.alpha = 0xffff;
1157 mask_c.red = 881 mask_c.red =
1162 mask_c.alpha = 0; 886 mask_c.alpha = 0;
1163 mask_c.red = 0xffff - c.r; 887 mask_c.red = 0xffff - c.r;
1164 mask_c.green = 0xffff - c.g; 888 mask_c.green = 0xffff - c.g;
1165 mask_c.blue = 0xffff - c.b; 889 mask_c.blue = 0xffff - c.b;
1166 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); 890 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
891
1167 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height); 892 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1168 893
1169 if (shade > 100) 894 if (shade > 100)
1170 { 895 {
1171 mask_c.red = mask_c.green = mask_c.blue = 0xffff * (shade - 100) / 100;
1172 mask_c.alpha = 0; 896 mask_c.alpha = 0;
897 mask_c.red =
898 mask_c.green =
899 mask_c.blue = 0xffff * (shade - 100) / 100;
1173 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); 900 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1174 901
1175 XRenderComposite (dpy, PictOpOver, overlay_pic, None, back_pic, 0, 0, 0, 0, 0, 0, width, height); 902 XRenderComposite (dpy, PictOpOver, overlay_pic, None, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1176 } 903 }
1177 904
1178 ret = true; 905 ret = true;
1179 906
1180 XRenderFreePicture (dpy, mask_pic); 907 XRenderFreePicture (dpy, mask_pic);
1181 XRenderFreePicture (dpy, overlay_pic); 908 XRenderFreePicture (dpy, overlay_pic);
1182 XRenderFreePicture (dpy, back_pic); 909 XRenderFreePicture (dpy, back_pic);
910 }
1183# endif 911# endif
1184 }
1185 912
1186 return ret; 913 return ret;
1187} 914}
1188 915
1189/* 916/*
1190 * Builds a pixmap of the same size as the terminal window that contains 917 * Builds a pixmap of the same size as the terminal window that contains
1191 * the tiled portion of the root pixmap that is supposed to be covered by 918 * the tiled portion of the root pixmap that is supposed to be covered by
1192 * our window. 919 * our window.
1193 */ 920 */
1194unsigned long 921bool
1195rxvt_term::make_transparency_pixmap () 922rxvt_term::make_transparency_pixmap ()
1196{ 923{
1197 unsigned long result = 0; 924 bool ret = false;
1198 925
1199 /* root dimensions may change from call to call - but Display structure should 926 /* root dimensions may change from call to call - but Display structure should
1200 * be always up-to-date, so let's use it : 927 * be always up-to-date, so let's use it :
1201 */ 928 */
1202 int screen = display->screen; 929 int screen = display->screen;
1240#if XRENDER 967#if XRENDER
1241 if (bg_flags & BG_HAS_RENDER) 968 if (bg_flags & BG_HAS_RENDER)
1242 { 969 {
1243 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth); 970 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth);
1244 971
1245 XRenderPictureAttributes pa;
1246
1247 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen)); 972 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
1248 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, &pa); 973 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, 0);
1249 974
1250 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual); 975 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
1251 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, &pa); 976 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, 0);
1252 977
1253 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, root_pmap_width, root_pmap_height); 978 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, root_pmap_width, root_pmap_height);
1254 979
1255 XRenderFreePicture (dpy, src); 980 XRenderFreePicture (dpy, src);
1256 XRenderFreePicture (dpy, dst); 981 XRenderFreePicture (dpy, dst);
1273 bg_pmap_width = window_width; 998 bg_pmap_width = window_width;
1274 bg_pmap_height = window_height; 999 bg_pmap_height = window_height;
1275 } 1000 }
1276 1001
1277 /* straightforward pixmap copy */ 1002 /* straightforward pixmap copy */
1278 while (sx < 0) sx += root_width; 1003 while (sx < 0) sx += root_pmap_width;
1279 while (sy < 0) sy += root_height; 1004 while (sy < 0) sy += root_pmap_height;
1280 1005
1281 gcv.tile = recoded_root_pmap; 1006 gcv.tile = recoded_root_pmap;
1282 gcv.fill_style = FillTiled; 1007 gcv.fill_style = FillTiled;
1283 gcv.ts_x_origin = -sx; 1008 gcv.ts_x_origin = -sx;
1284 gcv.ts_y_origin = -sy; 1009 gcv.ts_y_origin = -sy;
1285 gc = XCreateGC (dpy, vt, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv); 1010 gc = XCreateGC (dpy, vt, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv);
1286 1011
1287 if (gc) 1012 if (gc)
1288 { 1013 {
1289 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height); 1014 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height);
1290 result |= BG_IS_VALID | (bg_flags & BG_EFFECTS_FLAGS); 1015 ret = true;
1016 unsigned long tr_flags = bg_flags & BG_EFFECTS_FLAGS;
1017
1018 if (!(bg_flags & BG_CLIENT_RENDER))
1019 {
1020 if (bg_flags & BG_NEEDS_BLUR)
1021 {
1022 if (blur_pixmap (bg_pixmap, visual, window_width, window_height, depth))
1023 tr_flags &= ~BG_NEEDS_BLUR;
1024 }
1025 if (bg_flags & BG_NEEDS_TINT)
1026 {
1027 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1028 tr_flags &= ~BG_NEEDS_TINT;
1029 }
1030 if (tr_flags & BG_NEEDS_TINT)
1031 {
1032 XImage *ximage = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1033 if (ximage)
1034 {
1035 /* our own client-side tinting */
1036 tint_ximage (DefaultVisual (dpy, display->screen), ximage);
1037
1038 XPutImage (dpy, bg_pixmap, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
1039 XDestroyImage (ximage);
1040 }
1041 }
1042 } /* server side rendering completed */
1043
1291 XFreeGC (dpy, gc); 1044 XFreeGC (dpy, gc);
1292
1293 if (!(bg_flags & BG_CLIENT_RENDER))
1294 {
1295 if ((bg_flags & BG_NEEDS_BLUR)
1296 && (bg_flags & BG_HAS_RENDER_CONV))
1297 {
1298 if (blur_pixmap (bg_pixmap, visual, window_width, window_height))
1299 result &= ~BG_NEEDS_BLUR;
1300 }
1301 if ((bg_flags & BG_NEEDS_TINT)
1302 && (bg_flags & (BG_TINT_BITAND | BG_HAS_RENDER)))
1303 {
1304 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1305 result &= ~BG_NEEDS_TINT;
1306 }
1307 } /* server side rendering completed */
1308 } 1045 }
1309 1046
1310 if (recoded_root_pmap != root_pixmap) 1047 if (recoded_root_pmap != root_pixmap)
1311 XFreePixmap (dpy, recoded_root_pmap); 1048 XFreePixmap (dpy, recoded_root_pmap);
1312 1049
1313 return result; 1050 return ret;
1314} 1051}
1315 1052
1316void 1053void
1317rxvt_term::bg_set_root_pixmap () 1054rxvt_term::bg_set_root_pixmap ()
1318{ 1055{
1322 1059
1323 root_pixmap = new_root_pixmap; 1060 root_pixmap = new_root_pixmap;
1324} 1061}
1325# endif /* ENABLE_TRANSPARENCY */ 1062# endif /* ENABLE_TRANSPARENCY */
1326 1063
1327#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1328static void shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c);
1329# endif
1330
1331bool 1064bool
1332rxvt_term::bg_render () 1065rxvt_term::bg_render ()
1333{ 1066{
1334 unsigned long tr_flags = 0; 1067 bool transparent = false;
1335 1068
1336 bg_invalidate (); 1069 bg_invalidate ();
1337# ifdef ENABLE_TRANSPARENCY 1070# ifdef ENABLE_TRANSPARENCY
1338 if (bg_flags & BG_IS_TRANSPARENT) 1071 if (bg_flags & BG_IS_TRANSPARENT)
1339 { 1072 {
1340 /* we need to re-generate transparency pixmap in that case ! */ 1073 /* we need to re-generate transparency pixmap in that case ! */
1341 tr_flags = make_transparency_pixmap (); 1074 transparent = make_transparency_pixmap ();
1342 if (tr_flags == 0) 1075 if (transparent)
1343 return false;
1344 else if (!(tr_flags & BG_EFFECTS_FLAGS))
1345 bg_flags |= BG_IS_VALID; 1076 bg_flags |= BG_IS_VALID;
1346 } 1077 }
1347# endif 1078# endif
1348 1079
1349# ifdef BG_IMAGE_FROM_FILE 1080# ifdef BG_IMAGE_FROM_FILE
1350 if ((bg_flags & BG_IS_FROM_FILE) 1081 if (bg_flags & BG_IS_FROM_FILE)
1351 || (tr_flags & BG_EFFECTS_FLAGS))
1352 { 1082 {
1353 if (render_image (tr_flags)) 1083 if (render_image (transparent))
1354 bg_flags |= BG_IS_VALID; 1084 bg_flags |= BG_IS_VALID;
1355 }
1356# endif
1357
1358# if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1359 XImage *result = NULL;
1360
1361 if (tr_flags && !(bg_flags & BG_IS_VALID))
1362 {
1363 result = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1364 }
1365
1366 if (result)
1367 {
1368 /* our own client-side tinting */
1369 if (tr_flags & BG_NEEDS_TINT)
1370 {
1371 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
1372 if (bg_flags & BG_TINT_SET)
1373 tint.get (c);
1374 shade_ximage (DefaultVisual (dpy, display->screen), result, shade, c);
1375 }
1376
1377 GC gc = XCreateGC (dpy, vt, 0UL, NULL);
1378
1379 if (gc)
1380 {
1381 XPutImage (dpy, bg_pixmap, gc, result, 0, 0, 0, 0, result->width, result->height);
1382
1383 XFreeGC (dpy, gc);
1384 bg_flags |= BG_IS_VALID;
1385 }
1386
1387 XDestroyImage (result);
1388 } 1085 }
1389# endif 1086# endif
1390 1087
1391 if (!(bg_flags & BG_IS_VALID)) 1088 if (!(bg_flags & BG_IS_VALID))
1392 { 1089 {
1429#endif 1126#endif
1430} 1127}
1431 1128
1432#endif /* HAVE_BG_PIXMAP */ 1129#endif /* HAVE_BG_PIXMAP */
1433 1130
1434#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) 1131#ifdef ENABLE_TRANSPARENCY
1435/* taken from aterm-0.4.2 */ 1132/* based on code from aterm-0.4.2 */
1436 1133
1437static void 1134static inline void
1438shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c) 1135fill_lut (uint32_t *lookup, uint32_t mask, int sh, unsigned short low, unsigned short high)
1136{
1137 for (int i = 0; i <= mask >> sh; i++)
1138 {
1139 uint32_t tmp;
1140 tmp = i * high;
1141 tmp += (mask >> sh) * low;
1142 lookup[i] = (tmp / 0xffff) << sh;
1143 }
1144}
1145
1146void
1147rxvt_term::tint_ximage (Visual *visual, XImage *ximage)
1439{ 1148{
1440 int sh_r, sh_g, sh_b; 1149 int sh_r, sh_g, sh_b;
1441 uint32_t mask_r, mask_g, mask_b; 1150 uint32_t mask_r, mask_g, mask_b;
1442 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; 1151 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b;
1443 rgba low; 1152 unsigned short low;
1444 rgba high;
1445 int i;
1446 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst; 1153 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
1447 1154
1448 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return; 1155 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return;
1449 1156
1450 /* for convenience */ 1157 /* for convenience */
1509 break; 1216 break;
1510 default: 1217 default:
1511 return; /* we do not support this color depth */ 1218 return; /* we do not support this color depth */
1512 } 1219 }
1513 1220
1221 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1222
1223 if (bg_flags & BG_TINT_SET)
1224 tint.get (c);
1225
1514 /* prepare limits for color transformation (each channel is handled separately) */ 1226 /* prepare limits for color transformation (each channel is handled separately) */
1515 if (shade > 100) 1227 if (shade > 100)
1516 { 1228 {
1517 shade = 200 - shade;
1518
1519 high.r = c.r * shade / 100;
1520 high.g = c.g * shade / 100;
1521 high.b = c.b * shade / 100;
1522
1523 low.r = 65535 * (100 - shade) / 100; 1229 c.r = c.r * (200 - shade) / 100;
1524 low.g = 65535 * (100 - shade) / 100; 1230 c.g = c.g * (200 - shade) / 100;
1525 low.b = 65535 * (100 - shade) / 100; 1231 c.b = c.b * (200 - shade) / 100;
1232
1233 low = 0xffff * (shade - 100) / 100;
1526 } 1234 }
1527 else 1235 else
1528 { 1236 {
1529 high.r = c.r * shade / 100; 1237 c.r = c.r * shade / 100;
1530 high.g = c.g * shade / 100; 1238 c.g = c.g * shade / 100;
1531 high.b = c.b * shade / 100; 1239 c.b = c.b * shade / 100;
1532 1240
1533 low.r = low.g = low.b = 0; 1241 low = 0;
1534 } 1242 }
1535 1243
1536 /* fill our lookup tables */ 1244 /* fill our lookup tables */
1537 for (i = 0; i <= mask_r>>sh_r; i++) 1245 fill_lut (lookup_r, mask_r, sh_r, low, c.r);
1538 { 1246 fill_lut (lookup_g, mask_g, sh_g, low, c.g);
1539 uint32_t tmp; 1247 fill_lut (lookup_b, mask_b, sh_b, low, c.b);
1540 tmp = i * high.r;
1541 tmp += (mask_r>>sh_r) * low.r;
1542 lookup_r[i] = (tmp/65535)<<sh_r;
1543 }
1544 for (i = 0; i <= mask_g>>sh_g; i++)
1545 {
1546 uint32_t tmp;
1547 tmp = i * high.g;
1548 tmp += (mask_g>>sh_g) * low.g;
1549 lookup_g[i] = (tmp/65535)<<sh_g;
1550 }
1551 for (i = 0; i <= mask_b>>sh_b; i++)
1552 {
1553 uint32_t tmp;
1554 tmp = i * high.b;
1555 tmp += (mask_b>>sh_b) * low.b;
1556 lookup_b[i] = (tmp/65535)<<sh_b;
1557 }
1558 1248
1559 /* apply table to input image (replacing colors by newly calculated ones) */ 1249 /* apply table to input image (replacing colors by newly calculated ones) */
1560 if (ximage->bits_per_pixel == 32 1250 if (ximage->bits_per_pixel == 32
1561 && (ximage->depth == 24 || ximage->depth == 32) 1251 && (ximage->depth == 24 || ximage->depth == 32)
1562 && ximage->byte_order == host_byte_order) 1252 && ximage->byte_order == host_byte_order)
1592 } 1282 }
1593 } 1283 }
1594 1284
1595 free (lookup); 1285 free (lookup);
1596} 1286}
1597#endif /* defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) */ 1287#endif /* ENABLE_TRANSPARENCY */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines