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>
33 #include "WindowMaker.h"
38 extern WPreferences wPreferences
;
41 static Pixmap
renderTexture(WScreen
*scr
, int width
, int height
,
42 WTexture
*texture
, int rel
);
45 static void bevelImage(RImage
*image
, int relief
);
50 wTextureMakeSolid(WScreen
*scr
, XColor
*color
)
56 texture
= wmalloc(sizeof(WTexture
));
58 texture
->type
= WTEX_SOLID
;
61 XAllocColor(dpy
, scr
->w_colormap
, color
);
62 texture
->normal
= *color
;
63 if (color
->red
==0 && color
->blue
==0 && color
->green
== 0) {
64 texture
->light
.red
= 0xb6da;
65 texture
->light
.green
= 0xb6da;
66 texture
->light
.blue
= 0xb6da;
67 texture
->dim
.red
= 0x6185;
68 texture
->dim
.green
= 0x6185;
69 texture
->dim
.blue
= 0x6185;
75 rgb
.red
= color
->red
>> 8;
76 rgb
.green
= color
->green
>> 8;
77 rgb
.blue
= color
->blue
>> 8;
78 RRGBtoHSV(&rgb
, &hsv
);
79 RHSVtoRGB(&hsv
, &rgb
);
83 hsv
.value
= (v
> 255 ? 255 : v
);
84 RHSVtoRGB(&hsv
, &rgb
);
85 texture
->light
.red
= rgb
.red
<< 8;
86 texture
->light
.green
= rgb
.green
<< 8;
87 texture
->light
.blue
= rgb
.blue
<< 8;
89 hsv2
.value
= hsv2
.value
/2;
90 RHSVtoRGB(&hsv2
, &rgb
);
91 texture
->dim
.red
= rgb
.red
<< 8;
92 texture
->dim
.green
= rgb
.green
<< 8;
93 texture
->dim
.blue
= rgb
.blue
<< 8;
95 texture
->dark
.red
= 0;
96 texture
->dark
.green
= 0;
97 texture
->dark
.blue
= 0;
98 XAllocColor(dpy
, scr
->w_colormap
, &texture
->light
);
99 XAllocColor(dpy
, scr
->w_colormap
, &texture
->dim
);
100 XAllocColor(dpy
, scr
->w_colormap
, &texture
->dark
);
102 gcm
= GCForeground
|GCBackground
|GCGraphicsExposures
;
103 gcv
.graphics_exposures
= False
;
105 gcv
.background
= gcv
.foreground
= texture
->light
.pixel
;
106 texture
->light_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
108 gcv
.background
= gcv
.foreground
= texture
->dim
.pixel
;
109 texture
->dim_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
111 gcv
.background
= gcv
.foreground
= texture
->dark
.pixel
;
112 texture
->dark_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
114 gcv
.background
= gcv
.foreground
= color
->pixel
;
115 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, gcm
, &gcv
);
122 dummyErrorHandler(Display
*foo
, XErrorEvent
*bar
)
125 wwarning("your server is buggy. Tell the author if some error related to color occurs");
132 wTextureDestroy(WScreen
*scr
, WTexture
*texture
)
136 unsigned long colors
[8];
140 printf("BUG: trying to free NULL texture\n");
146 * some stupid servers don't like white or black being freed...
148 #define CANFREE(c) (c!=scr->black_pixel && c!=scr->white_pixel && c!=0)
149 switch (texture
->any
.type
) {
151 XFreeGC(dpy
, texture
->solid
.light_gc
);
152 XFreeGC(dpy
, texture
->solid
.dark_gc
);
153 XFreeGC(dpy
, texture
->solid
.dim_gc
);
154 if (CANFREE(texture
->solid
.light
.pixel
))
155 colors
[count
++] = texture
->solid
.light
.pixel
;
156 if (CANFREE(texture
->solid
.dim
.pixel
))
157 colors
[count
++] = texture
->solid
.dim
.pixel
;
158 if (CANFREE(texture
->solid
.dark
.pixel
))
159 colors
[count
++] = texture
->solid
.dark
.pixel
;
163 RDestroyImage(texture
->pixmap
.pixmap
);
166 case WTEX_MHGRADIENT
:
167 case WTEX_MVGRADIENT
:
168 case WTEX_MDGRADIENT
:
169 for (i
=0; texture
->mgradient
.colors
[i
]!=NULL
; i
++) {
170 free(texture
->mgradient
.colors
[i
]);
172 free(texture
->mgradient
.colors
);
175 case WTEX_THGRADIENT
:
176 case WTEX_TVGRADIENT
:
177 case WTEX_TDGRADIENT
:
178 RDestroyImage(texture
->tgradient
.pixmap
);
181 if (CANFREE(texture
->any
.color
.pixel
))
182 colors
[count
++] = texture
->any
.color
.pixel
;
184 XErrorHandler oldhandler
;
186 /* ignore error from buggy servers that don't know how
187 * to do reference counting for colors. */
189 oldhandler
= XSetErrorHandler(dummyErrorHandler
);
190 XFreeColors(dpy
, scr
->colormap
, colors
, count
, 0);
192 XSetErrorHandler(oldhandler
);
194 XFreeGC(dpy
, texture
->any
.gc
);
202 wTextureMakeGradient(WScreen
*scr
, int style
, RColor
*from
, RColor
*to
)
204 WTexGradient
*texture
;
208 texture
= wmalloc(sizeof(WTexture
));
209 memset(texture
, 0, sizeof(WTexture
));
210 texture
->type
= style
;
211 texture
->subtype
= 0;
213 texture
->color1
= *from
;
214 texture
->color2
= *to
;
216 texture
->normal
.red
= (from
->red
+ to
->red
)<<7;
217 texture
->normal
.green
= (from
->green
+ to
->green
)<<7;
218 texture
->normal
.blue
= (from
->blue
+ to
->blue
)<<7;
220 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
221 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
222 gcv
.graphics_exposures
= False
;
223 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
224 |GCGraphicsExposures
, &gcv
);
232 wTextureMakeMGradient(WScreen
*scr
, int style
, RColor
**colors
)
234 WTexMGradient
*texture
;
239 texture
= wmalloc(sizeof(WTexture
));
240 memset(texture
, 0, sizeof(WTexture
));
241 texture
->type
= style
;
242 texture
->subtype
= 0;
245 while (colors
[i
]!=NULL
) i
++;
247 texture
->normal
.red
= (colors
[0]->red
<<8);
248 texture
->normal
.green
= (colors
[0]->green
<<8);
249 texture
->normal
.blue
= (colors
[0]->blue
<<8);
251 texture
->colors
= colors
;
253 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
254 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
255 gcv
.graphics_exposures
= False
;
256 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
257 |GCGraphicsExposures
, &gcv
);
265 wTextureMakePixmap(WScreen
*scr
, int style
, char *pixmap_file
, XColor
*color
)
272 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
274 wwarning(_("image file \"%s\" used as texture could not be found."),
278 image
= RLoadImage(scr
->rcontext
, file
, 0);
280 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
281 RMessageForError(RErrorCode
));
287 texture
= wmalloc(sizeof(WTexture
));
288 memset(texture
, 0, sizeof(WTexture
));
289 texture
->type
= WTEX_PIXMAP
;
290 texture
->subtype
= style
;
292 texture
->normal
= *color
;
294 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
295 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
296 gcv
.graphics_exposures
= False
;
297 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
298 |GCGraphicsExposures
, &gcv
);
300 texture
->pixmap
= image
;
308 wTextureMakeTGradient(WScreen
*scr
, int style
, RColor
*from
, RColor
*to
,
309 char *pixmap_file
, int opacity
)
311 WTexTGradient
*texture
;
316 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
318 wwarning(_("image file \"%s\" used as texture could not be found."),
322 image
= RLoadImage(scr
->rcontext
, file
, 0);
324 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
325 RMessageForError(RErrorCode
));
331 texture
= wmalloc(sizeof(WTexture
));
332 memset(texture
, 0, sizeof(WTexture
));
333 texture
->type
= style
;
335 texture
->opacity
= opacity
;
337 texture
->color1
= *from
;
338 texture
->color2
= *to
;
340 texture
->normal
.red
= (from
->red
+ to
->red
)<<7;
341 texture
->normal
.green
= (from
->green
+ to
->green
)<<7;
342 texture
->normal
.blue
= (from
->blue
+ to
->blue
)<<7;
344 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
345 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
346 gcv
.graphics_exposures
= False
;
347 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
348 |GCGraphicsExposures
, &gcv
);
350 texture
->pixmap
= image
;
358 wTextureRenderImage(WTexture
*texture
, int width
, int height
, int relief
)
365 switch (texture
->any
.type
) {
367 image
= RCreateImage(width
, height
, False
);
369 color1
.red
= texture
->solid
.normal
.red
>> 8;
370 color1
.green
= texture
->solid
.normal
.green
>> 8;
371 color1
.blue
= texture
->solid
.normal
.blue
>> 8;
374 RClearImage(image
, &color1
);
378 if (texture
->pixmap
.subtype
== WTP_TILE
) {
379 image
= RMakeTiledImage(texture
->pixmap
.pixmap
, width
, height
);
380 } else if (texture
->pixmap
.subtype
== WTP_CENTER
) {
381 color1
.red
= texture
->pixmap
.normal
.red
>>8;
382 color1
.green
= texture
->pixmap
.normal
.green
>>8;
383 color1
.blue
= texture
->pixmap
.normal
.blue
>>8;
385 image
= RMakeCenteredImage(texture
->pixmap
.pixmap
, width
, height
,
388 image
= RScaleImage(texture
->pixmap
.pixmap
, width
, height
);
393 subtype
= RGRD_HORIZONTAL
;
394 goto render_gradient
;
397 subtype
= RGRD_VERTICAL
;
398 goto render_gradient
;
401 subtype
= RGRD_DIAGONAL
;
404 image
= RRenderGradient(width
, height
, &texture
->gradient
.color1
,
405 &texture
->gradient
.color2
, subtype
);
408 case WTEX_MHGRADIENT
:
409 subtype
= RGRD_HORIZONTAL
;
410 goto render_mgradient
;
412 case WTEX_MVGRADIENT
:
413 subtype
= RGRD_VERTICAL
;
414 goto render_mgradient
;
416 case WTEX_MDGRADIENT
:
417 subtype
= RGRD_DIAGONAL
;
419 image
= RRenderMultiGradient(width
, height
,
420 &(texture
->mgradient
.colors
[1]),
424 case WTEX_THGRADIENT
:
425 subtype
= RGRD_HORIZONTAL
;
426 goto render_tgradient
;
428 case WTEX_TVGRADIENT
:
429 subtype
= RGRD_VERTICAL
;
430 goto render_tgradient
;
432 case WTEX_TDGRADIENT
:
433 subtype
= RGRD_DIAGONAL
;
438 image
= RMakeTiledImage(texture
->tgradient
.pixmap
, width
, height
);
442 grad
= RRenderGradient(width
, height
, &texture
->tgradient
.color1
,
443 &texture
->tgradient
.color2
, subtype
);
445 RDestroyImage(image
);
450 RCombineImagesWithOpaqueness(image
, grad
,
451 texture
->tgradient
.opacity
);
457 puts("ERROR in wTextureRenderImage()");
463 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
496 RBevelImage(image
, d
);
498 bevelImage(image
, -d
);
505 /* used only for menu entries */
507 wTextureRender(WScreen
*scr
, WTexture
*texture
, Pixmap
*data
,
508 int width
, int height
, int relief
)
513 switch (texture->any.type) {
517 case WTEX_MHGRADIENT:
518 case WTEX_MVGRADIENT:
519 case WTEX_MDGRADIENT:
523 *data
= renderTexture(scr
, width
, height
, texture
, relief
);
532 bevelImage(RImage
*image
, int relief
)
534 int width
= image
->width
;
535 int height
= image
->height
;
540 color
.red
= color
.green
= color
.blue
= 80;
542 ROperateLine(image
, RAddOperation
, 1, 0, width
-2, 0, &color
);
544 ROperateLine(image
, RAddOperation
, 0, 0, 0, height
-1, &color
);
546 color
.red
= color
.green
= color
.blue
= 40;
548 ROperateLine(image
, RSubtractOperation
, width
-1, 0, width
-1,
551 ROperateLine(image
, RSubtractOperation
, 1, height
-2, width
-2,
554 color
.red
= color
.green
= color
.blue
= 0;
556 RDrawLine(image
, 0, height
-1, width
-1, height
-1, &color
);
565 renderTexture(WScreen
*scr
, int width
, int height
, WTexture
*texture
,
571 img
= wTextureRenderImage(texture
, width
, height
, rel
);
574 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
577 if (!RConvertImage(scr
->rcontext
, img
, &pix
)) {
578 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
586 wDrawBevel(Drawable d
, unsigned width
, unsigned height
,
587 WTexSolid
*texture
, int relief
)
592 if (relief
==WREL_FLAT
) return;
594 light
= texture
->light_gc
;
595 dim
= texture
->dim_gc
;
596 dark
= texture
->dark_gc
;
604 segs
[0].x2
= width
- 2;
605 segs
[0].y2
= segs
[0].y1
= height
- 2;
606 segs
[1].x1
= width
- 2;
608 segs
[1].x2
= width
- 2;
609 segs
[1].y2
= height
- 2;
610 XDrawSegments(dpy
, d
, dim
, segs
, 2);
612 segs
[0].x2
= width
- 1;
613 segs
[0].y2
= segs
[0].y1
= height
- 1;
614 segs
[1].x1
= segs
[1].x2
= width
- 1;
616 segs
[1].y2
= height
- 1;
617 XDrawSegments(dpy
, d
, dark
, segs
, 2);
618 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 0;
619 segs
[0].x2
= width
- 2;
620 segs
[1].x1
= segs
[1].y1
= 0;
622 segs
[1].y2
= height
- 2;
623 XDrawSegments(dpy
, d
, light
, segs
, 2);
624 if (relief
==WREL_ICON
) {
625 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 1;
626 segs
[0].x2
= width
- 2;
627 segs
[1].x1
= segs
[1].y1
= 1;
629 segs
[1].y2
= height
- 2;
630 XDrawSegments(dpy
, d
, light
, segs
, 2);
636 segs
[0].x2
= width
- 1;
637 segs
[0].y2
= segs
[0].y1
= 0;
638 segs
[1].x1
= segs
[1].x2
= 0;
640 segs
[1].y2
= height
- 1;
641 XDrawSegments(dpy
, d
, dark
, segs
, 2);
644 segs
[0].y1
= segs
[0].y2
= height
- 1;
645 segs
[0].x2
= width
- 1;
646 segs
[1].x2
= segs
[1].x1
= width
- 1;
648 segs
[1].y2
= height
- 1;
649 XDrawSegments(dpy
, d
, light
, segs
, 2);