2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Generic graphics and misc. utilities
24 extern Window main_win
;
25 #include "libs/fvwmlib.h"
26 #include "libs/PictureBase.h"
27 #include "libs/PictureUtils.h"
28 #include "libs/Graphics.h"
30 /* Masks to apply to color components when allocating colors
31 * you may want to set them to 0xffff if your display supports 16bpp+
33 #define RED_MASK 0xff00
34 #define GREEN_MASK 0xff00
35 #define BLUE_MASK 0xff00
37 * Allocates colors and fill a pixel value array. Color values are
38 * truncated with RED_MASK, GREEN_MASK and BLUE_MASK
40 * from,to are the primary colors to use
41 * maxcols is the number of colors
42 * colors is the array of pixel values
43 * light,dark are the colors for the relief
44 * dr,dg,db are the increment values for the colors
45 * alloc_relief if colors for relief should be allocated
46 * incr - 0 if gradient is light to dark, 1 if dark to light
48 int MakeColors(Display
*dpy
, Drawable d
, int from
[3], int to
[3], int maxcols
,
49 unsigned long *colors
, unsigned long *dark
,
50 unsigned long *light
, int dr
, int dg
, int db
,
51 int alloc_relief
, int incr
)
59 sr
= (float)dr
/ (float)maxcols
;
60 sg
= (float)dg
/ (float)maxcols
;
61 sb
= (float)db
/ (float)maxcols
;
65 /* kludge to frce color allocation in the first iteration on any case */
66 color
.red
= (from
[0] == 0) ? 0xffff : 0;
69 for(i
= 0; i
< maxcols
; i
++) {
70 /* color allocation saver */
71 red
= ((short)rv
) & RED_MASK
;
72 green
= ((short)gv
) & GREEN_MASK
;
73 blue
= ((short)bv
) & BLUE_MASK
;
74 if (color
.red
!= red
|| color
.green
!= green
|| color
.blue
!= blue
) {
78 if (PictureAllocColor(dpy
, Pcmap
, &color
, True
)==0) {
82 colors
[i
] = color
.pixel
;
86 if ((rv
> 65535.0) || (rv
< 0.0)) rv
-= sr
;
87 if ((gv
> 65535.0) || (gv
< 0.0)) gv
-= sg
;
88 if ((bv
> 65535.0) || (bv
< 0.0)) bv
-= sb
;
90 /* allocate 2 colors for the bevel */
93 rv
= (float)from
[0] * 0.8;
94 gv
= (float)from
[1] * 0.8;
95 bv
= (float)from
[2] * 0.8;
97 rv
= (float)to
[0] * 0.8;
98 gv
= (float)to
[1] * 0.8;
99 bv
= (float)to
[2] * 0.8;
101 color
.red
= (unsigned short)(rv
<0?0:rv
);
102 color
.green
= (unsigned short)(gv
<0?0:gv
);
103 color
.blue
= (unsigned short)(bv
<0?0:bv
);
104 if (PictureAllocColor(dpy
, Pcmap
, &color
, True
))
107 *dark
= colors
[incr
? 0 : maxcols
-1];
111 avg
= (float)(to
[0]+to
[1]+to
[2])/3;
112 rv
= avg
+ (float)(to
[0]/2);
113 gv
= avg
+ (float)(to
[1]/2);
114 bv
= avg
+ (float)(to
[2]/2);
117 avg
= (float)(from
[0]+from
[1]+from
[2])/3;
118 rv
= avg
+ (float)(from
[0]/2);
119 gv
= avg
+ (float)(from
[1]/2);
120 bv
= avg
+ (float)(from
[2]/2);
122 color
.red
= (unsigned short)(rv
>65535.0 ? 65535.0:rv
);
123 color
.green
= (unsigned short)(gv
>65535.0 ? 65535.0:gv
);
124 color
.blue
= (unsigned short)(bv
>65535.0 ? 65535.0:bv
);
125 if (PictureAllocColor(dpy
, Pcmap
, &color
, True
))
126 *light
= color
.pixel
;
128 *light
= colors
[incr
? maxcols
-1 : 0];
130 *light
= colors
[incr
? maxcols
-1 : 0];
131 *dark
= colors
[incr
? 0 : maxcols
-1];
139 * Draws a texture similar to Wharf's button background
141 * from: r,g,b values of top left color
142 * to: r,g,b values of bottom right color
143 * relief: relief to add to the borders. 0=flat, >0 raised, <0 sunken
144 * maxcols: # of max colors to use
146 * Aborts and returns 0 on error
149 int DrawDegradeRelief(Display
*dpy
, Drawable d
, int x
, int y
, int w
, int h
,
150 int from
[3], int to
[3], int relief
, int maxcols
)
153 int dr
, dg
, db
; /* delta */
158 unsigned long lightcolor
, darkcolor
;
160 unsigned long *colors
;
163 if (w
<= 0 || h
<= 0)
167 gc
= fvwmlib_XCreateGC(dpy
, d
, GCForeground
, &gcv
);
168 gc2
= fvwmlib_XCreateGC(dpy
, d
, GCForeground
, &gcv
);
170 dr
= to
[0] - from
[0];
171 dg
= to
[1] - from
[1];
172 db
= to
[2] - from
[2];
176 if (dmax
< abs(dg
)) {
180 if (dmax
< abs(db
)) {
184 /* if colors from and to are the same, force to one color */
190 maxcols
-= 2; /* reserve two colors for the relief */
197 if (dmax
< maxcols
) {
198 maxcols
= dmax
; /* we need less colors than we expected */
201 colors
= malloc(sizeof(unsigned long)*maxcols
);
203 if (!MakeColors(dpy
, d
, from
, to
, maxcols
, colors
, &darkcolor
, &lightcolor
,
204 dr
, dg
, db
, alloc_relief
, dmax2
>0))
208 s1
= (float)(maxcols
)/((float)w
*2.0);
209 pd
= relief
==0 ? 0 : 1;
210 for(py
= pd
; py
< h
-pd
; py
++) {
211 c1
= ((float)maxcols
/2.0)*((float)py
/(float)((h
-pd
*2)-1));
214 for(px
= pd
+x
; px
< w
-pd
+x
; px
++) {
216 if (i
>=maxcols
) i
=maxcols
-1;
217 if (j
!= colors
[i
]) {
219 XSetForeground(dpy
, gc
, j
);
220 XDrawLine(dpy
, d
, gc
, k
, y
+py
, px
, y
+py
);
225 XSetForeground(dpy
, gc
, colors
[i
]);
226 XDrawLine(dpy
, d
, gc
, k
, y
+py
, w
-pd
+x
, y
+py
);
231 XSetForeground(dpy
, gc
, lightcolor
);
232 XSetForeground(dpy
, gc2
, darkcolor
);
234 XSetForeground(dpy
, gc
, darkcolor
);
235 XSetForeground(dpy
, gc2
, lightcolor
);
237 XDrawLine(dpy
, d
, gc
, x
, y
, x
, y
+h
-1);
238 XDrawLine(dpy
, d
, gc
, x
, y
, x
+w
-1, y
);
239 XDrawLine(dpy
, d
, gc2
, x
, y
+h
-1, x
+w
-1, y
+h
-1);
240 XDrawLine(dpy
, d
, gc2
, x
+w
-1, y
, x
+w
-1, y
+h
-1);
250 * Draws a horizontal gradient
252 * from: r,g,b values of top color
253 * to: r,g,b values of bottom color
254 * relief: relief to add to the borders. 0=flat, >0 raised, <0 sunken
255 * maxcols: max colors to use
256 * type: gradient type. 0 for one-way, != 0 for cilindrical
258 * aborts and returns 0 on error.
260 int DrawHGradient(Display
*dpy
, Drawable d
, int x
, int y
, int w
, int h
,
261 int from
[3], int to
[3], int relief
, int maxcols
,
270 unsigned long *colors
, lightcolor
, darkcolor
;
274 if (w
<= 1 || h
<= 1)
278 gc
= fvwmlib_XCreateGC(dpy
, d
, GCForeground
, &gcv
);
279 gc2
= fvwmlib_XCreateGC(dpy
, d
, GCForeground
, &gcv
);
281 dr
= to
[0] - from
[0];
282 dg
= to
[1] - from
[1];
283 db
= to
[2] - from
[2];
286 if (abs(dmax
) < abs(dg
)) {
289 if (abs(dmax
) < abs(db
)) {
295 maxcols
-= 2; /* reserve two colors for the relief */
304 maxcols
= h
/2; /* we need less colors than we expected */
308 maxcols
= h
; /* we need less colors than we expected */
312 colors
=malloc(maxcols
*sizeof(unsigned long));
313 if (!MakeColors(dpy
, d
, from
, to
, maxcols
, colors
, &darkcolor
, &lightcolor
,
314 dr
, dg
, db
, alloc_relief
, dmax
>0))
318 s
= ((float)maxcols
*2)/(float)h
;
320 s
= (float)maxcols
/(float)h
;
322 pd
= relief
==0 ? 0 : 1;
325 if (type
==0) { /* one-way */
326 for(py
= pd
; py
< h
-pd
; py
++) {
328 if (i
>=maxcols
) i
=maxcols
-1;
330 XSetForeground(dpy
, gc
, colors
[i
]);
332 XDrawLine(dpy
, d
, gc
, x
+pd
, y
+py
, x
+w
-1-pd
, y
+py
);
336 } else { /* cylindrical */
337 for(py
= pd
; py
< h
-pd
; py
++) {
339 if (i
>=maxcols
) i
=maxcols
-1;
341 XSetForeground(dpy
, gc
, colors
[i
]);
343 XDrawLine(dpy
, d
, gc
, x
+pd
, y
+py
, x
+w
-1-pd
, y
+py
);
345 if (py
== h
/2) s
= -s
;
352 XSetForeground(dpy
, gc
, lightcolor
);
353 XSetForeground(dpy
, gc2
, darkcolor
);
355 XSetForeground(dpy
, gc
, darkcolor
);
356 XSetForeground(dpy
, gc2
, lightcolor
);
358 XDrawLine(dpy
, d
, gc
, x
, y
, x
, y
+h
-1);
359 XDrawLine(dpy
, d
, gc
, x
, y
, x
+w
-1, y
);
360 XDrawLine(dpy
, d
, gc2
, x
, y
+h
-1, x
+w
-1, y
+h
-1);
361 XDrawLine(dpy
, d
, gc2
, x
+w
-1, y
, x
+w
-1, y
+h
-1);
371 * Draws a vertical gradient
373 * from: r,g,b values of left color
374 * to: r,g,b values of right color
375 * relief: relief to add to the borders. 0=flat, >0 raised, <0 sunken
376 * maxcols: max colors to use
377 * type: gradient type. 0 for one-way, != 0 for cilindrical
379 * aborts and returns 0 on error.
381 int DrawVGradient(Display
*dpy
, Drawable d
, int x
, int y
, int w
, int h
,
382 int from
[3], int to
[3], int relief
, int maxcols
,
391 unsigned long *colors
, lightcolor
, darkcolor
;
395 if (w
<= 1 || h
<= 1)
399 gc
= fvwmlib_XCreateGC(dpy
, d
, GCForeground
, &gcv
);
400 gc2
= fvwmlib_XCreateGC(dpy
, d
, GCForeground
, &gcv
);
402 dr
= to
[0] - from
[0];
403 dg
= to
[1] - from
[1];
404 db
= to
[2] - from
[2];
407 if (abs(dmax
) < abs(dg
)) {
410 if (abs(dmax
) < abs(db
)) {
416 maxcols
-= 2; /* reserve two colors for the relief */
425 maxcols
= w
/2; /* we need less colors than we expected */
429 maxcols
= w
; /* we need less colors than we expected */
433 colors
=malloc(maxcols
*sizeof(unsigned long));
434 if (!MakeColors(dpy
, d
, from
, to
, maxcols
, colors
, &darkcolor
, &lightcolor
,
435 dr
, dg
, db
, alloc_relief
, dmax
>0))
439 s
= ((float)maxcols
*2)/(float)w
;
441 s
= (float)maxcols
/(float)w
;
443 pd
= relief
==0 ? 0 : 1;
446 if (type
==0) { /* one-way */
447 for(px
= pd
; px
< w
-pd
; px
++) {
449 if (i
>=maxcols
) i
=maxcols
-1;
451 XSetForeground(dpy
, gc
, colors
[i
]);
453 XDrawLine(dpy
, d
, gc
, x
+px
, y
+pd
, x
+px
, y
+h
-pd
-1);
457 } else { /* cylindrical */
458 for(px
= pd
; px
< w
-pd
; px
++) {
460 if (i
>=maxcols
) i
=maxcols
-1;
462 XSetForeground(dpy
, gc
, colors
[i
]);
464 XDrawLine(dpy
, d
, gc
, x
+px
, y
+pd
, x
+px
, y
+h
-pd
-1);
466 if (px
== w
/2) s
= -s
;
473 XSetForeground(dpy
, gc
, lightcolor
);
474 XSetForeground(dpy
, gc2
, darkcolor
);
476 XSetForeground(dpy
, gc
, darkcolor
);
477 XSetForeground(dpy
, gc2
, lightcolor
);
479 XDrawLine(dpy
, d
, gc
, x
, y
, x
, y
+h
-1);
480 XDrawLine(dpy
, d
, gc
, x
, y
, x
+w
-1, y
);
481 XDrawLine(dpy
, d
, gc2
, x
, y
+h
-1, x
+w
-1, y
+h
-1);
482 XDrawLine(dpy
, d
, gc2
, x
+w
-1, y
, x
+w
-1, y
+h
-1);
491 /* Draws text with a texture
493 * d - target drawable
494 * font - font to draw text
495 * x,y - position of text
496 * gradient - texture pixmap. size must be at least as large as text
497 * text - text to draw
498 * chars - chars in text
500 void DrawTexturedText(Display
*dpy
, Drawable d
, XFontStruct
*font
,
501 int x
, int y
, Pixmap gradient
, char *text
, int chars
)
509 /* make the mask pixmap */
510 w
= XTextWidth(font
,text
,chars
);
511 h
= font
->ascent
+font
->descent
;
512 mask
=XCreatePixmap(dpy
,main_win
,w
+1,h
+1,1);
514 gcv
.function
= GXcopy
;
515 gcv
.font
= font
->fid
;
516 gc
= fvwmlib_XCreateGC(dpy
,mask
,GCFunction
|GCForeground
|GCFont
,&gcv
);
517 XFillRectangle(dpy
,mask
,gc
,0,0,w
,h
);
518 XSetForeground(dpy
,gc
,1);
519 XDrawString(dpy
,mask
,gc
,0,font
->ascent
,text
,chars
);
521 /* draw the texture */
523 gc
= fvwmlib_XCreateGC(dpy
,d
,GCFunction
,&gcv
);
524 XSetClipOrigin(dpy
,gc
,x
,y
);
525 XSetClipMask(dpy
,gc
,mask
);
526 XCopyArea(dpy
,gradient
,d
,gc
,0,0,w
,h
,x
,y
);
528 XFreePixmap(dpy
,mask
);
534 int MakeShadowColors(Display
*dpy
, int from
[3], int to
[3],
535 unsigned long *dark
, unsigned long *light
)
541 dr
= to
[0] - from
[0];
542 dg
= to
[1] - from
[1];
543 db
= to
[2] - from
[2];
546 if (abs(dmax
) < abs(dg
)) {
549 if (abs(dmax
) < abs(db
)) {
553 /* allocate 2 colors for the bevel */
555 rv
= (float)from
[0] * 0.8;
556 gv
= (float)from
[1] * 0.8;
557 bv
= (float)from
[2] * 0.8;
559 rv
= (float)to
[0] * 0.8;
560 gv
= (float)to
[1] * 0.8;
561 bv
= (float)to
[2] * 0.8;
563 color
.red
= (short)(rv
<0?0:rv
);
564 color
.green
= (short)(gv
<0?0:gv
);
565 color
.blue
= (short)(bv
<0?0:bv
);
566 if (PictureAllocColor(dpy
, Pcmap
,&color
, True
))
573 avg
= (float)(to
[0]+to
[1]+to
[2])/3;
574 rv
= avg
+ (float)(to
[0]/2);
575 gv
= avg
+ (float)(to
[1]/2);
576 bv
= avg
+ (float)(to
[2]/2);
579 avg
= (float)(from
[0]+from
[1]+from
[2])/3;
580 rv
= avg
+ (float)(from
[0]/2);
581 gv
= avg
+ (float)(from
[1]/2);
582 bv
= avg
+ (float)(from
[2]/2);
584 color
.red
= (unsigned short)(rv
>65535.0 ? 65535.0:rv
);
585 color
.green
= (unsigned short)(gv
>65535.0 ? 65535.0:gv
);
586 color
.blue
= (unsigned short)(bv
>65535.0 ? 65535.0:bv
);
587 if (PictureAllocColor(dpy
, Pcmap
, &color
, True
))
588 *light
= color
.pixel
;