Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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 */
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
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 
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
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 
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
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
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 ------ */