17dd7cddfSDavid du Colombier /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: gdevxalt.c,v 1.11 2004/05/26 04:10:58 dan Exp $ */
187dd7cddfSDavid du Colombier /* Alternative X Windows drivers for help in driver debugging */
197dd7cddfSDavid du Colombier #include "gx.h" /* for gx_bitmap; includes std.h */
207dd7cddfSDavid du Colombier #include "math_.h"
217dd7cddfSDavid du Colombier #include "memory_.h"
227dd7cddfSDavid du Colombier #include "x_.h"
237dd7cddfSDavid du Colombier #include "gserrors.h"
247dd7cddfSDavid du Colombier #include "gsparam.h"
257dd7cddfSDavid du Colombier #include "gsstruct.h"
267dd7cddfSDavid du Colombier #include "gxdevice.h"
277dd7cddfSDavid du Colombier #include "gsdevice.h" /* for gs_copydevice */
287dd7cddfSDavid du Colombier #include "gdevx.h"
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier extern const gx_device_X gs_x11_device;
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier /*
337dd7cddfSDavid du Colombier * Define a forwarding device with a cache for the first 16 colors,
347dd7cddfSDavid du Colombier * which avoids all of the time-consuming color mapping calls for
357dd7cddfSDavid du Colombier * the black-and-white, 2-bit gray, and 1-bit CMYK devices defined here.
367dd7cddfSDavid du Colombier */
377dd7cddfSDavid du Colombier typedef struct {
387dd7cddfSDavid du Colombier gx_device_forward_common;
397dd7cddfSDavid du Colombier gx_color_index color_cache[16];
407dd7cddfSDavid du Colombier /*
417dd7cddfSDavid du Colombier * alt_map_color returns a value >= 0 if it maps directly to the final
427dd7cddfSDavid du Colombier * gx_color_index, or < 0 if it only sets RGB values.
437dd7cddfSDavid du Colombier */
447dd7cddfSDavid du Colombier dev_proc_map_color_rgb((*alt_map_color));
457dd7cddfSDavid du Colombier } gx_device_X_wrapper;
467dd7cddfSDavid du Colombier #define X_WRAPPER_DATA(amc_proc)\
477dd7cddfSDavid du Colombier /* gx_device_forward_common */\
487dd7cddfSDavid du Colombier {0}, /* std_procs */\
497dd7cddfSDavid du Colombier 0, /* target */\
507dd7cddfSDavid du Colombier /* gx_device_X_wrapper */\
517dd7cddfSDavid du Colombier {0}, /* cache */\
527dd7cddfSDavid du Colombier amc_proc
537dd7cddfSDavid du Colombier gs_private_st_suffix_add0_final(st_device_X_wrapper, gx_device_X_wrapper,
547dd7cddfSDavid du Colombier "gx_device_X_wrapper", gdevx_wrapper_enum_ptrs, gdevx_wrapper_reloc_ptrs,
557dd7cddfSDavid du Colombier gx_device_finalize, st_device_forward);
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier /* ---------------- Generic procedures ---------------- */
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier /* Forward declarations */
60*593dc095SDavid du Colombier private int get_dev_target(gx_device **, gx_device *);
617dd7cddfSDavid du Colombier
62*593dc095SDavid du Colombier private int get_target_info(gx_device *);
63*593dc095SDavid du Colombier private gx_color_index x_alt_map_color(gx_device *, gx_color_index);
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier /* Clear the color mapping cache. */
667dd7cddfSDavid du Colombier private void
x_clear_color_cache(gx_device * dev)677dd7cddfSDavid du Colombier x_clear_color_cache(gx_device /*gx_device_X_wrapper */ * dev)
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier gx_device_X_wrapper *xdev = (gx_device_X_wrapper *) dev;
707dd7cddfSDavid du Colombier int i;
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier for (i = 0; i < countof(xdev->color_cache); ++i)
737dd7cddfSDavid du Colombier xdev->color_cache[i] = gx_no_color_index;
747dd7cddfSDavid du Colombier gx_device_decache_colors(dev);
757dd7cddfSDavid du Colombier }
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier /* "Wrappers" for driver procedures */
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier private int
x_wrap_open(gx_device * dev)807dd7cddfSDavid du Colombier x_wrap_open(gx_device * dev)
817dd7cddfSDavid du Colombier {
827dd7cddfSDavid du Colombier gx_device *tdev;
837dd7cddfSDavid du Colombier int rcode, code;
847dd7cddfSDavid du Colombier
85*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
86*593dc095SDavid du Colombier return code;
877dd7cddfSDavid du Colombier rcode = (*dev_proc(tdev, open_device)) (tdev);
887dd7cddfSDavid du Colombier if (rcode < 0)
897dd7cddfSDavid du Colombier return rcode;
907dd7cddfSDavid du Colombier tdev->is_open = true;
917dd7cddfSDavid du Colombier code = get_target_info(dev);
927dd7cddfSDavid du Colombier return (code < 0 ? code : rcode);
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier
957dd7cddfSDavid du Colombier private int
x_forward_sync_output(gx_device * dev)967dd7cddfSDavid du Colombier x_forward_sync_output(gx_device * dev)
977dd7cddfSDavid du Colombier {
987dd7cddfSDavid du Colombier gx_device *tdev;
99*593dc095SDavid du Colombier int code;
1007dd7cddfSDavid du Colombier
101*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
102*593dc095SDavid du Colombier return code;
1037dd7cddfSDavid du Colombier return (*dev_proc(tdev, sync_output)) (tdev);
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier
1067dd7cddfSDavid du Colombier private int
x_forward_output_page(gx_device * dev,int num_copies,int flush)1077dd7cddfSDavid du Colombier x_forward_output_page(gx_device * dev, int num_copies, int flush)
1087dd7cddfSDavid du Colombier {
1097dd7cddfSDavid du Colombier gx_device *tdev;
110*593dc095SDavid du Colombier int code;
1117dd7cddfSDavid du Colombier
112*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
113*593dc095SDavid du Colombier return code;
1147dd7cddfSDavid du Colombier return (*dev_proc(tdev, output_page)) (tdev, num_copies, flush);
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier
1177dd7cddfSDavid du Colombier private int
x_wrap_close(gx_device * dev)1187dd7cddfSDavid du Colombier x_wrap_close(gx_device * dev)
1197dd7cddfSDavid du Colombier {
1207dd7cddfSDavid du Colombier /*
1217dd7cddfSDavid du Colombier * The underlying x11 device will be closed and freed as soon as there
1227dd7cddfSDavid du Colombier * are no more pointers to it, which normally occurs in the next
1237dd7cddfSDavid du Colombier * statement.
1247dd7cddfSDavid du Colombier */
1257dd7cddfSDavid du Colombier gx_device_set_target((gx_device_forward *)dev, NULL);
1267dd7cddfSDavid du Colombier x_clear_color_cache(dev);
1277dd7cddfSDavid du Colombier return 0;
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier
1307dd7cddfSDavid du Colombier private int
x_wrap_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])1317dd7cddfSDavid du Colombier x_wrap_map_color_rgb(gx_device * dev, gx_color_index color,
1327dd7cddfSDavid du Colombier gx_color_value prgb[3])
1337dd7cddfSDavid du Colombier {
1347dd7cddfSDavid du Colombier gx_device *tdev;
135*593dc095SDavid du Colombier int code;
1367dd7cddfSDavid du Colombier
137*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
138*593dc095SDavid du Colombier return code;
1397dd7cddfSDavid du Colombier return (*dev_proc(tdev, map_color_rgb)) (tdev,
1407dd7cddfSDavid du Colombier x_alt_map_color(dev, color),
1417dd7cddfSDavid du Colombier prgb);
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier
1447dd7cddfSDavid du Colombier private int
x_wrap_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)1457dd7cddfSDavid du Colombier x_wrap_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
1467dd7cddfSDavid du Colombier gx_color_index color)
1477dd7cddfSDavid du Colombier {
1487dd7cddfSDavid du Colombier gx_device *tdev;
149*593dc095SDavid du Colombier int code;
1507dd7cddfSDavid du Colombier
151*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
152*593dc095SDavid du Colombier return code;
1537dd7cddfSDavid du Colombier return (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, w, h,
1547dd7cddfSDavid du Colombier x_alt_map_color(dev, color));
1557dd7cddfSDavid du Colombier }
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier private int
x_wrap_copy_mono(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)1587dd7cddfSDavid du Colombier x_wrap_copy_mono(gx_device * dev,
1597dd7cddfSDavid du Colombier const byte * base, int sourcex, int raster, gx_bitmap_id id,
1607dd7cddfSDavid du Colombier int x, int y, int w, int h,
1617dd7cddfSDavid du Colombier gx_color_index zero, gx_color_index one)
1627dd7cddfSDavid du Colombier {
1637dd7cddfSDavid du Colombier gx_device *tdev;
164*593dc095SDavid du Colombier int code;
1657dd7cddfSDavid du Colombier
166*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
167*593dc095SDavid du Colombier return code;
1687dd7cddfSDavid du Colombier return (*dev_proc(tdev, copy_mono)) (tdev, base, sourcex, raster, id,
1697dd7cddfSDavid du Colombier x, y, w, h,
1707dd7cddfSDavid du Colombier x_alt_map_color(dev, zero),
1717dd7cddfSDavid du Colombier x_alt_map_color(dev, one));
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier }
1747dd7cddfSDavid du Colombier
1757dd7cddfSDavid du Colombier private int
x_wrap_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)1767dd7cddfSDavid du Colombier x_wrap_copy_color(gx_device * dev, const byte * base, int sourcex,
1777dd7cddfSDavid du Colombier int raster, gx_bitmap_id id, int x, int y, int w, int h)
1787dd7cddfSDavid du Colombier {
1797dd7cddfSDavid du Colombier gx_device *tdev;
1807dd7cddfSDavid du Colombier
1817dd7cddfSDavid du Colombier #define mapped_bytes 480 /* must be a multiple of 3 & 4 */
1827dd7cddfSDavid du Colombier int depth_bytes, source_bits;
1837dd7cddfSDavid du Colombier int block_w, block_h;
1847dd7cddfSDavid du Colombier int xblock, yblock;
1857dd7cddfSDavid du Colombier byte mapped[mapped_bytes];
186*593dc095SDavid du Colombier int code;
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
189*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
190*593dc095SDavid du Colombier return code;
1917dd7cddfSDavid du Colombier /* Device pixels must be an integral number of bytes. */
1927dd7cddfSDavid du Colombier if (tdev->color_info.depth & 7)
1937dd7cddfSDavid du Colombier return gx_default_copy_color(dev, base, sourcex, raster, id,
1947dd7cddfSDavid du Colombier x, y, w, h);
1957dd7cddfSDavid du Colombier depth_bytes = tdev->color_info.depth >> 3;
1967dd7cddfSDavid du Colombier source_bits = dev->color_info.depth;
1977dd7cddfSDavid du Colombier {
1987dd7cddfSDavid du Colombier int mapped_pixels = mapped_bytes / depth_bytes;
1997dd7cddfSDavid du Colombier
2007dd7cddfSDavid du Colombier if (w > mapped_pixels >> 1)
2017dd7cddfSDavid du Colombier block_w = min(w, mapped_pixels), block_h = 1;
2027dd7cddfSDavid du Colombier else
2037dd7cddfSDavid du Colombier block_w = w, block_h = mapped_pixels / w;
2047dd7cddfSDavid du Colombier }
2057dd7cddfSDavid du Colombier for (yblock = y; yblock < y + h; yblock += block_h)
2067dd7cddfSDavid du Colombier for (xblock = x; xblock < x + w; xblock += block_w) {
2077dd7cddfSDavid du Colombier byte *p = mapped;
2087dd7cddfSDavid du Colombier int xend = min(xblock + block_w, x + w);
2097dd7cddfSDavid du Colombier int yend = min(yblock + block_h, y + h);
2107dd7cddfSDavid du Colombier int xcur, ycur;
2117dd7cddfSDavid du Colombier int code;
2127dd7cddfSDavid du Colombier
2137dd7cddfSDavid du Colombier for (ycur = yblock; ycur < yend; ++ycur)
2147dd7cddfSDavid du Colombier for (xcur = xblock; xcur < xend; ++xcur) {
2157dd7cddfSDavid du Colombier int sbit = (xcur - x + sourcex) * source_bits;
2167dd7cddfSDavid du Colombier uint sbyte =
2177dd7cddfSDavid du Colombier base[(ycur - y) * raster + (sbit >> 3)];
2187dd7cddfSDavid du Colombier uint spixel =
2197dd7cddfSDavid du Colombier ((sbyte << (sbit & 7)) & 0xff) >> (8 - source_bits);
2207dd7cddfSDavid du Colombier gx_color_index cindex =
2217dd7cddfSDavid du Colombier ((gx_device_X_wrapper *) dev)->color_cache[spixel];
2227dd7cddfSDavid du Colombier
2237dd7cddfSDavid du Colombier if (cindex == gx_no_color_index)
2247dd7cddfSDavid du Colombier cindex = x_alt_map_color(dev, spixel);
2257dd7cddfSDavid du Colombier switch (depth_bytes) {
2267dd7cddfSDavid du Colombier case 4:
2277dd7cddfSDavid du Colombier *p++ = (byte) (cindex >> 24);
2287dd7cddfSDavid du Colombier case 3:
2297dd7cddfSDavid du Colombier *p++ = (byte) (cindex >> 16);
2307dd7cddfSDavid du Colombier case 2:
2317dd7cddfSDavid du Colombier *p++ = (byte) (cindex >> 8);
2327dd7cddfSDavid du Colombier default /*case 1 */ :
2337dd7cddfSDavid du Colombier *p++ = (byte) cindex;
2347dd7cddfSDavid du Colombier }
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier code = (*dev_proc(tdev, copy_color))
2377dd7cddfSDavid du Colombier (tdev, mapped, 0, (xend - xblock) * depth_bytes, gx_no_bitmap_id,
2387dd7cddfSDavid du Colombier xblock, yblock, xend - xblock, yend - yblock);
2397dd7cddfSDavid du Colombier if (code < 0)
2407dd7cddfSDavid du Colombier return code;
2417dd7cddfSDavid du Colombier }
2427dd7cddfSDavid du Colombier return 0;
2437dd7cddfSDavid du Colombier }
2447dd7cddfSDavid du Colombier
2457dd7cddfSDavid du Colombier
2467dd7cddfSDavid du Colombier private int
x_forward_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)2477dd7cddfSDavid du Colombier x_forward_copy_color(gx_device * dev, const byte * base, int sourcex,
2487dd7cddfSDavid du Colombier int raster, gx_bitmap_id id, int x, int y, int w, int h)
2497dd7cddfSDavid du Colombier {
2507dd7cddfSDavid du Colombier gx_device *tdev;
251*593dc095SDavid du Colombier int code;
2527dd7cddfSDavid du Colombier
253*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
254*593dc095SDavid du Colombier return code;
2557dd7cddfSDavid du Colombier return (*dev_proc(tdev, copy_color)) (tdev, base, sourcex, raster, id,
2567dd7cddfSDavid du Colombier x, y, w, h);
2577dd7cddfSDavid du Colombier }
2587dd7cddfSDavid du Colombier
2597dd7cddfSDavid du Colombier private int
x_forward_get_bits(gx_device * dev,int y,byte * str,byte ** actual_data)2607dd7cddfSDavid du Colombier x_forward_get_bits(gx_device * dev, int y, byte * str, byte ** actual_data)
2617dd7cddfSDavid du Colombier {
2627dd7cddfSDavid du Colombier gx_device *tdev;
263*593dc095SDavid du Colombier int code;
2647dd7cddfSDavid du Colombier
265*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
266*593dc095SDavid du Colombier return code;
2677dd7cddfSDavid du Colombier return (*dev_proc(tdev, get_bits)) (tdev, y, str, actual_data);
2687dd7cddfSDavid du Colombier }
2697dd7cddfSDavid du Colombier
2707dd7cddfSDavid du Colombier private int
x_wrap_get_bits(gx_device * dev,int y,byte * str,byte ** actual_data)2717dd7cddfSDavid du Colombier x_wrap_get_bits(gx_device * dev, int y, byte * str, byte ** actual_data)
2727dd7cddfSDavid du Colombier {
2737dd7cddfSDavid du Colombier int depth = dev->color_info.depth;
2747dd7cddfSDavid du Colombier gx_device *tdev;
2757dd7cddfSDavid du Colombier int width;
2767dd7cddfSDavid du Colombier int sdepth;
2777dd7cddfSDavid du Colombier byte smask;
2787dd7cddfSDavid du Colombier uint dsize;
2797dd7cddfSDavid du Colombier gs_memory_t *mem = dev->memory;
2807dd7cddfSDavid du Colombier byte *row;
2817dd7cddfSDavid du Colombier byte *base;
2827dd7cddfSDavid du Colombier int code;
2837dd7cddfSDavid du Colombier gx_color_index pixel_in = gx_no_color_index;
2847dd7cddfSDavid du Colombier /*
2857dd7cddfSDavid du Colombier * The following initialization is unnecessary: since no pixel has a
2867dd7cddfSDavid du Colombier * value of gx_no_color_index, the test pixel != pixel_in will always
2877dd7cddfSDavid du Colombier * succeed the first time through the loop below, so pixel_out will
2887dd7cddfSDavid du Colombier * always be set before it is used. We initialize pixel_out solely to
2897dd7cddfSDavid du Colombier * suppress bogus warning messages from certain compilers.
2907dd7cddfSDavid du Colombier */
2917dd7cddfSDavid du Colombier gx_color_index pixel_out = 0;
2927dd7cddfSDavid du Colombier int xi;
2937dd7cddfSDavid du Colombier int sbit;
2947dd7cddfSDavid du Colombier
2957dd7cddfSDavid du Colombier DECLARE_LINE_ACCUM(str, depth, 0);
2967dd7cddfSDavid du Colombier
297*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
298*593dc095SDavid du Colombier return code;
2997dd7cddfSDavid du Colombier width = tdev->width;
3007dd7cddfSDavid du Colombier sdepth = tdev->color_info.depth;
3017dd7cddfSDavid du Colombier smask = (sdepth <= 8 ? (1 << sdepth) - 1 : 0xff);
3027dd7cddfSDavid du Colombier dsize = (width * sdepth + 7) / 8;
3037dd7cddfSDavid du Colombier row = gs_alloc_bytes(mem, dsize, "x_wrap_get_bits");
3047dd7cddfSDavid du Colombier if (row == 0)
3057dd7cddfSDavid du Colombier return_error(gs_error_VMerror);
3067dd7cddfSDavid du Colombier code = (*dev_proc(tdev, get_bits)) (tdev, y, row, &base);
3077dd7cddfSDavid du Colombier if (code < 0)
3087dd7cddfSDavid du Colombier goto gx;
3097dd7cddfSDavid du Colombier for (sbit = 0, xi = 0; xi < width; sbit += sdepth, ++xi) {
3107dd7cddfSDavid du Colombier const byte *sptr = base + (sbit >> 3);
3117dd7cddfSDavid du Colombier gx_color_index pixel;
3127dd7cddfSDavid du Colombier gx_color_value rgb[3];
3137dd7cddfSDavid du Colombier int i;
3147dd7cddfSDavid du Colombier
3157dd7cddfSDavid du Colombier if (sdepth <= 8)
3167dd7cddfSDavid du Colombier pixel = (*sptr >> (8 - sdepth - (sbit & 7))) & smask;
3177dd7cddfSDavid du Colombier else {
3187dd7cddfSDavid du Colombier pixel = 0;
3197dd7cddfSDavid du Colombier for (i = 0; i < sdepth; i += 8, ++sptr)
3207dd7cddfSDavid du Colombier pixel = (pixel << 8) + *sptr;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier if (pixel != pixel_in) {
3237dd7cddfSDavid du Colombier (*dev_proc(tdev, map_color_rgb))(tdev, pixel, rgb);
3247dd7cddfSDavid du Colombier pixel_in = pixel;
3257dd7cddfSDavid du Colombier if (dev->color_info.num_components <= 3)
326*593dc095SDavid du Colombier pixel_out = (*dev_proc(dev, map_rgb_color))(dev, rgb);
3277dd7cddfSDavid du Colombier else {
3287dd7cddfSDavid du Colombier /* Convert RGB to CMYK. */
3297dd7cddfSDavid du Colombier gx_color_value c = gx_max_color_value - rgb[0];
3307dd7cddfSDavid du Colombier gx_color_value m = gx_max_color_value - rgb[1];
3317dd7cddfSDavid du Colombier gx_color_value y = gx_max_color_value - rgb[2];
3327dd7cddfSDavid du Colombier gx_color_value k = (c < m ? min(c, y) : min(m, y));
3337dd7cddfSDavid du Colombier
334*593dc095SDavid du Colombier gx_color_value cmyk[4];
335*593dc095SDavid du Colombier cmyk[0] = c - k; cmyk[1] = m - k; cmyk[2] = y - k; cmyk[3] = k;
336*593dc095SDavid du Colombier pixel_out = (*dev_proc(dev, map_cmyk_color))(dev, cmyk);
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier LINE_ACCUM(pixel_out, depth);
3407dd7cddfSDavid du Colombier }
3417dd7cddfSDavid du Colombier LINE_ACCUM_STORE(depth);
3427dd7cddfSDavid du Colombier gx:gs_free_object(mem, row, "x_wrap_get_bits");
3437dd7cddfSDavid du Colombier *actual_data = str;
3447dd7cddfSDavid du Colombier return code;
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier
3477dd7cddfSDavid du Colombier private int
x_wrap_get_params(gx_device * dev,gs_param_list * plist)3487dd7cddfSDavid du Colombier x_wrap_get_params(gx_device * dev, gs_param_list * plist)
3497dd7cddfSDavid du Colombier {
3507dd7cddfSDavid du Colombier gx_device *tdev;
3517dd7cddfSDavid du Colombier /* We assume that a get_params call has no side effects.... */
3527dd7cddfSDavid du Colombier gx_device_X save_dev;
3537dd7cddfSDavid du Colombier int ecode;
354*593dc095SDavid du Colombier int code;
3557dd7cddfSDavid du Colombier
356*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
357*593dc095SDavid du Colombier return code;
3587dd7cddfSDavid du Colombier save_dev = *(gx_device_X *) tdev;
3597dd7cddfSDavid du Colombier if (tdev->is_open)
3607dd7cddfSDavid du Colombier tdev->color_info = dev->color_info;
3617dd7cddfSDavid du Colombier tdev->dname = dev->dname;
3627dd7cddfSDavid du Colombier ecode = (*dev_proc(tdev, get_params)) (tdev, plist);
3637dd7cddfSDavid du Colombier *(gx_device_X *) tdev = save_dev;
3647dd7cddfSDavid du Colombier return ecode;
3657dd7cddfSDavid du Colombier }
3667dd7cddfSDavid du Colombier
3677dd7cddfSDavid du Colombier private int
x_wrap_put_params(gx_device * dev,gs_param_list * plist)3687dd7cddfSDavid du Colombier x_wrap_put_params(gx_device * dev, gs_param_list * plist)
3697dd7cddfSDavid du Colombier {
3707dd7cddfSDavid du Colombier gx_device *tdev;
3717dd7cddfSDavid du Colombier gx_device_color_info cinfo;
3727dd7cddfSDavid du Colombier const char *dname;
3737dd7cddfSDavid du Colombier int rcode, code;
3747dd7cddfSDavid du Colombier
375*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
376*593dc095SDavid du Colombier return code;
3777dd7cddfSDavid du Colombier /*
3787dd7cddfSDavid du Colombier * put_params will choke if we simply feed it the output of
3797dd7cddfSDavid du Colombier * get_params; we have to substitute color_info the same way.
3807dd7cddfSDavid du Colombier */
3817dd7cddfSDavid du Colombier cinfo = tdev->color_info;
3827dd7cddfSDavid du Colombier dname = tdev->dname;
3837dd7cddfSDavid du Colombier tdev->color_info = dev->color_info;
3847dd7cddfSDavid du Colombier tdev->dname = dev->dname;
3857dd7cddfSDavid du Colombier rcode = (*dev_proc(tdev, put_params)) (tdev, plist);
3867dd7cddfSDavid du Colombier tdev->color_info = cinfo;
3877dd7cddfSDavid du Colombier tdev->dname = dname;
3887dd7cddfSDavid du Colombier if (rcode < 0)
3897dd7cddfSDavid du Colombier return rcode;
3907dd7cddfSDavid du Colombier code = get_target_info(dev);
3917dd7cddfSDavid du Colombier return (code < 0 ? code : rcode);
3927dd7cddfSDavid du Colombier }
3937dd7cddfSDavid du Colombier
3947dd7cddfSDavid du Colombier /* Internal procedures */
3957dd7cddfSDavid du Colombier
3967dd7cddfSDavid du Colombier /* Get the target, creating it if necessary. */
3977dd7cddfSDavid du Colombier private int
get_dev_target(gx_device ** ptdev,gx_device * dev)3987dd7cddfSDavid du Colombier get_dev_target(gx_device ** ptdev, gx_device * dev)
3997dd7cddfSDavid du Colombier {
4007dd7cddfSDavid du Colombier gx_device *tdev = ((gx_device_forward *) dev)->target;
4017dd7cddfSDavid du Colombier
4027dd7cddfSDavid du Colombier if (tdev == 0) {
4037dd7cddfSDavid du Colombier /* Create an X device instance. */
4047dd7cddfSDavid du Colombier int code = gs_copydevice(&tdev, (const gx_device *)&gs_x11_device,
4057dd7cddfSDavid du Colombier dev->memory);
4067dd7cddfSDavid du Colombier
4077dd7cddfSDavid du Colombier if (code < 0)
4087dd7cddfSDavid du Colombier return 0;
409*593dc095SDavid du Colombier check_device_separable(tdev);
4107dd7cddfSDavid du Colombier gx_device_fill_in_procs(tdev);
4117dd7cddfSDavid du Colombier gx_device_set_target((gx_device_forward *)dev, tdev);
4127dd7cddfSDavid du Colombier x_clear_color_cache(dev);
4137dd7cddfSDavid du Colombier }
4147dd7cddfSDavid du Colombier *ptdev = tdev;
4157dd7cddfSDavid du Colombier return 0;
4167dd7cddfSDavid du Colombier }
4177dd7cddfSDavid du Colombier
4187dd7cddfSDavid du Colombier /* Copy parameters back from the target. */
4197dd7cddfSDavid du Colombier private int
get_target_info(gx_device * dev)4207dd7cddfSDavid du Colombier get_target_info(gx_device * dev)
4217dd7cddfSDavid du Colombier {
4227dd7cddfSDavid du Colombier gx_device *tdev;
423*593dc095SDavid du Colombier int code;
4247dd7cddfSDavid du Colombier
425*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
426*593dc095SDavid du Colombier return code;
4277dd7cddfSDavid du Colombier
4287dd7cddfSDavid du Colombier #define copy(m) dev->m = tdev->m;
4297dd7cddfSDavid du Colombier #define copy2(m) copy(m[0]); copy(m[1])
4307dd7cddfSDavid du Colombier #define copy4(m) copy2(m); copy(m[2]); copy(m[3])
4317dd7cddfSDavid du Colombier
4327dd7cddfSDavid du Colombier copy(width);
4337dd7cddfSDavid du Colombier copy(height);
4347dd7cddfSDavid du Colombier copy2(MediaSize);
4357dd7cddfSDavid du Colombier copy4(ImagingBBox);
4367dd7cddfSDavid du Colombier copy(ImagingBBox_set);
4377dd7cddfSDavid du Colombier copy2(HWResolution);
4387dd7cddfSDavid du Colombier copy2(MarginsHWResolution);
4397dd7cddfSDavid du Colombier copy2(Margins);
4407dd7cddfSDavid du Colombier copy4(HWMargins);
4417dd7cddfSDavid du Colombier if (dev->color_info.num_components == 3) {
4427dd7cddfSDavid du Colombier /* Leave the anti-aliasing information alone. */
4437dd7cddfSDavid du Colombier gx_device_anti_alias_info aa;
4447dd7cddfSDavid du Colombier
4457dd7cddfSDavid du Colombier aa = dev->color_info.anti_alias;
4467dd7cddfSDavid du Colombier copy(color_info);
4477dd7cddfSDavid du Colombier dev->color_info.anti_alias = aa;
4487dd7cddfSDavid du Colombier }
4497dd7cddfSDavid du Colombier
4507dd7cddfSDavid du Colombier #undef copy4
4517dd7cddfSDavid du Colombier #undef copy2
4527dd7cddfSDavid du Colombier #undef copy
4537dd7cddfSDavid du Colombier
4547dd7cddfSDavid du Colombier x_clear_color_cache(dev);
4557dd7cddfSDavid du Colombier return 0;
4567dd7cddfSDavid du Colombier }
4577dd7cddfSDavid du Colombier
4587dd7cddfSDavid du Colombier /* Map a fake CMYK or black/white color to a real X color if necessary. */
4597dd7cddfSDavid du Colombier private gx_color_index
x_alt_map_color(gx_device * dev,gx_color_index color)4607dd7cddfSDavid du Colombier x_alt_map_color(gx_device * dev, gx_color_index color)
4617dd7cddfSDavid du Colombier {
4627dd7cddfSDavid du Colombier gx_device_X_wrapper *xdev = (gx_device_X_wrapper *) dev;
4637dd7cddfSDavid du Colombier gx_device *tdev;
4647dd7cddfSDavid du Colombier gx_color_value rgb[3];
4657dd7cddfSDavid du Colombier gx_color_index cindex;
4667dd7cddfSDavid du Colombier int result;
467*593dc095SDavid du Colombier int code;
4687dd7cddfSDavid du Colombier
4697dd7cddfSDavid du Colombier if (color == gx_no_color_index)
4707dd7cddfSDavid du Colombier return color;
4717dd7cddfSDavid du Colombier if (color < 16) {
4727dd7cddfSDavid du Colombier cindex = ((gx_device_X_wrapper *) dev)->color_cache[color];
4737dd7cddfSDavid du Colombier if (cindex != gx_no_color_index)
4747dd7cddfSDavid du Colombier return cindex;
4757dd7cddfSDavid du Colombier }
476*593dc095SDavid du Colombier if ((code = get_dev_target(&tdev, dev)) < 0)
477*593dc095SDavid du Colombier return code;
4787dd7cddfSDavid du Colombier result = xdev->alt_map_color(dev, color, rgb);
4797dd7cddfSDavid du Colombier if (result >= 0)
4807dd7cddfSDavid du Colombier cindex = result;
4817dd7cddfSDavid du Colombier else
482*593dc095SDavid du Colombier cindex = dev_proc(tdev, map_rgb_color)(tdev, rgb);
4837dd7cddfSDavid du Colombier if (color < 16)
4847dd7cddfSDavid du Colombier ((gx_device_X_wrapper *) dev)->color_cache[color] = cindex;
4857dd7cddfSDavid du Colombier return cindex;
4867dd7cddfSDavid du Colombier }
4877dd7cddfSDavid du Colombier
4887dd7cddfSDavid du Colombier /* ---------------- CMYK procedures ---------------- */
4897dd7cddfSDavid du Colombier
4907dd7cddfSDavid du Colombier /* Device procedures */
4917dd7cddfSDavid du Colombier private dev_proc_open_device(x_cmyk_open);
4927dd7cddfSDavid du Colombier private dev_proc_put_params(x_cmyk_put_params);
4937dd7cddfSDavid du Colombier private dev_proc_map_cmyk_color(x_cmyk_map_cmyk_color);
4947dd7cddfSDavid du Colombier /* Extended device procedures */
4957dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(x_cmyk_alt_map_color);
4967dd7cddfSDavid du Colombier
4977dd7cddfSDavid du Colombier /* The device descriptor */
4987dd7cddfSDavid du Colombier private const gx_device_procs x_cmyk_procs = {
4997dd7cddfSDavid du Colombier x_cmyk_open,
5007dd7cddfSDavid du Colombier gx_forward_get_initial_matrix,
5017dd7cddfSDavid du Colombier x_forward_sync_output,
5027dd7cddfSDavid du Colombier x_forward_output_page,
5037dd7cddfSDavid du Colombier x_wrap_close,
5047dd7cddfSDavid du Colombier NULL, /* map_rgb_color */
5057dd7cddfSDavid du Colombier x_wrap_map_color_rgb,
5067dd7cddfSDavid du Colombier x_wrap_fill_rectangle,
5077dd7cddfSDavid du Colombier gx_default_tile_rectangle,
5087dd7cddfSDavid du Colombier x_wrap_copy_mono,
5097dd7cddfSDavid du Colombier x_wrap_copy_color,
5107dd7cddfSDavid du Colombier gx_default_draw_line,
5117dd7cddfSDavid du Colombier x_wrap_get_bits,
5127dd7cddfSDavid du Colombier x_wrap_get_params,
5137dd7cddfSDavid du Colombier x_cmyk_put_params,
5147dd7cddfSDavid du Colombier x_cmyk_map_cmyk_color,
5157dd7cddfSDavid du Colombier gx_forward_get_xfont_procs,
5167dd7cddfSDavid du Colombier gx_forward_get_xfont_device,
5177dd7cddfSDavid du Colombier NULL, /* map_rgb_alpha_color */
5187dd7cddfSDavid du Colombier gx_forward_get_page_device,
5197dd7cddfSDavid du Colombier gx_forward_get_alpha_bits,
5207dd7cddfSDavid du Colombier NULL /* copy_alpha */
5217dd7cddfSDavid du Colombier };
5227dd7cddfSDavid du Colombier
5237dd7cddfSDavid du Colombier /* The instances are public. */
5247dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11cmyk_device = {
5257dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk",
5267dd7cddfSDavid du Colombier &st_device_X_wrapper,
5277dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
5287dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
5297dd7cddfSDavid du Colombier 4, 4, 1, 1, 2, 2),
5307dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_cmyk_alt_map_color)
5317dd7cddfSDavid du Colombier };
5327dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11cmyk2_device = {
5337dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk2",
5347dd7cddfSDavid du Colombier &st_device_X_wrapper,
5357dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
5367dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
5377dd7cddfSDavid du Colombier 4, 8, 3, 3, 4, 4),
5387dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_cmyk_alt_map_color)
5397dd7cddfSDavid du Colombier };
5407dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11cmyk4_device = {
5417dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk4",
5427dd7cddfSDavid du Colombier &st_device_X_wrapper,
5437dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
5447dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
5457dd7cddfSDavid du Colombier 4, 16, 15, 15, 16, 16),
5467dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_cmyk_alt_map_color)
5477dd7cddfSDavid du Colombier };
5487dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11cmyk8_device = {
5497dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk8",
5507dd7cddfSDavid du Colombier &st_device_X_wrapper,
5517dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
5527dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
5537dd7cddfSDavid du Colombier 4, 32, 255, 255, 256, 256),
5547dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_cmyk_alt_map_color)
5557dd7cddfSDavid du Colombier };
5567dd7cddfSDavid du Colombier
5577dd7cddfSDavid du Colombier /* Map a fake color to RGB. */
5587dd7cddfSDavid du Colombier private int
x_cmyk_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])5597dd7cddfSDavid du Colombier x_cmyk_alt_map_color(gx_device * dev, gx_color_index color,
5607dd7cddfSDavid du Colombier gx_color_value rgb[3])
5617dd7cddfSDavid du Colombier {
5627dd7cddfSDavid du Colombier int shift = dev->color_info.depth >> 2;
5637dd7cddfSDavid du Colombier int mask = (1 << shift) - 1;
5647dd7cddfSDavid du Colombier /* The following division is guaranteed exact. */
5657dd7cddfSDavid du Colombier gx_color_value scale = gx_max_color_value / mask;
5667dd7cddfSDavid du Colombier int cw = ~color & mask;
5677dd7cddfSDavid du Colombier int cb = cw - ((color >> shift) & mask);
5687dd7cddfSDavid du Colombier int cg = cw - ((color >> (shift * 2)) & mask);
5697dd7cddfSDavid du Colombier int cr = cw - ((color >> (shift * 3)) & mask);
5707dd7cddfSDavid du Colombier
5717dd7cddfSDavid du Colombier rgb[0] = max(cr, 0) * scale;
5727dd7cddfSDavid du Colombier rgb[1] = max(cg, 0) * scale;
5737dd7cddfSDavid du Colombier rgb[2] = max(cb, 0) * scale;
5747dd7cddfSDavid du Colombier return -1;
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier
5777dd7cddfSDavid du Colombier /* Set color mapping procedures */
5787dd7cddfSDavid du Colombier private void
x_cmyk_set_procs(gx_device * dev)5797dd7cddfSDavid du Colombier x_cmyk_set_procs(gx_device *dev)
5807dd7cddfSDavid du Colombier {
5817dd7cddfSDavid du Colombier if (dev->color_info.depth == 4) {
5827dd7cddfSDavid du Colombier set_dev_proc(dev, map_cmyk_color, cmyk_1bit_map_cmyk_color);
5837dd7cddfSDavid du Colombier } else {
5847dd7cddfSDavid du Colombier set_dev_proc(dev, map_cmyk_color, x_cmyk_map_cmyk_color);
5857dd7cddfSDavid du Colombier }
5867dd7cddfSDavid du Colombier }
5877dd7cddfSDavid du Colombier
5887dd7cddfSDavid du Colombier /* Device procedures */
5897dd7cddfSDavid du Colombier
5907dd7cddfSDavid du Colombier private int
x_cmyk_open(gx_device * dev)5917dd7cddfSDavid du Colombier x_cmyk_open(gx_device *dev)
5927dd7cddfSDavid du Colombier {
5937dd7cddfSDavid du Colombier int code = x_wrap_open(dev);
5947dd7cddfSDavid du Colombier
5957dd7cddfSDavid du Colombier if (code >= 0)
5967dd7cddfSDavid du Colombier x_cmyk_set_procs(dev);
5977dd7cddfSDavid du Colombier return code;
5987dd7cddfSDavid du Colombier }
5997dd7cddfSDavid du Colombier
6007dd7cddfSDavid du Colombier private int
x_cmyk_put_params(gx_device * dev,gs_param_list * plist)6017dd7cddfSDavid du Colombier x_cmyk_put_params(gx_device * dev, gs_param_list * plist)
6027dd7cddfSDavid du Colombier {
6037dd7cddfSDavid du Colombier int code = x_wrap_put_params(dev, plist);
6047dd7cddfSDavid du Colombier
6057dd7cddfSDavid du Colombier if (code >= 0)
6067dd7cddfSDavid du Colombier x_cmyk_set_procs(dev);
6077dd7cddfSDavid du Colombier return code;
6087dd7cddfSDavid du Colombier }
6097dd7cddfSDavid du Colombier
6107dd7cddfSDavid du Colombier private gx_color_index
x_cmyk_map_cmyk_color(gx_device * dev,const gx_color_value cv[])611*593dc095SDavid du Colombier x_cmyk_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
6127dd7cddfSDavid du Colombier {
6137dd7cddfSDavid du Colombier int shift = dev->color_info.depth >> 2;
614*593dc095SDavid du Colombier gx_color_index pixel = cv[0] >> (gx_color_value_bits - shift);
615*593dc095SDavid du Colombier gx_color_value c, m, y, k;
616*593dc095SDavid du Colombier c = cv[0]; m = cv[1]; y = cv[2]; k = cv[3];
6177dd7cddfSDavid du Colombier pixel = (pixel << shift) | (m >> (gx_color_value_bits - shift));
6187dd7cddfSDavid du Colombier pixel = (pixel << shift) | (y >> (gx_color_value_bits - shift));
6197dd7cddfSDavid du Colombier return (pixel << shift) | (k >> (gx_color_value_bits - shift));
6207dd7cddfSDavid du Colombier }
6217dd7cddfSDavid du Colombier
6227dd7cddfSDavid du Colombier /* ---------------- Black-and-white procedures ---------------- */
6237dd7cddfSDavid du Colombier
6247dd7cddfSDavid du Colombier /* Extended device procedures */
6257dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(x_mono_alt_map_color);
6267dd7cddfSDavid du Colombier
6277dd7cddfSDavid du Colombier /* The device descriptor */
6287dd7cddfSDavid du Colombier private const gx_device_procs x_mono_procs = {
6297dd7cddfSDavid du Colombier x_wrap_open,
6307dd7cddfSDavid du Colombier gx_forward_get_initial_matrix,
6317dd7cddfSDavid du Colombier x_forward_sync_output,
6327dd7cddfSDavid du Colombier x_forward_output_page,
6337dd7cddfSDavid du Colombier x_wrap_close,
6347dd7cddfSDavid du Colombier gx_default_b_w_map_rgb_color,
6357dd7cddfSDavid du Colombier x_wrap_map_color_rgb,
6367dd7cddfSDavid du Colombier x_wrap_fill_rectangle,
6377dd7cddfSDavid du Colombier gx_default_tile_rectangle,
6387dd7cddfSDavid du Colombier x_wrap_copy_mono,
6397dd7cddfSDavid du Colombier gx_default_copy_color, /* this is fast for the 1-bit case */
6407dd7cddfSDavid du Colombier gx_default_draw_line,
6417dd7cddfSDavid du Colombier x_wrap_get_bits,
6427dd7cddfSDavid du Colombier x_wrap_get_params,
6437dd7cddfSDavid du Colombier x_wrap_put_params,
6447dd7cddfSDavid du Colombier gx_default_map_cmyk_color,
6457dd7cddfSDavid du Colombier gx_forward_get_xfont_procs,
6467dd7cddfSDavid du Colombier gx_forward_get_xfont_device,
6477dd7cddfSDavid du Colombier NULL, /* map_rgb_alpha_color */
6487dd7cddfSDavid du Colombier gx_forward_get_page_device,
6497dd7cddfSDavid du Colombier gx_forward_get_alpha_bits,
6507dd7cddfSDavid du Colombier NULL /* copy_alpha */
6517dd7cddfSDavid du Colombier };
6527dd7cddfSDavid du Colombier
6537dd7cddfSDavid du Colombier /* The instance is public. */
6547dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11mono_device = {
6557dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_mono_procs, "x11mono",
6567dd7cddfSDavid du Colombier &st_device_X_wrapper,
6577dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
6587dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
6597dd7cddfSDavid du Colombier 1, 1, 1, 0, 2, 0),
6607dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_mono_alt_map_color)
6617dd7cddfSDavid du Colombier };
6627dd7cddfSDavid du Colombier
6637dd7cddfSDavid du Colombier /* Map a fake color to RGB. */
6647dd7cddfSDavid du Colombier private int
x_mono_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])6657dd7cddfSDavid du Colombier x_mono_alt_map_color(gx_device * dev, gx_color_index color,
6667dd7cddfSDavid du Colombier gx_color_value rgb[3])
6677dd7cddfSDavid du Colombier {
6687dd7cddfSDavid du Colombier rgb[0] = rgb[1] = rgb[2] = (color ? 0 : gx_max_color_value);
6697dd7cddfSDavid du Colombier return -1;
6707dd7cddfSDavid du Colombier }
6717dd7cddfSDavid du Colombier
6727dd7cddfSDavid du Colombier /* ---------------- 2- and 4-bit gray-scale procedures ---------------- */
6737dd7cddfSDavid du Colombier
6747dd7cddfSDavid du Colombier /* Extended device procedures */
6757dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(x_gray_alt_map_color);
6767dd7cddfSDavid du Colombier
6777dd7cddfSDavid du Colombier /* The device descriptor */
6787dd7cddfSDavid du Colombier private const gx_device_procs x_gray_procs = {
6797dd7cddfSDavid du Colombier x_wrap_open,
6807dd7cddfSDavid du Colombier gx_forward_get_initial_matrix,
6817dd7cddfSDavid du Colombier x_forward_sync_output,
6827dd7cddfSDavid du Colombier x_forward_output_page,
6837dd7cddfSDavid du Colombier x_wrap_close,
6847dd7cddfSDavid du Colombier gx_default_gray_map_rgb_color,
6857dd7cddfSDavid du Colombier x_wrap_map_color_rgb,
6867dd7cddfSDavid du Colombier x_wrap_fill_rectangle,
6877dd7cddfSDavid du Colombier gx_default_tile_rectangle,
6887dd7cddfSDavid du Colombier x_wrap_copy_mono,
6897dd7cddfSDavid du Colombier x_wrap_copy_color,
6907dd7cddfSDavid du Colombier gx_default_draw_line,
6917dd7cddfSDavid du Colombier x_wrap_get_bits,
6927dd7cddfSDavid du Colombier x_wrap_get_params,
6937dd7cddfSDavid du Colombier x_wrap_put_params,
6947dd7cddfSDavid du Colombier gx_default_map_cmyk_color,
6957dd7cddfSDavid du Colombier gx_forward_get_xfont_procs,
6967dd7cddfSDavid du Colombier gx_forward_get_xfont_device,
6977dd7cddfSDavid du Colombier NULL, /* map_rgb_alpha_color */
6987dd7cddfSDavid du Colombier gx_forward_get_page_device,
6997dd7cddfSDavid du Colombier gx_forward_get_alpha_bits,
7007dd7cddfSDavid du Colombier NULL /* copy_alpha */
7017dd7cddfSDavid du Colombier };
7027dd7cddfSDavid du Colombier
7037dd7cddfSDavid du Colombier /* The instances are public. */
7047dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11gray2_device = {
7057dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_gray_procs, "x11gray2",
7067dd7cddfSDavid du Colombier &st_device_X_wrapper,
7077dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
7087dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
7097dd7cddfSDavid du Colombier 1, 2, 3, 0, 4, 0),
7107dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_gray_alt_map_color)
7117dd7cddfSDavid du Colombier };
7127dd7cddfSDavid du Colombier
7137dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11gray4_device = {
7147dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_gray_procs, "x11gray4",
7157dd7cddfSDavid du Colombier &st_device_X_wrapper,
7167dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
7177dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
7187dd7cddfSDavid du Colombier 1, 4, 15, 0, 16, 0),
7197dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_gray_alt_map_color)
7207dd7cddfSDavid du Colombier };
7217dd7cddfSDavid du Colombier
7227dd7cddfSDavid du Colombier /* Map a fake color to RGB. */
7237dd7cddfSDavid du Colombier private int
x_gray_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])7247dd7cddfSDavid du Colombier x_gray_alt_map_color(gx_device * dev, gx_color_index color,
7257dd7cddfSDavid du Colombier gx_color_value rgb[3])
7267dd7cddfSDavid du Colombier {
7277dd7cddfSDavid du Colombier rgb[0] = rgb[1] = rgb[2] =
7287dd7cddfSDavid du Colombier color * gx_max_color_value / dev->color_info.max_gray;
7297dd7cddfSDavid du Colombier return -1;
7307dd7cddfSDavid du Colombier }
7317dd7cddfSDavid du Colombier
7327dd7cddfSDavid du Colombier /* Device procedures */
7337dd7cddfSDavid du Colombier
7347dd7cddfSDavid du Colombier /* We encode a complemented alpha value in the top 8 bits of the */
7357dd7cddfSDavid du Colombier /* device color. */
7367dd7cddfSDavid du Colombier private gx_color_index
x_alpha_map_rgb_alpha_color(gx_device * dev,gx_color_value r,gx_color_value g,gx_color_value b,gx_color_value alpha)7377dd7cddfSDavid du Colombier x_alpha_map_rgb_alpha_color(gx_device * dev,
7387dd7cddfSDavid du Colombier gx_color_value r, gx_color_value g, gx_color_value b, gx_color_value alpha)
7397dd7cddfSDavid du Colombier {
740*593dc095SDavid du Colombier gx_color_index color;
741*593dc095SDavid du Colombier gx_color_value cv[3];
7427dd7cddfSDavid du Colombier byte abyte = alpha >> (gx_color_value_bits - 8);
743*593dc095SDavid du Colombier cv[0] = r; cv[1] = g; cv[2] = b;
744*593dc095SDavid du Colombier color = gx_forward_map_rgb_color(dev, cv);
7457dd7cddfSDavid du Colombier return (abyte == 0 ? (gx_color_index)0xff << 24 :
7467dd7cddfSDavid du Colombier ((gx_color_index) (abyte ^ 0xff) << 24) + color);
7477dd7cddfSDavid du Colombier }
7487dd7cddfSDavid du Colombier
7497dd7cddfSDavid du Colombier /* ---------------- Permuted RGB16/32 procedures ---------------- */
7507dd7cddfSDavid du Colombier
7517dd7cddfSDavid du Colombier /* Device procedures */
7527dd7cddfSDavid du Colombier private dev_proc_map_rgb_color(x_rg16x_map_rgb_color);
7537dd7cddfSDavid du Colombier private dev_proc_map_rgb_color(x_rg32x_map_rgb_color);
7547dd7cddfSDavid du Colombier /* Extended device procedures */
7557dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(x_rg16x_alt_map_color);
7567dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(x_rg32x_alt_map_color);
7577dd7cddfSDavid du Colombier
7587dd7cddfSDavid du Colombier /* The device descriptor */
7597dd7cddfSDavid du Colombier #define RGBX_PROCS(map_rgb_proc)\
7607dd7cddfSDavid du Colombier x_wrap_open,\
7617dd7cddfSDavid du Colombier gx_forward_get_initial_matrix,\
7627dd7cddfSDavid du Colombier x_forward_sync_output,\
7637dd7cddfSDavid du Colombier x_forward_output_page,\
7647dd7cddfSDavid du Colombier x_wrap_close,\
7657dd7cddfSDavid du Colombier map_rgb_proc, /* differs */\
7667dd7cddfSDavid du Colombier x_wrap_map_color_rgb,\
7677dd7cddfSDavid du Colombier x_wrap_fill_rectangle,\
7687dd7cddfSDavid du Colombier gx_default_tile_rectangle,\
7697dd7cddfSDavid du Colombier x_wrap_copy_mono,\
7707dd7cddfSDavid du Colombier x_forward_copy_color,\
7717dd7cddfSDavid du Colombier gx_default_draw_line,\
7727dd7cddfSDavid du Colombier x_forward_get_bits,\
7737dd7cddfSDavid du Colombier x_wrap_get_params,\
7747dd7cddfSDavid du Colombier x_wrap_put_params,\
7757dd7cddfSDavid du Colombier gx_forward_map_cmyk_color,\
7767dd7cddfSDavid du Colombier gx_forward_get_xfont_procs,\
7777dd7cddfSDavid du Colombier gx_forward_get_xfont_device,\
7787dd7cddfSDavid du Colombier x_alpha_map_rgb_alpha_color,\
7797dd7cddfSDavid du Colombier gx_forward_get_page_device,\
7807dd7cddfSDavid du Colombier gx_default_get_alpha_bits,\
7817dd7cddfSDavid du Colombier gx_default_copy_alpha
7827dd7cddfSDavid du Colombier
7837dd7cddfSDavid du Colombier private const gx_device_procs x_rg16x_procs = {
7847dd7cddfSDavid du Colombier RGBX_PROCS(x_rg16x_map_rgb_color)
7857dd7cddfSDavid du Colombier };
7867dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11rg16x_device = {
7877dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_rg16x_procs, "x11rg16x",
7887dd7cddfSDavid du Colombier &st_device_X_wrapper,
7897dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
7907dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
7917dd7cddfSDavid du Colombier 3, 16, 31, 31, 32, 32),
7927dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_rg16x_alt_map_color)
7937dd7cddfSDavid du Colombier };
7947dd7cddfSDavid du Colombier
7957dd7cddfSDavid du Colombier private const gx_device_procs x_rg32x_procs = {
7967dd7cddfSDavid du Colombier RGBX_PROCS(x_rg32x_map_rgb_color)
7977dd7cddfSDavid du Colombier };
7987dd7cddfSDavid du Colombier const gx_device_X_wrapper gs_x11rg32x_device = {
7997dd7cddfSDavid du Colombier std_device_dci_type_body(gx_device_X_wrapper, &x_rg32x_procs, "x11rg32x",
8007dd7cddfSDavid du Colombier &st_device_X_wrapper,
8017dd7cddfSDavid du Colombier FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
8027dd7cddfSDavid du Colombier FAKE_RES, FAKE_RES, /* x and y density (nominal) */
8037dd7cddfSDavid du Colombier 3, 32, 1023, 1023, 1024, 1024),
8047dd7cddfSDavid du Colombier X_WRAPPER_DATA(x_rg32x_alt_map_color)
8057dd7cddfSDavid du Colombier };
8067dd7cddfSDavid du Colombier
8077dd7cddfSDavid du Colombier /* Map RGB to a fake color. */
8087dd7cddfSDavid du Colombier private gx_color_index
x_rg16x_map_rgb_color(gx_device * dev,const gx_color_value cv[])809*593dc095SDavid du Colombier x_rg16x_map_rgb_color(gx_device * dev, const gx_color_value cv[])
8107dd7cddfSDavid du Colombier {
8117dd7cddfSDavid du Colombier /* Permute the colors to G5/B5/R6. */
812*593dc095SDavid du Colombier gx_color_value r, g, b;
813*593dc095SDavid du Colombier r = cv[0]; g = cv[1]; b = cv[2];
8147dd7cddfSDavid du Colombier return (r >> (gx_color_value_bits - 6)) +
8157dd7cddfSDavid du Colombier ((g >> (gx_color_value_bits - 5)) << 11) +
8167dd7cddfSDavid du Colombier ((b >> (gx_color_value_bits - 5)) << 6);
8177dd7cddfSDavid du Colombier }
8187dd7cddfSDavid du Colombier private gx_color_index
x_rg32x_map_rgb_color(gx_device * dev,const gx_color_value cv[])819*593dc095SDavid du Colombier x_rg32x_map_rgb_color(gx_device * dev, const gx_color_value cv[])
8207dd7cddfSDavid du Colombier {
8217dd7cddfSDavid du Colombier /* Permute the colors to G11/B10/R11. */
822*593dc095SDavid du Colombier gx_color_value r, g, b;
823*593dc095SDavid du Colombier r = cv[0]; g = cv[1]; b = cv[2];
8247dd7cddfSDavid du Colombier return (r >> (gx_color_value_bits - 11)) +
8257dd7cddfSDavid du Colombier ((gx_color_index)(g >> (gx_color_value_bits - 11)) << 21) +
8267dd7cddfSDavid du Colombier ((gx_color_index)(b >> (gx_color_value_bits - 10)) << 11);
8277dd7cddfSDavid du Colombier }
8287dd7cddfSDavid du Colombier
8297dd7cddfSDavid du Colombier /* Map a fake color to RGB. */
8307dd7cddfSDavid du Colombier private int
x_rg16x_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])8317dd7cddfSDavid du Colombier x_rg16x_alt_map_color(gx_device * dev, gx_color_index color,
8327dd7cddfSDavid du Colombier gx_color_value rgb[3])
8337dd7cddfSDavid du Colombier {
8347dd7cddfSDavid du Colombier rgb[0] = (color & 0x3f) * gx_max_color_value / 0x3f;
8357dd7cddfSDavid du Colombier rgb[1] = ((color >> 11) & 0x1f) * gx_max_color_value / 0x1f;
8367dd7cddfSDavid du Colombier rgb[2] = ((color >> 6) & 0x1f) * gx_max_color_value / 0x1f;
8377dd7cddfSDavid du Colombier return -1;
8387dd7cddfSDavid du Colombier }
8397dd7cddfSDavid du Colombier private int
x_rg32x_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])8407dd7cddfSDavid du Colombier x_rg32x_alt_map_color(gx_device * dev, gx_color_index color,
8417dd7cddfSDavid du Colombier gx_color_value rgb[3])
8427dd7cddfSDavid du Colombier {
8437dd7cddfSDavid du Colombier rgb[0] = (color & 0x7ff) * gx_max_color_value / 0x7ff;
8447dd7cddfSDavid du Colombier rgb[1] = ((color >> 21) & 0x7ff) * gx_max_color_value / 0x7ff;
8457dd7cddfSDavid du Colombier rgb[2] = ((color >> 11) & 0x3ff) * gx_max_color_value / 0x3ff;
8467dd7cddfSDavid du Colombier return -1;
8477dd7cddfSDavid du Colombier }
848