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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines