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