Coverage Report

Created: 2025-06-10 06:58

/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
43.6k
{
37
43.6k
    gx_device_color temp_devc;
38
39
43.6k
    memset(psc, 0, sizeof(*psc)); /* clear the entire structure */
40
43.6k
    psc->color_space_id = psc->pattern_id = gs_no_id;
41
43.6k
    color_set_null(&temp_devc);
42
43.6k
    temp_devc.type->save_dc(&temp_devc, &(psc->saved_dev_color));
43
43.6k
}
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.25M
{
55
3.25M
    memset(psc, 0, sizeof(*psc)); /* clear the entire structure */
56
57
3.25M
    if (pdevc == NULL) {
58
        /* No device color given, should not happen */
59
23.0k
        gx_hld_saved_color_init(psc); /* revert to unknown color */
60
23.0k
        return false;
61
3.23M
    } else if (pgs == NULL) {
62
        /* No color space, simply save device color specific info */
63
41.5k
        psc->color_space_id = psc->pattern_id = gs_no_id;
64
41.5k
        pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
65
41.5k
        return false;
66
3.19M
    } 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.19M
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
74
3.19M
        int i = gs_color_space_num_components(pcs);
75
76
3.19M
        psc->color_space_id = pcs->id;
77
3.19M
        pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
78
3.19M
        if (pdevc->type == gx_dc_type_pattern2)
79
20.1k
            i = 0;
80
3.17M
        else if (i < 0)
81
24.5k
            i = -i - 1; /* See gx_num_components_Pattern. */
82
8.97M
        for (i--; i >= 0; i--)
83
5.78M
            psc->ccolor.paint.values[i] = pdevc->ccolor.paint.values[i];
84
85
        /* Save the pattern id - if present */
86
3.19M
        if ((pdevc->type == gx_dc_type_pattern
87
3.19M
           || pdevc->type == gx_dc_type_pattern2) && pdevc->ccolor_valid)
88
29.1k
            psc->pattern_id = pdevc->ccolor.pattern->pattern_id;
89
3.16M
        else
90
3.16M
            psc->pattern_id = gs_no_id;
91
3.19M
        return true;
92
3.19M
    }
93
3.25M
}
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.12M
{
103
104
3.12M
    int i;
105
106
3.12M
    if (psc1->saved_dev_color.type != psc2->saved_dev_color.type
107
3.12M
     || psc1->color_space_id != psc2->color_space_id
108
3.12M
     || psc1->pattern_id != psc2->pattern_id
109
3.12M
     || psc1->ccolor_valid != psc2->ccolor_valid
110
3.12M
     || psc1->ccolor.pattern != psc2->ccolor.pattern
111
3.12M
     || psc1->saved_dev_color.phase.x != psc2->saved_dev_color.phase.x
112
3.12M
     || psc1->saved_dev_color.phase.y != psc2->saved_dev_color.phase.y) {
113
114
206k
        return(false);
115
206k
    }
116
117
    /* early bailout for pattern comparison */
118
2.92M
    if (gx_dc_is_pattern1_color((gx_device_color *)(&psc1->saved_dev_color.type))) {
119
120
27
        if (psc1->saved_dev_color.colors.pattern.id != psc2->saved_dev_color.colors.pattern.id)
121
0
            return(false);
122
27
        else
123
27
            return true;
124
27
    }
125
2.92M
    if (gx_dc_is_pattern2_color((gx_device_color *)(&psc1->saved_dev_color.type))) {
126
21
        if (psc1->saved_dev_color.colors.pattern2.id != psc2->saved_dev_color.colors.pattern2.id
127
21
         || psc1->saved_dev_color.colors.pattern2.shfill != psc2->saved_dev_color.colors.pattern2.shfill)
128
0
            return(false);
129
21
        else
130
21
            return true;
131
21
    }
132
133
179M
    for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) {
134
176M
        if (psc1->ccolor.paint.values[i] != psc2->ccolor.paint.values[i]) {
135
164k
            return(false);
136
164k
        }
137
176M
    }
138
    /* NAFF: only gx_dc_pure_masked doesn't have a type checker */
139
2.75M
    if (gx_dc_is_pure(&psc1->saved_dev_color) || psc1->saved_dev_color.type == &gx_dc_pure_masked) {
140
2.75M
        if (psc1->saved_dev_color.colors.pure != psc2->saved_dev_color.colors.pure) {
141
2
            return(false);
142
2
        }
143
2.75M
    }
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
2.75M
    return (true);
175
2.75M
}
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
25.2k
{
183
25.2k
    if (psc1->color_space_id != psc2->color_space_id)
184
14.7k
        return false;
185
10.5k
    if (psc1->pattern_id != psc2->pattern_id)
186
0
        return false;
187
10.5k
    if (psc1->ccolor_valid != psc2->ccolor_valid)
188
0
        return false;
189
10.5k
    if (psc1->color_space_id != psc2->color_space_id)
190
0
        return false;
191
10.5k
    return true;
192
10.5k
}
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
207k
{
201
207k
    if (pgs != NULL && pdevc != NULL && pdevc->type != gx_dc_type_null && pdevc->ccolor_valid)
202
199k
        return true;
203
8.35k
    return false;
204
207k
}
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
205k
{
216
    /* Check if the current color space was used to build the device color */
217
205k
    if (gx_hld_is_hl_color_available(pgs, pdevc)) {
218
197k
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
219
220
197k
        *ppcs = pcs;
221
197k
        *ppcc = &(pdevc->ccolor);
222
197k
        if (pdevc->type == gx_dc_type_pattern
223
197k
           || pdevc->type == &gx_dc_pure_masked
224
197k
           || pdevc->type == gx_dc_type_pattern2)
225
14.5k
            return pattern_color_space;
226
182k
        else {
227
182k
            return non_pattern_color_space;
228
182k
        }
229
197k
    }
230
    /* No color space */
231
8.35k
    *ppcs = NULL;
232
8.35k
    *ppcc = NULL;
233
8.35k
    return use_process_color;
234
205k
}
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
146k
{
244
146k
    if (pgs != NULL) {
245
146k
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
246
146k
        int n = gs_color_space_num_components(pcs);
247
248
146k
        return (n >= 0 ? n : -n - 1);
249
146k
    } else
250
0
        return -1;
251
146k
}
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
}