1 /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevxalt.c,v 1.11 2004/05/26 04:10:58 dan Exp $ */
18 /* Alternative X Windows drivers for help in driver debugging */
19 #include "gx.h" /* for gx_bitmap; includes std.h */
20 #include "math_.h"
21 #include "memory_.h"
22 #include "x_.h"
23 #include "gserrors.h"
24 #include "gsparam.h"
25 #include "gsstruct.h"
26 #include "gxdevice.h"
27 #include "gsdevice.h" /* for gs_copydevice */
28 #include "gdevx.h"
29
30 extern const gx_device_X gs_x11_device;
31
32 /*
33 * Define a forwarding device with a cache for the first 16 colors,
34 * which avoids all of the time-consuming color mapping calls for
35 * the black-and-white, 2-bit gray, and 1-bit CMYK devices defined here.
36 */
37 typedef struct {
38 gx_device_forward_common;
39 gx_color_index color_cache[16];
40 /*
41 * alt_map_color returns a value >= 0 if it maps directly to the final
42 * gx_color_index, or < 0 if it only sets RGB values.
43 */
44 dev_proc_map_color_rgb((*alt_map_color));
45 } gx_device_X_wrapper;
46 #define X_WRAPPER_DATA(amc_proc)\
47 /* gx_device_forward_common */\
48 {0}, /* std_procs */\
49 0, /* target */\
50 /* gx_device_X_wrapper */\
51 {0}, /* cache */\
52 amc_proc
53 gs_private_st_suffix_add0_final(st_device_X_wrapper, gx_device_X_wrapper,
54 "gx_device_X_wrapper", gdevx_wrapper_enum_ptrs, gdevx_wrapper_reloc_ptrs,
55 gx_device_finalize, st_device_forward);
56
57 /* ---------------- Generic procedures ---------------- */
58
59 /* Forward declarations */
60 private int get_dev_target(gx_device **, gx_device *);
61
62 private int get_target_info(gx_device *);
63 private gx_color_index x_alt_map_color(gx_device *, gx_color_index);
64
65 /* Clear the color mapping cache. */
66 private void
x_clear_color_cache(gx_device * dev)67 x_clear_color_cache(gx_device /*gx_device_X_wrapper */ * dev)
68 {
69 gx_device_X_wrapper *xdev = (gx_device_X_wrapper *) dev;
70 int i;
71
72 for (i = 0; i < countof(xdev->color_cache); ++i)
73 xdev->color_cache[i] = gx_no_color_index;
74 gx_device_decache_colors(dev);
75 }
76
77 /* "Wrappers" for driver procedures */
78
79 private int
x_wrap_open(gx_device * dev)80 x_wrap_open(gx_device * dev)
81 {
82 gx_device *tdev;
83 int rcode, code;
84
85 if ((code = get_dev_target(&tdev, dev)) < 0)
86 return code;
87 rcode = (*dev_proc(tdev, open_device)) (tdev);
88 if (rcode < 0)
89 return rcode;
90 tdev->is_open = true;
91 code = get_target_info(dev);
92 return (code < 0 ? code : rcode);
93 }
94
95 private int
x_forward_sync_output(gx_device * dev)96 x_forward_sync_output(gx_device * dev)
97 {
98 gx_device *tdev;
99 int code;
100
101 if ((code = get_dev_target(&tdev, dev)) < 0)
102 return code;
103 return (*dev_proc(tdev, sync_output)) (tdev);
104 }
105
106 private int
x_forward_output_page(gx_device * dev,int num_copies,int flush)107 x_forward_output_page(gx_device * dev, int num_copies, int flush)
108 {
109 gx_device *tdev;
110 int code;
111
112 if ((code = get_dev_target(&tdev, dev)) < 0)
113 return code;
114 return (*dev_proc(tdev, output_page)) (tdev, num_copies, flush);
115 }
116
117 private int
x_wrap_close(gx_device * dev)118 x_wrap_close(gx_device * dev)
119 {
120 /*
121 * The underlying x11 device will be closed and freed as soon as there
122 * are no more pointers to it, which normally occurs in the next
123 * statement.
124 */
125 gx_device_set_target((gx_device_forward *)dev, NULL);
126 x_clear_color_cache(dev);
127 return 0;
128 }
129
130 private int
x_wrap_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])131 x_wrap_map_color_rgb(gx_device * dev, gx_color_index color,
132 gx_color_value prgb[3])
133 {
134 gx_device *tdev;
135 int code;
136
137 if ((code = get_dev_target(&tdev, dev)) < 0)
138 return code;
139 return (*dev_proc(tdev, map_color_rgb)) (tdev,
140 x_alt_map_color(dev, color),
141 prgb);
142 }
143
144 private int
x_wrap_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)145 x_wrap_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
146 gx_color_index color)
147 {
148 gx_device *tdev;
149 int code;
150
151 if ((code = get_dev_target(&tdev, dev)) < 0)
152 return code;
153 return (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, w, h,
154 x_alt_map_color(dev, color));
155 }
156
157 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)158 x_wrap_copy_mono(gx_device * dev,
159 const byte * base, int sourcex, int raster, gx_bitmap_id id,
160 int x, int y, int w, int h,
161 gx_color_index zero, gx_color_index one)
162 {
163 gx_device *tdev;
164 int code;
165
166 if ((code = get_dev_target(&tdev, dev)) < 0)
167 return code;
168 return (*dev_proc(tdev, copy_mono)) (tdev, base, sourcex, raster, id,
169 x, y, w, h,
170 x_alt_map_color(dev, zero),
171 x_alt_map_color(dev, one));
172
173 }
174
175 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)176 x_wrap_copy_color(gx_device * dev, const byte * base, int sourcex,
177 int raster, gx_bitmap_id id, int x, int y, int w, int h)
178 {
179 gx_device *tdev;
180
181 #define mapped_bytes 480 /* must be a multiple of 3 & 4 */
182 int depth_bytes, source_bits;
183 int block_w, block_h;
184 int xblock, yblock;
185 byte mapped[mapped_bytes];
186 int code;
187
188 fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
189 if ((code = get_dev_target(&tdev, dev)) < 0)
190 return code;
191 /* Device pixels must be an integral number of bytes. */
192 if (tdev->color_info.depth & 7)
193 return gx_default_copy_color(dev, base, sourcex, raster, id,
194 x, y, w, h);
195 depth_bytes = tdev->color_info.depth >> 3;
196 source_bits = dev->color_info.depth;
197 {
198 int mapped_pixels = mapped_bytes / depth_bytes;
199
200 if (w > mapped_pixels >> 1)
201 block_w = min(w, mapped_pixels), block_h = 1;
202 else
203 block_w = w, block_h = mapped_pixels / w;
204 }
205 for (yblock = y; yblock < y + h; yblock += block_h)
206 for (xblock = x; xblock < x + w; xblock += block_w) {
207 byte *p = mapped;
208 int xend = min(xblock + block_w, x + w);
209 int yend = min(yblock + block_h, y + h);
210 int xcur, ycur;
211 int code;
212
213 for (ycur = yblock; ycur < yend; ++ycur)
214 for (xcur = xblock; xcur < xend; ++xcur) {
215 int sbit = (xcur - x + sourcex) * source_bits;
216 uint sbyte =
217 base[(ycur - y) * raster + (sbit >> 3)];
218 uint spixel =
219 ((sbyte << (sbit & 7)) & 0xff) >> (8 - source_bits);
220 gx_color_index cindex =
221 ((gx_device_X_wrapper *) dev)->color_cache[spixel];
222
223 if (cindex == gx_no_color_index)
224 cindex = x_alt_map_color(dev, spixel);
225 switch (depth_bytes) {
226 case 4:
227 *p++ = (byte) (cindex >> 24);
228 case 3:
229 *p++ = (byte) (cindex >> 16);
230 case 2:
231 *p++ = (byte) (cindex >> 8);
232 default /*case 1 */ :
233 *p++ = (byte) cindex;
234 }
235 }
236 code = (*dev_proc(tdev, copy_color))
237 (tdev, mapped, 0, (xend - xblock) * depth_bytes, gx_no_bitmap_id,
238 xblock, yblock, xend - xblock, yend - yblock);
239 if (code < 0)
240 return code;
241 }
242 return 0;
243 }
244
245
246 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)247 x_forward_copy_color(gx_device * dev, const byte * base, int sourcex,
248 int raster, gx_bitmap_id id, int x, int y, int w, int h)
249 {
250 gx_device *tdev;
251 int code;
252
253 if ((code = get_dev_target(&tdev, dev)) < 0)
254 return code;
255 return (*dev_proc(tdev, copy_color)) (tdev, base, sourcex, raster, id,
256 x, y, w, h);
257 }
258
259 private int
x_forward_get_bits(gx_device * dev,int y,byte * str,byte ** actual_data)260 x_forward_get_bits(gx_device * dev, int y, byte * str, byte ** actual_data)
261 {
262 gx_device *tdev;
263 int code;
264
265 if ((code = get_dev_target(&tdev, dev)) < 0)
266 return code;
267 return (*dev_proc(tdev, get_bits)) (tdev, y, str, actual_data);
268 }
269
270 private int
x_wrap_get_bits(gx_device * dev,int y,byte * str,byte ** actual_data)271 x_wrap_get_bits(gx_device * dev, int y, byte * str, byte ** actual_data)
272 {
273 int depth = dev->color_info.depth;
274 gx_device *tdev;
275 int width;
276 int sdepth;
277 byte smask;
278 uint dsize;
279 gs_memory_t *mem = dev->memory;
280 byte *row;
281 byte *base;
282 int code;
283 gx_color_index pixel_in = gx_no_color_index;
284 /*
285 * The following initialization is unnecessary: since no pixel has a
286 * value of gx_no_color_index, the test pixel != pixel_in will always
287 * succeed the first time through the loop below, so pixel_out will
288 * always be set before it is used. We initialize pixel_out solely to
289 * suppress bogus warning messages from certain compilers.
290 */
291 gx_color_index pixel_out = 0;
292 int xi;
293 int sbit;
294
295 DECLARE_LINE_ACCUM(str, depth, 0);
296
297 if ((code = get_dev_target(&tdev, dev)) < 0)
298 return code;
299 width = tdev->width;
300 sdepth = tdev->color_info.depth;
301 smask = (sdepth <= 8 ? (1 << sdepth) - 1 : 0xff);
302 dsize = (width * sdepth + 7) / 8;
303 row = gs_alloc_bytes(mem, dsize, "x_wrap_get_bits");
304 if (row == 0)
305 return_error(gs_error_VMerror);
306 code = (*dev_proc(tdev, get_bits)) (tdev, y, row, &base);
307 if (code < 0)
308 goto gx;
309 for (sbit = 0, xi = 0; xi < width; sbit += sdepth, ++xi) {
310 const byte *sptr = base + (sbit >> 3);
311 gx_color_index pixel;
312 gx_color_value rgb[3];
313 int i;
314
315 if (sdepth <= 8)
316 pixel = (*sptr >> (8 - sdepth - (sbit & 7))) & smask;
317 else {
318 pixel = 0;
319 for (i = 0; i < sdepth; i += 8, ++sptr)
320 pixel = (pixel << 8) + *sptr;
321 }
322 if (pixel != pixel_in) {
323 (*dev_proc(tdev, map_color_rgb))(tdev, pixel, rgb);
324 pixel_in = pixel;
325 if (dev->color_info.num_components <= 3)
326 pixel_out = (*dev_proc(dev, map_rgb_color))(dev, rgb);
327 else {
328 /* Convert RGB to CMYK. */
329 gx_color_value c = gx_max_color_value - rgb[0];
330 gx_color_value m = gx_max_color_value - rgb[1];
331 gx_color_value y = gx_max_color_value - rgb[2];
332 gx_color_value k = (c < m ? min(c, y) : min(m, y));
333
334 gx_color_value cmyk[4];
335 cmyk[0] = c - k; cmyk[1] = m - k; cmyk[2] = y - k; cmyk[3] = k;
336 pixel_out = (*dev_proc(dev, map_cmyk_color))(dev, cmyk);
337 }
338 }
339 LINE_ACCUM(pixel_out, depth);
340 }
341 LINE_ACCUM_STORE(depth);
342 gx:gs_free_object(mem, row, "x_wrap_get_bits");
343 *actual_data = str;
344 return code;
345 }
346
347 private int
x_wrap_get_params(gx_device * dev,gs_param_list * plist)348 x_wrap_get_params(gx_device * dev, gs_param_list * plist)
349 {
350 gx_device *tdev;
351 /* We assume that a get_params call has no side effects.... */
352 gx_device_X save_dev;
353 int ecode;
354 int code;
355
356 if ((code = get_dev_target(&tdev, dev)) < 0)
357 return code;
358 save_dev = *(gx_device_X *) tdev;
359 if (tdev->is_open)
360 tdev->color_info = dev->color_info;
361 tdev->dname = dev->dname;
362 ecode = (*dev_proc(tdev, get_params)) (tdev, plist);
363 *(gx_device_X *) tdev = save_dev;
364 return ecode;
365 }
366
367 private int
x_wrap_put_params(gx_device * dev,gs_param_list * plist)368 x_wrap_put_params(gx_device * dev, gs_param_list * plist)
369 {
370 gx_device *tdev;
371 gx_device_color_info cinfo;
372 const char *dname;
373 int rcode, code;
374
375 if ((code = get_dev_target(&tdev, dev)) < 0)
376 return code;
377 /*
378 * put_params will choke if we simply feed it the output of
379 * get_params; we have to substitute color_info the same way.
380 */
381 cinfo = tdev->color_info;
382 dname = tdev->dname;
383 tdev->color_info = dev->color_info;
384 tdev->dname = dev->dname;
385 rcode = (*dev_proc(tdev, put_params)) (tdev, plist);
386 tdev->color_info = cinfo;
387 tdev->dname = dname;
388 if (rcode < 0)
389 return rcode;
390 code = get_target_info(dev);
391 return (code < 0 ? code : rcode);
392 }
393
394 /* Internal procedures */
395
396 /* Get the target, creating it if necessary. */
397 private int
get_dev_target(gx_device ** ptdev,gx_device * dev)398 get_dev_target(gx_device ** ptdev, gx_device * dev)
399 {
400 gx_device *tdev = ((gx_device_forward *) dev)->target;
401
402 if (tdev == 0) {
403 /* Create an X device instance. */
404 int code = gs_copydevice(&tdev, (const gx_device *)&gs_x11_device,
405 dev->memory);
406
407 if (code < 0)
408 return 0;
409 check_device_separable(tdev);
410 gx_device_fill_in_procs(tdev);
411 gx_device_set_target((gx_device_forward *)dev, tdev);
412 x_clear_color_cache(dev);
413 }
414 *ptdev = tdev;
415 return 0;
416 }
417
418 /* Copy parameters back from the target. */
419 private int
get_target_info(gx_device * dev)420 get_target_info(gx_device * dev)
421 {
422 gx_device *tdev;
423 int code;
424
425 if ((code = get_dev_target(&tdev, dev)) < 0)
426 return code;
427
428 #define copy(m) dev->m = tdev->m;
429 #define copy2(m) copy(m[0]); copy(m[1])
430 #define copy4(m) copy2(m); copy(m[2]); copy(m[3])
431
432 copy(width);
433 copy(height);
434 copy2(MediaSize);
435 copy4(ImagingBBox);
436 copy(ImagingBBox_set);
437 copy2(HWResolution);
438 copy2(MarginsHWResolution);
439 copy2(Margins);
440 copy4(HWMargins);
441 if (dev->color_info.num_components == 3) {
442 /* Leave the anti-aliasing information alone. */
443 gx_device_anti_alias_info aa;
444
445 aa = dev->color_info.anti_alias;
446 copy(color_info);
447 dev->color_info.anti_alias = aa;
448 }
449
450 #undef copy4
451 #undef copy2
452 #undef copy
453
454 x_clear_color_cache(dev);
455 return 0;
456 }
457
458 /* Map a fake CMYK or black/white color to a real X color if necessary. */
459 private gx_color_index
x_alt_map_color(gx_device * dev,gx_color_index color)460 x_alt_map_color(gx_device * dev, gx_color_index color)
461 {
462 gx_device_X_wrapper *xdev = (gx_device_X_wrapper *) dev;
463 gx_device *tdev;
464 gx_color_value rgb[3];
465 gx_color_index cindex;
466 int result;
467 int code;
468
469 if (color == gx_no_color_index)
470 return color;
471 if (color < 16) {
472 cindex = ((gx_device_X_wrapper *) dev)->color_cache[color];
473 if (cindex != gx_no_color_index)
474 return cindex;
475 }
476 if ((code = get_dev_target(&tdev, dev)) < 0)
477 return code;
478 result = xdev->alt_map_color(dev, color, rgb);
479 if (result >= 0)
480 cindex = result;
481 else
482 cindex = dev_proc(tdev, map_rgb_color)(tdev, rgb);
483 if (color < 16)
484 ((gx_device_X_wrapper *) dev)->color_cache[color] = cindex;
485 return cindex;
486 }
487
488 /* ---------------- CMYK procedures ---------------- */
489
490 /* Device procedures */
491 private dev_proc_open_device(x_cmyk_open);
492 private dev_proc_put_params(x_cmyk_put_params);
493 private dev_proc_map_cmyk_color(x_cmyk_map_cmyk_color);
494 /* Extended device procedures */
495 private dev_proc_map_color_rgb(x_cmyk_alt_map_color);
496
497 /* The device descriptor */
498 private const gx_device_procs x_cmyk_procs = {
499 x_cmyk_open,
500 gx_forward_get_initial_matrix,
501 x_forward_sync_output,
502 x_forward_output_page,
503 x_wrap_close,
504 NULL, /* map_rgb_color */
505 x_wrap_map_color_rgb,
506 x_wrap_fill_rectangle,
507 gx_default_tile_rectangle,
508 x_wrap_copy_mono,
509 x_wrap_copy_color,
510 gx_default_draw_line,
511 x_wrap_get_bits,
512 x_wrap_get_params,
513 x_cmyk_put_params,
514 x_cmyk_map_cmyk_color,
515 gx_forward_get_xfont_procs,
516 gx_forward_get_xfont_device,
517 NULL, /* map_rgb_alpha_color */
518 gx_forward_get_page_device,
519 gx_forward_get_alpha_bits,
520 NULL /* copy_alpha */
521 };
522
523 /* The instances are public. */
524 const gx_device_X_wrapper gs_x11cmyk_device = {
525 std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk",
526 &st_device_X_wrapper,
527 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
528 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
529 4, 4, 1, 1, 2, 2),
530 X_WRAPPER_DATA(x_cmyk_alt_map_color)
531 };
532 const gx_device_X_wrapper gs_x11cmyk2_device = {
533 std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk2",
534 &st_device_X_wrapper,
535 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
536 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
537 4, 8, 3, 3, 4, 4),
538 X_WRAPPER_DATA(x_cmyk_alt_map_color)
539 };
540 const gx_device_X_wrapper gs_x11cmyk4_device = {
541 std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk4",
542 &st_device_X_wrapper,
543 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
544 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
545 4, 16, 15, 15, 16, 16),
546 X_WRAPPER_DATA(x_cmyk_alt_map_color)
547 };
548 const gx_device_X_wrapper gs_x11cmyk8_device = {
549 std_device_dci_type_body(gx_device_X_wrapper, &x_cmyk_procs, "x11cmyk8",
550 &st_device_X_wrapper,
551 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
552 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
553 4, 32, 255, 255, 256, 256),
554 X_WRAPPER_DATA(x_cmyk_alt_map_color)
555 };
556
557 /* Map a fake color to RGB. */
558 private int
x_cmyk_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])559 x_cmyk_alt_map_color(gx_device * dev, gx_color_index color,
560 gx_color_value rgb[3])
561 {
562 int shift = dev->color_info.depth >> 2;
563 int mask = (1 << shift) - 1;
564 /* The following division is guaranteed exact. */
565 gx_color_value scale = gx_max_color_value / mask;
566 int cw = ~color & mask;
567 int cb = cw - ((color >> shift) & mask);
568 int cg = cw - ((color >> (shift * 2)) & mask);
569 int cr = cw - ((color >> (shift * 3)) & mask);
570
571 rgb[0] = max(cr, 0) * scale;
572 rgb[1] = max(cg, 0) * scale;
573 rgb[2] = max(cb, 0) * scale;
574 return -1;
575 }
576
577 /* Set color mapping procedures */
578 private void
x_cmyk_set_procs(gx_device * dev)579 x_cmyk_set_procs(gx_device *dev)
580 {
581 if (dev->color_info.depth == 4) {
582 set_dev_proc(dev, map_cmyk_color, cmyk_1bit_map_cmyk_color);
583 } else {
584 set_dev_proc(dev, map_cmyk_color, x_cmyk_map_cmyk_color);
585 }
586 }
587
588 /* Device procedures */
589
590 private int
x_cmyk_open(gx_device * dev)591 x_cmyk_open(gx_device *dev)
592 {
593 int code = x_wrap_open(dev);
594
595 if (code >= 0)
596 x_cmyk_set_procs(dev);
597 return code;
598 }
599
600 private int
x_cmyk_put_params(gx_device * dev,gs_param_list * plist)601 x_cmyk_put_params(gx_device * dev, gs_param_list * plist)
602 {
603 int code = x_wrap_put_params(dev, plist);
604
605 if (code >= 0)
606 x_cmyk_set_procs(dev);
607 return code;
608 }
609
610 private gx_color_index
x_cmyk_map_cmyk_color(gx_device * dev,const gx_color_value cv[])611 x_cmyk_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
612 {
613 int shift = dev->color_info.depth >> 2;
614 gx_color_index pixel = cv[0] >> (gx_color_value_bits - shift);
615 gx_color_value c, m, y, k;
616 c = cv[0]; m = cv[1]; y = cv[2]; k = cv[3];
617 pixel = (pixel << shift) | (m >> (gx_color_value_bits - shift));
618 pixel = (pixel << shift) | (y >> (gx_color_value_bits - shift));
619 return (pixel << shift) | (k >> (gx_color_value_bits - shift));
620 }
621
622 /* ---------------- Black-and-white procedures ---------------- */
623
624 /* Extended device procedures */
625 private dev_proc_map_color_rgb(x_mono_alt_map_color);
626
627 /* The device descriptor */
628 private const gx_device_procs x_mono_procs = {
629 x_wrap_open,
630 gx_forward_get_initial_matrix,
631 x_forward_sync_output,
632 x_forward_output_page,
633 x_wrap_close,
634 gx_default_b_w_map_rgb_color,
635 x_wrap_map_color_rgb,
636 x_wrap_fill_rectangle,
637 gx_default_tile_rectangle,
638 x_wrap_copy_mono,
639 gx_default_copy_color, /* this is fast for the 1-bit case */
640 gx_default_draw_line,
641 x_wrap_get_bits,
642 x_wrap_get_params,
643 x_wrap_put_params,
644 gx_default_map_cmyk_color,
645 gx_forward_get_xfont_procs,
646 gx_forward_get_xfont_device,
647 NULL, /* map_rgb_alpha_color */
648 gx_forward_get_page_device,
649 gx_forward_get_alpha_bits,
650 NULL /* copy_alpha */
651 };
652
653 /* The instance is public. */
654 const gx_device_X_wrapper gs_x11mono_device = {
655 std_device_dci_type_body(gx_device_X_wrapper, &x_mono_procs, "x11mono",
656 &st_device_X_wrapper,
657 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
658 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
659 1, 1, 1, 0, 2, 0),
660 X_WRAPPER_DATA(x_mono_alt_map_color)
661 };
662
663 /* Map a fake color to RGB. */
664 private int
x_mono_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])665 x_mono_alt_map_color(gx_device * dev, gx_color_index color,
666 gx_color_value rgb[3])
667 {
668 rgb[0] = rgb[1] = rgb[2] = (color ? 0 : gx_max_color_value);
669 return -1;
670 }
671
672 /* ---------------- 2- and 4-bit gray-scale procedures ---------------- */
673
674 /* Extended device procedures */
675 private dev_proc_map_color_rgb(x_gray_alt_map_color);
676
677 /* The device descriptor */
678 private const gx_device_procs x_gray_procs = {
679 x_wrap_open,
680 gx_forward_get_initial_matrix,
681 x_forward_sync_output,
682 x_forward_output_page,
683 x_wrap_close,
684 gx_default_gray_map_rgb_color,
685 x_wrap_map_color_rgb,
686 x_wrap_fill_rectangle,
687 gx_default_tile_rectangle,
688 x_wrap_copy_mono,
689 x_wrap_copy_color,
690 gx_default_draw_line,
691 x_wrap_get_bits,
692 x_wrap_get_params,
693 x_wrap_put_params,
694 gx_default_map_cmyk_color,
695 gx_forward_get_xfont_procs,
696 gx_forward_get_xfont_device,
697 NULL, /* map_rgb_alpha_color */
698 gx_forward_get_page_device,
699 gx_forward_get_alpha_bits,
700 NULL /* copy_alpha */
701 };
702
703 /* The instances are public. */
704 const gx_device_X_wrapper gs_x11gray2_device = {
705 std_device_dci_type_body(gx_device_X_wrapper, &x_gray_procs, "x11gray2",
706 &st_device_X_wrapper,
707 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
708 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
709 1, 2, 3, 0, 4, 0),
710 X_WRAPPER_DATA(x_gray_alt_map_color)
711 };
712
713 const gx_device_X_wrapper gs_x11gray4_device = {
714 std_device_dci_type_body(gx_device_X_wrapper, &x_gray_procs, "x11gray4",
715 &st_device_X_wrapper,
716 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
717 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
718 1, 4, 15, 0, 16, 0),
719 X_WRAPPER_DATA(x_gray_alt_map_color)
720 };
721
722 /* Map a fake color to RGB. */
723 private int
x_gray_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])724 x_gray_alt_map_color(gx_device * dev, gx_color_index color,
725 gx_color_value rgb[3])
726 {
727 rgb[0] = rgb[1] = rgb[2] =
728 color * gx_max_color_value / dev->color_info.max_gray;
729 return -1;
730 }
731
732 /* Device procedures */
733
734 /* We encode a complemented alpha value in the top 8 bits of the */
735 /* device color. */
736 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)737 x_alpha_map_rgb_alpha_color(gx_device * dev,
738 gx_color_value r, gx_color_value g, gx_color_value b, gx_color_value alpha)
739 {
740 gx_color_index color;
741 gx_color_value cv[3];
742 byte abyte = alpha >> (gx_color_value_bits - 8);
743 cv[0] = r; cv[1] = g; cv[2] = b;
744 color = gx_forward_map_rgb_color(dev, cv);
745 return (abyte == 0 ? (gx_color_index)0xff << 24 :
746 ((gx_color_index) (abyte ^ 0xff) << 24) + color);
747 }
748
749 /* ---------------- Permuted RGB16/32 procedures ---------------- */
750
751 /* Device procedures */
752 private dev_proc_map_rgb_color(x_rg16x_map_rgb_color);
753 private dev_proc_map_rgb_color(x_rg32x_map_rgb_color);
754 /* Extended device procedures */
755 private dev_proc_map_color_rgb(x_rg16x_alt_map_color);
756 private dev_proc_map_color_rgb(x_rg32x_alt_map_color);
757
758 /* The device descriptor */
759 #define RGBX_PROCS(map_rgb_proc)\
760 x_wrap_open,\
761 gx_forward_get_initial_matrix,\
762 x_forward_sync_output,\
763 x_forward_output_page,\
764 x_wrap_close,\
765 map_rgb_proc, /* differs */\
766 x_wrap_map_color_rgb,\
767 x_wrap_fill_rectangle,\
768 gx_default_tile_rectangle,\
769 x_wrap_copy_mono,\
770 x_forward_copy_color,\
771 gx_default_draw_line,\
772 x_forward_get_bits,\
773 x_wrap_get_params,\
774 x_wrap_put_params,\
775 gx_forward_map_cmyk_color,\
776 gx_forward_get_xfont_procs,\
777 gx_forward_get_xfont_device,\
778 x_alpha_map_rgb_alpha_color,\
779 gx_forward_get_page_device,\
780 gx_default_get_alpha_bits,\
781 gx_default_copy_alpha
782
783 private const gx_device_procs x_rg16x_procs = {
784 RGBX_PROCS(x_rg16x_map_rgb_color)
785 };
786 const gx_device_X_wrapper gs_x11rg16x_device = {
787 std_device_dci_type_body(gx_device_X_wrapper, &x_rg16x_procs, "x11rg16x",
788 &st_device_X_wrapper,
789 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
790 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
791 3, 16, 31, 31, 32, 32),
792 X_WRAPPER_DATA(x_rg16x_alt_map_color)
793 };
794
795 private const gx_device_procs x_rg32x_procs = {
796 RGBX_PROCS(x_rg32x_map_rgb_color)
797 };
798 const gx_device_X_wrapper gs_x11rg32x_device = {
799 std_device_dci_type_body(gx_device_X_wrapper, &x_rg32x_procs, "x11rg32x",
800 &st_device_X_wrapper,
801 FAKE_RES * 85 / 10, FAKE_RES * 11, /* x and y extent (nominal) */
802 FAKE_RES, FAKE_RES, /* x and y density (nominal) */
803 3, 32, 1023, 1023, 1024, 1024),
804 X_WRAPPER_DATA(x_rg32x_alt_map_color)
805 };
806
807 /* Map RGB to a fake color. */
808 private gx_color_index
x_rg16x_map_rgb_color(gx_device * dev,const gx_color_value cv[])809 x_rg16x_map_rgb_color(gx_device * dev, const gx_color_value cv[])
810 {
811 /* Permute the colors to G5/B5/R6. */
812 gx_color_value r, g, b;
813 r = cv[0]; g = cv[1]; b = cv[2];
814 return (r >> (gx_color_value_bits - 6)) +
815 ((g >> (gx_color_value_bits - 5)) << 11) +
816 ((b >> (gx_color_value_bits - 5)) << 6);
817 }
818 private gx_color_index
x_rg32x_map_rgb_color(gx_device * dev,const gx_color_value cv[])819 x_rg32x_map_rgb_color(gx_device * dev, const gx_color_value cv[])
820 {
821 /* Permute the colors to G11/B10/R11. */
822 gx_color_value r, g, b;
823 r = cv[0]; g = cv[1]; b = cv[2];
824 return (r >> (gx_color_value_bits - 11)) +
825 ((gx_color_index)(g >> (gx_color_value_bits - 11)) << 21) +
826 ((gx_color_index)(b >> (gx_color_value_bits - 10)) << 11);
827 }
828
829 /* Map a fake color to RGB. */
830 private int
x_rg16x_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])831 x_rg16x_alt_map_color(gx_device * dev, gx_color_index color,
832 gx_color_value rgb[3])
833 {
834 rgb[0] = (color & 0x3f) * gx_max_color_value / 0x3f;
835 rgb[1] = ((color >> 11) & 0x1f) * gx_max_color_value / 0x1f;
836 rgb[2] = ((color >> 6) & 0x1f) * gx_max_color_value / 0x1f;
837 return -1;
838 }
839 private int
x_rg32x_alt_map_color(gx_device * dev,gx_color_index color,gx_color_value rgb[3])840 x_rg32x_alt_map_color(gx_device * dev, gx_color_index color,
841 gx_color_value rgb[3])
842 {
843 rgb[0] = (color & 0x7ff) * gx_max_color_value / 0x7ff;
844 rgb[1] = ((color >> 21) & 0x7ff) * gx_max_color_value / 0x7ff;
845 rgb[2] = ((color >> 11) & 0x3ff) * gx_max_color_value / 0x3ff;
846 return -1;
847 }
848