~ubuntu-branches/ubuntu/vivid/ghostscript/vivid-security

« back to all changes in this revision

Viewing changes to devices/gdevfax.c

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2013-08-09 20:01:36 UTC
  • mfrom: (1.1.37)
  • Revision ID: package-import@ubuntu.com-20130809200136-amb6zrr7hnjb5jq9
Tags: 9.08~rc1~dfsg-0ubuntu1
* New upstream release
   - Ghostscript 9.08rc1.
   - We are using the system's liblcms2 and libopenjpeg now.
* debian/patches/020130401-852e545-pxl-xl-driver-produced-drawing-commands-without-setting-color-space.patch:
  Removed patch backported from upstream.
* debian/patches/ojdk-8007925+8007926.patch,
  debian/patches/ojdk-8007927.patch,
  debian/patches/ojdk-8007929.patch,
  debian/patches/ojdk-8009654.patch: Removed patches on build in liblcms2, we
  use the system's liblcms2 now.
* debian/patches/2001_docdir_fix_for_debian.patch: Manually updated to new
  upstream source code.
* debian/patches/2003_support_multiarch.patch: Refreshed with quilt.
* debian/control: Added build dependencies on liblcms2-dev and
  libopenjpeg-dev.
* debian/rules: Check for removed lcms2/ and openjpeg/ subdirectories in
  the repackaging check again, also set build options for shared liblcms2
  and libopenjpeg libraries.
* debian/rules: Makefile.in and configure.ac are in the root directory of
  the source now and do not need to get linked from base/. Also there is no
  gstoraster and gstopxl CUPS filter in the package any more and no
  "install-cups" make target any more.
* debian/control, debian/rules, debian/ghostscript-cups.install,
  debian/ghostscript-cups.ppd-updater: Removed the ghostscript-cups binary
  package. The files are now provided by cups-filters.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
 
2
   All Rights Reserved.
 
3
 
 
4
   This software is provided AS-IS with no warranty, either express or
 
5
   implied.
 
6
 
 
7
   This software is distributed under license and may not be copied,
 
8
   modified or distributed except as expressly authorized under the terms
 
9
   of the license contained in the file LICENSE in this distribution.
 
10
 
 
11
   Refer to licensing information at http://www.artifex.com or contact
 
12
   Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
 
13
   CA  94903, U.S.A., +1(415)492-9861, for further information.
 
14
*/
 
15
 
 
16
/* Fax devices */
 
17
#include "gdevprn.h"
 
18
#include "strimpl.h"
 
19
#include "scfx.h"
 
20
#include "gdevfax.h"
 
21
#include "minftrsz.h"
 
22
 
 
23
/* The device descriptors */
 
24
static dev_proc_print_page(faxg3_print_page);
 
25
static dev_proc_print_page(faxg32d_print_page);
 
26
static dev_proc_print_page(faxg4_print_page);
 
27
 
 
28
/* Define procedures that adjust the paper size. */
 
29
/* Since the print_page doesn't alter the device, this device can print in the background */
 
30
const gx_device_procs gdev_fax_std_procs =
 
31
    prn_params_procs(gdev_prn_open, gdev_prn_bg_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
const gx_device_fax gs_faxg3_device =
 
40
    FAX_DEVICE("faxg3", faxg3_print_page);
 
41
 
 
42
const gx_device_fax gs_faxg32d_device =
 
43
    FAX_DEVICE("faxg32d", faxg32d_print_page);
 
44
 
 
45
const gx_device_fax gs_faxg4_device =
 
46
    FAX_DEVICE("faxg4", faxg4_print_page);
 
47
 
 
48
/* Open the device. */
 
49
/* This is no longer needed: we retain it for client backward compatibility. */
 
50
int
 
51
gdev_fax_open(gx_device * dev)
 
52
{
 
53
    return gdev_prn_open(dev);
 
54
}
 
55
 
 
56
/* Get/put the fax parameters: AdjustWidth and MinFeatureSize */
 
57
int
 
58
gdev_fax_get_params(gx_device * dev, gs_param_list * plist)
 
59
{
 
60
    gx_device_fax *const fdev = (gx_device_fax *)dev;
 
61
    int code = gdev_prn_get_params(dev, plist);
 
62
    int ecode = code;
 
63
 
 
64
    if ((code = param_write_int(plist, "AdjustWidth", &fdev->AdjustWidth)) < 0)
 
65
        ecode = code;
 
66
    if ((code = param_write_int(plist, "MinFeatureSize", &fdev->MinFeatureSize)) < 0)
 
67
        ecode = code;
 
68
    return ecode;
 
69
}
 
70
int
 
71
gdev_fax_put_params(gx_device * dev, gs_param_list * plist)
 
72
{
 
73
    gx_device_fax *const fdev = (gx_device_fax *)dev;
 
74
    int ecode = 0;
 
75
    int code;
 
76
    int aw = fdev->AdjustWidth;
 
77
    int mfs = fdev->MinFeatureSize;
 
78
    const char *param_name;
 
79
 
 
80
    switch (code = param_read_int(plist, (param_name = "AdjustWidth"), &aw)) {
 
81
        case 0:
 
82
            if (aw >= 0)
 
83
                break;
 
84
            code = gs_error_rangecheck;
 
85
        default:
 
86
            ecode = code;
 
87
            param_signal_error(plist, param_name, ecode);
 
88
        case 1:
 
89
            break;
 
90
    }
 
91
 
 
92
    switch (code = param_read_int(plist, (param_name = "MinFeatureSize"), &mfs)) {
 
93
        case 0:
 
94
            if (mfs >= 0 && mfs <= 4)
 
95
                break;
 
96
            code = gs_error_rangecheck;
 
97
        default:
 
98
            ecode = code;
 
99
            param_signal_error(plist, param_name, ecode);
 
100
        case 1:
 
101
            break;
 
102
    }
 
103
 
 
104
    if (ecode < 0)
 
105
        return ecode;
 
106
    code = gdev_prn_put_params(dev, plist);
 
107
    if (code < 0)
 
108
        return code;
 
109
 
 
110
    fdev->AdjustWidth = aw;
 
111
    fdev->MinFeatureSize = mfs;
 
112
    return code;
 
113
}
 
114
 
 
115
/* Initialize the stream state with a set of default parameters. */
 
116
/* These select the same defaults as the CCITTFaxEncode filter, */
 
117
/* except we set BlackIs1 = true. */
 
118
static void
 
119
gdev_fax_init_state_adjust(stream_CFE_state *ss,
 
120
                           const gx_device_fax *fdev,
 
121
                           int adjust_width)
 
122
{
 
123
    s_CFE_template.set_defaults((stream_state *)ss);
 
124
    ss->Columns = fdev->width;
 
125
    ss->Rows = fdev->height;
 
126
    ss->BlackIs1 = true;
 
127
    ss->Columns = fax_adjusted_width(ss->Columns, adjust_width);
 
128
}
 
129
 
 
130
void
 
131
gdev_fax_init_state(stream_CFE_state *ss, const gx_device_fax *fdev)
 
132
{
 
133
    gdev_fax_init_state_adjust(ss, fdev, 1);
 
134
}
 
135
void
 
136
gdev_fax_init_fax_state(stream_CFE_state *ss, const gx_device_fax *fdev)
 
137
{
 
138
    gdev_fax_init_state_adjust(ss, fdev, fdev->AdjustWidth);
 
139
}
 
140
 
 
141
/*
 
142
 * Print one strip with fax compression.  Fax devices call this once per
 
143
 * page; TIFF devices call this once per strip.
 
144
 */
 
145
int
 
146
gdev_fax_print_strip(gx_device_printer * pdev, FILE * prn_stream,
 
147
                     const stream_template * temp, stream_state * ss,
 
148
                     int width, int row_first, int row_end /* last + 1 */)
 
149
{
 
150
    gs_memory_t *mem = pdev->memory;
 
151
    int code;
 
152
    stream_cursor_read r;
 
153
    stream_cursor_write w;
 
154
    int in_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
 
155
    /*
 
156
     * Because of the width adjustment for fax systems, width may
 
157
     * be different from (either greater than or less than) pdev->width.
 
158
     * Allocate a large enough buffer to account for this.
 
159
     */
 
160
    int col_size = (width * pdev->color_info.depth + 7) >> 3;
 
161
    int max_size = max(in_size, col_size);
 
162
    int lnum = 0;
 
163
    int row_in = row_first;
 
164
    byte *in;
 
165
    byte *out;
 
166
    void *min_feature_data = NULL;
 
167
    /* If the file is 'nul', don't even do the writes. */
 
168
    bool nul = !strcmp(pdev->fname, "nul");
 
169
    int lnum_in = row_in;
 
170
    int min_feature_size = ((gx_device_fax *const)pdev)->MinFeatureSize;
 
171
 
 
172
    /* Initialize the common part of the encoder state. */
 
173
    ss->templat = temp;
 
174
    ss->memory = mem;
 
175
    /* Now initialize the encoder. */
 
176
    code = temp->init(ss);
 
177
    if (code < 0)
 
178
        return_error(gs_error_limitcheck);      /* bogus, but as good as any */
 
179
 
 
180
    /* Allocate the buffers. */
 
181
    in = gs_alloc_bytes(mem, temp->min_in_size + max_size + 1,
 
182
                        "gdev_stream_print_page(in)");
 
183
#define OUT_SIZE 1000
 
184
    out = gs_alloc_bytes(mem, OUT_SIZE, "gdev_stream_print_page(out)");
 
185
    if (in == 0 || out == 0) {
 
186
        code = gs_note_error(gs_error_VMerror);
 
187
        goto done;
 
188
    }
 
189
    /* Init the min_feature_size expansion for entire image (not strip) */
 
190
    if ((min_feature_size > 1) && (row_first == 0))
 
191
        code = min_feature_size_init(mem, min_feature_size,
 
192
                                     width, pdev->height, &min_feature_data);
 
193
    if (min_feature_size > 1)
 
194
        row_in = max(0, row_first-min_feature_size);    /* need some data before this row */
 
195
 
 
196
    /* Set up the processing loop. */
 
197
    r.ptr = r.limit = in - 1;
 
198
    w.ptr = out - 1;
 
199
    w.limit = w.ptr + OUT_SIZE;
 
200
#undef OUT_SIZE
 
201
 
 
202
    /* Process the image. */
 
203
    for (lnum = row_in; ;) {
 
204
        int status;
 
205
 
 
206
        if_debug7m('w', mem,
 
207
                   "[w]lnum=%d r=0x%lx,0x%lx,0x%lx w=0x%lx,0x%lx,0x%lx\n", lnum,
 
208
                   (ulong)in, (ulong)r.ptr, (ulong)r.limit,
 
209
                   (ulong)out, (ulong)w.ptr, (ulong)w.limit);
 
210
        status = temp->process(ss, &r, &w, lnum == row_end);
 
211
        if_debug7m('w', mem,
 
212
                   "...%d, r=0x%lx,0x%lx,0x%lx w=0x%lx,0x%lx,0x%lx\n", status,
 
213
                   (ulong)in, (ulong)r.ptr, (ulong)r.limit,
 
214
                   (ulong)out, (ulong)w.ptr, (ulong)w.limit);
 
215
        switch (status) {
 
216
            case 0:             /* need more input data */
 
217
                if (lnum == row_end)
 
218
                    goto ok;
 
219
                {
 
220
                    uint left = r.limit - r.ptr;
 
221
                    int filtered_count = in_size;
 
222
 
 
223
                    memcpy(in, r.ptr + 1, left);
 
224
                    do {
 
225
                        if (lnum_in < row_end)
 
226
                        {
 
227
                            code = gdev_prn_copy_scan_lines(pdev, lnum_in++, in + left, in_size);
 
228
                            if (code < 0) {
 
229
                                code = gs_note_error(code);
 
230
                                goto done;
 
231
                            }
 
232
                        }
 
233
                        if (min_feature_size > 1)
 
234
                            filtered_count =
 
235
                                min_feature_size_process(in+left, min_feature_data);
 
236
                    } while (filtered_count == 0);
 
237
                    /* Note: we use col_size here, not in_size. */
 
238
                    lnum++;
 
239
                    if (col_size > in_size) {
 
240
                        memset(in + left + in_size, 0, col_size - in_size);
 
241
                    }
 
242
                    r.limit = in + left + col_size - 1;
 
243
                    r.ptr = in - 1;
 
244
                }
 
245
                break;
 
246
            case 1:             /* need to write output */
 
247
                if (!nul)
 
248
                    fwrite(out, 1, w.ptr + 1 - out, prn_stream);
 
249
                w.ptr = out - 1;
 
250
                break;
 
251
        }
 
252
    }
 
253
 
 
254
  ok:
 
255
    /* Write out any remaining output. */
 
256
    if (!nul)
 
257
        fwrite(out, 1, w.ptr + 1 - out, prn_stream);
 
258
 
 
259
  done:
 
260
    if ((min_feature_size > 1) && (lnum == pdev->height))
 
261
        min_feature_size_dnit(min_feature_data);
 
262
    gs_free_object(mem, out, "gdev_stream_print_page(out)");
 
263
    gs_free_object(mem, in, "gdev_stream_print_page(in)");
 
264
    if (temp->release)
 
265
        temp->release(ss);
 
266
    return code;
 
267
}
 
268
 
 
269
/* Print a fax page.  Other fax drivers use this. */
 
270
int
 
271
gdev_fax_print_page(gx_device_printer * pdev, FILE * prn_stream,
 
272
                    stream_CFE_state * ss)
 
273
{
 
274
    return gdev_fax_print_strip(pdev, prn_stream, &s_CFE_template,
 
275
                                (stream_state *)ss, ss->Columns,
 
276
                                0, pdev->height);
 
277
}
 
278
 
 
279
/* Print a 1-D Group 3 page. */
 
280
static int
 
281
faxg3_print_page(gx_device_printer * pdev, FILE * prn_stream)
 
282
{
 
283
    stream_CFE_state state;
 
284
 
 
285
    gdev_fax_init_fax_state(&state, (gx_device_fax *)pdev);
 
286
    state.EndOfLine = true;
 
287
    state.EndOfBlock = false;
 
288
    return gdev_fax_print_page(pdev, prn_stream, &state);
 
289
}
 
290
 
 
291
/* Print a 2-D Group 3 page. */
 
292
static int
 
293
faxg32d_print_page(gx_device_printer * pdev, FILE * prn_stream)
 
294
{
 
295
    stream_CFE_state state;
 
296
 
 
297
    gdev_fax_init_fax_state(&state, (gx_device_fax *)pdev);
 
298
    state.K = (pdev->y_pixels_per_inch < 100 ? 2 : 4);
 
299
    state.EndOfLine = true;
 
300
    state.EndOfBlock = false;
 
301
    return gdev_fax_print_page(pdev, prn_stream, &state);
 
302
}
 
303
 
 
304
/* Print a Group 4 page. */
 
305
static int
 
306
faxg4_print_page(gx_device_printer * pdev, FILE * prn_stream)
 
307
{
 
308
    stream_CFE_state state;
 
309
 
 
310
    gdev_fax_init_fax_state(&state, (gx_device_fax *)pdev);
 
311
    state.K = -1;
 
312
    state.EndOfBlock = false;
 
313
    return gdev_fax_print_page(pdev, prn_stream, &state);
 
314
}