summaryrefslogtreecommitdiff
path: root/gs/src/gdevx.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/src/gdevx.c')
-rw-r--r--gs/src/gdevx.c635
1 files changed, 116 insertions, 519 deletions
diff --git a/gs/src/gdevx.c b/gs/src/gdevx.c
index 953dd8b9d..e97af25b9 100644
--- a/gs/src/gdevx.c
+++ b/gs/src/gdevx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1995, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
This file is part of Aladdin Ghostscript.
@@ -49,6 +49,10 @@ private int X_MAX_TEMP_PIXMAP = 20000;
/* for get_bits_rectangle. */
private int X_MAX_TEMP_IMAGE = 5000;
+/* Define whether to try to read back exposure events after XGetImage. */
+/****** THIS IS USELESS. XGetImage DOES NOT GENERATE EXPOSURE EVENTS. ******/
+#define GET_IMAGE_EXPOSURES 0
+
/* Forward references */
private int set_tile(P2(gx_device *, const gx_strip_bitmap *));
private void free_cp(P1(gx_device *));
@@ -73,15 +77,16 @@ private dev_proc_open_device(x_open);
private dev_proc_get_initial_matrix(x_get_initial_matrix);
private dev_proc_sync_output(x_sync);
private dev_proc_output_page(x_output_page);
+extern void gdev_x_free_dynamic_colors(P1(gx_device_X *));
+extern void gdev_x_free_colors(P1(gx_device_X *));
private dev_proc_close_device(x_close);
-private dev_proc_map_rgb_color(x_map_rgb_color);
-private dev_proc_map_color_rgb(x_map_color_rgb);
+extern dev_proc_map_rgb_color(gdev_x_map_rgb_color);
+extern dev_proc_map_color_rgb(gdev_x_map_color_rgb);
private dev_proc_fill_rectangle(x_fill_rectangle);
private dev_proc_copy_mono(x_copy_mono);
private dev_proc_copy_color(x_copy_color);
private dev_proc_get_params(x_get_params);
private dev_proc_put_params(x_put_params);
-
dev_proc_get_xfont_procs(x_get_xfont_procs);
private dev_proc_get_page_device(x_get_page_device);
private dev_proc_strip_tile_rectangle(x_strip_tile_rectangle);
@@ -96,8 +101,8 @@ private const gx_device_procs x_procs =
x_sync,
x_output_page,
x_close,
- x_map_rgb_color,
- x_map_color_rgb,
+ gdev_x_map_rgb_color,
+ gdev_x_map_color_rgb,
x_fill_rectangle,
NULL, /* tile_rectangle */
x_copy_mono,
@@ -144,7 +149,7 @@ const gx_device_X gs_x11_device =
{ /* image */
0, 0, /* width, height */
0, XYBitmap, NULL, /* xoffset, format, data */
- LSBFirst, 8, /* byte-order, bitmap-unit */
+ MSBFirst, 8, /* byte-order, bitmap-unit */
MSBFirst, 8, 1, /* bitmap-bit-order, bitmap-pad, depth */
0, 1, /* bytes_per_line, bits_per_pixel */
0, 0, 0, /* red_mask, green_mask, blue_mask */
@@ -167,9 +172,6 @@ const gx_device_X gs_x11_device =
(Pixmap) 0, /* bpixmap */
0, /* ghostview */
(Window) None, /* mwin */
-#if HaveStdCMap
- NULL, /* std_cmap */
-#endif
{identity_matrix_body}, /* initial matrix (filled in) */
(Atom) 0, (Atom) 0, (Atom) 0, /* Atoms: NEXT, PAGE, DONE */
{0, 0, 0, 0}, 0, 0, /* update, up_area, up_count */
@@ -192,11 +194,7 @@ const gx_device_X gs_x11_device =
0, /* font */
0, 0, /* back_color, fore_color */
0, 0, /* background, foreground */
- NULL, /* dither_colors */
- 0, 0, /* color_mask, num_rgb */
- NULL, 0, /* dynamic_colors, max_dynamic_colors */
- 0, 0, /* dynamic_size, dynamic_allocs */
- NULL, 0, /* color_to_rgb, color_to_rgb_size */
+ { 0 }, /* cman */
0, 0, /* borderColor, borderWidth */
NULL, /* geometry */
128, 5, /* maxGrayRamp, maxRGBRamp */
@@ -248,482 +246,45 @@ x_open(gx_device * dev)
return 0;
}
-/* Close the device. */
-private int
-x_close(gx_device * dev)
+/* Free fonts when closing the device. */
+private void
+free_x_fontmaps(x11fontmap **pmaps)
{
- gx_device_X *xdev = (gx_device_X *) dev;
-
- if (xdev->ghostview)
- x_send_event(dev, xdev->DONE);
- if (xdev->vinfo) {
- XFree((char *)xdev->vinfo);
- xdev->vinfo = NULL;
- }
- if (xdev->dither_colors) {
- if (gx_device_has_color(xdev))
-#define cube(r) (r*r*r)
- gs_free((char *)xdev->dither_colors, sizeof(x_pixel),
- cube(xdev->color_info.dither_colors), "x11_rgb_cube");
-#undef cube
- else
- gs_free((char *)xdev->dither_colors, sizeof(x_pixel),
- xdev->color_info.dither_grays, "x11_gray_ramp");
- xdev->dither_colors = NULL;
- }
- if (xdev->dynamic_colors) {
- int i;
-
- for (i = 0; i < xdev->dynamic_size; i++) {
- x11color *xcp = (*xdev->dynamic_colors)[i];
- x11color *next;
-
- while (xcp) {
- next = xcp->next;
- gs_free((char *)xcp, sizeof(x11color), 1, "x11_dynamic_color");
- xcp = next;
- }
- }
- gs_free((char *)xdev->dynamic_colors, sizeof(x11color *),
- xdev->dynamic_size, "x11_dynamic_colors");
- xdev->dynamic_colors = NULL;
- }
- if (xdev->color_to_rgb) {
- gs_free((char *)xdev->color_to_rgb, sizeof(x11_rgb_t),
- xdev->color_to_rgb_size, "color_to_rgb");
- xdev->color_to_rgb = NULL;
- xdev->color_to_rgb_size = 0;
- }
- while (xdev->regular_fonts) {
- x11fontmap *font = xdev->regular_fonts;
-
- xdev->regular_fonts = font->next;
- if (font->std_names)
- XFreeFontNames(font->std_names);
- if (font->iso_names)
- XFreeFontNames(font->iso_names);
- gs_free(font->x11_name, sizeof(char), strlen(font->x11_name) + 1,
- "x11_font_x11name");
- gs_free(font->ps_name, sizeof(char), strlen(font->ps_name) + 1,
- "x11_font_psname");
-
- gs_free((char *)font, sizeof(x11fontmap), 1, "x11_fontmap");
- }
- while (xdev->symbol_fonts) {
- x11fontmap *font = xdev->symbol_fonts;
-
- xdev->symbol_fonts = font->next;
- if (font->std_names)
- XFreeFontNames(font->std_names);
- if (font->iso_names)
- XFreeFontNames(font->iso_names);
- gs_free(font->x11_name, sizeof(char), strlen(font->x11_name) + 1,
- "x11_font_x11name");
- gs_free(font->ps_name, sizeof(char), strlen(font->ps_name) + 1,
- "x11_font_psname");
-
- gs_free((char *)font, sizeof(x11fontmap), 1, "x11_fontmap");
- }
- while (xdev->dingbat_fonts) {
- x11fontmap *font = xdev->dingbat_fonts;
-
- xdev->dingbat_fonts = font->next;
- if (font->std_names)
- XFreeFontNames(font->std_names);
- if (font->iso_names)
- XFreeFontNames(font->iso_names);
+ while (*pmaps) {
+ x11fontmap *font = *pmaps;
+
+ *pmaps = font->next;
+ if (font->std.names)
+ XFreeFontNames(font->std.names);
+ if (font->iso.names)
+ XFreeFontNames(font->iso.names);
gs_free(font->x11_name, sizeof(char), strlen(font->x11_name) + 1,
"x11_font_x11name");
gs_free(font->ps_name, sizeof(char), strlen(font->ps_name) + 1,
"x11_font_psname");
- gs_free((char *)font, sizeof(x11fontmap), 1, "x11_fontmap");
- }
- XCloseDisplay(xdev->dpy);
- return 0;
-}
-
-/* Define a table for computing N * X_max_color_value / D for 0 <= N <= D, */
-/* 1 <= D <= 7. */
-/* This requires a multiply and a divide otherwise; */
-/* integer multiply and divide are slow on all platforms. */
-#define cv_fraction(n, d) ((ushort)(X_max_color_value * (n) / (d)))
-#define nd(n, d) cv_fraction(n, d)
-private const ushort cv_tab1[] =
-{
- nd(0, 1), nd(1, 1)
-};
-private const ushort cv_tab2[] =
-{
- nd(0, 2), nd(1, 2), nd(2, 2)
-};
-private const ushort cv_tab3[] =
-{
- nd(0, 3), nd(1, 3), nd(2, 3), nd(3, 3)
-};
-private const ushort cv_tab4[] =
-{
- nd(0, 4), nd(1, 4), nd(2, 4), nd(3, 4), nd(4, 4)
-};
-private const ushort cv_tab5[] =
-{
- nd(0, 5), nd(1, 5), nd(2, 5), nd(3, 5), nd(4, 5), nd(5, 5)
-};
-private const ushort cv_tab6[] =
-{
- nd(0, 6), nd(1, 6), nd(2, 6), nd(3, 6), nd(4, 6), nd(5, 6), nd(6, 6)
-};
-private const ushort cv_tab7[] =
-{
- nd(0, 7), nd(1, 7), nd(2, 7), nd(3, 7), nd(4, 7), nd(5, 7), nd(6, 7), nd(7, 7)
-};
-private const ushort *const cv_tables[] =
-{
- 0, cv_tab1, cv_tab2, cv_tab3, cv_tab4, cv_tab5, cv_tab6, cv_tab7
-};
-
-/* Map a color. The "device colors" are just r,g,b packed together. */
-private gx_color_index
-x_map_rgb_color(register gx_device * dev,
- gx_color_value r, gx_color_value g, gx_color_value b)
-{
- gx_device_X *xdev = (gx_device_X *) dev;
-
- /* X and ghostscript both use shorts for color values */
- unsigned short dr = r & xdev->color_mask; /* Nearest color that */
- unsigned short dg = g & xdev->color_mask; /* the X device can */
- unsigned short db = b & xdev->color_mask; /* represent */
- unsigned short cv_max = X_max_color_value & xdev->color_mask;
-
-#define cv_denom (gx_max_color_value + 1)
-
- /* Foreground and background get special treatment: */
- /* They may be mapped to other colors. */
- if ((dr | dg | db) == 0) { /* i.e., all 0 */
- if_debug4('C', "[cX]%u,%u,%u => foreground = %lu\n",
- r, g, b, (ulong) xdev->foreground);
- return xdev->foreground;
- }
- if ((dr & dg & db) == cv_max) { /* i.e., all max value */
- if_debug4('C', "[cX]%u,%u,%u => background = %lu\n",
- r, g, b, (ulong) xdev->background);
- return xdev->background;
- }
-#if HaveStdCMap
- /* check the standard colormap first */
- if (xdev->std_cmap) {
- XStandardColormap *cmap = xdev->std_cmap;
-
- if (gx_device_has_color(xdev)) {
- unsigned short cr, cg, cb; /* rgb cube indices */
- unsigned short cvr, cvg, cvb; /* color value on cube */
-
- cr = r * (cmap->red_max + 1) / cv_denom;
- cg = g * (cmap->green_max + 1) / cv_denom;
- cb = b * (cmap->blue_max + 1) / cv_denom;
- cvr = X_max_color_value * cr / cmap->red_max;
- cvg = X_max_color_value * cg / cmap->green_max;
- cvb = X_max_color_value * cb / cmap->blue_max;
- if ((abs((int)r - (int)cvr) & xdev->color_mask) == 0 &&
- (abs((int)g - (int)cvg) & xdev->color_mask) == 0 &&
- (abs((int)b - (int)cvb) & xdev->color_mask) == 0) {
- gx_color_index pixel =
- cr * cmap->red_mult + cg * cmap->green_mult +
- cb * cmap->blue_mult + cmap->base_pixel;
-
- if_debug4('C', "[cX]%u,%u,%u (std cmap) => %lu\n",
- r, g, b, pixel);
- return pixel;
- }
- if_debug3('C', "[cX]%u,%u,%u (std cmap fails)\n", r, g, b);
- } else {
- unsigned short cr;
- unsigned short cvr;
- int dither_grays = xdev->color_info.dither_grays;
-
- cr = r * dither_grays / cv_denom;
- cvr = X_max_color_value * cr / cmap->red_max;
- if ((abs((int)r - (int)cvr) & xdev->color_mask) == 0) {
- gx_color_index pixel = cr * cmap->red_mult + cmap->base_pixel;
-
- if_debug2('C', "[cX]%u (std cmap) => %lu\n", r, pixel);
- return pixel;
- }
- if_debug1('C', "[cX]%u (std cmap fails)\n", r);
- }
- } else
-#endif
- /* If there is no standard colormap, check the dither cube/ramp */
- if (xdev->dither_colors) {
- if (gx_device_has_color(xdev)) {
- unsigned short cr, cg, cb; /* rgb cube indices */
- unsigned short cvr, cvg, cvb; /* color value on cube */
- int dither_rgb = xdev->color_info.dither_colors;
- unsigned short max_rgb = dither_rgb - 1;
-
- cr = r * dither_rgb / cv_denom;
- cg = g * dither_rgb / cv_denom;
- cb = b * dither_rgb / cv_denom;
- if (max_rgb < countof(cv_tables)) {
- const ushort *cv_tab = cv_tables[max_rgb];
-
- cvr = cv_tab[cr];
- cvg = cv_tab[cg];
- cvb = cv_tab[cb];
- } else {
- cvr = cv_fraction(cr, max_rgb);
- cvg = cv_fraction(cg, max_rgb);
- cvb = cv_fraction(cb, max_rgb);
- }
- if ((abs((int)r - (int)cvr) & xdev->color_mask) == 0 &&
- (abs((int)g - (int)cvg) & xdev->color_mask) == 0 &&
- (abs((int)b - (int)cvb) & xdev->color_mask) == 0) {
- gx_color_index pixel =
- xdev->dither_colors[cube_index(cr, cg, cb)];
-
- if_debug4('C', "[cX]%u,%u,%u (dither cube) => %lu\n",
- r, g, b, pixel);
- return pixel;
- }
- if_debug3('C', "[cX]%u,%u,%u (dither cube fails)\n", r, g, b);
- } else {
- unsigned short cr;
- unsigned short cvr;
- int dither_grays = xdev->color_info.dither_grays;
- unsigned short max_gray = dither_grays - 1;
-
- cr = r * dither_grays / cv_denom;
- cvr = (X_max_color_value * cr / max_gray);
- if ((abs((int)r - (int)cvr) & xdev->color_mask) == 0) {
- gx_color_index pixel = xdev->dither_colors[cr];
-
- if_debug2('C', "[cX]%u (dither ramp) => %lu\n", r, pixel);
- return pixel;
- }
- if_debug1('C', "[cX]%u (dither ramp fails)\n", r);
- }
- }
- /* Finally look through the list of dynamic colors */
- if (xdev->dynamic_colors) {
- int i = (dr ^ dg ^ db) >> (16 - xdev->vinfo->bits_per_rgb);
- x11color *xcp = (*xdev->dynamic_colors)[i];
- x11color *last = NULL;
- XColor xc;
-
- while (xcp) {
- if (xcp->color.red == dr && xcp->color.green == dg &&
- xcp->color.blue == db) {
- if (last) {
- last->next = xcp->next;
- xcp->next = (*xdev->dynamic_colors)[i];
- (*xdev->dynamic_colors)[i] = xcp;
- }
- if (xcp->color.pad) {
- if_debug4('C', "[cX]%u,%u,%u (dynamic) => %lu\n",
- r, g, b, (ulong) xcp->color.pixel);
- return xcp->color.pixel;
- } else {
- if_debug3('C', "[cX]%u,%u,%u (dynamic) => missing\n",
- r, g, b);
- return gx_no_color_index;
- }
- }
- last = xcp;
- xcp = xcp->next;
- }
-
- /* If not in our list of dynamic colors, */
- /* ask the X server and add an entry. */
- /* First check if dynamic table is exhausted */
- if (xdev->dynamic_allocs > xdev->max_dynamic_colors) {
- if_debug3('C', "[cX]%u,%u,%u (dynamic) => full\n", r, g, b);
- return gx_no_color_index;
- }
- xcp = (x11color *) gs_malloc(sizeof(x11color), 1, "x11_dynamic_color");
- if (!xcp)
- return gx_no_color_index;
- xc.red = xcp->color.red = dr;
- xc.green = xcp->color.green = dg;
- xc.blue = xcp->color.blue = db;
- xcp->next = (*xdev->dynamic_colors)[i];
- (*xdev->dynamic_colors)[i] = xcp;
- xdev->dynamic_allocs++;
- if (XAllocColor(xdev->dpy, xdev->cmap, &xc)) {
- xcp->color.pixel = xc.pixel;
- xcp->color.pad = True;
- if_debug4('C', "[cX]%u,%u,%u (dynamic) => added %lu\n",
- r, g, b, (ulong) xc.pixel);
- return xc.pixel;
- } else {
- xcp->color.pad = False;
- if_debug3('C', "[cX]%u,%u,%u (dynamic) => can't alloc\n", r, g, b);
- return gx_no_color_index;
- }
+ gs_free(font, sizeof(x11fontmap), 1, "x11_fontmap");
}
- if_debug3('C', "[cX]%u,%u,%u fails\n", r, g, b);
- return gx_no_color_index;
}
-
-/*
- * Map a "device color" back to r-g-b. This happens surprisingly often, so
- * we go to some trouble to make it efficient. Foreground and background
- * may be mapped to other colors, so they are handled specially.
- */
+/* Close the device. */
private int
-x_map_color_rgb(register gx_device * dev, gx_color_index color,
- gx_color_value prgb[3])
+x_close(gx_device * dev)
{
gx_device_X *xdev = (gx_device_X *) dev;
-#if HaveStdCMap
- const XStandardColormap *cmap = xdev->std_cmap;
-
-#endif
-#define cv_denom (gx_max_color_value + 1)
-
- if (color == xdev->foreground) {
- prgb[0] = prgb[1] = prgb[2] = 0;
- return 0;
- }
- if (color == xdev->background) {
- prgb[0] = prgb[1] = prgb[2] = gx_max_color_value;
- return 0;
- }
- if (color < xdev->color_to_rgb_size) {
- x11_rgb_t *pxrgb = &xdev->color_to_rgb[color];
-
- if (pxrgb->defined) {
- prgb[0] = pxrgb->rgb[0];
- prgb[1] = pxrgb->rgb[1];
- prgb[2] = pxrgb->rgb[2];
- return 0;
- }
- }
-#if HaveStdCMap
- /* Check the standard colormap first. */
- if (cmap) {
- if (color >= cmap->base_pixel) {
- x_pixel value = color - cmap->base_pixel;
- unsigned long mult[3];
- unsigned long rgb[3];
-
-#define R 0
-#define G 1
-#define B 2
- mult[R] = cmap->red_mult;
- mult[G] = cmap->green_mult;
- mult[B] = cmap->blue_mult;
- /* Get the multipliers in the right order. */
- {
- static const byte order[8][3] =
- {
- {0, 0, 0}, /* not possible */
- {B, G, R},
- {G, R, B},
- {G, B, R},
- {R, B, G},
- {B, R, G},
- {R, G, B},
- {0, 0, 0} /* not possible */
- };
- const byte *indices =
- order[((mult[R] > mult[G]) << 2) + ((mult[G] > mult[B]) << 1) +
- (mult[B] > mult[R])];
-
- rgb[indices[0]] = value / mult[indices[0]];
- value %= mult[indices[0]];
- rgb[indices[1]] = value / mult[indices[1]];
- value %= mult[indices[1]];
- rgb[indices[2]] = value / mult[indices[2]];
- value %= mult[indices[2]];
- if (value == 0 && rgb[R] <= cmap->red_max &&
- rgb[G] <= cmap->green_max && rgb[B] <= cmap->blue_max
- ) {
- /*
- * When mapping color buckets back to specific colors, we can
- * choose to map them to the darkest shades (e.g., 0, 1/3, 2/3),
- * to the lightest shades (e.g., 1/3-epsilon, 2/3-epsilon,
- * 1-epsilon), to the middle shades (e.g., 1/6, 1/2, 5/6),
- * or for maximum contrast (e.g., 0, 1/2, 1). The last of these
- * matches the assumptions of the halftoning code, so that is
- * what we choose.
- */
- prgb[0] = rgb[R] * gx_max_color_value / cmap->red_max;
- prgb[1] = rgb[G] * gx_max_color_value / cmap->green_max;
- prgb[2] = rgb[B] * gx_max_color_value / cmap->blue_max;
- goto found;
- }
- }
-#undef R
-#undef G
-#undef B
- }
- }
-#endif
- /* Check the dither cube/ramp. */
- if (xdev->dither_colors) {
- if (gx_device_has_color(xdev)) {
- int size = xdev->color_info.dither_colors;
- int size3 = size * size * size;
- int i;
-
- for (i = 0; i < size3; ++i)
- if (xdev->dither_colors[i] == color) {
- uint max_rgb = size - 1;
- unsigned long
- r = i / (size * size),
- g = (i / size) % size,
- b = i % size;
-
- /*
- * See above regarding the choice of color mapping
- * algorithm.
- */
- prgb[0] = r * gx_max_color_value / max_rgb;
- prgb[1] = g * gx_max_color_value / max_rgb;
- prgb[2] = b * gx_max_color_value / max_rgb;
- goto found;
- }
- }
- } else {
- int size = xdev->color_info.dither_grays;
- int i;
-
- for (i = 0; i < size; ++i)
- if (xdev->dither_colors[i] == color) {
- prgb[0] = prgb[1] = prgb[2] =
- i * gx_max_color_value / (size - 1);
- goto found;
- }
- }
- /* Finally, search the list of dynamic colors. */
- if (xdev->dynamic_colors) {
- int i;
- const x11color *xcp;
-
- for (i = 1 << xdev->vinfo->bits_per_rgb; --i >= 0;)
- for (xcp = (*xdev->dynamic_colors)[i]; xcp; xcp = xcp->next)
- if (xcp->color.pad && xcp->color.pixel == color) {
- prgb[0] = xcp->color.red;
- prgb[1] = xcp->color.green;
- prgb[2] = xcp->color.blue;
- goto found;
- }
- }
- /* Not found -- not possible! */
- return_error(gs_error_unknownerror);
- found:
- if (color < xdev->color_to_rgb_size) {
- x11_rgb_t *pxrgb = &xdev->color_to_rgb[color];
-
- pxrgb->rgb[0] = prgb[0];
- pxrgb->rgb[1] = prgb[1];
- pxrgb->rgb[2] = prgb[2];
- pxrgb->defined = true;
+ if (xdev->ghostview)
+ x_send_event(dev, xdev->DONE);
+ if (xdev->vinfo) {
+ XFree((char *)xdev->vinfo);
+ xdev->vinfo = NULL;
}
+ gdev_x_free_colors(xdev);
+ free_x_fontmaps(&xdev->dingbat_fonts);
+ free_x_fontmaps(&xdev->symbol_fonts);
+ free_x_fontmaps(&xdev->regular_fonts);
+ XCloseDisplay(xdev->dpy);
return 0;
-#undef cv_denom
}
/* Get initial matrix for X device. */
@@ -812,35 +373,12 @@ x_fill_rectangle(register gx_device * dev,
set_function(GXcopy);
XFillRectangle(xdev->dpy, xdev->dest, xdev->gc, x, y, w, h);
/* If we are filling the entire screen, reset */
- /* colors_or and colors_and. It's wasteful to do this */
+ /* colors_or and colors_and. It's wasteful to test this */
/* on every operation, but there's no separate driver routine */
/* for erasepage (yet). */
if (x == 0 && y == 0 && w == xdev->width && h == xdev->height) {
- if (color == xdev->foreground || color == xdev->background) {
- if (xdev->dynamic_colors) {
- int i;
-
- for (i = 0; i < xdev->dynamic_size; i++) {
- x11color *xcp = (*xdev->dynamic_colors)[i];
- x11color *next;
-
- while (xcp) {
- next = xcp->next;
- if (xcp->color.pad) {
- XFreeColors(xdev->dpy, xdev->cmap,
- &xcp->color.pixel, 1, 0);
- }
- gs_free((char *)xcp, sizeof(x11color), 1,
- "x11_dynamic_color");
- xcp = next;
- }
- (*xdev->dynamic_colors)[i] = NULL;
- }
- xdev->dynamic_allocs = 0;
- for (i = 0; i < xdev->color_to_rgb_size; ++i)
- xdev->color_to_rgb[i].defined = false;
- }
- }
+ if (color == xdev->foreground || color == xdev->background)
+ gdev_x_free_dynamic_colors(xdev);
xdev->colors_or = xdev->colors_and = color;
}
if (xdev->bpixmap != (Pixmap) 0) {
@@ -1369,7 +907,9 @@ x_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
int y, h;
XImage *image;
int code = 0;
+#if GET_IMAGE_EXPOSURES
XWindowAttributes attributes;
+#endif /* GET_IMAGE_EXPOSURES */
if (x0 < 0 || y0 < 0 || x1 > dev->width || y1 > dev->height)
return_error(gs_error_rangecheck);
@@ -1401,46 +941,103 @@ x_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
****** FOLLOWING IS WRONG. XGetImage DOES NOT GENERATE
****** EXPOSURE EVENTS.
******/
-#if 0 /*************** */
+#if GET_IMAGE_EXPOSURES
if (unread) {
XSetGraphicsExposures(xdev->dpy, xdev->gc, True);
XGetWindowAttributes(xdev->dpy, xdev->win, &attributes);
XSelectInput(xdev->dpy, xdev->win,
attributes.your_event_mask | ExposureMask);
}
-#endif /*************** */
+#endif /* GET_IMAGE_EXPOSURES */
/*
* The X library doesn't provide any way to specify the desired
- * bit or byte ordering for the result, so we just hope for the best
- * (big-endian).
+ * bit or byte ordering for the result, so we may have to swap the
+ * bit or byte order.
*/
if (band == 0)
band = 1;
for (y = y0; y < y1; y += h) {
+ int cy;
+
h = min(band, y1 - y);
image = XGetImage(xdev->dpy, xdev->dest, x0, y, x1 - x0, h,
plane_mask, ZPixmap);
- {
- int cy;
-
- for (cy = y; cy < y + h; ++cy)
- memcpy(params->data[0] + (cy - y0) * raster,
- image->data + (cy - y) * image->bytes_per_line,
- width_bytes);
+ for (cy = y; cy < y + h; ++cy) {
+ const byte *source =
+ (const byte *)image->data + (cy - y) * image->bytes_per_line;
+ byte *dest = params->data[0] + (cy - y0) * raster;
+
+ /*
+ * XGetImage can return an image with any bit order, byte order,
+ * unit size (for bitmaps), and bits_per_pixel it wants: it's up
+ * to us to convert the results. (It's a major botch in the X
+ * design that even though the server has to have the ability to
+ * convert images from any format to any format, there's no way
+ * to specify a requested format for XGetImage.)
+ */
+ if (image->bits_per_pixel == image->depth &&
+ (image->depth > 1 || image->bitmap_bit_order == MSBFirst) &&
+ (image->byte_order == MSBFirst || image->depth <= 8)
+ ) {
+ /*
+ * The server has been nice enough to return an image in the
+ * format we use.
+ */
+ memcpy(dest, source, width_bytes);
+ } else {
+ /*
+ * We need to swap byte order and/or bit order. What a
+ * totally unnecessary nuisance! For the moment, the only
+ * cases we deal with are 16- and 24-bit images with padding
+ * and/or byte swapping.
+ */
+ if (image->depth == 24) {
+ int cx;
+ const byte *p = source;
+ byte *q = dest;
+ int step = image->bits_per_pixel >> 3;
+
+ if (image->byte_order == MSBFirst) {
+ p += step - 3;
+ for (cx = x0; cx < x1; p += step, q += 3, ++cx)
+ q[0] = p[0], q[1] = p[1], q[2] = p[2];
+ } else {
+ for (cx = x0; cx < x1; p += step, q += 3, ++cx)
+ q[0] = p[2], q[1] = p[1], q[2] = p[0];
+ }
+ } else if (image->depth == 16) {
+ int cx;
+ const byte *p = source;
+ byte *q = dest;
+ int step = image->bits_per_pixel >> 3;
+
+ if (image->byte_order == MSBFirst) {
+ p += step - 2;
+ for (cx = x0; cx < x1; p += step, q += 2, ++cx)
+ q[0] = p[0], q[1] = p[1];
+ } else {
+ for (cx = x0; cx < x1; p += step, q += 2, ++cx)
+ q[0] = p[1], q[1] = p[0];
+ }
+ } else
+ code = gs_note_error(gs_error_rangecheck);
+ }
}
XDestroyImage(image);
}
if (unread) {
+#if GET_IMAGE_EXPOSURES
XEvent event;
+#endif /* GET_IMAGE_EXPOSURES */
*unread = 0;
-#if 0 /*************** */
+#if GET_IMAGE_EXPOSURES
/* Read any exposure events. */
XWindowEvent(xdev->dpy, xdev->win, ExposureMask, &event);
if (event.type == GraphicsExpose) {
gs_int_rect *rects = (gs_int_rect *)
- gs_alloc_bytes(dev->memory, sizeof(gs_int_rect),
- "x_get_bits_rectangle");
+ gs_alloc_bytes(dev->memory, sizeof(gs_int_rect),
+ "x_get_bits_rectangle");
int num_rects = 0;
for (;;) {
@@ -1458,7 +1055,7 @@ x_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
break;
#undef xevent
rects = gs_resize_object(dev->memory, rects,
- (num_rects + 1) * sizeof(gs_int_rect),
+ (num_rects + 1) * sizeof(gs_int_rect),
"x_get_bits_rectangle");
}
if (code >= 0) {
@@ -1469,7 +1066,7 @@ x_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
/* Restore the window state. */
XSetGraphicsExposures(xdev->dpy, xdev->gc, False);
XSelectInput(xdev->dpy, xdev->win, attributes.your_event_mask);
-#endif /*************** */
+#endif /* GET_IMAGE_EXPOSURES */
}
return code;
}
@@ -1575,7 +1172,7 @@ x_update_add(gx_device * dev, int xo, int yo, int w, int h)
/* would result in too much being copied unnecessarily. */
long old_area = xdev->up_area;
long new_up_area;
- rect u;
+ x_rect u;
u.xo = min(xo, xdev->update.xo);
u.yo = min(yo, xdev->update.yo);