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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines