2 * Window Maker window manager
4 * Copyright (c) 1997, 1998 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 RDestroyImage(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 free(texture
->mgradient
.colors
[i
]);
174 free(texture
->mgradient
.colors
);
177 case WTEX_THGRADIENT
:
178 case WTEX_TVGRADIENT
:
179 case WTEX_TDGRADIENT
:
180 RDestroyImage(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 free(texture
->function
.argv
[i
]);
193 free(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
);
248 wTextureMakeMGradient(WScreen
*scr
, int style
, RColor
**colors
)
250 WTexMGradient
*texture
;
255 texture
= wmalloc(sizeof(WTexture
));
256 memset(texture
, 0, sizeof(WTexture
));
257 texture
->type
= style
;
258 texture
->subtype
= 0;
261 while (colors
[i
]!=NULL
) i
++;
263 texture
->normal
.red
= (colors
[0]->red
<<8);
264 texture
->normal
.green
= (colors
[0]->green
<<8);
265 texture
->normal
.blue
= (colors
[0]->blue
<<8);
267 texture
->colors
= colors
;
269 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
270 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
271 gcv
.graphics_exposures
= False
;
272 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
273 |GCGraphicsExposures
, &gcv
);
281 wTextureMakePixmap(WScreen
*scr
, int style
, char *pixmap_file
, XColor
*color
)
288 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
290 wwarning(_("image file \"%s\" used as texture could not be found."),
294 image
= RLoadImage(scr
->rcontext
, file
, 0);
296 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
297 RMessageForError(RErrorCode
));
303 texture
= wmalloc(sizeof(WTexture
));
304 memset(texture
, 0, sizeof(WTexture
));
305 texture
->type
= WTEX_PIXMAP
;
306 texture
->subtype
= style
;
308 texture
->normal
= *color
;
310 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
311 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
312 gcv
.graphics_exposures
= False
;
313 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
314 |GCGraphicsExposures
, &gcv
);
316 texture
->pixmap
= image
;
324 wTextureMakeTGradient(WScreen
*scr
, int style
, RColor
*from
, RColor
*to
,
325 char *pixmap_file
, int opacity
)
327 WTexTGradient
*texture
;
332 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
334 wwarning(_("image file \"%s\" used as texture could not be found."),
338 image
= RLoadImage(scr
->rcontext
, file
, 0);
340 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
341 RMessageForError(RErrorCode
));
347 texture
= wmalloc(sizeof(WTexture
));
348 memset(texture
, 0, sizeof(WTexture
));
349 texture
->type
= style
;
351 texture
->opacity
= opacity
;
353 texture
->color1
= *from
;
354 texture
->color2
= *to
;
356 texture
->normal
.red
= (from
->red
+ to
->red
)<<7;
357 texture
->normal
.green
= (from
->green
+ to
->green
)<<7;
358 texture
->normal
.blue
= (from
->blue
+ to
->blue
)<<7;
360 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
361 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
362 gcv
.graphics_exposures
= False
;
363 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
364 |GCGraphicsExposures
, &gcv
);
366 texture
->pixmap
= image
;
372 #ifdef TEXTURE_PLUGIN
374 wTextureMakeFunction(WScreen
*scr
, char *lib
, char *func
, int argc
, char **argv
)
376 XColor fallbackColor
;
378 WTexFunction
*texture
;
380 texture
= wmalloc(sizeof(WTexture
));
381 texture
->type
= WTEX_FUNCTION
;
382 texture
->handle
= NULL
;
384 texture
->argc
= argc
;
385 texture
->argv
= argv
;
387 fallbackColor
.red
= 0x8000;
388 fallbackColor
.green
= 0x8000;
389 fallbackColor
.blue
= 0x8000;
391 gcv
.background
= gcv
.foreground
= fallbackColor
.pixel
;
392 gcv
.graphics_exposures
= False
;
393 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
394 |GCGraphicsExposures
, &gcv
);
397 /* open the library */
398 texture
->handle
= dlopen(lib
, RTLD_LAZY
);
399 if (!texture
->handle
) {
400 wwarning(_("library \"%s\" cound not be opened."), lib
);
406 /* find the function */
407 texture
->render
= dlsym(texture
->handle
, func
);
408 if (!texture
->render
) {
409 wwarning(_("function \"%s\" not found in library \"%s\""), func
, lib
);
411 dlclose(texture
->handle
);
416 wwarning(_("function textures not supported on this system, sorry."));
422 #endif /* TEXTURE_PLUGIN */
426 wTextureRenderImage(WTexture
*texture
, int width
, int height
,
429 RImage
*image
= NULL
;
434 switch (texture
->any
.type
) {
436 image
= RCreateImage(width
, height
, False
);
438 color1
.red
= texture
->solid
.normal
.red
>> 8;
439 color1
.green
= texture
->solid
.normal
.green
>> 8;
440 color1
.blue
= texture
->solid
.normal
.blue
>> 8;
443 RClearImage(image
, &color1
);
447 if (texture
->pixmap
.subtype
== WTP_TILE
) {
448 image
= RMakeTiledImage(texture
->pixmap
.pixmap
, width
, height
);
449 } else if (texture
->pixmap
.subtype
== WTP_CENTER
) {
450 color1
.red
= texture
->pixmap
.normal
.red
>>8;
451 color1
.green
= texture
->pixmap
.normal
.green
>>8;
452 color1
.blue
= texture
->pixmap
.normal
.blue
>>8;
454 image
= RMakeCenteredImage(texture
->pixmap
.pixmap
, width
, height
,
457 image
= RScaleImage(texture
->pixmap
.pixmap
, width
, height
);
462 subtype
= RGRD_HORIZONTAL
;
463 goto render_gradient
;
466 subtype
= RGRD_VERTICAL
;
467 goto render_gradient
;
470 subtype
= RGRD_DIAGONAL
;
473 image
= RRenderGradient(width
, height
, &texture
->gradient
.color1
,
474 &texture
->gradient
.color2
, subtype
);
477 case WTEX_MHGRADIENT
:
478 subtype
= RGRD_HORIZONTAL
;
479 goto render_mgradient
;
481 case WTEX_MVGRADIENT
:
482 subtype
= RGRD_VERTICAL
;
483 goto render_mgradient
;
485 case WTEX_MDGRADIENT
:
486 subtype
= RGRD_DIAGONAL
;
488 image
= RRenderMultiGradient(width
, height
,
489 &(texture
->mgradient
.colors
[1]),
493 case WTEX_THGRADIENT
:
494 subtype
= RGRD_HORIZONTAL
;
495 goto render_tgradient
;
497 case WTEX_TVGRADIENT
:
498 subtype
= RGRD_VERTICAL
;
499 goto render_tgradient
;
501 case WTEX_TDGRADIENT
:
502 subtype
= RGRD_DIAGONAL
;
507 image
= RMakeTiledImage(texture
->tgradient
.pixmap
, width
, height
);
511 grad
= RRenderGradient(width
, height
, &texture
->tgradient
.color1
,
512 &texture
->tgradient
.color2
, subtype
);
514 RDestroyImage(image
);
519 RCombineImagesWithOpaqueness(image
, grad
,
520 texture
->tgradient
.opacity
);
525 #ifdef TEXTURE_PLUGIN
528 if (texture
->function
.render
) {
529 image
= texture
->function
.render (
530 texture
->function
.argc
, texture
->function
.argv
,
531 width
, height
, relief
);
535 RErrorCode
= RERR_INTERNAL
;
538 #endif /* TEXTURE_PLUGIN */
541 puts("ERROR in wTextureRenderImage()");
549 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
551 image
= RCreateImage(width
, height
, False
);
557 RClearImage(image
, &gray
);
589 RBevelImage(image
, d
);
591 bevelImage(image
, -d
);
600 bevelImage(RImage
*image
, int relief
)
602 int width
= image
->width
;
603 int height
= image
->height
;
608 color
.red
= color
.green
= color
.blue
= 80;
611 ROperateLine(image
, RAddOperation
, 1, 0, width
-2, 0, &color
);
614 ROperateLine(image
, RAddOperation
, 0, 0, 0, height
-1, &color
);
616 color
.red
= color
.green
= color
.blue
= 40;
618 ROperateLine(image
, RSubtractOperation
, width
-1, 0, width
-1,
622 ROperateLine(image
, RSubtractOperation
, 1, height
-2, width
-2,
625 color
.red
= color
.green
= color
.blue
= 0;
627 RDrawLine(image
, 0, height
-1, width
-1, height
-1, &color
);
637 wDrawBevel(Drawable d
, unsigned width
, unsigned height
,
638 WTexSolid
*texture
, int relief
)
643 if (relief
==WREL_FLAT
) return;
645 light
= texture
->light_gc
;
646 dim
= texture
->dim_gc
;
647 dark
= texture
->dark_gc
;
655 segs
[0].x2
= width
- 2;
656 segs
[0].y2
= segs
[0].y1
= height
- 2;
657 segs
[1].x1
= width
- 2;
659 segs
[1].x2
= width
- 2;
660 segs
[1].y2
= height
- 2;
661 XDrawSegments(dpy
, d
, dim
, segs
, 2);
663 segs
[0].x2
= width
- 1;
664 segs
[0].y2
= segs
[0].y1
= height
- 1;
665 segs
[1].x1
= segs
[1].x2
= width
- 1;
667 segs
[1].y2
= height
- 1;
668 XDrawSegments(dpy
, d
, dark
, segs
, 2);
669 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 0;
670 segs
[0].x2
= width
- 2;
671 segs
[1].x1
= segs
[1].y1
= 0;
673 segs
[1].y2
= height
- 2;
674 XDrawSegments(dpy
, d
, light
, segs
, 2);
675 if (relief
==WREL_ICON
) {
676 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 1;
677 segs
[0].x2
= width
- 2;
678 segs
[1].x1
= segs
[1].y1
= 1;
680 segs
[1].y2
= height
- 2;
681 XDrawSegments(dpy
, d
, light
, segs
, 2);
687 segs
[0].x2
= width
- 1;
688 segs
[0].y2
= segs
[0].y1
= 0;
689 segs
[1].x1
= segs
[1].x2
= 0;
691 segs
[1].y2
= height
- 1;
692 XDrawSegments(dpy
, d
, dark
, segs
, 2);
695 segs
[0].y1
= segs
[0].y2
= height
- 1;
696 segs
[0].x2
= width
- 1;
697 segs
[1].x2
= segs
[1].x1
= width
- 1;
699 segs
[1].y2
= height
- 1;
700 XDrawSegments(dpy
, d
, light
, segs
, 2);