📄 gdkcolor.c
字号:
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, 0); g_free (pixels);}/******************** * Color allocation * ********************//* Try to allocate a single color using XAllocColor. If it succeeds, * cache the result in our colormap, and store in ret. */static gboolean gdk_colormap_alloc1 (GdkColormap *colormap, GdkColor *color, GdkColor *ret){ GdkColormapPrivate *private; XColor xcolor; private = (GdkColormapPrivate*) colormap; xcolor.red = color->red; xcolor.green = color->green; xcolor.blue = color->blue; xcolor.pixel = color->pixel; xcolor.flags = DoRed | DoGreen | DoBlue; if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) { ret->pixel = xcolor.pixel; ret->red = xcolor.red; ret->green = xcolor.green; ret->blue = xcolor.blue; if (ret->pixel < colormap->size) { if (private->info[ret->pixel].ref_count) /* got a duplicate */ { XFreeColors (private->xdisplay, private->xcolormap, &ret->pixel, 1, 0); } else { colormap->colors[ret->pixel] = *color; colormap->colors[ret->pixel].pixel = ret->pixel; private->info[ret->pixel].ref_count = 1; g_hash_table_insert (private->hash, &colormap->colors[ret->pixel], &colormap->colors[ret->pixel]); } } return TRUE; } else { return FALSE; }}static gintgdk_colormap_alloc_colors_writeable (GdkColormap *colormap, GdkColor *colors, gint ncolors, gboolean writeable, gboolean best_match, gboolean *success){ GdkColormapPrivate *private; gulong *pixels; Status status; gint i, index; private = (GdkColormapPrivate*) colormap; if (private->private_val) { index = 0; for (i=0; i<ncolors; i++) { while ((index < colormap->size) && (private->info[index].ref_count != 0)) index++; if (index < colormap->size) { colors[i].pixel = index; success[i] = TRUE; private->info[index].ref_count++; private->info[i].flags |= GDK_COLOR_WRITEABLE; } else break; } return i; } else { pixels = g_new (gulong, ncolors); /* Allocation of a writeable color cells */ status = XAllocColorCells (private->xdisplay, private->xcolormap, FALSE, NULL, 0, pixels, ncolors); if (status) { for (i=0; i<ncolors; i++) { colors[i].pixel = pixels[i]; private->info[pixels[i]].ref_count++; private->info[pixels[i]].flags |= GDK_COLOR_WRITEABLE; } } g_free (pixels); return status ? ncolors : 0; }}static gintgdk_colormap_alloc_colors_private (GdkColormap *colormap, GdkColor *colors, gint ncolors, gboolean writeable, gboolean best_match, gboolean *success){ GdkColormapPrivate *private; gint i, index; XColor *store = g_new (XColor, ncolors); gint nstore = 0; gint nremaining = 0; private = (GdkColormapPrivate*) colormap; index = -1; /* First, store the colors we have room for */ index = 0; for (i=0; i<ncolors; i++) { if (!success[i]) { while ((index < colormap->size) && (private->info[index].ref_count != 0)) index++; if (index < colormap->size) { store[nstore].red = colors[i].red; store[nstore].blue = colors[i].blue; store[nstore].green = colors[i].green; store[nstore].pixel = index; nstore++; success[i] = TRUE; colors[i].pixel = index; private->info[index].ref_count++; } else nremaining++; } } XStoreColors (private->xdisplay, private->xcolormap, store, nstore); g_free (store); if (nremaining > 0 && best_match) { /* Get best matches for remaining colors */ gchar *available = g_new (gchar, colormap->size); for (i = 0; i < colormap->size; i++) available[i] = TRUE; for (i=0; i<ncolors; i++) { if (!success[i]) { index = gdk_colormap_match_color (colormap, &colors[i], available); if (index != -1) { colors[i] = colormap->colors[index]; private->info[index].ref_count++; success[i] = TRUE; nremaining--; } } } g_free (available); } return (ncolors - nremaining);}static gintgdk_colormap_alloc_colors_shared (GdkColormap *colormap, GdkColor *colors, gint ncolors, gboolean writeable, gboolean best_match, gboolean *success){ GdkColormapPrivate *private; gint i, index; gint nremaining = 0; gint nfailed = 0; private = (GdkColormapPrivate*) colormap; index = -1; for (i=0; i<ncolors; i++) { if (!success[i]) { if (gdk_colormap_alloc1 (colormap, &colors[i], &colors[i])) success[i] = TRUE; else nremaining++; } } if (nremaining > 0 && best_match) { gchar *available = g_new (gchar, colormap->size); for (i = 0; i < colormap->size; i++) available[i] = ((private->info[i].ref_count == 0) || !(private->info[i].flags && GDK_COLOR_WRITEABLE)); gdk_colormap_sync (colormap, FALSE); while (nremaining > 0) { for (i=0; i<ncolors; i++) { if (!success[i]) { index = gdk_colormap_match_color (colormap, &colors[i], available); if (index != -1) { if (private->info[index].ref_count) { private->info[index].ref_count++; colors[i] = colormap->colors[index]; success[i] = TRUE; nremaining--; } else { if (gdk_colormap_alloc1 (colormap, &colormap->colors[index], &colors[i])) { success[i] = TRUE; nremaining--; break; } else { available[index] = FALSE; } } } else { nfailed++; nremaining--; success[i] = 2; /* flag as permanent failure */ } } } } g_free (available); } /* Change back the values we flagged as permanent failures */ if (nfailed > 0) { for (i=0; i<ncolors; i++) if (success[i] == 2) success[i] = FALSE; nremaining = nfailed; } return (ncolors - nremaining);}static gintgdk_colormap_alloc_colors_pseudocolor (GdkColormap *colormap, GdkColor *colors, gint ncolors, gboolean writeable, gboolean best_match, gboolean *success){ GdkColormapPrivate *private; GdkColor *lookup_color; gint i; gint nremaining = 0; private = (GdkColormapPrivate*) colormap; /* Check for an exact match among previously allocated colors */ for (i=0; i<ncolors; i++) { if (!success[i]) { lookup_color = g_hash_table_lookup (private->hash, &colors[i]); if (lookup_color) { private->info[lookup_color->pixel].ref_count++; colors[i].pixel = lookup_color->pixel; success[i] = TRUE; } else nremaining++; } } /* If that failed, we try to allocate a new color, or approxmiate * with what we can get if best_match is TRUE. */ if (nremaining > 0) { if (private->private_val) return gdk_colormap_alloc_colors_private (colormap, colors, ncolors, writeable, best_match, success); else return gdk_colormap_alloc_colors_shared (colormap, colors, ncolors, writeable, best_match, success); } else return 0;}gintgdk_colormap_alloc_colors (GdkColormap *colormap, GdkColor *colors, gint ncolors, gboolean writeable, gboolean best_match, gboolean *success){ GdkColormapPrivate *private; GdkVisual *visual; gint i; gint nremaining = 0; XColor xcolor; g_return_val_if_fail (colormap != NULL, FALSE); g_return_val_if_fail (colors != NULL, FALSE); private = (GdkColormapPrivate*) colormap; for (i=0; i<ncolors; i++) { success[i] = FALSE; } switch (private->visual->type) { case GDK_VISUAL_PSEUDO_COLOR: case GDK_VISUAL_GRAYSCALE: if (writeable) return gdk_colormap_alloc_colors_writeable (colormap, colors, ncolors, writeable, best_match, success); else return gdk_colormap_alloc_colors_pseudocolor (colormap, colors, ncolors, writeable, best_match, success); break; case GDK_VISUAL_DIRECT_COLOR: case GDK_VISUAL_TRUE_COLOR: visual = private->visual; for (i=0; i<ncolors; i++) { colors[i].pixel = (((colors[i].red >> (16 - visual->red_prec)) << visual->red_shift) + ((colors[i].green >> (16 - visual->green_prec)) << visual->green_shift) + ((colors[i].blue >> (16 - visual->blue_prec)) << visual->blue_shift)); success[i] = TRUE; } break; case GDK_VISUAL_STATIC_GRAY: case GDK_VISUAL_STATIC_COLOR: for (i=0; i<ncolors; i++) { xcolor.red = colors[i].red; xcolor.green = colors[i].green; xcolor.blue = colors[i].blue; xcolor.pixel = colors[i].pixel; xcolor.flags = DoRed | DoGreen | DoBlue; if (XAllocColor (private->xdisplay, private->xcolormap, &xcolor)) { colors[i].pixel = xcolor.pixel; success[i] = TRUE; } else nremaining++; } break; } return nremaining;}gbooleangdk_colormap_alloc_color (GdkColormap *colormap, GdkColor *color, gboolean writeable, gboolean best_match){ gboolean success; gdk_colormap_alloc_colors (colormap, color, 1, writeable, best_match, &success); return success;}gbooleangdk_color_alloc (GdkColormap *colormap, GdkColor *color){ gboolean success; gdk_colormap_alloc_colors (colormap, color, 1, FALSE, TRUE, &success); return success;}gbooleangdk_color_change (GdkColormap *colormap, GdkColor *color){ GdkColormapPrivate *private; XColor xcolor; g_return_val_if_fail (colormap != NULL, FALSE); g_return_val_if_fail (color != NULL, FALSE); xcolor.pixel = color->pixel; xcolor.red = color->red; xcolor.green = color->green; xcolor.blue = color->blue; xcolor.flags = DoRed | DoGreen | DoBlue; private = (GdkColormapPrivate*) colormap; XStoreColor (private->xdisplay, private->xcolormap, &xcolor); return TRUE;}guintgdk_color_hash (const GdkColor *colora, const GdkColor *colorb){ return ((colora->red) + (colora->green << 11) + (colora->blue << 22) + (colora->blue >> 6));}gintgdk_color_equal (const GdkColor *colora, const GdkColor *colorb){ g_return_val_if_fail (colora != NULL, FALSE); g_return_val_if_fail (colorb != NULL, FALSE); return ((colora->red == colorb->red) && (colora->green == colorb->green) && (colora->blue == colorb->blue));}/* XXX: Do not use this function until it is fixed. An X Colormap * is useless unless we also have the visual. */GdkColormap*gdkx_colormap_get (Colormap xcolormap){ GdkColormap *colormap; GdkColormapPrivate *private; colormap = gdk_colormap_lookup (xcolormap); if (colormap) return colormap; if (xcolormap == DefaultColormap (gdk_display, gdk_screen)) return gdk_colormap_get_system (); private = g_new (GdkColormapPrivate, 1); colormap = (GdkColormap*) private; private->xdisplay = gdk_display; private->xcolormap = xcolormap; private->visual = NULL; private->private_val = TRUE; /* To do the following safely, we would have to have some way of finding * out what the size or visual of the given colormap is. It seems * X doesn't allow this */#if 0 for (i = 0; i < 256; i++) { xpalette[i].pixel = i; xpalette[i].red = 0; xpalette[i].green = 0; xpalette[i].blue = 0; } XQueryColors (gdk_display, private->xcolormap, xpalette, 256); for (i = 0; i < 256; i++) { colormap->colors[i].pixel = xpalette[i].pixel; colormap->colors[i].red = xpalette[i].red; colormap->colors[i].green = xpalette[i].green; colormap->colors[i].blue = xpalette[i].blue; }#endif colormap->colors = NULL; colormap->size = 0; gdk_colormap_add (colormap); return colormap;}static gintgdk_colormap_match_color (GdkColormap *cmap, GdkColor *color, const gchar *available){ GdkColor *colors; guint sum, max; gint rdiff, gdiff, bdiff; gint i, index; g_return_val_if_fail (cmap != NULL, 0); g_return_val_if_fail (color != NULL, 0); colors = cmap->colors; max = 3 * (65536); index = -1; for (i = 0; i < cmap->size; i++) { if ((!available) || (available && available[i])) { rdiff = (color->red - colors[i].red); gdiff = (color->green - colors[i].green); bdiff = (color->blue - colors[i].blue); sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff); if (sum < max) { index = i; max = sum; } } } return index;}GdkColormap*gdk_colormap_lookup (Colormap xcolormap){ GdkColormap *cmap; if (!colormap_hash) return NULL; cmap = g_hash_table_lookup (colormap_hash, &xcolormap); return cmap;}static voidgdk_colormap_add (GdkColormap *cmap){ GdkColormapPrivate *private; if (!colormap_hash) colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash, (GCompareFunc) gdk_colormap_cmp); private = (GdkColormapPrivate*) cmap; g_hash_table_insert (colormap_hash, &private->xcolormap, cmap);}static voidgdk_colormap_remove (GdkColormap *cmap){ GdkColormapPrivate *private; if (!colormap_hash) colormap_hash = g_hash_table_new ((GHashFunc) gdk_colormap_hash, (GCompareFunc) gdk_colormap_cmp); private = (GdkColormapPrivate*) cmap; g_hash_table_remove (colormap_hash, &private->xcolormap);}static guintgdk_colormap_hash (Colormap *cmap){ return *cmap;}static gintgdk_colormap_cmp (Colormap *a, Colormap *b){ return (*a == *b);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -