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.154 by sf-exg, Mon May 9 16:35:37 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 }
735 Pixmap root_pmap; 483 Pixmap root_pmap;
736 484
737 image_width = gdk_pixbuf_get_width (result); 485 image_width = gdk_pixbuf_get_width (result);
738 image_height = gdk_pixbuf_get_height (result); 486 image_height = gdk_pixbuf_get_height (result);
739 487
740 if (tr_flags) 488 if (transparent)
741 { 489 {
742 root_pmap = bg_pixmap; 490 root_pmap = bg_pixmap;
743 bg_pixmap = None; 491 bg_pixmap = None;
744 } 492 }
745 else 493 else
746 { 494 {
747 if (h_scale == 0 || v_scale == 0) 495 if (bg_flags & BG_TILE)
748 { 496 {
749 new_pmap_width = min (image_width, target_width); 497 new_pmap_width = min (image_width, target_width);
750 new_pmap_height = min (image_height, target_height); 498 new_pmap_height = min (image_height, target_height);
751 } 499 }
752 } 500 }
765 gcv.foreground = pix_colors[Color_bg]; 513 gcv.foreground = pix_colors[Color_bg];
766 gc = XCreateGC (dpy, vt, GCForeground, &gcv); 514 gc = XCreateGC (dpy, vt, GCForeground, &gcv);
767 515
768 if (gc) 516 if (gc)
769 { 517 {
770 if (h_scale == 0 || v_scale == 0) 518 if (bg_flags & BG_TILE)
771 { 519 {
772 Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, depth); 520 Pixmap tile = XCreatePixmap (dpy, vt, image_width, image_height, depth);
773 pixbuf_to_pixmap (result, tile, gc, 521 pixbuf_to_pixmap (result, tile, gc,
774 0, 0, 522 0, 0,
775 0, 0, 523 0, 0,
803 dst_x, dst_y, 551 dst_x, dst_y,
804 dst_width, dst_height); 552 dst_width, dst_height);
805 } 553 }
806 554
807#if XRENDER 555#if XRENDER
808 if (tr_flags) 556 if (transparent)
809 { 557 {
810 XRenderPictureAttributes pa;
811
812 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, visual); 558 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
559
813 Picture src = XRenderCreatePicture (dpy, root_pmap, src_format, 0, &pa); 560 Picture src = XRenderCreatePicture (dpy, root_pmap, format, 0, 0);
814 561
815 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
816 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, dst_format, 0, &pa); 562 Picture dst = XRenderCreatePicture (dpy, bg_pixmap, format, 0, 0);
817 563
818 pa.repeat = True; 564 Picture mask = create_xrender_mask (dpy, vt, False, False);
819 Pixmap mask_pmap = XCreatePixmap (dpy, vt, 1, 1, 8);
820 XRenderPictFormat *mask_format = XRenderFindStandardFormat (dpy, PictStandardA8);
821 Picture mask = XRenderCreatePicture (dpy, mask_pmap, mask_format, CPRepeat, &pa);
822 XFreePixmap (dpy, mask_pmap);
823 565
824 XRenderColor mask_c; 566 XRenderColor mask_c;
825 567
826 mask_c.alpha = 0x8000; 568 mask_c.alpha = 0x8000;
827 mask_c.red = 0; 569 mask_c.red =
828 mask_c.green = 0; 570 mask_c.green =
829 mask_c.blue = 0; 571 mask_c.blue = 0;
830 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); 572 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
573
831 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);
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);
842 } 585 }
843 586
844 if (result != pixbuf) 587 if (result != pixbuf)
845 g_object_unref (result); 588 g_object_unref (result);
846 589
847 if (tr_flags) 590 if (transparent)
848 XFreePixmap (dpy, root_pmap); 591 XFreePixmap (dpy, root_pmap);
849 592
850 return ret; 593 return ret;
851} 594}
852# endif /* HAVE_PIXBUF */ 595# endif /* HAVE_PIXBUF */
855rxvt_term::bg_set_file (const char *file) 598rxvt_term::bg_set_file (const char *file)
856{ 599{
857 if (!file || !*file) 600 if (!file || !*file)
858 return false; 601 return false;
859 602
603 bool ret = false;
860 if (const char *p = strchr (file, ';')) 604 const char *p = strchr (file, ';');
605
606 if (p)
861 { 607 {
862 size_t len = p - file; 608 size_t len = p - file;
863 char *f = rxvt_temp_buf<char> (len + 1); 609 char *f = rxvt_temp_buf<char> (len + 1);
864 memcpy (f, file, len); 610 memcpy (f, file, len);
865 f[len] = '\0'; 611 f[len] = '\0';
866 file = f; 612 file = f;
867 } 613 }
868 614
869# ifdef HAVE_AFTERIMAGE
870 if (!asimman)
871 asimman = create_generic_imageman (rs[Rs_path]);
872 ASImage *image = get_asimage (asimman, file, 0xFFFFFFFF, 100);
873 if (image)
874 {
875 if (original_asim)
876 safe_asimage_destroy (original_asim);
877 original_asim = image;
878 bg_flags |= BG_IS_FROM_FILE | BG_CLIENT_RENDER;
879 return true;
880 }
881# endif
882
883# ifdef HAVE_PIXBUF 615# ifdef HAVE_PIXBUF
884 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL); 616 GdkPixbuf *image = gdk_pixbuf_new_from_file (file, NULL);
885 if (image) 617 if (image)
886 { 618 {
887 if (pixbuf) 619 if (pixbuf)
888 g_object_unref (pixbuf); 620 g_object_unref (pixbuf);
889 pixbuf = image; 621 pixbuf = image;
890 bg_flags |= BG_IS_FROM_FILE; 622 bg_flags |= BG_IS_FROM_FILE;
891 return true; 623 ret = true;
892 } 624 }
893# endif 625# endif
894 626
627 if (ret)
628 {
629 if (p)
630 bg_set_geometry (p + 1);
631 else
632 bg_set_default_geometry ();
633 }
634
895 return false; 635 return ret;
896} 636}
897 637
898# endif /* BG_IMAGE_FROM_FILE */ 638# endif /* BG_IMAGE_FROM_FILE */
899 639
900# ifdef ENABLE_TRANSPARENCY 640# ifdef ENABLE_TRANSPARENCY
936 { 676 {
937 changed = true; 677 changed = true;
938 v_blurRadius = vr; 678 v_blurRadius = vr;
939 } 679 }
940 680
941 if (v_blurRadius == 0 && h_blurRadius == 0) 681 if (h_blurRadius && v_blurRadius)
682 bg_flags |= BG_NEEDS_BLUR;
683 else
942 bg_flags &= ~BG_NEEDS_BLUR; 684 bg_flags &= ~BG_NEEDS_BLUR;
943 else
944 bg_flags |= BG_NEEDS_BLUR;
945 685
946 return changed; 686 return changed;
947} 687}
948 688
949void 689void
950rxvt_term::set_tint_shade_flags () 690rxvt_term::set_tint_shade_flags ()
951{ 691{
952 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); 692 if (shade != 100 || (bg_flags & BG_TINT_SET))
953 bool has_shade = shade != 100; 693 bg_flags |= BG_NEEDS_TINT;
694 else
695 bg_flags &= ~BG_NEEDS_TINT;
696}
954 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;
955 bg_flags &= ~BG_TINT_FLAGS; 704 bg_flags |= BG_TINT_SET;
956 705
957 if (bg_flags & BG_TINT_SET) 706 rgba c;
958 {
959 tint.get (c); 707 tint.get (c);
960 if (!has_shade
961 && (c.r <= 0x00ff || c.r >= 0xff00) 708 if ((c.r <= 0x00ff || c.r >= 0xff00)
962 && (c.g <= 0x00ff || c.g >= 0xff00) 709 && (c.g <= 0x00ff || c.g >= 0xff00)
963 && (c.b <= 0x00ff || c.b >= 0xff00)) 710 && (c.b <= 0x00ff || c.b >= 0xff00))
964 bg_flags |= BG_TINT_BITAND; 711 bg_flags |= BG_TINT_BITAND;
965 } 712 else
966
967 if (has_shade || (bg_flags & BG_TINT_SET))
968 bg_flags |= BG_NEEDS_TINT;
969}
970
971bool
972rxvt_term::bg_set_tint (rxvt_color &new_tint)
973{
974 if (!(bg_flags & BG_TINT_SET) || tint != new_tint)
975 {
976 tint = new_tint;
977 bg_flags |= BG_TINT_SET; 713 bg_flags &= ~BG_TINT_BITAND;
714
978 set_tint_shade_flags (); 715 set_tint_shade_flags ();
979 return true; 716 return true;
980 } 717 }
981 718
982 return false; 719 return false;
983} 720}
984 721
985bool 722bool
986rxvt_term::bg_set_shade (const char *shade_str) 723rxvt_term::bg_set_shade (const char *shade_str)
987{ 724{
988 int new_shade = (shade_str) ? atoi (shade_str) : 100; 725 int new_shade = atoi (shade_str);
989 726
990 clamp_it (new_shade, -100, 200); 727 clamp_it (new_shade, -100, 200);
991 if (new_shade < 0) 728 if (new_shade < 0)
992 new_shade = 200 - (100 + new_shade); 729 new_shade = 200 - (100 + new_shade);
993 730
1023 params[i+2] = XDoubleToFixed (kernel[i] / sum); 760 params[i+2] = XDoubleToFixed (kernel[i] / sum);
1024} 761}
1025#endif 762#endif
1026 763
1027bool 764bool
1028rxvt_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)
1029{ 766{
1030 bool ret = false; 767 bool ret = false;
1031#if XRENDER 768#if XRENDER
769 if (!(bg_flags & BG_HAS_RENDER_CONV))
770 return false;
771
1032 int size = max (h_blurRadius, v_blurRadius) * 2 + 1; 772 int size = max (h_blurRadius, v_blurRadius) * 2 + 1;
1033 double *kernel = (double *)malloc (size * sizeof (double)); 773 double *kernel = (double *)malloc (size * sizeof (double));
1034 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 774 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
1035 775
1036 XRenderPictureAttributes pa; 776 XRenderPictureAttributes pa;
1037 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 777 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1038 778
779 pa.repeat = RepeatPad;
1039 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);
1040 Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 782 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa);
783 XFreePixmap (dpy, tmp);
1041 784
1042 if (kernel && params) 785 if (kernel && params)
1043 { 786 {
1044 if (h_blurRadius)
1045 {
1046 size = h_blurRadius * 2 + 1; 787 size = h_blurRadius * 2 + 1;
1047 get_gaussian_kernel (h_blurRadius, size, kernel, params); 788 get_gaussian_kernel (h_blurRadius, size, kernel, params);
1048 789
1049 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 790 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1050 XRenderComposite (dpy, 791 XRenderComposite (dpy,
1051 PictOpSrc, 792 PictOpSrc,
1052 src, 793 src,
1053 None, 794 None,
1054 dst, 795 dst,
1055 0, 0, 796 0, 0,
1056 0, 0, 797 0, 0,
1057 0, 0, 798 0, 0,
1058 width, height); 799 width, height);
1059 }
1060 800
1061 if (v_blurRadius) 801 ::swap (src, dst);
1062 { 802
1063 size = v_blurRadius * 2 + 1; 803 size = v_blurRadius * 2 + 1;
1064 get_gaussian_kernel (v_blurRadius, size, kernel, params); 804 get_gaussian_kernel (v_blurRadius, size, kernel, params);
1065 ::swap (params[0], params[1]); 805 ::swap (params[0], params[1]);
1066 806
1067 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 807 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
1068 XRenderComposite (dpy, 808 XRenderComposite (dpy,
1069 PictOpSrc, 809 PictOpSrc,
1070 src, 810 src,
1071 None, 811 None,
1072 dst, 812 dst,
1073 0, 0, 813 0, 0,
1074 0, 0, 814 0, 0,
1075 0, 0, 815 0, 0,
1076 width, height); 816 width, height);
1077 }
1078 817
1079 ret = true; 818 ret = true;
1080 } 819 }
1081 820
1082 free (kernel); 821 free (kernel);
1090bool 829bool
1091rxvt_term::tint_pixmap (Pixmap pixmap, Visual *visual, int width, int height) 830rxvt_term::tint_pixmap (Pixmap pixmap, Visual *visual, int width, int height)
1092{ 831{
1093 bool ret = false; 832 bool ret = false;
1094 833
1095 if (bg_flags & BG_TINT_BITAND) 834 if (shade == 100 && (bg_flags & BG_TINT_BITAND))
1096 { 835 {
1097 XGCValues gcv; 836 XGCValues gcv;
1098 GC gc; 837 GC gc;
1099 838
1100 /* In this case we can tint image server-side getting significant 839 /* In this case we can tint image server-side getting significant
1109 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height); 848 XFillRectangle (dpy, pixmap, gc, 0, 0, width, height);
1110 ret = true; 849 ret = true;
1111 XFreeGC (dpy, gc); 850 XFreeGC (dpy, gc);
1112 } 851 }
1113 } 852 }
1114 else
1115 {
1116# if XRENDER 853# if XRENDER
854 else if (bg_flags & BG_HAS_RENDER)
855 {
1117 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); 856 rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC);
1118 857
1119 if (bg_flags & BG_TINT_SET) 858 if (bg_flags & BG_TINT_SET)
1120 tint.get (c); 859 tint.get (c);
1121 860
1130 c.r = c.r * (200 - shade) / 100; 869 c.r = c.r * (200 - shade) / 100;
1131 c.g = c.g * (200 - shade) / 100; 870 c.g = c.g * (200 - shade) / 100;
1132 c.b = c.b * (200 - shade) / 100; 871 c.b = c.b * (200 - shade) / 100;
1133 } 872 }
1134 873
1135 XRenderPictFormat *solid_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
1136 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 874 XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual);
1137 XRenderPictureAttributes pa;
1138 875
1139 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, &pa); 876 Picture back_pic = XRenderCreatePicture (dpy, pixmap, format, 0, 0);
1140 877
1141 pa.repeat = True; 878 Picture overlay_pic = create_xrender_mask (dpy, pixmap, True, False);
1142 879
1143 Pixmap overlay_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32); 880 Picture mask_pic = create_xrender_mask (dpy, pixmap, True, True);
1144 Picture overlay_pic = XRenderCreatePicture (dpy, overlay_pmap, solid_format, CPRepeat, &pa);
1145 XFreePixmap (dpy, overlay_pmap);
1146
1147 pa.component_alpha = True;
1148 Pixmap mask_pmap = XCreatePixmap (dpy, pixmap, 1, 1, 32);
1149 Picture mask_pic = XRenderCreatePicture (dpy, mask_pmap, solid_format, CPRepeat | CPComponentAlpha, &pa);
1150 XFreePixmap (dpy, mask_pmap);
1151 881
1152 XRenderColor mask_c; 882 XRenderColor mask_c;
1153 883
1154 mask_c.alpha = 0xffff; 884 mask_c.alpha = 0xffff;
1155 mask_c.red = 885 mask_c.red =
1160 mask_c.alpha = 0; 890 mask_c.alpha = 0;
1161 mask_c.red = 0xffff - c.r; 891 mask_c.red = 0xffff - c.r;
1162 mask_c.green = 0xffff - c.g; 892 mask_c.green = 0xffff - c.g;
1163 mask_c.blue = 0xffff - c.b; 893 mask_c.blue = 0xffff - c.b;
1164 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); 894 XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1);
895
1165 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height); 896 XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height);
1166 897
1167 if (shade > 100) 898 if (shade > 100)
1168 { 899 {
1169 mask_c.red = mask_c.green = mask_c.blue = 0xffff * (shade - 100) / 100;
1170 mask_c.alpha = 0; 900 mask_c.alpha = 0;
901 mask_c.red =
902 mask_c.green =
903 mask_c.blue = 0xffff * (shade - 100) / 100;
1171 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); 904 XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1);
1172 905
1173 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);
1174 } 907 }
1175 908
1176 ret = true; 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/* 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;
1238#if XRENDER 971#if XRENDER
1239 if (bg_flags & BG_HAS_RENDER) 972 if (bg_flags & BG_HAS_RENDER)
1240 { 973 {
1241 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth); 974 recoded_root_pmap = XCreatePixmap (dpy, vt, root_pmap_width, root_pmap_height, depth);
1242 975
1243 XRenderPictureAttributes pa;
1244
1245 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen)); 976 XRenderPictFormat *src_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
1246 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, &pa); 977 Picture src = XRenderCreatePicture (dpy, root_pixmap, src_format, 0, 0);
1247 978
1248 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual); 979 XRenderPictFormat *dst_format = XRenderFindVisualFormat (dpy, visual);
1249 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, &pa); 980 Picture dst = XRenderCreatePicture (dpy, recoded_root_pmap, dst_format, 0, 0);
1250 981
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 983
1253 XRenderFreePicture (dpy, src); 984 XRenderFreePicture (dpy, src);
1254 XRenderFreePicture (dpy, dst); 985 XRenderFreePicture (dpy, dst);
1271 bg_pmap_width = window_width; 1002 bg_pmap_width = window_width;
1272 bg_pmap_height = window_height; 1003 bg_pmap_height = window_height;
1273 } 1004 }
1274 1005
1275 /* straightforward pixmap copy */ 1006 /* straightforward pixmap copy */
1276 while (sx < 0) sx += root_width; 1007 while (sx < 0) sx += root_pmap_width;
1277 while (sy < 0) sy += root_height; 1008 while (sy < 0) sy += root_pmap_height;
1278 1009
1279 gcv.tile = recoded_root_pmap; 1010 gcv.tile = recoded_root_pmap;
1280 gcv.fill_style = FillTiled; 1011 gcv.fill_style = FillTiled;
1281 gcv.ts_x_origin = -sx; 1012 gcv.ts_x_origin = -sx;
1282 gcv.ts_y_origin = -sy; 1013 gcv.ts_y_origin = -sy;
1283 gc = XCreateGC (dpy, vt, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv); 1014 gc = XCreateGC (dpy, vt, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcv);
1284 1015
1285 if (gc) 1016 if (gc)
1286 { 1017 {
1287 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height); 1018 XFillRectangle (dpy, bg_pixmap, gc, 0, 0, window_width, window_height);
1288 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
1289 XFreeGC (dpy, gc); 1048 XFreeGC (dpy, gc);
1290
1291 if (!(bg_flags & BG_CLIENT_RENDER))
1292 {
1293 if ((bg_flags & BG_NEEDS_BLUR)
1294 && (bg_flags & BG_HAS_RENDER_CONV))
1295 {
1296 if (blur_pixmap (bg_pixmap, visual, window_width, window_height))
1297 result &= ~BG_NEEDS_BLUR;
1298 }
1299 if ((bg_flags & BG_NEEDS_TINT)
1300 && (bg_flags & (BG_TINT_BITAND | BG_HAS_RENDER)))
1301 {
1302 if (tint_pixmap (bg_pixmap, visual, window_width, window_height))
1303 result &= ~BG_NEEDS_TINT;
1304 }
1305 } /* server side rendering completed */
1306 } 1049 }
1307 1050
1308 if (recoded_root_pmap != root_pixmap) 1051 if (recoded_root_pmap != root_pixmap)
1309 XFreePixmap (dpy, recoded_root_pmap); 1052 XFreePixmap (dpy, recoded_root_pmap);
1310 1053
1311 return result; 1054 return ret;
1312} 1055}
1313 1056
1314void 1057void
1315rxvt_term::bg_set_root_pixmap () 1058rxvt_term::bg_set_root_pixmap ()
1316{ 1059{
1320 1063
1321 root_pixmap = new_root_pixmap; 1064 root_pixmap = new_root_pixmap;
1322} 1065}
1323# endif /* ENABLE_TRANSPARENCY */ 1066# endif /* ENABLE_TRANSPARENCY */
1324 1067
1325#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1326static void shade_ximage (Visual *visual, XImage *ximage, int shade, const rgba &c);
1327# endif
1328
1329bool 1068bool
1330rxvt_term::bg_render () 1069rxvt_term::bg_render ()
1331{ 1070{
1332 unsigned long tr_flags = 0; 1071 bool transparent = false;
1333 1072
1334 bg_invalidate (); 1073 bg_invalidate ();
1335# ifdef ENABLE_TRANSPARENCY 1074# ifdef ENABLE_TRANSPARENCY
1336 if (bg_flags & BG_IS_TRANSPARENT) 1075 if (bg_flags & BG_IS_TRANSPARENT)
1337 { 1076 {
1338 /* we need to re-generate transparency pixmap in that case ! */ 1077 /* we need to re-generate transparency pixmap in that case ! */
1339 tr_flags = make_transparency_pixmap (); 1078 transparent = make_transparency_pixmap ();
1340 if (tr_flags == 0) 1079 if (transparent)
1341 return false;
1342 else if (!(tr_flags & BG_EFFECTS_FLAGS))
1343 bg_flags |= BG_IS_VALID; 1080 bg_flags |= BG_IS_VALID;
1344 } 1081 }
1345# endif 1082# endif
1346 1083
1347# ifdef BG_IMAGE_FROM_FILE 1084# ifdef BG_IMAGE_FROM_FILE
1348 if ((bg_flags & BG_IS_FROM_FILE) 1085 if (bg_flags & BG_IS_FROM_FILE)
1349 || (tr_flags & BG_EFFECTS_FLAGS))
1350 { 1086 {
1351 if (render_image (tr_flags)) 1087 if (render_image (transparent))
1352 bg_flags |= BG_IS_VALID; 1088 bg_flags |= BG_IS_VALID;
1353 }
1354# endif
1355
1356# if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE)
1357 XImage *result = NULL;
1358
1359 if (tr_flags && !(bg_flags & BG_IS_VALID))
1360 {
1361 result = XGetImage (dpy, bg_pixmap, 0, 0, bg_pmap_width, bg_pmap_height, AllPlanes, ZPixmap);
1362 }
1363
1364 if (result)
1365 {
1366 /* our own client-side tinting */
1367 if (tr_flags & BG_NEEDS_TINT)
1368 {
1369 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
1370 if (bg_flags & BG_TINT_SET)
1371 tint.get (c);
1372 shade_ximage (DefaultVisual (dpy, display->screen), result, shade, c);
1373 }
1374
1375 GC gc = XCreateGC (dpy, vt, 0UL, NULL);
1376
1377 if (gc)
1378 {
1379 XPutImage (dpy, bg_pixmap, gc, result, 0, 0, 0, 0, result->width, result->height);
1380
1381 XFreeGC (dpy, gc);
1382 bg_flags |= BG_IS_VALID;
1383 }
1384
1385 XDestroyImage (result);
1386 } 1089 }
1387# endif 1090# endif
1388 1091
1389 if (!(bg_flags & BG_IS_VALID)) 1092 if (!(bg_flags & BG_IS_VALID))
1390 { 1093 {
1427#endif 1130#endif
1428} 1131}
1429 1132
1430#endif /* HAVE_BG_PIXMAP */ 1133#endif /* HAVE_BG_PIXMAP */
1431 1134
1432#if defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) 1135#ifdef ENABLE_TRANSPARENCY
1433/* taken from aterm-0.4.2 */ 1136/* based on code from aterm-0.4.2 */
1434 1137
1435static void 1138static inline void
1436shade_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)
1437{ 1152{
1438 int sh_r, sh_g, sh_b; 1153 int sh_r, sh_g, sh_b;
1439 uint32_t mask_r, mask_g, mask_b; 1154 uint32_t mask_r, mask_g, mask_b;
1440 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; 1155 uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b;
1441 rgba low; 1156 unsigned short low;
1442 rgba high;
1443 int i;
1444 int host_byte_order = byteorder::big_endian () ? MSBFirst : LSBFirst; 1157 int host_byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
1445 1158
1446 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return; 1159 if (visual->c_class != TrueColor || ximage->format != ZPixmap) return;
1447 1160
1448 /* for convenience */ 1161 /* for convenience */
1449 mask_r = visual->red_mask; 1162 mask_r = visual->red_mask;
1507 break; 1220 break;
1508 default: 1221 default:
1509 return; /* we do not support this color depth */ 1222 return; /* we do not support this color depth */
1510 } 1223 }
1511 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
1512 /* prepare limits for color transformation (each channel is handled separately) */ 1230 /* prepare limits for color transformation (each channel is handled separately) */
1513 if (shade > 100) 1231 if (shade > 100)
1514 { 1232 {
1515 shade = 200 - shade;
1516
1517 high.r = c.r * shade / 100;
1518 high.g = c.g * shade / 100;
1519 high.b = c.b * shade / 100;
1520
1521 low.r = 65535 * (100 - shade) / 100; 1233 c.r = c.r * (200 - shade) / 100;
1522 low.g = 65535 * (100 - shade) / 100; 1234 c.g = c.g * (200 - shade) / 100;
1523 low.b = 65535 * (100 - shade) / 100; 1235 c.b = c.b * (200 - shade) / 100;
1236
1237 low = 0xffff * (shade - 100) / 100;
1524 } 1238 }
1525 else 1239 else
1526 { 1240 {
1527 high.r = c.r * shade / 100; 1241 c.r = c.r * shade / 100;
1528 high.g = c.g * shade / 100; 1242 c.g = c.g * shade / 100;
1529 high.b = c.b * shade / 100; 1243 c.b = c.b * shade / 100;
1530 1244
1531 low.r = low.g = low.b = 0; 1245 low = 0;
1532 } 1246 }
1533 1247
1534 /* fill our lookup tables */ 1248 /* fill our lookup tables */
1535 for (i = 0; i <= mask_r>>sh_r; i++) 1249 fill_lut (lookup_r, mask_r, sh_r, low, c.r);
1536 { 1250 fill_lut (lookup_g, mask_g, sh_g, low, c.g);
1537 uint32_t tmp; 1251 fill_lut (lookup_b, mask_b, sh_b, low, c.b);
1538 tmp = i * high.r;
1539 tmp += (mask_r>>sh_r) * low.r;
1540 lookup_r[i] = (tmp/65535)<<sh_r;
1541 }
1542 for (i = 0; i <= mask_g>>sh_g; i++)
1543 {
1544 uint32_t tmp;
1545 tmp = i * high.g;
1546 tmp += (mask_g>>sh_g) * low.g;
1547 lookup_g[i] = (tmp/65535)<<sh_g;
1548 }
1549 for (i = 0; i <= mask_b>>sh_b; i++)
1550 {
1551 uint32_t tmp;
1552 tmp = i * high.b;
1553 tmp += (mask_b>>sh_b) * low.b;
1554 lookup_b[i] = (tmp/65535)<<sh_b;
1555 }
1556 1252
1557 /* apply table to input image (replacing colors by newly calculated ones) */ 1253 /* apply table to input image (replacing colors by newly calculated ones) */
1558 if (ximage->bits_per_pixel == 32 1254 if (ximage->bits_per_pixel == 32
1559 && (ximage->depth == 24 || ximage->depth == 32) 1255 && (ximage->depth == 24 || ximage->depth == 32)
1560 && ximage->byte_order == host_byte_order) 1256 && ximage->byte_order == host_byte_order)
1590 } 1286 }
1591 } 1287 }
1592 1288
1593 free (lookup); 1289 free (lookup);
1594} 1290}
1595#endif /* defined(ENABLE_TRANSPARENCY) && !defined(HAVE_AFTERIMAGE) */ 1291#endif /* ENABLE_TRANSPARENCY */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines