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