1
/* Copyright (C) 2001-2006 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, 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.
13
/* $Id: gdevmswn.c 8250 2007-09-25 13:31:24Z giles $ */
15
* Microsoft Windows 3.n driver for Ghostscript.
17
* Original version by Russell Lang and Maurice Castro with help from
18
* Programming Windows, 2nd Ed., Charles Petzold, Microsoft Press;
19
* created from gdevbgi.c and gnuplot/term/win.trm 5th June 1992.
20
* Extensively modified by L. Peter Deutsch, Aladdin Enterprises.
29
/* Forward references */
30
static int win_set_bits_per_pixel(gx_device_win *, int);
34
/* Open the win driver */
36
win_open(gx_device * dev)
41
if (dev->width == INITIAL_WIDTH)
42
dev->width = (int)(8.5 * dev->x_pixels_per_inch);
43
if (dev->height == INITIAL_HEIGHT)
44
dev->height = (int)(11.0 * dev->y_pixels_per_inch);
46
if (wdev->BitsPerPixel == 0) {
49
/* Set parameters that were unknown before opening device */
50
/* Find out if the device supports color */
51
/* We recognize 1, 4, 8, 16, 24 bit/pixel devices */
52
hdc = GetDC(NULL); /* get hdc for desktop */
53
depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
55
wdev->BitsPerPixel = 24;
56
} else if (depth > 8) {
57
wdev->BitsPerPixel = 16;
58
} else if (depth >= 8) {
59
wdev->BitsPerPixel = 8;
60
} else if (depth >= 4) {
61
wdev->BitsPerPixel = 4;
63
wdev->BitsPerPixel = 1;
66
wdev->mapped_color_flags = 0;
68
if ((code = win_set_bits_per_pixel(wdev, wdev->BitsPerPixel)) < 0)
71
if (wdev->nColors > 0) {
72
/* create palette for display */
73
if ((wdev->limgpalette = win_makepalette(wdev))
74
== (LPLOGPALETTE) NULL)
75
return win_nomemory();
76
wdev->himgpalette = CreatePalette(wdev->limgpalette);
81
/* Make the output appear on the screen. */
83
win_sync_output(gx_device * dev)
86
(*pgsdll_callback) (GSDLL_SYNC, (unsigned char *)wdev, 0);
90
/* Make the window visible, and display the output. */
92
win_output_page(gx_device * dev, int copies, int flush)
95
(*pgsdll_callback) (GSDLL_PAGE, (unsigned char *)wdev, 0);
96
return gx_finish_output_page(dev, copies, flush);;
99
/* Close the win driver */
101
win_close(gx_device * dev)
104
if (wdev->nColors > 0) {
106
wdev->mapped_color_flags, 4096, 1, "win_set_bits_per_pixel");
107
DeleteObject(wdev->himgpalette);
109
(char *)(wdev->limgpalette), 1, sizeof(LOGPALETTE) +
110
(1 << (wdev->color_info.depth)) * sizeof(PALETTEENTRY),
116
/* Map a r-g-b color to the colors available under Windows */
118
win_map_rgb_color(gx_device * dev, const gx_color_value cv[])
120
gx_color_value r = cv[0];
121
gx_color_value g = cv[1];
122
gx_color_value b = cv[2];
123
switch (wdev->BitsPerPixel) {
125
return (((unsigned long)b >> (gx_color_value_bits - 8)) << 16) +
126
(((unsigned long)g >> (gx_color_value_bits - 8)) << 8) +
127
(((unsigned long)r >> (gx_color_value_bits - 8)));
129
gx_color_index color = ((r >> (gx_color_value_bits - 5)) << 11) +
130
((g >> (gx_color_value_bits - 6)) << 5) +
131
(b >> (gx_color_value_bits - 5));
132
#if arch_is_big_endian
133
ushort color16 = (ushort)color;
135
ushort color16 = (ushort)((color << 8) | (color >> 8));
140
gx_color_index color = ((r >> (gx_color_value_bits - 5)) << 10) +
141
((g >> (gx_color_value_bits - 5)) << 5) +
142
(b >> (gx_color_value_bits - 5));
143
#if arch_is_big_endian
144
ushort color15 = (ushort)color;
146
ushort color15 = (ushort)((color << 8) | (color >> 8));
152
LPLOGPALETTE lpal = wdev->limgpalette;
158
/* Check for a color in the palette of 64. */
160
static const byte pal64[32] =
162
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
163
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
164
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
168
if (pal64[r >> (gx_color_value_bits - 5)] &&
169
pal64[g >> (gx_color_value_bits - 5)] &&
170
pal64[b >> (gx_color_value_bits - 5)]
172
return (gx_color_index) (
173
((r >> (gx_color_value_bits - 2)) << 4) +
174
((g >> (gx_color_value_bits - 2)) << 2) +
175
(b >> (gx_color_value_bits - 2))
179
/* map colors to 0->255 in 32 steps */
180
cr = win_color_value(r);
181
cg = win_color_value(g);
182
cb = win_color_value(b);
184
/* Search in palette, skipping the first 64. */
185
mc_index = ((cr >> 3) << 7) + ((cg >> 3) << 2) + (cb >> 6);
186
mc_mask = 0x80 >> ((cb >> 3) & 7);
187
if (wdev->mapped_color_flags[mc_index] & mc_mask)
188
for (i = wdev->nColors, pep = &lpal->palPalEntry[i];
191
if (cr == pep->peRed &&
192
cg == pep->peGreen &&
195
return ((gx_color_index) i); /* found it */
197
/* next try adding it to palette */
199
if (i < 220) { /* allow 36 for windows and other apps */
200
LPLOGPALETTE lipal = wdev->limgpalette;
202
wdev->nColors = i + 1;
204
DeleteObject(wdev->himgpalette);
205
lipal->palPalEntry[i].peFlags = 0;
206
lipal->palPalEntry[i].peRed = cr;
207
lipal->palPalEntry[i].peGreen = cg;
208
lipal->palPalEntry[i].peBlue = cb;
209
lipal->palNumEntries = wdev->nColors;
210
wdev->himgpalette = CreatePalette(lipal);
212
wdev->mapped_color_flags[mc_index] |= mc_mask;
213
return ((gx_color_index) i); /* return new palette index */
215
return (gx_no_color_index); /* not found - dither instead */
218
return pc_4bit_map_rgb_color(dev, cv);
220
return (gx_default_map_rgb_color(dev, cv));
223
/* Map a color code to r-g-b. */
225
win_map_color_rgb(gx_device * dev, gx_color_index color,
226
gx_color_value prgb[3])
231
switch (wdev->BitsPerPixel) {
233
one = (gx_color_value) (gx_max_color_value / 255);
234
prgb[0] = ((color) & 255) * one;
235
prgb[1] = ((color >> 8) & 255) * one;
236
prgb[2] = ((color >> 16) & 255) * one;
239
value = (color >> 11) & 0x1f;
240
prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
241
value = (color >> 5) & 0x3f;
242
prgb[1] = ((value << 10) + (value << 4) + (value >> 2)) >> (16 - gx_color_value_bits);
243
value = (color) & 0x1f;
244
prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
247
value = (color >> 10) & 0x1f;
248
prgb[0] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
249
value = (color >> 5) & 0x1f;
250
prgb[1] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
251
value = (color) & 0x1f;
252
prgb[2] = ((value << 11) + (value << 6) + (value << 1) + (value >> 4)) >> (16 - gx_color_value_bits);
257
one = (gx_color_value) (gx_max_color_value / 255);
258
prgb[0] = wdev->limgpalette->palPalEntry[(int)color].peRed * one;
259
prgb[1] = wdev->limgpalette->palPalEntry[(int)color].peGreen * one;
260
prgb[2] = wdev->limgpalette->palPalEntry[(int)color].peBlue * one;
263
pc_4bit_map_color_rgb(dev, color, prgb);
266
prgb[0] = prgb[1] = prgb[2] =
267
(int)color ? gx_max_color_value : 0;
272
/* Get Win parameters */
274
win_get_params(gx_device * dev, gs_param_list * plist)
276
int code = gx_default_get_params(dev, plist);
281
/* Put parameters. */
282
/* Set window parameters -- size and resolution. */
283
/* We implement this ourselves so that we can do it without */
284
/* closing and opening the device. */
286
win_put_params(gx_device * dev, gs_param_list * plist)
289
bool is_open = dev->is_open;
290
int width = dev->width;
291
int height = dev->height;
292
int old_bpp = dev->color_info.depth;
294
byte *old_flags = wdev->mapped_color_flags;
296
/* Handle extra parameters */
298
switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
300
if (dev->is_open && bpp != old_bpp)
301
ecode = gs_error_rangecheck;
302
else { /* Don't release existing mapped_color_flags. */
304
wdev->mapped_color_flags = 0;
305
code = win_set_bits_per_pixel(wdev, bpp);
314
bppe:param_signal_error(plist, "BitsPerPixel", ecode);
319
if (ecode >= 0) { /* Prevent gx_default_put_params from closing the device. */
320
dev->is_open = false;
321
ecode = gx_default_put_params(dev, plist);
322
dev->is_open = is_open;
324
if (ecode < 0) { /* If we allocated mapped_color_flags, release it. */
325
if (wdev->mapped_color_flags != 0 && old_flags == 0)
326
gs_free(wdev->memory,
327
wdev->mapped_color_flags, 4096, 1,
329
wdev->mapped_color_flags = old_flags;
331
win_set_bits_per_pixel(wdev, old_bpp);
334
if (wdev->mapped_color_flags == 0 && old_flags != 0) { /* Release old mapped_color_flags. */
336
old_flags, 4096, 1, "win_put_params");
338
/* Hand off the change to the implementation. */
339
if (is_open && (bpp != old_bpp ||
340
dev->width != width || dev->height != height)
344
(*wdev->free_bitmap) (wdev);
345
ccode = (*wdev->alloc_bitmap) (wdev, (gx_device *) wdev);
346
if (ccode < 0) { /* Bad news! Some of the other device parameters */
347
/* may have changed. We don't handle this. */
348
/* This is ****** WRONG ******. */
350
dev->height = height;
351
win_set_bits_per_pixel(wdev, old_bpp);
352
(*wdev->alloc_bitmap) (wdev, dev);
359
/* ------ 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;
375
win_makepalette(gx_device_win * wdev)
378
LPLOGPALETTE logpalette;
380
logpalette = (LPLOGPALETTE) gs_malloc(wdev->memory, 1, sizeof(LOGPALETTE) +
381
(1 << (wdev->color_info.depth)) * sizeof(PALETTEENTRY),
383
if (logpalette == (LPLOGPALETTE) NULL)
385
logpalette->palVersion = 0x300;
386
logpalette->palNumEntries = wdev->nColors;
387
for (i = 0; i < wdev->nColors; i++) {
388
logpalette->palPalEntry[i].peFlags = 0;
389
switch (wdev->nColors) {
391
/* colors are rrggbb */
392
logpalette->palPalEntry[i].peRed = ((i & 0x30) >> 4) * 85;
393
logpalette->palPalEntry[i].peGreen = ((i & 0xC) >> 2) * 85;
394
logpalette->palPalEntry[i].peBlue = (i & 3) * 85;
397
/* colors are irgb */
398
val = (i & 8 ? 255 : 128);
399
logpalette->palPalEntry[i].peRed = i & 4 ? val : 0;
400
logpalette->palPalEntry[i].peGreen = i & 2 ? val : 0;
401
logpalette->palPalEntry[i].peBlue = i & 1 ? val : 0;
402
if (i == 8) { /* light gray */
403
logpalette->palPalEntry[i].peRed =
404
logpalette->palPalEntry[i].peGreen =
405
logpalette->palPalEntry[i].peBlue = 192;
409
logpalette->palPalEntry[i].peRed =
410
logpalette->palPalEntry[i].peGreen =
411
logpalette->palPalEntry[i].peBlue = (i ? 255 : 0);
420
win_set_bits_per_pixel(gx_device_win * wdev, int bpp)
422
static const gx_device_color_info win_24bit_color = dci_color(24, 255, 255);
423
static const gx_device_color_info win_16bit_color = dci_color(16, 255, 255);
424
static const gx_device_color_info win_8bit_color = dci_color(8, 31, 4);
425
static const gx_device_color_info win_ega_color = dci_pc_4bit;
426
static const gx_device_color_info win_vga_color = dci_pc_4bit;
427
static const gx_device_color_info win_mono_color = dci_black_and_white;
428
/* remember old anti_alias info */
429
gx_device_anti_alias_info anti_alias = wdev->color_info.anti_alias;
434
wdev->color_info = win_24bit_color;
439
wdev->color_info = win_16bit_color;
443
/* use 64 static colors and 166 dynamic colors from 8 planes */
444
wdev->color_info = win_8bit_color;
449
if (GetDeviceCaps(hdc, VERTRES) <= 350)
450
wdev->color_info = win_ega_color;
452
wdev->color_info = win_vga_color;
453
ReleaseDC(NULL, hdc);
457
wdev->color_info = win_mono_color;
461
return (gs_error_rangecheck);
463
wdev->BitsPerPixel = bpp;
465
/* If necessary, allocate and clear the mapped color flags. */
467
if (wdev->mapped_color_flags == 0) {
468
wdev->mapped_color_flags = gs_malloc(wdev->memory,
469
4096, 1, "win_set_bits_per_pixel");
470
if (wdev->mapped_color_flags == 0)
471
return_error(gs_error_VMerror);
473
memset(wdev->mapped_color_flags, 0, 4096);
475
gs_free(wdev->memory,
476
wdev->mapped_color_flags, 4096, 1, "win_set_bits_per_pixel");
477
wdev->mapped_color_flags = 0;
480
/* copy encode/decode procedures */
481
wdev->procs.encode_color = wdev->procs.map_rgb_color;
482
wdev->procs.decode_color = wdev->procs.map_color_rgb;
484
wdev->procs.get_color_mapping_procs =
485
gx_default_DevGray_get_color_mapping_procs;
486
wdev->procs.get_color_comp_index =
487
gx_default_DevGray_get_color_comp_index;
490
wdev->procs.get_color_mapping_procs =
491
gx_default_DevRGB_get_color_mapping_procs;
492
wdev->procs.get_color_comp_index =
493
gx_default_DevRGB_get_color_comp_index;
496
/* restore old anti_alias info */
497
wdev->color_info.anti_alias = anti_alias;