gdkcc-win32.c

Go to the documentation of this file.
00001 /* GDK - The GIMP Drawing Kit
00002  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 /* Color Context module
00021  * Copyright 1994,1995 John L. Cwikla
00022  * Copyright (C) 1997 by Ripley Software Development
00023  * Copyright (C) 1997 by Federico Mena (port to Gtk/Gdk)
00024  */
00025 
00026 /* Copyright 1994,1995 John L. Cwikla
00027  *
00028  * Permission to use, copy, modify, distribute, and sell this software
00029  * and its documentation for any purpose is hereby granted without fee,
00030  * provided that the above copyright notice appears in all copies and that
00031  * both that copyright notice and this permission notice appear in
00032  * supporting documentation, and that the name of John L. Cwikla or
00033  * Wolfram Research, Inc not be used in advertising or publicity
00034  * pertaining to distribution of the software without specific, written
00035  * prior permission.  John L. Cwikla and Wolfram Research, Inc make no
00036  * representations about the suitability of this software for any
00037  * purpose.  It is provided "as is" without express or implied warranty.
00038  *
00039  * John L. Cwikla and Wolfram Research, Inc disclaim all warranties with
00040  * regard to this software, including all implied warranties of
00041  * merchantability and fitness, in no event shall John L. Cwikla or
00042  * Wolfram Research, Inc be liable for any special, indirect or
00043  * consequential damages or any damages whatsoever resulting from loss of
00044  * use, data or profits, whether in an action of contract, negligence or
00045  * other tortious action, arising out of or in connection with the use or
00046  * performance of this software.
00047  *
00048  * Author:
00049  *  John L. Cwikla
00050  *  X Programmer
00051  *  Wolfram Research Inc.
00052  *
00053  *  cwikla@wri.com
00054  */
00055 
00056 /*
00057  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
00058  * file for a list of people on the GTK+ Team.  See the ChangeLog
00059  * files for a list of changes.  These files are distributed with
00060  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
00061  */
00062 
00063 #include "config.h"
00064 
00065 #include <stdlib.h>
00066 #include <string.h>
00067 
00068 #include "gdkcc.h"
00069 #include "gdkcolor.h"
00070 #include "gdkwin32.h"
00071 
00072 #define MAX_IMAGE_COLORS 256
00073 
00074 typedef struct _GdkColorContextPrivate GdkColorContextPrivate;
00075 
00076 struct _GdkColorContextPrivate {
00077    GdkColorContext color_context;
00078    XStandardColormap std_cmap;
00079 };
00080 
00081 static guint hash_color(gconstpointer key)
00082 {
00083    const GdkColor *color = key;
00084 
00085    return (color->red * 33023 + color->green * 30013 +
00086            color->blue * 27011);
00087 }
00088 
00089 static gint compare_colors(gconstpointer a, gconstpointer b)
00090 {
00091    const GdkColor *aa = a;
00092    const GdkColor *bb = b;
00093 
00094    return ((aa->red == bb->red) && (aa->green == bb->green)
00095            && (aa->blue == bb->blue));
00096 }
00097 
00098 static void
00099 free_hash_entry(gpointer key, gpointer value, gpointer user_data)
00100 {
00101    g_free(key);                 /* key and value are the same GdkColor */
00102 }
00103 
00104 static int pixel_sort(const void *a, const void *b)
00105 {
00106    return ((GdkColor *) a)->pixel - ((GdkColor *) b)->pixel;
00107 }
00108 
00109 static void
00110 my_x_query_colors(GdkColormap * colormap, GdkColor * colors, gint ncolors)
00111 {
00112    gint i;
00113 
00114    for (i = 0; i < ncolors; i++) {
00115       PALETTEENTRY palentry;
00116 
00117       GetPaletteEntries(GDK_COLORMAP_WIN32COLORMAP(colormap)->palette,
00118                         colors[i].pixel, 1, &palentry);
00119       colors[i].red = (palentry.peRed * 65535) / 255;
00120       colors[i].green = (palentry.peGreen * 65535) / 255;
00121       colors[i].blue = (palentry.peBlue * 65535) / 255;
00122    }
00123 }
00124 
00125 static void query_colors(GdkColorContext * cc)
00126 {
00127    gint i;
00128    GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc;
00129    cc->cmap = g_new(GdkColor, cc->num_colors);
00130 
00131    for (i = 0; i < cc->num_colors; i++)
00132       cc->cmap[i].pixel =
00133           cc->clut ? cc->clut[i] : ccp->std_cmap.base_pixel + i;
00134 
00135    my_x_query_colors(cc->colormap, cc->cmap, cc->num_colors);
00136 
00137    qsort(cc->cmap, cc->num_colors, sizeof(GdkColor), pixel_sort);
00138 }
00139 
00140 static void init_bw(GdkColorContext * cc)
00141 {
00142    GdkColor color;
00143 
00144    g_warning
00145        ("init_bw: failed to allocate colors, falling back to black and white");
00146 
00147    cc->mode = GDK_CC_MODE_BW;
00148 
00149    color.red = color.green = color.blue = 0;
00150 
00151    if (!gdk_color_alloc(cc->colormap, &color))
00152       cc->black_pixel = 0;
00153    else
00154       cc->black_pixel = color.pixel;
00155 
00156    color.red = color.green = color.blue = 0xffff;
00157 
00158    if (!gdk_color_alloc(cc->colormap, &color))
00159       cc->white_pixel = cc->black_pixel ? 0 : 1;
00160    else
00161       cc->white_pixel = color.pixel;
00162 
00163    cc->num_colors = 2;
00164 }
00165 
00166 static void init_gray(GdkColorContext * cc)
00167 {
00168    GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc;
00169    GdkColor *clrs, *cstart;
00170    gint i;
00171    gdouble dinc;
00172 
00173    cc->num_colors = 256;        /* Bogus, but will never get here anyway? */
00174 
00175    cc->clut = g_new(gulong, cc->num_colors);
00176    cstart = g_new(GdkColor, cc->num_colors);
00177 
00178  retrygray:
00179 
00180    dinc = 65535.0 / (cc->num_colors - 1);
00181 
00182    clrs = cstart;
00183 
00184    for (i = 0; i < cc->num_colors; i++) {
00185       clrs->red = clrs->green = clrs->blue = dinc * i;
00186 
00187       if (!gdk_color_alloc(cc->colormap, clrs)) {
00188          gdk_colors_free(cc->colormap, cc->clut, i, 0);
00189 
00190          cc->num_colors /= 2;
00191 
00192          if (cc->num_colors > 1)
00193             goto retrygray;
00194          else {
00195             g_free(cc->clut);
00196             cc->clut = NULL;
00197             init_bw(cc);
00198             g_free(cstart);
00199             return;
00200          }
00201       }
00202 
00203       cc->clut[i] = clrs++->pixel;
00204    }
00205 
00206    g_free(cstart);
00207 
00208    /* XXX: is this the right thing to do? */
00209    ccp->std_cmap.colormap = GDK_COLORMAP_WIN32COLORMAP(cc->colormap);
00210    ccp->std_cmap.base_pixel = 0;
00211    ccp->std_cmap.red_max = cc->num_colors - 1;
00212    ccp->std_cmap.green_max = 0;
00213    ccp->std_cmap.blue_max = 0;
00214    ccp->std_cmap.red_mult = 1;
00215    ccp->std_cmap.green_mult = 0;
00216    ccp->std_cmap.blue_mult = 0;
00217 
00218    cc->white_pixel = 255;
00219    cc->black_pixel = 0;
00220 
00221    query_colors(cc);
00222 
00223    cc->mode = GDK_CC_MODE_MY_GRAY;
00224 }
00225 
00226 static void init_color(GdkColorContext * cc)
00227 {
00228    GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc;
00229    gint cubeval;
00230 
00231    cubeval = 1;
00232    while ((cubeval * cubeval * cubeval) <
00233           GDK_VISUAL_XVISUAL(cc->visual)->map_entries)
00234       cubeval++;
00235    cubeval--;
00236 
00237    cc->num_colors = cubeval * cubeval * cubeval;
00238 
00239    ccp->std_cmap.red_max = cubeval - 1;
00240    ccp->std_cmap.green_max = cubeval - 1;
00241    ccp->std_cmap.blue_max = cubeval - 1;
00242    ccp->std_cmap.red_mult = cubeval * cubeval;
00243    ccp->std_cmap.green_mult = cubeval;
00244    ccp->std_cmap.blue_mult = 1;
00245    ccp->std_cmap.base_pixel = 0;
00246 
00247    cc->white_pixel = 255;       /* ??? */
00248    cc->black_pixel = 0;         /* ??? */
00249 
00250    /* a CLUT for storing allocated pixel indices */
00251 
00252    cc->max_colors = cc->num_colors;
00253    cc->clut = g_new(gulong, cc->max_colors);
00254 
00255    for (cubeval = 0; cubeval < cc->max_colors; cubeval++)
00256       cc->clut[cubeval] = cubeval;
00257 
00258    query_colors(cc);
00259 
00260    cc->mode = GDK_CC_MODE_STD_CMAP;
00261 }
00262 
00263 
00264 static void init_true_color(GdkColorContext * cc)
00265 {
00266    GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc;
00267    gulong rmask, gmask, bmask;
00268 
00269    cc->mode = GDK_CC_MODE_TRUE;
00270 
00271    /* Red */
00272 
00273    rmask = cc->masks.red = cc->visual->red_mask;
00274 
00275    cc->shifts.red = 0;
00276    cc->bits.red = 0;
00277 
00278    while (!(rmask & 1)) {
00279       rmask >>= 1;
00280       cc->shifts.red++;
00281    }
00282 
00283    while (rmask & 1) {
00284       rmask >>= 1;
00285       cc->bits.red++;
00286    }
00287 
00288    /* Green */
00289 
00290    gmask = cc->masks.green = cc->visual->green_mask;
00291 
00292    cc->shifts.green = 0;
00293    cc->bits.green = 0;
00294 
00295    while (!(gmask & 1)) {
00296       gmask >>= 1;
00297       cc->shifts.green++;
00298    }
00299 
00300    while (gmask & 1) {
00301       gmask >>= 1;
00302       cc->bits.green++;
00303    }
00304 
00305    /* Blue */
00306 
00307    bmask = cc->masks.blue = cc->visual->blue_mask;
00308 
00309    cc->shifts.blue = 0;
00310    cc->bits.blue = 0;
00311 
00312    while (!(bmask & 1)) {
00313       bmask >>= 1;
00314       cc->shifts.blue++;
00315    }
00316 
00317    while (bmask & 1) {
00318       bmask >>= 1;
00319       cc->bits.blue++;
00320    }
00321 
00322    cc->num_colors =
00323        (cc->visual->red_mask | cc->visual->green_mask | cc->visual->
00324         blue_mask) + 1;
00325 
00326    cc->white_pixel = 0xffffff;
00327    cc->black_pixel = 0;
00328 }
00329 
00330 static void init_palette(GdkColorContext * cc)
00331 {
00332    /* restore correct mode for this cc */
00333 
00334    switch (cc->visual->type) {
00335    case GDK_VISUAL_STATIC_GRAY:
00336    case GDK_VISUAL_GRAYSCALE:
00337       if (GDK_VISUAL_XVISUAL(cc->visual)->map_entries == 2)
00338          cc->mode = GDK_CC_MODE_BW;
00339       else
00340          cc->mode = GDK_CC_MODE_MY_GRAY;
00341       break;
00342 
00343    case GDK_VISUAL_TRUE_COLOR:
00344       cc->mode = GDK_CC_MODE_TRUE;
00345       break;
00346 
00347    case GDK_VISUAL_STATIC_COLOR:
00348    case GDK_VISUAL_PSEUDO_COLOR:
00349       cc->mode = GDK_CC_MODE_STD_CMAP;
00350       break;
00351 
00352    default:
00353       cc->mode = GDK_CC_MODE_UNDEFINED;
00354       break;
00355    }
00356 
00357    /* previous palette */
00358 
00359    if (cc->num_palette)
00360       g_free(cc->palette);
00361 
00362    if (cc->fast_dither)
00363       g_free(cc->fast_dither);
00364 
00365    /* clear hash table if present */
00366 
00367    if (cc->color_hash) {
00368       g_hash_table_foreach(cc->color_hash, free_hash_entry, NULL);
00369       g_hash_table_destroy(cc->color_hash);
00370       cc->color_hash = g_hash_table_new(hash_color, compare_colors);
00371    }
00372 
00373    cc->palette = NULL;
00374    cc->num_palette = 0;
00375    cc->fast_dither = NULL;
00376 }
00377 
00378 GdkColorContext *gdk_color_context_new(GdkVisual * visual,
00379                                        GdkColormap * colormap)
00380 {
00381    GdkColorContextPrivate *ccp;
00382    gint use_private_colormap = FALSE;   /* XXX: maybe restore full functionality later? */
00383    GdkColorContext *cc;
00384    gint retry_count;
00385    GdkColormap *default_colormap;
00386 
00387    g_assert(visual != NULL);
00388    g_assert(colormap != NULL);
00389 
00390    ccp = g_new(GdkColorContextPrivate, 1);
00391    cc = (GdkColorContext *) ccp;
00392    cc->visual = visual;
00393    cc->colormap = colormap;
00394    cc->clut = NULL;
00395    cc->cmap = NULL;
00396    cc->mode = GDK_CC_MODE_UNDEFINED;
00397    cc->need_to_free_colormap = FALSE;
00398 
00399    cc->color_hash = NULL;
00400    cc->palette = NULL;
00401    cc->num_palette = 0;
00402    cc->fast_dither = NULL;
00403 
00404    default_colormap = gdk_colormap_get_system();
00405 
00406    retry_count = 0;
00407 
00408    while (retry_count < 2) {
00409       /* Only create a private colormap if the visual found isn't equal
00410        * to the default visual and we don't have a private colormap,
00411        * -or- if we are instructed to create a private colormap (which
00412        * never is the case for XmHTML).
00413        */
00414 
00415       if (use_private_colormap || ((cc->visual != gdk_visual_get_system())      /* default visual? */
00416                                    &&(GDK_COLORMAP_WIN32COLORMAP(colormap)
00417                                       ==
00418                                       GDK_COLORMAP_WIN32COLORMAP
00419                                       (default_colormap)))) {
00420          g_warning("gdk_color_context_new: non-default visual detected, "
00421                    "using private colormap");
00422 
00423          cc->colormap = gdk_colormap_new(cc->visual, FALSE);
00424 
00425          cc->need_to_free_colormap = (GDK_COLORMAP_WIN32COLORMAP(colormap)
00426                                       !=
00427                                       GDK_COLORMAP_WIN32COLORMAP
00428                                       (default_colormap));
00429       }
00430 
00431       switch (visual->type) {
00432       case GDK_VISUAL_STATIC_GRAY:
00433       case GDK_VISUAL_GRAYSCALE:
00434          GDK_NOTE(COLOR_CONTEXT,
00435                   g_message("gdk_color_context_new: visual class is %s\n",
00436                             (visual->type == GDK_VISUAL_STATIC_GRAY) ?
00437                             "GDK_VISUAL_STATIC_GRAY" :
00438                             "GDK_VISUAL_GRAYSCALE"));
00439 
00440          if (GDK_VISUAL_XVISUAL(cc->visual)->map_entries == 2)
00441             init_bw(cc);
00442          else
00443             init_gray(cc);
00444 
00445          break;
00446 
00447       case GDK_VISUAL_TRUE_COLOR:       /* shifts */
00448          GDK_NOTE(COLOR_CONTEXT,
00449                   g_message
00450                   ("gdk_color_context_new: visual class is GDK_VISUAL_TRUE_COLOR\n"));
00451 
00452          init_true_color(cc);
00453          break;
00454 
00455       case GDK_VISUAL_STATIC_COLOR:
00456       case GDK_VISUAL_PSEUDO_COLOR:
00457          GDK_NOTE(COLOR_CONTEXT,
00458                   g_message("gdk_color_context_new: visual class is %s\n",
00459                             (visual->type == GDK_VISUAL_STATIC_COLOR) ?
00460                             "GDK_VISUAL_STATIC_COLOR" :
00461                             "GDK_VISUAL_PSEUDO_COLOR"));
00462 
00463          init_color(cc);
00464          break;
00465 
00466       default:
00467          g_assert_not_reached();
00468       }
00469 
00470       if ((cc->mode == GDK_CC_MODE_BW) && (cc->visual->depth > 1)) {
00471          use_private_colormap = TRUE;
00472          retry_count++;
00473       } else
00474          break;
00475    }
00476 
00477    /* no. of colors allocated yet */
00478 
00479    cc->num_allocated = 0;
00480 
00481    GDK_NOTE(COLOR_CONTEXT,
00482             g_message
00483             ("gdk_color_context_new: screen depth is %i, no. of colors is %i\n",
00484              cc->visual->depth, cc->num_colors));
00485 
00486    return (GdkColorContext *) cc;
00487 }
00488 
00489 GdkColorContext *gdk_color_context_new_mono(GdkVisual * visual,
00490                                             GdkColormap * colormap)
00491 {
00492    GdkColorContextPrivate *ccp;
00493    GdkColorContext *cc;
00494 
00495    g_assert(visual != NULL);
00496    g_assert(colormap != NULL);
00497 
00498    cc = g_new(GdkColorContext, 1);
00499    ccp = (GdkColorContextPrivate *) cc;
00500    cc->visual = visual;
00501    cc->colormap = colormap;
00502    cc->clut = NULL;
00503    cc->cmap = NULL;
00504    cc->mode = GDK_CC_MODE_UNDEFINED;
00505    cc->need_to_free_colormap = FALSE;
00506 
00507    init_bw(cc);
00508 
00509    return (GdkColorContext *) cc;
00510 }
00511 
00512 /* This doesn't currently free black/white, hmm... */
00513 
00514 void gdk_color_context_free(GdkColorContext * cc)
00515 {
00516    g_assert(cc != NULL);
00517 
00518    if ((cc->visual->type == GDK_VISUAL_STATIC_COLOR)
00519        || (cc->visual->type == GDK_VISUAL_PSEUDO_COLOR)) {
00520       gdk_colors_free(cc->colormap, cc->clut, cc->num_allocated, 0);
00521       g_free(cc->clut);
00522    } else if (cc->clut != NULL) {
00523       gdk_colors_free(cc->colormap, cc->clut, cc->num_colors, 0);
00524       g_free(cc->clut);
00525    }
00526 
00527    if (cc->cmap != NULL)
00528       g_free(cc->cmap);
00529 
00530    if (cc->need_to_free_colormap)
00531       gdk_colormap_unref(cc->colormap);
00532 
00533    /* free any palette that has been associated with this GdkColorContext */
00534 
00535    init_palette(cc);
00536 
00537    g_free(cc);
00538 }
00539 
00540 gulong
00541 gdk_color_context_get_pixel(GdkColorContext * cc,
00542                             gushort red,
00543                             gushort green, gushort blue, gint * failed)
00544 {
00545    GdkColorContextPrivate *ccp = (GdkColorContextPrivate *) cc;
00546    g_assert(cc != NULL);
00547    g_assert(failed != NULL);
00548 
00549    *failed = FALSE;
00550 
00551    switch (cc->mode) {
00552    case GDK_CC_MODE_BW:
00553       {
00554          gdouble value;
00555 
00556          value = (red / 65535.0 * 0.30
00557                   + green / 65535.0 * 0.59 + blue / 65535.0 * 0.11);
00558 
00559          if (value > 0.5)
00560             return cc->white_pixel;
00561 
00562          return cc->black_pixel;
00563       }
00564 
00565    case GDK_CC_MODE_MY_GRAY:
00566       {
00567          gulong ired, igreen, iblue;
00568 
00569          red = red * 0.30 + green * 0.59 + blue * 0.11;
00570          green = 0;
00571          blue = 0;
00572 
00573          if ((ired =
00574               red * (ccp->std_cmap.red_max + 1) / 0xffff) >
00575              ccp->std_cmap.red_max)
00576             ired = ccp->std_cmap.red_max;
00577 
00578          ired *= ccp->std_cmap.red_mult;
00579 
00580          if ((igreen =
00581               green * (ccp->std_cmap.green_max + 1) / 0xffff) >
00582              ccp->std_cmap.green_max)
00583             igreen = ccp->std_cmap.green_max;
00584 
00585          igreen *= ccp->std_cmap.green_mult;
00586 
00587          if ((iblue =
00588               blue * (ccp->std_cmap.blue_max + 1) / 0xffff) >
00589              ccp->std_cmap.blue_max)
00590             iblue = ccp->std_cmap.blue_max;
00591 
00592          iblue *= ccp->std_cmap.blue_mult;
00593 
00594          if (cc->clut != NULL)
00595             return cc->clut[ccp->std_cmap.base_pixel + ired + igreen +
00596                             iblue];
00597 
00598          return ccp->std_cmap.base_pixel + ired + igreen + iblue;
00599       }
00600 
00601    case GDK_CC_MODE_TRUE:
00602       {
00603          gulong ired, igreen, iblue;
00604 
00605          if (cc->clut == NULL) {
00606             red >>= 16 - cc->bits.red;
00607             green >>= 16 - cc->bits.green;
00608             blue >>= 16 - cc->bits.blue;
00609 
00610             ired = (red << cc->shifts.red) & cc->masks.red;
00611             igreen = (green << cc->shifts.green) & cc->masks.green;
00612             iblue = (blue << cc->shifts.blue) & cc->masks.blue;
00613 
00614             return ired | igreen | iblue;
00615          }
00616 
00617          ired = cc->clut[red * cc->max_entry / 65535] & cc->masks.red;
00618          igreen =
00619              cc->clut[green * cc->max_entry / 65535] & cc->masks.green;
00620          iblue = cc->clut[blue * cc->max_entry / 65535] & cc->masks.blue;
00621 
00622          return ired | igreen | iblue;
00623       }
00624 
00625    case GDK_CC_MODE_PALETTE:
00626       return gdk_color_context_get_pixel_from_palette(cc, &red, &green,
00627                                                       &blue, failed);
00628 
00629    case GDK_CC_MODE_STD_CMAP:
00630    default:
00631       {
00632          GdkColor color;
00633          GdkColor *result = NULL;
00634 
00635          color.red = red;
00636          color.green = green;
00637          color.blue = blue;
00638 
00639          if (cc->color_hash)
00640             result = g_hash_table_lookup(cc->color_hash, &color);
00641 
00642          if (!result) {
00643             color.red = red;
00644             color.green = green;
00645             color.blue = blue;
00646             color.pixel = 0;
00647 
00648             if (!gdk_color_alloc(cc->colormap, &color))
00649                *failed = TRUE;
00650             else {
00651                GdkColor *cnew;
00652 
00653                /* XXX: the following comment comes directly from
00654                 * XCC.c.  I don't know if it is relevant for
00655                 * gdk_color_alloc() as it is for XAllocColor()
00656                 * - Federico
00657                 */
00658                /*
00659                 * I can't figure this out entirely, but it *is* possible
00660                 * that XAllocColor succeeds, even if the number of
00661                 * allocations we've made exceeds the number of available
00662                 * colors in the current colormap. And therefore it
00663                 * might be necessary for us to resize the CLUT.
00664                 */
00665 
00666                if (cc->num_allocated == cc->max_colors) {
00667                   cc->max_colors *= 2;
00668 
00669                   GDK_NOTE(COLOR_CONTEXT,
00670                            g_message("gdk_color_context_get_pixel: "
00671                                      "resizing CLUT to %i entries\n",
00672                                      cc->max_colors));
00673 
00674                   cc->clut = g_realloc(cc->clut,
00675                                        cc->max_colors * sizeof(gulong));
00676                }
00677 
00678                /* Key and value are the same color structure */
00679 
00680                cnew = g_new(GdkColor, 1);
00681                *cnew = color;
00682 
00683                if (!cc->color_hash)
00684                   cc->color_hash =
00685                       g_hash_table_new(hash_color, compare_colors);
00686                g_hash_table_insert(cc->color_hash, cnew, cnew);
00687 
00688                cc->clut[cc->num_allocated] = color.pixel;
00689                cc->num_allocated++;
00690                return color.pixel;
00691             }
00692          }
00693 
00694          return result->pixel;
00695       }
00696    }
00697 }
00698 
00699 void
00700 gdk_color_context_get_pixels(GdkColorContext * cc,
00701                              gushort * reds,
00702                              gushort * greens,
00703                              gushort * blues,
00704                              gint ncolors,
00705                              gulong * colors, gint * nallocated)
00706 {
00707    gint i, k, idx;
00708    gint cmapsize, ncols = 0, nopen = 0, counter = 0;
00709    gint bad_alloc = FALSE;
00710    gint failed[MAX_IMAGE_COLORS], allocated[MAX_IMAGE_COLORS];
00711    GdkColor defs[MAX_IMAGE_COLORS], cmap[MAX_IMAGE_COLORS];
00712 #ifdef G_ENABLE_DEBUG
00713    gint exact_col = 0, subst_col = 0, close_col = 0, black_col = 0;
00714 #endif
00715    g_assert(cc != NULL);
00716    g_assert(reds != NULL);
00717    g_assert(greens != NULL);
00718    g_assert(blues != NULL);
00719    g_assert(colors != NULL);
00720    g_assert(nallocated != NULL);
00721 
00722    memset(defs, 0, MAX_IMAGE_COLORS * sizeof(GdkColor));
00723    memset(failed, 0, MAX_IMAGE_COLORS * sizeof(gint));
00724    memset(allocated, 0, MAX_IMAGE_COLORS * sizeof(gint));
00725 
00726    /* Will only have a value if used by the progressive image loader */
00727 
00728    ncols = *nallocated;
00729 
00730    *nallocated = 0;
00731 
00732    /* First allocate all pixels */
00733 
00734    for (i = 0; i < ncolors; i++) {
00735       /* colors[i] is only zero if the pixel at that location hasn't
00736        * been allocated yet.  This is a sanity check required for proper
00737        * color allocation by the progressive image loader
00738        */
00739 
00740       if (colors[i] == 0) {
00741          defs[i].red = reds[i];
00742          defs[i].green = greens[i];
00743          defs[i].blue = blues[i];
00744 
00745          colors[i] =
00746              gdk_color_context_get_pixel(cc, reds[i], greens[i], blues[i],
00747                                          &bad_alloc);
00748 
00749          /* successfully allocated, store it */
00750 
00751          if (!bad_alloc) {
00752             defs[i].pixel = colors[i];
00753             allocated[ncols++] = colors[i];
00754          } else
00755             failed[nopen++] = i;
00756       }
00757    }
00758 
00759    *nallocated = ncols;
00760 
00761    /* all colors available, all done */
00762 
00763    if ((ncols == ncolors) || (nopen == 0)) {
00764       GDK_NOTE(COLOR_CONTEXT,
00765                g_message
00766                ("gdk_color_context_get_pixels: got all %i colors; "
00767                 "(%i colors allocated so far)\n", ncolors,
00768                 cc->num_allocated));
00769 
00770       return;
00771    }
00772 
00773    /* The fun part.  We now try to allocate the colors we couldn't allocate
00774     * directly.  The first step will map a color onto its nearest color
00775     * that has been allocated (either by us or someone else).  If any colors
00776     * remain unallocated, we map these onto the colors that we have allocated
00777     * ourselves.
00778     */
00779 
00780    /* read up to MAX_IMAGE_COLORS colors of the current colormap */
00781 
00782    cmapsize = MIN(cc->num_colors, MAX_IMAGE_COLORS);
00783 
00784    /* see if the colormap has any colors to read */
00785 
00786    if (cmapsize < 0) {
00787       g_warning
00788           ("gdk_color_context_get_pixels: oops!  no colors available, "
00789            "your images will look *really* ugly.");
00790 
00791       return;
00792    }
00793 #ifdef G_ENABLE_DEBUG
00794    exact_col = ncols;
00795 #endif
00796 
00797    /* initialize pixels */
00798 
00799    for (i = 0; i < cmapsize; i++) {
00800       cmap[i].pixel = i;
00801       cmap[i].red = cmap[i].green = cmap[i].blue = 0;
00802    }
00803 
00804    /* read the colormap */
00805 
00806    my_x_query_colors(cc->colormap, cmap, cmapsize);
00807 
00808    /* get a close match for any unallocated colors */
00809 
00810    counter = nopen;
00811    nopen = 0;
00812    idx = 0;
00813 
00814    do {
00815       gint d, j, mdist, close, ri, gi, bi;
00816       gint rd, gd, bd;
00817 
00818       i = failed[idx];
00819 
00820       mdist = 0x1000000;
00821       close = -1;
00822 
00823       /* Store these vals.  Small performance increase as this skips three
00824        * indexing operations in the loop code.
00825        */
00826 
00827       ri = reds[i];
00828       gi = greens[i];
00829       bi = blues[i];
00830 
00831       /* Walk all colors in the colormap and see which one is the
00832        * closest.  Uses plain least squares.
00833        */
00834 
00835       for (j = 0; (j < cmapsize) && (mdist != 0); j++) {
00836          /* Don't replace these by shifts; the sign may get clobbered */
00837 
00838          rd = (ri - cmap[j].red) / 256;
00839          gd = (gi - cmap[j].green) / 256;
00840          bd = (bi - cmap[j].blue) / 256;
00841 
00842          d = rd * rd + gd * gd + bd * bd;
00843 
00844          if (d < mdist) {
00845             close = j;
00846             mdist = d;
00847          }
00848       }
00849 
00850       if (close != -1) {
00851          rd = cmap[close].red;
00852          gd = cmap[close].green;
00853          bd = cmap[close].blue;
00854 
00855          /* allocate */
00856 
00857          colors[i] =
00858              gdk_color_context_get_pixel(cc, rd, gd, bd, &bad_alloc);
00859 
00860          /* store */
00861 
00862          if (!bad_alloc) {
00863             defs[i] = cmap[close];
00864             defs[i].pixel = colors[i];
00865             allocated[ncols++] = colors[i];
00866 #ifdef G_ENABLE_DEBUG
00867             close_col++;
00868 #endif
00869          } else
00870             failed[nopen++] = i;
00871       } else
00872          failed[nopen++] = i;
00873       /* deal with in next stage if allocation failed */
00874    }
00875    while (++idx < counter);
00876 
00877    *nallocated = ncols;
00878 
00879    /* This is the maximum no. of allocated colors.  See also the nopen == 0
00880     * note above.
00881     */
00882 
00883    if ((ncols == ncolors) || (nopen == 0)) {
00884       GDK_NOTE(COLOR_CONTEXT,
00885                g_message
00886                ("gdk_color_context_get_pixels: got %i colors, %i exact and "
00887                 "%i close (%i colors allocated so far)\n", ncolors,
00888                 exact_col, close_col, cc->num_allocated));
00889 
00890       return;
00891    }
00892 
00893    /* Now map any remaining unallocated pixels into the colors we did get */
00894 
00895    idx = 0;
00896 
00897    do {
00898       gint d, mdist, close, ri, gi, bi;
00899       gint j, rd, gd, bd;
00900 
00901       i = failed[idx];
00902 
00903       mdist = 0x1000000;
00904       close = -1;
00905 
00906       /* store */
00907 
00908       ri = reds[i];
00909       gi = greens[i];
00910       bi = blues[i];
00911 
00912       /* search allocated colors */
00913 
00914       for (j = 0; (j < ncols) && (mdist != 0); j++) {
00915          k = allocated[j];
00916 
00917          /* Don't replace these by shifts; the sign may get clobbered */
00918 
00919          rd = (ri - defs[k].red) / 256;
00920          gd = (gi - defs[k].green) / 256;
00921          bd = (bi - defs[k].blue) / 256;
00922 
00923          d = rd * rd + gd * gd + bd * bd;
00924 
00925          if (d < mdist) {
00926             close = k;
00927             mdist = d;
00928          }
00929       }
00930 
00931       if (close < 0) {
00932          /* too bad, map to black */
00933 
00934          defs[i].pixel = cc->black_pixel;
00935          defs[i].red = defs[i].green = defs[i].blue = 0;
00936 #ifdef G_ENABLE_DEBUG
00937          black_col++;
00938 #endif
00939       } else {
00940          defs[i] = defs[close];
00941 #ifdef G_ENABLE_DEBUG
00942          subst_col++;
00943 #endif
00944       }
00945 
00946       colors[i] = defs[i].pixel;
00947    }
00948    while (++idx < nopen);
00949 
00950    GDK_NOTE(COLOR_CONTEXT,
00951             g_message
00952             ("gdk_color_context_get_pixels: got %i colors, %i exact, %i close, "
00953              "%i substituted, %i to black (%i colors allocated so far)\n",
00954              ncolors, exact_col, close_col, subst_col, black_col,
00955              cc->num_allocated));
00956 }
00957 
00958 void
00959 gdk_color_context_get_pixels_incremental(GdkColorContext * cc,
00960                                          gushort * reds,
00961                                          gushort * greens,
00962                                          gushort * blues,
00963                                          gint ncolors,
00964                                          gint * used,
00965                                          gulong * colors,
00966                                          gint * nallocated)
00967 {
00968    gint i, k, idx;
00969    gint cmapsize, ncols = 0, nopen = 0, counter = 0;
00970    gint bad_alloc = FALSE;
00971    gint failed[MAX_IMAGE_COLORS], allocated[MAX_IMAGE_COLORS];
00972    GdkColor defs[MAX_IMAGE_COLORS], cmap[MAX_IMAGE_COLORS];
00973 #ifdef G_ENABLE_DEBUG
00974    gint exact_col = 0, subst_col = 0, close_col = 0, black_col = 0;
00975 #endif
00976 
00977    g_assert(cc != NULL);
00978    g_assert(reds != NULL);
00979    g_assert(greens != NULL);
00980    g_assert(blues != NULL);
00981    g_assert(used != NULL);
00982    g_assert(colors != NULL);
00983    g_assert(nallocated != NULL);
00984 
00985    memset(defs, 0, MAX_IMAGE_COLORS * sizeof(GdkColor));
00986    memset(failed, 0, MAX_IMAGE_COLORS * sizeof(gint));
00987    memset(allocated, 0, MAX_IMAGE_COLORS * sizeof(gint));
00988 
00989    /* Will only have a value if used by the progressive image loader */
00990 
00991    ncols = *nallocated;
00992 
00993    *nallocated = 0;
00994 
00995    /* First allocate all pixels */
00996 
00997    for (i = 0; i < ncolors; i++) {
00998       /* used[i] is only -1 if the pixel at that location hasn't
00999        * been allocated yet.  This is a sanity check required for proper
01000        * color allocation by the progressive image loader.
01001        * When colors[i] == 0 it indicates the slot is available for
01002        * allocation.
01003        */
01004 
01005       if (used[i] != FALSE) {
01006          if (colors[i] == 0) {
01007             defs[i].red = reds[i];
01008             defs[i].green = greens[i];
01009             defs[i].blue = blues[i];
01010 
01011             colors[i] =
01012                 gdk_color_context_get_pixel(cc, reds[i], greens[i],
01013                                             blues[i], &bad_alloc);
01014 
01015             /* successfully allocated, store it */
01016 
01017             if (!bad_alloc) {
01018                defs[i].pixel = colors[i];
01019                allocated[ncols++] = colors[i];
01020             } else
01021                failed[nopen++] = i;
01022          }
01023 #ifdef DEBUG
01024          else
01025             GDK_NOTE(COLOR_CONTEXT,
01026                      g_message("gdk_color_context_get_pixels_incremental: "
01027                                "pixel at slot %i already allocated, skipping\n",
01028                                i));
01029 #endif
01030       }
01031    }
01032 
01033    *nallocated = ncols;
01034 
01035    if ((ncols == ncolors) || (nopen == 0)) {
01036       GDK_NOTE(COLOR_CONTEXT,
01037                g_message
01038                ("gdk_color_context_get_pixels_incremental: got all %i colors "
01039                 "(%i colors allocated so far)\n", ncolors,
01040                 cc->num_allocated));
01041 
01042       return;
01043    }
01044 
01045    cmapsize = MIN(cc->num_colors, MAX_IMAGE_COLORS);
01046 
01047    if (cmapsize < 0) {
01048       g_warning("gdk_color_context_get_pixels_incremental: oops!  "
01049                 "No colors available images will look *really* ugly.");
01050       return;
01051    }
01052 #ifdef G_ENABLE_DEBUG
01053    exact_col = ncols;
01054 #endif
01055 
01056    /* initialize pixels */
01057 
01058    for (i = 0; i < cmapsize; i++) {
01059       cmap[i].pixel = i;
01060       cmap[i].red = cmap[i].green = cmap[i].blue = 0;
01061    }
01062 
01063    /* read */
01064 
01065    my_x_query_colors(cc->colormap, cmap, cmapsize);
01066 
01067    /* now match any unallocated colors */
01068 
01069    counter = nopen;
01070    nopen = 0;
01071    idx = 0;
01072 
01073    do {
01074       gint d, j, mdist, close, ri, gi, bi;
01075       gint rd, gd, bd;
01076 
01077       i = failed[idx];
01078 
01079       mdist = 0x1000000;
01080       close = -1;
01081 
01082       /* store */
01083 
01084       ri = reds[i];
01085       gi = greens[i];
01086       bi = blues[i];
01087 
01088       for (j = 0; (j < cmapsize) && (mdist != 0); j++) {
01089          /* Don't replace these by shifts; the sign may get clobbered */
01090 
01091          rd = (ri - cmap[j].red) / 256;
01092          gd = (gi - cmap[j].green) / 256;
01093          bd = (bi - cmap[j].blue) / 256;
01094 
01095          d = rd * rd + gd * gd + bd * bd;
01096 
01097          if (d < mdist) {
01098             close = j;
01099             mdist = d;
01100          }
01101       }
01102 
01103       if (close != -1) {
01104          rd = cmap[close].red;
01105          gd = cmap[close].green;
01106          bd = cmap[close].blue;
01107 
01108          /* allocate */
01109 
01110          colors[i] =
01111              gdk_color_context_get_pixel(cc, rd, gd, bd, &bad_alloc);
01112 
01113          /* store */
01114 
01115          if (!bad_alloc) {
01116             defs[i] = cmap[close];
01117             defs[i].pixel = colors[i];
01118             allocated[ncols++] = colors[i];
01119 #ifdef G_ENABLE_DEBUG
01120             close_col++;
01121 #endif
01122          } else
01123             failed[nopen++] = i;
01124       } else
01125          failed[nopen++] = i;
01126       /* deal with in next stage if allocation failed */
01127    }
01128    while (++idx < counter);
01129 
01130    *nallocated = ncols;
01131 
01132    if ((ncols == ncolors) || (nopen == 0)) {
01133       GDK_NOTE(COLOR_CONTEXT,
01134                g_message("gdk_color_context_get_pixels_incremental: "
01135                          "got %i colors, %i exact and %i close "
01136                          "(%i colors allocated so far)\n",
01137                          ncolors, exact_col, close_col,
01138                          cc->num_allocated));
01139 
01140       return;
01141    }
01142 
01143    /* map remaining unallocated pixels into colors we did get */
01144 
01145    idx = 0;
01146 
01147    do {
01148       gint d, mdist, close, ri, gi, bi;
01149       gint j, rd, gd, bd;
01150 
01151       i = failed[idx];
01152 
01153       mdist = 0x1000000;
01154       close = -1;
01155 
01156       ri = reds[i];
01157       gi = greens[i];
01158       bi = blues[i];
01159 
01160       /* search allocated colors */
01161 
01162       for (j = 0; (j < ncols) && (mdist != 0); j++) {
01163          k = allocated[j];
01164 
01165          /* downscale */
01166          /* Don't replace these by shifts; the sign may get clobbered */
01167 
01168          rd = (ri - defs[k].red) / 256;
01169          gd = (gi - defs[k].green) / 256;
01170          bd = (bi - defs[k].blue) / 256;
01171 
01172          d = rd * rd + gd * gd + bd * bd;
01173 
01174          if (d < mdist) {
01175             close = k;
01176             mdist = d;
01177          }
01178       }
01179 
01180       if (close < 0) {
01181          /* too bad, map to black */
01182 
01183          defs[i].pixel = cc->black_pixel;
01184          defs[i].red = defs[i].green = defs[i].blue = 0;
01185 #ifdef G_ENABLE_DEBUG
01186          black_col++;
01187 #endif
01188       } else {
01189          defs[i] = defs[close];
01190 #ifdef G_ENABLE_DEBUG
01191          subst_col++;
01192 #endif
01193       }
01194 
01195       colors[i] = defs[i].pixel;
01196    }
01197    while (++idx < nopen);
01198 
01199    GDK_NOTE(COLOR_CONTEXT,
01200             g_message("gdk_color_context_get_pixels_incremental: "
01201                       "got %i colors, %i exact, %i close, %i substituted, %i to black "
01202                       "(%i colors allocated so far)\n",
01203                       ncolors, exact_col, close_col, subst_col, black_col,
01204                       cc->num_allocated));
01205 }
01206 
01207 gint gdk_color_context_query_color(GdkColorContext * cc, GdkColor * color)
01208 {
01209    return gdk_color_context_query_colors(cc, color, 1);
01210 }
01211 
01212 gint
01213 gdk_color_context_query_colors(GdkColorContext * cc,
01214                                GdkColor * colors, gint num_colors)
01215 {
01216    gint i;
01217    GdkColor *tc;
01218 
01219    g_assert(cc != NULL);
01220    g_assert(colors != NULL);
01221 
01222    switch (cc->mode) {
01223    case GDK_CC_MODE_BW:
01224       for (i = 0, tc = colors; i < num_colors; i++, tc++) {
01225          if (tc->pixel == cc->white_pixel)
01226             tc->red = tc->green = tc->blue = 65535;
01227          else
01228             tc->red = tc->green = tc->blue = 0;
01229       }
01230       break;
01231 
01232    case GDK_CC_MODE_TRUE:
01233       if (cc->clut == NULL)
01234          for (i = 0, tc = colors; i < num_colors; i++, tc++) {
01235 #if 0 // bb change
01236             tc->red =
01237                 ((tc->pixel & cc->masks.red) >> cc->shifts.red) << (16 -
01238                                                                     cc->
01239                                                                     bits.
01240                                                                     red);
01241             tc->green =
01242                 ((tc->pixel & cc->masks.green) >> cc->shifts.
01243                  green) << (16 - cc->bits.green);
01244             tc->blue =
01245                 ((tc->pixel & cc->masks.blue) >> cc->shifts.blue) << (16 -
01246                                                                       cc->
01247                                                                       bits.
01248                                                                       blue);
01249 #else
01250             tc->red = 65535. * (double)((tc->pixel & cc->masks.red) 
01251                 >> cc->shifts.red) / ((1 << cc->visual->red_prec) - 1);
01252             tc->green = 65535. * (double)((tc->pixel & cc->masks.green) 
01253                 >> cc->shifts.green) / ((1 << cc->visual->green_prec) - 1);
01254             tc->blue = 65535. * (double)((tc->pixel & cc->masks.blue) 
01255                 >> cc->shifts.blue) / ((1 << cc->visual->blue_prec) - 1);
01256 #endif
01257       } else {
01258          my_x_query_colors(cc->colormap, colors, num_colors);
01259          return 1;
01260       }
01261       break;
01262 
01263    case GDK_CC_MODE_STD_CMAP:
01264    default:
01265       if (cc->cmap == NULL) {
01266          my_x_query_colors(cc->colormap, colors, num_colors);
01267          return 1;
01268       } else {
01269          gint first, last, half;
01270          gulong half_pixel;
01271 
01272          for (i = 0, tc = colors; i < num_colors; i++) {
01273             first = 0;
01274             last = cc->num_colors - 1;
01275 
01276             while (first <= last) {
01277                half = (first + last) / 2;
01278                half_pixel = cc->cmap[half].pixel;
01279 
01280                if (tc->pixel == half_pixel) {
01281                   tc->red = cc->cmap[half].red;
01282                   tc->green = cc->cmap[half].green;
01283                   tc->blue = cc->cmap[half].blue;
01284                   first = last + 1;     /* false break */
01285                } else {
01286                   if (tc->pixel > half_pixel)
01287                      first = half + 1;
01288                   else
01289                      last = half - 1;
01290                }
01291             }
01292          }
01293          return 1;
01294       }
01295       break;
01296    }
01297    return 1;
01298 }
01299 
01300 gint
01301 gdk_color_context_add_palette(GdkColorContext * cc,
01302                               GdkColor * palette, gint num_palette)
01303 {
01304    gint i, j, erg;
01305    gushort r, g, b;
01306    gulong pixel[1];
01307 
01308    g_assert(cc != NULL);
01309 
01310    /* initialize this palette (will also erase previous palette as well) */
01311 
01312    init_palette(cc);
01313 
01314    /* restore previous mode if we aren't adding a new palette */
01315 
01316    if (num_palette == 0)
01317       return 0;
01318 
01319    /* copy incoming palette */
01320 
01321    cc->palette = g_new0(GdkColor, num_palette);
01322 
01323    j = 0;
01324 
01325    for (i = 0; i < num_palette; i++) {
01326       erg = 0;
01327       pixel[0] = 0;
01328 
01329       /* try to allocate this color */
01330 
01331       r = palette[i].red;
01332       g = palette[i].green;
01333       b = palette[i].blue;
01334 
01335       gdk_color_context_get_pixels(cc, &r, &g, &b, 1, pixel, &erg);
01336 
01337       /* only store if we succeed */
01338 
01339       if (erg) {
01340          /* store in palette */
01341 
01342          cc->palette[j].red = r;
01343          cc->palette[j].green = g;
01344          cc->palette[j].blue = b;
01345          cc->palette[j].pixel = pixel[0];
01346 
01347          /* move to next slot */
01348 
01349          j++;
01350       }
01351    }
01352 
01353    /* resize to fit */
01354 
01355    if (j != num_palette)
01356       cc->palette = g_realloc(cc->palette, j * sizeof(GdkColor));
01357 
01358    /* clear the hash table, we don't use it when dithering */
01359 
01360    if (cc->color_hash) {
01361       g_hash_table_foreach(cc->color_hash, free_hash_entry, NULL);
01362       g_hash_table_destroy(cc->color_hash);
01363       cc->color_hash = NULL;
01364    }
01365 
01366    /* store real palette size */
01367 
01368    cc->num_palette = j;
01369 
01370    /* switch to palette mode */
01371 
01372    cc->mode = GDK_CC_MODE_PALETTE;
01373 
01374    /* sort palette */
01375 
01376    qsort(cc->palette, cc->num_palette, sizeof(GdkColor), pixel_sort);
01377 
01378    cc->fast_dither = NULL;
01379 
01380    return j;
01381 }
01382 
01383 void gdk_color_context_init_dither(GdkColorContext * cc)
01384 {
01385    gint rr, gg, bb, err, erg, erb;
01386    gint success = FALSE;
01387 
01388    g_assert(cc != NULL);
01389 
01390    /* now we can initialize the fast dither matrix */
01391 
01392    if (cc->fast_dither == NULL)
01393       cc->fast_dither = g_new(GdkColorContextDither, 1);
01394 
01395    /* Fill it.  We ignore unsuccessful allocations, they are just mapped
01396     * to black instead */
01397 
01398    for (rr = 0; rr < 32; rr++)
01399       for (gg = 0; gg < 32; gg++)
01400          for (bb = 0; bb < 32; bb++) {
01401             err = (rr << 3) | (rr >> 2);
01402             erg = (gg << 3) | (gg >> 2);
01403             erb = (bb << 3) | (bb >> 2);
01404 
01405             cc->fast_dither->fast_rgb[rr][gg][bb] =
01406                 gdk_color_context_get_index_from_palette(cc, &err, &erg,
01407                                                          &erb, &success);
01408             cc->fast_dither->fast_err[rr][gg][bb] = err;
01409             cc->fast_dither->fast_erg[rr][gg][bb] = erg;
01410             cc->fast_dither->fast_erb[rr][gg][bb] = erb;
01411          }
01412 }
01413 
01414 void gdk_color_context_free_dither(GdkColorContext * cc)
01415 {
01416    g_assert(cc != NULL);
01417 
01418    if (cc->fast_dither)
01419       g_free(cc->fast_dither);
01420 
01421    cc->fast_dither = NULL;
01422 }
01423 
01424 gulong
01425 gdk_color_context_get_pixel_from_palette(GdkColorContext * cc,
01426                                          gushort * red,
01427                                          gushort * green,
01428                                          gushort * blue, gint * failed)
01429 {
01430    gulong pixel = 0;
01431    gint dif, dr, dg, db, j = -1;
01432    gint mindif = 0x7fffffff;
01433    gint err = 0, erg = 0, erb = 0;
01434    gint i;
01435 
01436    g_assert(cc != NULL);
01437    g_assert(red != NULL);
01438    g_assert(green != NULL);
01439    g_assert(blue != NULL);
01440    g_assert(failed != NULL);
01441 
01442    *failed = FALSE;
01443 
01444    for (i = 0; i < cc->num_palette; i++) {
01445       dr = *red - cc->palette[i].red;
01446       dg = *green - cc->palette[i].green;
01447       db = *blue - cc->palette[i].blue;
01448 
01449       dif = dr * dr + dg * dg + db * db;
01450 
01451       if (dif < mindif) {
01452          mindif = dif;
01453          j = i;
01454          pixel = cc->palette[i].pixel;
01455          err = dr;
01456          erg = dg;
01457          erb = db;
01458 
01459          if (mindif == 0)
01460             break;
01461       }
01462    }
01463 
01464    /* we failed to map onto a color */
01465 
01466    if (j == -1)
01467       *failed = TRUE;
01468    else {
01469       *red = ABS(err);
01470       *green = ABS(erg);
01471       *blue = ABS(erb);
01472    }
01473 
01474    return pixel;
01475 }
01476 
01477 guchar
01478 gdk_color_context_get_index_from_palette(GdkColorContext * cc,
01479                                          gint * red,
01480                                          gint * green,
01481                                          gint * blue, gint * failed)
01482 {
01483    gint dif, dr, dg, db, j = -1;
01484    gint mindif = 0x7fffffff;
01485    gint err = 0, erg = 0, erb = 0;
01486    gint i;
01487 
01488    g_assert(cc != NULL);
01489    g_assert(red != NULL);
01490    g_assert(green != NULL);
01491    g_assert(blue != NULL);
01492    g_assert(failed != NULL);
01493 
01494    *failed = FALSE;
01495 
01496    for (i = 0; i < cc->num_palette; i++) {
01497       dr = *red - cc->palette[i].red;
01498       dg = *green - cc->palette[i].green;
01499       db = *blue - cc->palette[i].blue;
01500 
01501       dif = dr * dr + dg * dg + db * db;
01502 
01503       if (dif < mindif) {
01504          mindif = dif;
01505          j = i;
01506          err = dr;
01507          erg = dg;
01508          erb = db;
01509 
01510          if (mindif == 0)
01511             break;
01512       }
01513    }
01514 
01515    /* we failed to map onto a color */
01516 
01517    if (j == -1) {
01518       *failed = TRUE;
01519       j = 0;
01520    } else {
01521       /* return error fractions */
01522 
01523       *red = err;
01524       *green = erg;
01525       *blue = erb;
01526    }
01527 
01528    return j;
01529 }

Generated on Tue Jul 5 14:14:39 2011 for ROOT_528-00b_version by  doxygen 1.5.1