Coverage Report

Created: 2025-06-10 07:24

/src/ghostpdl/base/gxhldevc.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/* High level device color save/compare procedures */
17
18
/*
19
 * See comments at the start of gxhldevc.h for more explanation of the
20
 * purpose and operation of these procedures.
21
 */
22
#include "gx.h"
23
#include "gzstate.h"
24
#include "gscspace.h"
25
#include "gxcspace.h"
26
#include "gxhldevc.h"
27
#include "memory_.h"
28
#include "gxpcolor.h"
29
#include "gsptype1.h"
30
#include "gsptype2.h"
31
32
/*
33
 * Initiailze a high level saved color to null
34
 */
35
void gx_hld_saved_color_init(gx_hl_saved_color * psc)
36
19.5k
{
37
19.5k
    gx_device_color temp_devc;
38
39
19.5k
    memset(psc, 0, sizeof(*psc)); /* clear the entire structure */
40
19.5k
    psc->color_space_id = psc->pattern_id = gs_no_id;
41
19.5k
    color_set_null(&temp_devc);
42
19.5k
    temp_devc.type->save_dc(&temp_devc, &(psc->saved_dev_color));
43
19.5k
}
44
45
/*
46
 * Save the device color information including the color space id and
47
 * client color data (if available).
48
 *
49
 * More description in src/gxhldevc.h
50
 */
51
bool
52
gx_hld_save_color(const gs_gstate * pgs, const gx_device_color * pdevc,
53
                gx_hl_saved_color * psc)
54
3.86M
{
55
3.86M
    memset(psc, 0, sizeof(*psc)); /* clear the entire structure */
56
57
3.86M
    if (pdevc == NULL) {
58
        /* No device color given, should not happen */
59
0
        gx_hld_saved_color_init(psc); /* revert to unknown color */
60
0
        return false;
61
3.86M
    } else if (pgs == NULL) {
62
        /* No color space, simply save device color specific info */
63
199k
        psc->color_space_id = psc->pattern_id = gs_no_id;
64
199k
        pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
65
199k
        return false;
66
3.66M
    } else {
67
        /*
68
         * Have color space, save id,  ccolor, & device color specific info.
69
         * Also save the high level colors since two gx_color_index values
70
         * may be the same but for differing high level colors (due to the
71
         * usual lower resolution of the gx_color_index values.
72
         */
73
3.66M
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
74
3.66M
        int i = gs_color_space_num_components(pcs);
75
76
3.66M
        psc->color_space_id = pcs->id;
77
3.66M
        pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
78
3.66M
        if (pdevc->type == gx_dc_type_pattern2)
79
3.40k
            i = 0;
80
3.65M
        else if (i < 0)
81
9.45k
            i = -i - 1; /* See gx_num_components_Pattern. */
82
9.65M
        for (i--; i >= 0; i--)
83
5.99M
            psc->ccolor.paint.values[i] = pdevc->ccolor.paint.values[i];
84
85
        /* Save the pattern id - if present */
86
3.66M
        if ((pdevc->type == gx_dc_type_pattern
87
3.66M
           || pdevc->type == gx_dc_type_pattern2) && pdevc->ccolor_valid)
88
6.62k
            psc->pattern_id = pdevc->ccolor.pattern->pattern_id;
89
3.65M
        else
90
3.65M
            psc->pattern_id = gs_no_id;
91
3.66M
        return true;
92
3.66M
    }
93
3.86M
}
94
95
/*
96
 * Compare two saved colors to check if match.
97
 * This routine used to be a simple memcmp(), but
98
 * that is insufficient, the checks must be explicit.
99
 */
100
bool gx_hld_saved_color_equal(const gx_hl_saved_color * psc1,
101
                           const gx_hl_saved_color * psc2)
102
3.76M
{
103
104
3.76M
    int i;
105
106
3.76M
    if (psc1->saved_dev_color.type != psc2->saved_dev_color.type
107
3.76M
     || psc1->color_space_id != psc2->color_space_id
108
3.76M
     || psc1->pattern_id != psc2->pattern_id
109
3.76M
     || psc1->ccolor_valid != psc2->ccolor_valid
110
3.76M
     || psc1->ccolor.pattern != psc2->ccolor.pattern
111
3.76M
     || psc1->saved_dev_color.phase.x != psc2->saved_dev_color.phase.x
112
3.76M
     || psc1->saved_dev_color.phase.y != psc2->saved_dev_color.phase.y) {
113
114
198k
        return(false);
115
198k
    }
116
117
    /* early bailout for pattern comparison */
118
3.57M
    if (gx_dc_is_pattern1_color((gx_device_color *)(&psc1->saved_dev_color.type))) {
119
120
23
        if (psc1->saved_dev_color.colors.pattern.id != psc2->saved_dev_color.colors.pattern.id)
121
0
            return(false);
122
23
        else
123
23
            return true;
124
23
    }
125
3.57M
    if (gx_dc_is_pattern2_color((gx_device_color *)(&psc1->saved_dev_color.type))) {
126
0
        if (psc1->saved_dev_color.colors.pattern2.id != psc2->saved_dev_color.colors.pattern2.id
127
0
         || psc1->saved_dev_color.colors.pattern2.shfill != psc2->saved_dev_color.colors.pattern2.shfill)
128
0
            return(false);
129
0
        else
130
0
            return true;
131
0
    }
132
133
217M
    for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) {
134
214M
        if (psc1->ccolor.paint.values[i] != psc2->ccolor.paint.values[i]) {
135
231k
            return(false);
136
231k
        }
137
214M
    }
138
    /* NAFF: only gx_dc_pure_masked doesn't have a type checker */
139
3.33M
    if (gx_dc_is_pure(&psc1->saved_dev_color) || psc1->saved_dev_color.type == &gx_dc_pure_masked) {
140
3.33M
        if (psc1->saved_dev_color.colors.pure != psc2->saved_dev_color.colors.pure) {
141
116k
            return(false);
142
116k
        }
143
3.33M
    }
144
0
    else if (gx_dc_is_binary_halftone(&psc1->saved_dev_color)) {
145
146
0
        if ((psc1->saved_dev_color.colors.binary.b_color[0] != psc2->saved_dev_color.colors.binary.b_color[0])
147
0
             || (psc1->saved_dev_color.colors.binary.b_color[1] != psc2->saved_dev_color.colors.binary.b_color[1])
148
0
             || (psc1->saved_dev_color.colors.binary.b_level != psc2->saved_dev_color.colors.binary.b_level)
149
0
             || (psc1->saved_dev_color.colors.binary.b_index != psc2->saved_dev_color.colors.binary.b_index)) {
150
151
0
            return(false);
152
0
        }
153
0
    }
154
0
    else if (gx_dc_is_colored_halftone(&psc1->saved_dev_color)) {
155
156
0
        for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) {
157
0
            if (psc1->saved_dev_color.colors.colored.c_base[i] != psc2->saved_dev_color.colors.colored.c_base[i]
158
0
              || psc1->saved_dev_color.colors.colored.c_level[i] != psc2->saved_dev_color.colors.colored.c_level[i]) {
159
160
0
                return(false);
161
0
            }
162
0
        }
163
0
    }
164
0
    else if (gx_dc_is_devn(&psc1->saved_dev_color)) {
165
166
0
        for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) {
167
0
             if (psc1->saved_dev_color.colors.devn.values[i] != psc2->saved_dev_color.colors.devn.values[i]) {
168
169
0
                 return(false);
170
0
             }
171
0
        }
172
0
    }
173
174
3.22M
    return (true);
175
3.33M
}
176
177
/*
178
 * Check whether two saved colors have same color space.
179
 */
180
bool gx_hld_saved_color_same_cspace(const gx_hl_saved_color * psc1,
181
                           const gx_hl_saved_color * psc2)
182
7.22k
{
183
7.22k
    if (psc1->color_space_id != psc2->color_space_id)
184
5.32k
        return false;
185
1.90k
    if (psc1->pattern_id != psc2->pattern_id)
186
0
        return false;
187
1.90k
    if (psc1->ccolor_valid != psc2->ccolor_valid)
188
0
        return false;
189
1.90k
    if (psc1->color_space_id != psc2->color_space_id)
190
0
        return false;
191
1.90k
    return true;
192
1.90k
}
193
194
/*
195
 * Check if a high level color is availavble.
196
 */
197
bool
198
gx_hld_is_hl_color_available(const gs_gstate * pgs,
199
                const gx_device_color * pdevc)
200
869k
{
201
869k
    if (pgs != NULL && pdevc != NULL && pdevc->type != gx_dc_type_null && pdevc->ccolor_valid)
202
583k
        return true;
203
286k
    return false;
204
869k
}
205
206
/*
207
 * Get pointers to the current color space and client color.
208
 *
209
 * More description in src/gxhldevc.h
210
 */
211
gx_hld_get_color_space_and_ccolor_status
212
gx_hld_get_color_space_and_ccolor(const gs_gstate * pgs,
213
                const gx_device_color * pdevc, const gs_color_space ** ppcs,
214
                const gs_client_color ** ppcc)
215
637k
{
216
    /* Check if the current color space was used to build the device color */
217
637k
    if (gx_hld_is_hl_color_available(pgs, pdevc)) {
218
576k
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
219
220
576k
        *ppcs = pcs;
221
576k
        *ppcc = &(pdevc->ccolor);
222
576k
        if (pdevc->type == gx_dc_type_pattern
223
576k
           || pdevc->type == &gx_dc_pure_masked
224
576k
           || pdevc->type == gx_dc_type_pattern2)
225
3.37k
            return pattern_color_space;
226
572k
        else {
227
572k
            return non_pattern_color_space;
228
572k
        }
229
576k
    }
230
    /* No color space */
231
61.5k
    *ppcs = NULL;
232
61.5k
    *ppcc = NULL;
233
61.5k
    return use_process_color;
234
637k
}
235
236
/*
237
 * Get the number of components in the current color space.
238
 *
239
 * More description in src/gxhldevc.h
240
 */
241
int
242
gx_hld_get_number_color_components(const gs_gstate * pgs)
243
156k
{
244
156k
    if (pgs != NULL) {
245
156k
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
246
156k
        int n = gs_color_space_num_components(pcs);
247
248
156k
        return (n >= 0 ? n : -n - 1);
249
156k
    } else
250
0
        return -1;
251
156k
}
252
253
/*
254
 * Get the requested high level color value.
255
 *
256
 * More description in src/gxhldevc.h
257
 */
258
gx_hld_get_color_component_status
259
gx_hld_get_color_component(const gs_gstate * pgs,
260
                          const gx_device_color * pdevc,
261
                          int comp_num, float * output)
262
0
{
263
0
    if (pdevc != NULL && pdevc->ccolor_valid) {
264
0
        int ncomp = gx_hld_get_number_color_components(pgs);
265
266
0
        if (ncomp < 0)
267
0
            return invalid_color_info;
268
0
        if (comp_num < 0 || comp_num >= ncomp)
269
0
            return invalid_component_requested;
270
0
        *output = pdevc->ccolor.paint.values[comp_num];
271
0
        return valid_result;
272
0
    }
273
0
    return invalid_color_info;
274
0
}