static void free_colorset_background(colorset_t *cs, Bool do_free_args) { if (cs->picture != NULL) { if (cs->picture->picture != cs->pixmap) { add_to_junk(cs->pixmap); } SafeDestroyPicture(dpy, cs->picture); cs->picture = NULL; cs->pixmap = None; cs->alpha_pixmap = None; /* alaways equal to picture->alpha */ } if (cs->pixmap && cs->pixmap != ParentRelative && cs->pixmap != root_pic.pixmap && cs->pixmap != root_pic.old_pixmap) { add_to_junk(cs->pixmap); } cs->pixmap = None; if (cs->mask) { add_to_junk(cs->mask); cs->mask = None; } if (cs->alpha_pixmap) { add_to_junk(cs->alpha_pixmap); cs->alpha_pixmap = None; } if (cs->pixels && cs->nalloc_pixels) { PictureFreeColors( dpy, Pcmap, cs->pixels, cs->nalloc_pixels, 0, False); free(cs->pixels); cs->pixels = NULL; cs->nalloc_pixels = 0; } if (do_free_args) { if (cs->pixmap_args != NULL) { free(cs->pixmap_args); cs->pixmap_args = NULL; } if (cs->gradient_args != NULL) { free(cs->gradient_args); cs->gradient_args = NULL; } cs->is_maybe_root_transparent = False; cs->pixmap_type = 0; } }
/* Free an array of colours (n colours), never free black */ void fvwmlib_free_colors(Display *dpy, Pixel *pixels, int n, Bool no_limit) { int i; /* We don't ever free black - dirty hack to allow freeing colours at * all */ /* olicha: ???? */ for (i = 0; i < n; i++) { if (pixels[i] != 0) { PictureFreeColors( dpy, Pcmap, pixels + i, 1, 0, no_limit); } } return; }
/* translate a colorset spec into a colorset structure */ void parse_colorset(int n, char *line) { int i; int w; int h; int tmp; int percent; colorset_t *cs; char *optstring; char *args; char *option; char *tmp_str; char *fg = NULL; char *bg = NULL; char *hi = NULL; char *sh = NULL; char *fgsh = NULL; char *tint = NULL; char *fg_tint = NULL; char *bg_tint = NULL; char *icon_tint = NULL; Bool have_pixels_changed = False; Bool has_icon_pixels_changed = False; Bool has_fg_changed = False; Bool has_bg_changed = False; Bool has_sh_changed = False; Bool has_hi_changed = False; Bool has_fgsh_changed = False; Bool has_fg_alpha_changed = False; Bool has_tint_changed = False; Bool has_fg_tint_changed = False; Bool has_bg_tint_changed = False; Bool has_icon_tint_changed = False; Bool has_pixmap_changed = False; Bool has_shape_changed = False; Bool has_image_alpha_changed = False; Bool pixmap_is_a_bitmap = False; Bool do_reload_pixmap = False; Bool is_server_grabbed = False; XColor color; XGCValues xgcv; static char *name = "parse_colorset"; Window win = Scr.NoFocusWin; static GC gc = None; /* initialize statics */ if (gc == None) { gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv); } /* make sure it exists and has sensible contents */ alloc_colorset(n); cs = &Colorset[n]; /*** Parse the options ***/ while (line && *line) { /* Read next option specification delimited by a comma or \0. */ line = GetQuotedString( line, &optstring, ",", NULL, NULL, NULL); if (!optstring) break; args = GetNextToken(optstring, &option); if (!option) { free(optstring); break; } switch((i = GetTokenIndex(option, csetopts, 0, NULL))) { case 0: /* Foreground */ case 1: /* Fore */ case 2: /* fg */ get_simple_color( args, &fg, cs, FG_SUPPLIED, FG_CONTRAST, "contrast"); has_fg_changed = True; break; case 3: /* Background */ case 4: /* Back */ case 5: /* bg */ get_simple_color( args, &bg, cs, BG_SUPPLIED, BG_AVERAGE, "average"); has_bg_changed = True; break; case 6: /* Hilight */ case 7: /* Hilite */ case 8: /* hi */ get_simple_color(args, &hi, cs, HI_SUPPLIED, 0, NULL); has_hi_changed = True; break; case 9: /* Shadow */ case 10: /* Shade */ case 11: /* sh */ get_simple_color(args, &sh, cs, SH_SUPPLIED, 0, NULL); has_sh_changed = True; break; case 12: /* fgsh */ get_simple_color( args, &fgsh, cs, FGSH_SUPPLIED, 0,NULL); has_fgsh_changed = True; break; case 13: /* fg_alpha */ case 14: /* fgAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->fg_alpha_percent) { cs->fg_alpha_percent = tmp; has_fg_alpha_changed = True; } break; case 15: /* TiledPixmap */ case 16: /* Pixmap */ case 17: /* AspectPixmap */ has_pixmap_changed = True; free_colorset_background(cs, True); tmp_str = PeekToken(args, &args); if (tmp_str) { CopyString(&cs->pixmap_args, tmp_str); do_reload_pixmap = True; cs->gradient_type = 0; /* set the flags */ if (csetopts[i][0] == 'T') { cs->pixmap_type = PIXMAP_TILED; } else if (csetopts[i][0] == 'A') { cs->pixmap_type = PIXMAP_STRETCH_ASPECT; } else { cs->pixmap_type = PIXMAP_STRETCH; } } /* the pixmap is build later */ break; case 18: /* Shape */ case 19: /* TiledShape */ case 20: /* AspectShape */ parse_shape(win, cs, i, args, &has_shape_changed); break; case 21: /* Plain */ has_pixmap_changed = True; free_colorset_background(cs, True); break; case 22: /* NoShape */ has_shape_changed = True; if (cs->shape_mask) { add_to_junk(cs->shape_mask); cs->shape_mask = None; } break; case 23: /* Transparent */ /* This is only allowable when the root depth == fvwm * visual depth otherwise bad match errors happen, * it may be even more restrictive but my tests (on * exceed 6.2) show that only == depth is necessary */ if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy)))) { fvwm_msg( ERR, name, "can't do Transparent " "when root_depth!=fvwm_depth"); break; } has_pixmap_changed = True; free_colorset_background(cs, True); cs->pixmap = ParentRelative; cs->pixmap_type = PIXMAP_STRETCH; break; case 24: /* RootTransparent */ if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy)))) { fvwm_msg( ERR, name, "can't do RootTransparent " "when root_depth!=fvwm_depth"); break; } free_colorset_background(cs, True); has_pixmap_changed = True; cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE; do_reload_pixmap = True; tmp_str = PeekToken(args, &args); if (StrEquals(tmp_str, "buffer")) { cs->allows_buffered_transparency = True; } else { cs->allows_buffered_transparency = False; } cs->is_maybe_root_transparent = True; break; case 25: /* Tint */ case 26: /* PixmapTint */ case 27: /* ImageTint */ case 28: /* TintMask */ parse_simple_tint( cs, args, &tint, TINT_SUPPLIED, &has_tint_changed, &percent, "tint"); if (has_tint_changed) { cs->tint_percent = percent; } break; case 29: /* NoTint */ has_tint_changed = True; cs->tint_percent = 0; cs->color_flags &= ~TINT_SUPPLIED; break; case 30: /* fgTint */ parse_simple_tint( cs, args, &fg_tint, FG_TINT_SUPPLIED, &has_fg_tint_changed, &percent, "fgTint"); if (has_fg_tint_changed) { cs->fg_tint_percent = percent; } break; case 31: /* bgTint */ parse_simple_tint( cs, args, &bg_tint, BG_TINT_SUPPLIED, &has_bg_tint_changed, &percent, "bgTint"); if (has_bg_tint_changed) { cs->bg_tint_percent = percent; } break; case 32: /* dither */ if (cs->pixmap_args || cs->gradient_args) { has_pixmap_changed = True; do_reload_pixmap = True; } cs->dither = True; break; case 33: /* nodither */ if (cs->pixmap_args || cs->gradient_args) { has_pixmap_changed = True; do_reload_pixmap = True; } cs->dither = False; break; case 34: /* Alpha */ case 35: /* PixmapAlpha */ case 36: /* ImageAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->image_alpha_percent) { has_image_alpha_changed = True; cs->image_alpha_percent = tmp; } break; /* dither icon is not dynamic (yet) maybe a bad opt: default * to False ? */ case 37: /* ditherIcon */ cs->do_dither_icon = True; break; case 38: /* DoNotDitherIcon */ cs->do_dither_icon = False; break; case 39: /* IconTint */ parse_simple_tint( cs, args, &icon_tint, ICON_TINT_SUPPLIED, &has_icon_tint_changed, &percent, "IconTint"); if (has_icon_tint_changed) { cs->icon_tint_percent = percent; has_icon_pixels_changed = True; } break; case 40: /* NoIconTint */ has_icon_tint_changed = True; if (cs->icon_tint_percent != 0) { has_icon_pixels_changed = True; } cs->icon_tint_percent = 0; break; case 41: /* IconAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->icon_alpha_percent) { has_icon_pixels_changed = True; cs->icon_alpha_percent = tmp; } break; default: /* test for ?Gradient */ if (option[0] && StrEquals(&option[1], "Gradient")) { cs->gradient_type = toupper(option[0]); if (!IsGradientTypeSupported(cs->gradient_type)) break; has_pixmap_changed = True; free_colorset_background(cs, True); CopyString(&cs->gradient_args, args); do_reload_pixmap = True; if (cs->gradient_type == V_GRADIENT) { cs->pixmap_type = PIXMAP_STRETCH_Y; } else if (cs->gradient_type == H_GRADIENT) cs->pixmap_type = PIXMAP_STRETCH_X; else cs->pixmap_type = PIXMAP_STRETCH; } else { fvwm_msg( WARN, name, "bad colorset pixmap " "specifier %s %s", option, line); } break; } /* switch */ if (option) { free(option); option = NULL; } free(optstring); optstring = NULL; } /* while (line && *line) */ /* * ---------- change the "pixmap" tint colour ---------- */ if (has_tint_changed) { /* user specified colour */ if (tint != NULL) { Pixel old_tint = cs->tint; PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True); cs->tint = GetColor(tint); if (old_tint != cs->tint) { have_pixels_changed = True; } } else if (tint == NULL) { /* default */ Pixel old_tint = cs->tint; PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True); cs->tint = GetColor(black); if (old_tint != cs->tint) { have_pixels_changed = True; } } } /* * reload the gradient if the tint or the alpha have changed. * Do this too if we need to recompute the bg average and the * gradient is tinted (perforemence issue). */ if ((has_tint_changed || has_image_alpha_changed || (has_bg_changed && (cs->color_flags & BG_AVERAGE) && cs->tint_percent > 0)) && cs->gradient_args) { do_reload_pixmap = True; } /* * reset the pixmap if the tint or the alpha has changed */ if (!do_reload_pixmap && (has_tint_changed || has_image_alpha_changed || (has_bg_changed && cs->alpha_pixmap != None))) { if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE || cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN) { do_reload_pixmap = True; } else if (cs->picture != NULL && cs->pixmap) { XSetClipMask(dpy, gc, cs->picture->mask); reset_cs_pixmap(cs, gc); XSetClipMask(dpy, gc, None); has_pixmap_changed = True; } } /* * (re)build the pixmap or the gradient */ if (do_reload_pixmap) { free_colorset_background(cs, False); has_pixmap_changed = True; if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE || cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN) { cs->pixmap_type = 0; if (root_pic.pixmap) { cs->pixmap = root_pic.pixmap; cs->width = root_pic.width; cs->height = root_pic.height; cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE; #if 0 fprintf(stderr,"Cset %i LoadRoot 0x%lx\n", n, cs->pixmap); #endif } } else if (cs->pixmap_args) { parse_pixmap(win, gc, cs, &pixmap_is_a_bitmap); } else if (cs->gradient_args) { cs->pixmap = CreateGradientPixmapFromString( dpy, win, gc, cs->gradient_type, cs->gradient_args, &w, &h, &cs->pixels, &cs->nalloc_pixels, cs->dither); cs->width = w; cs->height = h; } has_pixmap_changed = True; } if (cs->picture != NULL && cs->picture->depth != Pdepth) { pixmap_is_a_bitmap = True; } /* * ---------- change the background colour ---------- */ if (has_bg_changed || (has_pixmap_changed && (cs->color_flags & BG_AVERAGE) && cs->pixmap != None && cs->pixmap != ParentRelative && !pixmap_is_a_bitmap)) { Bool do_set_default_background = False; Pixmap average_pix = None; if (cs->color_flags & BG_AVERAGE) { if (cs->picture != NULL && cs->picture->picture != None) { average_pix = cs->picture->picture; } else if (cs->pixmap != ParentRelative) { average_pix = cs->pixmap; } if (average_pix == root_pic.pixmap) { int w; int h; XID dummy; MyXGrabServer(dpy); is_server_grabbed = True; if (!XGetGeometry( dpy, average_pix, &dummy, (int *)&dummy, (int *)&dummy, (unsigned int *)&w, (unsigned int *)&h, (unsigned int *)&dummy, (unsigned int *)&dummy)) { average_pix = None; } else { if (w != cs->width || h != cs->height) { average_pix = None; } } if (average_pix == None) { MyXUngrabServer(dpy); is_server_grabbed = False; } } } /* note: no average for bitmap */ if ((cs->color_flags & BG_AVERAGE) && average_pix) { /* calculate average background color */ XColor *colors; XImage *image; XImage *mask_image = None; unsigned int i, j, k = 0; unsigned long red = 0, blue = 0, green = 0; unsigned long tred, tblue, tgreen; double dred = 0.0, dblue = 0.0, dgreen = 0.0; has_bg_changed = True; /* create an array to store all the pixmap colors in */ /* Note: this may allocate a lot of memory: * cs->width * cs->height * 12 and then the rest of the * procedure can take a lot of times */ colors = (XColor *)safemalloc( cs->width * cs->height * sizeof(XColor)); /* get the pixmap and mask into an image */ image = XGetImage( dpy, average_pix, 0, 0, cs->width, cs->height, AllPlanes, ZPixmap); if (cs->mask != None) { mask_image = XGetImage( dpy, cs->mask, 0, 0, cs->width, cs->height, AllPlanes, ZPixmap); } if (is_server_grabbed == True) { MyXUngrabServer(dpy); } if (image != None && mask_image != None) { /* only fetch the pixels that are not masked * out */ for (i = 0; i < cs->width; i++) { for (j = 0; j < cs->height; j++) { if ( cs->mask == None || XGetPixel( mask_image, i, j) == 0) { colors[k++].pixel = XGetPixel( image, i, j); } } } } if (image != None) { XDestroyImage(image); } if (mask_image != None) { XDestroyImage(mask_image); } if (k == 0) { do_set_default_background = True; } else { /* look them all up, XQueryColors() can't * handle more than 256 */ for (i = 0; i < k; i += 256) { XQueryColors( dpy, Pcmap, &colors[i], min(k - i, 256)); } /* calculate average, add overflows in a double * .red is short, red is long */ for (i = 0; i < k; i++) { tred = red; red += colors[i].red; if (red < tred) { dred += (double)tred; red = colors[i].red; } tgreen = green; green += colors[i].green; if (green < tgreen) { dgreen += (double)tgreen; green = colors[i].green; } tblue = blue; blue += colors[i].blue; if (blue < tblue) { dblue += (double)tblue; blue = colors[i].blue; } } dred += red; dgreen += green; dblue += blue; /* get it */ color.red = dred / k; color.green = dgreen / k; color.blue = dblue / k; { Pixel old_bg = cs->bg; PictureFreeColors( dpy, Pcmap, &cs->bg, 1, 0, True); PictureAllocColor( dpy, Pcmap, &color, True); cs->bg = color.pixel; if (old_bg != cs->bg) { have_pixels_changed = True; } } } free(colors); } /* average */ else if ((cs->color_flags & BG_SUPPLIED) && bg != NULL) { /* user specified colour */ Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetColor(bg); if (old_bg != cs->bg) { have_pixels_changed = True; } } /* user specified */ else if (bg == NULL && has_bg_changed) { /* default */ do_set_default_background = True; } /* default */ if (do_set_default_background) { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetColor(white); if (old_bg != cs->bg) { have_pixels_changed = True; } has_bg_changed = True; } if (has_bg_changed) { /* save the bg color for tinting */ cs->bg_saved = cs->bg; } } /* has_bg_changed */ /* * ---------- setup the bg tint colour ---------- */ if (has_bg_tint_changed && cs->bg_tint_percent > 0 && bg_tint != NULL) { PictureFreeColors(dpy, Pcmap, &cs->bg_tint, 1, 0, True); cs->bg_tint = GetColor(bg_tint); } /* * ---------- tint the bg colour ---------- */ if (has_bg_tint_changed || (has_bg_changed && cs->bg_tint_percent > 0)) { if (cs->bg_tint_percent == 0) { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = cs->bg_saved; if (old_bg != cs->bg) { have_pixels_changed = True; has_bg_changed = True; } } else { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetTintedPixel( cs->bg_saved, cs->bg_tint, cs->bg_tint_percent); if (old_bg != cs->bg) { have_pixels_changed = True; has_bg_changed = True; } } } /* * ---------- setup the fg tint colour ---------- */ if (has_fg_tint_changed && cs->fg_tint_percent > 0 && fg_tint != NULL) { PictureFreeColors(dpy, Pcmap, &cs->fg_tint, 1, 0, True); cs->fg_tint = GetColor(fg_tint); } /* * ---------- change the foreground colour ---------- */ if (has_fg_changed || (has_bg_changed && (cs->color_flags & FG_CONTRAST))) { if (cs->color_flags & FG_CONTRAST) { Pixel old_fg = cs->fg; /* calculate contrasting foreground color */ color.pixel = cs->bg; XQueryColor(dpy, Pcmap, &color); color.red = (color.red > 32767) ? 0 : 65535; color.green = (color.green > 32767) ? 0 : 65535; color.blue = (color.blue > 32767) ? 0 : 65535; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); PictureAllocColor(dpy, Pcmap, &color, True); cs->fg = color.pixel; if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* contrast */ else if ((cs->color_flags & FG_SUPPLIED) && fg != NULL) { /* user specified colour */ Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetColor(fg); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* user specified */ else if (fg == NULL) { /* default */ Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetColor(black); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* save the fg color for tinting */ cs->fg_saved = cs->fg; } /* has_fg_changed */ /* * ---------- tint the foreground colour ---------- */ if (has_fg_tint_changed || (has_fg_changed && cs->fg_tint_percent > 0)) { if (cs->fg_tint_percent == 0) { Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = cs->fg_saved; if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } else { Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetTintedPixel( cs->fg_saved, cs->fg_tint, cs->fg_tint_percent); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } } /* * ---------- change the hilight colour ---------- */ if (has_hi_changed || (has_bg_changed && !(cs->color_flags & HI_SUPPLIED))) { has_hi_changed = 1; if ((cs->color_flags & HI_SUPPLIED) && hi != NULL) { /* user specified colour */ Pixel old_hilite = cs->hilite; PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True); cs->hilite = GetColor(hi); if (old_hilite != cs->hilite) { have_pixels_changed = True; } } /* user specified */ else if (hi == NULL) { Pixel old_hilite = cs->hilite; PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True); cs->hilite = GetHilite(cs->bg); if (old_hilite != cs->hilite) { have_pixels_changed = True; } } } /* has_hi_changed */ /* * ---------- change the shadow colour ---------- */ if (has_sh_changed || (has_bg_changed && !(cs->color_flags & SH_SUPPLIED))) { has_sh_changed = 1; if ((cs->color_flags & SH_SUPPLIED) && sh != NULL) { /* user specified colour */ Pixel old_shadow = cs->shadow; PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True); cs->shadow = GetColor(sh); if (old_shadow != cs->shadow) { have_pixels_changed = True; } } /* user specified */ else if (sh == NULL) { Pixel old_shadow = cs->shadow; PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True); cs->shadow = GetShadow(cs->bg); if (old_shadow != cs->shadow) { have_pixels_changed = True; } } } /* has_sh_changed */ /* * ---------- change the shadow foreground colour ---------- */ if (has_fgsh_changed || ((has_fg_changed || has_bg_changed) && !(cs->color_flags & FGSH_SUPPLIED))) { has_fgsh_changed = 1; if ((cs->color_flags & FGSH_SUPPLIED) && fgsh != NULL) { /* user specified colour */ Pixel old_fgsh = cs->fgsh; PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True); cs->fgsh = GetColor(fgsh); if (old_fgsh != cs->fgsh) { have_pixels_changed = True; } } /* user specified */ else if (fgsh == NULL) { Pixel old_fgsh = cs->fgsh; PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True); cs->fgsh = GetForeShadow(cs->fg, cs->bg); if (old_fgsh != cs->fgsh) { have_pixels_changed = True; } } } /* has_fgsh_changed */ /* * ------- the pixmap is a bitmap: create here cs->pixmap ------- */ if (cs->picture != None && pixmap_is_a_bitmap && (has_pixmap_changed || has_bg_changed)) { cs->pixmap = XCreatePixmap( dpy, win, cs->width, cs->height, Pdepth); XSetBackground(dpy, gc, cs->bg); XSetForeground(dpy, gc, cs->fg); reset_cs_pixmap(cs, gc); } /* * ------- change the masked out parts of the background pixmap ------- */ if (cs->pixmap != None && cs->pixmap != ParentRelative && (!CSETS_IS_TRANSPARENT_ROOT(cs)|| cs->allows_buffered_transparency) && (cs->mask != None || cs->alpha_pixmap != None || cs->image_alpha_percent < 100 || cs->tint_percent > 0) && (has_pixmap_changed || has_bg_changed || has_image_alpha_changed || has_tint_changed)) { /* Now that we know the background colour we can update the * pixmap background. */ FvwmRenderAttributes fra; Pixmap temp, mask, alpha; memset(&fra, 0, sizeof(fra)); temp = XCreatePixmap(dpy, win, cs->width, cs->height, Pdepth); if (cs->picture != NULL) { mask = cs->picture->mask; alpha = cs->picture->alpha; } else { mask = None; alpha = None; } XSetForeground(dpy, gc, cs->bg); XFillRectangle( dpy, temp, gc, 0, 0, cs->width, cs->height); fra.mask = FRAM_HAVE_ADDED_ALPHA | FRAM_HAVE_TINT; fra.added_alpha_percent = cs->image_alpha_percent; fra.tint = cs->tint; fra.tint_percent = cs->tint_percent; PGraphicsRenderPixmaps( dpy, win, cs->pixmap, mask, alpha, Pdepth, &fra, temp, gc, Scr.MonoGC, Scr.AlphaGC, 0, 0, cs->width, cs->height, 0, 0, cs->width, cs->height, False); if (cs->pixmap != root_pic.pixmap) { add_to_junk(cs->pixmap); } cs->pixmap = temp; has_pixmap_changed = True; if (CSETS_IS_TRANSPARENT_ROOT(cs)) { cs->pixmap_type = PIXMAP_ROOT_PIXMAP_TRAN; } } /* has_pixmap_changed */ /* * ---------- change the icon tint colour ---------- */ if (has_icon_tint_changed) { /* user specified colour */ if (icon_tint != NULL) { Pixel old_tint = cs->icon_tint; PictureFreeColors( dpy, Pcmap, &cs->icon_tint, 1, 0, True); cs->icon_tint = GetColor(icon_tint); if (old_tint != cs->icon_tint) { has_icon_pixels_changed = True; } } else { /* default */ Pixel old_tint = cs->icon_tint; PictureFreeColors( dpy, Pcmap, &cs->icon_tint, 1, 0, True); cs->icon_tint = GetColor(black); if (old_tint != cs->icon_tint) { has_icon_pixels_changed = True; } } } /* * ---------- send new colorset to fvwm and clean up ---------- */ /* make sure the server has this to avoid races */ XSync(dpy, False); /* inform modules of the change */ if (have_pixels_changed || has_pixmap_changed || has_shape_changed || has_fg_alpha_changed || has_icon_pixels_changed) { BroadcastColorset(n); } if (fg) { free(fg); } if (bg) { free(bg); } if (hi) { free(hi); } if (sh) { free(sh); } if (fgsh) { free(fgsh); } if (tint) { free(tint); } if (fg_tint) { free(fg_tint); } if (bg_tint) { free(bg_tint); } if (icon_tint) { free(icon_tint); } return; }
void PDestroyFvwmPicture(Display *dpy, FvwmPicture *p) { FvwmPicture *q = FvwmPictureList; if (!p) { return; } /* Remove a weight */ if(--(p->count)>0) { /* still too heavy? */ return; } /* Let it fly */ if (p->alloc_pixels != NULL) { if (p->nalloc_pixels != 0) { PictureFreeColors( dpy, Pcmap, p->alloc_pixels, p->nalloc_pixels, 0, p->no_limit); } free(p->alloc_pixels); } if(p->name!=NULL) { free(p->name); } if(p->picture!=None) { XFreePixmap(dpy,p->picture); } if(p->mask!=None) { XFreePixmap(dpy,p->mask); } if(p->alpha != None) { XFreePixmap(dpy, p->alpha); } /* Link it out of the list (it might not be there) */ if(p==q) /* in head? simple */ { FvwmPictureList = p->next; } else { while(q && q->next!=p) /* fast forward until end or found */ { q = q->next; } if(q) /* not end? means we found it in there, possibly at end */ { q->next = p->next; /* link around it */ } } free(p); return; }
/* Does the actual drawing of the pixmap. If the in_drawable argument is None, * a new pixmap of the given depth, width and height is created. If it is not * None the gradient is drawn into it. The d_width, d_height, d_x and d_y * describe the traget rectangle within the drawable. */ Drawable CreateGradientPixmap( Display *dpy, Drawable d, GC gc, int type, int g_width, int g_height, int ncolors, XColor *xcs, int dither, Pixel **d_pixels, int *d_npixels, Drawable in_drawable, int d_x, int d_y, int d_width, int d_height, XRectangle *rclip) { Pixmap pixmap = None; PictureImageColorAllocator *pica = NULL; XColor c; FImage *fim; register int i, j; XGCValues xgcv; Drawable target; int t_x; int t_y; int t_width; int t_height; if (d_pixels != NULL && *d_pixels != NULL) { if (d_npixels != NULL && *d_npixels > 0) { PictureFreeColors( dpy, Pcmap, *d_pixels, *d_npixels, 0, False); } free(*d_pixels); *d_pixels = NULL; } if (d_npixels != NULL) { *d_npixels = 0; } if (g_height < 0 || g_width < 0 || d_width < 0 || d_height < 0) return None; if (in_drawable == None) { /* create a pixmap to use */ pixmap = XCreatePixmap(dpy, d, g_width, g_height, Pdepth); if (pixmap == None) return None; target = pixmap; t_x = 0; t_y = 0; t_width = g_width; t_height = g_height; } else { target = in_drawable; t_x = d_x; t_y = d_y; t_width = d_width; t_height = d_height; } fim = FCreateFImage( dpy, Pvisual, Pdepth, ZPixmap, t_width, t_height); if (!fim) { fprintf(stderr, "%cGradient couldn't get image\n", type); if (pixmap != None) XFreePixmap(dpy, pixmap); return None; } if (dither) { pica = PictureOpenImageColorAllocator( dpy, Pcmap, t_width, t_height, False, False, dither, False); } /* now do the fancy drawing */ switch (type) { case H_GRADIENT: { for (i = 0; i < t_width; i++) { int d = i * ncolors / t_width; c = xcs[d]; for (j = 0; j < t_height; j++) { if (dither) { c = xcs[d]; PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } } break; case V_GRADIENT: { for (j = 0; j < t_height; j++) { int d = j * ncolors / t_height; c = xcs[d]; for (i = 0; i < t_width; i++) { if (dither) { c = xcs[d]; PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } break; } case D_GRADIENT: { register int t_scale = t_width + t_height - 1; for (i = 0; i < t_width; i++) { for (j = 0; j < t_height; j++) { c = xcs[(i+j) * ncolors / t_scale]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } break; } case B_GRADIENT: { register int t_scale = t_width + t_height - 1; for (i = 0; i < t_width; i++) { for (j = 0; j < t_height; j++) { c = xcs[(i + (t_height - j - 1)) * ncolors / t_scale]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } break; } case S_GRADIENT: { register int t_scale = t_width * t_height; register int myncolors = ncolors * 2; for (i = 0; i < t_width; i++) { register int pi = min(i, t_width - 1 - i) * t_height; for (j = 0; j < t_height; j++) { register int pj = min(j, t_height - 1 - j) * t_width; c = xcs[(min(pi, pj) * myncolors - 1) / t_scale]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } } break; case C_GRADIENT: { register double t_scale = (double)(t_width * t_height) / sqrt(8); for (i = 0; i < t_width; i++) { for (j = 0; j < t_height; j++) { register double x = (double)((2 * i - t_width) * t_height) / 4.0; register double y = (double)((t_height - 2 * j) * t_width) / 4.0; register double rad = sqrt(x * x + y * y); c = xcs[(int)((rad * ncolors - 0.5) / t_scale)]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } break; } case R_GRADIENT: { register int w = t_width - 1; register int h = t_height - 1; /* g_width == g_height, both are odd, therefore x can be 0.0 */ for (i = 0; i <= w; i++) { for (j = 0; j <= h; j++) { register double x = (double)((2 * i - w) * h) / 4.0; register double y = (double)((h - 2 * j) * w) / 4.0; /* angle ranges from -pi/2 to +pi/2 */ register double angle; if (x != 0.0) { angle = atan(y / x); } else { angle = (y < 0) ? - M_PI_2 : M_PI_2; } /* extend to -pi/2 to 3pi/2 */ if (x < 0) angle += M_PI; /* move range from -pi/2:3*pi/2 to 0:2*pi */ if (angle < 0.0) angle += M_PI * 2.0; /* normalize to gradient */ c = xcs[(int)(angle * M_1_PI * 0.5 * ncolors)]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } } break; /* * The Yin Yang gradient style and the following code are: * Copyright 1999 Sir Boris. (email to [email protected] may be * read by his groom but is not guaranteed to elicit a response) * No restrictions are placed on this code, as long as the copyright * notice is preserved. */ case Y_GRADIENT: { register int r = t_width * t_height / 4; for (i = 0; i < t_width; i++) { for (j = 0; j < t_height; j++) { register double x = (double)((2 * i - t_width) * t_height) / 4.0; register double y = (double)((t_height - 2 * j) * t_width) / 4.0; register double rad = sqrt(x * x + y * y); /* angle ranges from -pi/2 to +pi/2 */ register double angle; if (x != 0.0) { angle = atan(y / x); } else { angle = (y < 0) ? - M_PI_2 : M_PI_2; } /* extend to -pi/2 to 3pi/2 */ if (x < 0) angle += M_PI; /* warp the angle within the yinyang circle */ if (rad <= r) { angle -= acos(rad / r); } /* move range from -pi/2:3*pi/2 to 0:2*pi */ if (angle < 0.0) angle += M_PI * 2.0; /* normalize to gradient */ c = xcs[(int)(angle * M_1_PI * 0.5 * ncolors)]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } } break; default: /* placeholder function, just fills the pixmap with the first * color */ memset(fim->im->data, 0, fim->im->bytes_per_line * t_height); XAddPixel(fim->im, xcs[0].pixel); break; } if (dither) { if (d_pixels != NULL && d_npixels != NULL) { PictureCloseImageColorAllocator( dpy, pica, d_npixels, d_pixels, 0); } else { /* possible color leak */ } } /* set the gc style */ xgcv.function = GXcopy; xgcv.plane_mask = AllPlanes; xgcv.fill_style = FillSolid; xgcv.clip_mask = None; XChangeGC(dpy, gc, GCFunction|GCPlaneMask|GCFillStyle|GCClipMask, &xgcv); if (rclip) { XSetClipRectangles(dpy, gc, 0, 0, rclip, 1, Unsorted); } /* copy the image to the server */ FPutFImage(dpy, target, gc, fim, 0, 0, t_x, t_y, t_width, t_height); if (rclip) { XSetClipMask(dpy, gc, None); } FDestroyFImage(dpy, fim); return target; }