Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/gs/src/gsovrc.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 2002 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: gsovrc.c,v 1.10 2005/06/29 23:46:24 dan Exp $ */
18
/* overprint/overprint mode compositor implementation */
19
 
20
#include "memory_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gsutil.h"             /* for gs_next_ids */
24
#include "gxcomp.h"
25
#include "gxdevice.h"
26
#include "gsdevice.h"
27
#include "gxgetbit.h"
28
#include "gsovrc.h"
29
#include "gxdcolor.h"
30
#include "gxoprect.h"
31
#include "gsbitops.h"
32
#include "gxistate.h"
33
 
34
 
35
/* GC descriptor for gs_overprint_t */
36
private_st_gs_overprint_t();
37
 
38
/*
39
 * Utility routine for encoding or decoding a color index. We cannot use
40
 * the general integer encoding routins for these, as they may be 64 bits
41
 * in length (the general routines are only designed for 32 bits). We also
42
 * cannot use the color-specific routines, as we do not have the required
43
 * device color information available.
44
 *
45
 * The scheme employed is the potentially 64-bit analog of the 32-bit
46
 * routines: the low order seven bits of each bytes represents a base-128
47
 * digit, and the high order bit is set if there is another digit. The
48
 * encoding order is little-endian.
49
 *
50
 * The write routine returns 0 on success, with *psize set to the number
51
 * of bytes used. Alternatively, the return value will be gs_error_rangecheck,
52
 * with *psize set to the number of bytes required, if there was insufficient
53
 * space.
54
 *
55
 * The read routine returns the number of bytes read on success, or < 0 in
56
 * the event of an error.
57
 */
58
private int
59
write_color_index(gx_color_index cindex, byte * data, uint * psize)
60
{
61
    int             num_bytes = 0;
62
    gx_color_index  ctmp = cindex;
63
 
64
    for (num_bytes = 1; (ctmp >>= 7) != 0; ++num_bytes)
65
        ;
66
    if (num_bytes > *psize) {
67
        *psize = num_bytes;
68
        return gs_error_rangecheck;
69
    }
70
    ctmp = cindex;
71
    *psize = num_bytes;
72
    for (; num_bytes > 1; ctmp >>= 7, --num_bytes)
73
        *data++ = 0x80 | (ctmp & 0x7f);
74
    *data = ctmp & 0x7f;
75
    return 0;
76
}
77
 
78
private int
79
read_color_index(gx_color_index * pcindex, const byte * data, uint size)
80
{
81
    gx_color_index  cindex = 0;
82
    int             nbytes = 0, shift = 0;
83
 
84
    for (;; shift += 7, data++) {
85
        if (++nbytes > size)
86
            return_error(gs_error_rangecheck);
87
        else {
88
            int     c = *data;
89
 
90
            cindex += (c & 0x7f) << shift;
91
            if ((c & 0x80) == 0)
92
                break;
93
        }
94
    }
95
    *pcindex = cindex;
96
    return nbytes;
97
}
98
 
99
/*
100
 * Check for equality of two overprint compositor objects.
101
 *
102
 * This is fairly simple.
103
 */
104
private bool
105
c_overprint_equal(const gs_composite_t * pct0, const gs_composite_t * pct1)
106
{
107
    if (pct0->type == pct1->type) {
108
        const gs_overprint_params_t *    pparams0;
109
        const gs_overprint_params_t *    pparams1;
110
 
111
        pparams0 = &((const gs_overprint_t *)(pct0))->params;
112
        pparams1 = &((const gs_overprint_t *)(pct1))->params;
113
        if (!pparams0->retain_any_comps)
114
            return !pparams1->retain_any_comps;
115
        else if (pparams0->retain_spot_comps)
116
            return pparams1->retain_spot_comps;
117
        else
118
            return pparams0->drawn_comps == pparams1->drawn_comps;
119
    } else
120
        return false;
121
}
122
 
123
/*
124
 * Bits corresponding to boolean values in the first byte of the string
125
 * representation of an overprint compositor.
126
 */
127
#define OVERPRINT_ANY_COMPS     1
128
#define OVERPRINT_SPOT_COMPS    2
129
 
130
/*
131
 * Convert an overprint compositor to string form for use by the command
132
 * list device.
133
 */
134
private int
135
c_overprint_write(const gs_composite_t * pct, byte * data, uint * psize)
136
{
137
    const gs_overprint_params_t *   pparams = &((const gs_overprint_t *)pct)->params;
138
    byte                            flags = 0;
139
    int                             used = 1, avail = *psize;
140
 
141
    /* encoded the booleans in a single byte */
142
    if (pparams->retain_any_comps) {
143
        flags |= OVERPRINT_ANY_COMPS;
144
 
145
        /* write out the component bits only if necessary (and possible) */
146
        if (pparams->retain_spot_comps)
147
            flags |= OVERPRINT_SPOT_COMPS;
148
        else {
149
            uint    tmp_size = (avail > 0 ? avail - 1 : 0);
150
            int     code = write_color_index( pparams->drawn_comps,
151
                                              data + 1,
152
                                              &tmp_size );
153
 
154
            if (code < 0 && code != gs_error_rangecheck)
155
                return code;
156
            used += tmp_size;
157
        }            
158
    }
159
 
160
    /* check for overflow */
161
    *psize = used;
162
    if (used > avail)
163
        return_error(gs_error_rangecheck);
164
    data[0] = flags;
165
    return 0;
166
}
167
 
168
/*
169
 * Convert the string representation of the overprint parameter into the
170
 * full compositor.
171
 */
172
private int
173
c_overprint_read(
174
    gs_composite_t **       ppct,
175
    const byte *            data,
176
    uint                    size,
177
    gs_memory_t *           mem )
178
{
179
    gs_overprint_params_t   params;
180
    byte                    flags = 0;
181
    int                     code = 0, nbytes = 1;
182
 
183
    if (size < 1)
184
        return_error(gs_error_rangecheck);
185
    flags = *data;
186
    params.retain_any_comps = (flags & OVERPRINT_ANY_COMPS) != 0;
187
    params.retain_spot_comps = (flags & OVERPRINT_SPOT_COMPS) != 0;
188
 
189
    /* check if the drawn_comps array is present */
190
    if (params.retain_any_comps && !params.retain_spot_comps) {
191
        code = read_color_index(&params.drawn_comps, data + 1, size - 1);
192
        if (code < 0)
193
            return code;
194
         nbytes += code;
195
    }
196
 
197
    code = gs_create_overprint(ppct, &params, mem);
198
 
199
    return code < 0 ? code : nbytes;
200
}
201
 
202
 
203
private composite_create_default_compositor_proc(c_overprint_create_default_compositor);
204
 
205
/* methods for the overprint compositor */
206
const gs_composite_type_t   gs_composite_overprint_type = {
207
    GX_COMPOSITOR_OVERPRINT,
208
    {
209
        c_overprint_create_default_compositor,  /* procs.create_default_compositor */
210
        c_overprint_equal,                      /* procs.equal */
211
        c_overprint_write,                      /* procs.write */
212
        c_overprint_read,                       /* procs.read */
213
	gx_default_composite_clist_write_update,/* procs.composite_clist_write_update */
214
	gx_default_composite_clist_read_update	/* procs.composite_clist_reade_update */
215
    }                                           /* procs */
216
};
217
 
218
 
219
/*
220
 * Create an overprint compositor data structure.
221
 *
222
 * Currently this just a stub.
223
 */
224
int
225
gs_create_overprint(
226
    gs_composite_t **               ppct,
227
    const gs_overprint_params_t *   pparams,
228
    gs_memory_t *                   mem )
229
{
230
    gs_overprint_t *                pct;
231
 
232
    rc_alloc_struct_0( pct,
233
                       gs_overprint_t,
234
                       &st_overprint,
235
                       mem,
236
                       return_error(gs_error_VMerror),
237
                       "gs_create_overprint" );
238
    pct->type = &gs_composite_overprint_type;
239
    pct->id = gs_next_ids(mem, 1);
240
    pct->params = *pparams;
241
    *ppct = (gs_composite_t *)pct;
242
    return 0;
243
}
244
 
245
 
246
/*
247
 * Verify that a compositor data structure is for the overprint compositor.
248
 * This is used by the gs_pdf1.4_device (and eventually the PDFWrite
249
 * device), which implements overprint and overprint mode directly.
250
 */
251
int
252
gs_is_overprint_compositor(const gs_composite_t * pct)
253
{
254
    return pct->type == &gs_composite_overprint_type;
255
}
256
 
257
 
258
/*
259
 * The overprint device.
260
 *
261
 * In principle there are two versions of this device: one if the traget
262
 * device is separable and linear, the other if it is not. The two have
263
 * slightly different data structures, but differ primarily in terms of
264
 * the standard set of methods. Because methods are non-static in
265
 * GhostScript, we make use of the same data structure and handle the
266
 * distinction during initialization.
267
 *
268
 * The data fields reflect entries in the gs_overprint_params_t
269
 * structure. There is no explicit retain_any_comps field, as the current
270
 * setting of this field can be determined by checking the fill_rectangle
271
 * method. There is also no retain_spot_comps field, as the code will
272
 * will determine explicitly which components are to be drawn.
273
 */
274
typedef struct overprint_device_s {
275
    gx_device_forward_common;
276
 
277
    /*
278
     * The set of components to be drawn. This field is used only if the
279
     * target color space is not separable and linear.
280
     */
281
    gx_color_index  drawn_comps;
282
 
283
    /*
284
     * The mask of gx_color_index bits to be retained during a drawing
285
     * operation. A bit in this mask is 1 if the corresponding bit or
286
     * the color index is to be retained; otherwise it is 0.
287
     *
288
     * The "non-drawn" region of the drawing gx_color_index is assumed
289
     * to have the value zero, so for a separable and linear color
290
     * encoding, the per-pixel drawing operation is:
291
     *
292
     *  output = (output & retain_mask) | src
293
     *
294
     * (For the fully general case, replace src by (src & ~retain_mask).)
295
     * Because of byte-alignment, byte-order and performance consideration,
296
     * the actually implement operation may be more complex, but this does
297
     * not change the overall effect.
298
     *
299
     * The actual value of retain_mask will be byte swap if this is
300
     * required. It will be required if depth > 8 and the host processor
301
     * is little-endian.
302
     */
303
    gx_color_index  retain_mask;
304
 
305
} overprint_device_t;
306
 
307
gs_private_st_suffix_add0_final( st_overprint_device_t,
308
                                 overprint_device_t,
309
                                 "overprint_device_t",
310
                                 overprint_device_t_enum_ptrs,
311
                                 overprint_device_t_reloc_ptrs,
312
                                 gx_device_finalize,
313
                                 st_device_forward );
314
 
315
 
316
/*
317
 * In the default (overprint false) case, the overprint device is almost
318
 * a pure forwarding device: only the open_device and create_compositor
319
 * methods are not pure-forwarding methods. The
320
 * gx_device_foward_fill_in_procs procedure does not fill in all of the
321
 * necessary procedures, so some of them are provided explicitly below.
322
 * The put_params procedure also requires a small modification, so that
323
 * the open/close state of this device always reflects that of its
324
 * target.
325
 *
326
 * This and other method arrays are not declared const so that they may
327
 * be initialized once via gx_device_forward_fill_in_procs. They are
328
 * constant once this initialization is complete.
329
 */
330
private dev_proc_open_device(overprint_open_device);
331
private dev_proc_put_params(overprint_put_params);
332
private dev_proc_get_page_device(overprint_get_page_device);
333
private dev_proc_create_compositor(overprint_create_compositor);
334
 
335
private gx_device_procs no_overprint_procs = {
336
    overprint_open_device,              /* open_device */
337
    0,                                  /* get_initial_matrix */
338
    0,                                  /* sync_output */
339
    0,                                  /* output_page */
340
    0,                                  /* close_device */
341
    0,                                  /* map_rgb_color */
342
    0,                                  /* map_color_rgb */
343
    gx_forward_fill_rectangle,          /* fill_rectangle */
344
    gx_forward_tile_rectangle,          /* tile_rectangle */
345
    gx_forward_copy_mono,               /* copy_mono */
346
    gx_forward_copy_color,              /* copy_color */
347
    0,                                  /* draw_line (obsolete) */
348
    0,                                  /* get_bits */
349
    0,                                  /* get_params */
350
    overprint_put_params,               /* put_params */
351
    0,                                  /* map_cmyk_color */
352
    0,                                  /* get_xfont_procs */
353
    0,                                  /* get_xfont_device */
354
    0,                                  /* map_rgb_alpha_color */
355
    overprint_get_page_device,          /* get_page_device */
356
    0,                                  /* get_alpha_bits (obsolete) */
357
    0,                                  /* copy alpha */
358
    0,                                  /* get_band */
359
    0,                                  /* copy_rop */
360
    0,                                  /* fill_path */
361
    0,                                  /* stroke_path */
362
    0,                                  /* fill_mask */
363
    0,                                  /* fill_trapezoid */
364
    0,                                  /* fill_parallelogram */
365
    0,                                  /* fill_triangle */
366
    0,                                  /* draw_thin_line */
367
    0,                                  /* begin_image */
368
    0,                                  /* image_data (obsolete) */
369
    0,                                  /* end_image (obsolete) */
370
    gx_forward_strip_tile_rectangle,    /* strip_tile_rectangle */
371
    0,                                  /* strip_copy_rop */
372
    0,                                  /* get_clipping_box */
373
    0,                                  /* begin_typed_image */
374
    0,                                  /* get_bits_rectangle */
375
    0,                                  /* map_color_rgb_alpha */
376
    overprint_create_compositor,        /* create_compositor */
377
    0,                                  /* get_hardware_params */
378
    0,                                  /* text_begin */
379
    0,                                  /* gx_finish_copydevice */
380
    0,                                  /* begin_transparency_group */
381
    0,                                  /* end_transparency_group */
382
    0,                                  /* being_transparency_mask */
383
    0,                                  /* end_transparency_mask */
384
    0,                                  /* discard_transparency_layer */
385
    0,                                  /* get_color_mapping_procs */
386
    0,                                  /* get_color_comp_index */
387
    0,                                  /* encode_color */
388
 
389
};
390
 
391
/*
392
 * If overprint is set, the high and mid-level rendering methods are
393
 * replaced by the default routines. The low-level color rendering methods
394
 * are replaced with one of two sets of functions, depending on whether or
395
 * not the target device has a separable and linear color encoding.
396
 *
397
 *  1. If the target device does not have a separable and linear
398
 *     encoding, an overprint-specific fill_rectangle method is used,
399
 *     and the default methods are used for all other low-level rendering
400
 *     methods. There is no way to achieve good rendering performance
401
 *     when overprint is true and the color encoding is not separable
402
 *     and linear, so there is little reason to use more elaborate
403
 *     methods int this case.
404
 *
405
 *  2. If the target device does have a separable and linear color
406
 *     model, at least the fill_rectangle method and potentially other
407
 *     methods will be replaced by overprint-specific methods. Those
408
 *     methods not replaced will have their default values. The number
409
 *     of methods replaced is dependent on the desired level of
410
 *     performance: the more methods, the better the performance.
411
 *
412
 *     Note that certain procedures, such as copy_alpha and copy_rop,
413
 *     are likely to always be given their default values, as the concepts
414
 *     of alpha-compositing and raster operations are not compatible in
415
 *     a strict sense.
416
 */
417
private dev_proc_fill_rectangle(overprint_generic_fill_rectangle);
418
private dev_proc_fill_rectangle(overprint_sep_fill_rectangle);
419
/* other low-level overprint_sep_* rendering methods prototypes go here */
420
 
421
private gx_device_procs generic_overprint_procs = {
422
    overprint_open_device,              /* open_device */
423
    0,                                  /* get_initial_matrix */
424
    0,                                  /* sync_output */
425
    0,                                  /* output_page */
426
    0,                                  /* close_device */
427
    0,                                  /* map_rgb_color */
428
    0,                                  /* map_color_rgb */
429
    overprint_generic_fill_rectangle,   /* fill_rectangle */
430
    gx_default_tile_rectangle,          /* tile_rectangle */
431
    gx_default_copy_mono,               /* copy_mono */
432
    gx_default_copy_color,              /* copy_color */
433
    gx_default_draw_line,               /* draw_line (obsolete) */
434
    0,                                  /* get_bits */
435
    0,                                  /* get_params */
436
    overprint_put_params,               /* put_params */
437
    0,                                  /* map_cmyk_color */
438
    0,                                  /* get_xfont_procs */
439
    gx_default_get_xfont_device,        /* get_xfont_device */
440
    0,                                  /* map_rgb_alpha_color */
441
    overprint_get_page_device,          /* get_page_device */
442
    0,                                  /* get_alpha_bits (obsolete) */
443
    gx_default_copy_alpha,              /* copy alpha */
444
    0,                                  /* get_band */
445
    gx_default_copy_rop,                /* copy_rop */
446
    gx_default_fill_path,               /* fill_path */
447
    gx_default_stroke_path,             /* stroke_path */
448
    gx_default_fill_mask,               /* fill_mask */
449
    gx_default_fill_trapezoid,          /* fill_trapezoid */
450
    gx_default_fill_parallelogram,      /* fill_parallelogram */
451
    gx_default_fill_triangle,           /* fill_triangle */
452
    gx_default_draw_thin_line,          /* draw_thin_line */
453
    gx_default_begin_image,             /* begin_image */
454
    0,                                  /* image_data (obsolete) */
455
    0,                                  /* end_image (obsolete) */
456
    gx_default_strip_tile_rectangle,    /* strip_tile_rectangle */
457
    gx_default_strip_copy_rop,          /* strip_copy_rop */
458
    0,                                  /* get_clipping_box */
459
    gx_default_begin_typed_image,       /* begin_typed_image */
460
    0,                                  /* get_bits_rectangle */
461
    0,                                  /* map_color_rgb_alpha */
462
    overprint_create_compositor,        /* create_compositor */
463
    0,                                  /* get_hardware_params */
464
    gx_default_text_begin,              /* text_begin */
465
    0,                                  /* gx_finish_copydevice */
466
    0,                                  /* begin_transparency_group */
467
    0,                                  /* end_transparency_group */
468
    0,                                  /* begin_transparency_mask */
469
    0,                                  /* end_transparency_mask */
470
    0,                                  /* discard_transparency_layer */
471
    0,                                  /* get_color_mapping_procs */
472
    0,                                  /* get_color_comp_index */
473
    0,                                  /* encode_color */
474
 
475
};
476
 
477
private gx_device_procs sep_overprint_procs = {
478
    overprint_open_device,              /* open_device */
479
    0,                                  /* get_initial_matrix */
480
    0,                                  /* sync_output */
481
    0,                                  /* output_page */
482
    0,                                  /* close_device */
483
    0,                                  /* map_rgb_color */
484
    0,                                  /* map_color_rgb */
485
    overprint_sep_fill_rectangle,       /* fill_rectangle */
486
    gx_default_tile_rectangle,          /* tile_rectangle */
487
    gx_default_copy_mono,               /* copy_mono */
488
    gx_default_copy_color,              /* copy_color */
489
    gx_default_draw_line,               /* draw_line (obsolete) */
490
    0,                                  /* get_bits */
491
    0,                                  /* get_params */
492
    overprint_put_params,               /* put_params */
493
    0,                                  /* map_cmyk_color */
494
    0,                                  /* get_xfont_procs */
495
    gx_default_get_xfont_device,        /* get_xfont_device */
496
    0,                                  /* map_rgb_alpha_color */
497
    overprint_get_page_device,          /* get_page_device */
498
    0,                                  /* get_alpha_bits (obsolete) */
499
    gx_default_copy_alpha,              /* copy alpha */
500
    0,                                  /* get_band */
501
    gx_default_copy_rop,                /* copy_rop */
502
    gx_default_fill_path,               /* fill_path */
503
    gx_default_stroke_path,             /* stroke_path */
504
    gx_default_fill_mask,               /* fill_mask */
505
    gx_default_fill_trapezoid,          /* fill_trapezoid */
506
    gx_default_fill_parallelogram,      /* fill_parallelogram */
507
    gx_default_fill_triangle,           /* fill_triangle */
508
    gx_default_draw_thin_line,          /* draw_thin_line */
509
    gx_default_begin_image,             /* begin_image */
510
    0,                                  /* image_data (obsolete) */
511
    0,                                  /* end_image (obsolete) */
512
    gx_default_strip_tile_rectangle,    /* strip_tile_rectangle */
513
    gx_default_strip_copy_rop,          /* strip_copy_rop */
514
    0,                                  /* get_clipping_box */
515
    gx_default_begin_typed_image,       /* begin_typed_image */
516
    0,                                  /* get_bits_rectangle */
517
    0,                                  /* map_color_rgb_alpha */
518
    overprint_create_compositor,        /* create_compositor */
519
    0,                                  /* get_hardware_params */
520
    gx_default_text_begin,              /* text_begin */
521
    0,                                  /* gx_finish_copydevice */
522
    0,                                  /* begin_transparency_group */
523
    0,                                  /* end_transparency_group */
524
    0,                                  /* begin_transparency_mask */
525
    0,                                  /* end_transparency_mask */
526
    0,                                  /* discard_transparency_layer */
527
    0,                                  /* get_color_mapping_procs */
528
    0,                                  /* get_color_comp_index */
529
    0,                                  /* encode_color */
530
 
531
};
532
 
533
/*
534
 * The prototype for the overprint device does not provide much
535
 * information; it exists primarily to facilitate use gx_init_device
536
 * and sundry other device utility routines.
537
 */
538
const overprint_device_t    gs_overprint_device = {
539
    std_device_std_body_open( overprint_device_t,   /* device type */
540
                              0,                    /* static_procs */
541
                              "overprint_device",   /* dname */
542
                              0, 0,                 /* width, height */
543
                              1, 1 ),               /* HWResolution */
544
    { 0 }                                           /* procs */
545
};
546
 
547
 
548
 
549
/*
550
 * Utility to reorder bytes in a color or mask based on the endianness of
551
 * the current device. This is required on little-endian machines if the
552
 * depth is larger 8. The resulting value is also replicated to fill the
553
 * entire gx_color_index if the depth is a divisor of the color index
554
 * size. If this is not the case, the result will be in the low-order
555
 * bytes of the color index.
556
 *
557
 * Though this process can be handled in full generality, the code below
558
 * takes advantage of the fact that depths that are > 8 must be a multiple
559
 * of 8 and <= 64
560
 */
561
#if !arch_is_big_endian
562
 
563
private gx_color_index
564
swap_color_index(int depth, gx_color_index color)
565
{
566
    int             shift = depth - 8;
567
    gx_color_index  mask = 0xff;
568
 
569
    color =  ((color >> shift) & mask)
570
           | ((color & mask) << shift)
571
           | (color & ~((mask << shift) | mask));
572
    if (depth > 24) {
573
        shift -= 16;
574
        mask <<= 8;
575
        color =  ((color >> shift) & mask)
576
               | ((color & mask) << shift)
577
               | (color & ~((mask << shift) | mask));
578
 
579
        if (depth > 40) {
580
            shift -= 16;
581
            mask <<= 8;
582
            color =  ((color >> shift) & mask)
583
                   | ((color & mask) << shift)
584
                   | (color & ~((mask << shift) | mask));
585
 
586
            if (depth > 56) {
587
                shift -= 16;
588
                mask <<= 8;
589
                color =  ((color >> shift) & mask)
590
                       | ((color & mask) << shift)
591
                       | (color & ~((mask << shift) | mask));
592
            }
593
        }
594
    }
595
 
596
    return color;
597
}
598
 
599
#endif  /* !arch_is_big_endian */
600
 
601
/*
602
 * Update the retain_mask field to reflect the information in the
603
 * drawn_comps field. This is useful only if the device color model
604
 * is separable.
605
 */
606
private void
607
set_retain_mask(overprint_device_t * opdev)
608
{
609
    int             i, ncomps = opdev->color_info.num_components;
610
    gx_color_index  drawn_comps = opdev->drawn_comps, retain_mask = 0;
611
#if !arch_is_big_endian
612
    int             depth = opdev->color_info.depth;
613
#endif
614
 
615
    for (i = 0; i < ncomps; i++, drawn_comps >>= 1) {
616
        if ((drawn_comps & 0x1) == 0)
617
            retain_mask |= opdev->color_info.comp_mask[i];
618
    }
619
#if !arch_is_big_endian
620
    if (depth > 8)
621
        retain_mask = swap_color_index(depth, retain_mask);
622
#endif
623
    opdev->retain_mask = retain_mask;
624
}
625
 
626
/* enlarge mask of non-zero components */
627
private gx_color_index
628
check_drawn_comps(int ncomps, frac cvals[GX_DEVICE_COLOR_MAX_COMPONENTS])
629
{
630
    int              i;
631
    gx_color_index   mask = 0x1, drawn_comps = 0;
632
 
633
    for (i = 0; i < ncomps; i++, mask <<= 1) {
634
        if (cvals[i] != frac_0)
635
            drawn_comps |= mask;
636
    }
637
    return drawn_comps;
638
}
639
 
640
/*
641
 * Update the overprint-specific device parameters.
642
 *
643
 * If spot colors are to be retain, the set of process (non-spot) colors is
644
 * determined by mapping through the standard color spaces and check which
645
 * components assume non-zero values.
646
 */
647
private int
648
update_overprint_params(
649
    overprint_device_t *            opdev,
650
    const gs_overprint_params_t *   pparams )
651
{
652
    int                             ncomps = opdev->color_info.num_components;
653
 
654
    /* check if overprint is to be turned off */
655
    if (!pparams->retain_any_comps) {
656
        /* if fill_rectangle forwards, overprint is already off */
657
        if (dev_proc(opdev, fill_rectangle) != gx_forward_fill_rectangle)
658
            memcpy( &opdev->procs,
659
                    &no_overprint_procs,
660
                    sizeof(no_overprint_procs) );
661
        return 0;
662
    }
663
 
664
    /* set the procedures according to the color model */
665
    if (opdev->color_info.separable_and_linear == GX_CINFO_SEP_LIN)
666
        memcpy( &opdev->procs,
667
                &sep_overprint_procs,
668
                sizeof(sep_overprint_procs) );
669
    else
670
        memcpy( &opdev->procs,
671
                &generic_overprint_procs,
672
                sizeof(generic_overprint_procs) );
673
 
674
    /* see if we need to determine the spot color components */
675
    if (!pparams->retain_spot_comps)
676
        opdev->drawn_comps = pparams->drawn_comps;
677
    else {
678
        gx_device *                     dev = (gx_device *)opdev;
679
        const gx_cm_color_map_procs *   pprocs;
680
        frac                            cvals[GX_DEVICE_COLOR_MAX_COMPONENTS];
681
        gx_color_index                  drawn_comps = 0;
682
        static const frac               frac_13 = float2frac(1.0 / 3.0);
683
 
684
        if ((pprocs = dev_proc(opdev, get_color_mapping_procs)(dev)) == 0 ||
685
            pprocs->map_gray == 0                                         ||
686
            pprocs->map_rgb == 0                                          ||
687
            pprocs->map_cmyk == 0                                           )
688
            return_error(gs_error_unknownerror);
689
 
690
        pprocs->map_gray(dev, frac_13, cvals);
691
        drawn_comps |= check_drawn_comps(ncomps, cvals);
692
 
693
        pprocs->map_rgb(dev, 0, frac_13, frac_0, frac_0, cvals);
694
        drawn_comps |= check_drawn_comps(ncomps, cvals);
695
        pprocs->map_rgb(dev, 0, frac_0, frac_13, frac_0, cvals);
696
        drawn_comps |= check_drawn_comps(ncomps, cvals);
697
        pprocs->map_rgb(dev, 0, frac_0, frac_0, frac_13, cvals);
698
        drawn_comps |= check_drawn_comps(ncomps, cvals);
699
 
700
        pprocs->map_cmyk(dev, frac_13, frac_0, frac_0, frac_0, cvals);
701
        drawn_comps |= check_drawn_comps(ncomps, cvals);
702
        pprocs->map_cmyk(dev, frac_0, frac_13, frac_0, frac_0, cvals);
703
        drawn_comps |= check_drawn_comps(ncomps, cvals);
704
        pprocs->map_cmyk(dev, frac_0, frac_0, frac_13, frac_0, cvals);
705
        drawn_comps |= check_drawn_comps(ncomps, cvals);
706
        pprocs->map_cmyk(dev, frac_0, frac_0, frac_0, frac_13, cvals);
707
        drawn_comps |= check_drawn_comps(ncomps, cvals);
708
 
709
        opdev->drawn_comps = drawn_comps;
710
    }
711
 
712
    /* check for degenerate case */
713
    if (opdev->drawn_comps == ((gx_color_index)1 << ncomps) - 1) {
714
        memcpy( &opdev->procs,
715
                &no_overprint_procs,
716
                sizeof(no_overprint_procs) );
717
        return 0;
718
    }
719
 
720
    /* if appropriate, update the retain_mask field */
721
    if (opdev->color_info.separable_and_linear == GX_CINFO_SEP_LIN)
722
        set_retain_mask(opdev);
723
 
724
    return 0;
725
}
726
 
727
 
728
/*
729
 * The open_device method for the overprint device is about as close to
730
 * a pure "forwarding" open_device operation as is possible. Its only
731
 * significant function is to ensure that the is_open field of the
732
 * overprint device matches that of the target device.
733
 *
734
 * We assume this procedure is called only if the device is not already
735
 * open, and that gs_opendevice will take care of the is_open flag.
736
 */
737
private int
738
overprint_open_device(gx_device * dev)
739
{
740
    overprint_device_t *    opdev = (overprint_device_t *)dev;
741
    gx_device *             tdev = opdev->target;
742
    int                     code = 0;
743
 
744
    /* the overprint device must have a target */
745
    if (tdev == 0)
746
        return_error(gs_error_unknownerror);
747
    if ((code = gs_opendevice(tdev)) >= 0)
748
        gx_device_copy_params(dev, tdev);
749
    return code;
750
}
751
 
752
/*
753
 * The put_params method for the overprint device will check if the
754
 * target device has closed and, if so, close itself.
755
 */
756
private int
757
overprint_put_params(gx_device * dev, gs_param_list * plist)
758
{
759
    overprint_device_t *    opdev = (overprint_device_t *)dev;
760
    gx_device *             tdev = opdev->target;
761
    int                     code = 0;
762
 
763
 
764
    if (tdev != 0 && (code = dev_proc(tdev, put_params)(tdev, plist)) >= 0) {
765
        gx_device_decache_colors(dev);
766
        if (!tdev->is_open)
767
            code = gs_closedevice(dev);
768
    }
769
    return code;
770
}
771
 
772
/*
773
 * The overprint device must never be confused with a page device.
774
 * Thus, we always forward the request for the page device to the
775
 * target, as should all forwarding devices.
776
 */
777
private gx_device *
778
overprint_get_page_device(gx_device * dev)
779
{
780
    overprint_device_t *    opdev = (overprint_device_t *)dev;
781
    gx_device *             tdev = opdev->target;
782
 
783
    return tdev == 0 ? 0 : dev_proc(tdev, get_page_device)(tdev);
784
}
785
 
786
/*
787
 * Calling create_compositor on the overprint device just updates the
788
 * overprint parameters; no new device is created.
789
 */
790
private int
791
overprint_create_compositor(
792
    gx_device *             dev,
793
    gx_device **            pcdev,
794
    const gs_composite_t *  pct,
795
    gs_imager_state *	    pis,
796
    gs_memory_t *           memory )
797
{
798
    if (pct->type != &gs_composite_overprint_type)
799
        return gx_default_create_compositor(dev, pcdev, pct, pis, memory);
800
    else {
801
        int     code;
802
 
803
        /* device must already exist, so just update the parameters */
804
        code = update_overprint_params(
805
                       (overprint_device_t *)dev,
806
                       &((const gs_overprint_t *)pct)->params );
807
        if (code >= 0)
808
            *pcdev = dev;
809
        return code;
810
    }
811
}
812
 
813
 
814
/*
815
 * The two rectangle-filling routines (which do the actual work) are just
816
 * stubbs for the time being. The actual routines would allocate a buffer,
817
 * use get_bits_rectangle to build a buffer of the existing data, modify
818
 * the appropriate components, then invoke the copy_color procedure on the
819
 * target device.
820
 */
821
private int
822
overprint_generic_fill_rectangle(
823
    gx_device *     dev,
824
    int             x,
825
    int             y,
826
    int             width,
827
    int             height,
828
    gx_color_index  color )
829
{
830
    overprint_device_t *    opdev = (overprint_device_t *)dev;
831
    gx_device *             tdev = opdev->target;
832
 
833
    if (tdev == 0)
834
        return 0;
835
    else
836
        return gx_overprint_generic_fill_rectangle( tdev,
837
                                                    opdev->drawn_comps,
838
                                                    x, y, width, height,
839
                                                    color,
840
                                                    dev->memory );
841
}
842
 
843
private int
844
overprint_sep_fill_rectangle(
845
    gx_device *     dev,
846
    int             x,
847
    int             y,
848
    int             width,
849
    int             height,
850
    gx_color_index  color )
851
{
852
    overprint_device_t *    opdev = (overprint_device_t *)dev;
853
    gx_device *             tdev = opdev->target;
854
 
855
    if (tdev == 0)
856
        return 0;
857
    else {
858
        int     depth = tdev->color_info.depth;
859
 
860
        /*
861
         * Swap the color index into the order required by a byte-oriented
862
         * bitmap. This is required only for littl-endian processors, and
863
         * then only if the depth > 8.
864
         */
865
#if !arch_is_big_endian
866
        if (depth > 8)
867
            color = swap_color_index(depth, color);
868
#endif
869
 
870
        /*
871
         * We can handle rectangle filling via bits_fill_rectangle_masked
872
         * if the depth is a divisor of 8 * sizeof(mono_fill_chunk). The
873
         * non-masked fill_rectangle code uses a byte-oriented routine
874
         * if depth > 8, but there is not much advantage to doing so if
875
         * masking is required.
876
         *
877
         * Directly testing (8 * sizeof(mono_fill_chunk)) % depth is
878
         * potentially expensive, since many rectangles are small. We
879
         * can avoid the modulus operation by noting that
880
         * 8 * sizeof(mono_fill_chunk) will be a power of 2, and so
881
         * we need only check that depth is a power of 2 and
882
         * depth < 8 * sizeof(mono_fill_chunk).
883
         */
884
        if ( depth <= 8 * sizeof(mono_fill_chunk) &&
885
             (depth & (depth - 1)) == 0             )
886
            return gx_overprint_sep_fill_rectangle_1( tdev,
887
                                                      opdev->retain_mask,
888
                                                      x, y, width, height,
889
                                                      color,
890
                                                      dev->memory );
891
        else
892
            return gx_overprint_sep_fill_rectangle_2( tdev,
893
                                                      opdev->retain_mask,
894
                                                      x, y, width, height,
895
                                                      color,
896
                                                      dev->memory );
897
    }
898
}
899
 
900
 
901
/* complete a porcedure set */
902
private void
903
fill_in_procs(gx_device_procs * pprocs)
904
{
905
    gx_device_forward   tmpdev;
906
 
907
    /*
908
     * gx_device_forward_fill_in_procs calls gx_device_fill_in_procs, which
909
     * requires the color_info field of the device be set to "reasonable"
910
     * values. Which values is irrelevant in this case, but they must not
911
     * contain dangling pointers, excessive numbers of components, etc.
912
     */
913
    memcpy( &tmpdev.color_info,
914
            &gs_overprint_device.color_info,
915
            sizeof(tmpdev.color_info) );
916
    /*
917
     * Prevent the check_device_separable routine from executing while we
918
     * fill in the procs.  Our tmpdev is not complete enough for it.
919
     */
920
    tmpdev.color_info.separable_and_linear = GX_CINFO_SEP_LIN_NONE;
921
    tmpdev.static_procs = 0;
922
    memcpy(&tmpdev.procs, pprocs, sizeof(tmpdev.procs));
923
    gx_device_forward_fill_in_procs(&tmpdev);
924
    memcpy(pprocs, &tmpdev.procs, sizeof(tmpdev.procs));
925
}
926
 
927
/*
928
 * Create an overprint compositor.
929
 *
930
 * Note that this routine will be called only if the device is not already
931
 * an overprint compositor. Hence, if pct->params.retain_any_comps is
932
 * false, we can just return.
933
 *
934
 * We also suppress use of overprint if the current device color model has only
935
 * a single component. In this case overprint mode is inapplicable (it applies
936
 * only to CMYK devices), and nothing can possibly be gained by using overprint.
937
 * More significantly, this cause avoids erroneous use of overprint when a
938
 * mask caching device is the current device, which would otherwise require
939
 * elaborate special handling in the caching device create_compositor
940
 * procedure.
941
 */
942
private int
943
c_overprint_create_default_compositor(
944
    const gs_composite_t *  pct,
945
    gx_device **            popdev,
946
    gx_device *             tdev,
947
    gs_imager_state *	    pis,
948
    gs_memory_t *           mem )
949
{
950
    const gs_overprint_t *  ovrpct = (const gs_overprint_t *)pct;
951
    overprint_device_t *    opdev = 0;
952
 
953
    /* see if there is anything to do */
954
    if ( !ovrpct->params.retain_any_comps) {
955
        *popdev = tdev;
956
        return 0;
957
    }
958
 
959
    /* check if the procedure arrays have been initialized */
960
    if (no_overprint_procs.get_xfont_procs == 0) {
961
        fill_in_procs(&no_overprint_procs);
962
        fill_in_procs(&generic_overprint_procs);
963
        fill_in_procs(&sep_overprint_procs);
964
    }
965
 
966
    /* build the overprint device */
967
    opdev = gs_alloc_struct_immovable( mem,
968
                                       overprint_device_t,
969
                                       &st_overprint_device_t,
970
                                       "create overprint compositor" );
971
    if ((*popdev = (gx_device *)opdev) == 0)
972
        return_error(gs_error_VMerror);
973
    gx_device_init( (gx_device *)opdev, 
974
                    (const gx_device *)&gs_overprint_device,
975
                    mem,
976
                    true );
977
    gx_device_copy_params((gx_device *)opdev, tdev);
978
    gx_device_set_target((gx_device_forward *)opdev, tdev);
979
 
980
    /* set up the overprint parameters */
981
    return update_overprint_params( opdev,
982
                                    &((const gs_overprint_t *)pct)->params );
983
}