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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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