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)
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 if (CANFREE(texture
->any
.color
.pixel
))
176 colors
[count
++] = texture
->any
.color
.pixel
;
178 XErrorHandler oldhandler
;
180 /* ignore error from buggy servers that don't know how
181 * to do reference counting for colors. */
182 oldhandler
= XSetErrorHandler(dummyErrorHandler
);
183 XFreeColors(dpy
, scr
->colormap
, colors
, count
, 0);
185 XSetErrorHandler(oldhandler
);
187 XFreeGC(dpy
, texture
->any
.gc
);
195 wTextureMakeGradient(WScreen
*scr
, int style
, XColor
*from
, XColor
*to
)
197 WTexGradient
*texture
;
201 texture
= wmalloc(sizeof(WTexture
));
202 memset(texture
, 0, sizeof(WTexture
));
203 texture
->type
= style
;
204 texture
->subtype
= 0;
206 texture
->color1
= *from
;
207 texture
->color2
= *to
;
209 texture
->normal
.red
= (from
->red
+ to
->red
)/2;
210 texture
->normal
.green
= (from
->green
+ to
->green
)/2;
211 texture
->normal
.blue
= (from
->blue
+ to
->blue
)/2;
213 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
214 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
215 gcv
.graphics_exposures
= False
;
216 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
217 |GCGraphicsExposures
, &gcv
);
225 wTextureMakeMGradient(WScreen
*scr
, int style
, RColor
**colors
)
227 WTexMGradient
*texture
;
232 texture
= wmalloc(sizeof(WTexture
));
233 memset(texture
, 0, sizeof(WTexture
));
234 texture
->type
= style
;
235 texture
->subtype
= 0;
238 while (colors
[i
]!=NULL
) i
++;
240 texture
->normal
.red
= (colors
[0]->red
<<8);
241 texture
->normal
.green
= (colors
[0]->green
<<8);
242 texture
->normal
.blue
= (colors
[0]->blue
<<8);
244 texture
->colors
= colors
;
246 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
247 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
248 gcv
.graphics_exposures
= False
;
249 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
250 |GCGraphicsExposures
, &gcv
);
258 wTextureMakePixmap(WScreen
*scr
, int style
, char *pixmap_file
, XColor
*color
)
265 file
= FindImage(wPreferences
.pixmap_path
, pixmap_file
);
267 wwarning(_("image file \"%s\" used as texture could not be found."),
271 image
= RLoadImage(scr
->rcontext
, file
, 0);
273 wwarning(_("could not load texture pixmap \"%s\":%s"), file
,
274 RMessageForError(RErrorCode
));
280 texture
= wmalloc(sizeof(WTexture
));
281 memset(texture
, 0, sizeof(WTexture
));
282 texture
->type
= WTEX_PIXMAP
;
283 texture
->subtype
= style
;
285 texture
->normal
= *color
;
287 XAllocColor(dpy
, scr
->w_colormap
, &texture
->normal
);
288 gcv
.background
= gcv
.foreground
= texture
->normal
.pixel
;
289 gcv
.graphics_exposures
= False
;
290 texture
->normal_gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
|GCBackground
291 |GCGraphicsExposures
, &gcv
);
293 texture
->pixmap
= image
;
300 wTextureRenderImage(WTexture
*texture
, int width
, int height
, int relief
)
303 RColor color1
, color2
;
307 switch (texture
->any
.type
) {
309 image
= RCreateImage(width
, height
, False
);
311 color1
.red
= texture
->solid
.normal
.red
>> 8;
312 color1
.green
= texture
->solid
.normal
.green
>> 8;
313 color1
.blue
= texture
->solid
.normal
.blue
>> 8;
316 RClearImage(image
, &color1
);
320 if (texture
->pixmap
.subtype
== WTP_TILE
) {
321 image
= RMakeTiledImage(texture
->pixmap
.pixmap
, width
, height
);
322 } else if (texture
->pixmap
.subtype
== WTP_CENTER
) {
323 color1
.red
= texture
->pixmap
.normal
.red
>>8;
324 color1
.green
= texture
->pixmap
.normal
.green
>>8;
325 color1
.blue
= texture
->pixmap
.normal
.blue
>>8;
327 image
= RMakeCenteredImage(texture
->pixmap
.pixmap
, width
, height
,
330 image
= RScaleImage(texture
->pixmap
.pixmap
, width
, height
);
335 subtype
= RGRD_HORIZONTAL
;
336 goto render_gradient
;
339 subtype
= RGRD_VERTICAL
;
340 goto render_gradient
;
343 subtype
= RGRD_DIAGONAL
;
345 color1
.red
= texture
->gradient
.color1
.red
>> 8;
346 color1
.green
= texture
->gradient
.color1
.green
>> 8;
347 color1
.blue
= texture
->gradient
.color1
.blue
>> 8;
348 color2
.red
= texture
->gradient
.color2
.red
>> 8;
349 color2
.green
= texture
->gradient
.color2
.green
>> 8;
350 color2
.blue
= texture
->gradient
.color2
.blue
>> 8;
352 image
= RRenderGradient(width
, height
, &color1
, &color2
, subtype
);
355 case WTEX_MHGRADIENT
:
356 subtype
= RGRD_HORIZONTAL
;
357 goto render_mgradient
;
359 case WTEX_MVGRADIENT
:
360 subtype
= RGRD_VERTICAL
;
361 goto render_mgradient
;
363 case WTEX_MDGRADIENT
:
364 subtype
= RGRD_DIAGONAL
;
366 image
= RRenderMultiGradient(width
, height
,
367 &(texture
->mgradient
.colors
[1]),
372 puts("ERROR in wTextureRenderImage()");
377 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
410 RBevelImage(image
, d
);
412 bevelImage(image
, -d
);
419 /* used only for menu entries */
421 wTextureRender(WScreen
*scr
, WTexture
*texture
, Pixmap
*data
,
422 int width
, int height
, int relief
)
427 switch (texture->any.type) {
431 case WTEX_MHGRADIENT:
432 case WTEX_MVGRADIENT:
433 case WTEX_MDGRADIENT:
437 *data
= renderTexture(scr
, width
, height
, texture
, relief
);
446 bevelImage(RImage
*image
, int relief
)
448 int width
= image
->width
;
449 int height
= image
->height
;
454 color
.red
= color
.green
= color
.blue
= 80;
456 ROperateLine(image
, RAddOperation
, 1, 0, width
-2, 0, &color
);
458 ROperateLine(image
, RAddOperation
, 0, 0, 0, height
-1, &color
);
460 color
.red
= color
.green
= color
.blue
= 40;
462 ROperateLine(image
, RSubtractOperation
, width
-1, 0, width
-1,
465 ROperateLine(image
, RSubtractOperation
, 1, height
-2, width
-2,
468 color
.red
= color
.green
= color
.blue
= 0;
470 RDrawLine(image
, 0, height
-1, width
-1, height
-1, &color
);
479 renderTexture(WScreen
*scr
, int width
, int height
, WTexture
*texture
,
485 img
= wTextureRenderImage(texture
, width
, height
, rel
);
488 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
491 if (!RConvertImage(scr
->rcontext
, img
, &pix
)) {
492 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
500 wDrawBevel(Drawable d
, unsigned width
, unsigned height
,
501 WTexSolid
*texture
, int relief
)
506 if (relief
==WREL_FLAT
) return;
508 light
= texture
->light_gc
;
509 dim
= texture
->dim_gc
;
510 dark
= texture
->dark_gc
;
518 segs
[0].x2
= width
- 2;
519 segs
[0].y2
= segs
[0].y1
= height
- 2;
520 segs
[1].x1
= width
- 2;
522 segs
[1].x2
= width
- 2;
523 segs
[1].y2
= height
- 2;
524 XDrawSegments(dpy
, d
, dim
, segs
, 2);
526 segs
[0].x2
= width
- 1;
527 segs
[0].y2
= segs
[0].y1
= height
- 1;
528 segs
[1].x1
= segs
[1].x2
= width
- 1;
530 segs
[1].y2
= height
- 1;
531 XDrawSegments(dpy
, d
, dark
, segs
, 2);
532 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 0;
533 segs
[0].x2
= width
- 2;
534 segs
[1].x1
= segs
[1].y1
= 0;
536 segs
[1].y2
= height
- 2;
537 XDrawSegments(dpy
, d
, light
, segs
, 2);
538 if (relief
==WREL_ICON
) {
539 segs
[0].x1
= segs
[0].y1
= segs
[0].y2
= 1;
540 segs
[0].x2
= width
- 2;
541 segs
[1].x1
= segs
[1].y1
= 1;
543 segs
[1].y2
= height
- 2;
544 XDrawSegments(dpy
, d
, light
, segs
, 2);
550 segs
[0].x2
= width
- 1;
551 segs
[0].y2
= segs
[0].y1
= 0;
552 segs
[1].x1
= segs
[1].x2
= 0;
554 segs
[1].y2
= height
- 1;
555 XDrawSegments(dpy
, d
, dark
, segs
, 2);
558 segs
[0].y1
= segs
[0].y2
= height
- 1;
559 segs
[0].x2
= width
- 1;
560 segs
[1].x2
= segs
[1].x1
= width
- 1;
562 segs
[1].y2
= height
- 1;
563 XDrawSegments(dpy
, d
, light
, segs
, 2);