1 /* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevl256.c,v 1.5 2002/02/21 22:24:51 giles Exp $ */
18 /* Ghostscript driver for 256-color VGA modes with Linux and vgalib */
19 /* This Driver was derived from the BGI-Driver. It was written
20 only for my own purpose. I never planned to release it or send
21 it to others. So, if something doesn't work, you may send
22 me a short note, but don't expect me to correct it. I will
23 try my very best, but i have some work to do.
24
25 Ludger Kunz | ____________|Tel.: 02371/566-230
26 FernUniversitaet Hagen| /| / / \ |FAX: 02371/52212
27 Lehrgebiet ES | / |/ /_ \ |EMAIL:
28 Frauenstuhlweg 31 | / |\ / \ |ludger.kunz@fernuni-hagen.de
29 58644 Iserlohn |/___|_\/_______\|
30 */
31 #include "memory_.h"
32 #include "gx.h"
33 #include "gxdevice.h"
34 #include "gserrors.h"
35
36 #include <errno.h>
37 #include <vga.h>
38 #include <vgagl.h>
39
40 /* The color map for dynamically assignable colors. */
41 #define first_dc_index 64
42 private int next_dc_index;
43
44 #define dc_hash_size 293 /* prime, >num_dc */
45 typedef struct {
46 ushort rgb, index;
47 } dc_entry;
48 private dc_entry dynamic_colors[dc_hash_size + 1];
49
50 #define XDPI 60 /* to get a more-or-less square aspect ratio */
51 #define YDPI 60
52
53 #ifndef A4 /*Letter size */
54 #define YSIZE (20.0 * YDPI / 2.5)
55 #define XSIZE (8.5 / 11)*YSIZE /* 8.5 x 11 inch page, by default */
56 #else /* A4 paper */
57 #define XSIZE 8.3 /*8.27 */
58 #define YSIZE 11.7 /*11.69 */
59 #endif
60
61
62 /* The device descriptor */
63 typedef struct gx_device_lvga256 {
64 gx_device_common;
65 } gx_device_lvga256;
66
67 #define lvga256dev ((gx_device_lvga256 *)dev)
68
69 private dev_proc_open_device(lvga256_open);
70 private dev_proc_close_device(lvga256_close);
71 private dev_proc_map_rgb_color(lvga256_map_rgb_color);
72 private dev_proc_map_color_rgb(lvga256_map_color_rgb);
73 private dev_proc_fill_rectangle(lvga256_fill_rectangle);
74 private dev_proc_tile_rectangle(lvga256_tile_rectangle);
75 private dev_proc_copy_mono(lvga256_copy_mono);
76 private dev_proc_copy_color(lvga256_copy_color);
77 private dev_proc_draw_line(lvga256_draw_line);
78
79 private gx_device_procs lvga256_procs =
80 {
81 lvga256_open,
82 NULL, /* get_initial_matrix */
83 NULL, /* sync_output */
84 NULL, /* output_page */
85 lvga256_close,
86 lvga256_map_rgb_color,
87 lvga256_map_color_rgb,
88 lvga256_fill_rectangle,
89 lvga256_tile_rectangle,
90 lvga256_copy_mono,
91 lvga256_copy_color,
92 lvga256_draw_line
93 };
94
95 gx_device_lvga256 far_data gs_lvga256_device =
96 {std_device_color_body(gx_device_lvga256, &lvga256_procs, "lvga256",
97 0, 0, /* width and height are set in lvga256_open */
98 1, 1, /* density is set in lvga256_open */
99 /*dci_color( */ 8, 31, 4 /*) */ )
100 };
101
102 /* Open the LINUX driver for graphics mode */
103 int
lvga256_open(gx_device * dev)104 lvga256_open(gx_device * dev)
105 {
106 int vgamode;
107 int width, height;
108
109 vga_init();
110 vgamode = vga_getdefaultmode();
111 if (vgamode == -1)
112 vgamode = G320x200x256;
113 vga_setmode(vgamode);
114 gl_setcontextvga(vgamode);
115 width = vga_getxdim();
116 height = vga_getydim();
117 dev->y_pixels_per_inch = height / 12.0;
118 dev->x_pixels_per_inch = dev->y_pixels_per_inch;
119 gx_device_set_width_height(dev, width, height);
120 {
121 int c;
122
123 for (c = 0; c < 64; c++) {
124 static const byte c2[10] =
125 {0, 42, 0, 0, 0, 0, 0, 0, 21, 63};
126
127 gl_setpalettecolor(c, c2[(c >> 2) & 9], c2[(c >> 1) & 9], c2[c & 9]);
128 }
129 }
130 /* Initialize the dynamic color table. */
131 memset(dynamic_colors, 0, (dc_hash_size + 1) * sizeof(dc_entry));
132 next_dc_index = first_dc_index;
133
134 return 0;
135 }
136
137 /* Close the LINUX driver */
138 int
lvga256_close(gx_device * dev)139 lvga256_close(gx_device * dev)
140 {
141 vga_setmode(TEXT);
142 return 0;
143 }
144
145 /* Map a r-g-b color to a palette index. */
146 /* The first 64 entries of the color map are set */
147 /* for compatibility with the older display modes: */
148 /* these are indexed as 0.0.R0.G0.B0.R1.G1.B1. */
149 gx_color_index
lvga256_map_rgb_color(gx_device * dev,gx_color_value r,gx_color_value g,gx_color_value b)150 lvga256_map_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
151 gx_color_value b)
152 {
153 #define cv_bits(v,n) (v >> (gx_color_value_bits - n))
154 ushort r5 = cv_bits(r, 5), g5 = cv_bits(g, 5), b5 = cv_bits(b, 5);
155 static const byte cube_bits[32] =
156 {0, 128, 128, 128, 128, 128, 128, 128, 128, 128,
157 8, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
158 1, 128, 128, 128, 128, 128, 128, 128, 128, 128,
159 9
160 };
161 uint cx = ((uint) cube_bits[r5] << 2) + ((uint) cube_bits[g5] << 1) +
162 (uint) cube_bits[b5];
163 ushort rgb;
164 register dc_entry *pdc;
165
166 /* Check for a color on the cube. */
167 if (cx < 64)
168 return (gx_color_index) cx;
169 /* Not on the cube, check the dynamic color table. */
170 rgb = (r5 << 10) + (g5 << 5) + b5;
171 for (pdc = &dynamic_colors[rgb % dc_hash_size]; pdc->rgb != 0; pdc++) {
172 if (pdc->rgb == rgb)
173 return (gx_color_index) (pdc->index);
174 }
175 if (pdc == &dynamic_colors[dc_hash_size]) { /* Wraparound */
176 for (pdc = &dynamic_colors[0]; pdc->rgb != 0; pdc++) {
177 if (pdc->rgb == rgb)
178 return (gx_color_index) (pdc->index);
179 }
180 }
181 if (next_dc_index == 256) { /* No space left, report failure. */
182 return gx_no_color_index;
183 }
184 /* Not on the cube, and not in the dynamic table. */
185 /* Put in the dynamic table if space available. */
186 {
187 int i = next_dc_index++;
188
189 pdc->rgb = rgb;
190 pdc->index = i;
191 gl_setpalettecolor(i, cv_bits(r, 6), cv_bits(g, 6), cv_bits(b, 6));
192 return (gx_color_index) i;
193 }
194 }
195
196 int
lvga256_map_color_rgb(gx_device * dev,gx_color_index color,unsigned short prgb[3])197 lvga256_map_color_rgb(gx_device * dev, gx_color_index color,
198 unsigned short prgb[3])
199 {
200 /* gl_getpalettecolor (color,(int *)&prgb[0],(int *)&prgb[1],(int *)&prgb[2]); */
201 prgb[0] = gx_max_color_value;
202 prgb[1] = gx_max_color_value;
203 prgb[2] = gx_max_color_value;
204 return 0;
205 }
206
207 /* Copy a monochrome bitmap. The colors are given explicitly. */
208 /* Color = gx_no_color_index means transparent (no effect on the image). */
209 int
lvga256_copy_mono(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)210 lvga256_copy_mono(gx_device * dev,
211 const byte * base, int sourcex, int raster, gx_bitmap_id id,
212 int x, int y, int w, int h,
213 gx_color_index zero, gx_color_index one)
214 {
215 const byte *ptr_line = base + (sourcex >> 3);
216 int left_bit = 0x80 >> (sourcex & 7);
217 int dest_y = y, end_x = x + w;
218 int invert = 0;
219 int color;
220
221 fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
222 if (zero == gx_no_color_index) {
223 if (one == gx_no_color_index)
224 return 0;
225 color = (int)one;
226 } else {
227 if (one == gx_no_color_index) {
228 color = (int)zero;
229 invert = -1;
230 } else { /* Pre-clear the rectangle to zero */
231 gl_fillbox(x, y, w, h, 0);
232 color = (int)one;
233 }
234 }
235 while (h--) { /* for each line */
236 const byte *ptr_source = ptr_line;
237 register int dest_x = x;
238 register int bit = left_bit;
239
240 while (dest_x < end_x) { /* for each bit in the line */
241 if ((*ptr_source ^ invert) & bit) {
242 gl_setpixel(dest_x, dest_y, color);
243 }
244 dest_x++;
245 if ((bit >>= 1) == 0)
246 bit = 0x80, ptr_source++;
247 }
248 dest_y++;
249 ptr_line += raster;
250 }
251 return 0;
252 }
253
254 /* Copy a color pixel map. This is just like a bitmap, except that */
255 /* each pixel takes 4 bits instead of 1 when device driver has color. */
256 int
lvga256_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)257 lvga256_copy_color(gx_device * dev,
258 const byte * base, int sourcex, int raster, gx_bitmap_id id,
259 int x, int y, int w, int h)
260 {
261 fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
262 if (gx_device_has_color(dev)) { /* color device, four bits per pixel */
263 const byte *line = base + sourcex;
264
265 gl_putbox(x, y, w, h, line);
266 } else { /* monochrome device: one bit per pixel */
267 /* bit map is the same as lvga256_copy_mono: one bit per pixel */
268 lvga256_copy_mono(dev, base, sourcex, raster, id, x, y, w, h,
269 (gx_color_index) 0, (gx_color_index) 255);
270 }
271 return 0;
272 }
273
274 /* Fill a rectangle. */
275 int
lvga256_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)276 lvga256_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
277 gx_color_index color)
278 {
279 fit_fill(dev, x, y, w, h);
280 gl_fillbox(x, y, w, h, color);
281 return 0;
282 }
283
284 /* Tile a rectangle. If neither color is transparent, */
285 /* pre-clear the rectangle to color0 and just tile with color1. */
286 /* This is faster because of how lvga256_copy_mono is implemented. */
287 /* Note that this also does the right thing for colored tiles. */
288 int
lvga256_tile_rectangle(gx_device * dev,const gx_tile_bitmap * tile,int x,int y,int w,int h,gx_color_index czero,gx_color_index cone,int px,int py)289 lvga256_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
290 int x, int y, int w, int h, gx_color_index czero, gx_color_index cone,
291 int px, int py)
292 {
293 if (czero != gx_no_color_index && cone != gx_no_color_index) {
294 lvga256_fill_rectangle(dev, x, y, w, h, czero);
295 czero = gx_no_color_index;
296 }
297 return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py);
298 }
299
300 /* Draw a line */
301 int
lvga256_draw_line(gx_device * dev,int x0,int y0,int x1,int y1,gx_color_index color)302 lvga256_draw_line(gx_device * dev, int x0, int y0, int x1, int y1,
303 gx_color_index color)
304 {
305 gl_line(x0, y0, x1, y1, color);
306 return 0;
307 }
308