Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/cmd/gs/src/gdevwddb.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989, 1995, 1996, 1997 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: gdevwddb.c,v 1.7 2004/08/10 13:02:36 stefan Exp $ */
18
/*
19
 * Microsoft Windows 3.n driver for Ghostscript,
20
 * using device-dependent bitmap.
21
 *
22
 * Original version by Russell Lang and Maurice Castro with help from
23
 * Programming Windows, 2nd Ed., Charles Petzold, Microsoft Press;
24
 * created from gdevbgi.c and gnuplot/term/win.trm 5th June 1992.
25
 * Extensively modified by L. Peter Deutsch, Aladdin Enterprises.
26
 */
27
#include "gdevmswn.h"
28
 
29
/* Make sure we cast to the correct structure type. */
30
typedef struct gx_device_win_ddb_s gx_device_win_ddb;
31
 
32
#undef wdev
33
#define wdev ((gx_device_win_ddb *)dev)
34
 
35
/* Forward references */
36
private void near win_addtool(gx_device_win_ddb *, int);
37
private void near win_maketools(gx_device_win_ddb *, HDC);
38
private void near win_destroytools(gx_device_win_ddb *);
39
 
40
/* Device procedures */
41
 
42
/* See gxdevice.h for the definitions of the procedures. */
43
private dev_proc_open_device(win_ddb_open);
44
private dev_proc_close_device(win_ddb_close);
45
private dev_proc_map_rgb_color(win_ddb_map_rgb_color);
46
private dev_proc_fill_rectangle(win_ddb_fill_rectangle);
47
private dev_proc_tile_rectangle(win_ddb_tile_rectangle);
48
private dev_proc_copy_mono(win_ddb_copy_mono);
49
private dev_proc_copy_color(win_ddb_copy_color);
50
 
51
/* Windows-specific procedures */
52
private win_proc_copy_to_clipboard(win_ddb_copy_to_clipboard);
53
private win_proc_repaint(win_ddb_repaint);
54
private win_proc_alloc_bitmap(win_ddb_alloc_bitmap);
55
private win_proc_free_bitmap(win_ddb_free_bitmap);
56
 
57
/* The device descriptor */
58
struct gx_device_win_ddb_s {
59
    gx_device_common;
60
    gx_device_win_common;
61
 
62
    /* Handles */
63
 
64
    HBITMAP FAR hbitmap;
65
    HDC FAR hdcbit;
66
    HPEN hpen, *hpens;
67
    uint hpensize;
68
    HBRUSH hbrush, *hbrushs;
69
    uint hbrushsize;
70
#define select_brush(color)\
71
  if (wdev->hbrush != wdev->hbrushs[color])\
72
   {	wdev->hbrush = wdev->hbrushs[color];\
73
	SelectObject(wdev->hdcbit,wdev->hbrush);\
74
   }
75
    HPALETTE hpalette;
76
    LPLOGPALETTE lpalette;
77
 
78
    /* A staging bitmap for copy_mono. */
79
    /* We want one big enough to handle the standard 16x16 halftone; */
80
    /* this is also big enough for ordinary-size characters. */
81
 
82
#define bmWidthBytes 4		/* must be even */
83
#define bmWidthBits (bmWidthBytes * 8)
84
#define bmHeight 32
85
    HBITMAP FAR hbmmono;
86
    HDC FAR hdcmono;
87
    gx_bitmap_id bm_id;
88
};
89
private const gx_device_procs win_ddb_procs =
90
{
91
    win_ddb_open,
92
    NULL,			/* get_initial_matrix */
93
    win_sync_output,
94
    win_output_page,
95
    win_ddb_close,
96
    win_ddb_map_rgb_color,
97
    win_map_color_rgb,
98
    win_ddb_fill_rectangle,
99
    win_ddb_tile_rectangle,
100
    win_ddb_copy_mono,
101
    win_ddb_copy_color,
102
    NULL,			/* draw_line */
103
    NULL,			/* get_bits */
104
    win_get_params,
105
    win_put_params,
106
    NULL,			/* map_cmyk_color */
107
    win_get_xfont_procs
108
};
109
gx_device_win_ddb far_data gs_mswin_device =
110
{
111
    std_device_std_body(gx_device_win_ddb, &win_ddb_procs, "mswin",
112
			INITIAL_WIDTH, INITIAL_HEIGHT,	/* win_open() fills these in later */
113
			INITIAL_RESOLUTION, INITIAL_RESOLUTION	/* win_open() fills these in later */
114
    ),
115
    {0},			/* std_procs */
116
    0,				/* BitsPerPixel - not used */
117
    5000,			/* UpdateInterval (in milliseconds) */
118
    "\0",			/* GSVIEW_STR */
119
    0,				/* not a DLL device */
120
    2,				/* nColors */
121
    0,				/* mapped_color_flags */
122
    win_ddb_copy_to_clipboard,
123
    win_ddb_repaint,
124
    win_ddb_alloc_bitmap,
125
    win_ddb_free_bitmap
126
};
127
 
128
/* Open the win_ddb driver */
129
private int
130
win_ddb_open(gx_device * dev)
131
{
132
    int code = win_open(dev);
133
    HDC hdc;
134
 
135
    if (code < 0)
136
	return code;
137
 
138
    if (wdev->BitsPerPixel > 8)
139
	return gs_error_limitcheck;	/* don't support 24 bit/pixel */
140
 
141
    /* Create the backing bitmap. */
142
    code = win_ddb_alloc_bitmap((gx_device_win *) dev, dev);
143
    if (code < 0)
144
	return code;
145
 
146
    /* Create the bitmap and DC for copy_mono. */
147
    hdc = GetDC(wdev->hwndimg);
148
    wdev->hbmmono = CreateBitmap(bmWidthBits, bmHeight, 1, 1, NULL);
149
    wdev->hdcmono = CreateCompatibleDC(hdc);
150
    if (wdev->hbmmono == NULL || wdev->hdcmono == NULL) {
151
	win_ddb_free_bitmap((gx_device_win *) dev);
152
	ReleaseDC(wdev->hwndimg, hdc);
153
	return win_nomemory();
154
    }
155
    SetMapMode(wdev->hdcmono, GetMapMode(hdc));
156
    SelectObject(wdev->hdcmono, wdev->hbmmono);
157
    wdev->bm_id = gx_no_bitmap_id;
158
    ReleaseDC(wdev->hwndimg, hdc);
159
 
160
    /* create palette and tools for bitmap */
161
    if ((wdev->lpalette = win_makepalette((gx_device_win *) dev))
162
	== (LPLOGPALETTE) NULL)
163
	return win_nomemory();
164
    wdev->hpalette = CreatePalette(wdev->lpalette);
165
    (void)SelectPalette(wdev->hdcbit, wdev->hpalette, NULL);
166
    RealizePalette(wdev->hdcbit);
167
    win_maketools(wdev, wdev->hdcbit);
168
 
169
    wdev->hdctext = wdev->hdcbit;	/* draw text here */
170
 
171
    return 0;
172
}
173
 
174
/* Close the win_ddb driver */
175
private int
176
win_ddb_close(gx_device * dev)
177
{
178
    /* Free resources */
179
 
180
    win_destroytools(wdev);
181
    DeleteDC(wdev->hdcmono);
182
    win_ddb_free_bitmap((gx_device_win *) dev);
183
    DeleteObject(wdev->hpalette);
184
    DeleteObject(wdev->hbmmono);
185
    gs_free((char *)(wdev->lpalette), 1, sizeof(LOGPALETTE) +
186
	    (1 << (wdev->color_info.depth)) * sizeof(PALETTEENTRY),
187
	    "win_ddb_close");
188
 
189
    return win_close(dev);
190
}
191
 
192
/* Map a r-g-b color to the colors available under Windows */
193
private gx_color_index
194
win_ddb_map_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
195
		      gx_color_value b)
196
{
197
    int i = wdev->nColors;
198
    gx_color_index color = win_map_rgb_color(dev, r, g, b);
199
    LPLOGPALETTE lipal = wdev->limgpalette;
200
    LPLOGPALETTE lpal = wdev->lpalette;
201
 
202
    if (color != i)
203
	return color;
204
 
205
    /* We just added a color to the window palette. */
206
    /* Add it to the bitmap palette as well. */
207
 
208
    DeleteObject(wdev->hpalette);
209
    lpal->palPalEntry[i].peFlags = NULL;
210
    lpal->palPalEntry[i].peRed = lipal->palPalEntry[i].peRed;
211
    lpal->palPalEntry[i].peGreen = lipal->palPalEntry[i].peGreen;
212
    lpal->palPalEntry[i].peBlue = lipal->palPalEntry[i].peBlue;
213
    lpal->palNumEntries = i + 1;
214
    wdev->hpalette = CreatePalette(lpal);
215
    (void)SelectPalette(wdev->hdcbit, wdev->hpalette, NULL);
216
    RealizePalette(wdev->hdcbit);
217
    win_addtool(wdev, i);
218
 
219
    return color;
220
}
221
 
222
/* Macro for filling a rectangle with a color. */
223
/* Note that it starts with a declaration. */
224
#define fill_rect(x, y, w, h, color)\
225
RECT rect;\
226
rect.left = x, rect.top = y;\
227
rect.right = x + w, rect.bottom = y + h;\
228
FillRect(wdev->hdcbit, &rect, wdev->hbrushs[(int)color])
229
 
230
 
231
/* Fill a rectangle. */
232
private int
233
win_ddb_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
234
		       gx_color_index color)
235
{
236
    fit_fill(dev, x, y, w, h);
237
    /* Use PatBlt for filling.  Special-case black. */
238
    if (color == 0)
239
	PatBlt(wdev->hdcbit, x, y, w, h, rop_write_0s);
240
    else {
241
	select_brush((int)color);
242
	PatBlt(wdev->hdcbit, x, y, w, h, rop_write_pattern);
243
    }
244
    win_update((gx_device_win *) dev);
245
 
246
    return 0;
247
}
248
 
249
/* Tile a rectangle.  If neither color is transparent, */
250
/* pre-clear the rectangle to color0 and just tile with color1. */
251
/* This is faster because of how win_copy_mono is implemented. */
252
/* Note that this also does the right thing for colored tiles. */
253
private int
254
win_ddb_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
255
      int x, int y, int w, int h, gx_color_index czero, gx_color_index cone,
256
		       int px, int py)
257
{
258
    fit_fill(dev, x, y, w, h);
259
    if (czero != gx_no_color_index && cone != gx_no_color_index) {
260
	fill_rect(x, y, w, h, czero);
261
	czero = gx_no_color_index;
262
    }
263
    if (tile->raster == bmWidthBytes && tile->size.y <= bmHeight &&
264
	(px | py) == 0 && cone != gx_no_color_index
265
	) {			/* We can do this much more efficiently */
266
	/* by using the internal algorithms of copy_mono */
267
	/* and gx_default_tile_rectangle. */
268
	int width = tile->size.x;
269
	int height = tile->size.y;
270
	int rwidth = tile->rep_width;
271
	int irx = ((rwidth & (rwidth - 1)) == 0 ?	/* power of 2 */
272
		   x & (rwidth - 1) :
273
		   x % rwidth);
274
	int ry = y % tile->rep_height;
275
	int icw = width - irx;
276
	int ch = height - ry;
277
	int ex = x + w, ey = y + h;
278
	int fex = ex - width, fey = ey - height;
279
	int cx, cy;
280
 
281
	select_brush((int)cone);
282
 
283
	if (tile->id != wdev->bm_id || tile->id == gx_no_bitmap_id) {
284
	    wdev->bm_id = tile->id;
285
	    SetBitmapBits(wdev->hbmmono,
286
			  (DWORD) (bmWidthBytes * tile->size.y),
287
			  (BYTE *) tile->data);
288
	}
289
#define copy_tile(srcx, srcy, tx, ty, tw, th)\
290
  BitBlt(wdev->hdcbit, tx, ty, tw, th, wdev->hdcmono, srcx, srcy, rop_write_at_1s)
291
 
292
	if (ch > h)
293
	    ch = h;
294
	for (cy = y;;) {
295
	    if (w <= icw)
296
		copy_tile(irx, ry, x, cy, w, ch);
297
	    else {
298
		copy_tile(irx, ry, x, cy, icw, ch);
299
		cx = x + icw;
300
		while (cx <= fex) {
301
		    copy_tile(0, ry, cx, cy, width, ch);
302
		    cx += width;
303
		}
304
		if (cx < ex) {
305
		    copy_tile(0, ry, cx, cy, ex - cx, ch);
306
		}
307
	    }
308
	    if ((cy += ch) >= ey)
309
		break;
310
	    ch = (cy > fey ? ey - cy : height);
311
	    ry = 0;
312
	}
313
 
314
	win_update((gx_device_win *) dev);
315
	return 0;
316
    }
317
    return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py);
318
}
319
 
320
 
321
/* Copy a monochrome bitmap.  The colors are given explicitly. */
322
/* Color = gx_no_color_index means transparent (no effect on the image). */
323
private int
324
win_ddb_copy_mono(gx_device * dev,
325
		const byte * base, int sourcex, int raster, gx_bitmap_id id,
326
		  int x, int y, int w, int h,
327
		  gx_color_index zero, gx_color_index one)
328
{
329
    int endx;
330
    const byte *ptr_line;
331
    int width_bytes, height;
332
    DWORD rop = rop_write_at_1s;
333
    int color;
334
    BYTE aBit[bmWidthBytes * bmHeight];
335
    BYTE *aptr = aBit;
336
 
337
    fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
338
 
339
    if (sourcex & ~7) {
340
	base += sourcex >> 3;
341
	sourcex &= 7;
342
    }
343
    /* Break up large transfers into smaller ones. */
344
    while ((endx = sourcex + w) > bmWidthBits) {
345
	int lastx = (endx - 1) & -bmWidthBits;
346
	int subw = endx - lastx;
347
	int code = win_ddb_copy_mono(dev, base, lastx,
348
				     raster, gx_no_bitmap_id,
349
				     x + lastx - sourcex, y,
350
				     subw, h, zero, one);
351
 
352
	if (code < 0)
353
	    return code;
354
	w -= subw;
355
    }
356
    while (h > bmHeight) {
357
	int code;
358
 
359
	h -= bmHeight;
360
	code = win_ddb_copy_mono(dev, base + h * raster, sourcex,
361
				 raster, gx_no_bitmap_id,
362
				 x, y + h, w, bmHeight, zero, one);
363
	if (code < 0)
364
	    return code;
365
    }
366
 
367
    width_bytes = (sourcex + w + 7) >> 3;
368
    ptr_line = base;
369
 
370
    if (zero == gx_no_color_index) {
371
	if (one == gx_no_color_index)
372
	    return 0;
373
	color = (int)one;
374
	if (color == 0)
375
	    rop = rop_write_0_at_1s;
376
	else
377
	    select_brush(color);
378
    } else {
379
	if (one == gx_no_color_index) {
380
	    color = (int)zero;
381
	    rop = rop_write_at_0s;
382
	} else {		/* Pre-clear the rectangle to zero */
383
	    fill_rect(x, y, w, h, zero);
384
	    color = (int)one;
385
	}
386
	select_brush(color);
387
    }
388
 
389
    if (id != wdev->bm_id || id == gx_no_bitmap_id) {
390
	wdev->bm_id = id;
391
	if (raster == bmWidthBytes) {	/* We can do the whole thing in a single transfer! */
392
	    SetBitmapBits(wdev->hbmmono,
393
			  (DWORD) (bmWidthBytes * h),
394
			  (BYTE *) base);
395
	} else {
396
	    for (height = h; height--;
397
		 ptr_line += raster, aptr += bmWidthBytes
398
		) {		/* Pack the bits into the bitmap. */
399
		switch (width_bytes) {
400
		    default:
401
			memcpy(aptr, ptr_line, width_bytes);
402
			break;
403
		    case 4:
404
			aptr[3] = ptr_line[3];
405
		    case 3:
406
			aptr[2] = ptr_line[2];
407
		    case 2:
408
			aptr[1] = ptr_line[1];
409
		    case 1:
410
			aptr[0] = ptr_line[0];
411
		}
412
	    }
413
	    SetBitmapBits(wdev->hbmmono,
414
			  (DWORD) (bmWidthBytes * h),
415
			  &aBit[0]);
416
	}
417
    }
418
    BitBlt(wdev->hdcbit, x, y, w, h, wdev->hdcmono, sourcex, 0, rop);
419
    win_update((gx_device_win *) dev);
420
    return 0;
421
}
422
 
423
 
424
/* Copy a color pixel map.  This is just like a bitmap, except that */
425
/* each pixel takes 8 or 4 bits instead of 1 when device driver has color. */
426
private int
427
win_ddb_copy_color(gx_device * dev,
428
		const byte * base, int sourcex, int raster, gx_bitmap_id id,
429
		   int x, int y, int w, int h)
430
{
431
    fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
432
 
433
    if (gx_device_has_color(dev)) {
434
	switch (dev->color_info.depth) {
435
	    case 8:
436
		{
437
		    int xi, yi;
438
		    int skip = raster - w;
439
		    const byte *sptr = base + sourcex;
440
 
441
		    if (w <= 0)
442
			return 0;
443
		    if (x < 0 || x + w > dev->width)
444
			return_error(gs_error_rangecheck);
445
		    for (yi = y; yi - y < h; yi++) {
446
			for (xi = x; xi - x < w; xi++) {
447
			    int color = *sptr++;
448
 
449
			    SetPixel(wdev->hdcbit, xi, yi, PALETTEINDEX(color));
450
			}
451
			sptr += skip;
452
		    }
453
		}
454
		break;
455
	    case 4:
456
		{		/* color device, four bits per pixel */
457
		    const byte *line = base + (sourcex >> 1);
458
		    int dest_y = y, end_x = x + w;
459
 
460
		    if (w <= 0)
461
			return 0;
462
		    while (h--) {	/* for each line */
463
			const byte *source = line;
464
			register int dest_x = x;
465
 
466
			if (sourcex & 1) {	/* odd nibble first */
467
			    int color = *source++ & 0xf;
468
 
469
			    SetPixel(wdev->hdcbit, dest_x, dest_y, PALETTEINDEX(color));
470
			    dest_x++;
471
			}
472
			/* Now do full bytes */
473
			while (dest_x < end_x) {
474
			    int color = *source >> 4;
475
 
476
			    SetPixel(wdev->hdcbit, dest_x, dest_y, PALETTEINDEX(color));
477
			    dest_x++;
478
			    if (dest_x < end_x) {
479
				color = *source++ & 0xf;
480
				SetPixel(wdev->hdcbit, dest_x, dest_y, PALETTEINDEX(color));
481
				dest_x++;
482
			    }
483
			}
484
			dest_y++;
485
			line += raster;
486
		    }
487
		}
488
		break;
489
	    default:
490
		return (-1);	/* panic */
491
	}
492
    } else
493
	/* monochrome device: one bit per pixel */
494
    {				/* bitmap is the same as win_copy_mono: one bit per pixel */
495
	win_ddb_copy_mono(dev, base, sourcex, raster, id, x, y, w, h,
496
			  (gx_color_index) 0,
497
			  (gx_color_index) (dev->color_info.depth == 8 ? 63 : dev->color_info.max_gray));
498
    }
499
    win_update((gx_device_win *) dev);
500
    return 0;
501
}
502
 
503
/* ------ Windows-specific device procedures ------ */
504
 
505
 
506
/* Copy the bitmap to the clipboard. */
507
private void
508
win_ddb_copy_to_clipboard(gx_device_win * dev)
509
{				/* make somewhere to put it and copy */
510
    HDC hdcbit = wdev->hdcbit;
511
    HBITMAP bitmap = CreateCompatibleBitmap(hdcbit, dev->width,
512
					    dev->height);
513
 
514
    if (bitmap) {
515
	/* there is enough memory and the bitmaps OK */
516
	HDC mem = CreateCompatibleDC(hdcbit);
517
 
518
	SelectObject(mem, bitmap);
519
	BitBlt(mem, 0, 0, dev->width, dev->height,
520
	       hdcbit, 0, 0, SRCCOPY);
521
	DeleteDC(mem);
522
	/* copy it to the clipboard */
523
	OpenClipboard(wdev->hwndimg);
524
	EmptyClipboard();
525
	SetClipboardData(CF_BITMAP, bitmap);
526
	SetClipboardData(CF_PALETTE, CreatePalette(wdev->limgpalette));
527
	CloseClipboard();
528
    }
529
}
530
 
531
 
532
/* Repaint a section of the window. */
533
private void
534
win_ddb_repaint(gx_device_win * dev, HDC hdc, int dx, int dy, int wx, int wy,
535
		int sx, int sy)
536
{
537
    BitBlt(hdc, dx, dy, wx, wy, wdev->hdcbit, sx, sy, SRCCOPY);
538
}
539
 
540
 
541
/* Allocate the backing bitmap. */
542
private int
543
win_ddb_alloc_bitmap(gx_device_win * dev, gx_device * param_dev)
544
{
545
    HDC hdc;
546
    int i;
547
 
548
    hdc = GetDC(wdev->hwndimg);
549
    for (i = 0;; i++) {
550
	wdev->hbitmap = CreateCompatibleBitmap(hdc,
551
				       param_dev->width, param_dev->height);
552
	if (wdev->hbitmap != (HBITMAP) NULL)
553
	    break;
554
	if (i >= 4) {
555
	    ReleaseDC(wdev->hwndimg, hdc);
556
	    return win_nomemory();
557
	}
558
	errprintf("\nNot enough memory for bitmap.  Halving resolution... ");
559
	param_dev->x_pixels_per_inch /= 2;
560
	param_dev->y_pixels_per_inch /= 2;
561
	param_dev->width /= 2;
562
	param_dev->height /= 2;
563
    }
564
 
565
    wdev->hdcbit = CreateCompatibleDC(hdc);	/* create Device Context for drawing */
566
    SelectObject(wdev->hdcbit, wdev->hbitmap);
567
    ReleaseDC(wdev->hwndimg, hdc);
568
    return 0;
569
}
570
 
571
 
572
/* Free the backing bitmap. */
573
private void
574
win_ddb_free_bitmap(gx_device_win * dev)
575
{
576
    DeleteDC(wdev->hdcbit);	/* must do this first */
577
    DeleteObject(wdev->hbitmap);
578
}
579
 
580
 
581
/* ------ Internal routines ------ */
582
 
583
#undef wdev
584
 
585
 
586
private void near
587
win_addtool(gx_device_win_ddb * wdev, int i)
588
{
589
    wdev->hpens[i] = CreatePen(PS_SOLID, 1, PALETTEINDEX(i));
590
    wdev->hbrushs[i] = CreateSolidBrush(PALETTEINDEX(i));
591
}
592
 
593
 
594
private void near
595
win_maketools(gx_device_win_ddb * wdev, HDC hdc)
596
{
597
    int i;
598
 
599
    wdev->hpensize = (1 << (wdev->color_info.depth)) * sizeof(HPEN);
600
    wdev->hpens = (HPEN *) gs_malloc(wdev->memory, 1, wdev->hpensize,
601
				     "win_maketools(pens)");
602
    wdev->hbrushsize = (1 << (wdev->color_info.depth)) * sizeof(HBRUSH);
603
    wdev->hbrushs = (HBRUSH *) gs_malloc(wdev->memory, 1, wdev->hbrushsize,
604
					 "win_maketools(brushes)");
605
    if (wdev->hpens && wdev->hbrushs) {
606
	for (i = 0; i < wdev->nColors; i++)
607
	    win_addtool(wdev, i);
608
 
609
	wdev->hpen = wdev->hpens[0];
610
	SelectObject(hdc, wdev->hpen);
611
 
612
	wdev->hbrush = wdev->hbrushs[0];
613
	SelectObject(hdc, wdev->hbrush);
614
    }
615
}
616
 
617
 
618
private void near
619
win_destroytools(gx_device_win_ddb * wdev)
620
{
621
    int i;
622
 
623
    for (i = 0; i < wdev->nColors; i++) {
624
	DeleteObject(wdev->hpens[i]);
625
	DeleteObject(wdev->hbrushs[i]);
626
    }
627
    gs_free(wdev->memory, (char *)wdev->hbrushs, 1, wdev->hbrushsize,
628
	    "win_destroytools(brushes)");
629
    gs_free(wdev->memory, (char *)wdev->hpens, 1, wdev->hpensize,
630
	    "win_destroytools(pens)");
631
}