X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/59fc927dc9f183802621138534fa6eaafe5593ba..688a56e8ab67b56550e2874d9d7423f0d435bfd9:/src/texture.c diff --git a/src/texture.c b/src/texture.c dissimilarity index 91% index 0fd2ad30..c0f6c2a5 100644 --- a/src/texture.c +++ b/src/texture.c @@ -1,754 +1,694 @@ -/* - * Window Maker window manager - * - * Copyright (c) 1997-2003 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 -#include - -#ifdef TEXTURE_PLUGIN -# ifdef HAVE_DLFCN_H -# include -# endif -#endif - -#include -#include -#include - -#include - -#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 - } -} - +/* + * Window Maker window manager + * + * Copyright (c) 1997-2003 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 +#include + +#ifdef TEXTURE_PLUGIN +# ifdef HAVE_DLFCN_H +# include +# endif +#endif + +#include +#include +#include + +#include + +#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 + } +}