ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/xpm.C
Revision: 1.38
Committed: Fri Jun 8 20:04:12 2007 UTC (16 years, 11 months ago) by sasha
Content type: text/plain
Branch: MAIN
Changes since 1.37: +57 -3 lines
Log Message:
added preliminary support to use libAfterImage for background pixmap loading and rendering of transparency effects including blending of pixmap over background using several methods, and gaussian blurr of the transparency background

File Contents

# User Rev Content
1 root 1.34 /*----------------------------------------------------------------------*
2 pcg 1.12 * File: xpm.C
3 pcg 1.1 *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1997 Carsten Haitzler <raster@zip.com.au>
7     * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
8     * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
9 root 1.33 * Copyright (c) 2005-2006 Marc Lehmann <pcg@goof.com>
10 pcg 1.1 *
11     * This program is free software; you can redistribute it and/or modify
12     * it under the terms of the GNU General Public License as published by
13     * the Free Software Foundation; either version 2 of the License, or
14     * (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU General Public License
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24     *---------------------------------------------------------------------*/
25    
26     #include "../config.h" /* NECESSARY */
27     #include "rxvt.h" /* NECESSARY */
28    
29     #ifdef XPM_BACKGROUND
30    
31 root 1.22 static void rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight);
32    
33 pcg 1.1 /*
34     * These GEOM strings indicate absolute size/position:
35     * @ `WxH+X+Y'
36     * @ `WxH+X' -> Y = X
37     * @ `WxH' -> Y = X = 50
38     * @ `W+X+Y' -> H = W
39     * @ `W+X' -> H = W, Y = X
40     * @ `W' -> H = W, X = Y = 50
41     * @ `0xH' -> H *= H/100, X = Y = 50 (W unchanged)
42     * @ `Wx0' -> W *= W/100, X = Y = 50 (H unchanged)
43     * @ `=+X+Y' -> (H, W unchanged)
44     * @ `=+X' -> Y = X (H, W unchanged)
45     *
46     * These GEOM strings adjust position relative to current position:
47     * @ `+X+Y'
48     * @ `+X' -> Y = X
49     *
50     * And this GEOM string is for querying current scale/position:
51     * @ `?'
52     */
53     int
54 pcg 1.5 rxvt_term::scale_pixmap (const char *geom)
55 pcg 1.1 {
56 root 1.28 int flags, changed = 0;
57     int x = 0, y = 0;
58     unsigned int w = 0, h = 0;
59     unsigned int n;
60     char *p;
61 root 1.35 bgPixmap_t *bgpixmap = &bgPixmap;
62 pcg 1.1
63 root 1.28 #define MAXLEN_GEOM sizeof("[10000x10000+10000+10000]")
64 pcg 1.1
65 pcg 1.7 if (geom == NULL)
66     return 0;
67 root 1.28
68     char str[MAXLEN_GEOM];
69    
70 root 1.17 if (!strcmp (geom, "?"))
71 pcg 1.7 {
72 pcg 1.9 sprintf (str, "[%dx%d+%d+%d]", /* can't presume snprintf () ! */
73 root 1.28 min (bgpixmap->w, 32767), min (bgpixmap->h, 32767),
74     min (bgpixmap->x, 32767), min (bgpixmap->y, 32767));
75 pcg 1.11 process_xterm_seq (XTerm_title, str, CHAR_ST);
76 pcg 1.7 return 0;
77 pcg 1.1 }
78    
79 root 1.17 if ((p = strchr (geom, ';')) == NULL)
80     p = strchr (geom, '\0');
81 root 1.28
82 pcg 1.7 n = (p - geom);
83 root 1.35 if (n < MAXLEN_GEOM)
84 pcg 1.7 {
85 root 1.17 strncpy (str, geom, n);
86 pcg 1.7 str[n] = '\0';
87    
88 sasha 1.38 if (strcmp(str, "auto") == 0)
89     {
90     if (!bgpixmap->auto_resize)
91     changed++;
92     bgpixmap->auto_resize = True ;
93     w = szHint.width ;
94     h = szHint.height ;
95     flags = WidthValue|HeightValue ;
96     }
97     else
98     {
99     bgpixmap->auto_resize = False ;
100     flags = XParseGeometry (str, &x, &y, &w, &h);
101     }
102 root 1.28
103 pcg 1.7 if (!flags)
104     {
105     flags |= WidthValue;
106     w = 0;
107     } /* default is tile */
108 root 1.28
109 pcg 1.7 if (flags & WidthValue)
110     {
111 root 1.28 if (!(flags & XValue))
112 pcg 1.7 x = 50;
113 root 1.28
114     if (!(flags & HeightValue))
115 pcg 1.7 h = w;
116 root 1.28
117 pcg 1.7 if (w && !h)
118     {
119     w = (bgpixmap->w * w) / 100;
120     h = bgpixmap->h;
121     }
122     else if (h && !w)
123     {
124     w = bgpixmap->w;
125     h = (bgpixmap->h * h) / 100;
126     }
127 root 1.28
128     min_it (w, 32767);
129     min_it (h, 32767);
130    
131 pcg 1.7 if (bgpixmap->w != (short)w)
132     {
133     bgpixmap->w = (short)w;
134     changed++;
135     }
136 root 1.28
137 pcg 1.7 if (bgpixmap->h != (short)h)
138     {
139     bgpixmap->h = (short)h;
140     changed++;
141     }
142     }
143 root 1.28
144     if (!(flags & YValue))
145 pcg 1.7 {
146     if (flags & XNegative)
147     flags |= YNegative;
148 root 1.28
149 pcg 1.7 y = x;
150     }
151    
152 root 1.28 if (!(flags & WidthValue) && geom[0] != '=')
153 pcg 1.7 {
154     x += bgpixmap->x;
155     y += bgpixmap->y;
156     }
157 root 1.28
158     if (xpmAttr.width && xpmAttr.height)
159 pcg 1.7 {
160 root 1.28 x = MOD(x, xpmAttr.width);
161     y = MOD(y, xpmAttr.height);
162     }
163    
164 pcg 1.7 if (bgpixmap->x != x)
165     {
166     bgpixmap->x = x;
167     changed++;
168     }
169 root 1.28
170 pcg 1.7 if (bgpixmap->y != y)
171     {
172     bgpixmap->y = y;
173     changed++;
174     }
175 pcg 1.1 }
176 root 1.28
177 pcg 1.7 return changed;
178 pcg 1.1 }
179    
180     void
181 pcg 1.5 rxvt_term::resize_pixmap ()
182 pcg 1.1 {
183 root 1.27 XGCValues gcvalue;
184     GC gc;
185 pcg 1.7
186 root 1.24 if (pixmap != None)
187 sasha 1.38 {
188     XFreePixmap (dpy, pixmap);
189     pixmap = None ;
190     }
191 pcg 1.7
192     if (bgPixmap.pixmap == None)
193     { /* So be it: I'm not using pixmaps */
194 root 1.24 pixmap = None;
195 root 1.20
196 ayin 1.36 #ifdef TRANSPARENT
197 root 1.37 if (!option (Opt_transparent) || !am_transparent)
198 ayin 1.36 #endif
199 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
200 root 1.20
201 pcg 1.7 return;
202 pcg 1.1 }
203    
204 root 1.17 gcvalue.foreground = pix_colors[Color_bg];
205 root 1.31 gc = XCreateGC (dpy, vt, GCForeground, &gcvalue);
206 pcg 1.1
207 pcg 1.7 if (bgPixmap.pixmap != None)
208     { /* we have a specified pixmap */
209 root 1.28 unsigned int w = bgPixmap.w, h = bgPixmap.h,
210     x = bgPixmap.x, y = bgPixmap.y;
211     unsigned int xpmh = xpmAttr.height,
212     xpmw = xpmAttr.width;
213 pcg 1.7
214 sasha 1.38 if (bgPixmap.auto_resize)
215     {
216     w = szHint.width ;
217     h = szHint.height ;
218     }
219 pcg 1.7 /*
220     * don't zoom pixmap too much nor expand really small pixmaps
221     */
222 root 1.28 if (w > 32767 || h > 32767)
223 pcg 1.7 w = 1;
224     else if (width > (10 * xpmw)
225     || height > (10 * xpmh))
226     w = 0; /* tile */
227    
228 root 1.28 if (!w)
229 pcg 1.7 {
230     /* basic X tiling - let the X server do it */
231 root 1.31 pixmap = XCreatePixmap (dpy, vt, xpmw, xpmh, depth);
232 root 1.28
233 root 1.31 XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, y, xpmw - x, xpmh - y, 0, 0);
234     XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, x, 0, xpmw - x, y, 0, xpmh - y);
235     XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, y, x, xpmh - y, xpmw - x, 0);
236     XCopyArea (dpy, bgPixmap.pixmap, pixmap, gc, 0, 0, x, y, xpmw - x, xpmh - y);
237 pcg 1.7 }
238     else
239 sasha 1.38 #ifdef HAVE_AFTERIMAGE
240     #ifdef TRANSPARENT
241     if (!option(Opt_transparent) || !am_transparent)
242     /* will do that in check_our_parents otherwise */
243     #endif
244     {
245     ASImage *scaled_im = scale_asimage( display->asv, original_asim, w, h, ASA_XImage, 0, ASIMAGE_QUALITY_DEFAULT );
246     if (scaled_im)
247     {
248     pixmap = asimage2pixmap( display->asv, display->root, scaled_im, gc, True );
249     destroy_asimage( &scaled_im );
250     }
251     }
252     #else /* HAVE_AFTERIMAGE */
253 pcg 1.7 {
254 root 1.27 float incr, p;
255     Pixmap tmp;
256 pcg 1.7
257 root 1.31 pixmap = XCreatePixmap (dpy, vt, width, height, depth);
258 pcg 1.7 /*
259     * horizontal scaling
260     */
261 pcg 1.9 rxvt_pixmap_incr (&w, &x, &incr, &p, width, xpmw);
262 pcg 1.7
263 root 1.31 tmp = XCreatePixmap (dpy, vt, width, xpmh, depth);
264     XFillRectangle (dpy, tmp, gc, 0, 0, width, xpmh);
265 pcg 1.7
266     for ( /*nil */ ; x < w; x++, p += incr)
267     {
268     if (p >= xpmw)
269     p = 0;
270 root 1.28
271 pcg 1.7 /* copy one column from the original pixmap to the tmp pixmap */
272 root 1.31 XCopyArea (dpy, bgPixmap.pixmap, tmp, gc, (int)p, 0, 1, xpmh, (int)x, 0);
273 pcg 1.7 }
274    
275     /*
276     * vertical scaling
277     */
278 pcg 1.9 rxvt_pixmap_incr (&h, &y, &incr, &p, height, xpmh);
279 pcg 1.7
280     if (y > 0)
281 root 1.31 XFillRectangle (dpy, pixmap, gc, 0, 0, width, y);
282 root 1.20
283 pcg 1.7 if (h < height)
284 root 1.31 XFillRectangle (dpy, pixmap, gc, 0, (int)h, width, height - h + 1);
285 root 1.20
286 pcg 1.7 for ( /*nil */ ; y < h; y++, p += incr)
287     {
288     if (p >= xpmh)
289     p = 0;
290 root 1.20
291 pcg 1.7 /* copy one row from the tmp pixmap to the main pixmap */
292 root 1.31 XCopyArea (dpy, tmp, pixmap, gc, 0, (int)p, width, 1, 0, (int)y);
293 pcg 1.7 }
294 root 1.20
295 root 1.31 XFreePixmap (dpy, tmp);
296 pcg 1.7 }
297 sasha 1.38 #endif /* HAVE_AFTERIMAGE */
298 pcg 1.1 }
299 root 1.14
300 root 1.31 XSetWindowBackgroundPixmap (dpy, vt, pixmap);
301 root 1.28
302 root 1.31 XFreeGC (dpy, gc);
303 ayin 1.36 #ifdef TRANSPARENT
304 pcg 1.7 am_transparent = 0;
305 ayin 1.36 #endif
306 pcg 1.1 }
307    
308     /*
309     * Calculate tiling sizes and increments
310     * At start, p == 0, incr == xpmwidthheight
311     */
312 pcg 1.6 static void
313 pcg 1.9 rxvt_pixmap_incr (unsigned int *wh, unsigned int *xy, float *incr, float *p, unsigned int widthheight, unsigned int xpmwidthheight)
314 pcg 1.1 {
315 pcg 1.7 unsigned int cwh, cxy;
316     float cincr, cp;
317 pcg 1.1
318 pcg 1.7 cp = 0;
319     cincr = (float)xpmwidthheight;
320     cxy = *xy;
321     cwh = *wh;
322     if (cwh == 1)
323     { /* display one image, no horizontal/vertical scaling */
324     cincr = (float)widthheight;
325     if (xpmwidthheight <= widthheight)
326     {
327     cwh = xpmwidthheight;
328     cxy = (cxy * (widthheight - cwh)) / 100; /* beware! order */
329     cwh += cxy;
330     }
331     else
332     {
333     cxy = 0;
334     cwh = widthheight;
335     }
336 pcg 1.1 }
337 pcg 1.7 else if (cwh < 10)
338     { /* fit WH images across/down screen */
339     cincr *= cwh;
340     cxy = 0;
341     cwh = widthheight;
342     }
343     else
344     {
345     cincr *= 100.0 / cwh;
346     if (cwh < 100)
347     { /* contract */
348     float pos;
349    
350     cwh = (cwh * widthheight) / 100;
351     pos = (float)cxy / 100 * widthheight - (cwh / 2);
352    
353     cxy = (widthheight - cwh);
354     if (pos <= 0)
355     cxy = 0;
356     else if (pos < cxy)
357     cxy = (int) pos;
358     cwh += cxy;
359     }
360     else
361     { /* expand */
362     if (cxy > 0)
363     { /* position */
364     float pos;
365    
366     pos = (float)cxy / 100 * xpmwidthheight - (cincr / 2);
367     cp = xpmwidthheight - cincr;
368     if (pos <= 0)
369     cp = 0;
370     else if (pos < cp)
371     cp = pos;
372     }
373     cxy = 0;
374     cwh = widthheight;
375     }
376     }
377     cincr /= widthheight;
378     *wh = cwh;
379     *xy = cxy;
380     *incr = cincr;
381     *p = cp;
382 pcg 1.1 }
383    
384     Pixmap
385 pcg 1.5 rxvt_term::set_bgPixmap (const char *file)
386 pcg 1.1 {
387 root 1.21 char *f;
388 pcg 1.1
389 pcg 1.9 assert (file != NULL);
390 pcg 1.1
391 pcg 1.7 if (bgPixmap.pixmap != None)
392     {
393 root 1.31 XFreePixmap (dpy, bgPixmap.pixmap);
394 pcg 1.7 bgPixmap.pixmap = None;
395 pcg 1.1 }
396 root 1.19
397 root 1.31 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
398 pcg 1.1
399 pcg 1.7 if (*file != '\0')
400     {
401     /* XWindowAttributes attr; */
402    
403     /*
404     * we already have the required attributes
405     */
406 root 1.31 /* XGetWindowAttributes (dpy, vt, &attr); */
407 pcg 1.7
408 sasha 1.38 #ifdef HAVE_AFTERIMAGE
409     if (asimman == NULL)
410     asimman = create_generic_imageman(rs[Rs_path]);
411     if ((f = strchr (file, ';')) == NULL)
412     original_asim = get_asimage( asimman, file, 0xFFFFFFFF, 100 );
413     else
414     {
415     f = strndup( file, f - file );
416     original_asim = get_asimage( asimman, f, 0xFFFFFFFF, 100 );
417     free( f );
418     }
419     if (original_asim)
420     {
421     bgPixmap.pixmap = asimage2pixmap( display->asv, display->root, original_asim, NULL, True );
422     xpmAttr.width = original_asim->width ;
423     xpmAttr.height = original_asim->height ;
424     }
425     #else /* HAVE_AFTERIMAGE */
426 pcg 1.7 xpmAttr.closeness = 30000;
427 root 1.29 xpmAttr.colormap = cmap;
428     xpmAttr.visual = visual;
429     xpmAttr.depth = depth;
430     xpmAttr.valuemask = (XpmCloseness | XpmColormap | XpmVisual
431     | XpmDepth | XpmSize | XpmReturnPixels);
432 pcg 1.7
433     /* search environment variables here too */
434 pcg 1.9 f = (char *)rxvt_File_find (file, ".xpm", rs[Rs_path]);
435 pcg 1.7 if (f == NULL
436 root 1.31 || XpmReadFileToPixmap (dpy, display->root, f,
437 root 1.29 &bgPixmap.pixmap, NULL,
438     &xpmAttr))
439 pcg 1.7 {
440 pcg 1.10 char *p;
441 pcg 1.7
442     /* semi-colon delimited */
443 root 1.17 if ((p = strchr (file, ';')) == NULL)
444     p = strchr (file, '\0');
445 pcg 1.7
446 root 1.19 rxvt_warn ("couldn't load XPM file \"%.*s\", ignoring.\n", (p - file), file);
447 pcg 1.7 }
448 pcg 1.9 free (f);
449 sasha 1.38 #endif /* HAVE_AFTERIMAGE */
450 pcg 1.1 }
451 pcg 1.10
452 pcg 1.7 resize_pixmap ();
453     return bgPixmap.pixmap;
454 pcg 1.1 }
455    
456     #endif /* XPM_BACKGROUND */