Coverage Report

Created: 2025-06-24 07:01

/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
170k
{
37
170k
    gx_device_color temp_devc;
38
39
170k
    memset(psc, 0, sizeof(*psc)); /* clear the entire structure */
40
170k
    psc->color_space_id = psc->pattern_id = gs_no_id;
41
170k
    color_set_null(&temp_devc);
42
170k
    temp_devc.type->save_dc(&temp_devc, &(psc->saved_dev_color));
43
170k
}
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
88.9M
{
55
88.9M
    memset(psc, 0, sizeof(*psc)); /* clear the entire structure */
56
57
88.9M
    if (pdevc == NULL) {
58
        /* No device color given, should not happen */
59
280
        gx_hld_saved_color_init(psc); /* revert to unknown color */
60
280
        return false;
61
88.9M
    } else if (pgs == NULL) {
62
        /* No color space, simply save device color specific info */
63
76.0M
        psc->color_space_id = psc->pattern_id = gs_no_id;
64
76.0M
        pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
65
76.0M
        return false;
66
76.0M
    } 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
12.9M
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
74
12.9M
        int i = gs_color_space_num_components(pcs);
75
76
12.9M
        psc->color_space_id = pcs->id;
77
12.9M
        pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
78
12.9M
        if (pdevc->type == gx_dc_type_pattern2)
79
25.6k
            i = 0;
80
12.9M
        else if (i < 0)
81
34.0k
            i = -i - 1; /* See gx_num_components_Pattern. */
82
33.8M
        for (i--; i >= 0; i--)
83
20.8M
            psc->ccolor.paint.values[i] = pdevc->ccolor.paint.values[i];
84
85
        /* Save the pattern id - if present */
86
12.9M
        if ((pdevc->type == gx_dc_type_pattern
87
12.9M
           || pdevc->type == gx_dc_type_pattern2) && pdevc->ccolor_valid)
88
37.6k
            psc->pattern_id = pdevc->ccolor.pattern->pattern_id;
89
12.9M
        else
90
12.9M
            psc->pattern_id = gs_no_id;
91
12.9M
        return true;
92
12.9M
    }
93
88.9M
}
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
88.6M
{
103
104
88.6M
    int i;
105
106
88.6M
    if (psc1->saved_dev_color.type != psc2->saved_dev_color.type
107
88.6M
     || psc1->color_space_id != psc2->color_space_id
108
88.6M
     || psc1->pattern_id != psc2->pattern_id
109
88.6M
     || psc1->ccolor_valid != psc2->ccolor_valid
110
88.6M
     || psc1->ccolor.pattern != psc2->ccolor.pattern
111
88.6M
     || psc1->saved_dev_color.phase.x != psc2->saved_dev_color.phase.x
112
88.6M
     || psc1->saved_dev_color.phase.y != psc2->saved_dev_color.phase.y) {
113
114
981k
        return(false);
115
981k
    }
116
117
    /* early bailout for pattern comparison */
118
87.6M
    if (gx_dc_is_pattern1_color((gx_device_color *)(&psc1->saved_dev_color.type))) {
119
120
140
        if (psc1->saved_dev_color.colors.pattern.id != psc2->saved_dev_color.colors.pattern.id)
121
0
            return(false);
122
140
        else
123
140
            return true;
124
140
    }
125
87.6M
    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
5.61G
    for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) {
134
5.52G
        if (psc1->ccolor.paint.values[i] != psc2->ccolor.paint.values[i]) {
135
1.33M
            return(false);
136
1.33M
        }
137
5.52G
    }
138
    /* NAFF: only gx_dc_pure_masked doesn't have a type checker */
139
86.3M
    if (gx_dc_is_pure(&psc1->saved_dev_color) || psc1->saved_dev_color.type == &gx_dc_pure_masked) {
140
86.2M
        if (psc1->saved_dev_color.colors.pure != psc2->saved_dev_color.colors.pure) {
141
33.4M
            return(false);
142
33.4M
        }
143
86.2M
    }
144
93.9k
    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
93.9k
    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
93.9k
    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
52.8M
    return (true);
175
86.3M
}
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
36.9k
{
183
36.9k
    if (psc1->color_space_id != psc2->color_space_id)
184
26.0k
        return false;
185
10.9k
    if (psc1->pattern_id != psc2->pattern_id)
186
0
        return false;
187
10.9k
    if (psc1->ccolor_valid != psc2->ccolor_valid)
188
0
        return false;
189
10.9k
    if (psc1->color_space_id != psc2->color_space_id)
190
0
        return false;
191
10.9k
    return true;
192
10.9k
}
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
5.69M
{
201
5.69M
    if (pgs != NULL && pdevc != NULL && pdevc->type != gx_dc_type_null && pdevc->ccolor_valid)
202
1.95M
        return true;
203
3.73M
    return false;
204
5.69M
}
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
2.66M
{
216
    /* Check if the current color space was used to build the device color */
217
2.66M
    if (gx_hld_is_hl_color_available(pgs, pdevc)) {
218
1.89M
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
219
220
1.89M
        *ppcs = pcs;
221
1.89M
        *ppcc = &(pdevc->ccolor);
222
1.89M
        if (pdevc->type == gx_dc_type_pattern
223
1.89M
           || pdevc->type == &gx_dc_pure_masked
224
1.89M
           || pdevc->type == gx_dc_type_pattern2)
225
18.8k
            return pattern_color_space;
226
1.87M
        else {
227
1.87M
            return non_pattern_color_space;
228
1.87M
        }
229
1.89M
    }
230
    /* No color space */
231
768k
    *ppcs = NULL;
232
768k
    *ppcc = NULL;
233
768k
    return use_process_color;
234
2.66M
}
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
828k
{
244
828k
    if (pgs != NULL) {
245
828k
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
246
828k
        int n = gs_color_space_num_components(pcs);
247
248
828k
        return (n >= 0 ? n : -n - 1);
249
828k
    } else
250
0
        return -1;
251
828k
}
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
}