Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
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
}