2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 #include <X11/Xutil.h>
39 #include "WindowMaker.h"
44 extern WPreferences wPreferences
;
47 static void bevelImage(RImage
*image
, int relief
);
52 wTextureMakeSolid(WScreen
*scr
, XColor
*color
)
58 texture
= wmalloc(sizeof(WTexture
));
60 texture
->type
= WTEX_SOLID
;
63 XAllocColor(dpy
, scr
->w_colormap
, color
);
64 texture
->normal
= *color
;
65 if (color
->red
==0 && color
->blue
==0 && color
->green
== 0) {
66 texture
->light
.red
= 0xb6da;
67 texture
->light
.green
= 0xb6da;
68 texture
->light
.blue
= 0xb6da;
69 texture
->dim
.red
= 0x6185;
70 texture
->dim
.green
= 0x6185;
71 texture
->dim
.blue
= 0x6185;
77 rgb
.red
= color
->red
>> 8;
78 rgb
.green
= color
->green
>> 8;
79 rgb
.blue
= color
->blue
>> 8;
80 RRGBtoHSV(&rgb
, &hsv
);
81 RHSVtoRGB(&hsv
, &rgb
);
85 hsv
.value
= (v
> 255 ? 255 : v
);
86 RHSVtoRGB(&hsv
, &rgb
);
87 texture
->light
.red
= rgb
.red
<< 8;
88 texture
->light
.green
= rgb
.green
<< 8;
89 texture
->light
.blue
= rgb
.blue
<< 8;
91 hsv2
.value
= hsv2
.value
/2;
92 RHSVtoRGB(&hsv2
, &rgb
);
93 texture
->dim
.red
= rgb
.red
<< 8;
94 texture
->dim
.green
= rgb
.green
<< 8;
95 texture
->dim
.blue
= rgb
.blue
<< 8;
97 texture
->dark
.red
= 0;
98 texture
->dark
.green
= 0;
99 texture
->dark
.blue
= 0;
100 XAllocColor(dpy
, scr
->w_colormap
, &texture
->light
);
101 XAllocColor(dpy
, scr
->w_colormap
, &texture
->dim
);
102 XAllocColor(dpy
, scr
->w_colormap
, &texture
->dark
);
104 gcm
= GCForeground
|GCBackground
|GCGraphicsExposures
;
105 gcv
.graphics_exposures
= False
;
107 gcv
.background
= gcv
.foreground
= texture
->light
.pixel
;
108 texture
->light_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
110 gcv
.background
= gcv
.foreground
= texture
->dim
.pixel
;
111 texture
->dim_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
113 gcv
.background
= gcv
.foreground
= texture
->dark
.pixel
;
114 texture
->dark_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
116 gcv
.background
= gcv
.foreground
= color
->pixel
;
117 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
124 dummyErrorHandler(Display
*foo
, XErrorEvent
*bar
)
127 wwarning("your server is buggy. Tell the author if some error related to color occurs");
134 wTextureDestroy(WScreen
*scr
, WTexture
*texture
)
138 unsigned long colors
[8];
142 printf("BUG: trying to free NULL texture\n");
148 * some stupid servers don't like white or black being freed...
150 #define CANFREE(c) (c!=scr->black_pixel && c!=scr->white_pixel && c!=0)
151 switch (texture
->any
.type
) {
153 XFreeGC(dpy
, texture
->solid
.light_gc
);
154 XFreeGC(dpy
, texture
->solid
.dark_gc
);
155 XFreeGC(dpy
, texture
->solid
.dim_gc
);
156 if (CANFREE(texture
->solid
.light
.pixel
))
157 colors
[count
++] = texture
->solid
.light
.pixel
;
158 if (CANFREE(texture
->solid
.dim
.pixel
))
159 colors
[count
++] = texture
->solid
.dim
.pixel
;
160 if (CANFREE(texture
->solid
.dark
.pixel
))
161 colors
[count
++] = texture
->solid
.dark
.pixel
;
165 RReleaseImage(texture
->pixmap
.pixmap
);
168 case WTEX_MHGRADIENT
:
169 case WTEX_MVGRADIENT
:
170 case WTEX_MDGRADIENT
:
171 for (i
=0; texture
->mgradient
.colors
[i
]!=NULL
; i
++) {
172 wfree(texture
->mgradient
.colors
[i
]);
174 wfree(texture
->mgradient
.colors
);
177 case WTEX_THGRADIENT
:
178 case WTEX_TVGRADIENT
:
179 case WTEX_TDGRADIENT
:
180 RReleaseImage(texture
->tgradient
.pixmap
);
183 #ifdef TEXTURE_PLUGIN
186 if (texture
->function
.handle
) {
187 dlclose(texture
->function
.handle
);
190 for (i
= 0; i
< texture
->function
.argc
; i
++) {
191 wfree(texture
->function
.argv
[i
]);
193 wfree(texture
->function
.argv
);
195 #endif /* TEXTURE_PLUGIN */
197 if (CANFREE(texture
->any
.color
.pixel
))
198 colors
[count
++] = texture
->any
.color
.pixel
;
200 XErrorHandler oldhandler
;
202 /* ignore error from buggy servers that don't know how
203 * to do reference counting for colors. */
205 oldhandler
= XSetErrorHandler(dummyErrorHandler
);
206 XFreeColors(dpy
, scr
->w_colormap
, colors
, count
, 0);
208 XSetErrorHandler(oldhandler
);
210 XFreeGC(dpy
, texture
->any
.gc
);
218 wTextureMakeGradient(WScreen
*scr
, int style
, RColor
*from
, RColor
*to
)
220 WTexGradient
*texture
;
224 texture
= wmalloc(sizeof(WTexture
));
225 memset(texture
, 0, sizeof(WTexture
));
226 texture
->type
= style
;
227 texture
->subtype
= 0;
229 texture
->color1
= *from
;
230 texture
->color2
= *to
;
232 texture
->normal
.red
= (from
->red
+ to
->red
)<<7;
233 texture
->normal
.green
= (from
->green
+ to
->green
)<<7;
234 texture
->normal
.blue
= (from
->blue
+ to
->blue
)<<7;
236 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
237 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
238 gcv
.graphics_exposures
= False
;
239 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
240 |GCGraphicsExposures
, &gcv
);
249 wTextureMakeIGradient(WScreen
*scr
, int thickness1
, RColor colors1
[2],
250 int thickness2
, RColor colors2
[2])
252 WTexIGradient
*texture
;
257 texture
= wmalloc(sizeof(WTexture
));
258 memset(texture
, 0, sizeof(WTexture
));
259 texture
->type
= WTEX_IGRADIENT
;
260 for (i
= 0; i
< 2; i
++) {
261 texture
->colors1
[i
] = colors1
[i
];
262 texture
->colors2
[i
] = colors2
[i
];
264 texture
->thickness1
= thickness1
;
265 texture
->thickness2
= thickness2
;
266 if (thickness1
>= thickness2
) {
267 texture
->normal
.red
= (colors1
[0].red
+ colors1
[1].red
)<<7;
268 texture
->normal
.green
= (colors1
[0].green
+ colors1
[1].green
)<<7;
269 texture
->normal
.blue
= (colors1
[0].blue
+ colors1
[1].blue
)<<7;
271 texture
->normal
.red
= (colors2
[0].red
+ colors2
[1].red
)<<7;
272 texture
->normal
.green
= (colors2
[0].green
+ colors2
[1].green
)<<7;
273 texture
->normal
.blue
= (colors2
[0].blue
+ colors2
[1].blue
)<<7;
275 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
276 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
277 gcv
.graphics_exposures
= False
;
278 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
279 |GCGraphicsExposures
, &gcv
);
287 wTextureMakeMGradient(WScreen
*scr
, int style
, RColor
**colors
)
289 WTexMGradient
*texture
;
294 texture
= wmalloc(sizeof(WTexture
));
295 memset(texture
, 0, sizeof(WTexture
));
296 texture
->type
= style
;
297 texture
->subtype
= 0;
300 while (colors
[i
]!=NULL
) i
++;
302 texture
->normal
.red
= (colors
[0]->red
<<8);
303 texture
->normal
.green
= (colors
[0]->green
<<8);
304 texture
->normal
.blue
= (colors
[0]->blue
<<8);
306 texture
->colors
= colors
;
308 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
309 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
310 gcv
.graphics_exposures
= False
;
311 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
312 |GCGraphicsExposures
, &gcv
);
320 wTextureMakePixmap(WScreen
*scr
, int style
, char *pixmap_file
, XColor
*color
)
327 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
329 wwarning(_("image file \"%s\" used as texture could not be found."),
333 image
= RLoadImage(scr
->rcontext
, file
, 0);
335 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
336 RMessageForError(RErrorCode
));
342 texture
= wmalloc(sizeof(WTexture
));
343 memset(texture
, 0, sizeof(WTexture
));
344 texture
->type
= WTEX_PIXMAP
;
345 texture
->subtype
= style
;
347 texture
->normal
= *color
;
349 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
350 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
351 gcv
.graphics_exposures
= False
;
352 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
353 |GCGraphicsExposures
, &gcv
);
355 texture
->pixmap
= image
;
361 wTextureMakeTGradient(WScreen
*scr
, int style
, RColor
*from
, RColor
*to
,
362 char *pixmap_file
, int opacity
)
364 WTexTGradient
*texture
;
369 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
371 wwarning(_("image file \"%s\" used as texture could not be found."),
375 image
= RLoadImage(scr
->rcontext
, file
, 0);
377 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
378 RMessageForError(RErrorCode
));
384 texture
= wmalloc(sizeof(WTexture
));
385 memset(texture
, 0, sizeof(WTexture
));
386 texture
->type
= style
;
388 texture
->opacity
= opacity
;
390 texture
->color1
= *from
;
391 texture
->color2
= *to
;
393 texture
->normal
.red
= (from
->red
+ to
->red
)<<7;
394 texture
->normal
.green
= (from
->green
+ to
->green
)<<7;
395 texture
->normal
.blue
= (from
->blue
+ to
->blue
)<<7;
397 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
398 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
399 gcv
.graphics_exposures
= False
;
400 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
401 |GCGraphicsExposures
, &gcv
);
403 texture
->pixmap
= image
;
409 #ifdef TEXTURE_PLUGIN
411 wTextureMakeFunction(WScreen
*scr
, char *lib
, char *func
, int argc
, char **argv
)
413 XColor fallbackColor
;
415 WTexFunction
*texture
;
417 texture
= wmalloc(sizeof(WTexture
));
418 texture
->type
= WTEX_FUNCTION
;
419 texture
->handle
= NULL
;
421 texture
->argc
= argc
;
422 texture
->argv
= argv
;
424 fallbackColor
.red
= 0x8000;
425 fallbackColor
.green
= 0x8000;
426 fallbackColor
.blue
= 0x8000;
428 gcv
.background
= gcv
.foreground
= fallbackColor
.pixel
;
429 gcv
.graphics_exposures
= False
;
430 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
431 |GCGraphicsExposures
, &gcv
);
434 /* open the library */
435 texture
->handle
= dlopen(lib
, RTLD_LAZY
);
436 if (!texture
->handle
) {
437 wwarning(_("library \"%s\" cound not be opened."), lib
);
443 /* find the function */
444 texture
->render
= dlsym(texture
->handle
, func
);
445 if (!texture
->render
) {
446 wwarning(_("function \"%s\" not found in library \"%s\""), func
, lib
);
448 dlclose(texture
->handle
);
453 wwarning(_("function textures not supported on this system, sorry."));
459 #endif /* TEXTURE_PLUGIN */
463 wTextureRenderImage(WTexture
*texture
, int width
, int height
,
466 RImage
*image
= NULL
;
471 switch (texture
->any
.type
) {
473 image
= RCreateImage(width
, height
, False
);
475 color1
.red
= texture
->solid
.normal
.red
>> 8;
476 color1
.green
= texture
->solid
.normal
.green
>> 8;
477 color1
.blue
= texture
->solid
.normal
.blue
>> 8;
480 RClearImage(image
, &color1
);
484 if (texture
->pixmap
.subtype
== WTP_TILE
) {
485 image
= RMakeTiledImage(texture
->pixmap
.pixmap
, width
, height
);
486 } else if (texture
->pixmap
.subtype
== WTP_CENTER
) {
487 color1
.red
= texture
->pixmap
.normal
.red
>>8;
488 color1
.green
= texture
->pixmap
.normal
.green
>>8;
489 color1
.blue
= texture
->pixmap
.normal
.blue
>>8;
491 image
= RMakeCenteredImage(texture
->pixmap
.pixmap
, width
, height
,
494 image
= RScaleImage(texture
->pixmap
.pixmap
, width
, height
);
499 image
= RRenderInterwovenGradient(width
, height
,
500 texture
->igradient
.colors1
,
501 texture
->igradient
.thickness1
,
502 texture
->igradient
.colors2
,
503 texture
->igradient
.thickness2
);
507 subtype
= RGRD_HORIZONTAL
;
508 goto render_gradient
;
511 subtype
= RGRD_VERTICAL
;
512 goto render_gradient
;
515 subtype
= RGRD_DIAGONAL
;
518 image
= RRenderGradient(width
, height
, &texture
->gradient
.color1
,
519 &texture
->gradient
.color2
, subtype
);
522 case WTEX_MHGRADIENT
:
523 subtype
= RGRD_HORIZONTAL
;
524 goto render_mgradient
;
526 case WTEX_MVGRADIENT
:
527 subtype
= RGRD_VERTICAL
;
528 goto render_mgradient
;
530 case WTEX_MDGRADIENT
:
531 subtype
= RGRD_DIAGONAL
;
533 image
= RRenderMultiGradient(width
, height
,
534 &(texture
->mgradient
.colors
[1]),
538 case WTEX_THGRADIENT
:
539 subtype
= RGRD_HORIZONTAL
;
540 goto render_tgradient
;
542 case WTEX_TVGRADIENT
:
543 subtype
= RGRD_VERTICAL
;
544 goto render_tgradient
;
546 case WTEX_TDGRADIENT
:
547 subtype
= RGRD_DIAGONAL
;
552 image
= RMakeTiledImage(texture
->tgradient
.pixmap
, width
, height
);
556 grad
= RRenderGradient(width
, height
, &texture
->tgradient
.color1
,
557 &texture
->tgradient
.color2
, subtype
);
559 RReleaseImage(image
);
564 RCombineImagesWithOpaqueness(image
, grad
,
565 texture
->tgradient
.opacity
);
570 #ifdef TEXTURE_PLUGIN
573 if (texture
->function
.render
) {
574 image
= texture
->function
.render (
575 texture
->function
.argc
, texture
->function
.argv
,
576 width
, height
, relief
);
580 RErrorCode
= RERR_INTERNAL
;
583 #endif /* TEXTURE_PLUGIN */
586 puts("ERROR in wTextureRenderImage()");
594 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
596 image
= RCreateImage(width
, height
, False
);
598 wwarning(_("could not allocate image buffer"));
606 RClearImage(image
, &gray
);
638 RBevelImage(image
, d
);
640 bevelImage(image
, -d
);
649 bevelImage(RImage
*image
, int relief
)
651 int width
= image
->width
;
652 int height
= image
->height
;
657 color
.red
= color
.green
= color
.blue
= 80;
660 ROperateLine(image
, RAddOperation
, 1, 0, width
-2, 0, &color
);
663 ROperateLine(image
, RAddOperation
, 0, 0, 0, height
-1, &color
);
665 color
.red
= color
.green
= color
.blue
= 40;
667 ROperateLine(image
, RSubtractOperation
, width
-1, 0, width
-1,
671 ROperateLine(image
, RSubtractOperation
, 1, height
-2, width
-2,
674 color
.red
= color
.green
= color
.blue
= 0;
676 RDrawLine(image
, 0, height
-1, width
-1, height
-1, &color
);
686 wDrawBevel(Drawable d
, unsigned width
, unsigned height
,
687 WTexSolid
*texture
, int relief
)
692 if (relief
==WREL_FLAT
) return;
694 light
= texture
->light_gc
;
695 dim
= texture
->dim_gc
;
696 dark
= texture
->dark_gc
;
704 segs
[0].x2
= width
- 2;
705 segs
[0].y2
= segs
[0].y1
= height
- 2;
706 segs
[1].x1
= width
- 2;
708 segs
[1].x2
= width
- 2;
709 segs
[1].y2
= height
- 2;
710 XDrawSegments(dpy
, d
, dim
, segs
, 2);
712 segs
[0].x2
= width
- 1;
713 segs
[0].y2
= segs
[0].y1
= height
- 1;
714 segs
[1].x1
= segs
[1].x2
= width
- 1;
716 segs
[1].y2
= height
- 1;
717 XDrawSegments(dpy
, d
, dark
, segs
, 2);
718 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 0;
719 segs
[0].x2
= width
- 2;
720 segs
[1].x1
= segs
[1].y1
= 0;
722 segs
[1].y2
= height
- 2;
723 XDrawSegments(dpy
, d
, light
, segs
, 2);
724 if (relief
==WREL_ICON
) {
725 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 1;
726 segs
[0].x2
= width
- 2;
727 segs
[1].x1
= segs
[1].y1
= 1;
729 segs
[1].y2
= height
- 2;
730 XDrawSegments(dpy
, d
, light
, segs
, 2);
736 segs
[0].x2
= width
- 1;
737 segs
[0].y2
= segs
[0].y1
= 0;
738 segs
[1].x1
= segs
[1].x2
= 0;
740 segs
[1].y2
= height
- 1;
741 XDrawSegments(dpy
, d
, dark
, segs
, 2);
744 segs
[0].y1
= segs
[0].y2
= height
- 1;
745 segs
[0].x2
= width
- 1;
746 segs
[1].x2
= segs
[1].x1
= width
- 1;
748 segs
[1].y2
= height
- 1;
749 XDrawSegments(dpy
, d
, light
, segs
, 2);