~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to base/gdevwddb.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

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