1 /* Copyright (C) 1992, 1993, 1994, 1996, 1997, 1998, 1999 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: gdevvglb.c,v 1.5 2002/02/21 22:24:52 giles Exp $ */
18 /*
19 * This is a driver for 386 PCs using vgalib for graphics on the console
20 * display. Note that this driver only works with 16-color modes.
21 *
22 * Written by Sigfrid Lundberg, siglun@euler.teorekol.lu.se.
23 * Modified by Erik Talvola, talvola@gnu.ai.mit.edu
24 * Updated 9/28/96 by L. Peter Deutsch, ghost@aladdin.com: allow setting
25 * the display mode as a device parameter.
26 * Updated 2/13/97 by ghost@aladdin.com: make the device identify itself
27 * as a page device.
28 * Updated 5/2/97 by ghost@aladdin.com: copy_mono computed some parameters
29 * before doing fit_copy.
30 * Update 1997-06-28 by ghost@aladdin.com: get_bits wasn't implemented.
31 */
32
33 #include "gx.h"
34 #include "gserrors.h"
35 #include "gsparam.h"
36 #include "gxdevice.h"
37 #include "gdevpccm.h"
38
39 #include <errno.h>
40 #include <vga.h>
41
42 typedef struct gx_device_vgalib {
43 gx_device_common;
44 int display_mode;
45 } gx_device_vgalib;
46
47 #define vga_dev ((gx_device_vgalib *)dev)
48
49 #define XDPI 60 /* to get a more-or-less square aspect ratio */
50 #define YDPI 60
51
52 #ifndef A4 /*Letter size */
53 #define YSIZE (20.0 * YDPI / 2.5)
54 #define XSIZE (8.5 / 11)*YSIZE /* 8.5 x 11 inch page, by default */
55 #else /* A4 paper */
56 #define XSIZE 8.27
57 #define YSIZE 11.69
58 #endif
59
60 private dev_proc_open_device(vgalib_open);
61 private dev_proc_close_device(vgalib_close);
62 private dev_proc_map_rgb_color(vgalib_map_rgb_color);
63 private dev_proc_map_color_rgb(vgalib_map_color_rgb);
64 private dev_proc_fill_rectangle(vgalib_fill_rectangle);
65 private dev_proc_tile_rectangle(vgalib_tile_rectangle);
66 private dev_proc_copy_mono(vgalib_copy_mono);
67 private dev_proc_copy_color(vgalib_copy_color);
68 private dev_proc_get_bits(vgalib_get_bits);
69 private dev_proc_get_params(vgalib_get_params);
70 private dev_proc_put_params(vgalib_put_params);
71
72 const gx_device_vgalib gs_vgalib_device =
73 {
74 std_device_std_body(gx_device_vgalib, 0, "vgalib",
75 0, 0, 1, 1),
76 {vgalib_open,
77 NULL, /* get_initial_matrix */
78 NULL, /* sync_output */
79 NULL, /* output_page */
80 vgalib_close,
81 vgalib_map_rgb_color,
82 vgalib_map_color_rgb,
83 vgalib_fill_rectangle,
84 vgalib_tile_rectangle,
85 vgalib_copy_mono,
86 vgalib_copy_color,
87 NULL, /* draw_line (obsolete) */
88 vgalib_get_bits,
89 vgalib_get_params,
90 vgalib_put_params,
91 NULL, /* map_cmyk_color */
92 NULL, /* get_xfont_procs */
93 NULL, /* get_xfont_device */
94 NULL, /* map_rgb_alpha_color */
95 gx_page_device_get_page_device
96 },
97 -1 /* display_mode */
98 };
99
100 private int
vgalib_open(gx_device * dev)101 vgalib_open(gx_device * dev)
102 {
103 int VGAMODE = vga_dev->display_mode;
104 int width = dev->width, height = dev->height;
105
106 if (VGAMODE == -1)
107 VGAMODE = vga_getdefaultmode();
108 if (VGAMODE == -1)
109 vga_setmode(G640x480x16);
110 else
111 vga_setmode(VGAMODE);
112 vga_clear();
113 if (width == 0)
114 width = vga_getxdim() + 1;
115 if (height == 0)
116 height = vga_getydim() + 1;
117
118 /*vgalib provides no facilities for finding out aspect ratios */
119 if (dev->y_pixels_per_inch == 1) {
120 dev->y_pixels_per_inch = height / 11.0;
121 dev->x_pixels_per_inch = dev->y_pixels_per_inch;
122 }
123 gx_device_set_width_height(dev, width, height);
124
125 /* Find out if the device supports color */
126 /* (default initialization is monochrome). */
127 /* We only recognize 16-color devices right now. */
128 if (vga_getcolors() > 1) {
129 int index;
130
131 static const gx_device_color_info vgalib_16color = dci_pc_4bit;
132
133 dev->color_info = vgalib_16color;
134
135 for (index = 0; index < 16; ++index) {
136 gx_color_value rgb[3];
137
138 (*dev_proc(dev, map_color_rgb)) (dev, (gx_color_index) index, rgb);
139 #define cv2pv(cv) ((cv) >> (gx_color_value_bits - 8))
140 vga_setpalette(index, cv2pv(rgb[0]), cv2pv(rgb[1]), cv2pv(rgb[2]));
141 #undef cv2pv
142 }
143 }
144 return 0;
145 }
146
147 private int
vgalib_close(gx_device * dev)148 vgalib_close(gx_device * dev)
149 {
150 vga_setmode(TEXT);
151 return 0;
152 }
153
154 private gx_color_index
vgalib_map_rgb_color(gx_device * dev,gx_color_value red,gx_color_value green,gx_color_value blue)155 vgalib_map_rgb_color(gx_device * dev, gx_color_value red,
156 gx_color_value green, gx_color_value blue)
157 {
158 return pc_4bit_map_rgb_color(dev, red, green, blue);
159 }
160
161 private int
vgalib_map_color_rgb(gx_device * dev,gx_color_index index,unsigned short rgb[3])162 vgalib_map_color_rgb(gx_device * dev, gx_color_index index,
163 unsigned short rgb[3])
164 {
165 return pc_4bit_map_color_rgb(dev, index, rgb);
166 }
167
168 private int
vgalib_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)169 vgalib_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
170 int x, int y, int w, int h, gx_color_index czero,
171 gx_color_index cone, int px, int py)
172 {
173 if (czero != gx_no_color_index && cone != gx_no_color_index) {
174 vgalib_fill_rectangle(dev, x, y, w, h, czero);
175 czero = gx_no_color_index;
176 }
177 return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px,
178 py);
179 }
180
181 private int
vgalib_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)182 vgalib_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
183 gx_color_index color)
184 {
185 int i, j;
186
187 fit_fill(dev, x, y, w, h);
188 vga_setcolor((int)color);
189 if ((w | h) > 3) { /* Draw larger rectangles as lines. */
190 if (w > h)
191 for (i = y; i < y + h; ++i)
192 vga_drawline(x, i, x + w - 1, i);
193 else
194 for (j = x; j < x + w; ++j)
195 vga_drawline(j, y, j, y + h - 1);
196 } else { /* Draw small rectangles point-by-point. */
197 for (i = y; i < y + h; i++)
198 for (j = x; j < x + w; j++)
199 vga_drawpixel(j, i);
200 }
201 return 0;
202 }
203
204 private int
vgalib_copy_mono(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index zero,gx_color_index one)205 vgalib_copy_mono(gx_device * dev, const byte * base, int sourcex,
206 int raster, gx_bitmap_id id, int x, int y, int width,
207 int height, gx_color_index zero, gx_color_index one)
208 {
209 const byte *ptr_line;
210 int left_bit, dest_y, end_x;
211 int invert = 0;
212 int color;
213
214 fit_copy(dev, base, sourcex, raster, id, x, y, width, height);
215 ptr_line = base + (sourcex >> 3);
216 left_bit = 0x80 >> (sourcex & 7);
217 dest_y = y, end_x = x + width;
218
219 if (zero == gx_no_color_index) {
220 if (one == gx_no_color_index)
221 return 0;
222 color = (int)one;
223 } else {
224 if (one == gx_no_color_index) {
225 color = (int)zero;
226 invert = -1;
227 } else { /* Pre-clear the rectangle to zero */
228 vgalib_fill_rectangle(dev, x, y, width, height, zero);
229 color = (int)one;
230 }
231 }
232
233 vga_setcolor(color);
234 while (height--) { /* for each line */
235 const byte *ptr_source = ptr_line;
236 register int dest_x = x;
237 register int bit = left_bit;
238
239 while (dest_x < end_x) { /* for each bit in the line */
240 if ((*ptr_source ^ invert) & bit)
241 vga_drawpixel(dest_x, dest_y);
242 dest_x++;
243 if ((bit >>= 1) == 0)
244 bit = 0x80, ptr_source++;
245 }
246
247 dest_y++;
248 ptr_line += raster;
249 }
250 return 0;
251 }
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 private int
vgalib_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int width,int height)257 vgalib_copy_color(gx_device * dev, const byte * base, int sourcex,
258 int raster, gx_bitmap_id id, int x, int y,
259 int width, int height)
260 {
261
262 fit_copy(dev, base, sourcex, raster, id, x, y, width, height);
263
264 if (gx_device_has_color(dev)) { /* color device, four bits per pixel */
265 const byte *line = base + (sourcex >> 1);
266 int dest_y = y, end_x = x + width;
267
268 if (width <= 0)
269 return 0;
270 while (height--) { /* for each line */
271 const byte *source = line;
272 register int dest_x = x;
273
274 if (sourcex & 1) { /* odd nibble first */
275 int color = *source++ & 0xf;
276
277 vga_setcolor(color);
278 vga_drawpixel(dest_x, dest_y);
279 dest_x++;
280 }
281 /* Now do full bytes */
282 while (dest_x < end_x) {
283 int color = *source >> 4;
284
285 vga_setcolor(color);
286 vga_drawpixel(dest_x, dest_y);
287 dest_x++;
288
289 if (dest_x < end_x) {
290 color = *source++ & 0xf;
291 vga_setcolor(color);
292 vga_drawpixel(dest_x, dest_y);
293 dest_x++;
294 }
295 }
296
297 dest_y++;
298 line += raster;
299 }
300 } else { /* monochrome device: one bit per pixel */
301 /* bitmap is the same as bgi_copy_mono: one bit per pixel */
302 vgalib_copy_mono(dev, base, sourcex, raster, id, x, y, width, height,
303 (gx_color_index) 0, (gx_color_index) 7);
304 }
305
306 return 0;
307 }
308
309 /* Read bits back from the device. */
310 private int
vgalib_get_bits(gx_device * dev,int y,byte * data,byte ** actual_data)311 vgalib_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
312 {
313 int x;
314 byte *dest = data;
315 int b = 0;
316 int depth = dev->color_info.depth; /* 1 or 4 */
317 int mask = (1 << depth) - 1;
318 int left = 8;
319
320 if (actual_data)
321 *actual_data = data;
322 for (x = 0; x < dev->width; ++x) {
323 int color = vga_getpixel(x, y);
324
325 if ((left -= depth) < 0)
326 *dest++ = b, b = 0, left += 8;
327 b += (color & mask) << left;
328 }
329 if (left < 8)
330 *dest = b;
331 return 0;
332 }
333
334 /* Get/put the display mode parameter. */
335 private int
vgalib_get_params(gx_device * dev,gs_param_list * plist)336 vgalib_get_params(gx_device * dev, gs_param_list * plist)
337 {
338 int code = gx_default_get_params(dev, plist);
339
340 if (code < 0)
341 return code;
342 return param_write_int(plist, "DisplayMode", &vga_dev->display_mode);
343 }
344 private int
vgalib_put_params(gx_device * dev,gs_param_list * plist)345 vgalib_put_params(gx_device * dev, gs_param_list * plist)
346 {
347 int ecode = 0;
348 int code;
349 int imode = vga_dev->display_mode;
350 const char *param_name;
351
352 switch (code = param_read_int(plist, (param_name = "DisplayMode"), &imode)) {
353 default:
354 ecode = code;
355 param_signal_error(plist, param_name, ecode);
356 case 0:
357 case 1:
358 break;
359 }
360
361 if (ecode < 0)
362 return ecode;
363 code = gx_default_put_params(dev, plist);
364 if (code < 0)
365 return code;
366
367 if (imode != vga_dev->display_mode) {
368 if (dev->is_open)
369 gs_closedevice(dev);
370 vga_dev->display_mode = imode;
371 }
372 return 0;
373 }
374