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