📄 gdkcc.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. *//* Color Context module * Copyright 1994,1995 John L. Cwikla * Copyright (C) 1997 by Ripley Software Development * Copyright (C) 1997 by Federico Mena (port to Gtk/Gdk) *//* Copyright 1994,1995 John L. Cwikla * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of John L. Cwikla or * Wolfram Research, Inc not be used in advertising or publicity * pertaining to distribution of the software without specific, written * prior permission. John L. Cwikla and Wolfram Research, Inc make no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * * John L. Cwikla and Wolfram Research, Inc disclaim all warranties with * regard to this software, including all implied warranties of * merchantability and fitness, in no event shall John L. Cwikla or * Wolfram Research, Inc be liable for any special, indirect or * consequential damages or any damages whatsoever resulting from loss of * use, data or profits, whether in an action of contract, negligence or * other tortious action, arising out of or in connection with the use or * performance of this software. * * Author: * John L. Cwikla * X Programmer * Wolfram Research Inc. * * cwikla@wri.com *//* * 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 <X11/Xlib.h>#include <stdlib.h>#include <string.h>#include "gdk.h"#include "gdkprivate.h"#include "gdkx.h"#define MAX_IMAGE_COLORS 256static guinthash_color (gconstpointer key){ const GdkColor *color = key; return (color->red * 33023 + color->green * 30013 + color->blue * 27011);}static gintcompare_colors (gconstpointer a, gconstpointer b){ const GdkColor *aa = a; const GdkColor *bb = b; return ((aa->red == bb->red) && (aa->green == bb->green) && (aa->blue == bb->blue));}static voidfree_hash_entry (gpointer key, gpointer value, gpointer user_data){ g_free (key); /* key and value are the same GdkColor */}static intpixel_sort (const void *a, const void *b){ return ((GdkColor *) a)->pixel - ((GdkColor *) b)->pixel;}/* XXX: This function does an XQueryColors() the hard way, because there is * no corresponding function in Gdk. */static voidmy_x_query_colors (GdkColormap *colormap, GdkColor *colors, gint ncolors){ XColor *xcolors; gint i; xcolors = g_new (XColor, ncolors); for (i = 0; i < ncolors; i++) xcolors[i].pixel = colors[i].pixel; XQueryColors (gdk_display, GDK_COLORMAP_XCOLORMAP (colormap), xcolors, ncolors); for (i = 0; i < ncolors; i++) { colors[i].red = xcolors[i].red; colors[i].green = xcolors[i].green; colors[i].blue = xcolors[i].blue; } g_free (xcolors);}static voidquery_colors (GdkColorContext *cc){ gint i; GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc; cc->cmap = g_new (GdkColor, cc->num_colors); for (i = 0; i < cc->num_colors; i++) cc->cmap[i].pixel = cc->clut ? cc->clut[i] : ccp->std_cmap.base_pixel + i; my_x_query_colors (cc->colormap, cc->cmap, cc->num_colors); qsort (cc->cmap, cc->num_colors, sizeof (GdkColor), pixel_sort);}static voidinit_bw (GdkColorContext *cc){ GdkColor color; g_warning ("init_bw: failed to allocate colors, falling back to black and white"); cc->mode = GDK_CC_MODE_BW; color.red = color.green = color.blue = 0; if (!gdk_color_alloc (cc->colormap, &color)) cc->black_pixel = 0; else cc->black_pixel = color.pixel; color.red = color.green = color.blue = 0xffff; if (!gdk_color_alloc (cc->colormap, &color)) cc->white_pixel = cc->black_pixel ? 0 : 1; else cc->white_pixel = color.pixel; cc->num_colors = 2;}static voidinit_gray (GdkColorContext *cc){ GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc; GdkColor *clrs, *cstart; gint i; gdouble dinc; cc->num_colors = GDK_VISUAL_XVISUAL (cc->visual)->map_entries; cc->clut = g_new (gulong, cc->num_colors); cstart = g_new (GdkColor, cc->num_colors); retrygray: dinc = 65535.0 / (cc->num_colors - 1); clrs = cstart; for (i = 0; i < cc->num_colors; i++) { clrs->red = clrs->green = clrs->blue = dinc * i; if (!gdk_color_alloc (cc->colormap, clrs)) { gdk_colors_free (cc->colormap, cc->clut, i, 0); cc->num_colors /= 2; if (cc->num_colors > 1) goto retrygray; else { g_free (cc->clut); cc->clut = NULL; init_bw (cc); g_free (cstart); return; } } cc->clut[i] = clrs++->pixel; } g_free (cstart); /* XXX: is this the right thing to do? */ ccp->std_cmap.colormap = GDK_COLORMAP_XCOLORMAP (cc->colormap); ccp->std_cmap.base_pixel = 0; ccp->std_cmap.red_max = cc->num_colors - 1; ccp->std_cmap.green_max = 0; ccp->std_cmap.blue_max = 0; ccp->std_cmap.red_mult = 1; ccp->std_cmap.green_mult = 0; ccp->std_cmap.blue_mult = 0; cc->white_pixel = WhitePixel (ccp->xdisplay, gdk_screen); cc->black_pixel = BlackPixel (ccp->xdisplay, gdk_screen); query_colors (cc); cc->mode = GDK_CC_MODE_MY_GRAY;}static voidinit_color (GdkColorContext *cc){ GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc; gint cubeval; cubeval = 1; while ((cubeval * cubeval * cubeval) < GDK_VISUAL_XVISUAL (cc->visual)->map_entries) cubeval++; cubeval--; cc->num_colors = cubeval * cubeval * cubeval; ccp->std_cmap.red_max = cubeval - 1; ccp->std_cmap.green_max = cubeval - 1; ccp->std_cmap.blue_max = cubeval - 1; ccp->std_cmap.red_mult = cubeval * cubeval; ccp->std_cmap.green_mult = cubeval; ccp->std_cmap.blue_mult = 1; ccp->std_cmap.base_pixel = 0; cc->white_pixel = WhitePixel (ccp->xdisplay, gdk_screen); cc->black_pixel = BlackPixel (ccp->xdisplay, gdk_screen); cc->num_colors = DisplayCells (ccp->xdisplay, gdk_screen); /* a CLUT for storing allocated pixel indices */ cc->max_colors = cc->num_colors; cc->clut = g_new (gulong, cc->max_colors); for (cubeval = 0; cubeval < cc->max_colors; cubeval++) cc->clut[cubeval] = cubeval; query_colors (cc); cc->mode = GDK_CC_MODE_STD_CMAP;}static voidinit_true_color (GdkColorContext *cc){ GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc; gulong rmask, gmask, bmask; cc->mode = GDK_CC_MODE_TRUE; /* Red */ rmask = cc->masks.red = cc->visual->red_mask; cc->shifts.red = 0; cc->bits.red = 0; while (!(rmask & 1)) { rmask >>= 1; cc->shifts.red++; } while (rmask & 1) { rmask >>= 1; cc->bits.red++; } /* Green */ gmask = cc->masks.green = cc->visual->green_mask; cc->shifts.green = 0; cc->bits.green = 0; while (!(gmask & 1)) { gmask >>= 1; cc->shifts.green++; } while (gmask & 1) { gmask >>= 1; cc->bits.green++; } /* Blue */ bmask = cc->masks.blue = cc->visual->blue_mask; cc->shifts.blue = 0; cc->bits.blue = 0; while (!(bmask & 1)) { bmask >>= 1; cc->shifts.blue++; } while (bmask & 1) { bmask >>= 1; cc->bits.blue++; } cc->num_colors = (cc->visual->red_mask | cc->visual->green_mask | cc->visual->blue_mask) + 1; cc->white_pixel = WhitePixel (ccp->xdisplay, gdk_screen); cc->black_pixel = BlackPixel (ccp->xdisplay, gdk_screen);}static voidinit_direct_color (GdkColorContext *cc){ gint n, count; GdkColor *clrs, *cstart; gulong rval, gval, bval; gulong *rtable; gulong *gtable; gulong *btable; gdouble dinc; init_true_color (cc); /* for shift stuff */ rval = cc->visual->red_mask >> cc->shifts.red; gval = cc->visual->green_mask >> cc->shifts.green; bval = cc->visual->blue_mask >> cc->shifts.blue; rtable = g_new (gulong, rval + 1); gtable = g_new (gulong, gval + 1); btable = g_new (gulong, bval + 1); cc->max_entry = MAX (rval, gval); cc->max_entry = MAX (cc->max_entry, bval); cstart = g_new (GdkColor, cc->max_entry + 1); cc->clut = g_new (gulong, cc->max_entry + 1); retrydirect: for (n = 0; n < rval; n++) rtable[n] = rval ? (65535.0 / rval * n) : 0; for (n = 0; n < gval; n++) gtable[n] = gval ? (65535.0 / gval * n) : 0; for (n = 0; n < bval; n++) btable[n] = bval ? (65535.0 / bval * n) : 0; cc->max_entry = MAX (rval, gval); cc->max_entry = MAX (cc->max_entry, bval); count = 0; clrs = cstart; cc->num_colors = (rval + 1) * (gval + 1) * (bval + 1); for (n = 0; n < cc->max_entry; n++) { dinc = (double) n / cc->max_entry; clrs->red = rtable[(int) (dinc * rval)]; clrs->green = gtable[(int) (dinc * gval)]; clrs->blue = btable[(int) (dinc * bval)]; if (gdk_color_alloc (cc->colormap, clrs)) { cc->clut[count++] = clrs->pixel; clrs++; } else { gdk_colors_free (cc->colormap, cc->clut, count, 0); rval >>= 1; gval >>= 1; bval >>= 1; cc->masks.red = (cc->masks.red >> 1) & cc->visual->red_mask; cc->masks.green = (cc->masks.green >> 1) & cc->visual->green_mask; cc->masks.blue = (cc->masks.blue >> 1) & cc->visual->blue_mask; cc->shifts.red++; cc->shifts.green++; cc->shifts.blue++; cc->bits.red--; cc->bits.green--; cc->bits.blue--; cc->num_colors = (rval + 1) * (gval + 1) * (bval + 1); if (cc->num_colors >1) goto retrydirect; else { g_free (cc->clut); cc->clut = NULL; init_bw (cc); break; } } } /* Update allocated color count; original num_colors is max_entry, which * is not necessarily the same as the really allocated number of colors. */ cc->num_colors = count; g_free (rtable); g_free (gtable); g_free (btable); g_free (cstart);}static voidinit_palette (GdkColorContext *cc){ /* restore correct mode for this cc */ switch (cc->visual->type) { case GDK_VISUAL_STATIC_GRAY: case GDK_VISUAL_GRAYSCALE: if (GDK_VISUAL_XVISUAL (cc->visual)->map_entries == 2) cc->mode = GDK_CC_MODE_BW; else cc->mode = GDK_CC_MODE_MY_GRAY; break; case GDK_VISUAL_TRUE_COLOR: case GDK_VISUAL_DIRECT_COLOR: cc->mode = GDK_CC_MODE_TRUE; break; case GDK_VISUAL_STATIC_COLOR: case GDK_VISUAL_PSEUDO_COLOR: cc->mode = GDK_CC_MODE_STD_CMAP; break; default: cc->mode = GDK_CC_MODE_UNDEFINED; break; } /* previous palette */ if (cc->num_palette) g_free (cc->palette); if (cc->fast_dither) g_free (cc->fast_dither); /* clear hash table if present */ if (cc->color_hash) { g_hash_table_foreach (cc->color_hash, free_hash_entry, NULL); g_hash_table_destroy (cc->color_hash); cc->color_hash = NULL; } cc->palette = NULL; cc->num_palette = 0; cc->fast_dither = NULL;}GdkColorContext *gdk_color_context_new (GdkVisual *visual, GdkColormap *colormap){ GdkColorContextPrivate *ccp; gint use_private_colormap = FALSE; /* XXX: maybe restore full functionality later? */ GdkColorContext *cc; gint retry_count; GdkColormap *default_colormap; g_assert (visual != NULL); g_assert (colormap != NULL); ccp = g_new (GdkColorContextPrivate, 1); cc = (GdkColorContext *) ccp; ccp->xdisplay = gdk_display; cc->visual = visual; cc->colormap = colormap; cc->clut = NULL; cc->cmap = NULL; cc->mode = GDK_CC_MODE_UNDEFINED; cc->need_to_free_colormap = FALSE; cc->color_hash = NULL; cc->palette = NULL; cc->num_palette = 0; cc->fast_dither = NULL; default_colormap = gdk_colormap_get_system (); retry_count = 0; while (retry_count < 2) { /* Only create a private colormap if the visual found isn't equal * to the default visual and we don't have a private colormap, * -or- if we are instructed to create a private colormap (which * never is the case for XmHTML). */ if (use_private_colormap || ((cc->visual != gdk_visual_get_system ()) /* default visual? */ && (GDK_COLORMAP_XCOLORMAP (colormap) == GDK_COLORMAP_XCOLORMAP (default_colormap)))) { g_warning ("gdk_color_context_new: non-default visual detected, " "using private colormap"); cc->colormap = gdk_colormap_new (cc->visual, FALSE); cc->need_to_free_colormap = (GDK_COLORMAP_XCOLORMAP (colormap) != GDK_COLORMAP_XCOLORMAP (default_colormap)); } switch (visual->type) { case GDK_VISUAL_STATIC_GRAY: case GDK_VISUAL_GRAYSCALE: GDK_NOTE (COLOR_CONTEXT, g_message ("gdk_color_context_new: visual class is %s\n", (visual->type == GDK_VISUAL_STATIC_GRAY) ? "GDK_VISUAL_STATIC_GRAY" : "GDK_VISUAL_GRAYSCALE")); if (GDK_VISUAL_XVISUAL (cc->visual)->map_entries == 2) init_bw (cc); else init_gray (cc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -