Commit | Line | Data |
---|---|---|
fade9343 WJ |
1 | /* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
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 */ | |
38 | dev_proc_open_device(sun_open); | |
39 | dev_proc_sync_output(sun_sync); | |
40 | dev_proc_close_device(sun_close); | |
41 | dev_proc_map_rgb_color(sun_map_rgb_color); | |
42 | dev_proc_map_color_rgb(sun_map_color_rgb); | |
43 | dev_proc_fill_rectangle(sun_fill_rectangle); | |
44 | dev_proc_copy_mono(sun_copy_mono); | |
45 | dev_proc_copy_color(sun_copy_color); | |
46 | dev_proc_draw_line(sun_draw_line); | |
47 | ||
48 | /* The device descriptor */ | |
49 | private 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 */ | |
70 | typedef 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. */ | |
89 | static 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. */ | |
110 | gx_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) | |
186 | Display_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. */ | |
224 | private Notify_value destroy_func(); | |
225 | int | |
226 | sun_open(register gx_device *dev) | |
227 | { | |
228 | #ifdef gs_DEBUG | |
229 | if ( 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. */ | |
401 | private Notify_value | |
402 | destroy_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. */ | |
411 | int | |
412 | sun_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 */ | |
428 | int | |
429 | sun_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 | */ | |
438 | gx_color_index | |
439 | sun_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 */ | |
514 | int | |
515 | sun_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. */ | |
552 | int | |
553 | sun_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. */ | |
564 | int | |
565 | sun_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. */ | |
615 | int | |
616 | sun_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 */ | |
645 | int | |
646 | sun_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 | } |