386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / gdevpe.c
CommitLineData
ab694b5c
WJ
1/* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* gdevpe.c Private Eye display driver for Ghostscript
21 Hacked by Fran Taylor, Reflection Technology Inc. */
22
23#include "gx.h"
24#include "gxdevice.h"
25
26char *getenv(char *name);
27
28typedef struct gx_device_pe_s {
29 gx_device_common;
30 byte *fbaddr;
31 unsigned regs;
32} gx_device_pe;
33#define pedev ((gx_device_pe *)dev)
34
35typedef struct {
36 ushort reg, val;
37} regval;
38
39#define XSIZE 720
40#define YSIZE 280
41#define BPL 90
42#define XPPI 160.0
43#define YPPI 96.0
44#define DEFAULT_ADDRESS ((byte *) 0xb8000000)
45#define DEFAULT_REGISTERS 0x3d0
46
47dev_proc_open_device(pe_open);
48dev_proc_close_device(pe_close);
49dev_proc_fill_rectangle(pe_fill_rectangle);
50dev_proc_copy_mono(pe_copy_mono);
51
52static gx_device_procs pe_procs =
53{ pe_open,
54 gx_default_get_initial_matrix,
55 gx_default_sync_output,
56 gx_default_output_page,
57 pe_close,
58 gx_default_map_rgb_color,
59 gx_default_map_color_rgb,
60 pe_fill_rectangle,
61 gx_default_tile_rectangle,
62 pe_copy_mono,
63 gx_default_copy_color,
64 gx_default_draw_line,
65 gx_default_get_bits,
66 gx_default_get_props,
67 gx_default_put_props
68};
69
70gx_device_pe gs_pe_device =
71{ sizeof(gx_device_pe),
72 &pe_procs,
73 "Private Eye",
74 XSIZE, YSIZE,
75 XPPI, YPPI,
76 no_margins,
77 dci_black_and_white,
78 0,
79 DEFAULT_ADDRESS, DEFAULT_REGISTERS
80};
81
82static regval peinit[] = {{0x04, 0x1e}, {0x05, 0x00},
83 {0x04, 0x0c}, {0x05, 0x21},
84 {0x04, 0x0d}, {0x05, 0x98},
85 {0x08, 0x00}, {0x08, 0x1e},
86 {0x04, 0x1e}, {0x05, 0x01}};
87
88static regval pedone[] = {{0x04, 0x1e}, {0x05, 0x10},
89 {0x04, 0x0a}, {0x05, 0x00},
90 {0x04, 0x0b}, {0x05, 0x07},
91 {0x04, 0x0c}, {0x05, 0x00},
92 {0x04, 0x0d}, {0x05, 0x00},
93 {0x04, 0x0e}, {0x05, 0x00},
94 {0x04, 0x0f}, {0x05, 0x00},
95 {0x08, 0x00}, {0x08, 0x29}};
96
97int pe_open(gx_device *dev)
98{
99 char *str;
100 int i;
101
102 if ((str = getenv("PEFBADDR")) != 0)
103 {
104 if (!sscanf(str, "%lx", &(pedev->fbaddr)))
105 {
106 eprintf("Private Eye: PEFBADDR environment string format error\n");
107 exit(1);
108 }
109 }
110
111 if ((str = getenv("PEREGS")) != 0)
112 {
113 if (!sscanf(str, "%x", &(pedev->regs)))
114 {
115 eprintf("Private Eye: PEREGS environment string format error\n");
116 exit(1);
117 }
118 }
119
120 for (i = 0; i < 10; i++)
121 outportb(pedev->regs + peinit[i].reg, peinit[i].val);
122
123 return 0;
124}
125
126int pe_close(gx_device *dev)
127{
128 int i;
129
130 /* restore the screen */
131 for (i = 0; i < 16; i++)
132 outportb(pedev->regs + pedone[i].reg, pedone[i].val);
133
134 /* clear the frame buffer */
135 memset(pedev->fbaddr, 0, 4000);
136
137 return 0;
138}
139
140int pe_fill_rectangle(gx_device *dev, int x1, int y1, int w, int h,
141 gx_color_index color)
142{
143 int x2, y2, xlen;
144 byte led, red, d;
145 byte *ptr;
146
147 /* cull */
148
149 if ((w <= 0) || (h <= 0) || (x1 > XSIZE) || (y1 > YSIZE))
150 return 0;
151
152 x2 = x1 + w - 1;
153 y2 = y1 + h - 1;
154
155 /* cull some more */
156
157 if ((x2 < 0) || (y2 < 0))
158 return 0;
159
160 /* clip */
161
162 if (x1 < 0) x1 = 0;
163 if (x2 > XSIZE-1) x2 = XSIZE-1;
164 if (y1 < 0) y1 = 0;
165 if (y2 > YSIZE-1) y2 = YSIZE-1;
166
167 w = x2 - x1 + 1;
168 h = y2 - y1 + 1;
169 xlen = (x2 >> 3) - (x1 >> 3) - 1;
170 led = 0xff >> (x1 & 7);
171 red = 0xff << (7 - (x2 & 7));
172
173 ptr = pedev->fbaddr + (y1 * BPL) + (x1 >> 3);
174
175 if (color)
176 {
177 /* here to set pixels */
178
179 if (xlen == -1)
180 {
181 /* special for rectangles that fit in a byte */
182
183 d = led & red;
184 for(; h >= 0; h--, ptr += BPL)
185 *ptr |= d;
186 return 0;
187 }
188
189 /* normal fill */
190
191 for(; h >= 0; h--, ptr += BPL)
192 { register int x = xlen;
193 register byte *p = ptr;
194 *p++ |= led;
195 while ( x-- ) *p++ = 0xff;
196 *p |= red;
197 }
198 }
199
200 /* here to clear pixels */
201
202 led = ~led;
203 red = ~red;
204
205 if (xlen == -1)
206 {
207 /* special for rectangles that fit in a byte */
208
209 d = led | red;
210 for(; h >= 0; h--, ptr += BPL)
211 *ptr &= d;
212 return 0;
213 }
214
215 /* normal fill */
216
217 for(; h >= 0; h--, ptr += BPL)
218 { register int x = xlen;
219 register byte *p = ptr;
220 *p++ &= led;
221 while ( x-- ) *p++ = 0x00;
222 *p &= red;
223 }
224 return 0;
225}
226
227int pe_copy_mono(gx_device *dev,
228 byte *base, int sourcex, int raster, gx_bitmap_id id,
229 int x, int y, int w, int h,
230 gx_color_index zero, gx_color_index one)
231{
232 byte *line;
233 int sleft, dleft;
234 int mask, rmask;
235 int invert, zmask, omask;
236 byte *dest;
237 int offset;
238
239#define izero (int)zero
240#define ione (int)one
241
242if ( ione == izero ) /* vacuous case */
243 return pe_fill_rectangle(dev, x, y, w, h, zero);
244
245 /* clip */
246
247 if ((x > XSIZE) || (y > YSIZE) || ((x + w) < 0) || ((y + h) < 0))
248 return 0;
249
250 offset = x >> 3;
251 dest = pedev->fbaddr + (y * BPL) + offset;
252 line = base + (sourcex >> 3);
253 sleft = 8 - (sourcex & 7);
254 dleft = 8 - (x & 7);
255 mask = 0xff >> (8 - dleft);
256 if ( w < dleft )
257 mask -= mask >> w;
258 else
259 rmask = 0xff00 >> ((w - dleft) & 7);
260
261 /* Macros for writing partial bytes. */
262 /* bits has already been inverted by xor'ing with invert. */
263
264#define write_byte_masked(ptr, bits, mask)\
265 *ptr = ((bits | ~mask | zmask) & *ptr | (bits & mask & omask))
266
267#define write_byte(ptr, bits)\
268 *ptr = ((bits | zmask) & *ptr | (bits & omask))
269
270/* if ( dev->invert )
271 {
272 if ( izero != (int)gx_no_color_index ) zero ^= 1;
273 if ( ione != (int)gx_no_color_index ) one ^= 1;
274 } */
275 invert = (izero == 1 || ione == 0 ? -1 : 0);
276 zmask = (izero == 0 || ione == 0 ? 0 : -1);
277 omask = (izero == 1 || ione == 1 ? -1 : 0);
278
279#undef izero
280#undef ione
281
282 if (sleft == dleft) /* optimize the aligned case */
283 {
284 w -= dleft;
285 while ( --h >= 0 )
286 {
287 register byte *bptr = line;
288 int count = w;
289 register byte *optr = dest;
290 register int bits = *bptr ^ invert; /* first partial byte */
291
292 write_byte_masked(optr, bits, mask);
293
294 /* Do full bytes. */
295
296 while ((count -= 8) >= 0)
297 {
298 bits = *++bptr ^ invert;
299 ++optr;
300 write_byte(optr, bits);
301 }
302
303 /* Do last byte */
304
305 if (count > -8)
306 {
307 bits = *++bptr ^ invert;
308 ++optr;
309 write_byte_masked(optr, bits, rmask);
310 }
311 dest += BPL;
312 line += raster;
313 }
314 }
315 else
316 {
317 int skew = (sleft - dleft) & 7;
318 int cskew = 8 - skew;
319
320 while (--h >= 0)
321 {
322 byte *bptr = line;
323 int count = w;
324 byte *optr = dest;
325 register int bits;
326
327 /* Do the first partial byte */
328
329 if (sleft >= dleft)
330 {
331 bits = *bptr >> skew;
332 }
333 else /* ( sleft < dleft ) */
334 {
335 bits = *bptr++ << cskew;
336 if (count > sleft)
337 bits += *bptr >> skew;
338 }
339 bits ^= invert;
340 write_byte_masked(optr, bits, mask);
341 count -= dleft;
342 optr++;
343
344 /* Do full bytes. */
345
346 while ( count >= 8 )
347 {
348 bits = *bptr++ << cskew;
349 bits += *bptr >> skew;
350 bits ^= invert;
351 write_byte(optr, bits);
352 count -= 8;
353 optr++;
354 }
355
356 /* Do last byte */
357
358 if (count > 0)
359 {
360 bits = *bptr++ << cskew;
361 if (count > skew)
362 bits += *bptr >> skew;
363 bits ^= invert;
364 write_byte_masked(optr, bits, rmask);
365 }
366 dest += BPL;
367 line += raster;
368 }
369 }
370 return 0;
371}