summaryrefslogtreecommitdiff
path: root/src/cairo-xlib-visual.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-xlib-visual.c')
-rw-r--r--src/cairo-xlib-visual.c103
1 files changed, 71 insertions, 32 deletions
diff --git a/src/cairo-xlib-visual.c b/src/cairo-xlib-visual.c
index 3a7b58657..f6eb1ee9b 100644
--- a/src/cairo-xlib-visual.c
+++ b/src/cairo-xlib-visual.c
@@ -66,15 +66,16 @@ _cairo_xlib_visual_info_create (Display *dpy,
Colormap colormap = DefaultColormap (dpy, screen);
XColor color;
int gray, red, green, blue;
- int i, index, distance, min_distance = 0;
+ int i, j, distance, min_distance = 0;
+ XColor colors[256];
+ unsigned short cube_index_to_short[CUBE_SIZE];
+ unsigned short ramp_index_to_short[RAMP_SIZE];
+ unsigned char gray_to_pseudocolor[RAMP_SIZE];
- const unsigned short index5_to_short[5] = {
- 0x0000, 0x36db, 0x8000, 0xc925, 0xffff
- };
- const unsigned short index8_to_short[8] = {
- 0x0000, 0x2492, 0x4924, 0x6db6,
- 0x9249, 0xb6db, 0xdb6d, 0xffff
- };
+ for (i = 0; i < CUBE_SIZE; i++)
+ cube_index_to_short[i] = (0xffff * i + ((CUBE_SIZE-1)>>1)) / (CUBE_SIZE-1);
+ for (i = 0; i < RAMP_SIZE; i++)
+ ramp_index_to_short[i] = (0xffff * i + ((RAMP_SIZE-1)>>1)) / (RAMP_SIZE-1);
info = malloc (sizeof (cairo_xlib_visual_info_t));
if (info == NULL)
@@ -82,10 +83,11 @@ _cairo_xlib_visual_info_create (Display *dpy,
info->visualid = visualid;
- /* Allocate a 8-entry gray ramp and a 5x5x5 color cube. Give up
- * as soon as failures start. */
- for (gray = 0; gray < 8; gray++) {
- color.red = color.green = color.blue = index8_to_short[gray];
+ /* Allocate a gray ramp and a color cube.
+ * Give up as soon as failures start. */
+
+ for (gray = 0; gray < RAMP_SIZE; gray++) {
+ color.red = color.green = color.blue = ramp_index_to_short[gray];
if (! XAllocColor (dpy, colormap, &color))
goto DONE_ALLOCATE;
}
@@ -93,12 +95,12 @@ _cairo_xlib_visual_info_create (Display *dpy,
/* XXX: Could do this in a more clever order to have the best
* possible results from early failure. Could also choose a cube
* uniformly distributed in a better space than RGB. */
- for (red = 0; red < 5; red++) {
- for (green = 0; green < 5; green++) {
- for (blue = 0; blue < 5; blue++) {
- color.red = index5_to_short[red];
- color.green = index5_to_short[green];
- color.blue = index5_to_short[blue];
+ for (red = 0; red < CUBE_SIZE; red++) {
+ for (green = 0; green < CUBE_SIZE; green++) {
+ for (blue = 0; blue < CUBE_SIZE; blue++) {
+ color.red = cube_index_to_short[red];
+ color.green = cube_index_to_short[green];
+ color.blue = cube_index_to_short[blue];
color.pixel = 0;
color.flags = 0;
color.pad = 0;
@@ -109,31 +111,68 @@ _cairo_xlib_visual_info_create (Display *dpy,
}
DONE_ALLOCATE:
- for (i = 0; i < ARRAY_LENGTH (info->colors); i++)
- info->colors[i].pixel = i;
- XQueryColors (dpy, colormap, info->colors, ARRAY_LENGTH (info->colors));
+ for (i = 0; i < ARRAY_LENGTH (colors); i++)
+ colors[i].pixel = i;
+ XQueryColors (dpy, colormap, colors, ARRAY_LENGTH (colors));
/* Search for nearest colors within allocated colormap. */
- for (red = 0; red < 8; red++) {
- for (green = 0; green < 8; green++) {
- for (blue = 0; blue < 8; blue++) {
- index = (red << 6) | (green << 3) | (blue);
+ for (gray = 0; gray < RAMP_SIZE; gray++) {
+ for (i = 0; i < 256; i++) {
+ distance = _color_distance (ramp_index_to_short[gray],
+ ramp_index_to_short[gray],
+ ramp_index_to_short[gray],
+ colors[i].red,
+ colors[i].green,
+ colors[i].blue);
+ if (i == 0 || distance < min_distance) {
+ gray_to_pseudocolor[gray] = colors[i].pixel;
+ min_distance = distance;
+ if (!min_distance)
+ break;
+ }
+ }
+ }
+ for (red = 0; red < CUBE_SIZE; red++) {
+ for (green = 0; green < CUBE_SIZE; green++) {
+ for (blue = 0; blue < CUBE_SIZE; blue++) {
for (i = 0; i < 256; i++) {
- distance = _color_distance (index8_to_short[red],
- index8_to_short[green],
- index8_to_short[blue],
- info->colors[i].red,
- info->colors[i].green,
- info->colors[i].blue);
+ distance = _color_distance (cube_index_to_short[red],
+ cube_index_to_short[green],
+ cube_index_to_short[blue],
+ colors[i].red,
+ colors[i].green,
+ colors[i].blue);
if (i == 0 || distance < min_distance) {
- info->rgb333_to_pseudocolor[index] = info->colors[i].pixel;
+ info->cube_to_pseudocolor[red][green][blue] = colors[i].pixel;
min_distance = distance;
+ if (!min_distance)
+ break;
}
}
}
}
}
+ for (i = 0, j = 0; i < 256; i++) {
+ if (j < CUBE_SIZE - 1 && (((i<<8)+i) - (int)cube_index_to_short[j]) > ((int)cube_index_to_short[j+1] - ((i<<8)+i)))
+ j++;
+ info->field8_to_cube[i] = j;
+
+ info->dither8_to_cube[i] = ((int)i - 128) / (CUBE_SIZE - 1);
+ }
+ for (i = 0, j = 0; i < 256; i++) {
+ if (j < RAMP_SIZE - 1 && (((i<<8)+i) - (int)ramp_index_to_short[j]) > ((int)ramp_index_to_short[j+1] - ((i<<8)+i)))
+ j++;
+ info->gray8_to_pseudocolor[i] = gray_to_pseudocolor[j];
+ }
+
+ for (i = 0; i < 256; i++) {
+ info->colors[i].a = 0xff;
+ info->colors[i].r = colors[i].red >> 8;
+ info->colors[i].g = colors[i].green >> 8;
+ info->colors[i].b = colors[i].blue >> 8;
+ }
+
*out = info;
return CAIRO_STATUS_SUCCESS;
}