1 /* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevpxut.c,v 1.8 2005/07/11 22:08:30 stefan Exp $ */
18 /* Utilities for PCL XL generation */
19 #include "math_.h"
20 #include "string_.h"
21 #include "gx.h"
22 #include "stream.h"
23 #include "gxdevcli.h"
24 #include "gdevpxat.h"
25 #include "gdevpxen.h"
26 #include "gdevpxop.h"
27 #include "gdevpxut.h"
28 #include <assert.h>
29
30 /* ---------------- High-level constructs ---------------- */
31
32 /* Write the file header, including the resolution. */
33 int
px_write_file_header(stream * s,const gx_device * dev)34 px_write_file_header(stream *s, const gx_device *dev)
35 {
36 static const char *const enter_pjl_header =
37 "\033%-12345X@PJL SET RENDERMODE=";
38 static const char *const rendermode_gray = "GRAYSCALE";
39 static const char *const rendermode_color = "COLOR";
40 static const char *const file_header =
41 "\n@PJL ENTER LANGUAGE = PCLXL\n\
42 ) HP-PCL XL;1;1;Comment Copyright artofcode LLC 2005\000\n";
43 static const byte stream_header[] = {
44 DA(pxaUnitsPerMeasure),
45 DUB(0), DA(pxaMeasure),
46 DUB(eBackChAndErrPage), DA(pxaErrorReport),
47 pxtBeginSession,
48 DUB(0), DA(pxaSourceType),
49 DUB(eBinaryLowByteFirst), DA(pxaDataOrg),
50 pxtOpenDataSource
51 };
52
53 px_put_bytes(s, (const byte *)enter_pjl_header,
54 strlen(enter_pjl_header));
55
56 if (dev->color_info.num_components == 1)
57 px_put_bytes(s, (const byte *)rendermode_gray,
58 strlen(rendermode_gray));
59 else
60 px_put_bytes(s, (const byte *)rendermode_color,
61 strlen(rendermode_color));
62
63 /* We have to add 2 to the strlen because the next-to-last */
64 /* character is a null. */
65 px_put_bytes(s, (const byte *)file_header,
66 strlen(file_header) + 2);
67 px_put_usp(s, (uint) (dev->HWResolution[0] + 0.5),
68 (uint) (dev->HWResolution[1] + 0.5));
69 PX_PUT_LIT(s, stream_header);
70 return 0;
71 }
72
73 /* Write the page header, including orientation. */
74 int
px_write_page_header(stream * s,const gx_device * dev)75 px_write_page_header(stream *s, const gx_device *dev)
76 {
77 static const byte page_header_1[] = {
78 DUB(ePortraitOrientation), DA(pxaOrientation)
79 };
80
81 PX_PUT_LIT(s, page_header_1);
82 return 0;
83 }
84
85 /* Write the media selection command if needed, updating the media size. */
86 int
px_write_select_media(stream * s,const gx_device * dev,pxeMediaSize_t * pms,byte * media_source)87 px_write_select_media(stream *s, const gx_device *dev,
88 pxeMediaSize_t *pms, byte *media_source)
89 {
90 #define MSD(ms, res, w, h)\
91 { ms, (float)((w) * 1.0 / (res)), (float)((h) * 1.0 / res) },
92 static const struct {
93 pxeMediaSize_t ms;
94 float width, height;
95 } media_sizes[] = {
96 px_enumerate_media(MSD)
97 { pxeMediaSize_next }
98 };
99 #undef MSD
100 float w = dev->width / dev->HWResolution[0],
101 h = dev->height / dev->HWResolution[1];
102 int i;
103 pxeMediaSize_t size;
104 byte tray = eAutoSelect;
105
106 /* The default is eLetterPaper, media size 0. */
107 for (i = countof(media_sizes) - 2; i > 0; --i)
108 if (fabs(media_sizes[i].width - w) < 5.0 / 72 &&
109 fabs(media_sizes[i].height - h) < 5.0 / 72
110 )
111 break;
112 size = media_sizes[i].ms;
113 /*
114 * According to the PCL XL documentation, MediaSize must always
115 * be specified, but MediaSource is optional.
116 */
117 px_put_uba(s, (byte)size, pxaMediaSize);
118
119 if (media_source != NULL)
120 tray = *media_source;
121 px_put_uba(s, tray, pxaMediaSource);
122 if (pms)
123 *pms = size;
124
125 return 0;
126 }
127
128 /*
129 * Write the file trailer. Note that this takes a FILE *, not a stream *,
130 * since it may be called after the stream is closed.
131 */
132 int
px_write_file_trailer(FILE * file)133 px_write_file_trailer(FILE *file)
134 {
135 static const byte file_trailer[] = {
136 pxtCloseDataSource,
137 pxtEndSession,
138 033, '%', '-', '1', '2', '3', '4', '5', 'X'
139 };
140
141 fwrite(file_trailer, 1, sizeof(file_trailer), file);
142 return 0;
143 }
144
145 /* ---------------- Low-level data output ---------------- */
146
147 /* Write a sequence of bytes. */
148 void
px_put_bytes(stream * s,const byte * data,uint count)149 px_put_bytes(stream * s, const byte * data, uint count)
150 {
151 uint used;
152
153 sputs(s, data, count, &used);
154 }
155
156 /* Utilities for writing data values. */
157 /* H-P printers only support little-endian data, so that's what we emit. */
158 void
px_put_a(stream * s,px_attribute_t a)159 px_put_a(stream * s, px_attribute_t a)
160 {
161 sputc(s, pxt_attr_ubyte);
162 sputc(s, (byte)a);
163 }
164 void
px_put_ac(stream * s,px_attribute_t a,px_tag_t op)165 px_put_ac(stream *s, px_attribute_t a, px_tag_t op)
166 {
167 px_put_a(s, a);
168 sputc(s, (byte)op);
169 }
170
171 void
px_put_ub(stream * s,byte b)172 px_put_ub(stream * s, byte b)
173 {
174 sputc(s, pxt_ubyte);
175 sputc(s, b);
176 }
177 void
px_put_uba(stream * s,byte b,px_attribute_t a)178 px_put_uba(stream *s, byte b, px_attribute_t a)
179 {
180 px_put_ub(s, b);
181 px_put_a(s, a);
182 }
183
184 void
px_put_s(stream * s,uint i)185 px_put_s(stream * s, uint i)
186 {
187 sputc(s, (byte) i);
188 sputc(s, (byte) (i >> 8));
189 }
190 void
px_put_us(stream * s,uint i)191 px_put_us(stream * s, uint i)
192 {
193 sputc(s, pxt_uint16);
194 px_put_s(s, i);
195 }
196 void
px_put_usa(stream * s,uint i,px_attribute_t a)197 px_put_usa(stream *s, uint i, px_attribute_t a)
198 {
199 px_put_us(s, i);
200 px_put_a(s, a);
201 }
202 void
px_put_u(stream * s,uint i)203 px_put_u(stream * s, uint i)
204 {
205 if (i <= 255)
206 px_put_ub(s, (byte)i);
207 else
208 px_put_us(s, i);
209 }
210
211 void
px_put_usp(stream * s,uint ix,uint iy)212 px_put_usp(stream * s, uint ix, uint iy)
213 {
214 spputc(s, pxt_uint16_xy);
215 px_put_s(s, ix);
216 px_put_s(s, iy);
217 }
218 void
px_put_usq_fixed(stream * s,fixed x0,fixed y0,fixed x1,fixed y1)219 px_put_usq_fixed(stream * s, fixed x0, fixed y0, fixed x1, fixed y1)
220 {
221 spputc(s, pxt_uint16_box);
222 px_put_s(s, fixed2int(x0));
223 px_put_s(s, fixed2int(y0));
224 px_put_s(s, fixed2int(x1));
225 px_put_s(s, fixed2int(y1));
226 }
227
228 void
px_put_ss(stream * s,int i)229 px_put_ss(stream * s, int i)
230 {
231 sputc(s, pxt_sint16);
232 px_put_s(s, (uint) i);
233 }
234 void
px_put_ssp(stream * s,int ix,int iy)235 px_put_ssp(stream * s, int ix, int iy)
236 {
237 sputc(s, pxt_sint16_xy);
238 px_put_s(s, (uint) ix);
239 px_put_s(s, (uint) iy);
240 }
241
242 void
px_put_l(stream * s,ulong l)243 px_put_l(stream * s, ulong l)
244 {
245 px_put_s(s, (uint) l);
246 px_put_s(s, (uint) (l >> 16));
247 }
248
249 void
px_put_r(stream * s,floatp r)250 px_put_r(stream * s, floatp r)
251 { /* Convert to single-precision IEEE float. */
252 int exp;
253 long mantissa = (long)(frexp(r, &exp) * 0x1000000);
254
255 if (exp < -126)
256 mantissa = 0, exp = 0; /* unnormalized */
257 if (mantissa < 0)
258 exp += 128, mantissa = -mantissa;
259 /* All quantities are little-endian. */
260 spputc(s, (byte) mantissa);
261 spputc(s, (byte) (mantissa >> 8));
262 spputc(s, (byte) (((exp + 127) << 7) + ((mantissa >> 16) & 0x7f)));
263 spputc(s, (byte) ((exp + 127) >> 1));
264 }
265 void
px_put_rl(stream * s,floatp r)266 px_put_rl(stream * s, floatp r)
267 {
268 spputc(s, pxt_real32);
269 px_put_r(s, r);
270 }
271
272 void
px_put_data_length(stream * s,uint num_bytes)273 px_put_data_length(stream * s, uint num_bytes)
274 {
275 if (num_bytes > 255) {
276 spputc(s, pxt_dataLength);
277 px_put_l(s, (ulong) num_bytes);
278 } else {
279 spputc(s, pxt_dataLengthByte);
280 spputc(s, (byte) num_bytes);
281 }
282 }
283