~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/gdevdsp.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

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