1 /* Copyright (C) 1989, 1995, 1996, 1997, 1998, 2000 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: gdevwprn.c,v 1.3.2.1.2.1 2003/01/17 00:49:02 giles Exp $ */
20 /*
21 * Microsoft Windows 3.n printer driver for Ghostscript.
22 *
23 * Original version by Russell Lang and
24 * L. Peter Deutsch, Aladdin Enterprises.
25 */
26 #include "gdevmswn.h"
27 #include "gp.h"
28 #include "gpcheck.h"
29 #include "commdlg.h"
30
31 #define PARENT_WINDOW HWND_DESKTOP
32
33
34 /*
35 ****** NOTE: this module and gdevwddb should be refactored.
36 * The drawing routines are almost identical.
37 * The differences are that the mswinprn doesn't use an extra
38 * palette (gdevwddb.c could probably be made to work with
39 * one palette also), mswinprn doesn't call win_update() because
40 * hwndimg doesn't exist, and the HDC is hdcmf not hdcbit.
41 ******/
42
43 /* Make sure we cast to the correct structure type. */
44 typedef struct gx_device_win_prn_s gx_device_win_prn;
45
46 #undef wdev
47 #define wdev ((gx_device_win_prn *)dev)
48
49 /* Forward references */
50 private void near win_prn_addtool(P2(gx_device_win_prn *, int));
51 private void near win_prn_maketools(P2(gx_device_win_prn *, HDC));
52 private void near win_prn_destroytools(P1(gx_device_win_prn *));
53 BOOL CALLBACK _export AbortProc(HDC, int);
54
55 /* Device procedures */
56
57 /* See gxdevice.h for the definitions of the procedures. */
58 private dev_proc_open_device(win_prn_open);
59 private dev_proc_close_device(win_prn_close);
60 private dev_proc_sync_output(win_prn_sync_output);
61 private dev_proc_output_page(win_prn_output_page);
62 private dev_proc_map_rgb_color(win_prn_map_rgb_color);
63 private dev_proc_fill_rectangle(win_prn_fill_rectangle);
64 private dev_proc_tile_rectangle(win_prn_tile_rectangle);
65 private dev_proc_copy_mono(win_prn_copy_mono);
66 private dev_proc_copy_color(win_prn_copy_color);
67 private dev_proc_draw_line(win_prn_draw_line);
68
69 /* The device descriptor */
70 struct gx_device_win_prn_s {
71 gx_device_common;
72 gx_device_win_common;
73
74 /* Handles */
75
76 HPEN hpen, *hpens;
77 uint hpensize;
78 HBRUSH hbrush, *hbrushs;
79 uint hbrushsize;
80 #define select_brush(color)\
81 if (wdev->hbrush != wdev->hbrushs[color])\
82 { wdev->hbrush = wdev->hbrushs[color];\
83 SelectObject(wdev->hdcmf,wdev->hbrush);\
84 }
85 /* A staging bitmap for copy_mono. */
86 /* We want one big enough to handle the standard 16x16 halftone; */
87 /* this is also big enough for ordinary-size characters. */
88
89 #define bmWidthBytes 4 /* must be even */
90 #define bmWidthBits (bmWidthBytes * 8)
91 #define bmHeight 32
92 HBITMAP FAR hbmmono;
93 HDC FAR hdcmono;
94 gx_bitmap_id bm_id;
95
96 HDC hdcprn;
97 HDC hdcmf;
98 char mfname[gp_file_name_sizeof];
99 DLGPROC lpfnAbortProc;
100 };
101 private const gx_device_procs win_prn_procs =
102 {
103 win_prn_open,
104 NULL, /* get_initial_matrix */
105 win_prn_sync_output,
106 win_prn_output_page,
107 win_prn_close,
108 win_prn_map_rgb_color,
109 win_map_color_rgb,
110 win_prn_fill_rectangle,
111 win_prn_tile_rectangle,
112 win_prn_copy_mono,
113 win_prn_copy_color,
114 win_prn_draw_line,
115 NULL, /* get_bits */
116 NULL, /* get_params */
117 NULL, /* put_params */
118 NULL, /* map_cmyk_color */
119 win_get_xfont_procs
120 };
121 gx_device_win_prn far_data gs_mswinprn_device =
122 {
123 std_device_std_body(gx_device_win_prn, &win_prn_procs, "mswinprn",
124 INITIAL_WIDTH, INITIAL_HEIGHT, /* win_open() fills these in later */
125 INITIAL_RESOLUTION, INITIAL_RESOLUTION /* win_open() fills these in later */
126 ),
127 {0}, /* std_procs */
128 0, /* BitsPerPixel */
129 2, /* nColors */
130 };
131
132 /* Open the win_prn driver */
133 private int
win_prn_open(gx_device * dev)134 win_prn_open(gx_device * dev)
135 {
136 int depth;
137 PRINTDLG pd;
138 FILE *f;
139 POINT offset;
140 POINT size;
141 float m[4];
142
143 memset(&pd, 0, sizeof(PRINTDLG));
144 pd.lStructSize = sizeof(PRINTDLG);
145 pd.hwndOwner = PARENT_WINDOW;
146 pd.Flags = PD_PRINTSETUP | PD_RETURNDC;
147 if (!PrintDlg(&pd)) {
148 /* device not opened - exit ghostscript */
149 return gs_error_limitcheck;
150 }
151 GlobalFree(pd.hDevMode);
152 GlobalFree(pd.hDevNames);
153 pd.hDevMode = pd.hDevNames = NULL;
154 wdev->hdcprn = pd.hDC;
155 if (!(GetDeviceCaps(wdev->hdcprn, RASTERCAPS) != RC_BITBLT)) {
156 DeleteDC(wdev->hdcprn);
157 return gs_error_limitcheck;
158 }
159 wdev->lpfnAbortProc = (DLGPROC) AbortProc;
160 Escape(wdev->hdcprn, SETABORTPROC, 0, (LPSTR) wdev->lpfnAbortProc, NULL);
161 if (Escape(wdev->hdcprn, STARTDOC, strlen(szAppName), szAppName, NULL) <= 0) {
162 DeleteDC(wdev->hdcprn);
163 return gs_error_limitcheck;
164 }
165 f = gp_open_scratch_file(gp_scratch_file_name_prefix,
166 wdev->mfname, "wb");
167 if (f == (FILE *) NULL) {
168 Escape(wdev->hdcprn, ENDDOC, 0, NULL, NULL);
169 DeleteDC(wdev->hdcprn);
170 return gs_error_limitcheck;
171 }
172 unlink(wdev->mfname);
173 wdev->hdcmf = CreateMetaFile(wdev->mfname);
174
175 dev->x_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSX);
176 dev->y_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSY);
177 Escape(wdev->hdcprn, GETPHYSPAGESIZE, 0, NULL, (LPPOINT) & size);
178 dev->width = size.x;
179 dev->height = size.y;
180 Escape(wdev->hdcprn, GETPRINTINGOFFSET, 0, NULL, (LPPOINT) & offset);
181 m[0] /*left */ = offset.x / dev->x_pixels_per_inch;
182 m[3] /*top */ = offset.y / dev->y_pixels_per_inch;
183 m[2] /*right */ =
184 (size.x - offset.x - GetDeviceCaps(wdev->hdcprn, HORZRES))
185 / dev->x_pixels_per_inch;
186 m[1] /*bottom */ =
187 (size.y - offset.y - GetDeviceCaps(wdev->hdcprn, VERTRES))
188 / dev->y_pixels_per_inch
189 + 0.15; /* hack to add a bit more margin for deskjet printer */
190 gx_device_set_margins(dev, m, true);
191
192 /* Set parameters that were unknown before opening device */
193 /* Find out if the device supports color */
194 /* We recognize 2, 16 or 256 color devices */
195 depth = GetDeviceCaps(wdev->hdcprn, PLANES) * GetDeviceCaps(wdev->hdcprn, BITSPIXEL);
196 if (depth >= 8) { /* use 64 static colors and 166 dynamic colors from 8 planes */
197 static const gx_device_color_info win_256color = dci_color(8, 31, 4);
198
199 dev->color_info = win_256color;
200 wdev->nColors = 64;
201 } else if (depth >= 4) {
202 static const gx_device_color_info win_16ega_color = dci_color(4, 2, 3);
203
204 dev->color_info = win_16ega_color;
205 wdev->nColors = 16;
206 } else { /* default is black_and_white */
207 wdev->nColors = 2;
208 }
209
210 /* create palette for display */
211 if ((wdev->limgpalette = win_makepalette((gx_device_win *) dev))
212 == (LPLOGPALETTE) NULL) {
213 HMETAFILE hmf = CloseMetaFile(wdev->hdcmf);
214
215 DeleteMetaFile(hmf);
216 unlink(wdev->mfname);
217 Escape(wdev->hdcprn, ENDDOC, 0, NULL, NULL);
218 DeleteDC(wdev->hdcprn);
219 return win_nomemory();
220 }
221 wdev->himgpalette = CreatePalette(wdev->limgpalette);
222
223 /* Create the bitmap and DC for copy_mono. */
224 wdev->hbmmono = CreateBitmap(bmWidthBits, bmHeight, 1, 1, NULL);
225 wdev->hdcmono = CreateCompatibleDC(wdev->hdcprn);
226 if (wdev->hbmmono == NULL || wdev->hdcmono == NULL) {
227 HMETAFILE hmf = CloseMetaFile(wdev->hdcmf);
228
229 DeleteMetaFile(hmf);
230 unlink(wdev->mfname);
231 Escape(wdev->hdcprn, ENDDOC, 0, NULL, NULL);
232 DeleteDC(wdev->hdcprn);
233 gs_free((char *)(wdev->limgpalette), 1, sizeof(LOGPALETTE) +
234 (1 << (wdev->color_info.depth)) * sizeof(PALETTEENTRY),
235 "win_prn_open");
236 return win_nomemory();
237 }
238 SetMapMode(wdev->hdcmono, GetMapMode(wdev->hdcprn));
239 SelectObject(wdev->hdcmono, wdev->hbmmono);
240 (void)SelectPalette(wdev->hdcmf, wdev->himgpalette, FALSE);
241 RealizePalette(wdev->hdcmf);
242 win_prn_maketools(wdev, wdev->hdcmf);
243 wdev->bm_id = gx_no_bitmap_id;
244
245 return 0;
246 }
247
248
249 /* Close the win_prn driver */
250 private int
win_prn_close(gx_device * dev)251 win_prn_close(gx_device * dev)
252 {
253 HMETAFILE hmf;
254
255 /* Free resources */
256 Escape(wdev->hdcprn, ENDDOC, 0, NULL, NULL);
257 DeleteDC(wdev->hdcprn);
258 hmf = CloseMetaFile(wdev->hdcmf);
259 DeleteMetaFile(hmf);
260 unlink(wdev->mfname);
261
262 win_prn_destroytools(wdev);
263 DeleteDC(wdev->hdcmono);
264 DeleteObject(wdev->hbmmono);
265 DeleteObject(wdev->himgpalette);
266 gs_free((char *)(wdev->limgpalette), 1, sizeof(LOGPALETTE) +
267 (1 << (wdev->color_info.depth)) * sizeof(PALETTEENTRY),
268 "win_prn_close");
269 return (0);
270 }
271
272 /* Do nothing */
273 int
win_prn_sync_output(gx_device * dev)274 win_prn_sync_output(gx_device * dev)
275 {
276 return 0;
277 }
278
279 /* Write page to printer */
280 int
win_prn_output_page(gx_device * dev,int num_copies,int flush)281 win_prn_output_page(gx_device * dev, int num_copies, int flush)
282 {
283 RECT rect;
284 HMETAFILE hmf;
285
286 hmf = CloseMetaFile(wdev->hdcmf);
287
288 Escape(wdev->hdcprn, NEXTBAND, 0, NULL, (LPRECT) & rect);
289 while (!IsRectEmpty(&rect)) {
290 PlayMetaFile(wdev->hdcprn, hmf);
291 if (Escape(wdev->hdcprn, NEXTBAND, 0, NULL, (LPRECT) & rect) <= 0)
292 break;
293 }
294 DeleteMetaFile(hmf);
295 unlink(wdev->mfname);
296 wdev->hdcmf = CreateMetaFile(wdev->mfname);
297 (void)SelectPalette(wdev->hdcmf, wdev->himgpalette, FALSE);
298 RealizePalette(wdev->hdcmf);
299 SelectObject(wdev->hdcmf, wdev->hpen);
300 SelectObject(wdev->hdcmf, wdev->hbrush);
301
302 return gx_finish_output_page(dev, num_copies, flush);
303 }
304
305
306 /* Map a r-g-b color to the colors available under Windows */
307 private gx_color_index
win_prn_map_rgb_color(gx_device * dev,gx_color_value r,gx_color_value g,gx_color_value b)308 win_prn_map_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
309 gx_color_value b)
310 {
311 int i = wdev->nColors;
312 gx_color_index color = win_map_rgb_color(dev, r, g, b);
313
314 if (color != i)
315 return color;
316 (void)SelectPalette(wdev->hdcmf, wdev->himgpalette, FALSE);
317 RealizePalette(wdev->hdcmf);
318 win_prn_addtool(wdev, i);
319
320 return color;
321 }
322
323
324 /* Macro for filling a rectangle with a color. */
325 /* Note that it starts with a declaration. */
326 #define fill_rect(x, y, w, h, color)\
327 RECT rect;\
328 rect.left = x, rect.top = y;\
329 rect.right = x + w, rect.bottom = y + h;\
330 FillRect(wdev->hdcmf, &rect, wdev->hbrushs[(int)color])
331
332
333 /* Fill a rectangle. */
334 private int
win_prn_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)335 win_prn_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
336 gx_color_index color)
337 {
338 fit_fill(dev, x, y, w, h);
339 /* Use PatBlt for filling. Special-case black. */
340 if (color == 0)
341 PatBlt(wdev->hdcmf, x, y, w, h, rop_write_0s);
342 else {
343 select_brush((int)color);
344 PatBlt(wdev->hdcmf, x, y, w, h, rop_write_pattern);
345 }
346
347 return 0;
348 }
349
350 /* Tile a rectangle. If neither color is transparent, */
351 /* pre-clear the rectangle to color0 and just tile with color1. */
352 /* This is faster because of how win_copy_mono is implemented. */
353 /* Note that this also does the right thing for colored tiles. */
354 private int
win_prn_tile_rectangle(gx_device * dev,const gx_tile_bitmap * tile,int x,int y,int w,int h,gx_color_index czero,gx_color_index cone,int px,int py)355 win_prn_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
356 int x, int y, int w, int h, gx_color_index czero, gx_color_index cone,
357 int px, int py)
358 {
359 fit_fill(dev, x, y, w, h);
360 if (czero != gx_no_color_index && cone != gx_no_color_index) {
361 fill_rect(x, y, w, h, czero);
362 czero = gx_no_color_index;
363 }
364 if (tile->raster == bmWidthBytes && tile->size.y <= bmHeight &&
365 (px | py) == 0 && cone != gx_no_color_index
366 ) { /* We can do this much more efficiently */
367 /* by using the internal algorithms of copy_mono */
368 /* and gx_default_tile_rectangle. */
369 int width = tile->size.x;
370 int height = tile->size.y;
371 int rwidth = tile->rep_width;
372 int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */
373 x & (rwidth - 1) :
374 x % rwidth);
375 int ry = y % tile->rep_height;
376 int icw = width - irx;
377 int ch = height - ry;
378 int ex = x + w, ey = y + h;
379 int fex = ex - width, fey = ey - height;
380 int cx, cy;
381
382 select_brush((int)cone);
383
384 if (tile->id != wdev->bm_id || tile->id == gx_no_bitmap_id) {
385 wdev->bm_id = tile->id;
386 SetBitmapBits(wdev->hbmmono,
387 (DWORD) (bmWidthBytes * tile->size.y),
388 (BYTE *) tile->data);
389 }
390 #define copy_tile(srcx, srcy, tx, ty, tw, th)\
391 BitBlt(wdev->hdcmf, tx, ty, tw, th, wdev->hdcmono, srcx, srcy, rop_write_at_1s)
392
393 if (ch > h)
394 ch = h;
395 for (cy = y;;) {
396 if (w <= icw)
397 copy_tile(irx, ry, x, cy, w, ch);
398 else {
399 copy_tile(irx, ry, x, cy, icw, ch);
400 cx = x + icw;
401 while (cx <= fex) {
402 copy_tile(0, ry, cx, cy, width, ch);
403 cx += width;
404 }
405 if (cx < ex) {
406 copy_tile(0, ry, cx, cy, ex - cx, ch);
407 }
408 }
409 if ((cy += ch) >= ey)
410 break;
411 ch = (cy > fey ? ey - cy : height);
412 ry = 0;
413 }
414
415 return 0;
416 }
417 return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py);
418 }
419
420
421 /* Draw a line */
422 private int
win_prn_draw_line(gx_device * dev,int x0,int y0,int x1,int y1,gx_color_index color)423 win_prn_draw_line(gx_device * dev, int x0, int y0, int x1, int y1,
424 gx_color_index color)
425 {
426 if (wdev->hpen != wdev->hpens[(int)color]) {
427 wdev->hpen = wdev->hpens[(int)color];
428 SelectObject(wdev->hdcmf, wdev->hpen);
429 }
430 MoveToEx(wdev->hdcmf, x0, y0, NULL);
431 LineTo(wdev->hdcmf, x1, y1);
432 return 0;
433 }
434
435 /* Copy a monochrome bitmap. The colors are given explicitly. */
436 /* Color = gx_no_color_index means transparent (no effect on the image). */
437 private int
win_prn_copy_mono(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)438 win_prn_copy_mono(gx_device * dev,
439 const byte * base, int sourcex, int raster, gx_bitmap_id id,
440 int x, int y, int w, int h,
441 gx_color_index zero, gx_color_index one)
442 {
443 int endx;
444 const byte *ptr_line;
445 int width_bytes, height;
446 DWORD rop = rop_write_at_1s;
447 int color;
448 BYTE aBit[bmWidthBytes * bmHeight];
449 BYTE *aptr = aBit;
450
451 fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
452
453 if (sourcex & ~7) {
454 base += sourcex >> 3;
455 sourcex &= 7;
456 }
457 /* Break up large transfers into smaller ones. */
458 while ((endx = sourcex + w) > bmWidthBits) {
459 int lastx = (endx - 1) & -bmWidthBits;
460 int subw = endx - lastx;
461 int code = win_prn_copy_mono(dev, base, lastx,
462 raster, gx_no_bitmap_id,
463 x + lastx - sourcex, y,
464 subw, h, zero, one);
465
466 if (code < 0)
467 return code;
468 w -= subw;
469 }
470 while (h > bmHeight) {
471 int code;
472
473 h -= bmHeight;
474 code = win_prn_copy_mono(dev, base + h * raster, sourcex,
475 raster, gx_no_bitmap_id,
476 x, y + h, w, bmHeight, zero, one);
477 if (code < 0)
478 return code;
479 }
480
481 width_bytes = (sourcex + w + 7) >> 3;
482 ptr_line = base;
483
484 if (zero == gx_no_color_index) {
485 if (one == gx_no_color_index)
486 return 0;
487 color = (int)one;
488 if (color == 0)
489 rop = rop_write_0_at_1s;
490 else
491 select_brush(color);
492 } else {
493 if (one == gx_no_color_index) {
494 color = (int)zero;
495 rop = rop_write_at_0s;
496 } else { /* Pre-clear the rectangle to zero */
497 fill_rect(x, y, w, h, zero);
498 color = (int)one;
499 }
500 select_brush(color);
501 }
502
503 if (id != wdev->bm_id || id == gx_no_bitmap_id) {
504 wdev->bm_id = id;
505 if (raster == bmWidthBytes) { /* We can do the whole thing in a single transfer! */
506 SetBitmapBits(wdev->hbmmono,
507 (DWORD) (bmWidthBytes * h),
508 (BYTE *) base);
509 } else {
510 for (height = h; height--;
511 ptr_line += raster, aptr += bmWidthBytes
512 ) { /* Pack the bits into the bitmap. */
513 switch (width_bytes) {
514 default:
515 memcpy(aptr, ptr_line, width_bytes);
516 break;
517 case 4:
518 aptr[3] = ptr_line[3];
519 case 3:
520 aptr[2] = ptr_line[2];
521 case 2:
522 aptr[1] = ptr_line[1];
523 case 1:
524 aptr[0] = ptr_line[0];
525 }
526 }
527 SetBitmapBits(wdev->hbmmono,
528 (DWORD) (bmWidthBytes * h),
529 &aBit[0]);
530 }
531 }
532 BitBlt(wdev->hdcmf, x, y, w, h, wdev->hdcmono, sourcex, 0, rop);
533 return 0;
534 }
535
536
537 /* Copy a color pixel map. This is just like a bitmap, except that */
538 /* each pixel takes 8 or 4 bits instead of 1 when device driver has color. */
539 private int
win_prn_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)540 win_prn_copy_color(gx_device * dev,
541 const byte * base, int sourcex, int raster, gx_bitmap_id id,
542 int x, int y, int w, int h)
543 {
544 fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
545
546 if (gx_device_has_color(dev)) {
547 switch (dev->color_info.depth) {
548 case 8:
549 {
550 int xi, yi;
551 int skip = raster - w;
552 const byte *sptr = base + sourcex;
553
554 if (w <= 0)
555 return 0;
556 if (x < 0 || x + w > dev->width)
557 return_error(gs_error_rangecheck);
558 for (yi = y; yi - y < h; yi++) {
559 for (xi = x; xi - x < w; xi++) {
560 int color = *sptr++;
561
562 SetPixel(wdev->hdcmf, xi, yi, PALETTEINDEX(color));
563 }
564 sptr += skip;
565 }
566 }
567 break;
568 case 4:
569 { /* color device, four bits per pixel */
570 const byte *line = base + (sourcex >> 1);
571 int dest_y = y, end_x = x + w;
572
573 if (w <= 0)
574 return 0;
575 while (h--) { /* for each line */
576 const byte *source = line;
577 register int dest_x = x;
578
579 if (sourcex & 1) { /* odd nibble first */
580 int color = *source++ & 0xf;
581
582 SetPixel(wdev->hdcmf, dest_x, dest_y, PALETTEINDEX(color));
583 dest_x++;
584 }
585 /* Now do full bytes */
586 while (dest_x < end_x) {
587 int color = *source >> 4;
588
589 SetPixel(wdev->hdcmf, dest_x, dest_y, PALETTEINDEX(color));
590 dest_x++;
591 if (dest_x < end_x) {
592 color = *source++ & 0xf;
593 SetPixel(wdev->hdcmf, dest_x, dest_y, PALETTEINDEX(color));
594 dest_x++;
595 }
596 }
597 dest_y++;
598 line += raster;
599 }
600 }
601 break;
602 default:
603 return (-1); /* panic */
604 }
605 } else
606 /* monochrome device: one bit per pixel */
607 { /* bitmap is the same as win_copy_mono: one bit per pixel */
608 win_prn_copy_mono(dev, base, sourcex, raster, id, x, y, w, h,
609 (gx_color_index) 0,
610 (gx_color_index) (dev->color_info.depth == 8 ? 63 : dev->color_info.max_gray));
611 }
612 return 0;
613 }
614
615
616 /* ------ Internal routines ------ */
617
618 #undef wdev
619
620
621 private void near
win_prn_addtool(gx_device_win_prn * wdev,int i)622 win_prn_addtool(gx_device_win_prn * wdev, int i)
623 {
624 wdev->hpens[i] = CreatePen(PS_SOLID, 1, PALETTEINDEX(i));
625 wdev->hbrushs[i] = CreateSolidBrush(PALETTEINDEX(i));
626 }
627
628
629 private void near
win_prn_maketools(gx_device_win_prn * wdev,HDC hdc)630 win_prn_maketools(gx_device_win_prn * wdev, HDC hdc)
631 {
632 int i;
633
634 wdev->hpensize = (1 << (wdev->color_info.depth)) * sizeof(HPEN);
635 wdev->hpens = (HPEN *) gs_malloc(1, wdev->hpensize,
636 "win_prn_maketools(pens)");
637 wdev->hbrushsize = (1 << (wdev->color_info.depth)) * sizeof(HBRUSH);
638 wdev->hbrushs = (HBRUSH *) gs_malloc(1, wdev->hbrushsize,
639 "win_prn_maketools(brushes)");
640 if (wdev->hpens && wdev->hbrushs) {
641 for (i = 0; i < wdev->nColors; i++)
642 win_prn_addtool(wdev, i);
643
644 wdev->hpen = wdev->hpens[0];
645 SelectObject(hdc, wdev->hpen);
646
647 wdev->hbrush = wdev->hbrushs[0];
648 SelectObject(hdc, wdev->hbrush);
649 }
650 }
651
652
653 private void near
win_prn_destroytools(gx_device_win_prn * wdev)654 win_prn_destroytools(gx_device_win_prn * wdev)
655 {
656 int i;
657
658 for (i = 0; i < wdev->nColors; i++) {
659 DeleteObject(wdev->hpens[i]);
660 DeleteObject(wdev->hbrushs[i]);
661 }
662 gs_free((char *)wdev->hbrushs, 1, wdev->hbrushsize,
663 "win_prn_destroytools(brushes)");
664 gs_free((char *)wdev->hpens, 1, wdev->hpensize,
665 "win_prn_destroytools(pens)");
666 }
667
668 BOOL CALLBACK _export
AbortProc(HDC hdcPrn,int code)669 AbortProc(HDC hdcPrn, int code)
670 {
671 process_interrupts();
672 if (code == SP_OUTOFDISK)
673 return (FALSE); /* cancel job */
674 return (TRUE);
675 }
676
677