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 Pixmap
renderTexture(WScreen
*scr
, int width
, int height
,
48 WTexture
*texture
, int rel
);
51 static void bevelImage(RImage
*image
, int relief
);
56 wTextureMakeSolid(WScreen
*scr
, XColor
*color
)
62 texture
= wmalloc(sizeof(WTexture
));
64 texture
->type
= WTEX_SOLID
;
67 XAllocColor(dpy
, scr
->w_colormap
, color
);
68 texture
->normal
= *color
;
69 if (color
->red
==0 && color
->blue
==0 && color
->green
== 0) {
70 texture
->light
.red
= 0xb6da;
71 texture
->light
.green
= 0xb6da;
72 texture
->light
.blue
= 0xb6da;
73 texture
->dim
.red
= 0x6185;
74 texture
->dim
.green
= 0x6185;
75 texture
->dim
.blue
= 0x6185;
81 rgb
.red
= color
->red
>> 8;
82 rgb
.green
= color
->green
>> 8;
83 rgb
.blue
= color
->blue
>> 8;
84 RRGBtoHSV(&rgb
, &hsv
);
85 RHSVtoRGB(&hsv
, &rgb
);
89 hsv
.value
= (v
> 255 ? 255 : v
);
90 RHSVtoRGB(&hsv
, &rgb
);
91 texture
->light
.red
= rgb
.red
<< 8;
92 texture
->light
.green
= rgb
.green
<< 8;
93 texture
->light
.blue
= rgb
.blue
<< 8;
95 hsv2
.value
= hsv2
.value
/2;
96 RHSVtoRGB(&hsv2
, &rgb
);
97 texture
->dim
.red
= rgb
.red
<< 8;
98 texture
->dim
.green
= rgb
.green
<< 8;
99 texture
->dim
.blue
= rgb
.blue
<< 8;
101 texture
->dark
.red
= 0;
102 texture
->dark
.green
= 0;
103 texture
->dark
.blue
= 0;
104 XAllocColor(dpy
, scr
->w_colormap
, &texture
->light
);
105 XAllocColor(dpy
, scr
->w_colormap
, &texture
->dim
);
106 XAllocColor(dpy
, scr
->w_colormap
, &texture
->dark
);
108 gcm
= GCForeground
|GCBackground
|GCGraphicsExposures
;
109 gcv
.graphics_exposures
= False
;
111 gcv
.background
= gcv
.foreground
= texture
->light
.pixel
;
112 texture
->light_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
114 gcv
.background
= gcv
.foreground
= texture
->dim
.pixel
;
115 texture
->dim_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
117 gcv
.background
= gcv
.foreground
= texture
->dark
.pixel
;
118 texture
->dark_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
120 gcv
.background
= gcv
.foreground
= color
->pixel
;
121 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
128 dummyErrorHandler(Display
*foo
, XErrorEvent
*bar
)
131 wwarning("your server is buggy. Tell the author if some error related to color occurs");
138 wTextureDestroy(WScreen
*scr
, WTexture
*texture
)
142 unsigned long colors
[8];
146 printf("BUG: trying to free NULL texture\n");
152 * some stupid servers don't like white or black being freed...
154 #define CANFREE(c) (c!=scr->black_pixel && c!=scr->white_pixel && c!=0)
155 switch (texture
->any
.type
) {
157 XFreeGC(dpy
, texture
->solid
.light_gc
);
158 XFreeGC(dpy
, texture
->solid
.dark_gc
);
159 XFreeGC(dpy
, texture
->solid
.dim_gc
);
160 if (CANFREE(texture
->solid
.light
.pixel
))
161 colors
[count
++] = texture
->solid
.light
.pixel
;
162 if (CANFREE(texture
->solid
.dim
.pixel
))
163 colors
[count
++] = texture
->solid
.dim
.pixel
;
164 if (CANFREE(texture
->solid
.dark
.pixel
))
165 colors
[count
++] = texture
->solid
.dark
.pixel
;
169 RDestroyImage(texture
->pixmap
.pixmap
);
172 case WTEX_MHGRADIENT
:
173 case WTEX_MVGRADIENT
:
174 case WTEX_MDGRADIENT
:
175 for (i
=0; texture
->mgradient
.colors
[i
]!=NULL
; i
++) {
176 free(texture
->mgradient
.colors
[i
]);
178 free(texture
->mgradient
.colors
);
181 case WTEX_THGRADIENT
:
182 case WTEX_TVGRADIENT
:
183 case WTEX_TDGRADIENT
:
184 RDestroyImage(texture
->tgradient
.pixmap
);
187 #ifdef TEXTURE_PLUGIN
190 if (texture
->function
.handle
) {
191 dlclose(texture
->function
.handle
);
194 for (i
= 0; i
< texture
->function
.argc
; i
++) {
195 free(texture
->function
.argv
[i
]);
197 free(texture
->function
.argv
);
199 #endif /* TEXTURE_PLUGIN */
201 if (CANFREE(texture
->any
.color
.pixel
))
202 colors
[count
++] = texture
->any
.color
.pixel
;
204 XErrorHandler oldhandler
;
206 /* ignore error from buggy servers that don't know how
207 * to do reference counting for colors. */
209 oldhandler
= XSetErrorHandler(dummyErrorHandler
);
210 XFreeColors(dpy
, scr
->w_colormap
, colors
, count
, 0);
212 XSetErrorHandler(oldhandler
);
214 XFreeGC(dpy
, texture
->any
.gc
);
222 wTextureMakeGradient(WScreen
*scr
, int style
, RColor
*from
, RColor
*to
)
224 WTexGradient
*texture
;
228 texture
= wmalloc(sizeof(WTexture
));
229 memset(texture
, 0, sizeof(WTexture
));
230 texture
->type
= style
;
231 texture
->subtype
= 0;
233 texture
->color1
= *from
;
234 texture
->color2
= *to
;
236 texture
->normal
.red
= (from
->red
+ to
->red
)<<7;
237 texture
->normal
.green
= (from
->green
+ to
->green
)<<7;
238 texture
->normal
.blue
= (from
->blue
+ to
->blue
)<<7;
240 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
241 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
242 gcv
.graphics_exposures
= False
;
243 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
244 |GCGraphicsExposures
, &gcv
);
252 wTextureMakeMGradient(WScreen
*scr
, int style
, RColor
**colors
)
254 WTexMGradient
*texture
;
259 texture
= wmalloc(sizeof(WTexture
));
260 memset(texture
, 0, sizeof(WTexture
));
261 texture
->type
= style
;
262 texture
->subtype
= 0;
265 while (colors
[i
]!=NULL
) i
++;
267 texture
->normal
.red
= (colors
[0]->red
<<8);
268 texture
->normal
.green
= (colors
[0]->green
<<8);
269 texture
->normal
.blue
= (colors
[0]->blue
<<8);
271 texture
->colors
= colors
;
273 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
274 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
275 gcv
.graphics_exposures
= False
;
276 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
277 |GCGraphicsExposures
, &gcv
);
285 wTextureMakePixmap(WScreen
*scr
, int style
, char *pixmap_file
, XColor
*color
)
292 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
294 wwarning(_("image file \"%s\" used as texture could not be found."),
298 image
= RLoadImage(scr
->rcontext
, file
, 0);
300 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
301 RMessageForError(RErrorCode
));
307 texture
= wmalloc(sizeof(WTexture
));
308 memset(texture
, 0, sizeof(WTexture
));
309 texture
->type
= WTEX_PIXMAP
;
310 texture
->subtype
= style
;
312 texture
->normal
= *color
;
314 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
315 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
316 gcv
.graphics_exposures
= False
;
317 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
318 |GCGraphicsExposures
, &gcv
);
320 texture
->pixmap
= image
;
328 wTextureMakeTGradient(WScreen
*scr
, int style
, RColor
*from
, RColor
*to
,
329 char *pixmap_file
, int opacity
)
331 WTexTGradient
*texture
;
336 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
338 wwarning(_("image file \"%s\" used as texture could not be found."),
342 image
= RLoadImage(scr
->rcontext
, file
, 0);
344 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
345 RMessageForError(RErrorCode
));
351 texture
= wmalloc(sizeof(WTexture
));
352 memset(texture
, 0, sizeof(WTexture
));
353 texture
->type
= style
;
355 texture
->opacity
= opacity
;
357 texture
->color1
= *from
;
358 texture
->color2
= *to
;
360 texture
->normal
.red
= (from
->red
+ to
->red
)<<7;
361 texture
->normal
.green
= (from
->green
+ to
->green
)<<7;
362 texture
->normal
.blue
= (from
->blue
+ to
->blue
)<<7;
364 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
365 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
366 gcv
.graphics_exposures
= False
;
367 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
368 |GCGraphicsExposures
, &gcv
);
370 texture
->pixmap
= image
;
376 #ifdef TEXTURE_PLUGIN
378 wTextureMakeFunction(WScreen
*scr
, char *lib
, char *func
, int argc
, char **argv
)
380 XColor fallbackColor
;
382 WTexFunction
*texture
;
384 texture
= wmalloc(sizeof(WTexture
));
385 texture
->type
= WTEX_FUNCTION
;
386 texture
->handle
= NULL
;
388 texture
->argc
= argc
;
389 texture
->argv
= argv
;
391 fallbackColor
.red
= 0x8000;
392 fallbackColor
.green
= 0x8000;
393 fallbackColor
.blue
= 0x8000;
395 gcv
.background
= gcv
.foreground
= fallbackColor
.pixel
;
396 gcv
.graphics_exposures
= False
;
397 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
398 |GCGraphicsExposures
, &gcv
);
401 /* open the library */
402 texture
->handle
= dlopen(lib
, RTLD_LAZY
);
403 if (!texture
->handle
) {
404 wwarning(_("library \"%s\" cound not be opened."), lib
);
410 /* find the function */
411 texture
->render
= dlsym(texture
->handle
, func
);
412 if (!texture
->render
) {
413 wwarning(_("function \"%s\" not found in library \"%s\""), func
, lib
);
415 dlclose(texture
->handle
);
420 wwarning(_("function textures not supported on this system, sorry."));
426 #endif /* TEXTURE_PLUGIN */
430 wTextureRenderImage(WTexture
*texture
, int width
, int height
,
438 switch (texture
->any
.type
) {
440 image
= RCreateImage(width
, height
, False
);
442 color1
.red
= texture
->solid
.normal
.red
>> 8;
443 color1
.green
= texture
->solid
.normal
.green
>> 8;
444 color1
.blue
= texture
->solid
.normal
.blue
>> 8;
447 RClearImage(image
, &color1
);
451 if (texture
->pixmap
.subtype
== WTP_TILE
) {
452 image
= RMakeTiledImage(texture
->pixmap
.pixmap
, width
, height
);
453 } else if (texture
->pixmap
.subtype
== WTP_CENTER
) {
454 color1
.red
= texture
->pixmap
.normal
.red
>>8;
455 color1
.green
= texture
->pixmap
.normal
.green
>>8;
456 color1
.blue
= texture
->pixmap
.normal
.blue
>>8;
458 image
= RMakeCenteredImage(texture
->pixmap
.pixmap
, width
, height
,
461 image
= RScaleImage(texture
->pixmap
.pixmap
, width
, height
);
466 subtype
= RGRD_HORIZONTAL
;
467 goto render_gradient
;
470 subtype
= RGRD_VERTICAL
;
471 goto render_gradient
;
474 subtype
= RGRD_DIAGONAL
;
477 image
= RRenderGradient(width
, height
, &texture
->gradient
.color1
,
478 &texture
->gradient
.color2
, subtype
);
481 case WTEX_MHGRADIENT
:
482 subtype
= RGRD_HORIZONTAL
;
483 goto render_mgradient
;
485 case WTEX_MVGRADIENT
:
486 subtype
= RGRD_VERTICAL
;
487 goto render_mgradient
;
489 case WTEX_MDGRADIENT
:
490 subtype
= RGRD_DIAGONAL
;
492 image
= RRenderMultiGradient(width
, height
,
493 &(texture
->mgradient
.colors
[1]),
497 case WTEX_THGRADIENT
:
498 subtype
= RGRD_HORIZONTAL
;
499 goto render_tgradient
;
501 case WTEX_TVGRADIENT
:
502 subtype
= RGRD_VERTICAL
;
503 goto render_tgradient
;
505 case WTEX_TDGRADIENT
:
506 subtype
= RGRD_DIAGONAL
;
511 image
= RMakeTiledImage(texture
->tgradient
.pixmap
, width
, height
);
515 grad
= RRenderGradient(width
, height
, &texture
->tgradient
.color1
,
516 &texture
->tgradient
.color2
, subtype
);
518 RDestroyImage(image
);
523 RCombineImagesWithOpaqueness(image
, grad
,
524 texture
->tgradient
.opacity
);
529 #ifdef TEXTURE_PLUGIN
532 if (texture
->function
.render
) {
533 image
= texture
->function
.render (
534 texture
->function
.argc
, texture
->function
.argv
,
535 width
, height
, relief
);
539 RErrorCode
= RERR_INTERNAL
;
542 #endif /* TEXTURE_PLUGIN */
545 puts("ERROR in wTextureRenderImage()");
553 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
555 image
= RCreateImage(width
, height
, False
);
561 RClearImage(image
, &gray
);
593 RBevelImage(image
, d
);
595 bevelImage(image
, -d
);
604 bevelImage(RImage
*image
, int relief
)
606 int width
= image
->width
;
607 int height
= image
->height
;
612 color
.red
= color
.green
= color
.blue
= 80;
615 ROperateLine(image
, RAddOperation
, 1, 0, width
-2, 0, &color
);
618 ROperateLine(image
, RAddOperation
, 0, 0, 0, height
-1, &color
);
620 color
.red
= color
.green
= color
.blue
= 40;
622 ROperateLine(image
, RSubtractOperation
, width
-1, 0, width
-1,
626 ROperateLine(image
, RSubtractOperation
, 1, height
-2, width
-2,
629 color
.red
= color
.green
= color
.blue
= 0;
631 RDrawLine(image
, 0, height
-1, width
-1, height
-1, &color
);
641 wDrawBevel(Drawable d
, unsigned width
, unsigned height
,
642 WTexSolid
*texture
, int relief
)
647 if (relief
==WREL_FLAT
) return;
649 light
= texture
->light_gc
;
650 dim
= texture
->dim_gc
;
651 dark
= texture
->dark_gc
;
659 segs
[0].x2
= width
- 2;
660 segs
[0].y2
= segs
[0].y1
= height
- 2;
661 segs
[1].x1
= width
- 2;
663 segs
[1].x2
= width
- 2;
664 segs
[1].y2
= height
- 2;
665 XDrawSegments(dpy
, d
, dim
, segs
, 2);
667 segs
[0].x2
= width
- 1;
668 segs
[0].y2
= segs
[0].y1
= height
- 1;
669 segs
[1].x1
= segs
[1].x2
= width
- 1;
671 segs
[1].y2
= height
- 1;
672 XDrawSegments(dpy
, d
, dark
, segs
, 2);
673 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 0;
674 segs
[0].x2
= width
- 2;
675 segs
[1].x1
= segs
[1].y1
= 0;
677 segs
[1].y2
= height
- 2;
678 XDrawSegments(dpy
, d
, light
, segs
, 2);
679 if (relief
==WREL_ICON
) {
680 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 1;
681 segs
[0].x2
= width
- 2;
682 segs
[1].x1
= segs
[1].y1
= 1;
684 segs
[1].y2
= height
- 2;
685 XDrawSegments(dpy
, d
, light
, segs
, 2);
691 segs
[0].x2
= width
- 1;
692 segs
[0].y2
= segs
[0].y1
= 0;
693 segs
[1].x1
= segs
[1].x2
= 0;
695 segs
[1].y2
= height
- 1;
696 XDrawSegments(dpy
, d
, dark
, segs
, 2);
699 segs
[0].y1
= segs
[0].y2
= height
- 1;
700 segs
[0].x2
= width
- 1;
701 segs
[1].x2
= segs
[1].x1
= width
- 1;
703 segs
[1].y2
= height
- 1;
704 XDrawSegments(dpy
, d
, light
, segs
, 2);