summaryrefslogtreecommitdiff
path: root/base/gsnamecl.c
blob: 8b51c6d91e5ff6c1c9f6868dc2e9175aac18412c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/* Copyright (C) 2001-2023 Artifex Software, Inc.
   All Rights Reserved.

   This software is provided AS-IS with no warranty, either express or
   implied.

   This software is distributed under license and may not be copied,
   modified or distributed except as expressly authorized under the terms
   of the license contained in the file LICENSE in this distribution.

   Refer to licensing information at http://www.artifex.com or contact
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
   CA 94129, USA, for further information.
*/

/* Callback mechanism for handling color spaces containing named colors. */

/*
 * This module has been created to provide a callback mechanism for special
 * processing of DeviceN and Separation color spaces.  One possible application
 * of this callback mechanism is to provide a means for special handling of
 * PANTONE or SWOP colors.
 *
 * This implementation consists of four routines.  There are a pair of
 * routines for both Separation and DeviceN color spaces.  Each pair consists
 * of a routine that is called when the color space is installed and a
 * second routine that is called to transform colors in that color space
 * into device colorant values.  The routines named_color_install_Separation
 * and named_color_install_DeviceN are called when a Separation or DeviceN
 * color space is installed.  These routines determine if the given color space
 * meets some criteria decided by the client.  These routines return true if the
 * colors in the color space should be processed via the second routine.
 */

#include "stdpre.h"
#include "math_.h"
#include "memory_.h"
#include "gx.h"
#include "gserrors.h"
#include "gscdefs.h"
#include "gscspace.h"
#include "gxdevice.h"
#include "gzstate.h"
#include "gsutil.h"
#include "gsnamecl.h"  /* Custom color call back define */

#if ENABLE_CUSTOM_COLOR_CALLBACK	/* Defined in src/gsnamecl.h */

/*
 * Check if we want to use the callback color processing logic for the given
 * Separation color space.
 */
bool
custom_color_callback_install_Separation(gs_color_space * pcs, gs_gstate * pgs)
{
        client_custom_color_params_t * pcb =
        (client_custom_color_params_t *) pgs->memory->gs_lib_ctx->custom_color_callback;

    return (pcb == NULL) ? false
                         : pcb->client_procs->install_Separation(pcb, pcs, pgs);
}

/*
 * Check if we want to use the callback color processing logic for the given
 * DeviceN color space.
 */
bool
custom_color_callback_install_DeviceN(gs_color_space * pcs, gs_gstate * pgs)
{
    client_custom_color_params_t * pcb =
        (client_custom_color_params_t *) pgs->memory->gs_lib_ctx->custom_color_callback;

    return (pcb == NULL) ? false
                         : pcb->client_procs->install_DeviceN(pcb, pcs, pgs);
  }

/*
 * Convert a Separation color using the 'custom color' callback into
 * device color.
*/
int
gx_remap_concrete_custom_color_Separation(const frac * pconc,
        const gs_color_space * pcs, gx_device_color * pdc,
                const gs_gstate * pgs, gx_device * dev, gs_color_select_t select)
{
    client_custom_color_params_t * pcb =
        (client_custom_color_params_t *) pgs->memory->gs_lib_ctx->custom_color_callback;

      if (pcb == NULL) {
        return_error(gs_error_rangecheck);
    }
    else
        return pcb->client_procs->remap_Separation(pcb, pconc,
                                        pcs, pdc, pgs, dev, select);
}

/*
 * Convert a DeviceN color using the 'custom color' callback into device
 * color.
 */
int
gx_remap_concrete_custom_color_DeviceN(const frac * pconc,
        const gs_color_space * pcs, gx_device_color * pdc,
        const gs_gstate * pgs, gx_device * dev, gs_color_select_t select)
{
    client_custom_color_params_t * pcb =
        (client_custom_color_params_t *) pgs->memory->gs_lib_ctx->custom_color_callback;

        if (pcb == NULL) {
                return_error(gs_error_rangecheck);
    }
    else
                return pcb->client_procs->remap_DeviceN(pcb, pconc,
                                        pcs, pdc, pgs, dev, select);
}

/*
 * Get the 'custom color' client callback parameter block pointer.  This value
 * is passed as a string type device paramter.  A string is being used since
 * PostScript does not support pointers as a type.  Note:  An integer type
 * is not being used since PS intergers are nominally 32 bits.  Thus there
 * would be a problem using integers to pass pointer values on 64 bit systems.
 */
int
custom_color_callback_get_params(gs_gstate * pgs, gs_param_list * plist)
{
    /* Convert our pointer to a PostScript hex string */
    char buf[64] = "16#";
    int buf_pos = 3;
    gs_param_string custom_color_param;
    int idx;
    int val;
    size_t iptr;

    idx = ((int)sizeof(size_t)) * 8 - 4;
    iptr = (size_t)(pgs->memory->gs_lib_ctx->custom_color_callback);
    while (idx >= 0) {
        val = (int)(iptr >> idx) & 0xf;
    if (val <= 9)
                buf[buf_pos++] = '0' + val;
        else
            buf[buf_pos++] = 'a' - 10 + val;
        idx -= 4;
    }
    param_string_from_transient_string(custom_color_param, buf);

    return param_write_string(plist, CustomColorCallbackParamName,
                                         &custom_color_param);
}

/*
 * Put the 'custom color' client callback parameter block pointer.  This value
 * is passed as a string type device paramter.  A string is being used since
 * PostScript does not support pointers as a type.  Note:  An integer type
 * is not being used since PS integers are nominally 32 bits.  Thus there
 * would be a problem using integers to pass pointer values on 64 bit systems.
 */
int
custom_color_callback_put_params(gs_gstate * pgs, gs_param_list * plist)
{
    int code;
    size_t iptr = (size_t)(pgs->memory->gs_lib_ctx->custom_color_callback);
    gs_param_string dh = { 0 };

    switch (code = param_read_string(plist, CustomColorCallbackParamName, &dh)) {
        case 0:
        {
       /*
        * Convert from a string to a pointer.
        * It is assumed that size_t has the same size as a pointer.
        * Allow formats (1234), (10#1234) or (16#04d2).
        */
                uint i;
                int base = 10;
                int val;
                code = 0;
                for (i = 0; i < dh.size; i++) {
                        val = dh.data[i];
                        if ((val >= '0') && (val <= '9'))
                                val = val - '0';
                        else if ((val >= 'A') && (val <= 'F'))
                        val = val - 'A' + 10;
                        else if ((val >= 'a') && (val <= 'f'))
                        val = val - 'a' + 10;
                        else if (val == '#' && ((iptr == 10) || (iptr == 16))) {
                        base = (int) iptr;
                        iptr = 0;
                        continue;
                        }
                        else {
                        code = gs_error_rangecheck;
                        break;
                        }
                        iptr = iptr * base + val;
                }
        }
        break;
        default:
        case 1:
            dh.data = 0;
            break;
    }
    if (code < 0) {
        param_signal_error(plist, "CustomColorCallback", code);
    }
    else if (pgs->memory->gs_lib_ctx->custom_color_callback != (void *)iptr) {
        pgs->memory->gs_lib_ctx->custom_color_callback = (void *)iptr;
    }

    return 0;
}

#endif 			/* ENABLE_CUSTOM_COLOR_CALLBACK */