Commit | Line | Data |
---|---|---|
ab694b5c WJ |
1 | /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
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 | ||
26 | char *getenv(char *name); | |
27 | ||
28 | typedef 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 | ||
35 | typedef 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 | ||
47 | dev_proc_open_device(pe_open); | |
48 | dev_proc_close_device(pe_close); | |
49 | dev_proc_fill_rectangle(pe_fill_rectangle); | |
50 | dev_proc_copy_mono(pe_copy_mono); | |
51 | ||
52 | static 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 | ||
70 | gx_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 | ||
82 | static 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 | ||
88 | static 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 | ||
97 | int 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 | ||
126 | int 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 | ||
140 | int 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 | ||
227 | int 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 | ||
242 | if ( 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 | } |