mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-31 02:52:30 +01:00
---------------
- Added retain/release mechanism to RImage by adding RRetainImage() and
RReleaseImage(). RDestroyImage() is an alias to RReleaseImage() now, but
will be removed in a future release because it no longer fits with the
semantics. Will be kept for a while to allow a smoother transition.
More about in wrlib/NEWS
For WINGs:
----------
- Small API change:
1. Renamed WMSetApplicationIconImage(), WMGetApplicationIconImage() and
WMSetWindowMiniwindowImage() to respectively WMSetApplicationIconPixmap(),
WMGetApplicationIconPixmap() and WMSetWindowMiniwindowPixmap()
They operate on a WMPixmap which is practically an X Pixmap with no alpha
channel information and the new name is more suggestive and also leaves
room for the new functions added for operating on images with alpha info.
2. Added WMSetApplicationIconImage() and WMGetApplicationIconImage() which
operate on an RImage and store alpha information too.
3. Added WMGetApplicationIconBlendedPixmap() which will take the image with
alpha set by WMSetApplicationIconImage() and will blend it with a color.
If color is NULL it will blend using the default panel color (#aeaaae)
All these changes will allow WINGs to handle images with alpha blending
correctly in panels and wherever else needed. More about in WINGs/NEWS.
- updated panels to use the newly available RImages if present and fallback
to old WMPixmaps if not, to properly show alpha blended images.
- replaced some still left malloc's with wmalloc's.
For Window Maker:
-----------------
- Fixed wrong mapping position of the "Docked Applications Panel" for some
icons.
- Smoother animation for the smiley =)
- Made images with alpha blending be shown correctly in the panels and the
icon chooser.
- The icon image set to be shown in panels ("Logo.WMPanel") will be
automatically updated if its entry in WMWindowAttributes changes (without
a need to restart as until now).
*** Note!!! ***
If you are developing applications with one of libwraster or libWINGs
then you should look to wrlib/NEWS and WINGs/NEWS to see what changed
and how should you update your code.
755 lines
18 KiB
C
755 lines
18 KiB
C
/*
|
|
* Window Maker window manager
|
|
*
|
|
* Copyright (c) 1997, 1998 Alfredo K. Kojima
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
* USA.
|
|
*/
|
|
|
|
#include "wconfig.h"
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
|
|
#ifdef TEXTURE_PLUGIN
|
|
# ifdef HAVE_DLFCN_H
|
|
# include <dlfcn.h>
|
|
# endif
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <wraster.h>
|
|
|
|
#include "WindowMaker.h"
|
|
#include "wcore.h"
|
|
#include "texture.h"
|
|
#include "funcs.h"
|
|
|
|
extern WPreferences wPreferences;
|
|
|
|
|
|
static void bevelImage(RImage *image, int relief);
|
|
|
|
|
|
|
|
WTexSolid*
|
|
wTextureMakeSolid(WScreen *scr, XColor *color)
|
|
{
|
|
WTexSolid *texture;
|
|
int gcm;
|
|
XGCValues gcv;
|
|
|
|
texture = wmalloc(sizeof(WTexture));
|
|
|
|
texture->type = WTEX_SOLID;
|
|
texture->subtype = 0;
|
|
|
|
XAllocColor(dpy, scr->w_colormap, color);
|
|
texture->normal = *color;
|
|
if (color->red==0 && color->blue==0 && color->green == 0) {
|
|
texture->light.red = 0xb6da;
|
|
texture->light.green = 0xb6da;
|
|
texture->light.blue = 0xb6da;
|
|
texture->dim.red = 0x6185;
|
|
texture->dim.green = 0x6185;
|
|
texture->dim.blue = 0x6185;
|
|
} else {
|
|
RColor rgb;
|
|
RHSVColor hsv, hsv2;
|
|
int v;
|
|
|
|
rgb.red = color->red >> 8;
|
|
rgb.green = color->green >> 8;
|
|
rgb.blue = color->blue >> 8;
|
|
RRGBtoHSV(&rgb, &hsv);
|
|
RHSVtoRGB(&hsv, &rgb);
|
|
hsv2 = hsv;
|
|
|
|
v = hsv.value*16/10;
|
|
hsv.value = (v > 255 ? 255 : v);
|
|
RHSVtoRGB(&hsv, &rgb);
|
|
texture->light.red = rgb.red << 8;
|
|
texture->light.green = rgb.green << 8;
|
|
texture->light.blue = rgb.blue << 8;
|
|
|
|
hsv2.value = hsv2.value/2;
|
|
RHSVtoRGB(&hsv2, &rgb);
|
|
texture->dim.red = rgb.red << 8;
|
|
texture->dim.green = rgb.green << 8;
|
|
texture->dim.blue = rgb.blue << 8;
|
|
}
|
|
texture->dark.red = 0;
|
|
texture->dark.green = 0;
|
|
texture->dark.blue = 0;
|
|
XAllocColor(dpy, scr->w_colormap, &texture->light);
|
|
XAllocColor(dpy, scr->w_colormap, &texture->dim);
|
|
XAllocColor(dpy, scr->w_colormap, &texture->dark);
|
|
|
|
gcm = GCForeground|GCBackground|GCGraphicsExposures;
|
|
gcv.graphics_exposures = False;
|
|
|
|
gcv.background = gcv.foreground = texture->light.pixel;
|
|
texture->light_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
|
|
|
|
gcv.background = gcv.foreground = texture->dim.pixel;
|
|
texture->dim_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
|
|
|
|
gcv.background = gcv.foreground = texture->dark.pixel;
|
|
texture->dark_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
|
|
|
|
gcv.background = gcv.foreground = color->pixel;
|
|
texture->normal_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
|
|
|
|
return texture;
|
|
}
|
|
|
|
|
|
static int
|
|
dummyErrorHandler(Display *foo, XErrorEvent *bar)
|
|
{
|
|
#ifdef DEBUG
|
|
wwarning("your server is buggy. Tell the author if some error related to color occurs");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
void
|
|
wTextureDestroy(WScreen *scr, WTexture *texture)
|
|
{
|
|
int i;
|
|
int count=0;
|
|
unsigned long colors[8];
|
|
|
|
#ifdef DEBUG
|
|
if (texture==NULL) {
|
|
printf("BUG: trying to free NULL texture\n");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* some stupid servers don't like white or black being freed...
|
|
*/
|
|
#define CANFREE(c) (c!=scr->black_pixel && c!=scr->white_pixel && c!=0)
|
|
switch (texture->any.type) {
|
|
case WTEX_SOLID:
|
|
XFreeGC(dpy, texture->solid.light_gc);
|
|
XFreeGC(dpy, texture->solid.dark_gc);
|
|
XFreeGC(dpy, texture->solid.dim_gc);
|
|
if (CANFREE(texture->solid.light.pixel))
|
|
colors[count++] = texture->solid.light.pixel;
|
|
if (CANFREE(texture->solid.dim.pixel))
|
|
colors[count++] = texture->solid.dim.pixel;
|
|
if (CANFREE(texture->solid.dark.pixel))
|
|
colors[count++] = texture->solid.dark.pixel;
|
|
break;
|
|
|
|
case WTEX_PIXMAP:
|
|
RReleaseImage(texture->pixmap.pixmap);
|
|
break;
|
|
|
|
case WTEX_MHGRADIENT:
|
|
case WTEX_MVGRADIENT:
|
|
case WTEX_MDGRADIENT:
|
|
for (i=0; texture->mgradient.colors[i]!=NULL; i++) {
|
|
wfree(texture->mgradient.colors[i]);
|
|
}
|
|
wfree(texture->mgradient.colors);
|
|
break;
|
|
|
|
case WTEX_THGRADIENT:
|
|
case WTEX_TVGRADIENT:
|
|
case WTEX_TDGRADIENT:
|
|
RReleaseImage(texture->tgradient.pixmap);
|
|
break;
|
|
|
|
#ifdef TEXTURE_PLUGIN
|
|
case WTEX_FUNCTION:
|
|
#ifdef HAVE_DLFCN_H
|
|
if (texture->function.handle) {
|
|
dlclose(texture->function.handle);
|
|
}
|
|
#endif
|
|
for (i = 0; i < texture->function.argc; i++) {
|
|
wfree(texture->function.argv[i]);
|
|
}
|
|
wfree(texture->function.argv);
|
|
break;
|
|
#endif /* TEXTURE_PLUGIN */
|
|
}
|
|
if (CANFREE(texture->any.color.pixel))
|
|
colors[count++] = texture->any.color.pixel;
|
|
if (count > 0) {
|
|
XErrorHandler oldhandler;
|
|
|
|
/* ignore error from buggy servers that don't know how
|
|
* to do reference counting for colors. */
|
|
XSync(dpy,0);
|
|
oldhandler = XSetErrorHandler(dummyErrorHandler);
|
|
XFreeColors(dpy, scr->w_colormap, colors, count, 0);
|
|
XSync(dpy,0);
|
|
XSetErrorHandler(oldhandler);
|
|
}
|
|
XFreeGC(dpy, texture->any.gc);
|
|
wfree(texture);
|
|
#undef CANFREE
|
|
}
|
|
|
|
|
|
|
|
WTexGradient*
|
|
wTextureMakeGradient(WScreen *scr, int style, RColor *from, RColor *to)
|
|
{
|
|
WTexGradient *texture;
|
|
XGCValues gcv;
|
|
|
|
|
|
texture = wmalloc(sizeof(WTexture));
|
|
memset(texture, 0, sizeof(WTexture));
|
|
texture->type = style;
|
|
texture->subtype = 0;
|
|
|
|
texture->color1 = *from;
|
|
texture->color2 = *to;
|
|
|
|
texture->normal.red = (from->red + to->red)<<7;
|
|
texture->normal.green = (from->green + to->green)<<7;
|
|
texture->normal.blue = (from->blue + to->blue)<<7;
|
|
|
|
XAllocColor(dpy, scr->w_colormap, &texture->normal);
|
|
gcv.background = gcv.foreground = texture->normal.pixel;
|
|
gcv.graphics_exposures = False;
|
|
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|
|
|GCGraphicsExposures, &gcv);
|
|
|
|
return texture;
|
|
}
|
|
|
|
|
|
|
|
|
|
WTexIGradient*
|
|
wTextureMakeIGradient(WScreen *scr, int thickness1, RColor colors1[2],
|
|
int thickness2, RColor colors2[2])
|
|
{
|
|
WTexIGradient *texture;
|
|
XGCValues gcv;
|
|
int i;
|
|
|
|
|
|
texture = wmalloc(sizeof(WTexture));
|
|
memset(texture, 0, sizeof(WTexture));
|
|
texture->type = WTEX_IGRADIENT;
|
|
for (i = 0; i < 2; i++) {
|
|
texture->colors1[i] = colors1[i];
|
|
texture->colors2[i] = colors2[i];
|
|
}
|
|
texture->thickness1 = thickness1;
|
|
texture->thickness2 = thickness2;
|
|
if (thickness1 >= thickness2) {
|
|
texture->normal.red = (colors1[0].red + colors1[1].red)<<7;
|
|
texture->normal.green = (colors1[0].green + colors1[1].green)<<7;
|
|
texture->normal.blue = (colors1[0].blue + colors1[1].blue)<<7;
|
|
} else {
|
|
texture->normal.red = (colors2[0].red + colors2[1].red)<<7;
|
|
texture->normal.green = (colors2[0].green + colors2[1].green)<<7;
|
|
texture->normal.blue = (colors2[0].blue + colors2[1].blue)<<7;
|
|
}
|
|
XAllocColor(dpy, scr->w_colormap, &texture->normal);
|
|
gcv.background = gcv.foreground = texture->normal.pixel;
|
|
gcv.graphics_exposures = False;
|
|
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|
|
|GCGraphicsExposures, &gcv);
|
|
|
|
return texture;
|
|
}
|
|
|
|
|
|
|
|
WTexMGradient*
|
|
wTextureMakeMGradient(WScreen *scr, int style, RColor **colors)
|
|
{
|
|
WTexMGradient *texture;
|
|
XGCValues gcv;
|
|
int i;
|
|
|
|
|
|
texture = wmalloc(sizeof(WTexture));
|
|
memset(texture, 0, sizeof(WTexture));
|
|
texture->type = style;
|
|
texture->subtype = 0;
|
|
|
|
i=0;
|
|
while (colors[i]!=NULL) i++;
|
|
i--;
|
|
texture->normal.red = (colors[0]->red<<8);
|
|
texture->normal.green = (colors[0]->green<<8);
|
|
texture->normal.blue = (colors[0]->blue<<8);
|
|
|
|
texture->colors = colors;
|
|
|
|
XAllocColor(dpy, scr->w_colormap, &texture->normal);
|
|
gcv.background = gcv.foreground = texture->normal.pixel;
|
|
gcv.graphics_exposures = False;
|
|
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|
|
|GCGraphicsExposures, &gcv);
|
|
|
|
return texture;
|
|
}
|
|
|
|
|
|
|
|
WTexPixmap*
|
|
wTextureMakePixmap(WScreen *scr, int style, char *pixmap_file, XColor *color)
|
|
{
|
|
WTexPixmap *texture;
|
|
XGCValues gcv;
|
|
RImage *image;
|
|
char *file;
|
|
|
|
file = FindImage(wPreferences.pixmap_path, pixmap_file);
|
|
if (!file) {
|
|
wwarning(_("image file \"%s\" used as texture could not be found."),
|
|
pixmap_file);
|
|
return NULL;
|
|
}
|
|
image = RLoadImage(scr->rcontext, file, 0);
|
|
if (!image) {
|
|
wwarning(_("could not load texture pixmap \"%s\":%s"), file,
|
|
RMessageForError(RErrorCode));
|
|
wfree(file);
|
|
return NULL;
|
|
}
|
|
wfree(file);
|
|
|
|
texture = wmalloc(sizeof(WTexture));
|
|
memset(texture, 0, sizeof(WTexture));
|
|
texture->type = WTEX_PIXMAP;
|
|
texture->subtype = style;
|
|
|
|
texture->normal = *color;
|
|
|
|
XAllocColor(dpy, scr->w_colormap, &texture->normal);
|
|
gcv.background = gcv.foreground = texture->normal.pixel;
|
|
gcv.graphics_exposures = False;
|
|
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|
|
|GCGraphicsExposures, &gcv);
|
|
|
|
texture->pixmap = image;
|
|
|
|
return texture;
|
|
}
|
|
|
|
WTexTGradient*
|
|
wTextureMakeTGradient(WScreen *scr, int style, RColor *from, RColor *to,
|
|
char *pixmap_file, int opacity)
|
|
{
|
|
WTexTGradient *texture;
|
|
XGCValues gcv;
|
|
RImage *image;
|
|
char *file;
|
|
|
|
file = FindImage(wPreferences.pixmap_path, pixmap_file);
|
|
if (!file) {
|
|
wwarning(_("image file \"%s\" used as texture could not be found."),
|
|
pixmap_file);
|
|
return NULL;
|
|
}
|
|
image = RLoadImage(scr->rcontext, file, 0);
|
|
if (!image) {
|
|
wwarning(_("could not load texture pixmap \"%s\":%s"), file,
|
|
RMessageForError(RErrorCode));
|
|
wfree(file);
|
|
return NULL;
|
|
}
|
|
wfree(file);
|
|
|
|
texture = wmalloc(sizeof(WTexture));
|
|
memset(texture, 0, sizeof(WTexture));
|
|
texture->type = style;
|
|
|
|
texture->opacity = opacity;
|
|
|
|
texture->color1 = *from;
|
|
texture->color2 = *to;
|
|
|
|
texture->normal.red = (from->red + to->red)<<7;
|
|
texture->normal.green = (from->green + to->green)<<7;
|
|
texture->normal.blue = (from->blue + to->blue)<<7;
|
|
|
|
XAllocColor(dpy, scr->w_colormap, &texture->normal);
|
|
gcv.background = gcv.foreground = texture->normal.pixel;
|
|
gcv.graphics_exposures = False;
|
|
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|
|
|GCGraphicsExposures, &gcv);
|
|
|
|
texture->pixmap = image;
|
|
|
|
return texture;
|
|
}
|
|
|
|
|
|
#ifdef TEXTURE_PLUGIN
|
|
WTexFunction*
|
|
wTextureMakeFunction(WScreen *scr, char *lib, char *func, int argc, char **argv)
|
|
{
|
|
XColor fallbackColor;
|
|
XGCValues gcv;
|
|
WTexFunction *texture;
|
|
|
|
texture = wmalloc(sizeof(WTexture));
|
|
texture->type = WTEX_FUNCTION;
|
|
texture->handle = NULL;
|
|
texture->render = 0;
|
|
texture->argc = argc;
|
|
texture->argv = argv;
|
|
|
|
fallbackColor.red = 0x8000;
|
|
fallbackColor.green = 0x8000;
|
|
fallbackColor.blue = 0x8000;
|
|
|
|
gcv.background = gcv.foreground = fallbackColor.pixel;
|
|
gcv.graphics_exposures = False;
|
|
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|
|
|GCGraphicsExposures, &gcv);
|
|
|
|
# ifdef HAVE_DLFCN_H
|
|
/* open the library */
|
|
texture->handle = dlopen(lib, RTLD_LAZY);
|
|
if (!texture->handle) {
|
|
wwarning(_("library \"%s\" cound not be opened."), lib);
|
|
wfree(argv);
|
|
wfree(texture);
|
|
return NULL;
|
|
}
|
|
|
|
/* find the function */
|
|
texture->render = dlsym(texture->handle, func);
|
|
if (!texture->render) {
|
|
wwarning(_("function \"%s\" not found in library \"%s\""), func, lib);
|
|
wfree(argv);
|
|
dlclose(texture->handle);
|
|
wfree(texture);
|
|
return NULL;
|
|
}
|
|
# else
|
|
wwarning(_("function textures not supported on this system, sorry."));
|
|
# endif
|
|
|
|
/* success! */
|
|
return texture;
|
|
}
|
|
#endif /* TEXTURE_PLUGIN */
|
|
|
|
|
|
RImage*
|
|
wTextureRenderImage(WTexture *texture, int width, int height,
|
|
int relief)
|
|
{
|
|
RImage *image = NULL;
|
|
RColor color1;
|
|
int d;
|
|
int subtype;
|
|
|
|
switch (texture->any.type) {
|
|
case WTEX_SOLID:
|
|
image = RCreateImage(width, height, False);
|
|
|
|
color1.red = texture->solid.normal.red >> 8;
|
|
color1.green = texture->solid.normal.green >> 8;
|
|
color1.blue = texture->solid.normal.blue >> 8;
|
|
color1.alpha = 255;
|
|
|
|
RClearImage(image, &color1);
|
|
break;
|
|
|
|
case WTEX_PIXMAP:
|
|
if (texture->pixmap.subtype == WTP_TILE) {
|
|
image = RMakeTiledImage(texture->pixmap.pixmap, width, height);
|
|
} else if (texture->pixmap.subtype == WTP_CENTER) {
|
|
color1.red = texture->pixmap.normal.red>>8;
|
|
color1.green = texture->pixmap.normal.green>>8;
|
|
color1.blue = texture->pixmap.normal.blue>>8;
|
|
color1.alpha = 255;
|
|
image = RMakeCenteredImage(texture->pixmap.pixmap, width, height,
|
|
&color1);
|
|
} else {
|
|
image = RScaleImage(texture->pixmap.pixmap, width, height);
|
|
}
|
|
break;
|
|
|
|
case WTEX_IGRADIENT:
|
|
image = RRenderInterwovenGradient(width, height,
|
|
texture->igradient.colors1,
|
|
texture->igradient.thickness1,
|
|
texture->igradient.colors2,
|
|
texture->igradient.thickness2);
|
|
break;
|
|
|
|
case WTEX_HGRADIENT:
|
|
subtype = RGRD_HORIZONTAL;
|
|
goto render_gradient;
|
|
|
|
case WTEX_VGRADIENT:
|
|
subtype = RGRD_VERTICAL;
|
|
goto render_gradient;
|
|
|
|
case WTEX_DGRADIENT:
|
|
subtype = RGRD_DIAGONAL;
|
|
render_gradient:
|
|
|
|
image = RRenderGradient(width, height, &texture->gradient.color1,
|
|
&texture->gradient.color2, subtype);
|
|
break;
|
|
|
|
case WTEX_MHGRADIENT:
|
|
subtype = RGRD_HORIZONTAL;
|
|
goto render_mgradient;
|
|
|
|
case WTEX_MVGRADIENT:
|
|
subtype = RGRD_VERTICAL;
|
|
goto render_mgradient;
|
|
|
|
case WTEX_MDGRADIENT:
|
|
subtype = RGRD_DIAGONAL;
|
|
render_mgradient:
|
|
image = RRenderMultiGradient(width, height,
|
|
&(texture->mgradient.colors[1]),
|
|
subtype);
|
|
break;
|
|
|
|
case WTEX_THGRADIENT:
|
|
subtype = RGRD_HORIZONTAL;
|
|
goto render_tgradient;
|
|
|
|
case WTEX_TVGRADIENT:
|
|
subtype = RGRD_VERTICAL;
|
|
goto render_tgradient;
|
|
|
|
case WTEX_TDGRADIENT:
|
|
subtype = RGRD_DIAGONAL;
|
|
render_tgradient:
|
|
{
|
|
RImage *grad;
|
|
|
|
image = RMakeTiledImage(texture->tgradient.pixmap, width, height);
|
|
if (!image)
|
|
break;
|
|
|
|
grad = RRenderGradient(width, height, &texture->tgradient.color1,
|
|
&texture->tgradient.color2, subtype);
|
|
if (!grad) {
|
|
RReleaseImage(image);
|
|
image = NULL;
|
|
break;
|
|
}
|
|
|
|
RCombineImagesWithOpaqueness(image, grad,
|
|
texture->tgradient.opacity);
|
|
RReleaseImage(grad);
|
|
}
|
|
break;
|
|
|
|
#ifdef TEXTURE_PLUGIN
|
|
case WTEX_FUNCTION:
|
|
#ifdef HAVE_DLFCN_H
|
|
if (texture->function.render) {
|
|
image = texture->function.render (
|
|
texture->function.argc, texture->function.argv,
|
|
width, height, relief);
|
|
}
|
|
#endif
|
|
if (!image) {
|
|
RErrorCode = RERR_INTERNAL;
|
|
}
|
|
break;
|
|
#endif /* TEXTURE_PLUGIN */
|
|
|
|
default:
|
|
puts("ERROR in wTextureRenderImage()");
|
|
image = NULL;
|
|
break;
|
|
}
|
|
|
|
if (!image) {
|
|
RColor gray;
|
|
|
|
wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
|
|
|
|
image = RCreateImage(width, height, False);
|
|
if (image == NULL) {
|
|
wwarning(_("could not allocate image buffer"));
|
|
return NULL;
|
|
}
|
|
|
|
gray.red = 190;
|
|
gray.green = 190;
|
|
gray.blue = 190;
|
|
gray.alpha = 255;
|
|
RClearImage(image, &gray);
|
|
}
|
|
|
|
|
|
/* render bevel */
|
|
|
|
switch (relief) {
|
|
case WREL_ICON:
|
|
d = RBEV_RAISED3;
|
|
break;
|
|
|
|
case WREL_RAISED:
|
|
d = RBEV_RAISED2;
|
|
break;
|
|
|
|
case WREL_SUNKEN:
|
|
d = RBEV_SUNKEN;
|
|
break;
|
|
|
|
case WREL_FLAT:
|
|
d = 0;
|
|
break;
|
|
|
|
case WREL_MENUENTRY:
|
|
d = -WREL_MENUENTRY;
|
|
break;
|
|
|
|
default:
|
|
d = 0;
|
|
}
|
|
|
|
if (d > 0) {
|
|
RBevelImage(image, d);
|
|
} else if (d < 0) {
|
|
bevelImage(image, -d);
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
bevelImage(RImage *image, int relief)
|
|
{
|
|
int width = image->width;
|
|
int height = image->height;
|
|
RColor color;
|
|
|
|
switch (relief) {
|
|
case WREL_MENUENTRY:
|
|
color.red = color.green = color.blue = 80;
|
|
color.alpha = 0;
|
|
/**/
|
|
ROperateLine(image, RAddOperation, 1, 0, width-2, 0, &color);
|
|
/**/
|
|
|
|
ROperateLine(image, RAddOperation, 0, 0, 0, height-1, &color);
|
|
|
|
color.red = color.green = color.blue = 40;
|
|
color.alpha = 0;
|
|
ROperateLine(image, RSubtractOperation, width-1, 0, width-1,
|
|
height-1, &color);
|
|
|
|
/**/
|
|
ROperateLine(image, RSubtractOperation, 1, height-2, width-2,
|
|
height-2, &color);
|
|
|
|
color.red = color.green = color.blue = 0;
|
|
color.alpha = 255;
|
|
RDrawLine(image, 0, height-1, width-1, height-1, &color);
|
|
/**/
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
wDrawBevel(Drawable d, unsigned width, unsigned height,
|
|
WTexSolid *texture, int relief)
|
|
{
|
|
GC light, dim, dark;
|
|
XSegment segs[4];
|
|
|
|
if (relief==WREL_FLAT) return;
|
|
|
|
light = texture->light_gc;
|
|
dim = texture->dim_gc;
|
|
dark = texture->dark_gc;
|
|
switch (relief) {
|
|
case WREL_FLAT:
|
|
return;
|
|
case WREL_MENUENTRY:
|
|
case WREL_RAISED:
|
|
case WREL_ICON:
|
|
segs[0].x1 = 1;
|
|
segs[0].x2 = width - 2;
|
|
segs[0].y2 = segs[0].y1 = height - 2;
|
|
segs[1].x1 = width - 2;
|
|
segs[1].y1 = 1;
|
|
segs[1].x2 = width - 2;
|
|
segs[1].y2 = height - 2;
|
|
XDrawSegments(dpy, d, dim, segs, 2);
|
|
segs[0].x1 = 0;
|
|
segs[0].x2 = width - 1;
|
|
segs[0].y2 = segs[0].y1 = height - 1;
|
|
segs[1].x1 = segs[1].x2 = width - 1;
|
|
segs[1].y1 = 0;
|
|
segs[1].y2 = height - 1;
|
|
XDrawSegments(dpy, d, dark, segs, 2);
|
|
segs[0].x1 = segs[0].y1 = segs[0].y2 = 0;
|
|
segs[0].x2 = width - 2;
|
|
segs[1].x1 = segs[1].y1 = 0;
|
|
segs[1].x2 = 0;
|
|
segs[1].y2 = height - 2;
|
|
XDrawSegments(dpy, d, light, segs, 2);
|
|
if (relief==WREL_ICON) {
|
|
segs[0].x1 = segs[0].y1 = segs[0].y2 = 1;
|
|
segs[0].x2 = width - 2;
|
|
segs[1].x1 = segs[1].y1 = 1;
|
|
segs[1].x2 = 1;
|
|
segs[1].y2 = height - 2;
|
|
XDrawSegments(dpy, d, light, segs, 2);
|
|
}
|
|
break;
|
|
#ifdef unused
|
|
case WREL_SUNKEN:
|
|
segs[0].x1 = 0;
|
|
segs[0].x2 = width - 1;
|
|
segs[0].y2 = segs[0].y1 = 0;
|
|
segs[1].x1 = segs[1].x2 = 0;
|
|
segs[1].y1 = 0;
|
|
segs[1].y2 = height - 1;
|
|
XDrawSegments(dpy, d, dark, segs, 2);
|
|
|
|
segs[0].x1 = 0;
|
|
segs[0].y1 = segs[0].y2 = height - 1;
|
|
segs[0].x2 = width - 1;
|
|
segs[1].x2 = segs[1].x1 = width - 1;
|
|
segs[1].y1 = 1;
|
|
segs[1].y2 = height - 1;
|
|
XDrawSegments(dpy, d, light, segs, 2);
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
|