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) 1997, 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: gdevpsdu.c,v 1.23 2005/03/14 18:08:36 dan Exp $ */
18
/* Common utilities for PostScript and PDF writers */
19
#include "stdio_.h"		/* for FILE for jpeglib.h */
20
#include "jpeglib_.h"		/* for sdct.h */
21
#include "memory_.h"
22
#include "gx.h"
23
#include "gserrors.h"
24
#include "gdevpsdf.h"
25
#include "strimpl.h"
26
#include "sa85x.h"
27
#include "scfx.h"
28
#include "sdct.h"
29
#include "sjpeg.h"
30
#include "spprint.h"
31
#include "sstring.h"
32
#include "gsovrc.h"
33
 
34
/* Structure descriptors */
35
public_st_device_psdf();
36
public_st_psdf_binary_writer();
37
 
38
/* Standard color command names. */
39
const psdf_set_color_commands_t psdf_set_fill_color_commands = {
40
    "g", "rg", "k", "cs", "sc", "scn"
41
};
42
const psdf_set_color_commands_t psdf_set_stroke_color_commands = {
43
    "G", "RG", "K", "CS", "SC", "SCN"
44
};
45
 
46
 
47
/* Define parameter-setting procedures. */
48
extern stream_state_proc_put_params(s_DCTE_put_params, stream_DCT_state);
49
 
50
/* ---------------- Vector implementation procedures ---------------- */
51
 
52
int
53
psdf_setlinewidth(gx_device_vector * vdev, floatp width)
54
{
55
    pprintg1(gdev_vector_stream(vdev), "%g w\n", width);
56
    return 0;
57
}
58
 
59
int
60
psdf_setlinecap(gx_device_vector * vdev, gs_line_cap cap)
61
{
62
    pprintd1(gdev_vector_stream(vdev), "%d J\n", cap);
63
    return 0;
64
}
65
 
66
int
67
psdf_setlinejoin(gx_device_vector * vdev, gs_line_join join)
68
{
69
    pprintd1(gdev_vector_stream(vdev), "%d j\n", join);
70
    return 0;
71
}
72
 
73
int
74
psdf_setmiterlimit(gx_device_vector * vdev, floatp limit)
75
{
76
    pprintg1(gdev_vector_stream(vdev), "%g M\n", limit);
77
    return 0;
78
}
79
 
80
int
81
psdf_setdash(gx_device_vector * vdev, const float *pattern, uint count,
82
	     floatp offset)
83
{
84
    stream *s = gdev_vector_stream(vdev);
85
    int i;
86
 
87
    stream_puts(s, "[ ");
88
    for (i = 0; i < count; ++i)
89
	pprintg1(s, "%g ", pattern[i]);
90
    pprintg1(s, "] %g d\n", offset);
91
    return 0;
92
}
93
 
94
int
95
psdf_setflat(gx_device_vector * vdev, floatp flatness)
96
{
97
    pprintg1(gdev_vector_stream(vdev), "%g i\n", flatness);
98
    return 0;
99
}
100
 
101
int
102
psdf_setlogop(gx_device_vector * vdev, gs_logical_operation_t lop,
103
	      gs_logical_operation_t diff)
104
{
105
/****** SHOULD AT LEAST DETECT SET-0 & SET-1 ******/
106
    return 0;
107
}
108
 
109
int
110
psdf_dorect(gx_device_vector * vdev, fixed x0, fixed y0, fixed x1, fixed y1,
111
	    gx_path_type_t type)
112
{
113
    int code = (*vdev_proc(vdev, beginpath)) (vdev, type);
114
 
115
    if (code < 0)
116
	return code;
117
    pprintg4(gdev_vector_stream(vdev), "%g %g %g %g re\n",
118
	     fixed2float(x0), fixed2float(y0),
119
	     fixed2float(x1 - x0), fixed2float(y1 - y0));
120
    return (*vdev_proc(vdev, endpath)) (vdev, type);
121
}
122
 
123
int
124
psdf_beginpath(gx_device_vector * vdev, gx_path_type_t type)
125
{
126
    return 0;
127
}
128
 
129
int
130
psdf_moveto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
131
	    gx_path_type_t type)
132
{
133
    pprintg2(gdev_vector_stream(vdev), "%g %g m\n", x, y);
134
    return 0;
135
}
136
 
137
int
138
psdf_lineto(gx_device_vector * vdev, floatp x0, floatp y0, floatp x, floatp y,
139
	    gx_path_type_t type)
140
{
141
    pprintg2(gdev_vector_stream(vdev), "%g %g l\n", x, y);
142
    return 0;
143
}
144
 
145
int
146
psdf_curveto(gx_device_vector * vdev, floatp x0, floatp y0,
147
	   floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3,
148
	     gx_path_type_t type)
149
{
150
    if (x1 == x0 && y1 == y0 && x2 == x3 && y2 == y3)
151
	pprintg2(gdev_vector_stream(vdev), "%g %g l\n", x3, y3);
152
    else if (x1 == x0 && y1 == y0)
153
	pprintg4(gdev_vector_stream(vdev), "%g %g %g %g v\n",
154
		 x2, y2, x3, y3);
155
    else if (x3 == x2 && y3 == y2)
156
	pprintg4(gdev_vector_stream(vdev), "%g %g %g %g y\n",
157
		 x1, y1, x2, y2);
158
    else
159
	pprintg6(gdev_vector_stream(vdev), "%g %g %g %g %g %g c\n",
160
		 x1, y1, x2, y2, x3, y3);
161
    return 0;
162
}
163
 
164
int
165
psdf_closepath(gx_device_vector * vdev, floatp x0, floatp y0,
166
	       floatp x_start, floatp y_start, gx_path_type_t type)
167
{
168
    stream_puts(gdev_vector_stream(vdev), "h\n");
169
    return 0;
170
}
171
 
172
/* endpath is deliberately omitted. */
173
 
174
/* ---------------- Utilities ---------------- */
175
 
176
gx_color_index
177
psdf_adjust_color_index(gx_device_vector *vdev, gx_color_index color)
178
{
179
    /*
180
     * Since gx_no_color_index is all 1's, we can't represent
181
     * a CMYK color consisting of full ink in all 4 components.
182
     * However, this color must be available for registration marks.
183
     * gxcmap.c fudges this by changing the K component to 254;
184
     * undo this fudge here.
185
     */
186
    return (color == (gx_no_color_index ^ 1) ? gx_no_color_index : color);
187
}
188
 
189
/* Round a double value to a specified precision. */
190
double 
191
psdf_round(double v, int precision, int radix)
192
{
193
    double mul = 1;
194
    double w = v;
195
 
196
    if (w <= 0)
197
	return w;
198
    while (w < precision) {
199
	w *= radix;
200
	mul *= radix;
201
    }
202
    return (int)(w + 0.5) / mul;
203
}
204
 
205
/*
206
 * Since we only have 8 bits of color to start with, round the
207
 * values to 3 digits for more compact output.
208
 */
209
private inline double
210
round_byte_color(gx_color_index cv)
211
{
212
    return (int)((uint)cv * (1000.0 / 255.0) + 0.5) / 1000.0;
213
}
214
int
215
psdf_set_color(gx_device_vector * vdev, const gx_drawing_color * pdc,
216
	       const psdf_set_color_commands_t *ppscc)
217
{
218
    const char *setcolor;
219
 
220
    if (!gx_dc_is_pure(pdc))
221
	return_error(gs_error_rangecheck);
222
    {
223
	stream *s = gdev_vector_stream(vdev);
224
	gx_color_index color =
225
	    psdf_adjust_color_index(vdev, gx_dc_pure_color(pdc));
226
	/*
227
	 * Normally we would precompute all of v0 .. v3, but gcc 2.7.2.3
228
	 * generates incorrect code for Intel CPUs if we do this.  The code
229
	 * below is longer, but does less computation in some cases.
230
	 */
231
	double v3 = round_byte_color(color & 0xff);
232
 
233
	switch (vdev->color_info.num_components) {
234
	case 4:
235
	    /* if (v0 == 0 && v1 == 0 && v2 == 0 && ...) */
236
	    if ((color & 0xffffff00) == 0 && ppscc->setgray != 0) {
237
		v3 = 1.0 - v3;
238
		goto g;
239
	    }
240
	    pprintg4(s, "%g %g %g %g", round_byte_color(color >> 24),
241
		     round_byte_color((color >> 16) & 0xff),
242
		     round_byte_color((color >> 8) & 0xff), v3);
243
	    setcolor = ppscc->setcmykcolor;
244
	    break;
245
	case 3:
246
	    /* if (v1 == v2 && v2 == v3 && ...) */
247
	    if (!((color ^ (color >> 8)) & 0xffff) && ppscc->setgray != 0)
248
		goto g;
249
	    pprintg3(s, "%g %g %g", round_byte_color((color >> 16) & 0xff),
250
		     round_byte_color((color >> 8) & 0xff), v3);
251
	    setcolor = ppscc->setrgbcolor;
252
	    break;
253
	case 1:
254
	g:
255
	    pprintg1(s, "%g", v3);
256
	    setcolor = ppscc->setgray;
257
	    break;
258
	default:		/* can't happen */
259
	    return_error(gs_error_rangecheck);
260
	}
261
	if (setcolor)
262
	    pprints1(s, " %s\n", setcolor);
263
    }
264
    return 0;
265
}
266
 
267
/* ---------------- Binary data writing ---------------- */
268
 
269
/* Begin writing binary data. */
270
int
271
psdf_begin_binary(gx_device_psdf * pdev, psdf_binary_writer * pbw)
272
{
273
    gs_memory_t *mem = pbw->memory = pdev->v_memory;
274
 
275
    pbw->target = pdev->strm;
276
    pbw->dev = pdev;
277
    pbw->strm = 0;		/* for GC in case of failure */
278
    /* If not binary, set up the encoding stream. */
279
    if (!pdev->binary_ok) {
280
#define BUF_SIZE 100		/* arbitrary */
281
	byte *buf = gs_alloc_bytes(mem, BUF_SIZE, "psdf_begin_binary(buf)");
282
	stream_A85E_state *ss = (stream_A85E_state *)
283
	    s_alloc_state(mem, s_A85E_template.stype,
284
			  "psdf_begin_binary(stream_state)");
285
	stream *s = s_alloc(mem, "psdf_begin_binary(stream)");
286
 
287
	if (buf == 0 || ss == 0 || s == 0) {
288
	    gs_free_object(mem, s, "psdf_begin_binary(stream)");
289
	    gs_free_object(mem, ss, "psdf_begin_binary(stream_state)");
290
	    gs_free_object(mem, buf, "psdf_begin_binary(buf)");
291
	    return_error(gs_error_VMerror);
292
	}
293
	ss->template = &s_A85E_template;
294
	s_init_filter(s, (stream_state *)ss, buf, BUF_SIZE, pdev->strm);
295
#undef BUF_SIZE
296
	pbw->strm = s;
297
    } else {
298
	pbw->strm = pdev->strm;
299
    }
300
    return 0;
301
}
302
 
303
/* Add an encoding filter.  The client must have allocated the stream state, */
304
/* if any, using pdev->v_memory. */
305
int
306
psdf_encode_binary(psdf_binary_writer * pbw, const stream_template * template,
307
		   stream_state * ss)
308
{
309
    return (s_add_filter(&pbw->strm, template, ss, pbw->memory) == 0 ?
310
	    gs_note_error(gs_error_VMerror) : 0);
311
}
312
 
313
/*
314
 * Acquire parameters, and optionally set up the filter for, a DCTEncode
315
 * filter.  This is a separate procedure so it can be used to validate
316
 * filter parameters when they are set, rather than waiting until they are
317
 * used.  pbw = NULL means just set up the stream state.
318
 */
319
int
320
psdf_DCT_filter(gs_param_list *plist /* may be NULL */,
321
		stream_state /*stream_DCTE_state*/ *st,
322
		int Columns, int Rows, int Colors,
323
		psdf_binary_writer *pbw /* may be NULL */)
324
{
325
	stream_DCT_state *const ss = (stream_DCT_state *) st;
326
	gs_memory_t *mem = st->memory;
327
	jpeg_compress_data *jcdp;
328
	gs_c_param_list rcc_list;
329
	int code;
330
 
331
	/*
332
	 * "Wrap" the actual Dict or ACSDict parameter list in one that
333
	 * sets Rows, Columns, and Colors.
334
	 */
335
	gs_c_param_list_write(&rcc_list, mem);
336
	if ((code = param_write_int((gs_param_list *)&rcc_list, "Rows",
337
				    &Rows)) < 0 ||
338
	    (code = param_write_int((gs_param_list *)&rcc_list, "Columns",
339
				    &Columns)) < 0 ||
340
	    (code = param_write_int((gs_param_list *)&rcc_list, "Colors",
341
				    &Colors)) < 0
342
	    ) {
343
	    goto rcc_fail;
344
	}
345
	gs_c_param_list_read(&rcc_list);
346
	if (plist)
347
	    gs_c_param_list_set_target(&rcc_list, plist);
348
	/* Allocate space for IJG parameters. */
349
	jcdp = gs_alloc_struct_immovable(mem, jpeg_compress_data,
350
           &st_jpeg_compress_data, "zDCTE");
351
        if (jcdp == 0)
352
	    return_error(gs_error_VMerror);
353
	ss->data.compress = jcdp;
354
	jcdp->memory = ss->jpeg_memory = mem;	/* set now for allocation */
355
	if ((code = gs_jpeg_create_compress(ss)) < 0)
356
	    goto dcte_fail;	/* correct to do jpeg_destroy here */
357
	/* Read parameters from dictionary */
358
	s_DCTE_put_params((gs_param_list *)&rcc_list, ss); /* ignore errors */
359
	/* Create the filter. */
360
	jcdp->template = s_DCTE_template;
361
	/* Make sure we get at least a full scan line of input. */
362
	ss->scan_line_size = jcdp->cinfo.input_components *
363
	    jcdp->cinfo.image_width;
364
	jcdp->template.min_in_size =
365
	    max(s_DCTE_template.min_in_size, ss->scan_line_size);
366
	/* Make sure we can write the user markers in a single go. */
367
	jcdp->template.min_out_size =
368
	    max(s_DCTE_template.min_out_size, ss->Markers.size);
369
	if (pbw)
370
	    code = psdf_encode_binary(pbw, &jcdp->template, st);
371
	if (code >= 0) {
372
	    gs_c_param_list_release(&rcc_list);
373
	    return 0;
374
	}
375
    dcte_fail:
376
	gs_jpeg_destroy(ss);
377
	gs_free_object(mem, jcdp, "setup_image_compression");
378
    rcc_fail:
379
	gs_c_param_list_release(&rcc_list);
380
	return code;
381
}
382
 
383
/* Add a 2-D CCITTFax encoding filter. */
384
/* Set EndOfBlock iff the stream is not ASCII85 encoded. */
385
int
386
psdf_CFE_binary(psdf_binary_writer * pbw, int w, int h, bool invert)
387
{
388
    gs_memory_t *mem = pbw->memory;
389
    const stream_template *template = &s_CFE_template;
390
    stream_CFE_state *st =
391
	gs_alloc_struct(mem, stream_CFE_state, template->stype,
392
			"psdf_CFE_binary");
393
    int code;
394
 
395
    if (st == 0)
396
	return_error(gs_error_VMerror);
397
    (*template->set_defaults) ((stream_state *) st);
398
    st->K = -1;
399
    st->Columns = w;
400
    st->Rows = 0;
401
    st->BlackIs1 = !invert;
402
    st->EndOfBlock = pbw->strm->state->template != &s_A85E_template;
403
    code = psdf_encode_binary(pbw, template, (stream_state *) st);
404
    if (code < 0)
405
	gs_free_object(mem, st, "psdf_CFE_binary");
406
    return code;
407
}
408
 
409
/* Finish writing binary data. */
410
int
411
psdf_end_binary(psdf_binary_writer * pbw)
412
{
413
    int status = s_close_filters(&pbw->strm, pbw->target);
414
 
415
    return (status >= 0 ? 0 : gs_note_error(gs_error_ioerror));
416
}
417
 
418
/* ---------------- Overprint, Get Bits ---------------- */
419
 
420
/*
421
 * High level devices cannot perform get_bits or get_bits_rectangle
422
 * operations, for obvious reasons.
423
 */
424
int
425
psdf_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
426
{
427
    return_error(gs_error_unregistered);
428
}
429
 
430
int
431
psdf_get_bits_rectangle(
432
    gx_device *             dev,
433
    const gs_int_rect *     prect,
434
    gs_get_bits_params_t *  params,
435
    gs_int_rect **          unread )
436
{
437
    return_error(gs_error_unregistered);
438
}
439
 
440
/*
441
 * Create compositor procedure for PostScript/PDF writer. Since these
442
 * devices directly support overprint (and have access to the imager
443
 * state), no compositor is required for overprint support. Hence, this
444
 * routine just recognizes and discards invocations of the overprint
445
 * compositor.
446
 */
447
int
448
psdf_create_compositor(
449
    gx_device *             dev,
450
    gx_device **            pcdev,
451
    const gs_composite_t *  pct,
452
    gs_imager_state * pis,
453
    gs_memory_t *           mem )
454
{
455
    if (gs_is_overprint_compositor(pct)) {
456
        *pcdev = dev;
457
        return 0;
458
    } else
459
        return gx_default_create_compositor(dev, pcdev, pct, pis, mem);
460
}