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) 1989, 2000 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: zcolor.c,v 1.21 2004/10/01 23:35:02 ghostgum Exp $ */
18
/* Color operators */
19
#include "memory_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "estack.h"
23
#include "ialloc.h"
24
#include "igstate.h"
25
#include "iutil.h"
26
#include "store.h"
27
#include "gxfixed.h"
28
#include "gxmatrix.h"
29
#include "gzstate.h"
30
#include "gxdcolor.h"		/* for gxpcolor.h */
31
#include "gxdevice.h"
32
#include "gxdevmem.h"		/* for gxpcolor.h */
33
#include "gxcmap.h"
34
#include "gxcspace.h"
35
#include "gxcolor2.h"
36
#include "gxpcolor.h"
37
#include "idict.h"
38
#include "icolor.h"
39
#include "idparam.h"
40
#include "iname.h"
41
 
42
/* imported from gsht.c */
43
extern  void    gx_set_effective_transfer(gs_state *);
44
 
45
/* define the number of stack slots needed for zcolor_remap_one */
46
const int   zcolor_remap_one_ostack = 4;
47
const int   zcolor_remap_one_estack = 3;
48
 
49
 
50
/* utility to test whether a Pattern instance uses a base space */
51
private inline bool
52
pattern_instance_uses_base_space(const gs_pattern_instance_t * pinst)
53
{
54
    return pinst->type->procs.uses_base_space(
55
                   pinst->type->procs.get_pattern(pinst) );
56
}
57
 
58
/*
59
 *  -   currentcolor   <param1>  ...  <paramN>
60
 *
61
 * Return the current color. <paramN> may be a dictionary or a null
62
 * object, if the current color space is a pattern color space. The
63
 * other parameters will be numeric.
64
 *
65
 * Note that the results of this operator differ slightly from those of
66
 * most currentcolor implementations. If a color component value is 
67
 * integral (e.g.: 0, 1), it will be pushed on the stack as an integer.
68
 * Most currentcolor implementations, including the earlier
69
 * implementation in Ghostscript, would push real objects for all
70
 * color spaces except indexed color space. The approach taken here is
71
 * equally legitimate, and avoids special handling of indexed color
72
 * spaces.
73
 */
74
private int
75
zcurrentcolor(i_ctx_t * i_ctx_p)
76
{
77
    os_ptr                  op = osp;
78
    const gs_color_space *  pcs = gs_currentcolorspace(igs);
79
    const gs_client_color * pcc = gs_currentcolor(igs);
80
    int                     i, n = cs_num_components(pcs);
81
    bool                    push_pattern = n < 0;
82
 
83
    /* check for pattern */
84
    if (push_pattern) {
85
        gs_pattern_instance_t * pinst = pcc->pattern;
86
 
87
        if (pinst == 0 || !pattern_instance_uses_base_space(pinst))
88
            n = 1;
89
        else
90
            n = -n;
91
    }
92
 
93
    /* check for sufficient space on the stack */
94
    push(n);
95
    op -= n - 1;
96
 
97
    /* push the numeric operands, if any */
98
    if (push_pattern)
99
        --n;
100
    for (i = 0; i < n; i++, op++) {
101
        float   rval = pcc->paint.values[i];
102
        int     ival = (int)rval;
103
 
104
        /* the following handles indexed color spaces */
105
        if (rval == ival)
106
            make_int(op, ival);
107
        else
108
            make_real(op, rval);
109
    }
110
 
111
    /* push the pattern dictionary or null object, if appropriate */
112
    if (push_pattern)
113
        *op = istate->pattern;
114
 
115
    return 0;
116
}
117
 
118
/*
119
 *  -   .currentcolorspace   <array>
120
 *
121
 * Return the current color space. Unlike the prior implementation, the
122
 * istate->color_space.array field will now always have a legitimate
123
 * (array) value.
124
 */
125
private int
126
zcurrentcolorspace(i_ctx_t * i_ctx_p)
127
{
128
    os_ptr  op = osp;   /* required by "push" macro */
129
 
130
    push(1);
131
    if ( gs_color_space_get_index(igs->color_space) == gs_color_space_index_DeviceGray ) {
132
        ref gray, graystr;
133
        ref csa = istate->colorspace.array; 
134
        if (array_get(imemory, &csa, 0, &gray) >= 0 && 
135
            r_has_type(&gray, t_name) && 
136
	    (name_string_ref(imemory, &gray, &graystr),
137
	    r_size(&graystr) == 10 &&
138
	    !memcmp(graystr.value.bytes, "DeviceGray", 10))) {
139
 
140
            *op = istate->colorspace.array;
141
        } else {
142
	    int code = ialloc_ref_array(op, a_all, 1, "currentcolorspace");
143
	    if (code < 0)
144
	        return code;
145
	    return name_enter_string(imemory, "DeviceGray", op->value.refs);
146
        }
147
    } else
148
        *op = istate->colorspace.array;
149
    return 0;
150
}
151
 
152
/*
153
 *  -   .getuseciecolor   <bool>
154
 *
155
 * Return the current setting of the use_cie_color graphic state parameter,
156
 * which tracks the UseCIEColor page device parameter. This parameter may be
157
 * read (via this operator) at all language leves, but may only be set (via
158
 * the .setuseciecolor operator; see zcolor3.c) only in language level 3.
159
 *
160
 * We handle this parameter separately from the page device primarily for
161
 * performance reasons (the parameter may be queried frequently), but as a
162
 * side effect achieve proper behavior relative to the language level. The
163
 * interpreter is always initialized with this parameter set to false, and
164
 * it can only be updated (via setpagedevice) in language level 3.
165
 */
166
private int
167
zgetuseciecolor(i_ctx_t * i_ctx_p)
168
{
169
    os_ptr  op = osp;
170
 
171
    push(1);
172
    *op = istate->use_cie_color;
173
    return 0;
174
}
175
 
176
/*
177
 *  <param1>  ...  <paramN>   setcolor   -
178
 *
179
 * Set the current color. All of the parameters except the topmost (paramN) are
180
 * numbers; the topmost (and possibly only) entry may be pattern dictionary or
181
 * a null object.
182
 *
183
 * The use of one operator to set both patterns and "normal" colors is
184
 * consistent with Adobe's documentation, but primarily reflects the use of
185
 * gs_setcolor for both purposes in the graphic library. An alternate
186
 * implementation would use a .setpattern operator, which would interface with
187
 * gs_setpattern.
188
 *
189
 * This operator is hidden by a pseudo-operator of the same name, so it will
190
 * only be invoked under controlled situations. Hence, it does no operand
191
 * checking.
192
 */
193
private int
194
zsetcolor(i_ctx_t * i_ctx_p)
195
{
196
    os_ptr                  op = osp;
197
    const gs_color_space *  pcs = gs_currentcolorspace(igs);
198
    gs_client_color         cc;
199
    int                     n_comps, n_numeric_comps, num_offset = 0, code;
200
    bool                    is_ptype2 = 0;
201
 
202
    /* initialize the client color pattern pointer for GC */
203
    cc.pattern = 0;
204
 
205
    /* check for a pattern color space */
206
    if ((n_comps = cs_num_components(pcs)) < 0) {
207
        n_comps = -n_comps;
208
        if (r_has_type(op, t_dictionary)) {
209
            ref *   pImpl;
210
            int     ptype;
211
 
212
            dict_find_string(op, "Implementation", &pImpl);
213
            cc.pattern = r_ptr(pImpl, gs_pattern_instance_t);
214
            n_numeric_comps = ( pattern_instance_uses_base_space(cc.pattern)
215
                                  ? n_comps - 1
216
                                  : 0 );
217
            (void)dict_int_param(op, "PatternType", 1, 2, 1, &ptype);
218
            is_ptype2 = ptype == 2;
219
        } else
220
            n_numeric_comps = 0;
221
        num_offset = 1;
222
    } else
223
        n_numeric_comps = n_comps;
224
 
225
    /* gather the numeric operands */
226
    float_params(op - num_offset, n_numeric_comps, cc.paint.values);
227
 
228
    /* pass the color to the graphic library */
229
    if ((code = gs_setcolor(igs, &cc)) >= 0) {
230
 
231
        if (n_comps > n_numeric_comps) {
232
            istate->pattern = *op;      /* save pattern dict or null */
233
            n_comps = n_numeric_comps + 1;
234
        }
235
        pop(n_comps);
236
    }
237
 
238
    return code;
239
}
240
 
241
/*
242
 *  <array>   setcolorspace   -
243
 *
244
 * Set the nominal color space. This color space will be pushd by the
245
 * currentcolorspace operator, but is not directly used to pass color
246
 * space information to the graphic library.
247
 *
248
 * This operator can only be called from within the setcolorspace
249
 * pseudo-operator; the definition of the latter will override this
250
 * definition. Because error cheching is performed by the pseudo-
251
 * operator, it need not be repeated here.
252
 */
253
private int
254
zsetcolorspace(i_ctx_t * i_ctx_p)
255
{
256
    os_ptr  op = osp;
257
 
258
    istate->colorspace.array = *op;
259
    pop(1);
260
    return 0;
261
}
262
 
263
/*
264
 *  <name> .includecolorspace -
265
 *
266
 * See the comment for gs_includecolorspace in gscolor2.c .
267
 */
268
private int
269
zincludecolorspace(i_ctx_t * i_ctx_p)
270
{
271
    os_ptr  op = osp;
272
    ref nsref;
273
    int code;
274
 
275
    check_type(*op, t_name);
276
    name_string_ref(imemory, op, &nsref);
277
    code =  gs_includecolorspace(igs, nsref.value.const_bytes, r_size(&nsref));
278
    if (!code)
279
	pop(1);
280
    return code;
281
}
282
 
283
 
284
/*
285
 *  <int>   .setdevcspace   -
286
 *
287
 * Set a parameterless color space. This is now used to set the
288
 * DeviceGray, DeviceRGB, and DeviceCMYK color spaces, rather than
289
 * the setgray/setrgbcolor/setcmykcolor operators. All PostScript-based
290
 * color space substitution will have been accomplished before this
291
 * operator is called.
292
 *
293
 * The use of an integer to indicate the specific color space is 
294
 * historical and on the whole not particularly desirable, as it ties
295
 * the PostScript code to a specific enumeration. This may be modified
296
 * in the future.
297
 *
298
 * As with setcolorspace, this operator is called only under controlled
299
 * circumstances, hence it does no operand error checking.
300
 */
301
private int
302
zsetdevcspace(i_ctx_t * i_ctx_p)
303
{
304
 
305
    gs_color_space  cs;
306
    int             code;
307
 
308
    switch((gs_color_space_index)osp->value.intval) {
309
      default:  /* can't happen */
310
      case gs_color_space_index_DeviceGray:
311
	gs_cspace_init_DeviceGray(imemory, &cs);
312
        break;
313
 
314
      case gs_color_space_index_DeviceRGB:
315
        gs_cspace_init_DeviceRGB(imemory, &cs);
316
        break;
317
 
318
      case gs_color_space_index_DeviceCMYK:
319
        gs_cspace_init_DeviceCMYK(imemory, &cs);
320
        break;
321
    }
322
    if ((code = gs_setcolorspace(igs, &cs)) >= 0)
323
        pop(1);
324
    return code;
325
}
326
 
327
 
328
/*  -   currenttransfer   <proc> */
329
private int
330
zcurrenttransfer(i_ctx_t *i_ctx_p)
331
{
332
    os_ptr  op = osp;
333
 
334
    push(1);
335
    *op = istate->transfer_procs.gray;
336
    return 0;
337
}
338
 
339
/*
340
 *  -   processcolors   <int>  -
341
 *
342
 * Note: this is an undocumented operator that is not supported
343
 * in Level 2.
344
 */
345
private int
346
zprocesscolors(i_ctx_t * i_ctx_p)
347
{
348
    os_ptr  op = osp;
349
 
350
    push(1);
351
    make_int(op, gs_currentdevice(igs)->color_info.num_components);
352
    return 0;
353
}
354
 
355
/* <proc> settransfer - */
356
private int
357
zsettransfer(i_ctx_t * i_ctx_p)
358
{
359
    os_ptr  op = osp;
360
    int     code;
361
 
362
    check_proc(*op);
363
    check_ostack(zcolor_remap_one_ostack - 1);
364
    check_estack(1 + zcolor_remap_one_estack);
365
    istate->transfer_procs.red =
366
        istate->transfer_procs.green =
367
        istate->transfer_procs.blue =
368
        istate->transfer_procs.gray = *op;
369
    if ((code = gs_settransfer_remap(igs, gs_mapped_transfer, false)) < 0)
370
        return code;
371
    push_op_estack(zcolor_reset_transfer);
372
    pop(1);
373
    return zcolor_remap_one( i_ctx_p,
374
                             &istate->transfer_procs.gray,
375
                             igs->set_transfer.gray,
376
                             igs,
377
                             zcolor_remap_one_finish );
378
}
379
 
380
 
381
/*
382
 * Internal routines
383
 */
384
 
385
/*
386
 * Prepare to remap one color component (also used for black generation
387
 * and undercolor removal). Use the 'for' operator to gather the values.
388
 * The caller must have done the necessary check_ostack and check_estack.
389
 */
390
int
391
zcolor_remap_one(
392
    i_ctx_t *           i_ctx_p,
393
    const ref *         pproc,
394
    gx_transfer_map *   pmap,
395
    const gs_state *    pgs,
396
    op_proc_t           finish_proc )
397
{
398
    os_ptr              op;
399
 
400
    /*
401
     * Detect the identity function, which is a common value for one or
402
     * more of these functions.
403
     */
404
    if (r_size(pproc) == 0) {
405
	gx_set_identity_transfer(pmap);
406
	/*
407
	 * Even though we don't actually push anything on the e-stack, all
408
	 * clients do, so we return o_push_estack in this case.  This is
409
	 * needed so that clients' finishing procedures will get run.
410
	 */
411
	return o_push_estack;
412
    }
413
    op = osp += 4;
414
    make_real(op - 3, 0);
415
    make_int(op - 2, transfer_map_size - 1);
416
    make_real(op - 1, 1);
417
    *op = *pproc;
418
    ++esp;
419
    make_struct(esp, imemory_space((gs_ref_memory_t *) pgs->memory),
420
		pmap);
421
    push_op_estack(finish_proc);
422
    push_op_estack(zfor_samples);
423
    return o_push_estack;
424
}
425
 
426
/* Store the result of remapping a component. */
427
private int
428
zcolor_remap_one_store(i_ctx_t *i_ctx_p, floatp min_value)
429
{
430
    int i;
431
    gx_transfer_map *pmap = r_ptr(esp, gx_transfer_map);
432
 
433
    if (ref_stack_count(&o_stack) < transfer_map_size)
434
	return_error(e_stackunderflow);
435
    for (i = 0; i < transfer_map_size; i++) {
436
	double v;
437
	int code =
438
	    real_param(ref_stack_index(&o_stack, transfer_map_size - 1 - i),
439
		       &v);
440
 
441
	if (code < 0)
442
	    return code;
443
	pmap->values[i] =
444
	    (v < min_value ? float2frac(min_value) :
445
	     v >= 1.0 ? frac_1 :
446
	     float2frac(v));
447
    }
448
    ref_stack_pop(&o_stack, transfer_map_size);
449
    esp--;			/* pop pointer to transfer map */
450
    return o_pop_estack;
451
}
452
int
453
zcolor_remap_one_finish(i_ctx_t *i_ctx_p)
454
{
455
    return zcolor_remap_one_store(i_ctx_p, 0.0);
456
}
457
int
458
zcolor_remap_one_signed_finish(i_ctx_t *i_ctx_p)
459
{
460
    return zcolor_remap_one_store(i_ctx_p, -1.0);
461
}
462
 
463
/* Finally, reset the effective transfer functions and */
464
/* invalidate the current color. */
465
int
466
zcolor_reset_transfer(i_ctx_t *i_ctx_p)
467
{
468
    gx_set_effective_transfer(igs);
469
    return zcolor_remap_color(i_ctx_p);
470
}
471
int
472
zcolor_remap_color(i_ctx_t *i_ctx_p)
473
{
474
    gx_unset_dev_color(igs);
475
    return 0;
476
}
477
 
478
/* 
479
 * <param1> ... <paramN> .color_test <param1> ... <paramN>
480
 *
481
 * encode and decode color to allow mapping to be tested.
482
 */
483
private int
484
zcolor_test(i_ctx_t *i_ctx_p)
485
{
486
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
487
    gx_device *dev = gs_currentdevice(igs);
488
    int ncomp = dev->color_info.num_components;
489
    gx_color_index color;
490
    os_ptr op = osp - (ncomp-1);
491
    int i;
492
    if (ref_stack_count(&o_stack) < ncomp)
493
	return_error(e_stackunderflow);
494
    for (i = 0; i < ncomp; i++) {
495
	if (r_has_type(op+i, t_real))
496
	    cv[i] = (gx_color_value)
497
		(op[i].value.realval * gx_max_color_value);
498
	else if (r_has_type(op+i, t_integer))
499
	    cv[i] = (gx_color_value)
500
		(op[i].value.intval * gx_max_color_value);
501
	else
502
	    return_error(e_typecheck);
503
    }
504
    color = (*dev_proc(dev, encode_color)) (dev, cv);
505
    (*dev_proc(dev, decode_color)) (dev, color, cv);
506
    for (i = 0; i < ncomp; i++)
507
        make_real(op+i, (float)cv[i] / (float)gx_max_color_value);
508
    return 0;
509
}
510
 
511
/* 
512
 * <levels> .color_test_all <value0> ... <valueN>
513
 *
514
 * Test encode/decode color procedures for a range of values.
515
 * Return value with the worst error in a single component.
516
 */
517
private int
518
zcolor_test_all(i_ctx_t *i_ctx_p)
519
{
520
    os_ptr                  op = osp;
521
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
522
    gx_color_value cvout[GX_DEVICE_COLOR_MAX_COMPONENTS];
523
    gx_color_value cvbad[GX_DEVICE_COLOR_MAX_COMPONENTS];
524
    int counter[GX_DEVICE_COLOR_MAX_COMPONENTS];
525
    gx_device *dev = gs_currentdevice(igs);
526
    int ncomp = dev->color_info.num_components;
527
    int steps;
528
    int maxerror = 0;
529
    int err;
530
    int acceptable_error;
531
    int linsep = dev->color_info.separable_and_linear == GX_CINFO_SEP_LIN;
532
    int linsepfailed = 0;
533
    int lsmaxerror = 0;
534
    gx_color_index color, lscolor;
535
    int i, j, k;
536
    int finished = 0;
537
 
538
    if (ncomp == 1) 
539
	acceptable_error = gx_max_color_value / dev->color_info.max_gray + 1;
540
    else
541
	acceptable_error = gx_max_color_value / dev->color_info.max_color + 1;
542
 
543
    if (ref_stack_count(&o_stack) < 1)
544
	return_error(e_stackunderflow);
545
    if (!r_has_type(&osp[0], t_integer))
546
        return_error(e_typecheck);
547
    steps = osp[0].value.intval;
548
    for (i = 0; i < ncomp; i++) {
549
        counter[i] = 0; 
550
	cvbad[i] = 0;
551
    }
552
 
553
    dprintf1("Number of components = %d\n", ncomp);
554
    dprintf1("Depth = %d\n", dev->color_info.depth);
555
    dprintf2("max_gray = %d   dither_grays = %d\n", 
556
	dev->color_info.max_gray, dev->color_info.dither_grays);
557
    dprintf2("max_color = %d   dither_colors = %d\n", 
558
 	dev->color_info.max_color, dev->color_info.dither_colors);
559
    dprintf1("polarity = %s\n", 
560
      dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE ? "Additive" :
561
      dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE ?"Subtractive":
562
      "Unknown");
563
    /* Indicate color index value with all colorants = zero */
564
    for (i = 0; i < ncomp; i++)
565
	cv[i] = 0;
566
    color = (*dev_proc(dev, encode_color)) (dev, cv);
567
    dprintf1("Zero color index:  %8x\n", color);
568
 
569
    dprintf1("separable_and_linear = %s\n", 
570
      linsep == GX_CINFO_SEP_LIN_NONE ? "No" :
571
      linsep == GX_CINFO_SEP_LIN ? "Yes" :
572
      "Unknown");
573
    if (dev->color_info.gray_index == GX_CINFO_COMP_INDEX_UNKNOWN)
574
        dprintf("gray_index is unknown\n");
575
    else
576
        dprintf1("gray_index = %d\n", dev->color_info.gray_index);
577
    if (linsep) {
578
        dprintf(" Shift     Mask  Bits\n");
579
        for (i = 0; i < ncomp; i++) {
580
            dprintf3(" %5d %8x  %4d\n",
581
		(int)(dev->color_info.comp_shift[i]),
582
		(int)(dev->color_info.comp_mask[i]),
583
		(int)(dev->color_info.comp_bits[i]));
584
        }
585
    }
586
 
587
    while (!finished) {
588
	for (j = 0; j <= steps; j++) {
589
	    for (i = 0; i < ncomp; i++)
590
		cv[i] = counter[i] * gx_max_color_value / steps;
591
	    color = (*dev_proc(dev, encode_color)) (dev, cv);
592
	    if (linsep) {
593
		/* Derive it the other way */
594
		lscolor = gx_default_encode_color(dev, cv);
595
		if ((color != lscolor) && (linsepfailed < 5)) {
596
		    linsepfailed++;
597
		    dprintf("Failed separable_and_linear for");
598
		    for (i = 0; i < ncomp; i++)
599
			dprintf1(" %d", cv[i]);
600
		    dprintf("\n");
601
		    dprintf2("encode_color=%x  gx_default_encode_color=%x\n",
602
			(int)color, (int)lscolor);
603
		}
604
	    }
605
	    (*dev_proc(dev, decode_color)) (dev, color, cvout);
606
	    for (i = 0; i < ncomp; i++) {
607
		err = (int)cvout[i] - (int)cv[i];
608
		if (err < 0)
609
		    err = -err;
610
		if (err > maxerror) {
611
		    maxerror = err;
612
		    for (k=0; k < ncomp; k++)
613
			cvbad[k] = cv[k];
614
		}
615
	    }
616
	    if (linsep) {
617
	        gx_default_decode_color(dev, color, cvout);
618
		for (i = 0; i < ncomp; i++) {
619
		    err = (int)cvout[i] - (int)cv[i];
620
		    if (err < 0)
621
			err = -err;
622
		    if (err > lsmaxerror) {
623
			lsmaxerror = err;
624
		    }
625
		}
626
	    }
627
	    counter[0] += 1;
628
	}
629
	counter[0] = 0;
630
	i = 1;
631
	while (i < ncomp) {
632
	    counter[i] += 1;
633
	    if (counter[i] > steps) {
634
		counter[i] = 0;
635
		i++;
636
	    }
637
	    else
638
		break;
639
	}
640
	if (i >= ncomp)
641
	    finished = 1;
642
    }
643
 
644
    dprintf2("Maximum error %g %s\n", 
645
	(float)maxerror / (float)gx_max_color_value,
646
	maxerror <= acceptable_error ? "is Ok" :
647
	maxerror <= 3*acceptable_error/2 ? "is POOR" : "FAILED");
648
 
649
    if (linsep)
650
      dprintf2("Maximum linear_and_separable error %g %s\n", 
651
	(float)lsmaxerror / (float)gx_max_color_value,
652
	lsmaxerror <= acceptable_error ? "is Ok" :
653
	lsmaxerror <= 3*acceptable_error/2 ? "is POOR" : "FAILED");
654
 
655
    /* push worst value */
656
    push(ncomp-1);
657
    op -= ncomp - 1;
658
    for (i = 0; i < ncomp; i++)
659
        make_real(op+i, (float)cvbad[i] / (float)gx_max_color_value);
660
 
661
    return 0;
662
}
663
 
664
 
665
/* ------ Initialization procedure ------ */
666
 
667
const op_def    zcolor_op_defs[] = 
668
{
669
    { "0currentcolor", zcurrentcolor },
670
    { "0currentcolorspace", zcurrentcolorspace },
671
    { "0.getuseciecolor", zgetuseciecolor },
672
    { "1setcolor", zsetcolor },
673
    { "1setcolorspace", zsetcolorspace },
674
    { "1.setdevcspace", zsetdevcspace },
675
 
676
    /* basic transfer operators */
677
    { "0currenttransfer", zcurrenttransfer },
678
    { "0processcolors", zprocesscolors },
679
    { "1settransfer", zsettransfer },
680
 
681
    /* internal operators */
682
    { "1%zcolor_remap_one_finish", zcolor_remap_one_finish },
683
    { "1%zcolor_remap_one_signed_finish", zcolor_remap_one_signed_finish },
684
    { "0%zcolor_reset_transfer", zcolor_reset_transfer },
685
    { "0%zcolor_remap_color", zcolor_remap_color },
686
    { "0.color_test", zcolor_test },
687
    { "1.color_test_all", zcolor_test_all },
688
 
689
 
690
    /* high level device support */
691
    { "0.includecolorspace", zincludecolorspace },
692
    op_def_end(0)
693
};