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