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: gdevfax.c,v 1.4 2002/02/21 22:24:51 giles Exp $ */
18
/* Fax devices */
19
#include "gdevprn.h"
20
#include "strimpl.h"
21
#include "scfx.h"
22
#include "gdevfax.h"
23
 
24
/* The device descriptors */
25
private dev_proc_print_page(faxg3_print_page);
26
private dev_proc_print_page(faxg32d_print_page);
27
private dev_proc_print_page(faxg4_print_page);
28
 
29
/* Define procedures that adjust the paper size. */
30
const gx_device_procs gdev_fax_std_procs =
31
    prn_params_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
32
		     gdev_fax_get_params, gdev_fax_put_params);
33
 
34
#define FAX_DEVICE(dname, print_page)\
35
{\
36
    FAX_DEVICE_BODY(gx_device_fax, gdev_fax_std_procs, dname, print_page)\
37
}
38
 
39
 
40
const gx_device_fax gs_faxg3_device =
41
    FAX_DEVICE("faxg3", faxg3_print_page);
42
 
43
const gx_device_fax gs_faxg32d_device =
44
    FAX_DEVICE("faxg32d", faxg32d_print_page);
45
 
46
const gx_device_fax gs_faxg4_device =
47
    FAX_DEVICE("faxg4", faxg4_print_page);
48
 
49
/* Open the device. */
50
/* This is no longer needed: we retain it for client backward compatibility. */
51
int
52
gdev_fax_open(gx_device * dev)
53
{
54
    return gdev_prn_open(dev);
55
}
56
 
57
/* Get/put the AdjustWidth parameter. */
58
int
59
gdev_fax_get_params(gx_device * dev, gs_param_list * plist)
60
{
61
    gx_device_fax *const fdev = (gx_device_fax *)dev;
62
    int code = gdev_prn_get_params(dev, plist);
63
    int ecode = code;
64
 
65
    if ((code = param_write_int(plist, "AdjustWidth", &fdev->AdjustWidth)) < 0)
66
        ecode = code;
67
    return ecode;
68
}
69
int
70
gdev_fax_put_params(gx_device * dev, gs_param_list * plist)
71
{
72
    gx_device_fax *const fdev = (gx_device_fax *)dev;
73
    int ecode = 0;
74
    int code;
75
    int aw = fdev->AdjustWidth;
76
    const char *param_name;
77
 
78
    switch (code = param_read_int(plist, (param_name = "AdjustWidth"), &aw)) {
79
        case 0:
80
	    if (aw >= 0 && aw <= 1)
81
		break;
82
	    code = gs_error_rangecheck;
83
	default:
84
	    ecode = code;
85
	    param_signal_error(plist, param_name, ecode);
86
	case 1:
87
	    break;
88
    }
89
 
90
    if (ecode < 0)
91
	return ecode;
92
    code = gdev_prn_put_params(dev, plist);
93
    if (code < 0)
94
	return code;
95
 
96
    fdev->AdjustWidth = aw;
97
    return code;
98
}
99
 
100
/* Initialize the stream state with a set of default parameters. */
101
/* These select the same defaults as the CCITTFaxEncode filter, */
102
/* except we set BlackIs1 = true. */
103
private void
104
gdev_fax_init_state_adjust(stream_CFE_state *ss,
105
			   const gx_device_fax *fdev,
106
			   int adjust_width)
107
{
108
    s_CFE_template.set_defaults((stream_state *)ss);
109
    ss->Columns = fdev->width;
110
    ss->Rows = fdev->height;
111
    ss->BlackIs1 = true;
112
    if (adjust_width > 0) {
113
	/* Adjust the page width to a legal value for fax systems. */
114
	if (ss->Columns >= 1680 && ss->Columns <= 1736) {
115
	    /* Adjust width for A4 paper. */
116
	    ss->Columns = 1728;
117
	} else if (ss->Columns >= 2000 && ss->Columns <= 2056) {
118
	    /* Adjust width for B4 paper. */
119
	    ss->Columns = 2048;
120
	}
121
    }
122
}
123
void
124
gdev_fax_init_state(stream_CFE_state *ss, const gx_device_fax *fdev)
125
{
126
    gdev_fax_init_state_adjust(ss, fdev, 1);
127
}
128
void
129
gdev_fax_init_fax_state(stream_CFE_state *ss, const gx_device_fax *fdev)
130
{
131
    gdev_fax_init_state_adjust(ss, fdev, fdev->AdjustWidth);
132
}
133
 
134
/*
135
 * Print one strip with fax compression.  Fax devices call this once per
136
 * page; TIFF devices call this once per strip.
137
 */
138
int
139
gdev_fax_print_strip(gx_device_printer * pdev, FILE * prn_stream,
140
		     const stream_template * temp, stream_state * ss,
141
		     int width, int row_first, int row_end /* last + 1 */)
142
{
143
    gs_memory_t *mem = pdev->memory;
144
    int code;
145
    stream_cursor_read r;
146
    stream_cursor_write w;
147
    int in_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
148
    /*
149
     * Because of the width adjustment for fax systems, width may
150
     * be different from (either greater than or less than) pdev->width.
151
     * Allocate a large enough buffer to account for this.
152
     */
153
    int col_size = (width * pdev->color_info.depth + 7) >> 3;
154
    int max_size = max(in_size, col_size);
155
    int lnum;
156
    byte *in;
157
    byte *out;
158
    /* If the file is 'nul', don't even do the writes. */
159
    bool nul = !strcmp(pdev->fname, "nul");
160
 
161
    /* Initialize the common part of the encoder state. */
162
    ss->template = temp;
163
    ss->memory = mem;
164
    /* Now initialize the encoder. */
165
    code = temp->init(ss);
166
    if (code < 0)
167
	return_error(gs_error_limitcheck);	/* bogus, but as good as any */
168
 
169
    /* Allocate the buffers. */
170
    in = gs_alloc_bytes(mem, temp->min_in_size + max_size + 1,
171
			"gdev_stream_print_page(in)");
172
#define OUT_SIZE 1000
173
    out = gs_alloc_bytes(mem, OUT_SIZE, "gdev_stream_print_page(out)");
174
    if (in == 0 || out == 0) {
175
	code = gs_note_error(gs_error_VMerror);
176
	goto done;
177
    }
178
    /* Set up the processing loop. */
179
    lnum = 0;
180
    r.ptr = r.limit = in - 1;
181
    w.ptr = out - 1;
182
    w.limit = w.ptr + OUT_SIZE;
183
#undef OUT_SIZE
184
 
185
    /* Process the image. */
186
    for (lnum = row_first; ;) {
187
	int status;
188
 
189
	if_debug7('w', "[w]lnum=%d r=0x%lx,0x%lx,0x%lx w=0x%lx,0x%lx,0x%lx\n", lnum,
190
		  (ulong)in, (ulong)r.ptr, (ulong)r.limit,
191
		  (ulong)out, (ulong)w.ptr, (ulong)w.limit);
192
	status = temp->process(ss, &r, &w, lnum == row_end);
193
	if_debug7('w', "...%d, r=0x%lx,0x%lx,0x%lx w=0x%lx,0x%lx,0x%lx\n", status,
194
		  (ulong)in, (ulong)r.ptr, (ulong)r.limit,
195
		  (ulong)out, (ulong)w.ptr, (ulong)w.limit);
196
	switch (status) {
197
	    case 0:		/* need more input data */
198
		if (lnum == row_end)
199
		    goto ok;
200
		{
201
		    uint left = r.limit - r.ptr;
202
 
203
		    memcpy(in, r.ptr + 1, left);
204
		    gdev_prn_copy_scan_lines(pdev, lnum++, in + left, in_size);
205
		    /* Note: we use col_size here, not in_size. */
206
		    if (col_size > in_size) {
207
			memset(in + left + in_size, 0, col_size - in_size);
208
		    }
209
		    r.limit = in + left + col_size - 1;
210
		    r.ptr = in - 1;
211
		}
212
		break;
213
	    case 1:		/* need to write output */
214
		if (!nul)
215
		    fwrite(out, 1, w.ptr + 1 - out, prn_stream);
216
		w.ptr = out - 1;
217
		break;
218
	}
219
    }
220
 
221
  ok:
222
    /* Write out any remaining output. */
223
    if (!nul)
224
	fwrite(out, 1, w.ptr + 1 - out, prn_stream);
225
 
226
  done:
227
    gs_free_object(mem, out, "gdev_stream_print_page(out)");
228
    gs_free_object(mem, in, "gdev_stream_print_page(in)");
229
    if (temp->release)
230
	temp->release(ss);
231
    return code;
232
}
233
 
234
/* Print a fax page.  Other fax drivers use this. */
235
int
236
gdev_fax_print_page(gx_device_printer * pdev, FILE * prn_stream,
237
		    stream_CFE_state * ss)
238
{
239
    return gdev_fax_print_strip(pdev, prn_stream, &s_CFE_template,
240
				(stream_state *)ss, ss->Columns,
241
				0, pdev->height);
242
}
243
 
244
/* Print a 1-D Group 3 page. */
245
private int
246
faxg3_print_page(gx_device_printer * pdev, FILE * prn_stream)
247
{
248
    stream_CFE_state state;
249
 
250
    gdev_fax_init_fax_state(&state, (gx_device_fax *)pdev);
251
    state.EndOfLine = true;
252
    state.EndOfBlock = false;
253
    return gdev_fax_print_page(pdev, prn_stream, &state);
254
}
255
 
256
/* Print a 2-D Group 3 page. */
257
private int
258
faxg32d_print_page(gx_device_printer * pdev, FILE * prn_stream)
259
{
260
    stream_CFE_state state;
261
 
262
    gdev_fax_init_fax_state(&state, (gx_device_fax *)pdev);
263
    state.K = (pdev->y_pixels_per_inch < 100 ? 2 : 4);
264
    state.EndOfLine = true;
265
    state.EndOfBlock = false;
266
    return gdev_fax_print_page(pdev, prn_stream, &state);
267
}
268
 
269
/* Print a Group 4 page. */
270
private int
271
faxg4_print_page(gx_device_printer * pdev, FILE * prn_stream)
272
{
273
    stream_CFE_state state;
274
 
275
    gdev_fax_init_fax_state(&state, (gx_device_fax *)pdev);
276
    state.K = -1;
277
    state.EndOfBlock = false;
278
    return gdev_fax_print_page(pdev, prn_stream, &state);
279
}