386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / gdevsun.c
CommitLineData
fade9343
WJ
1/* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* gdevsun.c */
21/* SunView driver for Ghostscript */
22#include "gx.h" /* for gx_bitmap; includes std.h */
23
24#include <suntool/sunview.h>
25#include <suntool/canvas.h>
26#include <sunwindow/cms_mono.h>
27#include <stdio.h>
28
29#include "gsmatrix.h" /* needed for gxdevice.h */
30#include "gxdevice.h"
31#include "malloc_.h"
32
33#ifndef DEFAULT_DPI
34# define DEFAULT_DPI 75 /* Sun standard monitor */
35#endif
36
37/* Procedures */
38dev_proc_open_device(sun_open);
39dev_proc_sync_output(sun_sync);
40dev_proc_close_device(sun_close);
41dev_proc_map_rgb_color(sun_map_rgb_color);
42dev_proc_map_color_rgb(sun_map_color_rgb);
43dev_proc_fill_rectangle(sun_fill_rectangle);
44dev_proc_copy_mono(sun_copy_mono);
45dev_proc_copy_color(sun_copy_color);
46dev_proc_draw_line(sun_draw_line);
47
48/* The device descriptor */
49private gx_device_procs sun_procs = {
50 sun_open,
51 gx_default_get_initial_matrix,
52 sun_sync,
53 gx_default_output_page,
54 sun_close,
55 sun_map_rgb_color,
56 sun_map_color_rgb,
57 sun_fill_rectangle,
58 gx_default_tile_rectangle,
59 sun_copy_mono,
60 sun_copy_color,
61 sun_draw_line,
62 gx_default_get_bits,
63 gx_default_get_props,
64 gx_default_put_props
65};
66
67#define CMSNAME "GHOSTVIEW" /* SunView colormap name */
68
69/* Define the SunView device */
70typedef struct gx_device_sun {
71 gx_device_common;
72 Frame frame;
73 Canvas canvas;
74 Pixwin *pw;
75 struct mpr_data mpr;
76 Pixrect pr;
77 int truecolor; /* use truecolor mapping */
78 gx_color_index ncols; /* allocated colors */
79 byte *red, *green, *blue; /* colormap */
80 char cmsname[sizeof(CMSNAME)+9];/* color map name */
81#if !arch_is_big_endian /* need to swap bits & bytes */
82# define BUF_WIDTH_BYTES (((int)(8.5*DEFAULT_DPI)+15)/16*2)
83 byte swap_buf[BUF_WIDTH_BYTES];
84#endif
85} gx_device_sun;
86
87#if !arch_is_big_endian
88/* Define a table for reversing bit order. */
89static byte reverse_bits[256] = {
90 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
91 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
92 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
93 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
94 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
95 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
96 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
97 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
98 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
99 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
100 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
101 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
102 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
103 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
104 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
105 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
106};
107#endif
108
109/* The instance is public. */
110gx_device_sun gs_sunview_device = {
111 sizeof(gx_device_sun),
112 &sun_procs,
113 "sunview",
114 (int)(8.5*DEFAULT_DPI), (int)(11*DEFAULT_DPI), /* x and y extent */
115 DEFAULT_DPI, DEFAULT_DPI, /* x and y density */
116 no_margins,
117 dci_color(0,0,0), /* fill in later from display depth */
118 0, /* connection not initialized */
119};
120
121/* Macro for casting gx_device argument */
122#define xdev ((gx_device_sun *)dev)
123
124/* Macro to validate arguments */
125#define check_rect()\
126 if ( w <= 0 || h <= 0 ) return 0;\
127 if ( x < 0 || x > xdev->width - w || y < 0 || y > xdev->height - h )\
128 return -1
129
130/*
131 * The macros below define the colormap configuration used on 8-bit
132 * pseudo-color displays.
133 */
134/*
135 * The following macros define the number of bits used to represent rgb colors.
136 * The total must not exceed the display depth.
137 * Note that the RGB dimensions could have an uneven number of bits assigned
138 * to them, but that will cause dithering to not work very well, since
139 * gs assumes the dither ramp is the same for all 3 color dimensions.
140 *
141 * Setting RED_BITS to n will pre-allocate a color-cube of 2^(3n) entries.
142 * The remaining entries are allocated on demand for colors requested by
143 * sun_map_rgb_color(), until the color map is full. At that point gs will
144 * fall back onto dithering using the pre-allocated colors.
145 * As a special case, if RED_BITS = GREEN_BITS = BLUE_BITS = 0, only
146 * black and white are pre-allocated.
147 */
148#define RED_BITS 2 /* everything depends on this one */
149#define GREEN_BITS RED_BITS
150#define BLUE_BITS RED_BITS
151#define DEPTH 8 /* don't change this */
152#define RGB_BITS (RED_BITS + GREEN_BITS + BLUE_BITS)
153/*
154 * Smallest # bits per dimension
155 */
156#define MAX_BITS RED_BITS
157#if (GREEN_BITS > MAX_BITS)
158#undef MAX_BITS
159#define MAX_BITS GREEN_BITS
160#endif
161#if (BLUE_BITS > MAX_BITS)
162#undef MAX_BITS
163#define MAX_BITS BLUE_BITS
164#endif
165/*
166 * masks to pull out rgb components
167 */
168#define BLUE_MASK ((1 << BLUE_BITS) - 1)
169#define GREEN_MASK ((1 << (BLUE_BITS + GREEN_BITS)) - 1 - BLUE_MASK)
170#define RED_MASK ((1 << (BLUE_BITS + GREEN_BITS + RED_BITS)) - 1 \
171 - BLUE_MASK - GREEN_MASK)
172/*
173 * number of colors on rgb dimensions
174 */
175#define RED_COLS (1 << RED_BITS)
176#define GREEN_COLS (1 << GREEN_BITS)
177#define BLUE_COLS (1 << BLUE_BITS)
178#define RGB_COLS (RED_COLS * GREEN_COLS * BLUE_COLS)
179#define MAX_COLS (1 << MAX_BITS)
180/*
181 * maximum number of colors in map
182 */
183#define ALL_COLS (1 << DEPTH) /* 256 */
184
185#if (RGB_BITS < 0) || (RGB_BITS > DEPTH)
186Display_does_not_support_this_many_colors
187#endif
188
189/*
190 * The macros below define the color mapping used on 24-bit true-color
191 * displays.
192 * FAKE_TRUE_COLOR is used for debugging only. It simulates a true-color
193 * type mapping on an 8-bit pseudo-color display.
194#define FAKE_TRUE_COLOR
195 */
196#ifdef FAKE_TRUE_COLOR
197# define TRUE_RED_BITS 3 /* everything depends on this one */
198# define TRUE_GREEN_BITS 2
199# define TRUE_BLUE_BITS (DEPTH - TRUE_RED_BITS - TRUE_GREEN_BITS)
200#else
201# define TRUE_RED_BITS 8 /* everything depends on this one */
202# define TRUE_GREEN_BITS TRUE_RED_BITS
203# define TRUE_BLUE_BITS TRUE_RED_BITS
204#endif ./* FAKE_TRUE_COLOR */
205#define TRUE_DEPTH (TRUE_RED_BITS + TRUE_GREEN_BITS + TRUE_BLUE_BITS)
206/*
207 * Masks to pull out rgb components. Note that the bit order is BGR from
208 * high to low order bits.
209 */
210#define TRUE_RED_MASK ((1 << TRUE_RED_BITS) - 1)
211#define TRUE_GREEN_MASK ((1 << (TRUE_RED_BITS + TRUE_GREEN_BITS)) - 1 \
212 - TRUE_RED_MASK)
213#define TRUE_BLUE_MASK ((1 << (TRUE_RED_BITS + TRUE_GREEN_BITS \
214 + TRUE_BLUE_BITS)) - 1 \
215 - TRUE_GREEN_MASK - TRUE_RED_MASK)
216/*
217 * number of colors on rgb dimensions
218 */
219#define TRUE_RED_COLS (1 << TRUE_RED_BITS)
220#define TRUE_GREEN_COLS (1 << TRUE_GREEN_BITS)
221#define TRUE_BLUE_COLS (1 << TRUE_BLUE_BITS)
222
223/* Initialize the device. */
224private Notify_value destroy_func();
225int
226sun_open(register gx_device *dev)
227{
228#ifdef gs_DEBUG
229if ( gs_debug['X'] )
230 { extern int _Xdebug;
231 _Xdebug = 1;
232 }
233#endif
234 if (xdev->frame == (Frame)0)
235 xdev->frame =
236 window_create(NULL, FRAME, FRAME_LABEL, "ghostscript",
237 WIN_HEIGHT, xdev->width + 20,
238 WIN_HEIGHT, xdev->height + 40, 0);
239 if (xdev->frame == (Frame)0)
240 return -1;
241 xdev->canvas = window_create(xdev->frame, CANVAS,
242 CANVAS_AUTO_EXPAND, FALSE,
243 CANVAS_AUTO_SHRINK, FALSE,
244 CANVAS_WIDTH, xdev->width,
245 CANVAS_HEIGHT, xdev->height,
246#ifndef PRE_IBIS /* try to use 24-bit visual if OS supports it */
247 CANVAS_COLOR24, TRUE,
248#endif
249 WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
250 WIN_HORIZONTAL_SCROLLBAR, scrollbar_create(0),
251 0);
252 xdev->pw = canvas_pixwin(xdev->canvas);
253
254 switch (xdev->pw->pw_pixrect->pr_depth) {
255 static gx_device_color_info mono_ci =
256 dci_black_and_white;
257 /*
258 * If the pre-allocated color cube leaves room for spare entries,
259 * tell gs we can render colors exactly. Otherwise admit our
260 * limitations.
261 */
262 static gx_device_color_info color_ci =
263#if (RGB_COLS < ALL_COLS)
264 dci_color(DEPTH, 31, MAX_COLS);
265#else
266 dci_color(DEPTH, MAX_COLS - 1, MAX_COLS);
267#endif
268 static gx_device_color_info truecolor_ci =
269 dci_color(TRUE_DEPTH,31,4);
270 case 1:
271 /* mono display */
272 xdev->color_info = mono_ci;
273 break;
274#ifndef FAKE_TRUE_COLOR
275 case DEPTH:
276 /* pseudo-color display */
277 xdev->color_info = color_ci;
278 xdev->truecolor = 0;
279 break;
280#endif /* FAKE_TRUE_COLOR */
281 case TRUE_DEPTH:
282 case TRUE_DEPTH+8: /* I'm not sure whether the XBGR frame buffer
283 returns depth 24 or 32. */
284 /* pseudo-color display */
285 xdev->color_info = truecolor_ci;
286 xdev->truecolor = 1;
287 break;
288 default:
289 eprintf1("gs: Cannot handle display of depth %d.\n",
290 xdev->pw->pw_pixrect->pr_depth);
291 return -1;
292 }
293
294 if ( gx_device_has_color(xdev)
295#ifndef FAKE_TRUE_COLOR
296 && !xdev->truecolor
297#endif
298 )
299 {
300 gx_color_index j;
301
302 /*
303 * Create the pre-allocated colorcube.
304 */
305 xdev->red = (byte *)malloc(ALL_COLS);
306 xdev->green = (byte *)malloc(ALL_COLS);
307 xdev->blue = (byte *)malloc(ALL_COLS);
308 if (!xdev->red || !xdev->green || !xdev->blue) {
309 eprintf("gs: no memory for colomap\n");
310 return -1;
311 }
312
313#ifdef FAKE_TRUE_COLOR
314 /*
315 * Fit the largest possible color cube into the colormap.
316 */
317 for ( j = 0; j < ALL_COLS; j++ ) {
318 xdev->blue[j] =
319 (double)((j & TRUE_BLUE_MASK)
320 >> (TRUE_GREEN_BITS + TRUE_RED_BITS))
321 / (TRUE_BLUE_COLS - 1)
322 * (ALL_COLS - 1);
323 xdev->green[j] =
324 (double)((j & TRUE_GREEN_MASK) >> TRUE_RED_BITS)
325 / (TRUE_GREEN_COLS - 1)
326 * (ALL_COLS - 1);
327 xdev->red[j] =
328 (double)((j & TRUE_RED_MASK))
329 / (TRUE_RED_COLS - 1)
330 * (ALL_COLS - 1);
331 }
332#else /* !FAKE_TRUE_COLOR */
333 /*
334 * Black and white are allocated in the first two slots,
335 * so as to be compatible with the monochrome colormap.
336 * This prevents most text etc. to go technicolor as focus
337 * changes into the ghostscript window.
338 */
339 cms_monochromeload(xdev->red, xdev->green, xdev->blue);
340
341 /*
342 * The remaining slots up to RGB_COLS-1 are filled with
343 * evenly spaced points from the colorcube.
344 */
345 for ( j = 2; j < RGB_COLS; j++ ) {
346 int color = j - 1; /* bit pattern corresponding to color */
347 xdev->red[j] =
348 (double)((color & RED_MASK) >> (GREEN_BITS + BLUE_BITS))
349 / (RED_COLS - 1)
350 * (ALL_COLS - 1);
351 xdev->green[j] =
352 (double)((color & GREEN_MASK) >> BLUE_BITS)
353 / (GREEN_COLS - 1)
354 * (ALL_COLS - 1);
355 xdev->blue[j] =
356 (double)((color & BLUE_MASK))
357 / (BLUE_COLS - 1)
358 * (ALL_COLS - 1);
359 }
360#endif /* FAKE_TRUE_COLOR */
361
362 /*
363 * Set the high-water mark to the end of the colorcube.
364 */
365 xdev->ncols = j;
366
367 /*
368 * The unusued entries are filled so that the last entry is
369 * always different from the 0th entry. This is a requirement
370 * for SunWindows.
371 */
372 for ( ; j < ALL_COLS; j++) {
373 xdev->red[j] = xdev->green[j] = xdev->blue[j] =
374 ~xdev->red[0];
375 }
376
377 /*
378 * Install the colormap.
379 */
380 sprintf(xdev->cmsname, "%s-%d", CMSNAME, getpid());
381 pw_setcmsname(xdev->pw, xdev->cmsname);
382 pw_putcolormap(xdev->pw, 0, ALL_COLS,
383 xdev->red, xdev->green, xdev->blue);
384 }
385 else {
386 xdev->ncols = 0;
387 xdev->red = (byte *)0;
388 xdev->green = (byte *)0;
389 xdev->blue = (byte *)0;
390 }
391
392 window_set(xdev->frame, WIN_SHOW, TRUE, 0);
393 /* Interpose a destroy function to keep Ghostscript from */
394 /* getting confused if the user closes the window. */
395 notify_interpose_destroy_func(xdev->frame, destroy_func);
396 (void) notify_do_dispatch();
397 (void) notify_dispatch();
398 return 0;
399}
400/* Prevent the user from closing the window. */
401private Notify_value
402destroy_func(Frame frame, Destroy_status status)
403{ if ( status == DESTROY_CHECKING )
404 { notify_veto_destroy(frame);
405 return (NOTIFY_DONE);
406 }
407 return (notify_next_destroy_func(frame, status));
408}
409
410/* Close the device. */
411int
412sun_close(gx_device *dev)
413{ window_destroy(xdev->frame);
414 xdev->frame = (Frame)0;
415 xdev->canvas = (Canvas)0;
416 xdev->pw = (Pixwin *)0;
417 xdev->ncols = 0;
418 if (xdev->red)
419 free(xdev->red);
420 if (xdev->green)
421 free(xdev->green);
422 if (xdev->blue)
423 free(xdev->blue);
424 return 0;
425}
426
427/* Synchronize the display with the commands already given */
428int
429sun_sync(register gx_device *dev)
430{ (void) notify_dispatch();
431 return 0;
432}
433
434/* Map RGB to color number -
435 Look for existing entry in colormap, or create a new one, or
436 give up if no free colormap entries (requesting dithering).
437 */
438gx_color_index
439sun_map_rgb_color(gx_device *dev, unsigned short red,
440 unsigned short green, unsigned short blue)
441{ if ( !gx_device_has_color(dev) )
442 /*
443 * Invert default color index to match mono display
444 * pixel values (black = 1, white = 0).
445 */
446 return !gx_default_map_rgb_color(dev, red, green, blue);
447 else if ( !xdev->truecolor ) {
448 byte red_val, green_val, blue_val;
449 gx_color_index i;
450 static int warn = 1;
451
452 /*
453 * Determine the RGB values at display resolution we
454 * ideally would want this color to be mapped into.
455 */
456 red_val = (double)red/gx_max_color_value * (ALL_COLS - 1);
457 green_val = (double)green/gx_max_color_value * (ALL_COLS - 1);
458 blue_val = (double)blue/gx_max_color_value * (ALL_COLS - 1);
459
460 /*
461 * Look for an exact match among the colors already allocated.
462 * This includes the pre-allocated default color cube.
463 */
464 for (i = 0; i < xdev->ncols; i++) {
465 if (xdev->red[i] == red_val &&
466 xdev->green[i] == green_val &&
467 xdev->blue[i] == blue_val) {
468 return i;
469 }
470 }
471
472 /*
473 * If we run out of space in the color map, let gs know.
474 * It will call us again to request colors to do the
475 * dithering, and hopefully request only RGB values that
476 * match the colorcube entries. IF NOT, WE WILL LOOP
477 * FOREVER!
478 */
479 if (xdev->ncols == ALL_COLS) {
480 if (warn) {
481 eprintf("gs: last spare color map entry allocated\n");
482 warn = 0;
483 }
484 return gx_no_color_index;
485 }
486
487 /*
488 * Allocate new color in map.
489 */
490 xdev->red[i] = red_val;
491 xdev->green[i] = green_val;
492 xdev->blue[i] = blue_val;
493 pw_setcmsname(xdev->pw, xdev->cmsname);
494 pw_putcolormap(xdev->pw, xdev->ncols, 1,
495 &xdev->red[i], &xdev->green[i], &xdev->blue[i]);
496
497 xdev->ncols++;
498
499 if (xdev->ncols == ALL_COLS)
500
501 return i;
502 }
503 else { /* true color mapping --
504 color index encodes all 3 RGB values */
505 return ((blue >> (gx_color_value_bits - TRUE_BLUE_BITS))
506 << (TRUE_GREEN_BITS + TRUE_RED_BITS)) |
507 ((green >> (gx_color_value_bits - TRUE_GREEN_BITS))
508 << TRUE_RED_BITS) |
509 (red >> (gx_color_value_bits - TRUE_RED_BITS));
510 }
511}
512
513/* Map color number back to RGB values - see sun_map_rgb_color(), above */
514int
515sun_map_color_rgb(gx_device *dev, gx_color_index color,
516 unsigned short rgb[3])
517{ if ( !gx_device_has_color(dev) )
518 return gx_default_map_color_rgb(dev, !color, rgb);
519 else if ( !xdev->truecolor ) {
520 /*
521 * We just use the colormap to map back to rgb values.
522 */
523 if (color >= xdev->ncols) {
524 eprintf1("gs: attempt to get RGB values for unallocated color index %d\n", color);
525 return -1;
526 }
527 rgb[0] = (double)xdev->red[color] / (ALL_COLS - 1)
528 * gx_max_color_value;
529 rgb[1] = (double)xdev->green[color] / (ALL_COLS - 1)
530 * gx_max_color_value;
531 rgb[2] = (double)xdev->blue[color] / (ALL_COLS - 1)
532 * gx_max_color_value;
533 return 0;
534 }
535 else { /* true color mapping */
536 rgb[0] = (double)((unsigned short)(color & TRUE_RED_MASK))
537 / (TRUE_RED_COLS - 1)
538 * gx_max_color_value;
539 rgb[1] = (double)((unsigned short)(color & TRUE_GREEN_MASK)
540 >> TRUE_RED_BITS)
541 / (TRUE_GREEN_COLS - 1)
542 * gx_max_color_value;
543 rgb[2] = (double)((unsigned short)(color & TRUE_BLUE_MASK)
544 >> (TRUE_GREEN_BITS + TRUE_RED_BITS))
545 / (TRUE_BLUE_COLS - 1)
546 * gx_max_color_value;
547 return 0;
548 }
549}
550
551/* Fill a rectangle with a color. */
552int
553sun_fill_rectangle(register gx_device *dev,
554 int x, int y, int w, int h, gx_color_index color)
555{ check_rect();
556
557 pw_write(xdev->pw, x, y, w, h, PIX_SRC | PIX_COLOR((int)(color)),
558 (Pixrect *)0, 0, 0);
559 (void) notify_dispatch();
560 return 0;
561}
562
563/* Copy a monochrome bitmap. */
564int
565sun_copy_mono(register gx_device *dev,
566 byte *base, int sourcex, int raster, gx_bitmap_id id,
567 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
568{
569 register int i;
570 int nbytes = h * raster;
571 extern struct pixrectops mem_ops;
572#if !arch_is_big_endian /* need to swap bits & bytes */
573# define BUF_WIDTH_BYTES (((int)(8.5*DEFAULT_DPI)+15)/16*2)
574 byte swap_buf[BUF_WIDTH_BYTES];
575#endif
576
577 check_rect();
578
579 xdev->pr.pr_ops = &mem_ops;
580 xdev->pr.pr_width = w + sourcex + 8;
581 xdev->pr.pr_height = h;
582 xdev->pr.pr_depth = 1;
583 xdev->pr.pr_data = (caddr_t)&(xdev->mpr);
584 xdev->mpr.md_linebytes = raster;
585 xdev->mpr.md_image = (short *)((ulong)base & ~1);
586#if !arch_is_big_endian
587 /* Reverse the bit order in each byte. */
588 for ( i = 0; i < nbytes; i++ ) base[i] = reverse_bits[base[i]];
589#endif
590 pw_batch_on(xdev->pw);
591 if (one != gx_no_color_index)
592 { pw_stencil(xdev->pw, x, y, w, h,
593 PIX_SRC | PIX_COLOR(one), &(xdev->pr),
594 ((int)base & 1) ? sourcex + 8 : sourcex, 0,
595 (Pixrect *)0, 0, 0);
596 }
597 if (zero != gx_no_color_index)
598 { for (i = 0; i < nbytes; i++) base[i] = ~base[i];
599 pw_stencil(xdev->pw, x, y, w, h,
600 PIX_SRC | PIX_COLOR(zero), &(xdev->pr),
601 ((int)base & 1) ? sourcex + 8 : sourcex, 0,
602 (Pixrect *)0, 0, 0);
603 for (i = 0; i < nbytes; i++) base[i] = ~base[i];
604 }
605 pw_batch_off(xdev->pw);
606#if !arch_is_big_endian
607 /* Reverse the bits back again. */
608 for ( i = 0; i < nbytes; i++ ) base[i] = reverse_bits[base[i]];
609#endif
610 (void) notify_dispatch();
611 return 0;
612}
613
614/* Copy a color bitmap. */
615int
616sun_copy_color(register gx_device *dev,
617 byte *base, int sourcex, int raster, gx_bitmap_id id,
618 int x, int y, int w, int h)
619{
620 register int i;
621 extern struct pixrectops mem_ops;
622
623 if ( !gx_device_has_color(dev) )
624 return sun_copy_mono(dev, base, sourcex, raster, id,
625 x, y, w, h,
626 (gx_color_index)0, (gx_color_index)1);
627
628 check_rect();
629
630 xdev->pr.pr_ops = &mem_ops;
631 xdev->pr.pr_width = w + sourcex + 8;
632 xdev->pr.pr_height = h;
633 xdev->pr.pr_depth = 8;
634 xdev->pr.pr_data = (caddr_t)&(xdev->mpr);
635 xdev->mpr.md_linebytes = raster;
636 xdev->mpr.md_image = (short *)((ulong)base & ~1);
637 pw_write(xdev->pw, x, y, w, h,
638 PIX_SRC, &(xdev->pr),
639 (((int)base & 1) ? sourcex + 8 : sourcex), 0);
640 (void) notify_dispatch();
641 return 0;
642}
643
644/* Draw a line */
645int
646sun_draw_line(register gx_device *dev,
647 int x0, int y0, int x1, int y1, gx_color_index color)
648{ pw_vector(xdev->pw, x0, y0, x1, y1, PIX_SRC, color);
649 (void) notify_dispatch();
650 return 0;
651}