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