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