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) 1999, 2000, 2001 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: gdevpdfg.c,v 1.68 2005/09/12 11:34:50 leonardo Exp $ */
18
/* Graphics state management for pdfwrite driver */
19
#include "math_.h"
20
#include "string_.h"
21
#include "memory_.h"
22
#include "gx.h"
23
#include "gserrors.h"
24
#include "gsfunc0.h"
25
#include "gsstate.h"
26
#include "gxbitmap.h"		/* for gxhttile.h in gzht.h */
27
#include "gxdht.h"
28
#include "gxfarith.h"		/* for gs_sin/cos_degrees */
29
#include "gxfmap.h"
30
#include "gxht.h"
31
#include "gxistate.h"
32
#include "gxdcolor.h"
33
#include "gxpcolor.h"
34
#include "gsptype2.h"
35
#include "gzht.h"
36
#include "gdevpdfx.h"
37
#include "gdevpdfg.h"
38
#include "gdevpdfo.h"
39
#include "szlibx.h"
40
 
41
/* ---------------- Miscellaneous ---------------- */
42
 
43
/* Save the viewer's graphic state. */
44
int
45
pdf_save_viewer_state(gx_device_pdf *pdev, stream *s)
46
{
47
    const int i = pdev->vgstack_depth;
48
 
49
    if (pdev->vgstack_depth >= count_of(pdev->vgstack))
50
	return_error(gs_error_unregistered); /* Must not happen. */
51
    pdev->vgstack[i].transfer_ids[0] = pdev->transfer_ids[0];
52
    pdev->vgstack[i].transfer_ids[1] = pdev->transfer_ids[1];
53
    pdev->vgstack[i].transfer_ids[2] = pdev->transfer_ids[2];
54
    pdev->vgstack[i].transfer_ids[3] = pdev->transfer_ids[3];
55
    pdev->vgstack[i].transfer_not_identity = pdev->transfer_not_identity;
56
    pdev->vgstack[i].opacity_alpha = pdev->state.opacity.alpha;
57
    pdev->vgstack[i].shape_alpha = pdev->state.shape.alpha;
58
    pdev->vgstack[i].blend_mode = pdev->state.blend_mode;
59
    pdev->vgstack[i].halftone_id = pdev->halftone_id;
60
    pdev->vgstack[i].black_generation_id = pdev->black_generation_id;
61
    pdev->vgstack[i].undercolor_removal_id = pdev->undercolor_removal_id;
62
    pdev->vgstack[i].overprint_mode = pdev->overprint_mode;
63
    pdev->vgstack[i].smoothness = pdev->state.smoothness;
64
    pdev->vgstack[i].flatness = pdev->state.flatness;
65
    pdev->vgstack[i].text_knockout = pdev->state.text_knockout;
66
    pdev->vgstack[i].fill_overprint = pdev->fill_overprint;
67
    pdev->vgstack[i].stroke_overprint = pdev->stroke_overprint;
68
    pdev->vgstack[i].stroke_adjust = pdev->state.stroke_adjust;
69
    pdev->vgstack[i].fill_used_process_color = pdev->fill_used_process_color;
70
    pdev->vgstack[i].stroke_used_process_color = pdev->stroke_used_process_color;
71
    pdev->vgstack[i].saved_fill_color = pdev->saved_fill_color;
72
    pdev->vgstack[i].saved_stroke_color = pdev->saved_stroke_color;
73
    pdev->vgstack[i].line_params = pdev->state.line_params;
74
    pdev->vgstack[i].line_params.dash.pattern = 0; /* Use pdev->dash_pattern instead. */
75
    memcpy(pdev->vgstack[i].dash_pattern, pdev->dash_pattern, 
76
		sizeof(pdev->vgstack[i].dash_pattern));
77
    pdev->vgstack_depth++;
78
    if (s)
79
	stream_puts(s, "q\n");
80
    return 0;
81
}
82
 
83
/* Load the viewer's graphic state. */
84
private void
85
pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s)
86
{   
87
    pdev->transfer_ids[0] = s->transfer_ids[0];
88
    pdev->transfer_ids[1] = s->transfer_ids[1];
89
    pdev->transfer_ids[2] = s->transfer_ids[2];
90
    pdev->transfer_ids[3] = s->transfer_ids[3];
91
    pdev->transfer_not_identity = s->transfer_not_identity;
92
    pdev->state.opacity.alpha = s->opacity_alpha;
93
    pdev->state.shape.alpha = s->shape_alpha;
94
    pdev->state.blend_mode = s->blend_mode;
95
    pdev->halftone_id = s->halftone_id;
96
    pdev->black_generation_id = s->black_generation_id;
97
    pdev->undercolor_removal_id = s->undercolor_removal_id;
98
    pdev->overprint_mode = s->overprint_mode;
99
    pdev->state.smoothness = s->smoothness;
100
    pdev->state.flatness = s->flatness;
101
    pdev->state.text_knockout = s->text_knockout;
102
    pdev->fill_overprint = s->fill_overprint;
103
    pdev->stroke_overprint = s->stroke_overprint;
104
    pdev->state.stroke_adjust = s->stroke_adjust;
105
    pdev->fill_used_process_color = s->fill_used_process_color;
106
    pdev->stroke_used_process_color = s->stroke_used_process_color;
107
    pdev->saved_fill_color = s->saved_fill_color;
108
    pdev->saved_stroke_color = s->saved_stroke_color;
109
    pdev->state.line_params = s->line_params;
110
    memcpy(pdev->dash_pattern, s->dash_pattern,
111
		sizeof(s->dash_pattern));
112
}
113
 
114
 
115
/* Restore the viewer's graphic state. */
116
int
117
pdf_restore_viewer_state(gx_device_pdf *pdev, stream *s)
118
{   const int i = --pdev->vgstack_depth;
119
 
120
    if (i < pdev->vgstack_bottom || i < 0)
121
	return_error(gs_error_unregistered); /* Must not happen. */
122
    if (s)
123
	stream_puts(s, "Q\n");
124
    pdf_load_viewer_state(pdev, pdev->vgstack + i);
125
    return 0;
126
}
127
 
128
/* Set initial color. */
129
void
130
pdf_set_initial_color(gx_device_pdf * pdev, gx_hl_saved_color *saved_fill_color,
131
		    gx_hl_saved_color *saved_stroke_color,
132
		    bool *fill_used_process_color, bool *stroke_used_process_color)
133
{
134
    gx_device_color black;
135
 
136
    pdev->black = gx_device_black((gx_device *)pdev);
137
    pdev->white = gx_device_white((gx_device *)pdev);
138
    set_nonclient_dev_color(&black, pdev->black);
139
    gx_hld_save_color(NULL, &black, saved_fill_color);
140
    gx_hld_save_color(NULL, &black, saved_stroke_color);
141
    *fill_used_process_color = true;
142
    *stroke_used_process_color = true;
143
}
144
 
145
/* Prepare intitial values for viewer's graphics state parameters. */
146
private void
147
pdf_viewer_state_from_imager_state_aux(pdf_viewer_state *pvs, const gs_imager_state *pis)
148
{
149
    pvs->transfer_not_identity = 
150
	    (pis->set_transfer.red   != NULL ? pis->set_transfer.red->proc   != gs_identity_transfer : 0) * 1 +
151
	    (pis->set_transfer.green != NULL ? pis->set_transfer.green->proc != gs_identity_transfer : 0) * 2 +
152
	    (pis->set_transfer.blue  != NULL ? pis->set_transfer.blue->proc  != gs_identity_transfer : 0) * 4 +
153
	    (pis->set_transfer.gray  != NULL ? pis->set_transfer.gray->proc  != gs_identity_transfer : 0) * 8;
154
    pvs->transfer_ids[0] = (pis->set_transfer.red != NULL ? pis->set_transfer.red->id : 0);
155
    pvs->transfer_ids[1] = (pis->set_transfer.green != NULL ? pis->set_transfer.green->id : 0);
156
    pvs->transfer_ids[2] = (pis->set_transfer.blue != NULL ? pis->set_transfer.blue->id : 0);
157
    pvs->transfer_ids[3] = (pis->set_transfer.gray != NULL ? pis->set_transfer.gray->id : 0);
158
    pvs->opacity_alpha = pis->opacity.alpha;
159
    pvs->shape_alpha = pis->shape.alpha;
160
    pvs->blend_mode = pis->blend_mode;
161
    pvs->halftone_id = (pis->dev_ht != 0 ? pis->dev_ht->id : 0);
162
    pvs->black_generation_id = (pis->black_generation != 0 ? pis->black_generation->id : 0);
163
    pvs->undercolor_removal_id = (pis->undercolor_removal != 0 ? pis->undercolor_removal->id : 0);
164
    pvs->overprint_mode = 0;
165
    pvs->smoothness = pis->smoothness;
166
    pvs->text_knockout = pis->text_knockout;
167
    pvs->fill_overprint = false;
168
    pvs->stroke_overprint = false;
169
    pvs->stroke_adjust = false;
170
    pvs->line_params.half_width = 0.5;
171
    pvs->line_params.cap = 0;
172
    pvs->line_params.join = 0;
173
    pvs->line_params.curve_join = 0;
174
    pvs->line_params.miter_limit = 10.0;
175
    pvs->line_params.miter_check = 0;
176
    pvs->line_params.dot_length = pis->line_params.dot_length;
177
    pvs->line_params.dot_length_absolute = pis->line_params.dot_length_absolute;
178
    pvs->line_params.dot_orientation = pis->line_params.dot_orientation;
179
    memset(&pvs->line_params.dash, 0 , sizeof(pvs->line_params.dash));
180
    memset(pvs->dash_pattern, 0, sizeof(pvs->dash_pattern));
181
}
182
 
183
/* Copy viewer state from images state. */
184
void
185
pdf_viewer_state_from_imager_state(gx_device_pdf * pdev, 
186
	const gs_imager_state *pis, const gx_device_color *pdevc)
187
{
188
    pdf_viewer_state vs;
189
 
190
    pdf_viewer_state_from_imager_state_aux(&vs, pis);
191
    gx_hld_save_color(pis, pdevc, &vs.saved_fill_color);
192
    gx_hld_save_color(pis, pdevc, &vs.saved_stroke_color);
193
    pdf_load_viewer_state(pdev, &vs);
194
}
195
 
196
/* Prepare intitial values for viewer's graphics state parameters. */
197
void
198
pdf_prepare_initial_viewer_state(gx_device_pdf * pdev, const gs_imager_state *pis)
199
{
200
    /* Parameter values, which are specified in PDF spec, are set here.
201
     * Parameter values, which are specified in PDF spec as "installation dependent",
202
     * are set here to intial values used with PS interpreter.
203
     * This allows to write differences to the output file
204
     * and skip initial values.
205
     */
206
 
207
    pdf_set_initial_color(pdev, &pdev->vg_initial.saved_fill_color, &pdev->vg_initial.saved_stroke_color,
208
	    &pdev->vg_initial.fill_used_process_color, &pdev->vg_initial.stroke_used_process_color);
209
    pdf_viewer_state_from_imager_state_aux(&pdev->vg_initial, pis);
210
    pdev->vg_initial_set = true;
211
    /*
212
     * Some parameters listed in PDF spec are missed here :
213
     * text state - it is initialized per page.
214
     * rendering intent - not sure why, fixme.
215
     */
216
}
217
 
218
/* Reset the graphics state parameters to initial values. */
219
/* Used if pdf_prepare_initial_viewer_state was not callad. */
220
private void
221
pdf_reset_graphics_old(gx_device_pdf * pdev)
222
{
223
 
224
    pdf_set_initial_color(pdev, &pdev->saved_fill_color, &pdev->saved_stroke_color, 
225
				&pdev->fill_used_process_color, &pdev->stroke_used_process_color);
226
    pdev->state.flatness = -1;
227
    {
228
	static const gx_line_params lp_initial = {
229
	    gx_line_params_initial
230
	};
231
 
232
	pdev->state.line_params = lp_initial;
233
    }
234
    pdev->fill_overprint = false;
235
    pdev->stroke_overprint = false;
236
    pdf_reset_text(pdev);
237
}
238
 
239
/* Reset the graphics state parameters to initial values. */
240
void
241
pdf_reset_graphics(gx_device_pdf * pdev)
242
{
243
    if (pdev->vg_initial_set)
244
	pdf_load_viewer_state(pdev, &pdev->vg_initial);
245
    else
246
	pdf_reset_graphics_old(pdev);
247
    pdf_reset_text(pdev);
248
}
249
 
250
/* Write client color. */
251
private int
252
pdf_write_ccolor(gx_device_pdf * pdev, const gs_imager_state * pis, 
253
	        const gs_client_color *pcc)
254
{   
255
    int i, n = gx_hld_get_number_color_components(pis);
256
 
257
    pprintg1(pdev->strm, "%g", psdf_round(pcc->paint.values[0], 255, 8));
258
    for (i = 1; i < n; i++) {
259
	pprintg1(pdev->strm, " %g", psdf_round(pcc->paint.values[i], 255, 8));
260
    }
261
    return 0;
262
}
263
 
264
 
265
/* Set the fill or stroke color. */
266
private int
267
pdf_reset_color(gx_device_pdf * pdev, const gs_imager_state * pis, 
268
	        const gx_drawing_color *pdc, gx_hl_saved_color * psc,
269
		bool *used_process_color,
270
		const psdf_set_color_commands_t *ppscc)
271
{
272
    int code;
273
    gx_hl_saved_color temp;
274
    bool process_color;
275
    const gs_color_space *pcs, *pcs2;
276
    const gs_client_color *pcc; /* fixme: not needed due to gx_hld_get_color_component. */
277
    cos_value_t cs_value;
278
    const char *command;
279
    int code1 = 0;
280
    gs_color_space_index csi;
281
 
282
    if (pdev->skip_colors)
283
	return 0;
284
    process_color = !gx_hld_save_color(pis, pdc, &temp);
285
    /* Since pdfwrite never applies halftones and patterns, but monitors
286
     * halftone/pattern IDs separately, we don't need to compare
287
     * halftone/pattern bodies here.
288
     */
289
    if (gx_hld_saved_color_equal(&temp, psc))
290
	return 0;
291
    /*
292
     * In principle, we can set colors in either stream or text
293
     * context.  However, since we currently enclose all text
294
     * strings inside a gsave/grestore, this causes us to lose
295
     * track of the color when we leave text context.  Therefore,
296
     * we require stream context for setting colors.
297
     */
298
    code = pdf_open_page(pdev, PDF_IN_STREAM);
299
    if (code < 0)
300
	return code;
301
    switch (gx_hld_get_color_space_and_ccolor(pis, pdc, &pcs, &pcc)) {
302
	case non_pattern_color_space:
303
	    switch (gs_color_space_get_index(pcs)) {
304
		case gs_color_space_index_DeviceGray:
305
		    command = ppscc->setgray; 
306
		    break;
307
		case gs_color_space_index_DeviceRGB:
308
		    command = ppscc->setrgbcolor; 
309
		    break;
310
		case gs_color_space_index_DeviceCMYK:
311
		    command = ppscc->setcmykcolor; 
312
		    break;
313
		case gs_color_space_index_Indexed:
314
		    if (pdev->CompatibilityLevel <= 1.2) {
315
			pcs2 = (const gs_color_space *)&pcs->params.indexed.base_space;
316
			csi = gs_color_space_get_index(pcs2);
317
			if (csi == gs_color_space_index_Separation) {
318
			    pcs2 = (const gs_color_space *)&pcs2->params.separation.alt_space;
319
			    goto check_pcs2;
320
			}
321
			goto check_pcs2;
322
		    }
323
		    goto scn;
324
		case gs_color_space_index_Separation:
325
		    if (pdev->CompatibilityLevel <= 1.2) {
326
			pcs2 = (const gs_color_space *)&pcs->params.separation.alt_space;
327
			check_pcs2:
328
			csi = gs_color_space_get_index(pcs2);
329
			switch(gs_color_space_get_index(pcs2)) {
330
			    case gs_color_space_index_DevicePixel :
331
			    case gs_color_space_index_DeviceN:
332
			    case gs_color_space_index_CIEICC:
333
				goto write_process_color;
334
			    default: 
335
				DO_NOTHING;
336
			}
337
		    }
338
		    goto scn;
339
		case gs_color_space_index_CIEICC:
340
		case gs_color_space_index_DevicePixel:
341
		case gs_color_space_index_DeviceN:
342
		    if (pdev->CompatibilityLevel <= 1.2)
343
	    		goto write_process_color;
344
		    goto scn;
345
		default :
346
	        scn:
347
		    command = ppscc->setcolorn;
348
		    if (!gx_hld_saved_color_same_cspace(&temp, psc)) {
349
			code = pdf_color_space(pdev, &cs_value, NULL, pcs,
350
					&pdf_color_space_names, true);
351
			/* fixme : creates redundant PDF objects. */
352
			if (code == gs_error_rangecheck) {
353
			    /* The color space can't write to PDF. */
354
			    goto write_process_color;
355
			}
356
			if (code < 0)
357
			    return code;
358
			code = cos_value_write(&cs_value, pdev);
359
			if (code < 0)
360
			    return code;
361
			pprints1(pdev->strm, " %s\n", ppscc->setcolorspace);
362
		    } else if (*used_process_color)
363
			goto write_process_color;
364
		    break;
365
	    }
366
	    *used_process_color = false;
367
	    code = pdf_write_ccolor(pdev, pis, pcc);
368
	    if (code < 0)
369
		return code;
370
	    pprints1(pdev->strm, " %s\n", command);
371
	    break;
372
	case pattern_color_sapce:
373
	    {	pdf_resource_t *pres;
374
 
375
		if (pdc->type == gx_dc_type_pattern)
376
		    code = pdf_put_colored_pattern(pdev, pdc, pcs,
377
				ppscc, pis->have_pattern_streams, &pres);
378
		else if (pdc->type == &gx_dc_pure_masked) {
379
		    code = pdf_put_uncolored_pattern(pdev, pdc, pcs, 
380
				ppscc, pis->have_pattern_streams, &pres);
381
		    if (code < 0 || pres == 0)
382
			return code;
383
		    if (pis->have_pattern_streams)
384
			code = pdf_write_ccolor(pdev, pis, pcc);
385
		} else if (pdc->type == &gx_dc_pattern2) {
386
		    if (pdev->CompatibilityLevel <= 1.2)
387
	    		return_error(gs_error_rangecheck);
388
		    code1 = pdf_put_pattern2(pdev, pdc, ppscc, &pres);
389
		} else
390
		    return_error(gs_error_rangecheck);
391
		if (code < 0)
392
		    return code;
393
		cos_value_write(cos_resource_value(&cs_value, pres->object), pdev);
394
		pprints1(pdev->strm, " %s\n", ppscc->setcolorn);
395
		code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
396
		if (code < 0)
397
		    return code;
398
	    }
399
	    *used_process_color = false;
400
	    break;
401
	default: /* must not happen. */
402
	case use_process_color:
403
	write_process_color:
404
	    code = psdf_set_color((gx_device_vector *)pdev, pdc, ppscc);
405
	    if (code < 0)
406
		return code;
407
	    *used_process_color = true;
408
    }
409
    *psc = temp;
410
    return code1;
411
}
412
int
413
pdf_set_drawing_color(gx_device_pdf * pdev, const gs_imager_state * pis,
414
		      const gx_drawing_color *pdc,
415
		      gx_hl_saved_color * psc,
416
		      bool *used_process_color,
417
		      const psdf_set_color_commands_t *ppscc)
418
{
419
    return pdf_reset_color(pdev, pis, pdc, psc, used_process_color, ppscc);
420
}
421
int
422
pdf_set_pure_color(gx_device_pdf * pdev, gx_color_index color,
423
		   gx_hl_saved_color * psc,
424
    		   bool *used_process_color,
425
		   const psdf_set_color_commands_t *ppscc)
426
{
427
    gx_drawing_color dcolor;
428
 
429
    set_nonclient_dev_color(&dcolor, color);
430
    return pdf_reset_color(pdev, NULL, &dcolor, psc, used_process_color, ppscc);
431
}
432
 
433
/*
434
 * Convert a string into cos name.
435
 */
436
int
437
pdf_string_to_cos_name(gx_device_pdf *pdev, const byte *str, uint len, 
438
		       cos_value_t *pvalue)
439
{
440
    byte *chars = gs_alloc_string(pdev->pdf_memory, len + 1, 
441
                                  "pdf_string_to_cos_name");
442
 
443
    if (chars == 0)
444
	return_error(gs_error_VMerror);
445
    chars[0] = '/';
446
    memcpy(chars + 1, str, len);
447
    cos_string_value(pvalue, chars, len + 1);
448
    return 0;
449
}
450
 
451
/* ---------------- Graphics state updating ---------------- */
452
 
453
/* ------ Functions ------ */
454
 
455
/* Define the maximum size of a Function reference. */
456
#define MAX_FN_NAME_CHARS 9	/* /Default, /Identity */
457
#define MAX_FN_CHARS max(MAX_REF_CHARS + 4, MAX_FN_NAME_CHARS)
458
 
459
/*
460
 * Create and write a Function for a gx_transfer_map.  We use this for
461
 * transfer, BG, and UCR functions.  If check_identity is true, check for
462
 * an identity map.  Return 1 if the map is the identity map, otherwise
463
 * return 0.
464
 */
465
private data_source_proc_access(transfer_map_access); /* check prototype */
466
private int
467
transfer_map_access(const gs_data_source_t *psrc, ulong start, uint length,
468
		    byte *buf, const byte **ptr)
469
{
470
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
471
    uint i;
472
 
473
    if (ptr)
474
	*ptr = buf;
475
    for (i = 0; i < length; ++i)
476
	buf[i] = frac2byte(map->values[(uint)start + i]);
477
    return 0;
478
}
479
private int
480
transfer_map_access_signed(const gs_data_source_t *psrc,
481
			   ulong start, uint length,
482
			   byte *buf, const byte **ptr)
483
{
484
    /* To prevent numeric errors, we need to map 0 to an integer. 
485
     * We can't apply a general expression, because Decode isn't accessible here.
486
     * Assuming this works for UCR only.
487
     * Assuming the range of UCR is always [-1, 1].
488
     * Assuming BitsPerSample = 8.
489
     */
490
    const gx_transfer_map *map = (const gx_transfer_map *)psrc->data.str.data;
491
    uint i;
492
 
493
    *ptr = buf;
494
    for (i = 0; i < length; ++i)
495
	buf[i] = (byte)
496
	    ((frac2float(map->values[(uint)start + i]) + 1) * 127);
497
    return 0;
498
}
499
private int
500
pdf_write_transfer_map(gx_device_pdf *pdev, const gx_transfer_map *map,
501
		       int range0, bool check_identity,
502
		       const char *key, char *ids)
503
{
504
    gs_memory_t *mem = pdev->pdf_memory;
505
    gs_function_Sd_params_t params;
506
    static const float domain01[2] = { 0, 1 };
507
    static const int size = transfer_map_size;
508
    float range01[2], decode[2];
509
    gs_function_t *pfn;
510
    long id;
511
    int code;
512
 
513
    if (map == 0) {
514
	*ids = 0;		/* no map */
515
	return 1;
516
    }
517
    if (check_identity) {
518
	/* Check for an identity map. */
519
	int i;
520
 
521
	if (map->proc == gs_identity_transfer)
522
	    i = transfer_map_size;
523
	else
524
 	    for (i = 0; i < transfer_map_size; ++i) {
525
 		fixed d = map->values[i] - bits2frac(i, log2_transfer_map_size);
526
 		if (any_abs(d) > fixed_epsilon) /* ignore small noise */
527
  		    break;
528
 	    }
529
	if (i == transfer_map_size) {
530
	    strcpy(ids, key);
531
	    strcat(ids, "/Identity");
532
	    return 1;
533
	}
534
    }
535
    params.m = 1;
536
    params.Domain = domain01;
537
    params.n = 1;
538
    range01[0] = (float)range0, range01[1] = 1.0;
539
    params.Range = range01;
540
    params.Order = 1;
541
    params.DataSource.access =
542
	(range0 < 0 ? transfer_map_access_signed : transfer_map_access);
543
    params.DataSource.data.str.data = (const byte *)map; /* bogus */
544
    /* DataSource */
545
    params.BitsPerSample = 8;	/* could be 16 */
546
    params.Encode = 0;
547
    if (range01[0] < 0 && range01[1] > 0) {
548
	/* This works for UCR only.
549
	 * Map 0 to an integer. 
550
	 * Rather the range of UCR is always [-1, 1], 
551
	 * we prefer a general expression. 
552
	 */
553
	int r0 = (int)( -range01[0] * ((1 << params.BitsPerSample) - 1) 
554
			/ (range01[1] - range01[0]) ); /* Round down. */
555
	float r1 = r0 * range01[1] / -range01[0]; /* r0 + r1 <= (1 << params.BitsPerSample) - 1 */
556
 
557
	decode[0] = range01[0];
558
	decode[1] = range01[0] + (range01[1] - range01[0]) * ((1 << params.BitsPerSample) - 1) 
559
				    / (r0 + r1);
560
	params.Decode = decode;
561
    } else
562
    	params.Decode = 0;
563
    params.Size = &size;
564
    code = gs_function_Sd_init(&pfn, &params, mem);
565
    if (code < 0)
566
	return code;
567
    code = pdf_write_function(pdev, pfn, &id);
568
    gs_function_free(pfn, false, mem);
569
    if (code < 0)
570
	return code;
571
    sprintf(ids, "%s%s%ld 0 R", key, (key[0] && key[0] != ' ' ? " " : ""), id);
572
    return 0;
573
}
574
private int
575
pdf_write_transfer(gx_device_pdf *pdev, const gx_transfer_map *map,
576
		   const char *key, char *ids)
577
{
578
    return pdf_write_transfer_map(pdev, map, 0, true, key, ids);
579
}
580
 
581
/* ------ Halftones ------ */
582
 
583
/*
584
 * Recognize the predefined PDF halftone functions.  Note that because the
585
 * corresponding PostScript functions use single-precision floats, the
586
 * functions used for testing must do the same in order to get identical
587
 * results.  Currently we only do this for a few of the functions.
588
 */
589
#define HT_FUNC(name, expr)\
590
  private floatp name(floatp xd, floatp yd) {\
591
    float x = (float)xd, y = (float)yd;\
592
    return d2f(expr);\
593
  }
594
 
595
/*
596
 * In most versions of gcc (e.g., 2.7.2.3, 2.95.4), return (float)xxx
597
 * doesn't actually do the coercion.  Force this here.  Note that if we
598
 * use 'inline', it doesn't work.
599
 */
600
private float
601
d2f(floatp d)
602
{
603
    float f = (float)d;
604
    return f;
605
}
606
private floatp
607
ht_Round(floatp xf, floatp yf)
608
{
609
    float x = (float)xf, y = (float)yf;
610
    float xabs = fabs(x), yabs = fabs(y);
611
 
612
    if (d2f(xabs + yabs) <= 1)
613
	return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
614
    xabs -= 1, yabs -= 1;
615
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
616
}
617
private floatp
618
ht_Diamond(floatp xf, floatp yf)
619
{
620
    float x = (float)xf, y = (float)yf;
621
    float xabs = fabs(x), yabs = fabs(y);
622
 
623
    if (d2f(xabs + yabs) <= 0.75)
624
	return d2f(1 - d2f(d2f(x * x) + d2f(y * y)));
625
    if (d2f(xabs + yabs) <= d2f(1.23))
626
	return d2f(1 - d2f(d2f(d2f(0.85) * xabs) + yabs));
627
    xabs -= 1, yabs -= 1;
628
    return d2f(d2f(d2f(xabs * xabs) + d2f(yabs * yabs)) - 1);
629
}
630
private floatp
631
ht_Ellipse(floatp xf, floatp yf)
632
{
633
    float x = (float)xf, y = (float)yf;
634
    float xabs = fabs(x), yabs = fabs(y);
635
    /*
636
     * The PDF Reference, 2nd edition, incorrectly specifies the
637
     * computation w = 4 * |x| + 3 * |y| - 3.  The PostScript code in the
638
     * same book correctly implements w = 3 * |x| + 4 * |y| - 3.
639
     */
640
    float w = (float)(d2f(d2f(3 * xabs) + d2f(4 * yabs)) - 3);
641
 
642
    if (w < 0) {
643
	yabs /= 0.75;
644
	return d2f(1 - d2f((d2f(x * x) + d2f(yabs * yabs)) / 4));
645
    }
646
    if (w > 1) {
647
	xabs = 1 - xabs, yabs = d2f(1 - yabs) / 0.75;
648
	return d2f(d2f((d2f(xabs * xabs) + d2f(yabs * yabs)) / 4) - 1);
649
    }
650
    return d2f(0.5 - w);
651
}
652
/*
653
 * Most of these are recognized properly even without d2f.  We've only
654
 * added d2f where it apparently makes a difference.
655
 */
656
private float
657
d2fsin_d(double x) {
658
    return d2f(gs_sin_degrees(d2f(x)));
659
}
660
private float
661
d2fcos_d(double x) {
662
    return d2f(gs_cos_degrees(d2f(x)));
663
}
664
HT_FUNC(ht_EllipseA, 1 - (x * x + 0.9 * y * y))
665
HT_FUNC(ht_InvertedEllipseA, x * x + 0.9 * y * y - 1)
666
HT_FUNC(ht_EllipseB, 1 - sqrt(x * x + 0.625 * y * y))
667
HT_FUNC(ht_EllipseC, 1 - (0.9 * x * x + y * y))
668
HT_FUNC(ht_InvertedEllipseC, 0.9 * x * x + y * y - 1)
669
HT_FUNC(ht_Line, -fabs((x - x) + y)) /* quiet compiler (unused variable x) */
670
HT_FUNC(ht_LineX, (y - y) + x) /* quiet compiler (unused variable y) */
671
HT_FUNC(ht_LineY, (x - x) + y) /* quiet compiler (unused variable x) */
672
HT_FUNC(ht_Square, -max(fabs(x), fabs(y)))
673
HT_FUNC(ht_Cross, -min(fabs(x), fabs(y)))
674
HT_FUNC(ht_Rhomboid, (0.9 * fabs(x) + fabs(y)) / 2)
675
HT_FUNC(ht_DoubleDot, (d2fsin_d(x * 360) + d2fsin_d(y * 360)) / 2)
676
HT_FUNC(ht_InvertedDoubleDot, -(d2fsin_d(x * 360) + d2fsin_d(y * 360)) / 2)
677
HT_FUNC(ht_SimpleDot, 1 - d2f(d2f(x * x) + d2f(y * y)))
678
HT_FUNC(ht_InvertedSimpleDot, d2f(d2f(x * x) + d2f(y * y)) - 1)
679
HT_FUNC(ht_CosineDot, (d2fcos_d(x * 180) + d2fcos_d(y * 180)) / 2)
680
HT_FUNC(ht_Double, (d2fsin_d(x * 180) + d2fsin_d(y * 360)) / 2)
681
HT_FUNC(ht_InvertedDouble, -(d2fsin_d(x * 180) + d2fsin_d(y * 360)) / 2)
682
typedef struct ht_function_s {
683
    const char *fname;
684
    floatp (*proc)(floatp, floatp);
685
} ht_function_t;
686
private const ht_function_t ht_functions[] = {
687
    {"Round", ht_Round},
688
    {"Diamond", ht_Diamond},
689
    {"Ellipse", ht_Ellipse},
690
    {"EllipseA", ht_EllipseA},
691
    {"InvertedEllipseA", ht_InvertedEllipseA},
692
    {"EllipseB", ht_EllipseB},
693
    {"EllipseC", ht_EllipseC},
694
    {"InvertedEllipseC", ht_InvertedEllipseC},
695
    {"Line", ht_Line},
696
    {"LineX", ht_LineX},
697
    {"LineY", ht_LineY},
698
    {"Square", ht_Square},
699
    {"Cross", ht_Cross},
700
    {"Rhomboid", ht_Rhomboid},
701
    {"DoubleDot", ht_DoubleDot},
702
    {"InvertedDoubleDot", ht_InvertedDoubleDot},
703
    {"SimpleDot", ht_SimpleDot},
704
    {"InvertedSimpleDot", ht_InvertedSimpleDot},
705
    {"CosineDot", ht_CosineDot},
706
    {"Double", ht_Double},
707
    {"InvertedDouble", ht_InvertedDouble}
708
};
709
 
710
/* Write each kind of halftone. */
711
private int
712
pdf_write_spot_function(gx_device_pdf *pdev, const gx_ht_order *porder,
713
			long *pid)
714
{
715
    /****** DOESN'T HANDLE STRIP HALFTONES ******/
716
    int w = porder->width, h = porder->height;
717
    uint num_bits = porder->num_bits;
718
    gs_function_Sd_params_t params;
719
    static const float domain_spot[4] = { -1, 1, -1, 1 };
720
    static const float range_spot[4] = { -1, 1 };
721
    int size[2];
722
    gs_memory_t *mem = pdev->pdf_memory;
723
    /*
724
     * Even though the values are logically ushort, we must always store
725
     * them in big-endian order, so we access them as bytes.
726
     */
727
    byte *values;
728
    gs_function_t *pfn;
729
    uint i;
730
    int code = 0;
731
 
732
    params.m = 2;
733
    params.Domain = domain_spot;
734
    params.n = 1;
735
    params.Range = range_spot;
736
    params.Order = 0;		/* default */
737
    /*
738
     * We could use 8, 16, or 32 bits per sample to save space, but for
739
     * simplicity, we always use 16.
740
     */
741
    if (num_bits > 0x10000)
742
	return_error(gs_error_rangecheck);
743
    params.BitsPerSample = 16;
744
    params.Encode = 0;
745
    /*
746
     * The default Decode array maps the actual data values [1 .. w*h] to a
747
     * sub-interval of the Range, but that's OK, since all that matters is
748
     * the relative values, not the absolute values.
749
     */
750
    params.Decode = 0;
751
    size[0] = w;
752
    size[1] = h;
753
    params.Size = size;
754
    /* Create the (temporary) threshold array. */
755
    values = gs_alloc_byte_array(mem, num_bits, 2, "pdf_write_spot_function");
756
    if (values == 0)
757
	return_error(gs_error_VMerror);
758
    for (i = 0; i < num_bits; ++i) {
759
	gs_int_point pt;
760
	int value;
761
 
762
	if ((code = porder->procs->bit_index(porder, i, &pt)) < 0)
763
	    break;
764
	value = pt.y * w + pt.x;
765
	/* Always store the values in big-endian order. */
766
	values[i * 2] = (byte)(value >> 8);
767
	values[i * 2 + 1] = (byte)value;
768
    }
769
    data_source_init_bytes(&params.DataSource, (const byte *)values,
770
			   sizeof(*values) * num_bits);
771
    if (code >= 0 &&
772
	(code = gs_function_Sd_init(&pfn, &params, mem)) >= 0
773
	) {
774
	code = pdf_write_function(pdev, pfn, pid);
775
	gs_function_free(pfn, false, mem);
776
    }
777
    gs_free_object(mem, values, "pdf_write_spot_function");
778
    return code;
779
}
780
private int
781
pdf_write_spot_halftone(gx_device_pdf *pdev, const gs_spot_halftone *psht,
782
			const gx_ht_order *porder, long *pid)
783
{
784
    char trs[17 + MAX_FN_CHARS + 1];
785
    int code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
786
				  trs);
787
    long id, spot_id;
788
    stream *s;
789
    int i = countof(ht_functions);
790
    gs_memory_t *mem = pdev->pdf_memory;
791
 
792
    if (code < 0)
793
	return code;
794
    /*
795
     * See if we can recognize the spot function, by comparing its sampled
796
     * values against those in the order.
797
     */
798
    {	gs_screen_enum senum;
799
	gx_ht_order order;
800
	int code;
801
 
802
	order = *porder;
803
	code = gs_screen_order_alloc(&order, mem);
804
	if (code < 0)
805
	    goto notrec;
806
	for (i = 0; i < countof(ht_functions); ++i) {
807
	    floatp (*spot_proc)(floatp, floatp) = ht_functions[i].proc;
808
	    gs_point pt;
809
 
810
	    gs_screen_enum_init_memory(&senum, &order, NULL, &psht->screen,
811
				       mem);
812
	    while ((code = gs_screen_currentpoint(&senum, &pt)) == 0 &&
813
		   gs_screen_next(&senum, spot_proc(pt.x, pt.y)) >= 0)
814
		DO_NOTHING;
815
	    if (code < 0)
816
		continue;
817
	    /* Compare the bits and levels arrays. */
818
	    if (memcmp(order.levels, porder->levels,
819
		       order.num_levels * sizeof(*order.levels)))
820
		continue;
821
	    if (memcmp(order.bit_data, porder->bit_data,
822
		       order.num_bits * porder->procs->bit_data_elt_size))
823
		continue;
824
	    /* We have a match. */
825
	    break;
826
	}
827
	gx_ht_order_release(&order, mem, false);
828
    }
829
 notrec:
830
    if (i == countof(ht_functions)) {
831
	/* Create and write a Function for the spot function. */
832
	pdf_write_spot_function(pdev, porder, &spot_id);
833
    }	
834
    *pid = id = pdf_begin_separate(pdev);
835
    s = pdev->strm;
836
    /* Use the original, requested frequency and angle. */
837
    pprintg2(s, "<</Type/Halftone/HalftoneType 1/Frequency %g/Angle %g",
838
	     psht->screen.frequency, psht->screen.angle);
839
    if (i < countof(ht_functions))
840
	pprints1(s, "/SpotFunction/%s", ht_functions[i].fname);
841
    else
842
	pprintld1(s, "/SpotFunction %ld 0 R", spot_id);
843
    stream_puts(s, trs);
844
    if (psht->accurate_screens)
845
	stream_puts(s, "/AccurateScreens true");
846
    stream_puts(s, ">>\n");
847
    return pdf_end_separate(pdev);
848
}
849
private int
850
pdf_write_screen_halftone(gx_device_pdf *pdev, const gs_screen_halftone *psht,
851
			  const gx_ht_order *porder, long *pid)
852
{
853
    gs_spot_halftone spot;
854
 
855
    spot.screen = *psht;
856
    spot.accurate_screens = false;
857
    spot.transfer = 0;
858
    spot.transfer_closure.proc = 0;
859
    return pdf_write_spot_halftone(pdev, &spot, porder, pid);
860
}
861
private int
862
pdf_write_colorscreen_halftone(gx_device_pdf *pdev,
863
			       const gs_colorscreen_halftone *pcsht,
864
			       const gx_device_halftone *pdht, long *pid)
865
{
866
    int i;
867
    stream *s;
868
    long ht_ids[4];
869
 
870
    for (i = 0; i < pdht->num_comp ; ++i) {
871
	int code = pdf_write_screen_halftone(pdev, &pcsht->screens.indexed[i],
872
					     &pdht->components[i].corder,
873
					     &ht_ids[i]);
874
	if (code < 0)
875
	    return code;
876
    }
877
    *pid = pdf_begin_separate(pdev);
878
    s = pdev->strm;
879
    /* Use Black, Gray as the Default unless we are in RGB colormodel */
880
    /* (num_comp < 4) in which case we use Green (arbitrarily) */
881
    pprintld1(s, "<</Type/Halftone/HalftoneType 5/Default %ld 0 R\n",
882
	      pdht->num_comp > 3 ? ht_ids[3] : ht_ids[1]);
883
    pprintld2(s, "/Red %ld 0 R/Cyan %ld 0 R", ht_ids[0], ht_ids[0]);
884
    pprintld2(s, "/Green %ld 0 R/Magenta %ld 0 R", ht_ids[1], ht_ids[1]);
885
    pprintld2(s, "/Blue %ld 0 R/Yellow %ld 0 R", ht_ids[2], ht_ids[2]);
886
    if (pdht->num_comp > 3)
887
    pprintld2(s, "/Gray %ld 0 R/Black %ld 0 R", ht_ids[3], ht_ids[3]);
888
    stream_puts(s, ">>\n");
889
    return pdf_end_separate(pdev);
890
}
891
 
892
#define CHECK(expr)\
893
  BEGIN if ((code = (expr)) < 0) return code; END
894
 
895
private int
896
pdf_write_threshold_halftone(gx_device_pdf *pdev,
897
			     const gs_threshold_halftone *ptht,
898
			     const gx_ht_order *porder, long *pid)
899
{
900
    char trs[17 + MAX_FN_CHARS + 1];
901
    stream *s;
902
    pdf_data_writer_t writer;
903
    int code = pdf_write_transfer(pdev, porder->transfer, "",
904
				  trs);
905
 
906
    if (code < 0)
907
	return code;
908
    CHECK(pdf_begin_data(pdev, &writer)); 
909
    s = pdev->strm;
910
    *pid = writer.pres->object->id;
911
    CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
912
	"/Type", "/Halftone"));
913
    CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
914
	"/HalftoneType", "6"));
915
    CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
916
	"/Width", ptht->width));
917
    CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
918
	"/Height", ptht->height));
919
    if (*trs != 0)
920
	CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
921
	    "/TransferFunction", trs));
922
    stream_write(writer.binary.strm, ptht->thresholds.data, ptht->thresholds.size);
923
    return pdf_end_data(&writer);
924
}
925
private int
926
pdf_write_threshold2_halftone(gx_device_pdf *pdev,
927
			      const gs_threshold2_halftone *ptht,
928
			      const gx_ht_order *porder, long *pid)
929
{
930
    char trs[17 + MAX_FN_CHARS + 1];
931
    stream *s;
932
    pdf_data_writer_t writer;
933
    int code = pdf_write_transfer(pdev, porder->transfer, "/TransferFunction",
934
				  trs);
935
 
936
    if (code < 0)
937
	return code;
938
    CHECK(pdf_begin_data(pdev, &writer)); 
939
    s = pdev->strm;
940
    *pid = writer.pres->object->id;
941
    CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
942
	"/Type", "/Halftone"));
943
    CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
944
	"/HalftoneType", "16"));
945
    CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
946
	"/Width", ptht->width));
947
    CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
948
	"/Height", ptht->height));
949
    if (ptht->width2 && ptht->height2) {
950
	CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
951
	    "/Width2", ptht->width2));
952
	CHECK(cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
953
	    "/Height2", ptht->height2));
954
    }
955
    if (*trs != 0)
956
	CHECK(cos_dict_put_c_strings((cos_dict_t *)writer.pres->object,
957
	    "/TransferFunction", trs));
958
    s = writer.binary.strm;
959
    if (ptht->bytes_per_sample == 2)
960
	stream_write(s, ptht->thresholds.data, ptht->thresholds.size);
961
    else {
962
	/* Expand 1-byte to 2-byte samples. */
963
	int i;
964
 
965
	for (i = 0; i < ptht->thresholds.size; ++i) {
966
	    byte b = ptht->thresholds.data[i];
967
 
968
	    stream_putc(s, b);
969
	    stream_putc(s, b);
970
	}
971
    }
972
    return pdf_end_data(&writer);
973
}
974
private int 
975
pdf_get_halftone_component_index(const gs_multiple_halftone *pmht,
976
				 const gx_device_halftone *pdht,
977
				 int dht_index)
978
{
979
    int j;
980
 
981
    for (j = 0; j < pmht->num_comp; j++)
982
	if (pmht->components[j].comp_number == dht_index)
983
	    break;
984
    if (j == pmht->num_comp) { 
985
	/* Look for Default. */
986
	for (j = 0; j < pmht->num_comp; j++)
987
	    if (pmht->components[j].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS)
988
		break;
989
	if (j == pmht->num_comp)
990
	    return_error(gs_error_undefined);
991
    }
992
    return j;
993
}
994
private int
995
pdf_write_multiple_halftone(gx_device_pdf *pdev,
996
			    const gs_multiple_halftone *pmht,
997
			    const gx_device_halftone *pdht, long *pid)
998
{
999
    stream *s;
1000
    int i, code, last_comp = 0;
1001
    gs_memory_t *mem = pdev->pdf_memory;
1002
    long *ids;
1003
    bool done_Default = false;
1004
 
1005
    ids = (long *)gs_alloc_byte_array(mem, pmht->num_comp, sizeof(long),
1006
				      "pdf_write_multiple_halftone");
1007
    if (ids == 0)
1008
	return_error(gs_error_VMerror);
1009
    for (i = 0; i < pdht->num_comp; ++i) {
1010
	const gs_halftone_component *phtc;
1011
	const gx_ht_order *porder;
1012
 
1013
	code = pdf_get_halftone_component_index(pmht, pdht, i);
1014
	if (code < 0)
1015
	    return code;
1016
	if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
1017
	    if (done_Default)
1018
		continue;
1019
	    done_Default = true;
1020
	}
1021
	phtc = &pmht->components[code];
1022
	porder = (pdht->components == 0 ? &pdht->order :
1023
	               &pdht->components[i].corder);
1024
	switch (phtc->type) {
1025
	case ht_type_spot:
1026
	    code = pdf_write_spot_halftone(pdev, &phtc->params.spot,
1027
					   porder, &ids[i]);
1028
	    break;
1029
	case ht_type_threshold:
1030
	    code = pdf_write_threshold_halftone(pdev, &phtc->params.threshold,
1031
						porder, &ids[i]);
1032
	    break;
1033
	case ht_type_threshold2:
1034
	    code = pdf_write_threshold2_halftone(pdev,
1035
						 &phtc->params.threshold2,
1036
						 porder, &ids[i]);
1037
	    break;
1038
	default:
1039
	    code = gs_note_error(gs_error_rangecheck);
1040
	}
1041
	if (code < 0) {
1042
	    gs_free_object(mem, ids, "pdf_write_multiple_halftone");
1043
	    return code;
1044
	}
1045
    }
1046
    *pid = pdf_begin_separate(pdev);
1047
    s = pdev->strm;
1048
    stream_puts(s, "<</Type/Halftone/HalftoneType 5\n");
1049
    done_Default = false;
1050
    for (i = 0; i < pdht->num_comp; ++i) {
1051
	const gs_halftone_component *phtc;
1052
	byte *str;
1053
	uint len;
1054
	cos_value_t value;
1055
 
1056
	code = pdf_get_halftone_component_index(pmht, pdht, i);
1057
	if (code < 0)
1058
	    return code;
1059
	if (pmht->components[code].comp_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
1060
	    if (done_Default)
1061
		continue;
1062
	    done_Default = true;
1063
	}
1064
	phtc = &pmht->components[code];
1065
	if ((code = pmht->get_colorname_string(pdev->memory, phtc->cname, &str, &len)) < 0 ||
1066
            (code = pdf_string_to_cos_name(pdev, str, len, &value)) < 0)
1067
	    return code;
1068
	cos_value_write(&value, pdev);
1069
	gs_free_string(mem, value.contents.chars.data,
1070
		       value.contents.chars.size,
1071
		       "pdf_write_multiple_halftone");
1072
	pprintld1(s, " %ld 0 R\n", ids[i]);
1073
	last_comp = i;
1074
    }
1075
    if (!done_Default) {
1076
	/*
1077
	 * BOGUS: Type 5 halftones must contain Default component.
1078
	 * Perhaps we have no way to obtain it,
1079
	 * because pdht contains ProcessColorModel components only.
1080
	 * We copy the last component as Default one.
1081
	 */
1082
	pprintld1(s, " /Default %ld 0 R\n", ids[last_comp]);
1083
    }
1084
    stream_puts(s, ">>\n");
1085
    gs_free_object(mem, ids, "pdf_write_multiple_halftone");
1086
    return pdf_end_separate(pdev);
1087
}
1088
 
1089
/*
1090
 * Update the halftone.  This is a separate procedure only for
1091
 * readability.
1092
 */
1093
private int
1094
pdf_update_halftone(gx_device_pdf *pdev, const gs_imager_state *pis,
1095
		    char *hts)
1096
{
1097
    const gs_halftone *pht = pis->halftone;
1098
    const gx_device_halftone *pdht = pis->dev_ht;
1099
    int code;
1100
    long id;
1101
 
1102
    switch (pht->type) {
1103
    case ht_type_screen:
1104
	code = pdf_write_screen_halftone(pdev, &pht->params.screen,
1105
					 &pdht->components[0].corder, &id);
1106
	break;
1107
    case ht_type_colorscreen:
1108
	code = pdf_write_colorscreen_halftone(pdev, &pht->params.colorscreen,
1109
					      pdht, &id);
1110
	break;
1111
    case ht_type_spot:
1112
	code = pdf_write_spot_halftone(pdev, &pht->params.spot,
1113
				       &pdht->components[0].corder, &id);
1114
	break;
1115
    case ht_type_threshold:
1116
	code = pdf_write_threshold_halftone(pdev, &pht->params.threshold,
1117
					    &pdht->components[0].corder, &id);
1118
	break;
1119
    case ht_type_threshold2:
1120
	code = pdf_write_threshold2_halftone(pdev, &pht->params.threshold2,
1121
					     &pdht->components[0].corder, &id);
1122
	break;
1123
    case ht_type_multiple:
1124
    case ht_type_multiple_colorscreen:
1125
	code = pdf_write_multiple_halftone(pdev, &pht->params.multiple,
1126
					   pdht, &id);
1127
	break;
1128
    default:
1129
	return_error(gs_error_rangecheck);
1130
    }
1131
    if (code < 0)
1132
	return code;
1133
    sprintf(hts, "%ld 0 R", id);
1134
    pdev->halftone_id = pis->dev_ht->id;
1135
    return code;
1136
}
1137
 
1138
/* ------ Graphics state updating ------ */
1139
 
1140
private inline cos_dict_t *
1141
resource_dict(pdf_resource_t *pres)
1142
{
1143
    return (cos_dict_t *)pres->object;
1144
}
1145
 
1146
/* Open an ExtGState. */
1147
private int
1148
pdf_open_gstate(gx_device_pdf *pdev, pdf_resource_t **ppres)
1149
{
1150
    int code;
1151
 
1152
    if (*ppres)
1153
	return 0;
1154
    /*
1155
     * We write gs command only in stream context.
1156
     * If we are clipped, and the clip path is about to change,
1157
     * the old clipping must be undone before writing gs.
1158
     */
1159
    if (pdev->context != PDF_IN_STREAM) {
1160
	/* We apparently use gs_error_interrupt as a request to change context. */
1161
	return gs_error_interrupt;
1162
    }
1163
    code = pdf_alloc_resource(pdev, resourceExtGState, gs_no_id, ppres, -1L);
1164
    if (code < 0)
1165
	return code;
1166
    cos_become((*ppres)->object, cos_type_dict);
1167
    code = cos_dict_put_c_key_string(resource_dict(*ppres), "/Type", (const byte *)"/ExtGState", 10);
1168
    if (code < 0)
1169
	return code;
1170
    return 0;
1171
}
1172
 
1173
/* Finish writing an ExtGState. */
1174
int
1175
pdf_end_gstate(gx_device_pdf *pdev, pdf_resource_t *pres)
1176
{
1177
    if (pres) {
1178
	int code = pdf_substitute_resource(pdev, &pres, resourceExtGState, NULL, true);
1179
 
1180
	if (code < 0)
1181
	    return code;
1182
	code = pdf_open_page(pdev, PDF_IN_STREAM);
1183
	if (code < 0)
1184
	    return code;
1185
	code = pdf_add_resource(pdev, pdev->substream_Resources, "/ExtGState", pres);
1186
	if (code < 0)
1187
	    return code;
1188
	pprintld1(pdev->strm, "/R%ld gs\n", pdf_resource_id(pres));
1189
	pres->where_used |= pdev->used_mask;
1190
    }
1191
    return 0;
1192
}
1193
 
1194
/*
1195
 * Update the transfer functions(s).  This is a separate procedure only
1196
 * for readability.
1197
 */
1198
private int
1199
pdf_update_transfer(gx_device_pdf *pdev, const gs_imager_state *pis,
1200
		    char *trs)
1201
{
1202
    int i, pi = -1;
1203
    bool multiple = false, update = false;
1204
    gs_id transfer_ids[4];
1205
    int code = 0;
1206
    const gx_transfer_map *tm[4];
1207
 
1208
    tm[0] = pis->set_transfer.red;
1209
    tm[1] = pis->set_transfer.green;
1210
    tm[2] = pis->set_transfer.blue;
1211
    tm[3] = pis->set_transfer.gray;
1212
    for (i = 0; i < 4; ++i) 
1213
	if (tm[i] != NULL) {
1214
	    transfer_ids[i] = tm[i]->id;
1215
	    if (pdev->transfer_ids[i] != tm[i]->id)
1216
		update = true;
1217
	    if (pi != -1 && transfer_ids[i] != transfer_ids[pi])
1218
		multiple = true;
1219
	    pi = i;
1220
	} else 
1221
	    transfer_ids[i] = -1;
1222
    if (update) {
1223
	int mask;
1224
 
1225
	if (!multiple) {
1226
	    code = pdf_write_transfer(pdev, tm[pi], "", trs);
1227
	    if (code < 0)
1228
		return code;
1229
	    mask = code == 0;
1230
	} else {
1231
	    strcpy(trs, "[");
1232
	    mask = 0;
1233
	    for (i = 0; i < 4; ++i) 
1234
		if (tm[i] != NULL) {
1235
		    code = pdf_write_transfer_map(pdev,
1236
						  tm[i],
1237
						  0, true, " ", trs + strlen(trs));
1238
		    if (code < 0)
1239
			return code;
1240
		    mask |= (code == 0) << i;
1241
		}
1242
	    strcat(trs, "]");
1243
	}
1244
	memcpy(pdev->transfer_ids, transfer_ids, sizeof(pdev->transfer_ids));
1245
	pdev->transfer_not_identity = mask;
1246
    }
1247
    return code;
1248
}
1249
 
1250
/*
1251
 * Update the current alpha if necessary.  Note that because Ghostscript
1252
 * stores separate opacity and shape alpha, a rangecheck will occur if
1253
 * both are different from the current setting.
1254
 */
1255
private int
1256
pdf_update_alpha(gx_device_pdf *pdev, const gs_imager_state *pis,
1257
		 pdf_resource_t **ppres)
1258
{
1259
    bool ais;
1260
    floatp alpha;
1261
    int code;
1262
 
1263
    if (pdev->state.soft_mask_id != pis->soft_mask_id) {
1264
	char buf[20];
1265
 
1266
	sprintf(buf, "%ld 0 R", pis->soft_mask_id);
1267
	code = pdf_open_gstate(pdev, ppres);
1268
	if (code < 0)
1269
	    return code;
1270
	code = cos_dict_put_c_key_string(resource_dict(*ppres), 
1271
		    "/SMask", (byte *)buf, strlen(buf));
1272
	if (code < 0)
1273
	    return code;
1274
	pdev->state.soft_mask_id = pis->soft_mask_id;
1275
    }
1276
    if (pdev->state.opacity.alpha != pis->opacity.alpha) {
1277
	if (pdev->state.shape.alpha != pis->shape.alpha)
1278
	    return_error(gs_error_rangecheck);
1279
	ais = false;
1280
	alpha = pdev->state.opacity.alpha = pis->opacity.alpha;
1281
    } else if (pdev->state.shape.alpha != pis->shape.alpha) {
1282
	ais = true;
1283
	alpha = pdev->state.shape.alpha = pis->shape.alpha;
1284
    } else
1285
	return 0;
1286
    code = pdf_open_gstate(pdev, ppres);
1287
    if (code < 0)
1288
	return code;
1289
    code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", ais);
1290
    if (code < 0)
1291
	return code;
1292
    /* we never do the 'both' operations (b, B, b*, B*) so we set both */
1293
    /* CA and ca the same so that we stay in sync with state.*.alpha   */
1294
    code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", alpha);
1295
    if (code < 0)
1296
	return code;
1297
    return cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", alpha);
1298
}
1299
 
1300
/*
1301
 * Update the graphics subset common to all high-level drawing operations.
1302
 */
1303
int
1304
pdf_prepare_drawing(gx_device_pdf *pdev, const gs_imager_state *pis,
1305
		    pdf_resource_t **ppres)
1306
{
1307
    int code = 0;
1308
    int bottom;
1309
 
1310
    if (pdev->CompatibilityLevel >= 1.4) {
1311
	if (pdev->state.blend_mode != pis->blend_mode) {
1312
	    static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
1313
	    char buf[20];
1314
 
1315
	    code = pdf_open_gstate(pdev, ppres);
1316
	    if (code < 0)
1317
		return code;
1318
	    buf[0] = '/';
1319
	    strncpy(buf + 1, bm_names[pis->blend_mode], sizeof(buf) - 2);
1320
	    code = cos_dict_put_string_copy(resource_dict(*ppres), "/BM", buf);
1321
	    if (code < 0)
1322
		return code;
1323
	    pdev->state.blend_mode = pis->blend_mode;
1324
	}
1325
	code = pdf_update_alpha(pdev, pis, ppres);
1326
	if (code < 0)
1327
	    return code;
1328
    } else {
1329
	/*
1330
	 * If the graphics state calls for any transparency functions,
1331
	 * we can't represent them, so return a rangecheck.
1332
	 */
1333
	if (pis->opacity.alpha != 1 || pis->opacity.mask != 0 ||
1334
	    pis->shape.alpha != 1 || pis->shape.mask != 0 ||
1335
	    pis->transparency_stack != 0
1336
	    )
1337
	    return_error(gs_error_rangecheck);
1338
    }
1339
    /*
1340
     * We originally thought the remaining items were only needed for
1341
     * fill and stroke, but in fact they are needed for images as well.
1342
     */
1343
    /*
1344
     * Update halftone, transfer function, black generation, undercolor
1345
     * removal, halftone phase, overprint mode, smoothness, blend mode, text
1346
     * knockout.
1347
     */
1348
    bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
1349
    /* When ResourcesBeforeUsage != 0, one sbstack element 
1350
       appears from the page contents stream. */
1351
    if (pdev->sbstack_depth == bottom) {
1352
	gs_int_point phase, dev_phase;
1353
	char hts[5 + MAX_FN_CHARS + 1],
1354
	    trs[5 + MAX_FN_CHARS * 4 + 6 + 1],
1355
	    bgs[5 + MAX_FN_CHARS + 1],
1356
	    ucrs[6 + MAX_FN_CHARS + 1];
1357
 
1358
	hts[0] = trs[0] = bgs[0] = ucrs[0] = 0;
1359
	if (pdev->params.PreserveHalftoneInfo &&
1360
	    pdev->halftone_id != pis->dev_ht->id &&
1361
	    !pdev->PDFX
1362
	    ) {
1363
	    code = pdf_update_halftone(pdev, pis, hts);
1364
	    if (code < 0)
1365
		return code;
1366
	}
1367
	if (pdev->params.TransferFunctionInfo == tfi_Preserve &&
1368
	    !pdev->PDFX
1369
	    ) {
1370
	    code = pdf_update_transfer(pdev, pis, trs);
1371
	    if (code < 0)
1372
		return code;
1373
	}
1374
	if (pdev->params.UCRandBGInfo == ucrbg_Preserve) {
1375
	    if (pdev->black_generation_id != pis->black_generation->id) {
1376
		code = pdf_write_transfer_map(pdev, pis->black_generation,
1377
					      0, false, "", bgs);
1378
		if (code < 0)
1379
		    return code;
1380
		pdev->black_generation_id = pis->black_generation->id;
1381
	    }
1382
	    if (pdev->undercolor_removal_id != pis->undercolor_removal->id) {
1383
		code = pdf_write_transfer_map(pdev, pis->undercolor_removal,
1384
					      -1, false, "", ucrs);
1385
		if (code < 0)
1386
		    return code;
1387
		pdev->undercolor_removal_id = pis->undercolor_removal->id;
1388
	    }
1389
	}
1390
	if (hts[0] || trs[0] || bgs[0] || ucrs[0]) {
1391
	    code = pdf_open_gstate(pdev, ppres);
1392
	    if (code < 0)
1393
		return code;
1394
	}
1395
	if (hts[0]) {
1396
	    code = cos_dict_put_string_copy(resource_dict(*ppres), "/HT", hts);
1397
	    if (code < 0)
1398
		return code;
1399
	}
1400
	if (trs[0]) {
1401
	    code = cos_dict_put_string_copy(resource_dict(*ppres), "/TR", trs);
1402
	    if (code < 0)
1403
		return code;
1404
	}
1405
	if (bgs[0]) {
1406
	    code = cos_dict_put_string_copy(resource_dict(*ppres), "/BG", bgs);
1407
	    if (code < 0)
1408
		return code;
1409
	}
1410
	if (ucrs[0]) {
1411
	    code = cos_dict_put_string_copy(resource_dict(*ppres), "/UCR", ucrs);
1412
	    if (code < 0)
1413
		return code;
1414
	}
1415
	if (!pdev->PDFX) {
1416
	    gs_currentscreenphase_pis(pis, &phase, 0);
1417
	    gs_currentscreenphase_pis(&pdev->state, &dev_phase, 0);
1418
	    if (dev_phase.x != phase.x || dev_phase.y != phase.y) {
1419
		char buf[sizeof(int) * 3 + 5];
1420
 
1421
		code = pdf_open_gstate(pdev, ppres);
1422
		if (code < 0)
1423
		    return code;
1424
		sprintf(buf, "[%d %d]", phase.x, phase.y);
1425
		code = cos_dict_put_string_copy(resource_dict(*ppres), "/HTP", buf);
1426
		if (code < 0)
1427
		    return code;
1428
		gx_imager_setscreenphase(&pdev->state, phase.x, phase.y,
1429
					 gs_color_select_all);
1430
	    }
1431
	}
1432
    }
1433
    if (pdev->CompatibilityLevel >= 1.3 && pdev->sbstack_depth == bottom) {
1434
	if (pdev->overprint_mode != pdev->params.OPM) {
1435
	    code = pdf_open_gstate(pdev, ppres);
1436
	    if (code < 0)
1437
		return code;
1438
	    code = cos_dict_put_c_key_int(resource_dict(*ppres), "/OPM", pdev->params.OPM);
1439
	    if (code < 0)
1440
		return code;
1441
	    pdev->overprint_mode = pdev->params.OPM;
1442
	}
1443
	if (pdev->state.smoothness != pis->smoothness) {
1444
	    code = pdf_open_gstate(pdev, ppres);
1445
	    if (code < 0)
1446
		return code;
1447
	    code = cos_dict_put_c_key_real(resource_dict(*ppres), "/SM", pis->smoothness);
1448
	    if (code < 0)
1449
		return code;
1450
	    pdev->state.smoothness = pis->smoothness;
1451
	}
1452
	if (pdev->CompatibilityLevel >= 1.4) {
1453
	    if (pdev->state.text_knockout != pis->text_knockout) {
1454
		code = pdf_open_gstate(pdev, ppres);
1455
		if (code < 0)
1456
		    return code;
1457
		code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/TK", pis->text_knockout);
1458
		if (code < 0)
1459
		    return code;
1460
		pdev->state.text_knockout = pis->text_knockout;
1461
	    }
1462
	}
1463
    }
1464
    return code;
1465
}
1466
 
1467
/* Update the graphics state for filling. */
1468
int
1469
pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_imager_state *pis)
1470
{
1471
    pdf_resource_t *pres = 0;
1472
    int code = pdf_prepare_drawing(pdev, pis, &pres);
1473
 
1474
    if (code < 0)
1475
	return code;
1476
    /* Update overprint. */
1477
    if (pdev->params.PreserveOverprintSettings &&
1478
	pdev->fill_overprint != pis->overprint &&
1479
	!pdev->skip_colors
1480
	) {
1481
	code = pdf_open_gstate(pdev, &pres);
1482
	if (code < 0)
1483
	    return code;
1484
	/* PDF 1.2 only has a single overprint setting. */
1485
	if (pdev->CompatibilityLevel < 1.3) {
1486
	    code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pis->overprint);
1487
	    if (code < 0)
1488
		return code;
1489
	    pdev->stroke_overprint = pis->overprint;
1490
	} else {
1491
	    code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pis->overprint);
1492
	    if (code < 0)
1493
		return code;
1494
	}
1495
	pdev->fill_overprint = pis->overprint;
1496
    }
1497
    return pdf_end_gstate(pdev, pres);
1498
}
1499
int
1500
pdf_prepare_fill(gx_device_pdf *pdev, const gs_imager_state *pis)
1501
{
1502
    int code;
1503
 
1504
    if (pdev->context != PDF_IN_STREAM) {
1505
	code = pdf_try_prepare_fill(pdev, pis);
1506
	if (code != gs_error_interrupt) /* See pdf_open_gstate */
1507
	    return code;
1508
	code = pdf_open_contents(pdev, PDF_IN_STREAM);
1509
	if (code < 0)
1510
	    return code;
1511
    }
1512
    return pdf_try_prepare_fill(pdev, pis);
1513
}
1514
 
1515
/* Update the graphics state for stroking. */
1516
private int
1517
pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_imager_state *pis)
1518
{
1519
    pdf_resource_t *pres = 0;
1520
    int code = pdf_prepare_drawing(pdev, pis, &pres);
1521
 
1522
    if (code < 0)
1523
	return code;
1524
    /* Update overprint, stroke adjustment. */
1525
    if (pdev->params.PreserveOverprintSettings &&
1526
	pdev->stroke_overprint != pis->overprint &&
1527
	!pdev->skip_colors
1528
	) {
1529
	code = pdf_open_gstate(pdev, &pres);
1530
	if (code < 0)
1531
	    return code;
1532
	code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pis->overprint);
1533
	if (code < 0)
1534
	    return code;
1535
	pdev->stroke_overprint = pis->overprint;
1536
	if (pdev->CompatibilityLevel < 1.3) {
1537
	    /* PDF 1.2 only has a single overprint setting. */
1538
	    pdev->fill_overprint = pis->overprint;
1539
	} else {
1540
	    /* According to PDF>=1.3 spec, OP also sets op,
1541
	       if there is no /op in same garphic state object. 
1542
	       We don't write /op, so monitor the viewer's state here : */
1543
	    pdev->fill_overprint = pis->overprint;
1544
	}
1545
    }
1546
    if (pdev->state.stroke_adjust != pis->stroke_adjust) {
1547
	code = pdf_open_gstate(pdev, &pres);
1548
	if (code < 0)
1549
	    return code;
1550
	code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pis->stroke_adjust);
1551
	if (code < 0)
1552
	    return code;
1553
	pdev->state.stroke_adjust = pis->stroke_adjust;
1554
    }
1555
    return pdf_end_gstate(pdev, pres);
1556
}
1557
int
1558
pdf_prepare_stroke(gx_device_pdf *pdev, const gs_imager_state *pis)
1559
{
1560
    int code;
1561
 
1562
    if (pdev->context != PDF_IN_STREAM) {
1563
	code = pdf_try_prepare_stroke(pdev, pis);
1564
	if (code != gs_error_interrupt) /* See pdf_open_gstate */
1565
	    return code;
1566
	code = pdf_open_contents(pdev, PDF_IN_STREAM);
1567
	if (code < 0)
1568
	    return code;
1569
    }
1570
    return pdf_try_prepare_stroke(pdev, pis);
1571
}
1572
 
1573
/* Update the graphics state for an image other than an ImageType 1 mask. */
1574
int
1575
pdf_prepare_image(gx_device_pdf *pdev, const gs_imager_state *pis)
1576
{
1577
    /*
1578
     * As it turns out, this requires updating the same parameters as for
1579
     * filling.
1580
     */
1581
    return pdf_prepare_fill(pdev, pis);
1582
}
1583
 
1584
/* Update the graphics state for an ImageType 1 mask. */
1585
int
1586
pdf_prepare_imagemask(gx_device_pdf *pdev, const gs_imager_state *pis,
1587
		      const gx_drawing_color *pdcolor)
1588
{
1589
    int code = pdf_prepare_image(pdev, pis);
1590
 
1591
    if (code < 0)
1592
	return code;
1593
    return pdf_set_drawing_color(pdev, pis, pdcolor, &pdev->saved_fill_color,
1594
				 &pdev->fill_used_process_color,
1595
				 &psdf_set_fill_color_commands);
1596
}
1597