1 /* Copyright (C) 2001-2005, Ghostgum Software Pty Ltd. 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 /* gdevdsp.c */
18 /* $Id: gdevdsp.c,v 1.35 2005/09/04 05:44:43 dan Exp $ */
19
20 /*
21 * DLL based display device driver.
22 *
23 * by Russell Lang, Ghostgum Software Pty Ltd
24 *
25 * This device is intended to be used for displays when
26 * Ghostscript is loaded as a DLL/shared library/static library.
27 * It is intended to work for Windows, OS/2, Linux, Mac OS 9 and
28 * hopefully others.
29 *
30 * Before this device is opened, the address of a structure must
31 * be provided using gsapi_set_display_callback(minst, callback);
32 * This structure contains callback functions to notify the
33 * caller when the device is opened, closed, resized, showpage etc.
34 * The structure is defined in gdevdsp.h.
35 *
36 * Not all combinations of display formats have been tested.
37 * At the end of this file is some example code showing which
38 * formats have been tested.
39 */
40
41 #include "string_.h"
42 #include "gx.h"
43 #include "gserrors.h"
44 #include "gsdevice.h" /* for gs_copydevice */
45 #include "gxdevice.h"
46
47 #include "gp.h"
48 #include "gpcheck.h"
49 #include "gsparam.h"
50
51 #include "gdevpccm.h" /* 4-bit PC color */
52 #include "gxdevmem.h"
53 #include "gdevdevn.h"
54 #include "gsequivc.h"
55 #include "gdevdsp.h"
56 #include "gdevdsp2.h"
57
58 /* Initial values for width and height */
59 #define INITIAL_RESOLUTION 96
60 #define INITIAL_WIDTH ((INITIAL_RESOLUTION * 85 + 5) / 10)
61 #define INITIAL_HEIGHT ((INITIAL_RESOLUTION * 110 + 5) / 10)
62
63 /* Device procedures */
64
65 /* See gxdevice.h for the definitions of the procedures. */
66 private dev_proc_open_device(display_open);
67 private dev_proc_get_initial_matrix(display_get_initial_matrix);
68 private dev_proc_sync_output(display_sync_output);
69 private dev_proc_output_page(display_output_page);
70 private dev_proc_close_device(display_close);
71
72 private dev_proc_map_rgb_color(display_map_rgb_color_device4);
73 private dev_proc_map_color_rgb(display_map_color_rgb_device4);
74 private dev_proc_encode_color(display_encode_color_device8);
75 private dev_proc_decode_color(display_decode_color_device8);
76 private dev_proc_map_rgb_color(display_map_rgb_color_device16);
77 private dev_proc_map_color_rgb(display_map_color_rgb_device16);
78 private dev_proc_map_rgb_color(display_map_rgb_color_rgb);
79 private dev_proc_map_color_rgb(display_map_color_rgb_rgb);
80 private dev_proc_map_rgb_color(display_map_rgb_color_bgr24);
81 private dev_proc_map_color_rgb(display_map_color_rgb_bgr24);
82
83 private dev_proc_fill_rectangle(display_fill_rectangle);
84 private dev_proc_copy_mono(display_copy_mono);
85 private dev_proc_copy_color(display_copy_color);
86 private dev_proc_get_bits(display_get_bits);
87 private dev_proc_get_params(display_get_params);
88 private dev_proc_put_params(display_put_params);
89 private dev_proc_finish_copydevice(display_finish_copydevice);
90
91 private dev_proc_get_color_mapping_procs(display_separation_get_color_mapping_procs);
92 private dev_proc_get_color_comp_index(display_separation_get_color_comp_index);
93 private dev_proc_encode_color(display_separation_encode_color);
94 private dev_proc_decode_color(display_separation_decode_color);
95 private dev_proc_update_spot_equivalent_colors(display_update_spot_equivalent_colors);
96
97
98 private const gx_device_procs display_procs =
99 {
100 display_open,
101 display_get_initial_matrix,
102 display_sync_output,
103 display_output_page,
104 display_close,
105 gx_default_w_b_map_rgb_color,
106 gx_default_w_b_map_color_rgb,
107 display_fill_rectangle,
108 NULL, /* tile rectangle */
109 display_copy_mono,
110 display_copy_color,
111 NULL, /* draw line */
112 display_get_bits,
113 display_get_params,
114 display_put_params,
115 gx_default_cmyk_map_cmyk_color, /* map_cmyk_color */
116 gx_default_get_xfont_procs,
117 NULL, /* get_xfont_device */
118 NULL, /* map_rgb_alpha_color */
119 gx_page_device_get_page_device,
120 /* extra entries */
121 NULL, /* get_alpha_bits */
122 NULL, /* copy_alpha */
123 NULL, /* get_band */
124 NULL, /* copy_rop */
125 NULL, /* fill_path */
126 NULL, /* stroke_path */
127 NULL, /* fill_mask */
128 NULL, /* fill_trapezoid */
129 NULL, /* fill_parallelogram */
130 NULL, /* fill_triangle */
131 NULL, /* draw_thin_line */
132 NULL, /* begin_image */
133 NULL, /* image_data */
134 NULL, /* end_image */
135 NULL, /* strip_tile_rectangle */
136 NULL, /* strip_copy_rop */
137 NULL, /* get_clipping_box */
138 NULL, /* begin_typed_image */
139 NULL, /* get_bits_rectangle */
140 NULL, /* map_color_rgb_alpha */
141 NULL, /* create_compositor */
142 NULL, /* get_hardware_params */
143 NULL, /* text_begin */
144 display_finish_copydevice, /* finish_copydevice */
145 NULL, /* begin_transparency_group */
146 NULL, /* end_transparency_group */
147 NULL, /* begin_transparency_mask */
148 NULL, /* end_transparency_mask */
149 NULL, /* discard_transparency_layer */
150 NULL, /* get_color_mapping_procs */
151 NULL, /* get_color_comp_index */
152 NULL, /* encode_color */
153 NULL, /* decode_color */
154 NULL, /* pattern_manage */
155 NULL, /* fill_rectangle_hl_color */\
156 NULL, /* include_color_space */\
157 NULL, /* fill_linear_color_scanline */\
158 NULL, /* fill_linear_color_trapezoid */\
159 NULL, /* fill_linear_color_triangle */\
160 display_update_spot_equivalent_colors /* update_spot_equivalent_colors */
161 };
162
163 /* GC descriptor */
164 public_st_device_display();
165
166 private
167 ENUM_PTRS_WITH(display_enum_ptrs, gx_device_display *ddev)
168 if (index == 0) {
169 if (ddev->mdev) {
170 return ENUM_OBJ(gx_device_enum_ptr((gx_device *)ddev->mdev));
171 }
172 return 0;
173 }
174 else if (index-1 < ddev->devn_params.separations.num_separations)
175 ENUM_RETURN(ddev->devn_params.separations.names[index-1].data);
176 else
177 return 0;
178 ENUM_PTRS_END
179
180 private
181 RELOC_PTRS_WITH(display_reloc_ptrs, gx_device_display *ddev)
182 if (ddev->mdev) {
183 ddev->mdev = (gx_device_memory *)
184 gx_device_reloc_ptr((gx_device *)ddev->mdev, gcst);
185 }
186 { int i;
187 for (i = 0; i < ddev->devn_params.separations.num_separations; ++i) {
188 RELOC_PTR(gx_device_display, devn_params.separations.names[i].data);
189 }
190 }
191 RELOC_PTRS_END
192
193
194 const gx_device_display gs_display_device =
195 {
196 std_device_std_body_type(gx_device_display, &display_procs, "display",
197 &st_device_display,
198 INITIAL_WIDTH, INITIAL_HEIGHT,
199 INITIAL_RESOLUTION, INITIAL_RESOLUTION),
200 {0}, /* std_procs */
201 NULL, /* mdev */
202 NULL, /* callback */
203 NULL, /* pHandle */
204 0, /* nFormat */
205 NULL, /* pBitmap */
206 0, /* ulBitmapSize */
207 0, /* HWResolution_set */
208
209 { /* devn_params specific parameters */
210 8, /* Bits per color - must match ncomp, depth, etc. */
211 DeviceCMYKComponents, /* Names of color model colorants */
212 4, /* Number of colorants for CMYK */
213 0, /* MaxSeparations has not been specified */
214 {0}, /* SeparationNames */
215 {0}, /* SeparationOrder names */
216 {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
217 },
218 { true } /* equivalent CMYK colors for spot colors */
219 };
220
221
222
223 /* prototypes for internal procedures */
224 private int display_check_structure(gx_device_display *dev);
225 private void display_free_bitmap(gx_device_display * dev);
226 private int display_alloc_bitmap(gx_device_display *, gx_device *);
227 private int display_set_color_format(gx_device_display *dev, int nFormat);
228 private int display_set_separations(gx_device_display *dev);
229 private int display_raster(gx_device_display *dev);
230
231 /* Open the display driver. */
232 private int
display_open(gx_device * dev)233 display_open(gx_device * dev)
234 {
235 gx_device_display *ddev = (gx_device_display *) dev;
236 int ccode;
237
238 /* Erase these, in case we are opening a copied device. */
239 ddev->mdev = NULL;
240 ddev->pBitmap = NULL;
241 ddev->ulBitmapSize = 0;
242
243 /* Allow device to be opened "disabled" without a callback. */
244 /* The callback will be set later and the device re-opened. */
245 if (ddev->callback == NULL)
246 return 0;
247
248 /* Make sure we have been passed a valid callback structure. */
249 if ((ccode = display_check_structure(ddev)) < 0)
250 return_error(ccode);
251
252 /* set color info */
253 if ((ccode = display_set_color_format(ddev, ddev->nFormat)) < 0)
254 return_error(ccode);
255
256 /* Tell caller that the device is open. */
257 /* This is always the first callback */
258 ccode = (*(ddev->callback->display_open))(ddev->pHandle, dev);
259 if (ccode < 0)
260 return_error(ccode);
261
262 /* Tell caller the proposed device parameters */
263 ccode = (*(ddev->callback->display_presize)) (ddev->pHandle, dev,
264 dev->width, dev->height, display_raster(ddev), ddev->nFormat);
265 if (ccode < 0) {
266 (*(ddev->callback->display_close))(ddev->pHandle, dev);
267 return_error(ccode);
268 }
269
270 /* allocate the image */
271 ccode = display_alloc_bitmap(ddev, dev);
272 if (ccode < 0) {
273 (*(ddev->callback->display_close))(ddev->pHandle, dev);
274 return_error(ccode);
275 }
276
277 /* Tell caller the device parameters */
278 ccode = (*(ddev->callback->display_size)) (ddev->pHandle, dev,
279 dev->width, dev->height, display_raster(ddev), ddev->nFormat,
280 ddev->mdev->base);
281 if (ccode < 0) {
282 display_free_bitmap(ddev);
283 (*(ddev->callback->display_close))(ddev->pHandle, dev);
284 return_error(ccode);
285 }
286
287 return 0;
288 }
289
290 private void
display_get_initial_matrix(gx_device * dev,gs_matrix * pmat)291 display_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
292 {
293 gx_device_display *ddev = (gx_device_display *) dev;
294 if ((ddev->nFormat & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST)
295 gx_default_get_initial_matrix(dev, pmat);
296 else
297 gx_upright_get_initial_matrix(dev, pmat); /* Windows / OS/2 */
298 }
299
300 /* Update the display. */
301 int
display_sync_output(gx_device * dev)302 display_sync_output(gx_device * dev)
303 {
304 gx_device_display *ddev = (gx_device_display *) dev;
305 if (ddev->callback == NULL)
306 return 0;
307 display_set_separations(ddev);
308
309 (*(ddev->callback->display_sync))(ddev->pHandle, dev);
310 return (0);
311 }
312
313 /* Update the display, bring to foreground. */
314 /* If you want to pause on showpage, delay your return from callback */
315 int
display_output_page(gx_device * dev,int copies,int flush)316 display_output_page(gx_device * dev, int copies, int flush)
317 {
318 gx_device_display *ddev = (gx_device_display *) dev;
319 int code;
320 if (ddev->callback == NULL)
321 return 0;
322 display_set_separations(ddev);
323
324 code = (*(ddev->callback->display_page))
325 (ddev->pHandle, dev, copies, flush);
326
327 if (code >= 0)
328 code = gx_finish_output_page(dev, copies, flush);
329 return code;
330 }
331
332 /* Close the display driver */
333 private int
display_close(gx_device * dev)334 display_close(gx_device * dev)
335 {
336 gx_device_display *ddev = (gx_device_display *) dev;
337 if (ddev->callback == NULL)
338 return 0;
339
340 /* Tell caller that device is about to be closed. */
341 (*(ddev->callback->display_preclose))(ddev->pHandle, dev);
342
343 /* Release memory. */
344 display_free_bitmap(ddev);
345
346 /* Tell caller that device is closed. */
347 /* This is always the last callback */
348 (*(ddev->callback->display_close))(ddev->pHandle, dev);
349
350 return 0;
351 }
352
353 /*
354 * This routine will encode a 1 Black on white color.
355 */
356 private gx_color_index
gx_b_w_gray_encode(gx_device * dev,const gx_color_value cv[])357 gx_b_w_gray_encode(gx_device * dev, const gx_color_value cv[])
358 {
359 return 1 - (cv[0] >> (gx_color_value_bits - 1));
360 }
361
362 /* DISPLAY_COLORS_NATIVE, 4bit/pixel */
363 /* Map a r-g-b color to a color code */
364 private gx_color_index
display_map_rgb_color_device4(gx_device * dev,const gx_color_value cv[])365 display_map_rgb_color_device4(gx_device * dev, const gx_color_value cv[])
366 {
367 return pc_4bit_map_rgb_color(dev, cv);
368 }
369
370 /* Map a color code to r-g-b. */
371 private int
display_map_color_rgb_device4(gx_device * dev,gx_color_index color,gx_color_value prgb[3])372 display_map_color_rgb_device4(gx_device * dev, gx_color_index color,
373 gx_color_value prgb[3])
374 {
375 pc_4bit_map_color_rgb(dev, color, prgb);
376 return 0;
377 }
378
379 /* DISPLAY_COLORS_NATIVE, 8bit/pixel */
380 /* Map a r-g-b-k color to a color code */
381 private gx_color_index
display_encode_color_device8(gx_device * dev,const gx_color_value cv[])382 display_encode_color_device8(gx_device * dev, const gx_color_value cv[])
383 {
384 /* palette of 96 colors */
385 /* 0->63 = 00RRGGBB, 64->95 = 010YYYYY */
386 gx_color_value r = cv[0];
387 gx_color_value g = cv[1];
388 gx_color_value b = cv[2];
389 gx_color_value k = cv[3]; /* 0 = black */
390 if ((r == 0) && (g == 0) && (b == 0)) {
391 k = ((k >> (gx_color_value_bits - 6)) + 1) >> 1;
392 if (k > 0x1f)
393 k = 0x1f;
394 return (k + 0x40);
395 }
396 if (k > 0) {
397 /* The RGB->RGBK color mapping shouldn't generate this. */
398 r = ((r+k) > gx_max_color_value) ? gx_max_color_value :
399 (gx_color_value)(r+k);
400 g = ((g+k) > gx_max_color_value) ? gx_max_color_value :
401 (gx_color_value)(g+k);
402 b = ((b+k) > gx_max_color_value) ? gx_max_color_value :
403 (gx_color_value)(b+k);
404 }
405 r = ((r >> (gx_color_value_bits - 3)) + 1) >> 1;
406 if (r > 0x3)
407 r = 0x3;
408 g = ((g >> (gx_color_value_bits - 3)) + 1) >> 1;
409 if (g > 0x3)
410 g = 0x3;
411 b = ((b >> (gx_color_value_bits - 3)) + 1) >> 1;
412 if (b > 0x3)
413 b = 0x3;
414 return (r << 4) + (g << 2) + b;
415 }
416
417 /* Map a color code to r-g-b-k. */
418 private int
display_decode_color_device8(gx_device * dev,gx_color_index color,gx_color_value prgb[4])419 display_decode_color_device8(gx_device * dev, gx_color_index color,
420 gx_color_value prgb[4])
421 {
422 gx_color_value one;
423 /* palette of 96 colors */
424 /* 0->63 = 00RRGGBB, 64->95 = 010YYYYY */
425 if (color < 64) {
426 one = (gx_color_value) (gx_max_color_value / 3);
427 prgb[0] = (gx_color_value) (((color >> 4) & 3) * one);
428 prgb[1] = (gx_color_value) (((color >> 2) & 3) * one);
429 prgb[2] = (gx_color_value) (((color) & 3) * one);
430 prgb[3] = 0;
431 }
432 else if (color < 96) {
433 one = (gx_color_value) (gx_max_color_value / 31);
434 prgb[0] = prgb[1] = prgb[2] = 0;
435 prgb[3] = (gx_color_value) ((color & 0x1f) * one);
436 }
437 else {
438 prgb[0] = prgb[1] = prgb[2] = prgb[3] = 0;
439 }
440 return 0;
441 }
442
443
444 /* DISPLAY_COLORS_NATIVE, 16bit/pixel */
445 /* Map a r-g-b color to a color code */
446 private gx_color_index
display_map_rgb_color_device16(gx_device * dev,const gx_color_value cv[])447 display_map_rgb_color_device16(gx_device * dev, const gx_color_value cv[])
448 {
449 gx_device_display *ddev = (gx_device_display *) dev;
450 gx_color_value r = cv[0];
451 gx_color_value g = cv[1];
452 gx_color_value b = cv[2];
453 if ((ddev->nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN) {
454 if ((ddev->nFormat & DISPLAY_555_MASK) == DISPLAY_NATIVE_555)
455 /* byte0=0RRRRRGG byte1=GGGBBBBB */
456 return ((r >> (gx_color_value_bits - 5)) << 10) +
457 ((g >> (gx_color_value_bits - 5)) << 5) +
458 (b >> (gx_color_value_bits - 5));
459 else
460 /* byte0=RRRRRGGG byte1=GGGBBBBB */
461 return ((r >> (gx_color_value_bits - 5)) << 11) +
462 ((g >> (gx_color_value_bits - 6)) << 5) +
463 (b >> (gx_color_value_bits - 5));
464 }
465
466 if ((ddev->nFormat & DISPLAY_555_MASK) == DISPLAY_NATIVE_555)
467 /* byte0=GGGBBBBB byte1=0RRRRRGG */
468 return ((r >> (gx_color_value_bits - 5)) << 2) +
469 (((g >> (gx_color_value_bits - 5)) & 0x7) << 13) +
470 (((g >> (gx_color_value_bits - 5)) & 0x18) >> 3) +
471 ((b >> (gx_color_value_bits - 5)) << 8);
472
473 /* byte0=GGGBBBBB byte1=RRRRRGGG */
474 return ((r >> (gx_color_value_bits - 5)) << 3) +
475 (((g >> (gx_color_value_bits - 6)) & 0x7) << 13) +
476 (((g >> (gx_color_value_bits - 6)) & 0x38) >> 3) +
477 ((b >> (gx_color_value_bits - 5)) << 8);
478 }
479
480
481
482 /* Map a color code to r-g-b. */
483 private int
display_map_color_rgb_device16(gx_device * dev,gx_color_index color,gx_color_value prgb[3])484 display_map_color_rgb_device16(gx_device * dev, gx_color_index color,
485 gx_color_value prgb[3])
486 {
487 gx_device_display *ddev = (gx_device_display *) dev;
488 ushort value;
489
490 if ((ddev->nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN) {
491 if ((ddev->nFormat & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) {
492 /* byte0=0RRRRRGG byte1=GGGBBBBB */
493 value = (ushort) (color >> 10);
494 prgb[0] = (gx_color_value)
495 (((value << 11) + (value << 6) + (value << 1) +
496 (value >> 4)) >> (16 - gx_color_value_bits));
497 value = (ushort) ((color >> 5) & 0x1f);
498 prgb[1] = (gx_color_value)
499 (((value << 11) + (value << 6) + (value << 1) +
500 (value >> 4)) >> (16 - gx_color_value_bits));
501 value = (ushort) (color & 0x1f);
502 prgb[2] = (gx_color_value)
503 (((value << 11) + (value << 6) + (value << 1) +
504 (value >> 4)) >> (16 - gx_color_value_bits));
505 }
506 else {
507 /* byte0=RRRRRGGG byte1=GGGBBBBB */
508 value = (ushort) (color >> 11);
509 prgb[0] = ((value << 11) + (value << 6) + (value << 1) +
510 (value >> 4)) >> (16 - gx_color_value_bits);
511 value = (ushort) ((color >> 5) & 0x3f);
512 prgb[1] = (gx_color_value)
513 ((value << 10) + (value << 4) + (value >> 2))
514 >> (16 - gx_color_value_bits);
515 value = (ushort) (color & 0x1f);
516 prgb[2] = (gx_color_value)
517 ((value << 11) + (value << 6) + (value << 1) +
518 (value >> 4)) >> (16 - gx_color_value_bits);
519 }
520 }
521 else {
522 if ((ddev->nFormat & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) {
523 /* byte0=GGGBBBBB byte1=0RRRRRGG */
524 value = (ushort) ((color >> 2) & 0x1f);
525 prgb[0] = (gx_color_value)
526 ((value << 11) + (value << 6) + (value << 1) +
527 (value >> 4)) >> (16 - gx_color_value_bits);
528 value = (ushort)
529 (((color << 3) & 0x18) + ((color >> 13) & 0x7));
530 prgb[1] = (gx_color_value)
531 ((value << 11) + (value << 6) + (value << 1) +
532 (value >> 4)) >> (16 - gx_color_value_bits);
533 value = (ushort) ((color >> 8) & 0x1f);
534 prgb[2] = (gx_color_value)
535 ((value << 11) + (value << 6) + (value << 1) +
536 (value >> 4)) >> (16 - gx_color_value_bits);
537 }
538 else {
539 /* byte0=GGGBBBBB byte1=RRRRRGGG */
540 value = (ushort) ((color >> 3) & 0x1f);
541 prgb[0] = (gx_color_value)
542 (((value << 11) + (value << 6) + (value << 1) +
543 (value >> 4)) >> (16 - gx_color_value_bits));
544 value = (ushort)
545 (((color << 3) & 0x38) + ((color >> 13) & 0x7));
546 prgb[1] = (gx_color_value)
547 (((value << 10) + (value << 4) + (value >> 2))
548 >> (16 - gx_color_value_bits));
549 value = (ushort) ((color >> 8) & 0x1f);
550 prgb[2] = (gx_color_value)
551 (((value << 11) + (value << 6) + (value << 1) +
552 (value >> 4)) >> (16 - gx_color_value_bits));
553 }
554 }
555 return 0;
556 }
557
558
559 /* Map a r-g-b color to a color code */
560 private gx_color_index
display_map_rgb_color_rgb(gx_device * dev,const gx_color_value cv[])561 display_map_rgb_color_rgb(gx_device * dev, const gx_color_value cv[])
562 {
563 gx_device_display *ddev = (gx_device_display *) dev;
564 gx_color_value r = cv[0];
565 gx_color_value g = cv[1];
566 gx_color_value b = cv[2];
567 int drop = gx_color_value_bits - 8;
568 gx_color_value red, green, blue;
569
570 red = r >> drop;
571 green = g >> drop;
572 blue = b >> drop;
573
574 switch (ddev->nFormat & DISPLAY_ALPHA_MASK) {
575 case DISPLAY_ALPHA_NONE:
576 if ((ddev->nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN) {
577 gx_color_value rgb[3];
578 rgb[0] = r; rgb[1] = g; rgb[2] = b;
579 return gx_default_rgb_map_rgb_color(dev, rgb); /* RGB */
580 }
581 else
582 return (blue<<16) + (green<<8) + red; /* BGR */
583 case DISPLAY_ALPHA_FIRST:
584 case DISPLAY_UNUSED_FIRST:
585 if ((ddev->nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN)
586 return ((gx_color_index)red<<16) + (green<<8) + blue; /* xRGB */
587 else
588 return ((gx_color_index)blue<<16) + (green<<8) + red; /* xBGR */
589 case DISPLAY_ALPHA_LAST:
590 case DISPLAY_UNUSED_LAST:
591 if ((ddev->nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN)
592 return ((gx_color_index)red<<24) + (green<<16) + (blue<<8); /* RGBx */
593 else
594 return ((gx_color_index)blue<<24) + (green<<16) + (red<<8); /* BGRx */
595 }
596 return 0;
597 }
598
599 /* Map a color code to r-g-b. */
600 private int
display_map_color_rgb_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])601 display_map_color_rgb_rgb(gx_device * dev, gx_color_index color,
602 gx_color_value prgb[3])
603 {
604 gx_device_display *ddev = (gx_device_display *) dev;
605 uint bits_per_color = 8;
606 uint color_mask;
607
608 color_mask = (1 << bits_per_color) - 1;
609
610 switch (ddev->nFormat & DISPLAY_ALPHA_MASK) {
611 case DISPLAY_ALPHA_NONE:
612 if ((ddev->nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN)
613 return gx_default_rgb_map_color_rgb(dev, color, prgb); /* RGB */
614 else {
615 /* BGR */
616 prgb[0] = (gx_color_value) (((color) & color_mask) *
617 (ulong) gx_max_color_value / color_mask);
618 prgb[1] = (gx_color_value)
619 (((color >> bits_per_color) & color_mask) *
620 (ulong) gx_max_color_value / color_mask);
621 prgb[2] = (gx_color_value)
622 (((color >> 2*bits_per_color) & color_mask) *
623 (ulong) gx_max_color_value / color_mask);
624 }
625 break;
626 case DISPLAY_ALPHA_FIRST:
627 case DISPLAY_UNUSED_FIRST:
628 if ((ddev->nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN) {
629 /* xRGB */
630 prgb[0] = (gx_color_value)
631 (((color >> 2*bits_per_color) & color_mask) *
632 (ulong) gx_max_color_value / color_mask);
633 prgb[1] = (gx_color_value)
634 (((color >> bits_per_color) & color_mask) *
635 (ulong) gx_max_color_value / color_mask);
636 prgb[2] = (gx_color_value) (((color) & color_mask) *
637 (ulong) gx_max_color_value / color_mask);
638 }
639 else {
640 /* xBGR */
641 prgb[0] = (gx_color_value)
642 (((color) & color_mask) *
643 (ulong) gx_max_color_value / color_mask);
644 prgb[1] = (gx_color_value)
645 (((color >> bits_per_color) & color_mask) *
646 (ulong) gx_max_color_value / color_mask);
647 prgb[2] = (gx_color_value)
648 (((color >> 2*bits_per_color) & color_mask) *
649 (ulong) gx_max_color_value / color_mask);
650 }
651 break;
652 case DISPLAY_ALPHA_LAST:
653 case DISPLAY_UNUSED_LAST:
654 if ((ddev->nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN) {
655 /* RGBx */
656 prgb[0] = (gx_color_value)
657 (((color >> 3*bits_per_color) & color_mask) *
658 (ulong) gx_max_color_value / color_mask);
659 prgb[1] = (gx_color_value)
660 (((color >> 2*bits_per_color) & color_mask) *
661 (ulong) gx_max_color_value / color_mask);
662 prgb[2] = (gx_color_value)
663 (((color >> bits_per_color) & color_mask) *
664 (ulong) gx_max_color_value / color_mask);
665 }
666 else {
667 /* BGRx */
668 prgb[0] = (gx_color_value)
669 (((color >> bits_per_color) & color_mask) *
670 (ulong) gx_max_color_value / color_mask);
671 prgb[1] = (gx_color_value)
672 (((color >> 2*bits_per_color) & color_mask) *
673 (ulong) gx_max_color_value / color_mask);
674 prgb[2] = (gx_color_value)
675 (((color >> 3*bits_per_color) & color_mask) *
676 (ulong) gx_max_color_value / color_mask);
677 }
678 }
679 return 0;
680 }
681
682 /* Map a r-g-b color to a color code */
683 private gx_color_index
display_map_rgb_color_bgr24(gx_device * dev,const gx_color_value cv[])684 display_map_rgb_color_bgr24(gx_device * dev, const gx_color_value cv[])
685 {
686 gx_color_value r = cv[0];
687 gx_color_value g = cv[1];
688 gx_color_value b = cv[2];
689 return (gx_color_value_to_byte(b)<<16) +
690 (gx_color_value_to_byte(g)<<8) +
691 gx_color_value_to_byte(r);
692 }
693
694 /* Map a color code to r-g-b. */
695 private int
display_map_color_rgb_bgr24(gx_device * dev,gx_color_index color,gx_color_value prgb[3])696 display_map_color_rgb_bgr24(gx_device * dev, gx_color_index color,
697 gx_color_value prgb[3])
698 {
699 prgb[0] = gx_color_value_from_byte(color & 0xff);
700 prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
701 prgb[2] = gx_color_value_from_byte((color >> 16) & 0xff);
702 return 0;
703 }
704
705 /* Fill a rectangle */
706 private int
display_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)707 display_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
708 gx_color_index color)
709 {
710 gx_device_display *ddev = (gx_device_display *) dev;
711 if (ddev->callback == NULL)
712 return 0;
713 dev_proc(ddev->mdev, fill_rectangle)((gx_device *)ddev->mdev,
714 x, y, w, h, color);
715 if (ddev->callback->display_update)
716 (*(ddev->callback->display_update))(ddev->pHandle, dev, x, y, w, h);
717 return 0;
718 }
719
720 /* Copy a monochrome bitmap */
721 private int
display_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)722 display_copy_mono(gx_device * dev,
723 const byte * base, int sourcex, int raster, gx_bitmap_id id,
724 int x, int y, int w, int h,
725 gx_color_index zero, gx_color_index one)
726 {
727 gx_device_display *ddev = (gx_device_display *) dev;
728 if (ddev->callback == NULL)
729 return 0;
730 dev_proc(ddev->mdev, copy_mono)((gx_device *)ddev->mdev,
731 base, sourcex, raster, id, x, y, w, h, zero, one);
732 if (ddev->callback->display_update)
733 (*(ddev->callback->display_update))(ddev->pHandle, dev, x, y, w, h);
734 return 0;
735 }
736
737 /* Copy a color pixel map */
738 private int
display_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)739 display_copy_color(gx_device * dev,
740 const byte * base, int sourcex, int raster, gx_bitmap_id id,
741 int x, int y, int w, int h)
742 {
743 gx_device_display *ddev = (gx_device_display *) dev;
744 if (ddev->callback == NULL)
745 return 0;
746 dev_proc(ddev->mdev, copy_color)((gx_device *)ddev->mdev,
747 base, sourcex, raster, id, x, y, w, h);
748 if (ddev->callback->display_update)
749 (*(ddev->callback->display_update))(ddev->pHandle, dev, x, y, w, h);
750 return 0;
751 }
752
753 private int
display_get_bits(gx_device * dev,int y,byte * str,byte ** actual_data)754 display_get_bits(gx_device * dev, int y, byte * str, byte ** actual_data)
755 {
756 gx_device_display *ddev = (gx_device_display *) dev;
757 if (ddev->callback == NULL)
758 return 0;
759 return dev_proc(ddev->mdev, get_bits)((gx_device *)ddev->mdev,
760 y, str, actual_data);
761 }
762
763 private int
display_get_params(gx_device * dev,gs_param_list * plist)764 display_get_params(gx_device * dev, gs_param_list * plist)
765 {
766 gx_device_display *ddev = (gx_device_display *) dev;
767 int code;
768 gs_param_string dhandle;
769 int idx;
770 int val;
771 int i = 0;
772 size_t dptr;
773 char buf[64];
774
775 idx = ((int)sizeof(size_t)) * 8 - 4;
776 buf[i++] = '1';
777 buf[i++] = '6';
778 buf[i++] = '#';
779 dptr = (size_t)(ddev->pHandle);
780 while (idx >= 0) {
781 val = (int)(dptr >> idx) & 0xf;
782 if (val <= 9)
783 buf[i++] = '0' + val;
784 else
785 buf[i++] = 'a' - 10 + val;
786 idx -= 4;
787 }
788 buf[i] = '\0';
789
790 param_string_from_transient_string(dhandle, buf);
791
792 code = gx_default_get_params(dev, plist);
793 (void)(code < 0 ||
794 (code = param_write_string(plist,
795 "DisplayHandle", &dhandle)) < 0 ||
796 (code = param_write_int(plist,
797 "DisplayFormat", &ddev->nFormat)) < 0 ||
798 (code = param_write_float(plist,
799 "DisplayResolution", &ddev->HWResolution[1])) < 0);
800 if (code >= 0 &&
801 (ddev->nFormat & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_SEPARATION)
802 code = devn_get_params(dev, plist, &ddev->devn_params,
803 &ddev->equiv_cmyk_colors);
804 return code;
805 }
806
807 /* Put parameters. */
808 /* The parameters "DisplayHandle" and "DisplayFormat"
809 * can be changed when the device is closed, but not when open.
810 * The device width and height can be changed when open.
811 */
812 private int
display_put_params(gx_device * dev,gs_param_list * plist)813 display_put_params(gx_device * dev, gs_param_list * plist)
814 {
815 gx_device_display *ddev = (gx_device_display *) dev;
816 int ecode = 0, code;
817 bool is_open = dev->is_open;
818 gs_param_float_array hwra;
819 float dispres = 0.0;
820
821 int old_width = dev->width;
822 int old_height = dev->height;
823 int old_format = ddev->nFormat;
824 void *old_handle = ddev->pHandle;
825
826 gs_devn_params *pdevn_params = &ddev->devn_params;
827 equivalent_cmyk_color_params *pequiv_colors = &ddev->equiv_cmyk_colors;
828 /* Save current data in case we have a problem */
829 gs_devn_params saved_devn_params = *pdevn_params;
830 equivalent_cmyk_color_params saved_equiv_colors = *pequiv_colors;
831
832 int format;
833 void *handle;
834 int found_string_handle = 0;
835 gs_param_string dh = { 0 };
836
837 /* Handle extra parameters */
838
839 switch (code = param_read_int(plist, "DisplayFormat", &format)) {
840 case 0:
841 if (dev->is_open) {
842 if (ddev->nFormat != format)
843 ecode = gs_error_rangecheck;
844 else
845 break;
846 }
847 else {
848 code = display_set_color_format(ddev, format);
849 if (code < 0)
850 ecode = code;
851 else
852 break;
853 }
854 goto cfe;
855 default:
856 ecode = code;
857 cfe:param_signal_error(plist, "DisplayFormat", ecode);
858 case 1:
859 break;
860 }
861
862 /* 64-bit systems need to use DisplayHandle as a string */
863 switch (code = param_read_string(plist, "DisplayHandle", &dh)) {
864 case 0:
865 found_string_handle = 1;
866 break;
867 default:
868 if ((code == gs_error_typecheck) && (sizeof(size_t) <= 4)) {
869 /* 32-bit systems can use the older long type */
870 switch (code = param_read_long(plist, "DisplayHandle",
871 (long *)(&handle))) {
872 case 0:
873 if (dev->is_open) {
874 if (ddev->pHandle != handle)
875 ecode = gs_error_rangecheck;
876 else
877 break;
878 }
879 else {
880 ddev->pHandle = handle;
881 break;
882 }
883 goto hdle;
884 default:
885 ecode = code;
886 hdle:param_signal_error(plist, "DisplayHandle", ecode);
887 case 1:
888 break;
889 }
890 break;
891 }
892 ecode = code;
893 param_signal_error(plist, "DisplayHandle", ecode);
894 /* fall through */
895 case 1:
896 dh.data = 0;
897 break;
898 }
899 if (found_string_handle) {
900 /*
901 * Convert from a string to a pointer.
902 * It is assumed that size_t has the same size as a pointer.
903 * Allow formats (1234), (10#1234) or (16#04d2).
904 */
905 size_t ptr = 0;
906 int i;
907 int base = 10;
908 int val;
909 code = 0;
910 for (i=0; i<dh.size; i++) {
911 val = dh.data[i];
912 if ((val >= '0') && (val <= '9'))
913 val = val - '0';
914 else if ((val >= 'A') && (val <= 'F'))
915 val = val - 'A' + 10;
916 else if ((val >= 'a') && (val <= 'f'))
917 val = val - 'a' + 10;
918 else if (val == '#') {
919 base = (int)ptr;
920 ptr = 0;
921 if ((base != 10) && (base != 16)) {
922 code = gs_error_rangecheck;
923 break;
924 }
925 continue;
926 }
927 else {
928 code = gs_error_rangecheck;
929 break;
930 }
931
932 if (base == 10)
933 ptr = ptr * 10 + val;
934 else if (base == 16)
935 ptr = ptr * 16 + val;
936 else {
937 code = gs_error_rangecheck;
938 break;
939 }
940 }
941 if (code == 0) {
942 if (dev->is_open) {
943 if (ddev->pHandle != (void *)ptr)
944 code = gs_error_rangecheck;
945 }
946 else
947 ddev->pHandle = (void *)ptr;
948 }
949 if (code < 0) {
950 ecode = code;
951 param_signal_error(plist, "DisplayHandle", ecode);
952 }
953 }
954
955 /*
956 * Set the initial display resolution.
957 * If HWResolution is explicitly set, e.g. using -rDPI on the
958 * command line, then use that. Otherwise, use DisplayResolution
959 * which is typically set by the client to the display
960 * logical resolution. Once either of these have been
961 * used, ignore all further DisplayResolution parameters.
962 */
963 if (param_read_float_array(plist, "HWResolution", &hwra) == 0)
964 ddev->HWResolution_set = 1;
965
966 switch (code = param_read_float(plist, "DisplayResolution", &dispres)) {
967 case 0:
968 if (!ddev->HWResolution_set) {
969 gx_device_set_resolution(dev, dispres, dispres);
970 ddev->HWResolution_set = 1;
971 }
972 break;
973 default:
974 ecode = code;
975 param_signal_error(plist, "DisplayResolution", ecode);
976 case 1:
977 break;
978 }
979
980 if (ecode >= 0 &&
981 (ddev->nFormat & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_SEPARATION) {
982 /* Use utility routine to handle devn parameters */
983 ecode = devn_put_params(dev, plist, pdevn_params, pequiv_colors);
984 /*
985 * Setting MaxSeparations changes color_info.depth in
986 * devn_put_params, but we always use 64bpp,
987 * so reset it to the the correct value.
988 */
989 dev->color_info.depth = arch_sizeof_color_index * 8;
990 }
991
992 if (ecode >= 0) {
993 /* Prevent gx_default_put_params from closing the device. */
994 dev->is_open = false;
995 ecode = gx_default_put_params(dev, plist);
996 dev->is_open = is_open;
997 }
998 if (ecode < 0) {
999 /* If we have an error then restore original data. */
1000 *pdevn_params = saved_devn_params;
1001 *pequiv_colors = saved_equiv_colors;
1002 if (format != old_format)
1003 display_set_color_format(ddev, old_format);
1004 ddev->pHandle = old_handle;
1005 dev->width = old_width;
1006 dev->height = old_height;
1007 return ecode;
1008 }
1009
1010
1011 if ( is_open && ddev->callback &&
1012 ((old_width != dev->width) || (old_height != dev->height)) ) {
1013 /* We can resize this device while it is open, but we cannot
1014 * change the color format or handle.
1015 */
1016 /* Tell caller we are about to change the device parameters */
1017 if ((*ddev->callback->display_presize)(ddev->pHandle, dev,
1018 dev->width, dev->height, display_raster(ddev),
1019 ddev->nFormat) < 0) {
1020 /* caller won't let us change the size */
1021 /* restore parameters then return an error */
1022 *pdevn_params = saved_devn_params;
1023 *pequiv_colors = saved_equiv_colors;
1024 display_set_color_format(ddev, old_format);
1025 ddev->nFormat = old_format;
1026 ddev->pHandle = old_handle;
1027 dev->width = old_width;
1028 dev->height = old_height;
1029 return_error(gs_error_rangecheck);
1030 }
1031
1032 display_free_bitmap(ddev);
1033
1034 code = display_alloc_bitmap(ddev, dev);
1035 if (code < 0) {
1036 /* No bitmap, so tell the caller it is zero size */
1037 (*ddev->callback->display_size)(ddev->pHandle, dev,
1038 0, 0, 0, ddev->nFormat, NULL);
1039 return_error(code);
1040 }
1041
1042 /* tell caller about the new size */
1043 if ((*ddev->callback->display_size)(ddev->pHandle, dev,
1044 dev->width, dev->height, display_raster(ddev),
1045 ddev->nFormat, ddev->mdev->base) < 0)
1046 return_error(gs_error_rangecheck);
1047 }
1048
1049 return 0;
1050 }
1051
1052 /* Clean up the instance after making a copy. */
1053 int
display_finish_copydevice(gx_device * dev,const gx_device * from_dev)1054 display_finish_copydevice(gx_device *dev, const gx_device *from_dev)
1055 {
1056 gx_device_display *ddev = (gx_device_display *) dev;
1057
1058 /* Mark the new instance as closed. */
1059 ddev->is_open = false;
1060
1061 /* Clear pointers */
1062 ddev->mdev = NULL;
1063 ddev->pBitmap = NULL;
1064 ddev->ulBitmapSize = 0;
1065
1066 return 0;
1067 }
1068
1069 /*
1070 * The following procedures are used to map the standard color spaces into
1071 * the separation color components for the display device.
1072 */
1073 private void
display_separation_gray_cs_to_cmyk_cm(gx_device * dev,frac gray,frac out[])1074 display_separation_gray_cs_to_cmyk_cm(gx_device * dev, frac gray, frac out[])
1075 {
1076 int * map =
1077 (int *)(&((gx_device_display *) dev)->devn_params.separation_order_map);
1078
1079 gray_cs_to_devn_cm(dev, map, gray, out);
1080 }
1081
1082 private void
display_separation_rgb_cs_to_cmyk_cm(gx_device * dev,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])1083 display_separation_rgb_cs_to_cmyk_cm(gx_device * dev,
1084 const gs_imager_state *pis, frac r, frac g, frac b, frac out[])
1085 {
1086 int * map =
1087 (int *)(&((gx_device_display *) dev)->devn_params.separation_order_map);
1088
1089 rgb_cs_to_devn_cm(dev, map, pis, r, g, b, out);
1090 }
1091
1092 private void
display_separation_cmyk_cs_to_cmyk_cm(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])1093 display_separation_cmyk_cs_to_cmyk_cm(gx_device * dev,
1094 frac c, frac m, frac y, frac k, frac out[])
1095 {
1096 int * map =
1097 (int *)(&((gx_device_display *) dev)->devn_params.separation_order_map);
1098
1099 cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
1100 }
1101
1102 private const gx_cm_color_map_procs display_separation_cm_procs = {
1103 display_separation_gray_cs_to_cmyk_cm,
1104 display_separation_rgb_cs_to_cmyk_cm,
1105 display_separation_cmyk_cs_to_cmyk_cm
1106 };
1107
1108 private const gx_cm_color_map_procs *
display_separation_get_color_mapping_procs(const gx_device * dev)1109 display_separation_get_color_mapping_procs(const gx_device * dev)
1110 {
1111 return &display_separation_cm_procs;
1112 }
1113
1114
1115 /*
1116 * Encode a list of colorant values into a gx_color_index_value.
1117 */
1118 private gx_color_index
display_separation_encode_color(gx_device * dev,const gx_color_value colors[])1119 display_separation_encode_color(gx_device *dev, const gx_color_value colors[])
1120 {
1121 int bpc = ((gx_device_display *)dev)->devn_params.bitspercomponent;
1122 int drop = sizeof(gx_color_value) * 8 - bpc;
1123 gx_color_index color = 0;
1124 int i = 0;
1125 int ncomp = dev->color_info.num_components;
1126
1127 for (; i<ncomp; i++) {
1128 color <<= bpc;
1129 color |= (colors[i] >> drop);
1130 }
1131 if (bpc*ncomp < arch_sizeof_color_index * 8)
1132 color <<= (arch_sizeof_color_index * 8 - ncomp * bpc);
1133 return (color == gx_no_color_index ? color ^ 1 : color);
1134 }
1135
1136 /*
1137 * Decode a gx_color_index value back to a list of colorant values.
1138 */
1139 private int
display_separation_decode_color(gx_device * dev,gx_color_index color,gx_color_value * out)1140 display_separation_decode_color(gx_device * dev, gx_color_index color,
1141 gx_color_value * out)
1142 {
1143 int bpc = ((gx_device_display *)dev)->devn_params.bitspercomponent;
1144 int drop = sizeof(gx_color_value) * 8 - bpc;
1145 int mask = (1 << bpc) - 1;
1146 int i = 0;
1147 int ncomp = dev->color_info.num_components;
1148
1149 if (bpc*ncomp < arch_sizeof_color_index * 8)
1150 color >>= (arch_sizeof_color_index * 8 - ncomp * bpc);
1151 for (; i<ncomp; i++) {
1152 out[ncomp - i - 1] = (gx_color_value) ((color & mask) << drop);
1153 color >>= bpc;
1154 }
1155 return 0;
1156 }
1157
1158 /*
1159 * Device proc for updating the equivalent CMYK color for spot colors.
1160 */
1161 private int
display_update_spot_equivalent_colors(gx_device * dev,const gs_state * pgs)1162 display_update_spot_equivalent_colors(gx_device * dev, const gs_state * pgs)
1163 {
1164 gx_device_display * ddev = (gx_device_display *)dev;
1165
1166 if ((ddev->nFormat & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_SEPARATION)
1167 update_spot_equivalent_cmyk_colors(dev, pgs,
1168 &ddev->devn_params, &ddev->equiv_cmyk_colors);
1169 return 0;
1170 }
1171
1172 /*
1173 * This routine will check to see if the color component name match those
1174 * that are available amoung the current device's color components.
1175 *
1176 * Parameters:
1177 * dev - pointer to device data structure.
1178 * pname - pointer to name (zero termination not required)
1179 * nlength - length of the name
1180 *
1181 * This routine returns a positive value (0 to n) which is the device colorant
1182 * number if the name is found. It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
1183 * the colorant is not being used due to a SeparationOrder device parameter.
1184 * It returns a negative value if not found.
1185 */
1186 private int
display_separation_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)1187 display_separation_get_color_comp_index(gx_device * dev,
1188 const char * pname, int name_size, int component_type)
1189 {
1190 return devn_get_color_comp_index(dev,
1191 &(((gx_device_display *)dev)->devn_params),
1192 &(((gx_device_display *)dev)->equiv_cmyk_colors),
1193 pname, name_size, component_type, ENABLE_AUTO_SPOT_COLORS);
1194 }
1195
1196
1197 /* ------ Internal routines ------ */
1198
1199 /* Make sure we have been given a valid structure */
1200 /* Return 0 on success, gs_error_rangecheck on failure */
display_check_structure(gx_device_display * ddev)1201 private int display_check_structure(gx_device_display *ddev)
1202 {
1203 if (ddev->callback == 0)
1204 return_error(gs_error_rangecheck);
1205
1206 if (ddev->callback->size == sizeof(struct display_callback_v1_s)) {
1207 /* Original V1 structure */
1208 if (ddev->callback->version_major != DISPLAY_VERSION_MAJOR_V1)
1209 return_error(gs_error_rangecheck);
1210
1211 /* complain if caller asks for newer features */
1212 if (ddev->callback->version_minor > DISPLAY_VERSION_MINOR_V1)
1213 return_error(gs_error_rangecheck);
1214 }
1215 else {
1216 /* V2 structure with added display_separation callback */
1217 if (ddev->callback->size != sizeof(display_callback))
1218 return_error(gs_error_rangecheck);
1219
1220 if (ddev->callback->version_major != DISPLAY_VERSION_MAJOR)
1221 return_error(gs_error_rangecheck);
1222
1223 /* complain if caller asks for newer features */
1224 if (ddev->callback->version_minor > DISPLAY_VERSION_MINOR)
1225 return_error(gs_error_rangecheck);
1226 }
1227
1228 if ((ddev->callback->display_open == NULL) ||
1229 (ddev->callback->display_close == NULL) ||
1230 (ddev->callback->display_presize == NULL) ||
1231 (ddev->callback->display_size == NULL) ||
1232 (ddev->callback->display_sync == NULL) ||
1233 (ddev->callback->display_page == NULL))
1234 return_error(gs_error_rangecheck);
1235
1236 /* Don't test display_update, display_memalloc or display_memfree
1237 * since these may be NULL if not provided.
1238 * Don't test display_separation, since this may be NULL if
1239 * separation format is not supported.
1240 */
1241
1242 return 0;
1243 }
1244
1245 private void
display_free_bitmap(gx_device_display * ddev)1246 display_free_bitmap(gx_device_display * ddev)
1247 {
1248 if (ddev->callback == NULL)
1249 return;
1250 if (ddev->pBitmap) {
1251 if (ddev->callback->display_memalloc
1252 && ddev->callback->display_memfree
1253 && ddev->pBitmap) {
1254 (*ddev->callback->display_memfree)(ddev->pHandle, ddev,
1255 ddev->pBitmap);
1256 }
1257 else {
1258 gs_free_object(ddev->memory->non_gc_memory,
1259 ddev->pBitmap, "display_free_bitmap");
1260 }
1261 ddev->pBitmap = NULL;
1262 if (ddev->mdev)
1263 ddev->mdev->base = NULL;
1264 }
1265 if (ddev->mdev) {
1266 dev_proc(ddev->mdev, close_device)((gx_device *)ddev->mdev);
1267 gx_device_retain((gx_device *)(ddev->mdev), false);
1268 ddev->mdev = NULL;
1269 }
1270 }
1271
1272 /* calculate byte length of a row */
1273 private int
display_raster(gx_device_display * dev)1274 display_raster(gx_device_display *dev)
1275 {
1276 int align = 0;
1277 int bytewidth = dev->width * dev->color_info.depth/8;
1278 switch (dev->nFormat & DISPLAY_ROW_ALIGN_MASK) {
1279 case DISPLAY_ROW_ALIGN_4:
1280 align = 4;
1281 break;
1282 case DISPLAY_ROW_ALIGN_8:
1283 align = 8;
1284 break;
1285 case DISPLAY_ROW_ALIGN_16:
1286 align = 16;
1287 break;
1288 case DISPLAY_ROW_ALIGN_32:
1289 align = 32;
1290 break;
1291 case DISPLAY_ROW_ALIGN_64:
1292 align = 64;
1293 break;
1294 }
1295 if (align < ARCH_ALIGN_PTR_MOD)
1296 align = ARCH_ALIGN_PTR_MOD;
1297 align -= 1;
1298 bytewidth = (bytewidth + align) & (~align);
1299 return bytewidth;
1300 }
1301
1302 /* Allocate the backing bitmap. */
1303 private int
display_alloc_bitmap(gx_device_display * ddev,gx_device * param_dev)1304 display_alloc_bitmap(gx_device_display * ddev, gx_device * param_dev)
1305 {
1306 int ccode;
1307 const gx_device_memory *mdproto;
1308 if (ddev->callback == NULL)
1309 return 0;
1310
1311 /* free old bitmap (if any) */
1312 display_free_bitmap(ddev);
1313
1314 /* allocate a memory device for rendering */
1315 mdproto = gdev_mem_device_for_bits(ddev->color_info.depth);
1316 if (mdproto == 0)
1317 return_error(gs_error_rangecheck);
1318
1319 ddev->mdev = gs_alloc_struct(gs_memory_stable(ddev->memory),
1320 gx_device_memory, &st_device_memory, "display_memory_device");
1321 if (ddev->mdev == 0)
1322 return_error(gs_error_VMerror);
1323
1324 gs_make_mem_device(ddev->mdev, mdproto, gs_memory_stable(ddev->memory),
1325 0, (gx_device *) NULL);
1326 check_device_separable((gx_device *)(ddev->mdev));
1327 gx_device_fill_in_procs((gx_device *)(ddev->mdev));
1328 /* Mark the memory device as retained. When the bitmap is closed,
1329 * we will clear this and the memory device will be then be freed.
1330 */
1331 gx_device_retain((gx_device *)(ddev->mdev), true);
1332
1333 /* Memory device width may be larger than device width
1334 * if row alignment is not 4.
1335 */
1336 ddev->mdev->width = param_dev->width;
1337 ddev->mdev->width = display_raster(ddev) * 8 / ddev->color_info.depth;
1338 ddev->mdev->height = param_dev->height;
1339
1340 /* Tell the memory device to allocate the line pointers separately
1341 * so we can place the bitmap in special memory.
1342 */
1343 ddev->mdev->line_pointer_memory = ddev->mdev->memory;
1344 ddev->ulBitmapSize = gdev_mem_bits_size(ddev->mdev,
1345 ddev->mdev->width, ddev->mdev->height);
1346
1347 /* allocate bitmap using an allocator not subject to GC */
1348 if (ddev->callback->display_memalloc
1349 && ddev->callback->display_memfree) {
1350 ddev->pBitmap = (*ddev->callback->display_memalloc)(ddev->pHandle,
1351 ddev, ddev->ulBitmapSize);
1352 }
1353 else {
1354 ddev->pBitmap = gs_alloc_byte_array_immovable(ddev->memory->non_gc_memory,
1355 (uint)ddev->ulBitmapSize, 1, "display_alloc_bitmap");
1356 }
1357
1358 if (ddev->pBitmap == NULL) {
1359 ddev->mdev->width = 0;
1360 ddev->mdev->height = 0;
1361 return_error(gs_error_VMerror);
1362 }
1363
1364 ddev->mdev->base = (byte *) ddev->pBitmap;
1365 ddev->mdev->foreign_bits = true;
1366
1367 ccode = dev_proc(ddev->mdev, open_device)((gx_device *)ddev->mdev);
1368 if (ccode < 0)
1369 display_free_bitmap(ddev);
1370
1371 /* erase bitmap - before display gets redrawn */
1372 if (ccode == 0) {
1373 int i;
1374 gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1375 for (i=0; i<GX_DEVICE_COLOR_MAX_COMPONENTS; i++)
1376 cv[i] = (ddev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
1377 ? gx_max_color_value : 0;
1378 dev_proc(ddev, fill_rectangle)((gx_device *)ddev,
1379 0, 0, ddev->width, ddev->height,
1380 ddev->procs.encode_color((gx_device *)ddev, cv));
1381 }
1382
1383 return ccode;
1384 }
1385
1386 private int
display_set_separations(gx_device_display * dev)1387 display_set_separations(gx_device_display *dev)
1388 {
1389 if (((dev->nFormat & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_SEPARATION) &&
1390 (dev->callback->version_major > DISPLAY_VERSION_MAJOR_V1) &&
1391 (dev->callback->display_separation != NULL)) {
1392 /* Tell the client about the separation to composite mapping */
1393 char name[64];
1394 int num_spot = dev->devn_params.separations.num_separations;
1395 int num_std_colorants = dev->devn_params.num_std_colorant_names;
1396 int num_comp = num_std_colorants + num_spot;
1397 int comp_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
1398 int comp_num;
1399 int sep_num;
1400 int sep_name_size;
1401 unsigned int c, m, y, k;
1402
1403 /* Map the separation numbers to component numbers */
1404 memset(comp_map, 0, sizeof(comp_map));
1405 for (sep_num = 0; sep_num < num_comp; sep_num++) {
1406 comp_num = dev->devn_params.separation_order_map[sep_num];
1407 if (comp_num >= 0 && comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS)
1408 comp_map[comp_num] = sep_num;
1409 }
1410 /* For each component, tell the client the separation mapping */
1411 for (comp_num = 0; comp_num < num_comp; comp_num++) {
1412 c = y = m = k = 0;
1413 sep_num = comp_map[comp_num];
1414 /* Get the CMYK equivalent */
1415 if (sep_num < dev->devn_params.num_std_colorant_names) {
1416 sep_name_size =
1417 strlen(dev->devn_params.std_colorant_names[sep_num]);
1418 if (sep_name_size > sizeof(name)-2)
1419 sep_name_size = sizeof(name)-1;
1420 memcpy(name, dev->devn_params.std_colorant_names[sep_num],
1421 sep_name_size);
1422 name[sep_name_size] = '\0';
1423 switch (sep_num) {
1424 case 0: c = 65535; break;
1425 case 1: m = 65535; break;
1426 case 2: y = 65535; break;
1427 case 3: k = 65535; break;
1428 }
1429 }
1430 else {
1431 sep_num -= dev->devn_params.num_std_colorant_names;
1432 sep_name_size =
1433 dev->devn_params.separations.names[sep_num].size;
1434 if (sep_name_size > sizeof(name)-2)
1435 sep_name_size = sizeof(name)-1;
1436 memcpy(name, dev->devn_params.separations.names[sep_num].data,
1437 sep_name_size);
1438 name[sep_name_size] = '\0';
1439 if (dev->equiv_cmyk_colors.color[sep_num].color_info_valid) {
1440 c = dev->equiv_cmyk_colors.color[sep_num].c
1441 * 65535 / frac_1;
1442 m = dev->equiv_cmyk_colors.color[sep_num].m
1443 * 65535 / frac_1;
1444 y = dev->equiv_cmyk_colors.color[sep_num].y
1445 * 65535 / frac_1;
1446 k = dev->equiv_cmyk_colors.color[sep_num].k
1447 * 65535 / frac_1;
1448 }
1449 }
1450 (*dev->callback->display_separation)(dev->pHandle, dev,
1451 comp_num, name,
1452 (unsigned short)c, (unsigned short)m,
1453 (unsigned short)y, (unsigned short)k);
1454 }
1455 }
1456 return 0;
1457 }
1458
1459 typedef enum DISPLAY_MODEL_e {
1460 DISPLAY_MODEL_GRAY=0,
1461 DISPLAY_MODEL_RGB=1,
1462 DISPLAY_MODEL_RGBK=2,
1463 DISPLAY_MODEL_CMYK=3,
1464 DISPLAY_MODEL_SEP=4
1465 } DISPLAY_MODEL;
1466
1467 /*
1468 * This is a utility routine to build the display device's color_info
1469 * structure (except for the anti alias info).
1470 */
1471 private void
set_color_info(gx_device_color_info * pdci,DISPLAY_MODEL model,int nc,int depth,int maxgray,int maxcolor)1472 set_color_info(gx_device_color_info * pdci, DISPLAY_MODEL model,
1473 int nc, int depth, int maxgray, int maxcolor)
1474 {
1475 pdci->num_components = pdci->max_components = nc;
1476 pdci->depth = depth;
1477 pdci->gray_index = 0;
1478 pdci->max_gray = maxgray;
1479 pdci->max_color = maxcolor;
1480 pdci->dither_grays = maxgray + 1;
1481 pdci->dither_colors = maxcolor + 1;
1482 pdci->separable_and_linear = GX_CINFO_UNKNOWN_SEP_LIN;
1483 switch (model) {
1484 case DISPLAY_MODEL_GRAY:
1485 pdci->polarity = GX_CINFO_POLARITY_ADDITIVE;
1486 pdci->cm_name = "DeviceGray";
1487 pdci->gray_index = 0;
1488 break;
1489 case DISPLAY_MODEL_RGB:
1490 pdci->polarity = GX_CINFO_POLARITY_ADDITIVE;
1491 pdci->cm_name = "DeviceRGB";
1492 pdci->gray_index = GX_CINFO_COMP_NO_INDEX;
1493 break;
1494 case DISPLAY_MODEL_RGBK:
1495 pdci->polarity = GX_CINFO_POLARITY_ADDITIVE;
1496 pdci->cm_name = "DeviceRGBK";
1497 pdci->gray_index = 3;
1498 break;
1499 case DISPLAY_MODEL_CMYK:
1500 pdci->polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
1501 pdci->cm_name = "DeviceCMYK";
1502 pdci->gray_index = 3;
1503 break;
1504 default:
1505 case DISPLAY_MODEL_SEP:
1506 /* Anything else is separations */
1507 pdci->polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
1508 pdci->cm_name = "DeviceCMYK";
1509 pdci->gray_index = GX_CINFO_COMP_NO_INDEX; /* may not have K */
1510 break;
1511 }
1512 }
1513
1514 /*
1515 * This is an utility routine to set up the color procs for the display
1516 * device. The display device can change its setup.
1517 */
1518 private void
1519 set_color_procs(gx_device * pdev,
1520 dev_t_proc_encode_color((*encode_color), gx_device),
1521 dev_t_proc_decode_color((*decode_color), gx_device),
1522 dev_t_proc_get_color_mapping_procs((*get_color_mapping_procs), gx_device),
1523 dev_t_proc_get_color_comp_index((*get_color_comp_index), gx_device))
1524 {
1525 #if 0 /* These procs are no longer used */
1526 pdev->procs.map_rgb_color = encode_color;
1527 pdev->procs.map_color_rgb = decode_color;
1528 #endif
1529 pdev->procs.get_color_mapping_procs = get_color_mapping_procs;
1530 pdev->procs.get_color_comp_index = get_color_comp_index;
1531 pdev->procs.encode_color = encode_color;
1532 pdev->procs.decode_color = decode_color;
1533 }
1534
1535 /*
1536 * This is an utility routine to set up the color procs for the display
1537 * device. This routine is used when the display device is Gray.
1538 */
1539 private void
1540 set_gray_color_procs(gx_device * pdev,
1541 dev_t_proc_encode_color((*encode_color), gx_device),
1542 dev_t_proc_decode_color((*decode_color), gx_device))
1543 {
1544 set_color_procs(pdev, encode_color, decode_color,
1545 gx_default_DevGray_get_color_mapping_procs,
1546 gx_default_DevGray_get_color_comp_index);
1547 }
1548
1549 /*
1550 * This is an utility routine to set up the color procs for the display
1551 * device. This routine is used when the display device is RGB.
1552 */
1553 private void
1554 set_rgb_color_procs(gx_device * pdev,
1555 dev_t_proc_encode_color((*encode_color), gx_device),
1556 dev_t_proc_decode_color((*decode_color), gx_device))
1557 {
1558 set_color_procs(pdev, encode_color, decode_color,
1559 gx_default_DevRGB_get_color_mapping_procs,
1560 gx_default_DevRGB_get_color_comp_index);
1561 }
1562
1563 /*
1564 * This is an utility routine to set up the color procs for the display
1565 * device. This routine is used when the display device is RGBK.
1566 */
1567 private void
1568 set_rgbk_color_procs(gx_device * pdev,
1569 dev_t_proc_encode_color((*encode_color), gx_device),
1570 dev_t_proc_decode_color((*decode_color), gx_device))
1571 {
1572 set_color_procs(pdev, encode_color, decode_color,
1573 gx_default_DevRGBK_get_color_mapping_procs,
1574 gx_default_DevRGBK_get_color_comp_index);
1575 }
1576
1577 /*
1578 * This is an utility routine to set up the color procs for the display
1579 * device. This routine is used when the display device is CMYK.
1580 */
1581 private void
1582 set_cmyk_color_procs(gx_device * pdev,
1583 dev_t_proc_encode_color((*encode_color), gx_device),
1584 dev_t_proc_decode_color((*decode_color), gx_device))
1585 {
1586 set_color_procs(pdev, encode_color, decode_color,
1587 gx_default_DevCMYK_get_color_mapping_procs,
1588 gx_default_DevCMYK_get_color_comp_index);
1589 }
1590
1591 /* Set the color_info and mapping functions for this instance of the device */
1592 private int
display_set_color_format(gx_device_display * ddev,int nFormat)1593 display_set_color_format(gx_device_display *ddev, int nFormat)
1594 {
1595 gx_device * pdev = (gx_device *) ddev;
1596 gx_device_color_info dci = ddev->color_info;
1597 int bpc; /* bits per component */
1598 int bpp; /* bits per pixel */
1599 int maxvalue;
1600 int align;
1601
1602 switch (nFormat & DISPLAY_DEPTH_MASK) {
1603 case DISPLAY_DEPTH_1:
1604 bpc = 1;
1605 break;
1606 case DISPLAY_DEPTH_2:
1607 bpc = 2;
1608 break;
1609 case DISPLAY_DEPTH_4:
1610 bpc = 4;
1611 break;
1612 case DISPLAY_DEPTH_8:
1613 bpc = 8;
1614 break;
1615 case DISPLAY_DEPTH_12:
1616 bpc = 12;
1617 break;
1618 case DISPLAY_DEPTH_16:
1619 bpc = 16;
1620 break;
1621 default:
1622 return_error(gs_error_rangecheck);
1623 }
1624 maxvalue = (1 << bpc) - 1;
1625 ddev->devn_params.bitspercomponent = bpc;
1626
1627 switch (ddev->nFormat & DISPLAY_ROW_ALIGN_MASK) {
1628 case DISPLAY_ROW_ALIGN_DEFAULT:
1629 align = ARCH_ALIGN_PTR_MOD;
1630 break;
1631 case DISPLAY_ROW_ALIGN_4:
1632 align = 4;
1633 break;
1634 case DISPLAY_ROW_ALIGN_8:
1635 align = 8;
1636 break;
1637 case DISPLAY_ROW_ALIGN_16:
1638 align = 16;
1639 break;
1640 case DISPLAY_ROW_ALIGN_32:
1641 align = 32;
1642 break;
1643 case DISPLAY_ROW_ALIGN_64:
1644 align = 64;
1645 break;
1646 default:
1647 align = 0; /* not permitted */
1648 }
1649 if (align < ARCH_ALIGN_PTR_MOD)
1650 return_error(gs_error_rangecheck);
1651
1652 switch (ddev->nFormat & DISPLAY_ALPHA_MASK) {
1653 case DISPLAY_ALPHA_FIRST:
1654 case DISPLAY_ALPHA_LAST:
1655 /* Not implemented and unlikely to ever be implemented
1656 * because they would interact with linear_and_separable
1657 */
1658 return_error(gs_error_rangecheck);
1659 }
1660
1661 switch (nFormat & DISPLAY_COLORS_MASK) {
1662 case DISPLAY_COLORS_NATIVE:
1663 switch (nFormat & DISPLAY_DEPTH_MASK) {
1664 case DISPLAY_DEPTH_1:
1665 /* 1bit/pixel, black is 1, white is 0 */
1666 set_color_info(&dci, DISPLAY_MODEL_GRAY, 1, 1, 1, 0);
1667 dci.separable_and_linear = GX_CINFO_SEP_LIN_NONE;
1668 set_gray_color_procs(pdev, gx_b_w_gray_encode,
1669 gx_default_b_w_map_color_rgb);
1670 break;
1671 case DISPLAY_DEPTH_4:
1672 /* 4bit/pixel VGA color */
1673 set_color_info(&dci, DISPLAY_MODEL_RGB, 3, 4, 3, 2);
1674 dci.separable_and_linear = GX_CINFO_SEP_LIN_NONE;
1675 set_rgb_color_procs(pdev, display_map_rgb_color_device4,
1676 display_map_color_rgb_device4);
1677 break;
1678 case DISPLAY_DEPTH_8:
1679 /* 8bit/pixel 96 color palette */
1680 set_color_info(&dci, DISPLAY_MODEL_RGBK, 4, 8, 31, 3);
1681 dci.separable_and_linear = GX_CINFO_SEP_LIN_NONE;
1682 set_rgbk_color_procs(pdev, display_encode_color_device8,
1683 display_decode_color_device8);
1684 break;
1685 case DISPLAY_DEPTH_16:
1686 /* Windows 16-bit display */
1687 /* Is maxgray = maxcolor = 63 correct? */
1688 if ((ddev->nFormat & DISPLAY_555_MASK)
1689 == DISPLAY_NATIVE_555)
1690 set_color_info(&dci, DISPLAY_MODEL_RGB, 3, 16, 31, 31);
1691 else
1692 set_color_info(&dci, DISPLAY_MODEL_RGB, 3, 16, 63, 63);
1693 set_rgb_color_procs(pdev, display_map_rgb_color_device16,
1694 display_map_color_rgb_device16);
1695 break;
1696 default:
1697 return_error(gs_error_rangecheck);
1698 }
1699 dci.gray_index = GX_CINFO_COMP_NO_INDEX;
1700 break;
1701 case DISPLAY_COLORS_GRAY:
1702 set_color_info(&dci, DISPLAY_MODEL_GRAY, 1, bpc, maxvalue, 0);
1703 if (bpc == 1)
1704 set_gray_color_procs(pdev, gx_default_gray_encode,
1705 gx_default_w_b_map_color_rgb);
1706 else
1707 set_gray_color_procs(pdev, gx_default_gray_encode,
1708 gx_default_gray_map_color_rgb);
1709 break;
1710 case DISPLAY_COLORS_RGB:
1711 if ((nFormat & DISPLAY_ALPHA_MASK) == DISPLAY_ALPHA_NONE)
1712 bpp = bpc * 3;
1713 else
1714 bpp = bpc * 4;
1715 set_color_info(&dci, DISPLAY_MODEL_RGB, 3, bpp, maxvalue, maxvalue);
1716 if (((nFormat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) &&
1717 ((nFormat & DISPLAY_ALPHA_MASK) == DISPLAY_ALPHA_NONE)) {
1718 if ((nFormat & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN)
1719 set_rgb_color_procs(pdev, gx_default_rgb_map_rgb_color,
1720 gx_default_rgb_map_color_rgb);
1721 else
1722 set_rgb_color_procs(pdev, display_map_rgb_color_bgr24,
1723 display_map_color_rgb_bgr24);
1724 }
1725 else {
1726 /* slower flexible functions for alpha/unused component */
1727 set_rgb_color_procs(pdev, display_map_rgb_color_rgb,
1728 display_map_color_rgb_rgb);
1729 }
1730 break;
1731 case DISPLAY_COLORS_CMYK:
1732 bpp = bpc * 4;
1733 set_color_info(&dci, DISPLAY_MODEL_CMYK, 4, bpp, maxvalue, maxvalue);
1734 if ((nFormat & DISPLAY_ALPHA_MASK) != DISPLAY_ALPHA_NONE)
1735 return_error(gs_error_rangecheck);
1736 if ((nFormat & DISPLAY_ENDIAN_MASK) != DISPLAY_BIGENDIAN)
1737 return_error(gs_error_rangecheck);
1738
1739 if ((nFormat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1)
1740 set_cmyk_color_procs(pdev, cmyk_1bit_map_cmyk_color,
1741 cmyk_1bit_map_color_cmyk);
1742 else if ((nFormat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8)
1743 set_cmyk_color_procs(pdev, cmyk_8bit_map_cmyk_color,
1744 cmyk_8bit_map_color_cmyk);
1745 else
1746 return_error(gs_error_rangecheck);
1747 break;
1748 case DISPLAY_COLORS_SEPARATION:
1749 if ((nFormat & DISPLAY_ENDIAN_MASK) != DISPLAY_BIGENDIAN)
1750 return_error(gs_error_rangecheck);
1751 bpp = arch_sizeof_color_index * 8;
1752 set_color_info(&dci, DISPLAY_MODEL_SEP, bpp/bpc, bpp,
1753 maxvalue, maxvalue);
1754 if ((nFormat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
1755 ddev->devn_params.bitspercomponent = bpc;
1756 set_color_procs(pdev,
1757 display_separation_encode_color,
1758 display_separation_decode_color,
1759 display_separation_get_color_mapping_procs,
1760 display_separation_get_color_comp_index);
1761 }
1762 else
1763 return_error(gs_error_rangecheck);
1764 break;
1765 default:
1766 return_error(gs_error_rangecheck);
1767 }
1768
1769 /* restore old anti_alias info */
1770 dci.anti_alias = ddev->color_info.anti_alias;
1771 ddev->color_info = dci;
1772 check_device_separable(pdev);
1773 switch (nFormat & DISPLAY_COLORS_MASK) {
1774 case DISPLAY_COLORS_NATIVE:
1775 ddev->color_info.gray_index = GX_CINFO_COMP_NO_INDEX;
1776 if ((nFormat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1)
1777 ddev->color_info.gray_index = 0;
1778 else if ((nFormat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8)
1779 ddev->color_info.gray_index = 3;
1780 break;
1781 case DISPLAY_COLORS_RGB:
1782 ddev->color_info.gray_index = GX_CINFO_COMP_NO_INDEX;
1783 break;
1784 case DISPLAY_COLORS_GRAY:
1785 ddev->color_info.gray_index = 0;
1786 break;
1787 case DISPLAY_COLORS_CMYK:
1788 ddev->color_info.gray_index = 3;
1789 break;
1790 case DISPLAY_COLORS_SEPARATION:
1791 ddev->color_info.gray_index = GX_CINFO_COMP_NO_INDEX;
1792 break;
1793 }
1794 ddev->nFormat = nFormat;
1795
1796 return 0;
1797 }
1798
1799 /* ------ Begin Test Code ------ */
1800
1801 /*********************************************************************
1802 typedef struct test_mode_s test_mode;
1803 struct test_mode_s {
1804 char *name;
1805 unsigned int format;
1806 };
1807
1808 test_mode test_modes[] = {
1809 {"1bit/pixel native, black is 1, Windows",
1810 DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_1 |
1811 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST},
1812 {"4bit/pixel native, Windows VGA 16 color palette",
1813 DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_4 |
1814 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST},
1815 {"8bit/pixel native, Windows SVGA 96 color palette",
1816 DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1817 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST},
1818 {"16bit/pixel native, Windows BGR555",
1819 DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_16 |
1820 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST | DISPLAY_NATIVE_555},
1821 {"16bit/pixel native, Windows BGR565",
1822 DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_16 |
1823 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST | DISPLAY_NATIVE_565},
1824 {"1bit/pixel gray, black is 0, topfirst",
1825 DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_1 |
1826 DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST},
1827 {"4bit/pixel gray, bottom first",
1828 DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_4 |
1829 DISPLAY_BIGENDIAN | DISPLAY_BOTTOMFIRST},
1830 {"8bit/pixel gray, bottom first",
1831 DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1832 DISPLAY_BIGENDIAN | DISPLAY_BOTTOMFIRST},
1833 {"24bit/pixel color, bottom first, Windows BGR24",
1834 DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1835 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST},
1836 {"24bit/pixel color, bottom first, RGB24",
1837 DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1838 DISPLAY_BIGENDIAN | DISPLAY_BOTTOMFIRST},
1839 {"24bit/pixel color, top first, GdkRgb RGB24",
1840 DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1841 DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST},
1842 {"32bit/pixel color, top first, Macintosh xRGB",
1843 DISPLAY_COLORS_RGB | DISPLAY_UNUSED_FIRST | DISPLAY_DEPTH_8 |
1844 DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST},
1845 {"32bit/pixel color, bottom first, xBGR",
1846 DISPLAY_COLORS_RGB | DISPLAY_UNUSED_FIRST | DISPLAY_DEPTH_8 |
1847 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST},
1848 {"32bit/pixel color, bottom first, Windows BGRx",
1849 DISPLAY_COLORS_RGB | DISPLAY_UNUSED_LAST | DISPLAY_DEPTH_8 |
1850 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST},
1851 {"32bit/pixel color, bottom first, RGBx",
1852 DISPLAY_COLORS_RGB | DISPLAY_UNUSED_LAST | DISPLAY_DEPTH_8 |
1853 DISPLAY_BIGENDIAN | DISPLAY_BOTTOMFIRST},
1854 {"32bit/pixel CMYK, bottom first",
1855 DISPLAY_COLORS_CMYK | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1856 DISPLAY_BIGENDIAN | DISPLAY_BOTTOMFIRST},
1857 {"64bit/pixel separations, bottom first",
1858 DISPLAY_COLORS_SEPARATIONS | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1859 DISPLAY_BIGENDIAN | DISPLAY_BOTTOMFIRST},
1860 {"4bit/pixel CMYK, bottom first",
1861 DISPLAY_COLORS_CMYK | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_1 |
1862 DISPLAY_BIGENDIAN | DISPLAY_BOTTOMFIRST},
1863 {"1bit/pixel native, black is 1, 8 byte alignment",
1864 DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_1 |
1865 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST | DISPLAY_ROW_ALIGN_8},
1866 {"24bit/pixel color, bottom first, BGR24, 64 byte alignment",
1867 DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 |
1868 DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST | DISPLAY_ROW_ALIGN_64}
1869 };
1870
1871 void
1872 test(int index)
1873 {
1874 char buf[1024];
1875 sprintf(buf, "gs -dDisplayFormat=16#%x examples/colorcir.ps -c quit", test_modes[index].format);
1876 system(buf);
1877 }
1878
1879 int main(int argc, char *argv[])
1880 {
1881 int i;
1882 int dotest = 0;
1883 if (argc >=2) {
1884 if (strcmp(argv[1], "-t") == 0)
1885 dotest = 1;
1886 else {
1887 fprintf(stdout, "To show modes: disp\nTo run test: disp -t\n");
1888 return 1;
1889 }
1890 }
1891 for (i=0; i < sizeof(test_modes)/sizeof(test_mode); i++) {
1892 fprintf(stdout, "16#%x or %d: %s\n", test_modes[i].format,
1893 test_modes[i].format, test_modes[i].name);
1894 if (dotest)
1895 test(i);
1896 }
1897 return 0;
1898 }
1899 *********************************************************************/
1900
1901 /* ------ End Test Code ------ */
1902