ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
(Generate patch)

Comparing rxvt-unicode/src/xpm.C (file contents):
Revision 1.20 by root, Wed Jan 26 07:08:15 2005 UTC vs.
Revision 1.56 by sasha, Fri Aug 3 22:40:10 2007 UTC

1/*--------------------------------*-C-*---------------------------------* 1/*----------------------------------------------------------------------*
2 * File: xpm.C 2 * File: 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) 1997 Carsten Haitzler <raster@zip.com.au> 6 * Copyright (c) 1997 Carsten Haitzler <raster@zip.com.au>
7 * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de> 7 * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
8 * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com> 8 * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
9 * Copyright (c) 2005-2006 Marc Lehmann <pcg@goof.com>
9 * 10 *
10 * This program is free software; you can redistribute it and/or modify 11 * 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 12 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or 13 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. 14 * (at your option) any later version.
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *---------------------------------------------------------------------*/ 24 *---------------------------------------------------------------------*/
24 25
25#include "../config.h" /* NECESSARY */ 26#include "../config.h" /* NECESSARY */
26#include "rxvt.h" /* NECESSARY */ 27#include "rxvt.h" /* NECESSARY */
27#include "xpm.intpro" /* PROTOS for internal routines */ 28
29/*
30 * Pixmap geometry string interpretation :
31 * Each geometry string contains zero or one scale/position
32 * adjustment and may optionally be followed by a colon and one or more
33 * colon-delimited pixmap operations.
34 * The following table shows the valid geometry strings and their
35 * affects on the background image :
36 *
37 * WxH+X+Y Set scaling to W% by H%, and position to X% by Y%.
38 * W and H are percentages of the terminal window size.
39 * X and Y are also percentages; e.g., +50+50 centers
40 * the image in the window.
41 * WxH+X Assumes Y == X
42 * WxH Assumes Y == X == 50 (centers the image)
43 * W+X+Y Assumes H == W
44 * W+X Assumes H == W and Y == X
45 * W Assumes H == W and Y == X == 50
46 *
47 * Adjusting position only :
48 * =+X+Y Set position to X% by Y% (absolute).
49 * =+X Set position to X% by X%.
50 * +X+Y Adjust position horizontally X% and vertically Y%
51 * from current position (relative).
52 * +X+X Adjust position horizontally X% and vertically X%
53 * from current position.
54 *
55 * Adjusting scale only :
56 * Wx0 Multiply horizontal scaling factor by W%
57 * 0xH Multiply vertical scaling factor by H%
58 * 0x0 No scaling (show image at normal size).
59 *
60 * Pixmap Operations : (should be prepended by a colon)
61 * tile Tile image. Scaling/position modifiers above will affect
62 * the tile size and origin.
63 * propscale When scaling, scale proportionally. That is, maintain the
64 * proper aspect ratio for the image. Any portion of the
65 * background not covered by the image is filled with the
66 * current background color.
67 * hscale Scale horizontally, tile vertically ?
68 * vscale Tile horizontally, scale vertically ?
69 * scale Scale both up and down
70 * auto Same as 100x100+50+50
71 */
72
73#ifdef HAVE_BG_PIXMAP
74bool
75bgPixmap_t::window_size_sensitive ()
76{
77 return (flags&(bgPmap_Scale|bgPmap_Transparent));
78}
28 79
29#ifdef XPM_BACKGROUND 80#ifdef XPM_BACKGROUND
30 81bool
31/* 82bgPixmap_t::handle_geometry (const char *geom)
32 * These GEOM strings indicate absolute size/position:
33 * @ `WxH+X+Y'
34 * @ `WxH+X' -> Y = X
35 * @ `WxH' -> Y = X = 50
36 * @ `W+X+Y' -> H = W
37 * @ `W+X' -> H = W, Y = X
38 * @ `W' -> H = W, X = Y = 50
39 * @ `0xH' -> H *= H/100, X = Y = 50 (W unchanged)
40 * @ `Wx0' -> W *= W/100, X = Y = 50 (H unchanged)
41 * @ `=+X+Y' -> (H, W unchanged)
42 * @ `=+X' -> Y = X (H, W unchanged)
43 *
44 * These GEOM strings adjust position relative to current position:
45 * @ `+X+Y'
46 * @ `+X' -> Y = X
47 *
48 * And this GEOM string is for querying current scale/position:
49 * @ `?'
50 */
51int
52rxvt_term::scale_pixmap (const char *geom)
53{ 83{
54 int flags, changed = 0; 84 int geom_flags, changed = 0;
55 int x = 0, y = 0; 85 int x = 0, y = 0;
56 unsigned int w = 0, h = 0; 86 unsigned int w = 0, h = 0;
57 unsigned int n; 87 unsigned int n;
58 char *p, *str; 88 unsigned long new_flags = (flags&(~bgPmap_geometryFlags)) ;
59 bgPixmap_t *bgpixmap = & (bgPixmap); 89 char *p;
60
61#define MAXLEN_GEOM sizeof("[1000x1000+1000+1000]") 90#define MAXLEN_GEOM sizeof("[10000x10000+10000+10000]")
62 91
63 if (geom == NULL) 92 if (geom == NULL)
64 return 0; 93 return false;
65 str = (char *)rxvt_malloc (MAXLEN_GEOM + 1); 94
95 char str[MAXLEN_GEOM];
96
66 if (!strcmp (geom, "?")) 97 if (!strcmp (geom, "?"))
67 { 98 {
99#if 0 /* TODO: */
68 sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */ 100 sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
69 min (bgpixmap->w, 9999), min (bgpixmap->h, 9999), 101 min (h_scale, 32767), min (v_scale, 32767),
70 min (bgpixmap->x, 9999), min (bgpixmap->y, 9999)); 102 min (h_align, 32767), min (v_align, 32767));
71 process_xterm_seq (XTerm_title, str, CHAR_ST); 103 process_xterm_seq (XTerm_title, str, CHAR_ST);
72 free (str); 104#endif
73 return 0; 105 return false;
74 } 106 }
75 107
76 if ((p = strchr (geom, ';')) == NULL) 108 if ((p = strchr (geom, ';')) == NULL)
77 p = strchr (geom, '\0'); 109 p = strchr (geom, '\0');
110
78 n = (p - geom); 111 n = (p - geom);
79 if (n <= MAXLEN_GEOM) 112 if (n < MAXLEN_GEOM)
80 { 113 {
114 new_flags |= bgPmap_geometrySet;
115
81 strncpy (str, geom, n); 116 strncpy (str, geom, n);
82 str[n] = '\0'; 117 str[n] = '\0';
83 118
119 if (strcmp(str, "auto") == 0)
120 {
121 w = h = 100;
122 geom_flags = WidthValue|HeightValue ;
123 }
124 else
125 {
84 flags = XParseGeometry (str, &x, &y, &w, &h); 126 geom_flags = XParseGeometry (str, &x, &y, &w, &h);
85 if (!flags)
86 { 127 }
128/* code below is garbage and needs to be rewritten */
129 if (!geom_flags)
130 {
87 flags |= WidthValue; 131 geom_flags |= WidthValue;
88 w = 0; 132 w = 0;
89 } /* default is tile */ 133 } /* default is tile */
134
90 if (flags & WidthValue) 135 if (geom_flags & WidthValue)
91 { 136 {
92 if (! (flags & XValue)) 137 if (!(geom_flags & XValue))
93 x = 50; 138 x = 50;
139
94 if (! (flags & HeightValue)) 140 if (!(geom_flags & HeightValue))
95 h = w; 141 h = w;
142
96 if (w && !h) 143 if (w && !h)
97 { 144 {
98 w = (bgpixmap->w * w) / 100; 145 w = (h_scale * w) / 100;
99 h = bgpixmap->h; 146 h = v_scale;
100 } 147 }
101 else if (h && !w) 148 else if (h && !w)
102 { 149 {
103 w = bgpixmap->w; 150 w = h_scale;
104 h = (bgpixmap->h * h) / 100; 151 h = (v_scale * h) / 100;
105 } 152 }
106 if (w > 1000) 153
107 w = 1000; 154 min_it (w, 32767);
108 if (h > 1000) 155 min_it (h, 32767);
109 h = 1000; 156
110 if (bgpixmap->w != (short)w) 157 if (h_scale != w)
111 { 158 {
112 bgpixmap->w = (short)w; 159 h_scale = w;
113 changed++; 160 changed++;
114 } 161 }
115 if (bgpixmap->h != (short)h) 162
163 if (v_scale != h)
116 { 164 {
117 bgpixmap->h = (short)h; 165 v_scale = h;
118 changed++; 166 changed++;
119 } 167 }
120 } 168 }
121 if (! (flags & YValue)) 169 if (!(geom_flags & YValue))
122 { 170 {
123 if (flags & XNegative) 171 if (geom_flags & XNegative)
124 flags |= YNegative; 172 geom_flags |= YNegative;
173
125 y = x; 174 y = x;
126 } 175 }
127 176
128 if (! (flags & WidthValue) && geom[0] != '=') 177 if (!(geom_flags & WidthValue) && geom[0] != '=')
129 {
130 x += bgpixmap->x;
131 y += bgpixmap->y;
132 } 178 {
133 else 179 x += h_align;
180 y += v_align;
134 { 181 }
135 if (flags & XNegative) 182
136 x += 100; 183 if (h_align != x)
137 if (flags & YNegative)
138 y += 100;
139 } 184 {
140 MIN_IT (x, 100); 185 h_align = x;
141 MIN_IT (y, 100);
142 MAX_IT (x, 0);
143 MAX_IT (y, 0);
144 if (bgpixmap->x != x)
145 {
146 bgpixmap->x = x;
147 changed++; 186 changed++;
148 } 187 }
149 if (bgpixmap->y != y) 188
189 if (v_align != y)
150 { 190 {
151 bgpixmap->y = y; 191 v_align = y;
152 changed++; 192 changed++;
153 } 193 }
194
195 if (h_scale != 0)
196 new_flags |= bgPmap_hScale;
197 if (v_scale != 0)
198 new_flags |= bgPmap_vScale;
199 }
200
201 if (new_flags != flags)
154 } 202 {
155 free (str); 203 flags = new_flags;
204 changed++;
205 }
156 return changed; 206 return (changed > 0);
157} 207}
158 208
159void 209void
160rxvt_term::resize_pixmap () 210rxvt_term::resize_pixmap ()
161{ 211{
162 XGCValues gcvalue; 212 XGCValues gcvalue;
163 GC gc; 213 GC gc;
164 unsigned int width = TermWin_TotalWidth (); 214 unsigned int w = bgPixmap.h_scale*szHint.width/100;
165 unsigned int height = TermWin_TotalHeight (); 215 unsigned int h = bgPixmap.v_scale*szHint.height/100;
166 216 int x = bgPixmap.h_align*szHint.width/100;
167 if (TermWin.pixmap != None) 217 int y = bgPixmap.v_align*szHint.height/100;
168 XFreePixmap (display->display, TermWin.pixmap); 218#ifdef HAVE_AFTERIMAGE
169 219 ASImage *im = bgPixmap.original_asim;
220#else
221 void *im = NULL;
222#endif
223/* preliminary cleanup - this needs to be integrated with check_our_parents() code */
170 if (bgPixmap.pixmap == None) 224 if (bgPixmap.pixmap != None)
225 {
226 XFreePixmap (dpy, bgPixmap.pixmap);
227 bgPixmap.pixmap = None ;
228 }
229#ifdef ENABLE_TRANSPARENCY
230 if (option(Opt_transparent) && am_transparent)
231 {
232 /* we need to re-generate transparency pixmap in that case ! */
233 check_our_parents ();
234 return;
235 }
236#endif
237
238 if (im == NULL)
171 { /* So be it: I'm not using pixmaps */ 239 { /* So be it: I'm not using pixmaps */
172 TermWin.pixmap = None; 240 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
173
174 if (!(options & Opt_transparent) || !am_transparent)
175 XSetWindowBackground (display->display, TermWin.vt,
176 pix_colors[Color_bg]);
177
178 return; 241 return;
179 } 242 }
180 243
181 gcvalue.foreground = pix_colors[Color_bg]; 244 gcvalue.foreground = pix_colors[Color_bg];
182 gc = XCreateGC (display->display, TermWin.vt, GCForeground, &gcvalue); 245 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
183 246
184 if (bgPixmap.pixmap != None)
185 { /* we have a specified pixmap */
186 unsigned int w = bgPixmap.w, h = bgPixmap.h,
187 x = bgPixmap.x, y = bgPixmap.y;
188 unsigned int xpmh = xpmAttr.height,
189 xpmw = xpmAttr.width;
190
191 /*
192 * don't zoom pixmap too much nor expand really small pixmaps 247 /* don't zoom pixmap too much nor expand really small pixmaps */
193 */ 248 if (w > 16000)
194 if (w > 1000 || h > 1000)
195 w = 1; 249 w = 1;
196 else if (width > (10 * xpmw) 250 if (h > 16000)
197 || height > (10 * xpmh)) 251 h = 1;
198 w = 0; /* tile */ 252
199 253#ifdef HAVE_AFTERIMAGE
200 if (w == 0) 254 if (w == 0)
201 { 255 w = im->width;
202 /* basic X tiling - let the X server do it */ 256 if (h == 0)
203 TermWin.pixmap = XCreatePixmap (display->display, TermWin.vt, 257 h = im->height;
204 xpmw, xpmh, 258
205 (unsigned int)display->depth); 259 if (w != im->width || h != im->height)
206 XCopyArea (display->display, bgPixmap.pixmap, TermWin.pixmap, gc, 260 {
207 0, 0, xpmw, xpmh, 0, 0); 261 ASImage *tmp = scale_asimage (asv, im, w, h, (x == 0 && y == 0)?ASA_XImage:ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
262 if (tmp != NULL)
263 im = tmp;
264 }
265 bgPixmap.pmap_width = MIN(w,szHint.width);
266 bgPixmap.pmap_height = MIN(h,szHint.height);
267#if 0 /* TODO: fix that! */
268 if (x != 0 || y != 0)
269 {
270 ASImage *tmp = tile_asimage (asv, im, x, y, w, h, TINT_LEAVE_SAME, ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
271 if (tmp != NULL)
208 } 272 {
209 else 273 if (im != bgPixmap.original_asim)
274 destroy_asimage (&im);
275 im = tmp;
210 { 276 }
211 float incr, p;
212 Pixmap tmp;
213
214 TermWin.pixmap = XCreatePixmap (display->display, TermWin.vt,
215 width, height,
216 (unsigned int)display->depth);
217 /*
218 * horizontal scaling
219 */
220 rxvt_pixmap_incr (&w, &x, &incr, &p, width, xpmw);
221
222 tmp = XCreatePixmap (display->display, TermWin.vt,
223 width, xpmh, (unsigned int)display->depth);
224 XFillRectangle (display->display, tmp, gc, 0, 0, width,
225 xpmh);
226
227 for ( /*nil */ ; x < w; x++, p += incr)
228 {
229 if (p >= xpmw)
230 p = 0;
231 /* copy one column from the original pixmap to the tmp pixmap */
232 XCopyArea (display->display, bgPixmap.pixmap, tmp, gc,
233 (int)p, 0, 1, xpmh, (int)x, 0);
234 }
235
236 /*
237 * vertical scaling
238 */
239 rxvt_pixmap_incr (&h, &y, &incr, &p, height, xpmh);
240
241 if (y > 0)
242 XFillRectangle (display->display, TermWin.pixmap, gc, 0, 0, width, y);
243
244 if (h < height)
245 XFillRectangle (display->display, TermWin.pixmap, gc, 0, (int)h, width, height - h + 1);
246
247 for ( /*nil */ ; y < h; y++, p += incr)
248 {
249 if (p >= xpmh)
250 p = 0;
251
252 /* copy one row from the tmp pixmap to the main pixmap */
253 XCopyArea (display->display, tmp, TermWin.pixmap, gc,
254 0, (int)p, width, 1, 0, (int)y);
255 }
256
257 XFreePixmap (display->display, tmp);
258 }
259 } 277 }
278#endif
279 bgPixmap.pixmap = XCreatePixmap (dpy, vt, bgPixmap.pmap_width, bgPixmap.pmap_height, depth);
280 bgPixmap.pmap_depth = depth;
260 281
261 XSetWindowBackgroundPixmap (display->display, TermWin.vt, TermWin.pixmap); 282 asimage2drawable (asv, bgPixmap.pixmap, im, gc, 0, 0, 0, 0, bgPixmap.pmap_width, bgPixmap.pmap_height, True);
283
284 if (im != bgPixmap.original_asim)
285 destroy_asimage (&im);
286#endif
287 if( bgPixmap.pixmap )
288 XSetWindowBackgroundPixmap (dpy, vt, bgPixmap.pixmap);
289
262 XFreeGC (display->display, gc); 290 XFreeGC (dpy, gc);
263 am_transparent = 0;
264} 291}
265 292
266/* 293void
267 * Calculate tiling sizes and increments
268 * At start, p == 0, incr == xpmwidthheight
269 */
270/* INTPROTO */
271static void
272rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
273{
274 unsigned int cwh, cxy;
275 float cincr, cp;
276
277 cp = 0;
278 cincr = (float)xpmwidthheight;
279 cxy = *xy;
280 cwh = *wh;
281 if (cwh == 1)
282 { /* display one image, no horizontal/vertical scaling */
283 cincr = (float)widthheight;
284 if (xpmwidthheight <= widthheight)
285 {
286 cwh = xpmwidthheight;
287 cxy = (cxy * (widthheight - cwh)) / 100; /* beware! order */
288 cwh += cxy;
289 }
290 else
291 {
292 cxy = 0;
293 cwh = widthheight;
294 }
295 }
296 else if (cwh < 10)
297 { /* fit WH images across/down screen */
298 cincr *= cwh;
299 cxy = 0;
300 cwh = widthheight;
301 }
302 else
303 {
304 cincr *= 100.0 / cwh;
305 if (cwh < 100)
306 { /* contract */
307 float pos;
308
309 cwh = (cwh * widthheight) / 100;
310 pos = (float)cxy / 100 * widthheight - (cwh / 2);
311
312 cxy = (widthheight - cwh);
313 if (pos <= 0)
314 cxy = 0;
315 else if (pos < cxy)
316 cxy = (int) pos;
317 cwh += cxy;
318 }
319 else
320 { /* expand */
321 if (cxy > 0)
322 { /* position */
323 float pos;
324
325 pos = (float)cxy / 100 * xpmwidthheight - (cincr / 2);
326 cp = xpmwidthheight - cincr;
327 if (pos <= 0)
328 cp = 0;
329 else if (pos < cp)
330 cp = pos;
331 }
332 cxy = 0;
333 cwh = widthheight;
334 }
335 }
336 cincr /= widthheight;
337 *wh = cwh;
338 *xy = cxy;
339 *incr = cincr;
340 *p = cp;
341}
342
343Pixmap
344rxvt_term::set_bgPixmap (const char *file) 294rxvt_term::set_bgPixmap (const char *file)
345{ 295{
346 char *f; 296 char *f;
347 297
348 assert (file != NULL); 298 assert (file != NULL);
349 299
350 if (bgPixmap.pixmap != None) 300 if (bgPixmap.pixmap != None)
351 { 301 {
352 XFreePixmap (display->display, bgPixmap.pixmap); 302 XFreePixmap (dpy, bgPixmap.pixmap);
353 bgPixmap.pixmap = None; 303 bgPixmap.pixmap = None;
354 } 304 }
355 305
356 XSetWindowBackground (display->display, TermWin.vt, pix_colors[Color_bg]); 306 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
357
358 if (*file != '\0') 307 if (*file != '\0')
359 { 308 {
360 /* XWindowAttributes attr; */ 309#ifdef HAVE_AFTERIMAGE
310 if (asimman == NULL)
311 asimman = create_generic_imageman(rs[Rs_path]);
312 if ((f = strchr (file, ';')) == NULL)
313 bgPixmap.original_asim = get_asimage( asimman, file, 0xFFFFFFFF, 100 );
314 else
315 {
316 size_t len = f - file;
317 f = (char *)malloc (len + 1);
318 strncpy (f, file, len);
319 f[len] = '\0';
320 bgPixmap.original_asim = get_asimage( asimman, f, 0xFFFFFFFF, 100 );
321 free( f );
322 }
323#endif
324 }
361 325
326 resize_pixmap ();
327}
328
329#endif /* XPM_BACKGROUND */
330#endif /* HAVE_BG_PIXMAP */
331
332#ifdef ENABLE_TRANSPARENCY
333#if TINTING && !defined(HAVE_AFTERIMAGE)
334/* taken from aterm-0.4.2 */
335
336typedef uint32_t RUINT32T;
337
338static void
339ShadeXImage(rxvt_term *term, XImage* srcImage, int shade, int rm, int gm, int bm)
340{
341 int sh_r, sh_g, sh_b;
342 RUINT32T mask_r, mask_g, mask_b;
343 RUINT32T *lookup, *lookup_r, *lookup_g, *lookup_b;
344 unsigned int lower_lim_r, lower_lim_g, lower_lim_b;
345 unsigned int upper_lim_r, upper_lim_g, upper_lim_b;
346 int i;
347
348 Visual *visual = term->visual;
349
350 if( visual->c_class != TrueColor || srcImage->format != ZPixmap ) return ;
351
352 /* for convenience */
353 mask_r = visual->red_mask;
354 mask_g = visual->green_mask;
355 mask_b = visual->blue_mask;
356
357 /* boring lookup table pre-initialization */
358 switch (srcImage->bits_per_pixel) {
359 case 15:
360 if ((mask_r != 0x7c00) ||
361 (mask_g != 0x03e0) ||
362 (mask_b != 0x001f))
363 return;
364 lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+32+32));
365 lookup_r = lookup;
366 lookup_g = lookup+32;
367 lookup_b = lookup+32+32;
368 sh_r = 10;
369 sh_g = 5;
370 sh_b = 0;
371 break;
372 case 16:
373 if ((mask_r != 0xf800) ||
374 (mask_g != 0x07e0) ||
375 (mask_b != 0x001f))
376 return;
377 lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+64+32));
378 lookup_r = lookup;
379 lookup_g = lookup+32;
380 lookup_b = lookup+32+64;
381 sh_r = 11;
382 sh_g = 5;
383 sh_b = 0;
384 break;
385 case 24:
386 if ((mask_r != 0xff0000) ||
387 (mask_g != 0x00ff00) ||
388 (mask_b != 0x0000ff))
389 return;
390 lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
391 lookup_r = lookup;
392 lookup_g = lookup+256;
393 lookup_b = lookup+256+256;
394 sh_r = 16;
395 sh_g = 8;
396 sh_b = 0;
397 break;
398 case 32:
399 if ((mask_r != 0xff0000) ||
400 (mask_g != 0x00ff00) ||
401 (mask_b != 0x0000ff))
402 return;
403 lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
404 lookup_r = lookup;
405 lookup_g = lookup+256;
406 lookup_b = lookup+256+256;
407 sh_r = 16;
408 sh_g = 8;
409 sh_b = 0;
410 break;
411 default:
412 return; /* we do not support this color depth */
413 }
414
415 /* prepare limits for color transformation (each channel is handled separately) */
416 if (shade < 0) {
417 shade = -shade;
418 if (shade < 0) shade = 0;
419 if (shade > 100) shade = 100;
420
421 lower_lim_r = 65535-rm;
422 lower_lim_g = 65535-gm;
423 lower_lim_b = 65535-bm;
424
425 lower_lim_r = 65535-(unsigned int)(((RUINT32T)lower_lim_r)*((RUINT32T)shade)/100);
426 lower_lim_g = 65535-(unsigned int)(((RUINT32T)lower_lim_g)*((RUINT32T)shade)/100);
427 lower_lim_b = 65535-(unsigned int)(((RUINT32T)lower_lim_b)*((RUINT32T)shade)/100);
428
429 upper_lim_r = upper_lim_g = upper_lim_b = 65535;
430 } else {
431 if (shade < 0) shade = 0;
432 if (shade > 100) shade = 100;
433
434 lower_lim_r = lower_lim_g = lower_lim_b = 0;
435
436 upper_lim_r = (unsigned int)((((RUINT32T)rm)*((RUINT32T)shade))/100);
437 upper_lim_g = (unsigned int)((((RUINT32T)gm)*((RUINT32T)shade))/100);
438 upper_lim_b = (unsigned int)((((RUINT32T)bm)*((RUINT32T)shade))/100);
439 }
440
441 /* switch red and blue bytes if necessary, we need it for some weird XServers like XFree86 3.3.3.1 */
442 if ((srcImage->bits_per_pixel == 24) && (mask_r >= 0xFF0000 ))
443 {
444 unsigned int tmp;
445
446 tmp = lower_lim_r;
447 lower_lim_r = lower_lim_b;
448 lower_lim_b = tmp;
449
450 tmp = upper_lim_r;
451 upper_lim_r = upper_lim_b;
452 upper_lim_b = tmp;
453 }
454
455 /* fill our lookup tables */
456 for (i = 0; i <= mask_r>>sh_r; i++)
457 {
458 RUINT32T tmp;
459 tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_r-lower_lim_r));
460 tmp += ((RUINT32T)(mask_r>>sh_r))*((RUINT32T)lower_lim_r);
461 lookup_r[i] = (tmp/65535)<<sh_r;
462 }
463 for (i = 0; i <= mask_g>>sh_g; i++)
464 {
465 RUINT32T tmp;
466 tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_g-lower_lim_g));
467 tmp += ((RUINT32T)(mask_g>>sh_g))*((RUINT32T)lower_lim_g);
468 lookup_g[i] = (tmp/65535)<<sh_g;
469 }
470 for (i = 0; i <= mask_b>>sh_b; i++)
471 {
472 RUINT32T tmp;
473 tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_b-lower_lim_b));
474 tmp += ((RUINT32T)(mask_b>>sh_b))*((RUINT32T)lower_lim_b);
475 lookup_b[i] = (tmp/65535)<<sh_b;
476 }
477
478 /* apply table to input image (replacing colors by newly calculated ones) */
479 switch (srcImage->bits_per_pixel)
480 {
481 case 15:
482 {
483 unsigned short *p1, *pf, *p, *pl;
484 p1 = (unsigned short *) srcImage->data;
485 pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
486 while (p1 < pf)
487 {
488 p = p1;
489 pl = p1 + srcImage->width;
490 for (; p < pl; p++)
491 {
492 *p = lookup_r[(*p & 0x7c00)>>10] |
493 lookup_g[(*p & 0x03e0)>> 5] |
494 lookup_b[(*p & 0x001f)];
495 }
496 p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
497 }
498 break;
499 }
500 case 16:
501 {
502 unsigned short *p1, *pf, *p, *pl;
503 p1 = (unsigned short *) srcImage->data;
504 pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
505 while (p1 < pf)
506 {
507 p = p1;
508 pl = p1 + srcImage->width;
509 for (; p < pl; p++)
510 {
511 *p = lookup_r[(*p & 0xf800)>>11] |
512 lookup_g[(*p & 0x07e0)>> 5] |
513 lookup_b[(*p & 0x001f)];
514 }
515 p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
516 }
517 break;
518 }
519 case 24:
520 {
521 unsigned char *p1, *pf, *p, *pl;
522 p1 = (unsigned char *) srcImage->data;
523 pf = (unsigned char *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
524 while (p1 < pf)
525 {
526 p = p1;
527 pl = p1 + srcImage->width * 3;
528 for (; p < pl; p += 3)
529 {
530 p[0] = lookup_r[(p[0] & 0xff0000)>>16];
531 p[1] = lookup_r[(p[1] & 0x00ff00)>> 8];
532 p[2] = lookup_r[(p[2] & 0x0000ff)];
533 }
534 p1 = (unsigned char *) ((char *) p1 + srcImage->bytes_per_line);
535 }
536 break;
537 }
538 case 32:
539 {
540 RUINT32T *p1, *pf, *p, *pl;
541 p1 = (RUINT32T *) srcImage->data;
542 pf = (RUINT32T *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
543
544 while (p1 < pf)
545 {
546 p = p1;
547 pl = p1 + srcImage->width;
548 for (; p < pl; p++)
549 {
550 *p = lookup_r[(*p & 0xff0000)>>16] |
551 lookup_g[(*p & 0x00ff00)>> 8] |
552 lookup_b[(*p & 0x0000ff)] |
553 (*p & ~0xffffff);
554 }
555 p1 = (RUINT32T *) ((char *) p1 + srcImage->bytes_per_line);
556 }
557 break;
558 }
559 }
560
561 free (lookup);
562}
563#endif
564
565/*
566 * Check our parents are still who we think they are.
567 * Do transparency updates if required
568 */
569int
570rxvt_term::check_our_parents ()
571{
572 check_our_parents_ev.stop ();
573 check_our_parents_ev.start (NOW + .1);
574 return 0;
575}
576
577void
578rxvt_term::check_our_parents_cb (time_watcher &w)
579{
580 int i, pchanged, aformat, rootdepth;
581 unsigned long nitems, bytes_after;
582 Atom atype;
583 unsigned char *prop = NULL;
584 Window root, oldp, *list;
585 Pixmap rootpixmap = None;
586 XWindowAttributes wattr, wrootattr;
587 int sx, sy;
588 Window cr;
589 unsigned int rootpixmap_w = 0, rootpixmap_h = 0;
590
591 pchanged = 0;
592
593 if (!option (Opt_transparent))
594 return /*pchanged*/; /* Don't try any more */
595
596#if 0
597 struct timeval stv;
598 gettimeofday (&stv,NULL);
599#define PRINT_BACKGROUND_OP_TIME do{ struct timeval tv;gettimeofday (&tv,NULL); tv.tv_sec-= stv.tv_sec;\
600 fprintf (stderr,"%d: elapsed %ld usec\n",__LINE__,\
601 tv.tv_sec*1000000+tv.tv_usec-stv.tv_usec );}while(0)
602#else
603#define PRINT_BACKGROUND_OP_TIME do{}while(0)
604#endif
605
606
607 XGetWindowAttributes (dpy, display->root, &wrootattr);
608 rootdepth = wrootattr.depth;
609
610 XGetWindowAttributes (dpy, parent[0], &wattr);
611
612 if (rootdepth != wattr.depth)
613 {
614 if (am_transparent)
615 {
616 pchanged = 1;
617 XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
618 am_transparent = am_pixmap_trans = 0;
619 }
620
621 return /*pchanged*/; /* Don't try any more */
622 }
623
624 /* Get all X ops out of the queue so that our information is up-to-date. */
625 XSync (dpy, False);
626
627 XTranslateCoordinates (dpy, parent[0], display->root,
628 0, 0, &sx, &sy, &cr);
629 /* check if we are outside of the visible part of the virtual screen : */
630 if( sx + (int)szHint.width <= 0 || sy + (int)szHint.height <= 0
631 || sx >= wrootattr.width || sy >= wrootattr.height )
632 return /* 0 */ ;
633 /*
634 * Make the frame window set by the window manager have
635 * the root background. Some window managers put multiple nested frame
636 * windows for each client, so we have to take care about that.
637 */
638 i = (xa[XA_XROOTPMAP_ID]
639 && XGetWindowProperty (dpy, display->root, xa[XA_XROOTPMAP_ID],
640 0L, 1L, False, XA_PIXMAP, &atype, &aformat,
641 &nitems, &bytes_after, &prop) == Success);
642
643 if (!i || prop == NULL)
644 i = (xa[XA_ESETROOT_PMAP_ID]
645 && XGetWindowProperty (dpy, display->root, xa[XA_ESETROOT_PMAP_ID],
646 0L, 1L, False, XA_PIXMAP, &atype, &aformat,
647 &nitems, &bytes_after, &prop) == Success);
648
649 /* TODO: the below logic needs to be cleaned up */
650 if (!i || prop == NULL
651#if TINTING
652 || (!ISSET_PIXCOLOR (Color_tint) && rs[Rs_shade] == NULL
653#ifdef HAVE_AFTERIMAGE
654 && bgPixmap.original_asim == NULL && rs[Rs_blurradius] == NULL
655#endif
656 )
657#endif
658 )
659 rootpixmap = None;
660 else
661 {
662 int junk;
663 unsigned int ujunk;
664 /* root pixmap may be bad - allow a error */
665 allowedxerror = -1;
666 if ((rootpixmap = *(Pixmap *)prop) != None)
667 if (!XGetGeometry (dpy, rootpixmap, &root, &junk, &junk, &rootpixmap_w, &rootpixmap_h, &ujunk, &ujunk))
668 rootpixmap = None;
669 allowedxerror = 0;
670 }
671
672 if (prop != NULL)
673 XFree (prop);
674
675 if (rootpixmap != None)
676 {
677 Bool success = False;
678 GC gc = NULL;
679 XGCValues gcvalue;
680 int shade = 100;
681 rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC);
682 Bool whole_tint = False, no_tint = True;
683
684 while (sx < 0) sx += (int)wrootattr.width;
685 while (sy < 0) sy += (int)wrootattr.height;
686
687#if TINTING
688 if (rs[Rs_shade])
689 shade = atoi (rs[Rs_shade]);
690 if (ISSET_PIXCOLOR (Color_tint))
691 pix_colors_focused [Color_tint].get (c);
692#define IS_COMPONENT_WHOLESOME(c) ((c) <=0x000700 || (c)>=0x00f700)
693 if (shade >= 100)
694 whole_tint = (IS_COMPONENT_WHOLESOME(c.r)
695 && IS_COMPONENT_WHOLESOME(c.g)
696 && IS_COMPONENT_WHOLESOME(c.b));
697 no_tint = (c.r >= 0x00f700 && c.g >= 0x00f700 && c.b >= 0x00f700);
698#undef IS_COMPONENT_WHOLESOME
699#endif /* TINTING */
700 /* theer are no performance advantages to reusing same pixmap */
701 if (bgPixmap.pixmap != None)
702 XFreePixmap (dpy, bgPixmap.pixmap);
703 bgPixmap.pixmap = XCreatePixmap (dpy, vt, szHint.width, szHint.height, rootdepth);
704 bgPixmap.pmap_width = szHint.width;
705 bgPixmap.pmap_height = szHint.height;
706 bgPixmap.pmap_depth = rootdepth;
707
708#if 0 /* TODO : identify cases where this will be detrimental to performance : */
709 /* we want to tile root pixmap into our own pixmap in this cases :
710 * 1) rootpixmap does not cover our window entirely
711 * 2) whole_tint - we can use server-side tinting or tinting disabled
712 */
713 if ( whole_tint || no_tint || pmap_w < sx + szHint.width || pmap_h < sy + szHint.height)
714 {
715 }
716#endif
717 gcvalue.tile = rootpixmap;
718 gcvalue.fill_style = FillTiled;
719 gcvalue.ts_x_origin = -sx;
720 gcvalue.ts_y_origin = -sy;
721 gc = XCreateGC (dpy, rootpixmap, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &gcvalue);
722 XFillRectangle (dpy, bgPixmap.pixmap, gc, 0, 0, szHint.width, szHint.height);
723
724#if TINTING
725 if (whole_tint && !no_tint)
726 {
727 /* In this case we can tint image server-side getting significant
728 * performance improvements, as we eliminate XImage transfer
729 */
730 gcvalue.foreground = Pixel (pix_colors_focused [Color_tint]);
731 gcvalue.function = GXand;
732 gcvalue.fill_style = FillSolid;
733 XChangeGC (dpy, gc, GCFillStyle | GCForeground | GCFunction, &gcvalue);
734 XFillRectangle (dpy, bgPixmap.pixmap, gc, 0, 0, szHint.width, szHint.height);
735 }
736#endif
737 success = True;
738#ifdef HAVE_AFTERIMAGE
739 if (rs[Rs_blurradius] || bgPixmap.original_asim != NULL || (!whole_tint && (!no_tint || shade !=100)))
740 {
741 ARGB32 tint = TINT_LEAVE_SAME;
742 ASImage *back_im = NULL;
743
744 back_im = pixmap2ximage (asv, bgPixmap.pixmap, 0, 0, szHint.width, szHint.height, AllPlanes, 100);
745 if (back_im != NULL)
746 {
747 if (!whole_tint && (!no_tint || shade !=100))
748 {
749 ShadingInfo as_shade;
750 as_shade.shading = shade;
751 as_shade.tintColor.red = c.r;
752 as_shade.tintColor.green = c.g;
753 as_shade.tintColor.blue = c.b;
754 tint = shading2tint32 (&as_shade);
755 }
756
757 if (rs[Rs_blurradius] && back_im)
758 {
759 ASImage* tmp;
760 int junk;
761 unsigned int hr = 1, vr = 1;
762 int flags = XParseGeometry (rs[Rs_blurradius], &junk, &junk, &hr, &vr);
763 if (!(flags&WidthValue))
764 hr = 1;
765 if (!(flags&HeightValue))
766 vr = hr;
767 tmp = blur_asimage_gauss (asv, back_im, hr, vr, 0xFFFFFFFF,
768 (bgPixmap.original_asim == NULL || tint == TINT_LEAVE_SAME)?ASA_XImage:ASA_ASImage,
769 100, ASIMAGE_QUALITY_DEFAULT);
770 if (tmp)
771 {
772 destroy_asimage (&back_im);
773 back_im = tmp;
774 }
775 }
776
777 if (bgPixmap.original_asim != NULL)
778 {
779 ASImageLayer *layers = create_image_layers (2);
780 ASImage *merged_im = NULL;
781 int fore_w, fore_h;
782
783 layers[0].im = back_im;
784 layers[0].clip_width = szHint.width;
785 layers[0].clip_height = szHint.height;
786 layers[0].tint = tint;
787 layers[1].im = bgPixmap.original_asim;
788
789 fore_w = (bgPixmap.h_scale == 0) ? bgPixmap.original_asim->width : bgPixmap.h_scale*szHint.width/100;
790 fore_h = (bgPixmap.v_scale == 0) ? bgPixmap.original_asim->height : bgPixmap.v_scale*szHint.height/100;
791
792 if (fore_w != bgPixmap.original_asim->width
793 || fore_h != bgPixmap.original_asim->height)
794 {
795 layers[1].im = scale_asimage (asv,
796 bgPixmap.original_asim,
797 fore_w, fore_h,
798 ASA_ASImage, 100,
799 ASIMAGE_QUALITY_DEFAULT);
800 }
801 layers[1].clip_width = szHint.width;
802 layers[1].clip_height = szHint.height;
803
804 if (rs[Rs_blendtype])
805 {
806 layers[1].merge_scanlines = blend_scanlines_name2func (rs[Rs_blendtype]);
807 if (layers[1].merge_scanlines == NULL)
808 layers[1].merge_scanlines = alphablend_scanlines;
809 }
810 PRINT_BACKGROUND_OP_TIME;
811 merged_im = merge_layers (asv, layers, 2, szHint.width, szHint.height,
812 ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT);
813 if (layers[1].im != bgPixmap.original_asim)
814 destroy_asimage (&(layers[1].im));
815 free (layers);
816
817 if (merged_im != NULL)
818 {
819 destroy_asimage (&back_im);
820 back_im = merged_im;
821 }
822 PRINT_BACKGROUND_OP_TIME;
823 }
824 else if (tint != TINT_LEAVE_SAME)
825 {
826 ASImage* tmp = tile_asimage (asv, back_im, 0, 0, szHint.width, szHint.height, tint, ASA_XImage, 100, ASIMAGE_QUALITY_DEFAULT);
827 if (tmp)
828 {
829 destroy_asimage (&back_im);
830 back_im = tmp;
831 }
832 PRINT_BACKGROUND_OP_TIME;
833 }
834 asimage2drawable (asv, bgPixmap.pixmap, back_im, gc, 0, 0, 0, 0, szHint.width, szHint.height, True);
835 destroy_asimage (&back_im);
836 } /* back_im != NULL */
837 else
838 success = False;
839 }
840#else /* HAVE_AFTERIMAGE */
841#if TINTING
842 if (!whole_tint && (!no_tint || shade !=100))
843 {
844 XImage *image = XGetImage (dpy, bgPixmap.pixmap, 0, 0, szHint.width, szHint.height, AllPlanes, ZPixmap);
845 success = False;
846 if (image != NULL)
847 {
848 PRINT_BACKGROUND_OP_TIME;
849 if (gc == NULL)
850 gc = XCreateGC (dpy, vt, 0UL, &gcvalue);
851 if (ISSET_PIXCOLOR (Color_tint) || shade != 100)
852 ShadeXImage (this, image, shade, c.r, c.g, c.b);
853 XPutImage (dpy, bgPixmap.pixmap, gc, image, 0, 0, 0, 0, image->width, image->height);
854 XDestroyImage (image);
855 success = True;
856 }
857 }
858#endif
859#endif /* HAVE_AFTERIMAGE */
860 PRINT_BACKGROUND_OP_TIME;
861
862 if (gc != NULL)
863 XFreeGC (dpy, gc);
864
865 if (!success)
866 {
867 if (am_transparent && am_pixmap_trans)
868 {
869 pchanged = 1;
870 if (bgPixmap.pixmap != None)
871 {
872 XFreePixmap (dpy, bgPixmap.pixmap);
873 bgPixmap.pixmap = None;
874 }
875 }
876
877 am_pixmap_trans = 0;
878 }
879 else
880 {
881 XSetWindowBackgroundPixmap (dpy, parent[0], bgPixmap.pixmap);
882 XClearWindow (dpy, parent[0]);
883
884 if (!am_transparent || !am_pixmap_trans)
885 pchanged = 1;
886
887 am_transparent = am_pixmap_trans = 1;
888 }
889 } /* rootpixmap != None */
890
891 if (am_pixmap_trans)
892 XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
893 else
894 {
895 unsigned int n;
362 /* 896 /*
363 * we already have the required attributes 897 * InheritPixmap transparency
364 */ 898 */
365 /* XGetWindowAttributes (display->display, TermWin.vt, &attr); */ 899 for (i = 1; i < (int) (sizeof (parent) / sizeof (Window)); i++)
900 {
901 oldp = parent[i];
902 XQueryTree (dpy, parent[i - 1], &root, &parent[i], &list, &n);
903 XFree (list);
366 904
367 xpmAttr.closeness = 30000; 905 if (parent[i] == display->root)
368 xpmAttr.colormap = display->cmap; 906 {
369 xpmAttr.visual = display->visual; 907 if (oldp != None)
370 xpmAttr.depth = display->depth; 908 pchanged = 1;
371 xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual |
372 XpmDepth | XpmSize | XpmReturnPixels);
373 909
374 /* search environment variables here too */ 910 break;
375 f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]); 911 }
376 if (f == NULL 912
377 || XpmReadFileToPixmap (display->display, display->root, f, 913 if (oldp != parent[i])
378 &bgPixmap.pixmap, NULL, 914 pchanged = 1;
379 &xpmAttr)) 915 }
916
917 n = 0;
918
919 if (pchanged)
920 for (; n < (unsigned int)i; n++)
380 { 921 {
381 char *p; 922 XGetWindowAttributes (dpy, parent[n], &wattr);
382 923
383 /* semi-colon delimited */ 924 if (wattr.depth != rootdepth || wattr.c_class == InputOnly)
384 if ((p = strchr (file, ';')) == NULL) 925 {
385 p = strchr (file, '\0'); 926 n = (int) (sizeof (parent) / sizeof (Window)) + 1;
386 927 break;
387 rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file); 928 }
388 } 929 }
389 930
390 free (f); 931 if (n > (sizeof (parent) / sizeof (parent[0])))
932 {
933 XSetWindowBackground (dpy, parent[0], pix_colors_focused[Color_border]);
934 XSetWindowBackground (dpy, vt, pix_colors_focused[Color_bg]);
935 am_transparent = 0;
936 /* XXX: also turn off Opt_transparent? */
937 }
938 else
939 {
940 for (n = 0; n < (unsigned int)i; n++)
941 {
942 XSetWindowBackgroundPixmap (dpy, parent[n], ParentRelative);
943 XClearWindow (dpy, parent[n]);
944 }
945
946 XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
947 am_transparent = 1;
948 }
949
950 for (; i < (int) (sizeof (parent) / sizeof (Window)); i++)
951 parent[i] = None;
952 }
953
954 if (scrollBar.win)
391 } 955 {
956 XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative);
957 scrollBar.setIdle ();
958 scrollbar_show (0);
959 }
392 960
393 resize_pixmap (); 961 if (am_transparent)
394 return bgPixmap.pixmap; 962 {
963 want_refresh = want_full_refresh = 1;
964 if (am_pixmap_trans)
965 flush ();
966 }
967
968// return pchanged;
395} 969}
396 970#endif
397#endif /* XPM_BACKGROUND */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines