2 |
- |
1 |
/* Copyright (C) 2000 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: gdevcfax.c,v 1.5 2002/02/21 22:24:51 giles Exp $ */
|
|
|
18 |
/* SFF format writer for CAPI fax devices */
|
|
|
19 |
#include "gdevprn.h"
|
|
|
20 |
#include "strimpl.h"
|
|
|
21 |
#include "scfx.h"
|
|
|
22 |
#include "gdevfax.h"
|
|
|
23 |
|
|
|
24 |
/* The device descriptor */
|
|
|
25 |
private dev_proc_print_page(cfax_print_page);
|
|
|
26 |
private dev_proc_close_device(cfax_prn_close);
|
|
|
27 |
|
|
|
28 |
/* Define procedures for cfax. For sff multipage documents */
|
|
|
29 |
/* a special close procedure is required because sff needs */
|
|
|
30 |
/* an additional "end of document" signature after the last */
|
|
|
31 |
/* "end page" signature */
|
|
|
32 |
private const gx_device_procs gdev_cfax_std_procs =
|
|
|
33 |
prn_params_procs(gdev_prn_open, gdev_prn_output_page, cfax_prn_close,
|
|
|
34 |
gdev_fax_get_params, gdev_fax_put_params);
|
|
|
35 |
|
|
|
36 |
const gx_device_fax gs_cfax_device = {
|
|
|
37 |
FAX_DEVICE_BODY(gx_device_fax, gdev_cfax_std_procs, "cfax", cfax_print_page)
|
|
|
38 |
};
|
|
|
39 |
|
|
|
40 |
/* ---------------- SFF output ----------------- */
|
|
|
41 |
|
|
|
42 |
private void
|
|
|
43 |
cfax_byte(uint c, FILE * file)
|
|
|
44 |
{
|
|
|
45 |
fputc(c & 0xff, file);
|
|
|
46 |
}
|
|
|
47 |
|
|
|
48 |
private void
|
|
|
49 |
cfax_word(ushort c, FILE * file)
|
|
|
50 |
{
|
|
|
51 |
cfax_byte(c & 0xff, file);
|
|
|
52 |
cfax_byte(c >> 8, file);
|
|
|
53 |
}
|
|
|
54 |
|
|
|
55 |
private void
|
|
|
56 |
cfax_dword(ulong c, FILE * file)
|
|
|
57 |
{
|
|
|
58 |
cfax_byte(c & 0xff, file);
|
|
|
59 |
cfax_byte(c >> 8, file);
|
|
|
60 |
cfax_byte(c >> 16, file);
|
|
|
61 |
cfax_byte(c >> 24, file);
|
|
|
62 |
}
|
|
|
63 |
|
|
|
64 |
private void
|
|
|
65 |
cfax_doc_hdr(FILE * file)
|
|
|
66 |
{
|
|
|
67 |
cfax_byte('S', file);
|
|
|
68 |
cfax_byte('f', file);
|
|
|
69 |
cfax_byte('f', file);
|
|
|
70 |
cfax_byte('f', file);
|
|
|
71 |
cfax_byte(1, file);
|
|
|
72 |
cfax_byte(0, file);
|
|
|
73 |
cfax_word(0, file);
|
|
|
74 |
cfax_word(0, file);
|
|
|
75 |
cfax_word(20, file);
|
|
|
76 |
cfax_dword(0, file);
|
|
|
77 |
cfax_dword(0, file);
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
private void
|
|
|
81 |
cfax_page_hdr(gx_device_printer * pdev, FILE * file)
|
|
|
82 |
{
|
|
|
83 |
cfax_byte(254, file);
|
|
|
84 |
cfax_byte(16, file);
|
|
|
85 |
cfax_byte((pdev->y_pixels_per_inch < 100 ? 0 : 1), file);
|
|
|
86 |
cfax_byte(0, file);
|
|
|
87 |
cfax_byte(0, file);
|
|
|
88 |
cfax_byte(0, file);
|
|
|
89 |
cfax_word(pdev->width, file);
|
|
|
90 |
cfax_word(pdev->height, file);
|
|
|
91 |
cfax_dword(0, file);
|
|
|
92 |
cfax_dword(0, file);
|
|
|
93 |
}
|
|
|
94 |
|
|
|
95 |
private void
|
|
|
96 |
cfax_doc_end(FILE * file)
|
|
|
97 |
{
|
|
|
98 |
cfax_byte(254, file);
|
|
|
99 |
cfax_byte(0, file);
|
|
|
100 |
}
|
|
|
101 |
|
|
|
102 |
/* Send the page to the printer. */
|
|
|
103 |
private int
|
|
|
104 |
cfax_stream_print_page_width(gx_device_printer * pdev, FILE * prn_stream,
|
|
|
105 |
const stream_template * temp, stream_state * ss,
|
|
|
106 |
int width)
|
|
|
107 |
{
|
|
|
108 |
gs_memory_t *mem = pdev->memory;
|
|
|
109 |
int code = 0;
|
|
|
110 |
stream_cursor_read r;
|
|
|
111 |
stream_cursor_write w;
|
|
|
112 |
int in_size = gdev_prn_raster((gx_device *) pdev);
|
|
|
113 |
/*
|
|
|
114 |
* Because of the width adjustment for fax systems, width may
|
|
|
115 |
* be different from (either greater than or less than) pdev->width.
|
|
|
116 |
* Allocate a large enough buffer to account for this.
|
|
|
117 |
*/
|
|
|
118 |
int col_size = (width * pdev->color_info.depth + 7) >> 3;
|
|
|
119 |
int max_size = max(in_size, col_size);
|
|
|
120 |
int lnum, nbytes, i;
|
|
|
121 |
byte *in;
|
|
|
122 |
byte *out;
|
|
|
123 |
/* If the file is 'nul', don't even do the writes. */
|
|
|
124 |
bool nul = !strcmp(pdev->fname, "nul");
|
|
|
125 |
|
|
|
126 |
/* Initialize the common part of the encoder state. */
|
|
|
127 |
ss->template = temp;
|
|
|
128 |
ss->memory = mem;
|
|
|
129 |
|
|
|
130 |
/* Allocate the buffers. */
|
|
|
131 |
in = gs_alloc_bytes(mem, temp->min_in_size + max_size + 1,
|
|
|
132 |
"cfax_stream_print_page(in)");
|
|
|
133 |
|
|
|
134 |
#define OUT_SIZE 1000
|
|
|
135 |
out = gs_alloc_bytes(mem, OUT_SIZE, "cfax_stream_print_page(out)");
|
|
|
136 |
if (in == 0 || out == 0) {
|
|
|
137 |
code = gs_note_error(gs_error_VMerror);
|
|
|
138 |
goto done;
|
|
|
139 |
}
|
|
|
140 |
|
|
|
141 |
/* Process the image */
|
|
|
142 |
for (lnum = 0; lnum < pdev->height; lnum++) {
|
|
|
143 |
/* Initialize read and write pointer each time, because they're getting modified */
|
|
|
144 |
r.ptr = in - 1;
|
|
|
145 |
r.limit = in + col_size;
|
|
|
146 |
w.ptr = out - 1;
|
|
|
147 |
w.limit = w.ptr + OUT_SIZE;
|
|
|
148 |
/* Decoder must encode line for line, so init it for each line */
|
|
|
149 |
code = (*temp->init) (ss);
|
|
|
150 |
if (code < 0)
|
|
|
151 |
return_error(gs_error_limitcheck);
|
|
|
152 |
/* Now, get the bits and encode them */
|
|
|
153 |
gdev_prn_copy_scan_lines(pdev, lnum, in, in_size);
|
|
|
154 |
if (col_size > in_size) {
|
|
|
155 |
memset(in + in_size , 0, col_size - in_size);
|
|
|
156 |
}
|
|
|
157 |
code = (*temp->process) (ss, &r, &w, 1 /* always last line */);
|
|
|
158 |
nbytes = w.ptr - out + 1;
|
|
|
159 |
if (!nul) {
|
|
|
160 |
if (nbytes > 0) {
|
|
|
161 |
if (nbytes < 217) {
|
|
|
162 |
cfax_byte(nbytes, prn_stream);
|
|
|
163 |
for (i = 0; i < nbytes; i++)
|
|
|
164 |
cfax_byte(out[i], prn_stream);
|
|
|
165 |
} else {
|
|
|
166 |
cfax_byte(0, prn_stream);
|
|
|
167 |
cfax_word(nbytes, prn_stream);
|
|
|
168 |
for (i = 0; i < nbytes; i++)
|
|
|
169 |
cfax_byte(out[i], prn_stream);
|
|
|
170 |
}
|
|
|
171 |
} else {
|
|
|
172 |
cfax_byte(218, prn_stream);
|
|
|
173 |
}
|
|
|
174 |
}
|
|
|
175 |
if (temp->release != 0)
|
|
|
176 |
(*temp->release) (ss);
|
|
|
177 |
}
|
|
|
178 |
#undef OUT_SIZE
|
|
|
179 |
|
|
|
180 |
done:
|
|
|
181 |
gs_free_object(mem, out, "cfax_stream_print_page(out)");
|
|
|
182 |
gs_free_object(mem, in, "cfax_stream_print_page(in)");
|
|
|
183 |
return code;
|
|
|
184 |
}
|
|
|
185 |
|
|
|
186 |
/* Begin a capi fax page. */
|
|
|
187 |
private int
|
|
|
188 |
cfax_begin_page(gx_device_printer * pdev, FILE * fp, int width)
|
|
|
189 |
{
|
|
|
190 |
/* Patch the width to reflect fax page width adjustment. */
|
|
|
191 |
int save_width = pdev->width;
|
|
|
192 |
|
|
|
193 |
pdev->width = width;
|
|
|
194 |
if (gdev_prn_file_is_new(pdev)) {
|
|
|
195 |
cfax_doc_hdr(fp);
|
|
|
196 |
}
|
|
|
197 |
cfax_page_hdr(pdev, fp);
|
|
|
198 |
|
|
|
199 |
pdev->width = save_width;
|
|
|
200 |
return 0;
|
|
|
201 |
}
|
|
|
202 |
|
|
|
203 |
/* Print an capi fax (sff-encoded) page. */
|
|
|
204 |
private int
|
|
|
205 |
cfax_print_page(gx_device_printer * pdev, FILE * prn_stream)
|
|
|
206 |
{
|
|
|
207 |
stream_CFE_state state;
|
|
|
208 |
int code;
|
|
|
209 |
|
|
|
210 |
gdev_fax_init_fax_state(&state, (gx_device_fax *)pdev);
|
|
|
211 |
state.EndOfLine = false;
|
|
|
212 |
state.EndOfBlock = false;
|
|
|
213 |
state.EncodedByteAlign = true;
|
|
|
214 |
state.FirstBitLowOrder = true;
|
|
|
215 |
state.K = 0;
|
|
|
216 |
|
|
|
217 |
cfax_begin_page(pdev, prn_stream, state.Columns);
|
|
|
218 |
code = cfax_stream_print_page_width(pdev, prn_stream,
|
|
|
219 |
&s_CFE_template, (stream_state *) &state, state.Columns);
|
|
|
220 |
return code;
|
|
|
221 |
}
|
|
|
222 |
|
|
|
223 |
/* Close an capi fax (sff-encoded) document. */
|
|
|
224 |
private int
|
|
|
225 |
cfax_prn_close(gx_device * pdev)
|
|
|
226 |
{
|
|
|
227 |
gx_device_printer * const ppdev = (gx_device_printer *)pdev;
|
|
|
228 |
|
|
|
229 |
if (ppdev->file != NULL) {
|
|
|
230 |
cfax_doc_end(ppdev->file);
|
|
|
231 |
}
|
|
|
232 |
return gdev_prn_close(pdev);
|
|
|
233 |
}
|