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.95 by sf-exg, Fri Oct 22 16:21:05 2010 UTC vs.
Revision 1.194 by sf-exg, Sun Jan 1 17:43:47 2012 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines