Commit | Line | Data |
---|---|---|
e2471650 WJ |
1 | /* Copyright (C) 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 | /* gdevpjet.c */ | |
21 | /* H-P PaintJet driver for Ghostscript */ | |
22 | #include "gdevprn.h" | |
23 | #include "gdevpcl.h" | |
24 | ||
25 | /* X_DPI and Y_DPI must be the same, and may be either 90 or 180. */ | |
26 | #define X_DPI 180 | |
27 | #define Y_DPI 180 | |
28 | ||
29 | /* We round up LINE_SIZE to a multiple of 8 bytes */ | |
30 | /* because that's the unit of transposition from pixels to planes. */ | |
31 | #define LINE_SIZE ((X_DPI * 85 / 10 + 63) / 64 * 8) | |
32 | ||
33 | /* The device descriptor */ | |
34 | private dev_proc_print_page(paintjet_print_page); | |
35 | private gx_device_procs paintjet_procs = | |
36 | prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close, | |
37 | gdev_pcl_3bit_map_rgb_color, gdev_pcl_3bit_map_color_rgb); | |
38 | gx_device_printer gs_paintjet_device = | |
39 | prn_device(paintjet_procs, "paintjet", | |
40 | 85, /* width_10ths, 8.5" */ | |
41 | 110, /* height_10ths, 11" */ | |
42 | X_DPI, Y_DPI, | |
43 | 0.25, 0, 0.25, 0, /* margins */ | |
44 | 3, paintjet_print_page); | |
45 | ||
46 | /* Forward references */ | |
47 | private int compress1_row(P3(byte _ss *, byte _ss *, byte _ss *)); | |
48 | ||
49 | /* ------ Internal routines ------ */ | |
50 | ||
51 | /* Send the page to the printer. Compress each scan line. */ | |
52 | private int | |
53 | paintjet_print_page(gx_device_printer *pdev, FILE *prn_stream) | |
54 | { | |
55 | #define DATA_SIZE (LINE_SIZE * 8) | |
56 | byte data[DATA_SIZE]; | |
57 | byte plane_data[LINE_SIZE * 3]; | |
58 | ||
59 | /* ends raster graphics to set raster graphics resolution */ | |
60 | fputs("\033*rB", prn_stream); | |
61 | ||
62 | /* set raster graphics resolution -- 90 or 180 dpi */ | |
63 | fprintf(prn_stream, "\033*t%dR", X_DPI); | |
64 | ||
65 | /* set the line width */ | |
66 | fprintf(prn_stream, "\033*r%dS", DATA_SIZE); | |
67 | ||
68 | /* set the number of color planes */ | |
69 | fprintf(prn_stream, "\033*r%dU", 3); /* always 3 */ | |
70 | ||
71 | /* move to top left of page */ | |
72 | fputs("\033&a0H\033&a0V", prn_stream); | |
73 | ||
74 | /* select data compression */ | |
75 | fputs("\033*b1M", prn_stream); | |
76 | ||
77 | /* start raster graphics */ | |
78 | fputs("\033*r1A", prn_stream); | |
79 | ||
80 | /* Send each scan line in turn */ | |
81 | { int lnum; | |
82 | int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev); | |
83 | int num_blank_lines = 0; | |
84 | for ( lnum = 0; lnum < pdev->height; lnum++ ) | |
85 | { byte _ss *end_data = data + line_size; | |
86 | gdev_prn_copy_scan_lines(pdev, lnum, | |
87 | (byte *)data, line_size); | |
88 | /* Remove trailing 0s. */ | |
89 | while ( end_data > data && end_data[-1] == 0 ) | |
90 | end_data--; | |
91 | if ( end_data == data ) | |
92 | { /* Blank line */ | |
93 | num_blank_lines++; | |
94 | } | |
95 | else | |
96 | { int i; | |
97 | byte _ss *odp; | |
98 | byte _ss *row; | |
99 | ||
100 | /* Pad with 0s to fill out the last */ | |
101 | /* block of 8 bytes. */ | |
102 | memset(end_data, 0, 7); | |
103 | ||
104 | /* Transpose the data to get pixel planes. */ | |
105 | for ( i = 0, odp = plane_data; i < DATA_SIZE; | |
106 | i += 8, odp++ | |
107 | ) | |
108 | { /* The following is for 16-bit machines */ | |
109 | #define spread3(c)\ | |
110 | { 0, c, c*0x100, c*0x101, c*0x10000L, c*0x10001L, c*0x10100L, c*0x10101L } | |
111 | static ulong spr40[8] = spread3(0x40); | |
112 | static ulong spr8[8] = spread3(8); | |
113 | static ulong spr2[8] = spread3(2); | |
114 | register byte _ss *dp = data + i; | |
115 | register ulong pword = | |
116 | (spr40[dp[0]] << 1) + | |
117 | (spr40[dp[1]]) + | |
118 | (spr40[dp[2]] >> 1) + | |
119 | (spr8[dp[3]] << 1) + | |
120 | (spr8[dp[4]]) + | |
121 | (spr8[dp[5]] >> 1) + | |
122 | (spr2[dp[6]]) + | |
123 | (spr2[dp[7]] >> 1); | |
124 | odp[0] = (byte)(pword >> 16); | |
125 | odp[LINE_SIZE] = (byte)(pword >> 8); | |
126 | odp[LINE_SIZE*2] = (byte)(pword); | |
127 | } | |
128 | /* Skip blank lines if any */ | |
129 | if ( num_blank_lines > 0 ) | |
130 | { /* move down from current position */ | |
131 | fprintf(prn_stream, "\033&a+%dV", | |
132 | num_blank_lines * (720 / Y_DPI)); | |
133 | num_blank_lines = 0; | |
134 | } | |
135 | ||
136 | /* Transfer raster graphics */ | |
137 | /* in the order R, G, B. */ | |
138 | for ( row = plane_data + LINE_SIZE * 2, i = 0; | |
139 | i < 3; row -= LINE_SIZE, i++ | |
140 | ) | |
141 | { byte temp[LINE_SIZE * 2]; | |
142 | int count = compress1_row(row, row + LINE_SIZE, temp); | |
143 | fprintf(prn_stream, "\033*b%d%c", | |
144 | count, "VVW"[i]); | |
145 | fwrite(temp, sizeof(byte), | |
146 | count, prn_stream); | |
147 | } | |
148 | } | |
149 | } | |
150 | } | |
151 | ||
152 | /* end raster graphics */ | |
153 | fputs("\033*r0B", prn_stream); | |
154 | ||
155 | /* eject page */ | |
156 | fputs("\014", prn_stream); | |
157 | ||
158 | return 0; | |
159 | } | |
160 | ||
161 | /* | |
162 | * Row compression for the H-P PaintJet. | |
163 | * Compresses data from row up to end_row, storing the result | |
164 | * starting at compressed. Returns the number of bytes stored. | |
165 | * The compressed format consists of a byte N followed by a | |
166 | * data byte that is to be repeated N+1 times. | |
167 | * In the worst case, the `compressed' representation is | |
168 | * twice as large as the input. | |
169 | * We complement the bytes at the same time, because | |
170 | * we accumulated the image in complemented form. | |
171 | */ | |
172 | private int | |
173 | compress1_row(byte _ss *row, byte _ss *end_row, byte _ss *compressed) | |
174 | { register byte _ss *in = row; | |
175 | register byte _ss *out = compressed; | |
176 | while ( in < end_row ) | |
177 | { byte test = *in++; | |
178 | byte _ss *run = in; | |
179 | while ( in < end_row && *in == test ) in++; | |
180 | /* Note that in - run + 1 is the repetition count. */ | |
181 | while ( in - run > 255 ) | |
182 | { *out++ = 255; | |
183 | *out++ = ~test; | |
184 | run += 256; | |
185 | } | |
186 | *out++ = in - run; | |
187 | *out++ = ~test; | |
188 | } | |
189 | return out - compressed; | |
190 | } |