Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1994, 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: gdevpsim.c,v 1.14 2004/10/07 05:18:34 ray Exp $ */
18
/* PostScript image output device */
19
#include "gdevprn.h"
20
#include "gdevpsu.h"
21
#include "stream.h"
22
#include "strimpl.h"
23
#include "sa85x.h"
24
#include "srlx.h"
25
 
26
/*
27
 * There are two drivers in this file, both of which produce PostScript
28
 * output consisting of a single bitmap per page.  The psmono/psgray
29
 * driver produces monochrome Level 1 images using home-grown run length
30
 * compression; the psrgb driver produces planar RGB Level 2 images
31
 * using the RunLengthEncode filter.
32
 */
33
 
34
/* ---------------- Shared code ---------------- */
35
 
36
/* Define the device parameters. */
37
#ifndef X_DPI
38
#  define X_DPI 300
39
#endif
40
#ifndef Y_DPI
41
#  define Y_DPI 300
42
#endif
43
 
44
/* Write the file (if necessary) and page headers. */
45
private void
46
ps_image_write_headers(FILE *f, gx_device_printer *pdev,
47
		       const char *const setup[],
48
		       gx_device_pswrite_common_t *pdpc)
49
{
50
    if (gdev_prn_file_is_new(pdev)) {
51
	gs_rect bbox;
52
 
53
	bbox.p.x = 0;
54
	bbox.p.y = 0;
55
	bbox.q.x = pdev->width / pdev->HWResolution[0] * 72.0;
56
	bbox.q.y = pdev->height / pdev->HWResolution[1] * 72.0;
57
	psw_begin_file_header(f, (gx_device *)pdev, &bbox, pdpc, false);
58
	psw_print_lines(f, setup);
59
	psw_end_file_header(f);
60
    }
61
    {
62
	byte buf[100];		/* arbitrary */
63
	stream s;
64
 
65
	s_init(&s, pdev->memory);
66
	swrite_file(&s, f, buf, sizeof(buf));
67
	psw_write_page_header(&s, (gx_device *)pdev, pdpc, true, pdev->PageCount + 1, 10);
68
	sflush(&s);
69
    }
70
}
71
 
72
/* ---------------- Level 1 monochrome driver ---------------- */
73
 
74
/*
75
 * This driver produces a bitmap in the form of a PostScript file that can
76
 * be fed to any PostScript printer.  It uses a run-length compression
77
 * method that executes quickly (unlike some produced by PostScript
78
 * drivers!).
79
 *
80
 * There are two devices here, one for 1-bit black-and-white and one
81
 * for 8-bit gray.  In fact, the same code could also handle 2- and
82
 * 4-bit gray output.
83
 */
84
 
85
/* The device descriptor */
86
private dev_proc_print_page(psmono_print_page);
87
private dev_proc_close_device(psmono_close);
88
 
89
const gx_device_printer gs_psmono_device =
90
prn_device(prn_std_procs, "psmono",
91
	   DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
92
	   X_DPI, Y_DPI,
93
	   0, 0, 0, 0,		/* margins */
94
	   1, psmono_print_page);
95
 
96
private const gx_device_procs psgray_procs =
97
prn_color_procs(gdev_prn_open, gdev_prn_output_page, psmono_close,
98
	      gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb);
99
 
100
const gx_device_printer gs_psgray_device = {
101
    prn_device_body(gx_device_printer, psgray_procs, "psgray",
102
		    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
103
		    X_DPI, Y_DPI,
104
		    0, 0, 0, 0,	/* margins */
105
		    1, 8, 255, 0, 256, 1, psmono_print_page)
106
};
107
 
108
private const char *const psmono_setup[] = {
109
		/* Initialize the strings for filling runs. */
110
    "/.ImageFills [ 0 1 255 {",
111
    "  256 string dup 0 1 7 { 3 index put dup } for { 8 16 32 64 128 } {",
112
    "    2 copy 0 exch getinterval putinterval dup",
113
    "  } forall pop exch pop",
114
    "} bind for ] def",
115
		/* Initialize the procedure table for input dispatching. */
116
    "/.ImageProcs [",
117
		/* Stack: <buffer> <file> <xdigits> <previous> <byte> */
118
    "  32 { { pop .ImageItem } } repeat",
119
    "  16 { {",	/* 0x20-0x2f: (N-0x20) data bytes follow */
120
    "    32 sub 3 -1 roll add 3 index exch 0 exch getinterval 2 index exch",
121
    "    readhexstring pop exch pop 0 exch dup",
122
    "  } bind } repeat",
123
    "  16 { {",	/* 0x30-0x3f: prefix hex digit (N-0x30) to next count */
124
    "    48 sub 3 -1 roll add 4 bitshift exch .ImageItem",
125
    "  } bind } repeat",
126
    "  32 { {",	/* 0x40-0x5f: repeat last data byte (N-0x40) times */
127
    "    64 sub 3 -1 roll add .ImageFills 2 index dup length 1 sub get get",
128
    "    exch 0 exch getinterval 0 3 1 roll",
129
    "  } bind } repeat",
130
    "  160 { { pop .ImageItem } } repeat",
131
    "] readonly def",
132
		/* Read one item from a compressed image. */
133
		/* Stack contents: <buffer> <file> <xdigits> <previous> */
134
    "/.ImageItem {",
135
    "  2 index read pop dup .ImageProcs exch get exec",
136
    "} bind def",
137
		/* Read and print an entire compressed image. */
138
    "/.ImageRead {"	/* <width> <height> <bpc> .ImageRead - */
139
    "  gsave [",
140
      /* Stack: width height bpc -mark- */
141
    "    1 0 0 -1 0 7 index",
142
      /* Stack: width height bpc -mark- 1 0 0 -1 0 height */
143
    "  ] { .ImageItem }",
144
	/* Stack: width height bpc <matrix> <proc> */
145
    "  4 index 3 index mul 7 add 8 idiv string currentfile 0 ()",
146
	/* Stack: width height bpc <matrix> <proc> <buffer> <file> 0 () */
147
    "  9 4 roll",
148
	/* Stack: <buffer> <file> 0 () width height bpc <matrix> <proc> */
149
    "  image pop pop pop pop grestore",
150
    "} def",
151
 
152
};
153
static const gx_device_pswrite_common_t psmono_values =
154
    PSWRITE_COMMON_VALUES(1, 0 /*false*/, 1);
155
 
156
#define data_run_code 0x20
157
#define xdigit_code 0x30
158
#define max_data_per_line 35
159
#define repeat_run_code 0x40
160
#define max_repeat_run_code 31
161
#define max_repeat_run 255
162
 
163
/* Send the page to the printer. */
164
private void write_data_run(const byte *, int, FILE *, byte);
165
private int
166
psmono_print_page(gx_device_printer * pdev, FILE * prn_stream)
167
{
168
    int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
169
    int lnum;
170
    byte *line = gs_alloc_bytes(pdev->memory, line_size, "psmono_print_page");
171
    byte invert = (pdev->color_info.depth == 1 ? 0xff : 0);
172
    gx_device_pswrite_common_t pswrite_common;
173
 
174
    if (line == 0)
175
	return_error(gs_error_VMerror);
176
    pswrite_common = psmono_values;
177
 
178
    /* If this is the first page of the file, */
179
    /* write the setup code. */
180
    ps_image_write_headers(prn_stream, pdev, psmono_setup, &pswrite_common);
181
 
182
    /* Write the .ImageRead command. */
183
    fprintf(prn_stream,
184
	    "%d %d %d .ImageRead\n",
185
	    pdev->width, pdev->height, pdev->color_info.depth);
186
 
187
    /* Compress each scan line in turn. */
188
    for (lnum = 0; lnum < pdev->height; lnum++) {
189
	const byte *p;
190
	int left = line_size;
191
	byte *data;
192
 
193
	gdev_prn_get_bits(pdev, lnum, line, &data);
194
	p = data;
195
	/* Loop invariant: p + left = data + line_size. */
196
#define min_repeat_run 10
197
	while (left >= min_repeat_run) {	/* Detect a maximal run of non-repeated data. */
198
	    const byte *p1 = p;
199
	    int left1 = left;
200
	    byte b;
201
	    int count, count_left;
202
 
203
	    while (left1 >= min_repeat_run &&
204
		   ((b = *p1) != p1[1] ||
205
		    b != p1[2] || b != p1[3] || b != p1[4] ||
206
		    b != p1[5] || b != p1[6] || b != p1[7] ||
207
		    b != p1[8] || b != p1[9])
208
		)
209
		++p1, --left1;
210
	    if (left1 < min_repeat_run)
211
		break;		/* no repeated data left */
212
	    write_data_run(p, (int)(p1 - p + 1), prn_stream,
213
			   invert);
214
	    /* Detect a maximal run of repeated data. */
215
	    p = ++p1 + (min_repeat_run - 1);
216
	    left = --left1 - (min_repeat_run - 1);
217
	    while (left > 0 && *p == b)
218
		++p, --left;
219
	    for (count = p - p1; count > 0;
220
		 count -= count_left
221
		) {
222
		count_left = min(count, max_repeat_run);
223
		if (count_left > max_repeat_run_code)
224
		    fputc(xdigit_code + (count_left >> 4),
225
			  prn_stream),
226
			fputc(repeat_run_code + (count_left & 0xf),
227
			      prn_stream);
228
		else
229
		    putc(repeat_run_code + count_left,
230
			 prn_stream);
231
	    }
232
            if (ferror(prn_stream))
233
	        return_error(gs_error_ioerror);
234
        }
235
	/* Write the remaining data, if any. */
236
	write_data_run(p, left, prn_stream, invert);
237
    }
238
 
239
    /* Clean up and return. */
240
    fputs("\n", prn_stream);
241
    psw_write_page_trailer(prn_stream, 1, true);
242
    gs_free_object(pdev->memory, line, "psmono_print_page");
243
    if (ferror(prn_stream))
244
	return_error(gs_error_ioerror);
245
    return 0;
246
}
247
 
248
/* Close the file. */
249
private int
250
psmono_close(gx_device *dev)
251
{
252
    int code = psw_end_file(((gx_device_printer *)dev)->file, dev, 
253
            &psmono_values, NULL, dev->PageCount);
254
 
255
    if (code < 0)
256
        return code;
257
    return gdev_prn_close(dev);
258
}
259
 
260
/* Write a run of data on the file. */
261
private void
262
write_data_run(const byte * data, int count, FILE * f, byte invert)
263
{
264
    const byte *p = data;
265
    const char *const hex_digits = "0123456789abcdef";
266
    int left = count;
267
    char line[sizeof(count) * 2 + max_data_per_line * 2 + 3];
268
    char *q = line;
269
 
270
    /* Write the count. */
271
 
272
    if (!count)
273
	return;
274
    {
275
	int shift = sizeof(count) * 8;
276
 
277
	while ((shift -= 4) > 0 && (count >> shift) == 0);
278
	for (; shift > 0; shift -= 4)
279
	    *q++ = xdigit_code + ((count >> shift) & 0xf);
280
	*q++ = data_run_code + (count & 0xf);
281
    }
282
 
283
    /* Write the data. */
284
 
285
    while (left > 0) {
286
	register int wcount = min(left, max_data_per_line);
287
 
288
	left -= wcount;
289
	for (; wcount > 0; ++p, --wcount) {
290
	    byte b = *p ^ invert;
291
 
292
	    *q++ = hex_digits[b >> 4];
293
	    *q++ = hex_digits[b & 0xf];
294
	}
295
	*q++ = '\n';
296
	fwrite(line, 1, q - line, f);
297
	q = line;
298
    }
299
 
300
}
301
 
302
/* ---------------- Level 2 RGB driver ---------------- */
303
 
304
/*
305
 * This driver produces plane-separated, run-length-encoded, 24-bit RGB
306
 * images suitable for a PostScript Level 2 printer.  LZW compression would
307
 * be better, but Unisys' claim to own the compression algorithm and their
308
 * demand for licensing and payment even for freely distributed software
309
 * rule this out.
310
 */
311
 
312
/* The device descriptor */
313
private dev_proc_print_page(psrgb_print_page);
314
private dev_proc_close_device(psrgb_close);
315
 
316
private const gx_device_procs psrgb_procs =
317
prn_color_procs(gdev_prn_open, gdev_prn_output_page, psrgb_close,
318
		gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
319
 
320
const gx_device_printer gs_psrgb_device = {
321
    prn_device_body(gx_device_printer, psrgb_procs, "psrgb",
322
		    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
323
		    X_DPI, Y_DPI,
324
		    0, 0, 0, 0,	/* margins */
325
		    3, 24, 255, 255, 256, 256, psrgb_print_page)
326
};
327
 
328
private const char *const psrgb_setup[] = {
329
    "/rgbimage {",		/* <width> <height> rgbimage - */
330
    "  gsave 2 copy scale /h exch def /w exch def",
331
    "  /s1 w string def /s2 w string def /s3 w string def",
332
    "  /f currentfile /ASCII85Decode filter /RunLengthDecode filter def",
333
    "  w h 8 [w 0 0 h neg 0 h]",
334
    "  {f s1 readstring pop} {f s2 readstring pop} {f s3 readstring pop}",
335
    "  true 3 colorimage grestore",
336
    "} bind def",
337
 
338
};
339
static const gx_device_pswrite_common_t psrgb_values =
340
    PSWRITE_COMMON_VALUES(2, 0 /*false*/, 1);
341
 
342
/* Send the page to the printer. */
343
private int
344
psrgb_print_page(gx_device_printer * pdev, FILE * prn_stream)
345
{
346
    gs_memory_t *mem = pdev->memory;
347
    int width = pdev->width;
348
    byte *lbuf = gs_alloc_bytes(mem, width * 3,
349
				"psrgb_print_page(lbuf)");
350
    int lnum;
351
    stream fs, a85s, rls;
352
    stream_A85E_state a85state;
353
    stream_RLE_state rlstate;
354
    byte fsbuf[200];		/* arbitrary, must be >2 */
355
    byte a85sbuf[100];		/* arbitrary, must be >=6 */
356
    byte rlsbuf[200];		/* arbitrary, must be >128 */
357
    gx_device_pswrite_common_t pswrite_common;
358
    pswrite_common = psrgb_values;
359
 
360
    if (lbuf == 0)
361
	return_error(gs_error_VMerror);
362
    ps_image_write_headers(prn_stream, pdev, psrgb_setup, &pswrite_common);
363
    fprintf(prn_stream, "%d %d rgbimage\n", width, pdev->height);
364
    s_init(&fs, mem);
365
    swrite_file(&fs, prn_stream, fsbuf, sizeof(fsbuf));
366
    fs.memory = 0;
367
 
368
    if (s_A85E_template.set_defaults)
369
	(*s_A85E_template.set_defaults) ((stream_state *) & a85state);
370
    s_init(&a85s, mem);
371
    s_std_init(&a85s, a85sbuf, sizeof(a85sbuf), &s_filter_write_procs,
372
	       s_mode_write);
373
    a85s.memory = 0;
374
    a85state.memory = 0;
375
    a85state.template = &s_A85E_template;
376
    (*s_A85E_template.init) ((stream_state *) & a85state);
377
    a85s.state = (stream_state *) & a85state;
378
    a85s.procs.process = s_A85E_template.process;
379
    a85s.strm = &fs;
380
 
381
    (*s_RLE_template.set_defaults) ((stream_state *) & rlstate);
382
    s_init(&rls, mem);
383
    s_std_init(&rls, rlsbuf, sizeof(rlsbuf), &s_filter_write_procs,
384
	       s_mode_write);
385
    rls.memory = 0;
386
    rlstate.memory = 0;
387
    rlstate.template = &s_RLE_template;
388
    (*s_RLE_template.init) ((stream_state *) & rlstate);
389
    rls.state = (stream_state *) & rlstate;
390
    rls.procs.process = s_RLE_template.process;
391
    rls.strm = &a85s;
392
 
393
    for (lnum = 0; lnum < pdev->height; ++lnum) {
394
	byte *data;
395
	int i, c;
396
 
397
	gdev_prn_get_bits(pdev, lnum, lbuf, &data);
398
	for (c = 0; c < 3; ++c) {
399
	    const byte *p;
400
 
401
	    for (i = 0, p = data + c; i < width; ++i, p += 3)
402
		sputc(&rls, *p);
403
            if (rls.end_status == ERRC)
404
              return_error(gs_error_ioerror);
405
	}
406
    }
407
    sclose(&rls);
408
    sclose(&a85s);
409
    sflush(&fs);
410
    fputs("\n", prn_stream);
411
    psw_write_page_trailer(prn_stream, 1, true);
412
    gs_free_object(mem, lbuf, "psrgb_print_page(lbuf)");
413
    if (ferror(prn_stream))
414
        return_error(gs_error_ioerror);
415
    return 0;
416
}
417
 
418
/* Close the file. */
419
private int
420
psrgb_close(gx_device *dev)
421
{
422
    int code = psw_end_file(((gx_device_printer *)dev)->file, dev,
423
            &psrgb_values, NULL, dev->PageCount);
424
 
425
    if (code < 0)
426
        return code;
427
    return gdev_prn_close(dev);
428
}