Coverage Report

Created: 2025-04-22 06:20

/src/libspectre/ghostscript/base/gxhldevc.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2020 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, 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
0
{
37
0
    gx_device_color temp_devc;
38
39
0
    memset(psc, 0, sizeof(*psc)); /* clear the entire structure */
40
0
    psc->color_space_id = psc->pattern_id = gs_no_id;
41
0
    color_set_null(&temp_devc);
42
0
    temp_devc.type->save_dc(&temp_devc, &(psc->saved_dev_color));
43
0
}
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
0
{
55
0
    memset(psc, 0, sizeof(*psc)); /* clear the entire structure */
56
57
0
    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
0
    } else if (pgs == NULL) {
62
        /* No color space, simply save device color specific info */
63
0
        psc->color_space_id = psc->pattern_id = gs_no_id;
64
0
        pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
65
0
        return false;
66
0
    } 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
0
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
74
0
        int i = gs_color_space_num_components(pcs);
75
76
0
        psc->color_space_id = pcs->id;
77
0
        pdevc->type->save_dc(pdevc, &(psc->saved_dev_color));
78
0
        if (pdevc->type == gx_dc_type_pattern2)
79
0
            i = 0;
80
0
        else if (i < 0)
81
0
            i = -i - 1; /* See gx_num_components_Pattern. */
82
0
        for (i--; i >= 0; i--)
83
0
            psc->ccolor.paint.values[i] = pdevc->ccolor.paint.values[i];
84
85
        /* Save the pattern id - if present */
86
0
        if ((pdevc->type == gx_dc_type_pattern
87
0
           || pdevc->type == gx_dc_type_pattern2) && pdevc->ccolor_valid)
88
0
            psc->pattern_id = pdevc->ccolor.pattern->pattern_id;
89
0
        else
90
0
            psc->pattern_id = gs_no_id;
91
0
        return true;
92
0
    }
93
0
}
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
0
{
103
104
0
    int i;
105
106
0
    if (psc1->saved_dev_color.type != psc2->saved_dev_color.type
107
0
     || psc1->color_space_id != psc2->color_space_id
108
0
     || psc1->pattern_id != psc2->pattern_id
109
0
     || psc1->ccolor_valid != psc2->ccolor_valid
110
0
     || psc1->ccolor.pattern != psc2->ccolor.pattern
111
0
     || psc1->saved_dev_color.phase.x != psc2->saved_dev_color.phase.x
112
0
     || psc1->saved_dev_color.phase.y != psc2->saved_dev_color.phase.y) {
113
114
0
        return(false);
115
0
    }
116
117
    /* early bailout for pattern comparison */
118
0
    if (gx_dc_is_pattern1_color((gx_device_color *)(&psc1->saved_dev_color.type))) {
119
120
0
        if (psc1->saved_dev_color.colors.pattern.id != psc2->saved_dev_color.colors.pattern.id
121
0
         || psc1->saved_dev_color.colors.pattern.phase.x != psc2->saved_dev_color.colors.pattern.phase.x
122
0
         || psc1->saved_dev_color.colors.pattern.phase.y != psc2->saved_dev_color.colors.pattern.phase.y)
123
0
            return(false);
124
0
        else
125
0
            return true;
126
0
    }
127
0
    if (gx_dc_is_pattern2_color((gx_device_color *)(&psc1->saved_dev_color.type))) {
128
0
        if (psc1->saved_dev_color.colors.pattern2.id != psc2->saved_dev_color.colors.pattern2.id
129
0
         || psc1->saved_dev_color.colors.pattern2.shfill != psc2->saved_dev_color.colors.pattern2.shfill)
130
0
            return(false);
131
0
        else
132
0
            return true;
133
0
    }
134
135
0
    for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) {
136
0
        if (psc1->ccolor.paint.values[i] != psc2->ccolor.paint.values[i]) {
137
0
            return(false);
138
0
        }
139
0
    }
140
    /* NAFF: only gx_dc_pure_masked doesn't have a type checker */
141
0
    if (gx_dc_is_pure(&psc1->saved_dev_color) || psc1->saved_dev_color.type == &gx_dc_pure_masked) {
142
0
        if (psc1->saved_dev_color.colors.pure != psc2->saved_dev_color.colors.pure) {
143
0
            return(false);
144
0
        }
145
0
    }
146
0
    else if (gx_dc_is_binary_halftone(&psc1->saved_dev_color)) {
147
148
0
        if ((psc1->saved_dev_color.colors.binary.b_color[0] != psc2->saved_dev_color.colors.binary.b_color[0])
149
0
             || (psc1->saved_dev_color.colors.binary.b_color[1] != psc2->saved_dev_color.colors.binary.b_color[1])
150
0
             || (psc1->saved_dev_color.colors.binary.b_level != psc2->saved_dev_color.colors.binary.b_level)
151
0
             || (psc1->saved_dev_color.colors.binary.b_index != psc2->saved_dev_color.colors.binary.b_index)) {
152
153
0
            return(false);
154
0
        }
155
0
    }
156
0
    else if (gx_dc_is_colored_halftone(&psc1->saved_dev_color)) {
157
158
0
        for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) {
159
0
            if (psc1->saved_dev_color.colors.colored.c_base[i] != psc2->saved_dev_color.colors.colored.c_base[i]
160
0
              || psc1->saved_dev_color.colors.colored.c_level[i] != psc2->saved_dev_color.colors.colored.c_level[i]) {
161
162
0
                return(false);
163
0
            }
164
0
        }
165
0
    }
166
0
    else if (gx_dc_is_devn(&psc1->saved_dev_color)) {
167
168
0
        for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) {
169
0
             if (psc1->saved_dev_color.colors.devn.values[i] != psc2->saved_dev_color.colors.devn.values[i]) {
170
171
0
                 return(false);
172
0
             }
173
0
        }
174
0
    }
175
176
0
    return (true);
177
0
}
178
179
/*
180
 * Check whether two saved colors have same color space.
181
 */
182
bool gx_hld_saved_color_same_cspace(const gx_hl_saved_color * psc1,
183
                           const gx_hl_saved_color * psc2)
184
0
{
185
0
    if (psc1->color_space_id != psc2->color_space_id)
186
0
        return false;
187
0
    if (psc1->pattern_id != psc2->pattern_id)
188
0
        return false;
189
0
    if (psc1->ccolor_valid != psc2->ccolor_valid)
190
0
        return false;
191
0
    if (psc1->color_space_id != psc2->color_space_id)
192
0
        return false;
193
0
    return true;
194
0
}
195
196
/*
197
 * Check if a high level color is availavble.
198
 */
199
bool
200
gx_hld_is_hl_color_available(const gs_gstate * pgs,
201
                const gx_device_color * pdevc)
202
0
{
203
0
    if (pgs != NULL && pdevc != NULL && pdevc->type != gx_dc_type_null && pdevc->ccolor_valid)
204
0
        return true;
205
0
    return false;
206
0
}
207
208
/*
209
 * Get pointers to the current color space and client color.
210
 *
211
 * More description in src/gxhldevc.h
212
 */
213
gx_hld_get_color_space_and_ccolor_status
214
gx_hld_get_color_space_and_ccolor(const gs_gstate * pgs,
215
                const gx_device_color * pdevc, const gs_color_space ** ppcs,
216
                const gs_client_color ** ppcc)
217
0
{
218
    /* Check if the current color space was used to build the device color */
219
0
    if (gx_hld_is_hl_color_available(pgs, pdevc)) {
220
0
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
221
222
0
        *ppcs = pcs;
223
0
        *ppcc = &(pdevc->ccolor);
224
0
        if (pdevc->type == gx_dc_type_pattern
225
0
           || pdevc->type == &gx_dc_pure_masked
226
0
           || pdevc->type == gx_dc_type_pattern2)
227
0
            return pattern_color_space;
228
0
        else {
229
0
            return non_pattern_color_space;
230
0
        }
231
0
    }
232
    /* No color space */
233
0
    *ppcs = NULL;
234
0
    *ppcc = NULL;
235
0
    return use_process_color;
236
0
}
237
238
/*
239
 * Get the number of components in the current color space.
240
 *
241
 * More description in src/gxhldevc.h
242
 */
243
int
244
gx_hld_get_number_color_components(const gs_gstate * pgs)
245
0
{
246
0
    if (pgs != NULL) {
247
0
        const gs_color_space * pcs = gs_currentcolorspace_inline(pgs);
248
0
        int n = gs_color_space_num_components(pcs);
249
250
0
        return (n >= 0 ? n : -n - 1);
251
0
    } else
252
0
        return -1;
253
0
}
254
255
/*
256
 * Get the requested high level color value.
257
 *
258
 * More description in src/gxhldevc.h
259
 */
260
gx_hld_get_color_component_status
261
gx_hld_get_color_component(const gs_gstate * pgs,
262
                          const gx_device_color * pdevc,
263
                          int comp_num, float * output)
264
0
{
265
0
    if (pdevc != NULL && pdevc->ccolor_valid) {
266
0
        int ncomp = gx_hld_get_number_color_components(pgs);
267
268
0
        if (ncomp < 0)
269
0
            return invalid_color_info;
270
0
        if (comp_num < 0 || comp_num >= ncomp)
271
0
            return invalid_component_requested;
272
0
        *output = pdevc->ccolor.paint.values[comp_num];
273
0
        return valid_result;
274
0
    }
275
0
    return invalid_color_info;
276
0
}