1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied,
8
modified or distributed except as expressly authorized under the terms
9
of the license contained in the file LICENSE in this distribution.
11
Refer to licensing information at http://www.artifex.com or contact
12
Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13
CA 94903, U.S.A., +1(415)492-9861, for further information.
17
* Microsoft Windows 3.n driver for Ghostscript.
19
* Original version by Russell Lang and Maurice Castro with help from
20
* Programming Windows, 2nd Ed., Charles Petzold, Microsoft Press;
21
* created from gdevbgi.c and gnuplot/term/win.trm 5th June 1992.
22
* Extensively modified by L. Peter Deutsch, Aladdin Enterprises.
31
/* Forward references */
32
static int win_set_bits_per_pixel(gx_device_win *, int);
36
/* Open the win driver */
38
win_open(gx_device * dev)
43
if (dev->width == INITIAL_WIDTH)
44
dev->width = (int)(8.5 * dev->x_pixels_per_inch);
45
if (dev->height == INITIAL_HEIGHT)
46
dev->height = (int)(11.0 * dev->y_pixels_per_inch);
48
if (wdev->BitsPerPixel == 0) {
51
/* Set parameters that were unknown before opening device */
52
/* Find out if the device supports color */
53
/* We recognize 1, 4, 8, 16, 24 bit/pixel devices */
54
hdc = GetDC(NULL); /* get hdc for desktop */
55
depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
57
wdev->BitsPerPixel = 24;
58
} else if (depth > 8) {
59
wdev->BitsPerPixel = 16;
60
} else if (depth >= 8) {
61
wdev->BitsPerPixel = 8;
62
} else if (depth >= 4) {
63
wdev->BitsPerPixel = 4;
65
wdev->BitsPerPixel = 1;
68
wdev->mapped_color_flags = 0;
70
if ((code = win_set_bits_per_pixel(wdev, wdev->BitsPerPixel)) < 0)
73
if (wdev->nColors > 0) {
74
/* create palette for display */
75
if ((wdev->limgpalette = win_makepalette(wdev))
76
== (LPLOGPALETTE) NULL)
77
return win_nomemory();
78
wdev->himgpalette = CreatePalette(wdev->limgpalette);
83
/* Make the output appear on the screen. */
85
win_sync_output(gx_device * dev)
88
(*pgsdll_callback) (GSDLL_SYNC, (unsigned char *)wdev, 0);
92
/* Make the window visible, and display the output. */
94
win_output_page(gx_device * dev, int copies, int flush)
97
(*pgsdll_callback) (GSDLL_PAGE, (unsigned char *)wdev, 0);
98
return gx_finish_output_page(dev, copies, flush);;
101
/* Close the win driver */
103
win_close(gx_device * dev)
106
if (wdev->nColors > 0) {
108
wdev->mapped_color_flags, 4096, 1, "win_set_bits_per_pixel");
109
DeleteObject(wdev->himgpalette);
111
(char *)(wdev->limgpalette), 1, sizeof(LOGPALETTE) +
112
(1 << (wdev->color_info.depth)) * sizeof(PALETTEENTRY),
118
/* Map a r-g-b color to the colors available under Windows */
120
win_map_rgb_color(gx_device * dev, const gx_color_value cv[])
122
gx_color_value r = cv[0];
123
gx_color_value g = cv[1];
124
gx_color_value b = cv[2];
125
switch (wdev->BitsPerPixel) {
127
return (((unsigned long)b >> (gx_color_value_bits - 8)) << 16) +
128
(((unsigned long)g >> (gx_color_value_bits - 8)) << 8) +
129
(((unsigned long)r >> (gx_color_value_bits - 8)));
131
gx_color_index color = ((r >> (gx_color_value_bits - 5)) << 11) +
132
((g >> (gx_color_value_bits - 6)) << 5) +
133
(b >> (gx_color_value_bits - 5));
134
#if arch_is_big_endian
135
ushort color16 = (ushort)color;
137
ushort color16 = (ushort)((color << 8) | (color >> 8));
142
gx_color_index color = ((r >> (gx_color_value_bits - 5)) << 10) +
143
((g >> (gx_color_value_bits - 5)) << 5) +
144
(b >> (gx_color_value_bits - 5));
145
#if arch_is_big_endian
146
ushort color15 = (ushort)color;
148
ushort color15 = (ushort)((color << 8) | (color >> 8));
154
LPLOGPALETTE lpal = wdev->limgpalette;
160
/* Check for a color in the palette of 64. */
162
static const byte pal64[32] =
164
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
165
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
166
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
170
if (pal64[r >> (gx_color_value_bits - 5)] &&
171
pal64[g >> (gx_color_value_bits - 5)] &&
172
pal64[b >> (gx_color_value_bits - 5)]
174
return (gx_color_index) (
175
((r >> (gx_color_value_bits - 2)) << 4) +
176
((g >> (gx_color_value_bits - 2)) << 2) +
177
(b >> (gx_color_value_bits - 2))
181
/* map colors to 0->255 in 32 steps */
182
cr = win_color_value(r);
183
cg = win_color_value(g);
184
cb = win_color_value(b);
186
/* Search in palette, skipping the first 64. */
187
mc_index = ((cr >> 3) << 7) + ((cg >> 3) << 2) + (cb >> 6);
188
mc_mask = 0x80 >> ((cb >> 3) & 7);
189
if (wdev->mapped_color_flags[mc_index] & mc_mask)
190
for (i = wdev->nColors, pep = &lpal->palPalEntry[i];
193
if (cr == pep->peRed &&
194
cg == pep->peGreen &&
197
return ((gx_color_index) i); /* found it */
199
/* next try adding it to palette */
201
if (i < 220) { /* allow 36 for windows and other apps */
202
LPLOGPALETTE lipal = wdev->limgpalette;
204
wdev->nColors = i + 1;
206
DeleteObject(wdev->himgpalette);
207
lipal->palPalEntry[i].peFlags = 0;
208
lipal->palPalEntry[i].peRed = cr;
209
lipal->palPalEntry[i].peGreen = cg;
210
lipal->palPalEntry[i].peBlue = cb;
211
lipal->palNumEntries = wdev->nColors;
212
wdev->himgpalette = CreatePalette(lipal);
214
wdev->mapped_color_flags[mc_index] |= mc_mask;
215
return ((gx_color_index) i); /* return new palette index */
217
return (gx_no_color_index); /* not found - dither instead */
220
return pc_4bit_map_rgb_color(dev, cv);
222
return (gx_default_map_rgb_color(dev, cv));
225
/* Map a color code to r-g-b. */
227
win_map_color_rgb(gx_device * dev, gx_color_index color,
228
gx_color_value prgb[3])
233
switch (wdev->BitsPerPixel) {
235
one = (gx_color_value) (gx_max_color_value / 255);
236
prgb[0] = ((color) & 255) * one;
237
prgb[1] = ((color >> 8) & 255) * one;
238
prgb[2] = ((color >> 16) & 255) * one;
241
value = (color >> 11) & 0x1f;
242
prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
243
value = (color >> 5) & 0x3f;
244
prgb[1] = ((value << 10) + (value << 4) + (value >> 2)) >> (16 - gx_color_value_bits);
245
value = (color) & 0x1f;
246
prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
249
value = (color >> 10) & 0x1f;
250
prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
251
value = (color >> 5) & 0x1f;
252
prgb[1] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
253
value = (color) & 0x1f;
254
prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
259
one = (gx_color_value) (gx_max_color_value / 255);
260
prgb[0] = wdev->limgpalette->palPalEntry[(int)color].peRed * one;
261
prgb[1] = wdev->limgpalette->palPalEntry[(int)color].peGreen * one;
262
prgb[2] = wdev->limgpalette->palPalEntry[(int)color].peBlue * one;
265
pc_4bit_map_color_rgb(dev, color, prgb);
268
prgb[0] = prgb[1] = prgb[2] =
269
(int)color ? gx_max_color_value : 0;
274
/* Get Win parameters */
276
win_get_params(gx_device * dev, gs_param_list * plist)
278
int code = gx_default_get_params(dev, plist);
283
/* Put parameters. */
284
/* Set window parameters -- size and resolution. */
285
/* We implement this ourselves so that we can do it without */
286
/* closing and opening the device. */
288
win_put_params(gx_device * dev, gs_param_list * plist)
291
bool is_open = dev->is_open;
292
int width = dev->width;
293
int height = dev->height;
294
int old_bpp = dev->color_info.depth;
296
byte *old_flags = wdev->mapped_color_flags;
298
/* Handle extra parameters */
300
switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
302
if (dev->is_open && bpp != old_bpp)
303
ecode = gs_error_rangecheck;
304
else { /* Don't release existing mapped_color_flags. */
306
wdev->mapped_color_flags = 0;
307
code = win_set_bits_per_pixel(wdev, bpp);
316
bppe:param_signal_error(plist, "BitsPerPixel", ecode);
321
if (ecode >= 0) { /* Prevent gx_default_put_params from closing the device. */
322
dev->is_open = false;
323
ecode = gx_default_put_params(dev, plist);
324
dev->is_open = is_open;
326
if (ecode < 0) { /* If we allocated mapped_color_flags, release it. */
327
if (wdev->mapped_color_flags != 0 && old_flags == 0)
328
gs_free(wdev->memory,
329
wdev->mapped_color_flags, 4096, 1,
331
wdev->mapped_color_flags = old_flags;
333
win_set_bits_per_pixel(wdev, old_bpp);
336
if (wdev->mapped_color_flags == 0 && old_flags != 0) { /* Release old mapped_color_flags. */
338
old_flags, 4096, 1, "win_put_params");
340
/* Hand off the change to the implementation. */
341
if (is_open && (bpp != old_bpp ||
342
dev->width != width || dev->height != height)
346
(*wdev->free_bitmap) (wdev);
347
ccode = (*wdev->alloc_bitmap) (wdev, (gx_device *) wdev);
348
if (ccode < 0) { /* Bad news! Some of the other device parameters */
349
/* may have changed. We don't handle this. */
350
/* This is ****** WRONG ******. */
352
dev->height = height;
353
win_set_bits_per_pixel(wdev, old_bpp);
354
(*wdev->alloc_bitmap) (wdev, dev);
361
/* ------ Internal routines ------ */
365
/* out of memory error message box */
369
MessageBox((HWND) NULL, (LPSTR) "Not enough memory", (LPSTR) szAppName, MB_ICONSTOP);
370
return gs_error_limitcheck;
374
win_makepalette(gx_device_win * wdev)
377
LPLOGPALETTE logpalette;
379
logpalette = (LPLOGPALETTE) gs_malloc(wdev->memory, 1, sizeof(LOGPALETTE) +
380
(1 << (wdev->color_info.depth)) * sizeof(PALETTEENTRY),
382
if (logpalette == (LPLOGPALETTE) NULL)
384
logpalette->palVersion = 0x300;
385
logpalette->palNumEntries = wdev->nColors;
386
for (i = 0; i < wdev->nColors; i++) {
387
logpalette->palPalEntry[i].peFlags = 0;
388
switch (wdev->nColors) {
390
/* colors are rrggbb */
391
logpalette->palPalEntry[i].peRed = ((i & 0x30) >> 4) * 85;
392
logpalette->palPalEntry[i].peGreen = ((i & 0xC) >> 2) * 85;
393
logpalette->palPalEntry[i].peBlue = (i & 3) * 85;
396
/* colors are irgb */
397
val = (i & 8 ? 255 : 128);
398
logpalette->palPalEntry[i].peRed = i & 4 ? val : 0;
399
logpalette->palPalEntry[i].peGreen = i & 2 ? val : 0;
400
logpalette->palPalEntry[i].peBlue = i & 1 ? val : 0;
401
if (i == 8) { /* light gray */
402
logpalette->palPalEntry[i].peRed =
403
logpalette->palPalEntry[i].peGreen =
404
logpalette->palPalEntry[i].peBlue = 192;
408
logpalette->palPalEntry[i].peRed =
409
logpalette->palPalEntry[i].peGreen =
410
logpalette->palPalEntry[i].peBlue = (i ? 255 : 0);
418
win_set_bits_per_pixel(gx_device_win * wdev, int bpp)
420
static const gx_device_color_info win_24bit_color = dci_color(24, 255, 255);
421
static const gx_device_color_info win_16bit_color = dci_color(16, 255, 255);
422
static const gx_device_color_info win_8bit_color = dci_color(8, 31, 4);
423
static const gx_device_color_info win_ega_color = dci_pc_4bit;
424
static const gx_device_color_info win_vga_color = dci_pc_4bit;
425
static const gx_device_color_info win_mono_color = dci_black_and_white;
426
/* remember old anti_alias info */
427
gx_device_anti_alias_info anti_alias = wdev->color_info.anti_alias;
432
wdev->color_info = win_24bit_color;
437
wdev->color_info = win_16bit_color;
441
/* use 64 static colors and 166 dynamic colors from 8 planes */
442
wdev->color_info = win_8bit_color;
447
if (GetDeviceCaps(hdc, VERTRES) <= 350)
448
wdev->color_info = win_ega_color;
450
wdev->color_info = win_vga_color;
451
ReleaseDC(NULL, hdc);
455
wdev->color_info = win_mono_color;
459
return (gs_error_rangecheck);
461
wdev->BitsPerPixel = bpp;
463
/* If necessary, allocate and clear the mapped color flags. */
465
if (wdev->mapped_color_flags == 0) {
466
wdev->mapped_color_flags = gs_malloc(wdev->memory,
467
4096, 1, "win_set_bits_per_pixel");
468
if (wdev->mapped_color_flags == 0)
469
return_error(gs_error_VMerror);
471
memset(wdev->mapped_color_flags, 0, 4096);
473
gs_free(wdev->memory,
474
wdev->mapped_color_flags, 4096, 1, "win_set_bits_per_pixel");
475
wdev->mapped_color_flags = 0;
478
/* copy encode/decode procedures */
479
wdev->procs.encode_color = wdev->procs.map_rgb_color;
480
wdev->procs.decode_color = wdev->procs.map_color_rgb;
482
wdev->procs.get_color_mapping_procs =
483
gx_default_DevGray_get_color_mapping_procs;
484
wdev->procs.get_color_comp_index =
485
gx_default_DevGray_get_color_comp_index;
488
wdev->procs.get_color_mapping_procs =
489
gx_default_DevRGB_get_color_mapping_procs;
490
wdev->procs.get_color_comp_index =
491
gx_default_DevRGB_get_color_comp_index;
494
/* restore old anti_alias info */
495
wdev->color_info.anti_alias = anti_alias;