📄 gdkcolor.c
字号:
/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include <time.h>#include <X11/Xlib.h>#include "gdk.h"#include "gdkprivate.h"#include "gdkx.h"static gint gdk_colormap_match_color (GdkColormap *cmap, GdkColor *color, const gchar *available);static void gdk_colormap_add (GdkColormap *cmap);static void gdk_colormap_remove (GdkColormap *cmap);static guint gdk_colormap_hash (Colormap *cmap);static gint gdk_colormap_cmp (Colormap *a, Colormap *b);static void gdk_colormap_real_destroy (GdkColormap *colormap);static GHashTable *colormap_hash = NULL;GdkColormap*gdk_colormap_new (GdkVisual *visual, gint private_cmap){ GdkColormap *colormap; GdkColormapPrivate *private; Visual *xvisual; int size; int i; g_return_val_if_fail (visual != NULL, NULL); private = g_new (GdkColormapPrivate, 1); colormap = (GdkColormap*) private; private->xdisplay = gdk_display; private->visual = visual; private->ref_count = 1; private->hash = NULL; private->last_sync_time = 0; private->info = NULL; xvisual = ((GdkVisualPrivate*) visual)->xvisual; colormap->size = visual->colormap_size; colormap->colors = NULL; switch (visual->type) { case GDK_VISUAL_GRAYSCALE: case GDK_VISUAL_PSEUDO_COLOR: private->info = g_new0 (GdkColorInfo, colormap->size); colormap->colors = g_new (GdkColor, colormap->size); private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash, (GCompareFunc) gdk_color_equal); private->private_val = private_cmap; private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window, xvisual, (private_cmap) ? (AllocAll) : (AllocNone)); if (private_cmap) { XColor *default_colors; default_colors = g_new (XColor, colormap->size); for (i = 0; i < colormap->size; i++) default_colors[i].pixel = i; XQueryColors (private->xdisplay, DefaultColormap (private->xdisplay, gdk_screen), default_colors, colormap->size); for (i = 0; i < colormap->size; i++) { colormap->colors[i].pixel = default_colors[i].pixel; colormap->colors[i].red = default_colors[i].red; colormap->colors[i].green = default_colors[i].green; colormap->colors[i].blue = default_colors[i].blue; } gdk_colormap_change (colormap, colormap->size); g_free (default_colors); } break; case GDK_VISUAL_DIRECT_COLOR: private->private_val = TRUE; private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window, xvisual, AllocAll); colormap->colors = g_new (GdkColor, colormap->size); size = 1 << visual->red_prec; for (i = 0; i < size; i++) colormap->colors[i].red = i * 65535 / (size - 1); size = 1 << visual->green_prec; for (i = 0; i < size; i++) colormap->colors[i].green = i * 65535 / (size - 1); size = 1 << visual->blue_prec; for (i = 0; i < size; i++) colormap->colors[i].blue = i * 65535 / (size - 1); gdk_colormap_change (colormap, colormap->size); break; case GDK_VISUAL_STATIC_GRAY: case GDK_VISUAL_STATIC_COLOR: case GDK_VISUAL_TRUE_COLOR: private->private_val = FALSE; private->xcolormap = XCreateColormap (private->xdisplay, gdk_root_window, xvisual, AllocNone); break; } gdk_colormap_add (colormap); return colormap;}static voidgdk_colormap_real_destroy (GdkColormap *colormap){ GdkColormapPrivate *private = (GdkColormapPrivate*) colormap; g_return_if_fail (colormap != NULL); g_return_if_fail (private->ref_count == 0); gdk_colormap_remove (colormap); XFreeColormap (private->xdisplay, private->xcolormap); if (private->hash) g_hash_table_destroy (private->hash); g_free (private->info); g_free (colormap->colors); g_free (colormap);}GdkColormap*gdk_colormap_ref (GdkColormap *cmap){ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap; g_return_val_if_fail (cmap != NULL, NULL); private->ref_count += 1; return cmap;}voidgdk_colormap_unref (GdkColormap *cmap){ GdkColormapPrivate *private = (GdkColormapPrivate *)cmap; g_return_if_fail (cmap != NULL); g_return_if_fail (private->ref_count > 0); private->ref_count -= 1; if (private->ref_count == 0) gdk_colormap_real_destroy (cmap);}GdkVisual *gdk_colormap_get_visual (GdkColormap *colormap){ GdkColormapPrivate *private; g_return_val_if_fail (colormap != NULL, NULL); private = (GdkColormapPrivate *)colormap; return private->visual;} #define MIN_SYNC_TIME 2voidgdk_colormap_sync (GdkColormap *colormap, gboolean force){ time_t current_time; GdkColormapPrivate *private = (GdkColormapPrivate *)colormap; XColor *xpalette; gint nlookup; gint i; g_return_if_fail (colormap != NULL); current_time = time (NULL); if (!force && ((current_time - private->last_sync_time) < MIN_SYNC_TIME)) return; private->last_sync_time = current_time; nlookup = 0; xpalette = g_new (XColor, colormap->size); for (i = 0; i < colormap->size; i++) { if (private->info[i].ref_count == 0) { xpalette[nlookup].pixel = i; xpalette[nlookup].red = 0; xpalette[nlookup].green = 0; xpalette[nlookup].blue = 0; nlookup++; } } XQueryColors (gdk_display, private->xcolormap, xpalette, nlookup); for (i = 0; i < nlookup; i++) { gulong pixel = xpalette[i].pixel; colormap->colors[pixel].pixel = pixel; colormap->colors[pixel].red = xpalette[i].red; colormap->colors[pixel].green = xpalette[i].green; colormap->colors[pixel].blue = xpalette[i].blue; } g_free (xpalette);} GdkColormap*gdk_colormap_get_system (void){ static GdkColormap *colormap = NULL; GdkColormapPrivate *private; if (!colormap) { private = g_new (GdkColormapPrivate, 1); colormap = (GdkColormap*) private; private->xdisplay = gdk_display; private->xcolormap = DefaultColormap (gdk_display, gdk_screen); private->visual = gdk_visual_get_system (); private->private_val = FALSE; private->ref_count = 1; private->hash = NULL; private->last_sync_time = 0; private->info = NULL; colormap->colors = NULL; colormap->size = private->visual->colormap_size; if ((private->visual->type == GDK_VISUAL_GRAYSCALE) || (private->visual->type == GDK_VISUAL_PSEUDO_COLOR)) { private->info = g_new0 (GdkColorInfo, colormap->size); colormap->colors = g_new (GdkColor, colormap->size); private->hash = g_hash_table_new ((GHashFunc) gdk_color_hash, (GCompareFunc) gdk_color_equal); gdk_colormap_sync (colormap, TRUE); } gdk_colormap_add (colormap); } return colormap;}gintgdk_colormap_get_system_size (void){ return DisplayCells (gdk_display, gdk_screen);}voidgdk_colormap_change (GdkColormap *colormap, gint ncolors){ GdkColormapPrivate *private; GdkVisual *visual; XColor *palette; gint shift; int max_colors; int size; int i; g_return_if_fail (colormap != NULL); palette = g_new (XColor, ncolors); private = (GdkColormapPrivate*) colormap; switch (private->visual->type) { case GDK_VISUAL_GRAYSCALE: case GDK_VISUAL_PSEUDO_COLOR: for (i = 0; i < ncolors; i++) { palette[i].pixel = colormap->colors[i].pixel; palette[i].red = colormap->colors[i].red; palette[i].green = colormap->colors[i].green; palette[i].blue = colormap->colors[i].blue; palette[i].flags = DoRed | DoGreen | DoBlue; } XStoreColors (private->xdisplay, private->xcolormap, palette, ncolors); break; case GDK_VISUAL_DIRECT_COLOR: visual = private->visual; shift = visual->red_shift; max_colors = 1 << visual->red_prec; size = (ncolors < max_colors) ? (ncolors) : (max_colors); for (i = 0; i < size; i++) { palette[i].pixel = i << shift; palette[i].red = colormap->colors[i].red; palette[i].flags = DoRed; } XStoreColors (private->xdisplay, private->xcolormap, palette, size); shift = visual->green_shift; max_colors = 1 << visual->green_prec; size = (ncolors < max_colors) ? (ncolors) : (max_colors); for (i = 0; i < size; i++) { palette[i].pixel = i << shift; palette[i].green = colormap->colors[i].green; palette[i].flags = DoGreen; } XStoreColors (private->xdisplay, private->xcolormap, palette, size); shift = visual->blue_shift; max_colors = 1 << visual->blue_prec; size = (ncolors < max_colors) ? (ncolors) : (max_colors); for (i = 0; i < size; i++) { palette[i].pixel = i << shift; palette[i].blue = colormap->colors[i].blue; palette[i].flags = DoBlue; } XStoreColors (private->xdisplay, private->xcolormap, palette, size); break; default: break; } g_free (palette);}voidgdk_colors_store (GdkColormap *colormap, GdkColor *colors, gint ncolors){ gint i; for (i = 0; i < ncolors; i++) { colormap->colors[i].pixel = colors[i].pixel; colormap->colors[i].red = colors[i].red; colormap->colors[i].green = colors[i].green; colormap->colors[i].blue = colors[i].blue; } gdk_colormap_change (colormap, ncolors);}gbooleangdk_colors_alloc (GdkColormap *colormap, gint contiguous, gulong *planes, gint nplanes, gulong *pixels, gint npixels){ GdkColormapPrivate *private; gint return_val; gint i; g_return_val_if_fail (colormap != NULL, 0); private = (GdkColormapPrivate*) colormap; return_val = XAllocColorCells (private->xdisplay, private->xcolormap, contiguous, planes, nplanes, pixels, npixels); if (return_val) { for (i=0; i<npixels; i++) { private->info[pixels[i]].ref_count++; private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE; } } return return_val != 0;}/* *-------------------------------------------------------------- * gdk_color_copy * * Copy a color structure into new storage. * * Arguments: * "color" is the color struct to copy. * * Results: * A new color structure. Free it with gdk_color_free. * *-------------------------------------------------------------- */static GMemChunk *color_chunk;GdkColor*gdk_color_copy (GdkColor *color){ GdkColor *new_color; g_return_val_if_fail (color != NULL, NULL); if (color_chunk == NULL) color_chunk = g_mem_chunk_new ("colors", sizeof (GdkColor), 4096, G_ALLOC_AND_FREE); new_color = g_chunk_new (GdkColor, color_chunk); *new_color = *color; return new_color;}/* *-------------------------------------------------------------- * gdk_color_free * * Free a color structure obtained from gdk_color_copy. Do not use * with other color structures. * * Arguments: * "color" is the color struct to free. * *-------------------------------------------------------------- */voidgdk_color_free (GdkColor *color){ g_assert (color_chunk != NULL); g_return_if_fail (color != NULL); g_mem_chunk_free (color_chunk, color);}gbooleangdk_color_white (GdkColormap *colormap, GdkColor *color){ gint return_val; g_return_val_if_fail (colormap != NULL, FALSE); if (color) { color->pixel = WhitePixel (gdk_display, gdk_screen); color->red = 65535; color->green = 65535; color->blue = 65535; return_val = gdk_color_alloc (colormap, color); } else return_val = FALSE; return return_val;}gbooleangdk_color_black (GdkColormap *colormap, GdkColor *color){ gint return_val; g_return_val_if_fail (colormap != NULL, FALSE); if (color) { color->pixel = BlackPixel (gdk_display, gdk_screen); color->red = 0; color->green = 0; color->blue = 0; return_val = gdk_color_alloc (colormap, color); } else return_val = FALSE; return return_val;}gbooleangdk_color_parse (const gchar *spec, GdkColor *color){ Colormap xcolormap; XColor xcolor; gboolean return_val; g_return_val_if_fail (spec != NULL, FALSE); g_return_val_if_fail (color != NULL, FALSE); xcolormap = DefaultColormap (gdk_display, gdk_screen); if (XParseColor (gdk_display, xcolormap, spec, &xcolor)) { return_val = TRUE; color->red = xcolor.red; color->green = xcolor.green; color->blue = xcolor.blue; } else return_val = FALSE; return return_val;}/* This is almost identical to gdk_colormap_free_colors. * Keep them in sync! */voidgdk_colors_free (GdkColormap *colormap, gulong *in_pixels, gint in_npixels, gulong planes){ GdkColormapPrivate *private; gulong *pixels; gint npixels = 0; gint i; g_return_if_fail (colormap != NULL); g_return_if_fail (in_pixels != NULL); private = (GdkColormapPrivate*) colormap; if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) && (private->visual->type != GDK_VISUAL_GRAYSCALE)) return; pixels = g_new (gulong, in_npixels); for (i=0; i<in_npixels; i++) { gulong pixel = in_pixels[i]; if (private->info[pixel].ref_count) { private->info[pixel].ref_count--; if (private->info[pixel].ref_count == 0) { pixels[npixels++] = pixel; if (!(private->info[pixel].flags & GDK_COLOR_WRITEABLE)) g_hash_table_remove (private->hash, &colormap->colors[pixel]); private->info[pixel].flags = 0; } } } if (npixels) XFreeColors (private->xdisplay, private->xcolormap, pixels, npixels, planes); g_free (pixels);}/* This is almost identical to gdk_colors_free. * Keep them in sync! */voidgdk_colormap_free_colors (GdkColormap *colormap, GdkColor *colors, gint ncolors){ GdkColormapPrivate *private; gulong *pixels; gint npixels = 0; gint i; g_return_if_fail (colormap != NULL); g_return_if_fail (colors != NULL); private = (GdkColormapPrivate*) colormap; if ((private->visual->type != GDK_VISUAL_PSEUDO_COLOR) && (private->visual->type != GDK_VISUAL_GRAYSCALE)) return; pixels = g_new (gulong, ncolors); for (i=0; i<ncolors; i++) { gulong pixel = colors[i].pixel; if (private->info[pixel].ref_count) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -